]>
git.proxmox.com Git - pve-manager.git/blob - www/manager6/ceph/CephInstallWizard.js
1 Ext
. define ( 'PVE.ceph.CephInstallWizardInfo' , {
2 extend
: 'Ext.panel.Panel' ,
3 xtype
: 'pveCephInstallWizardInfo' ,
6 <blockquote cite="https://ceph.com/"><p>"<b>Ceph</b> is a unified,
7 distributed storage system, designed for excellent performance, reliability,
8 and scalability."</p></blockquote>
10 <b>Ceph</b> is currently <b>not installed</b> on this node. This wizard
11 will guide you through the installation. Click on the next button below
12 to begin. After the initial installation, the wizard will offer to create
13 an initial configuration. This configuration step is only
14 needed once per cluster and will be skipped if a config is already present.
17 Before starting the installation, please take a look at our documentation,
18 by clicking the help button below. If you want to gain deeper knowledge about
19 Ceph, visit <a target="_blank" href="https://docs.ceph.com/en/latest/">ceph.com</a>.
23 Ext
. define ( 'PVE.ceph.CephVersionSelector' , {
24 extend
: 'Ext.form.field.ComboBox' ,
25 xtype
: 'pveCephVersionSelector' ,
27 fieldLabel
: gettext ( 'Ceph version to install' ),
29 displayField
: 'display' ,
30 valueField
: 'release' ,
42 calculate
: d
=> ` ${d.release} ( ${d.version} )` ,
52 { release
: "quincy" , version
: "17.2" },
57 Ext
. define ( 'PVE.ceph.CephHighestVersionDisplay' , {
58 extend
: 'Ext.form.field.Display' ,
59 xtype
: 'pveCephHighestVersionDisplay' ,
61 fieldLabel
: gettext ( 'Ceph in the cluster' ),
65 // called on success with (release, versionTxt, versionParts)
66 gotNewestVersion
: Ext
. emptyFn
,
68 initComponent : function () {
71 me
. callParent ( arguments
);
73 Proxmox
. Utils
. API2Request ({
75 url
: '/cluster/ceph/metadata' ,
80 success
: ( response
) => {
81 let res
= response
. result
;
82 if (! res
|| ! res
. data
|| ! res
. data
. node
) {
84 gettext ( 'Could not detect a ceph installation in the cluster' ),
88 let nodes
= res
. data
. node
;
90 // can happen on ceph purge, we do not yet cleanup old version data
91 delete nodes
[ me
. nodename
];
95 let maxversiontext
= "" ;
96 for ( const [ _nodename
, data
] of Object
. entries ( nodes
)) {
97 let version
= data
. version
. parts
;
98 if ( PVE
. Utils
. compare_ceph_versions ( version
, maxversion
) > 0 ) {
100 maxversiontext
= data
. version
. str
;
103 // FIXME: get from version selector store
104 const major2release
= {
112 let release
= major2release
[ maxversion
[ 0 ]] || 'unknown' ;
113 let newestVersionTxt
= ` ${Ext.String.capitalize(release)} ( ${maxversiontext} )` ;
115 if ( release
=== 'unknown' ) {
117 gettext ( 'Could not detect a ceph installation in the cluster' ),
120 me
. setValue ( Ext
. String
. format (
121 gettext ( 'Newest ceph version in cluster is {0}' ),
125 me
. gotNewestVersion ( release
, maxversiontext
, maxversion
);
127 failure : function ( response
, opts
) {
128 Ext
. Msg
. alert ( gettext ( 'Error' ), response
. htmlStatus
);
134 Ext
. define ( 'PVE.ceph.CephInstallWizard' , {
135 extend
: 'PVE.window.Wizard' ,
136 alias
: 'widget.pveCephInstallWizard' ,
137 mixins
: [ 'Proxmox.Mixin.CBind' ],
148 cephRelease
: 'quincy' ,
149 cephRepo
: 'enterprise' ,
158 title
: gettext ( 'Setup' ),
159 navigateNext : function () {
160 var tp
= this . down ( '#wizcontent' );
161 var atab
= tp
. getActiveTab ();
163 var next
= tp
. items
. indexOf ( atab
) + 1 ;
164 var ntab
= tp
. items
. getAt ( next
);
167 tp
. setActiveTab ( ntab
);
170 setInitialTab : function ( index
) {
171 var tp
= this . down ( '#wizcontent' );
172 var initialTab
= tp
. items
. getAt ( index
);
174 tp
. setActiveTab ( initialTab
);
177 this . callParent ( arguments
);
178 var isInstalled
= this . getViewModel (). get ( 'isInstalled' );
180 this . getViewModel (). set ( 'configuration' , false );
181 this . setInitialTab ( 2 );
187 title
: gettext ( 'Info' ),
188 viewModel
: {}, // needed to inherit parent viewModel data
191 onlineHelp
: 'chapter_pveceph' ,
202 xtype
: 'pveCephInstallWizardInfo' ,
208 xtype
: 'pveCephHighestVersionDisplay' ,
211 nodename
: '{nodename}' ,
213 gotNewestVersion : function ( release
, maxversiontext
, maxversion
) {
214 if ( release
=== 'unknown' ) {
217 let wizard
= this . up ( 'pveCephInstallWizard' );
218 wizard
. getViewModel (). set ( 'cephRelease' , release
);
230 xtype
: 'pveCephVersionSelector' ,
235 value
: '{cephRelease}' ,
238 change : function ( field
, release
) {
239 let wizard
= this . up ( 'pveCephInstallWizard' );
240 wizard
. down ( '#next' ). setText (
241 Ext
. String
. format ( gettext ( 'Start {0} installation' ), release
),
247 xtype
: 'proxmoxKVComboBox' ,
248 fieldLabel
: gettext ( 'Repository' ),
251 [ 'enterprise' , gettext ( 'Enterprise (recommended)' )],
252 [ 'no-subscription' , gettext ( 'No-Subscription' )],
253 [ 'test' , gettext ( 'Test' )],
265 activate : function () {
266 // notify owning container that it should display a help button
267 if ( this . onlineHelp
) {
268 Ext
. GlobalEvents
. fireEvent ( 'proxmoxShowHelp' , this . onlineHelp
);
270 let wizard
= this . up ( 'pveCephInstallWizard' );
271 let release
= wizard
. getViewModel (). get ( 'cephRelease' );
272 wizard
. down ( '#back' ). hide ( true );
273 wizard
. down ( '#next' ). setText (
274 Ext
. String
. format ( gettext ( 'Start {0} installation' ), release
),
277 deactivate : function () {
278 if ( this . onlineHelp
) {
279 Ext
. GlobalEvents
. fireEvent ( 'proxmoxHideHelp' , this . onlineHelp
);
281 this . up ( 'pveCephInstallWizard' ). down ( '#next' ). setText ( gettext ( 'Next' ));
286 title
: gettext ( 'Installation' ),
290 nodename
: '{nodename}' ,
292 viewModel
: {}, // needed to inherit parent viewModel data
294 afterrender : function () {
296 if ( this . getViewModel (). get ( 'isInstalled' )) {
297 this . mask ( "Ceph is already installed, click next to create your configuration." , [ 'pve-static-mask' ]);
299 me
. down ( 'pveNoVncConsole' ). fireEvent ( 'activate' );
302 activate : function () {
304 const nodename
= me
. nodename
;
305 me
. updateStore
= Ext
. create ( 'Proxmox.data.UpdateStore' , {
306 storeid
: 'ceph-status-' + nodename
,
310 url
: '/api2/json/nodes/' + nodename
+ '/ceph/status' ,
313 load : function ( rec
, response
, success
, operation
) {
315 me
. updateStore
. stopUpdate ();
316 me
. down ( 'textfield' ). setValue ( 'success' );
317 } else if ( operation
. error
. statusText
. match ( "not initialized" , "i" )) {
318 me
. updateStore
. stopUpdate ();
319 me
. up ( 'pveCephInstallWizard' ). getViewModel (). set ( 'configuration' , false );
320 me
. down ( 'textfield' ). setValue ( 'success' );
321 } else if ( operation
. error
. statusText
. match ( "rados_connect failed" , "i" )) {
322 me
. updateStore
. stopUpdate ();
323 me
. up ( 'pveCephInstallWizard' ). getViewModel (). set ( 'configuration' , true );
324 me
. down ( 'textfield' ). setValue ( 'success' );
325 } else if (! operation
. error
. statusText
. match ( "not installed" , "i" )) {
326 Proxmox
. Utils
. setErrorMask ( me
, operation
. error
. statusText
);
331 me
. updateStore
. startUpdate ();
333 destroy : function () {
335 if ( me
. updateStore
) {
336 me
. updateStore
. stopUpdate ();
342 xtype
: 'pveNoVncConsole' ,
347 nodename
: '{nodename}' ,
349 beforeLoad : function () {
351 let wizard
= me
. up ( 'pveCephInstallWizard' );
352 let release
= wizard
. getViewModel (). get ( 'cephRelease' );
353 let repo
= wizard
. getViewModel (). get ( 'cephRepo' );
354 me
. cmdOpts
= `--version\0 ${release} \0--repository\0 ${repo} ` ;
360 name
: 'installSuccess' ,
370 title
: gettext ( 'Configuration' ),
371 onlineHelp
: 'chapter_pveceph' ,
374 nodename
: '{nodename}' ,
379 minreplicas
: undefined ,
383 activate : function () {
384 this . up ( 'pveCephInstallWizard' ). down ( '#submit' ). setText ( gettext ( 'Next' ));
386 afterrender : function () {
387 if ( this . up ( 'pveCephInstallWizard' ). getViewModel (). get ( 'configuration' )) {
388 this . mask ( "Configuration already initialized" , [ 'pve-static-mask' ]);
393 deactivate : function () {
394 this . up ( 'pveCephInstallWizard' ). down ( '#submit' ). setText ( gettext ( 'Finish' ));
399 xtype
: 'displayfield' ,
400 value
: gettext ( 'Ceph cluster configuration' ) + ':' ,
403 xtype
: 'proxmoxNetworkSelector' ,
406 fieldLabel
: 'Public Network IP/CIDR' ,
409 allowBlank
: '{configuration}' ,
412 nodename
: '{nodename}' ,
416 xtype
: 'proxmoxNetworkSelector' ,
417 name
: 'cluster-network' ,
418 fieldLabel
: 'Cluster Network IP/CIDR' ,
421 emptyText
: gettext ( 'Same as Public Network' ),
423 nodename
: '{nodename}' ,
426 // FIXME: add hint about cluster network and/or reference user to docs??
430 xtype
: 'displayfield' ,
431 value
: gettext ( 'First Ceph monitor' ) + ':' ,
434 xtype
: 'displayfield' ,
435 fieldLabel
: gettext ( 'Monitor node' ),
441 xtype
: 'displayfield' ,
442 value
: gettext ( 'Additional monitors are recommended. They can be created at any time in the Monitor tab.' ),
448 xtype
: 'numberfield' ,
450 fieldLabel
: 'Number of replicas' ,
459 xtype
: 'numberfield' ,
461 fieldLabel
: 'Minimum replicas' ,
463 maxValue
: '{replicas}' ,
464 value
: '{minreplicas}' ,
468 setMaxValue : function ( value
) {
469 this . maxValue
= Ext
. Number
. from ( value
, 2 );
470 // allow enough to avoid split brains with max 'size', but more makes simply no sense
471 if ( this . maxValue
> 4 ) {
474 this . toggleSpinners ();
480 onGetValues : function ( values
) {
481 [ 'cluster-network' , 'size' , 'min_size' ]. forEach ( function ( field
) {
482 if (! values
[ field
]) {
483 delete values
[ field
];
488 onSubmit : function () {
490 if (! this . up ( 'pveCephInstallWizard' ). getViewModel (). get ( 'configuration' )) {
491 var wizard
= me
. up ( 'window' );
492 var kv
= wizard
. getValues ();
494 var nodename
= me
. nodename
;
496 Proxmox
. Utils
. API2Request ({
497 url
: `/nodes/ ${nodename} /ceph/init` ,
498 waitMsgTarget
: wizard
,
501 success : function () {
502 Proxmox
. Utils
. API2Request ({
503 url
: `/nodes/ ${nodename} /ceph/mon/ ${nodename} ` ,
504 waitMsgTarget
: wizard
,
506 success : function () {
507 me
. up ( 'pveCephInstallWizard' ). navigateNext ();
509 failure : function ( response
, opts
) {
510 Ext
. Msg
. alert ( gettext ( 'Error' ), response
. htmlStatus
);
514 failure : function ( response
, opts
) {
515 Ext
. Msg
. alert ( gettext ( 'Error' ), response
. htmlStatus
);
519 me
. up ( 'pveCephInstallWizard' ). navigateNext ();
524 title
: gettext ( 'Success' ),
528 onlineHelp
: 'pve_ceph_install' ,
529 html
: '<h3>Installation successful!</h3>' +
530 '<p>The basic installation and configuration is complete. Depending on your setup, some of the following steps are required to start using Ceph:</p>' +
531 '<ol><li>Install Ceph on other nodes</li>' +
532 '<li>Create additional Ceph Monitors</li>' +
533 '<li>Create Ceph OSDs</li>' +
534 '<li>Create Ceph Pools</li></ol>' +
535 '<p>To learn more, click on the help button below.</p>' ,
537 activate : function () {
538 // notify owning container that it should display a help button
539 if ( this . onlineHelp
) {
540 Ext
. GlobalEvents
. fireEvent ( 'proxmoxShowHelp' , this . onlineHelp
);
543 var tp
= this . up ( '#wizcontent' );
544 var idx
= tp
. items
. indexOf ( this )- 1 ;
545 for (; idx
>= 0 ; idx
--) {
546 var nc
= tp
. items
. getAt ( idx
);
552 deactivate : function () {
553 if ( this . onlineHelp
) {
554 Ext
. GlobalEvents
. fireEvent ( 'proxmoxHideHelp' , this . onlineHelp
);
558 onSubmit : function () {
559 var wizard
= this . up ( 'pveCephInstallWizard' );