]>
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
: "octopus" , version
: "15.2" },
53 { release
: "pacific" , version
: "16.2" },
54 { release
: "quincy" , version
: "17.2" },
59 Ext
. define ( 'PVE.ceph.CephHighestVersionDisplay' , {
60 extend
: 'Ext.form.field.Display' ,
61 xtype
: 'pveCephHighestVersionDisplay' ,
63 fieldLabel
: gettext ( 'Ceph in the cluster' ),
67 // called on success with (release, versionTxt, versionParts)
68 gotNewestVersion
: Ext
. emptyFn
,
70 initComponent : function () {
73 me
. callParent ( arguments
);
75 Proxmox
. Utils
. API2Request ({
77 url
: '/cluster/ceph/metadata' ,
82 success
: ( response
) => {
83 let res
= response
. result
;
84 if (! res
|| ! res
. data
|| ! res
. data
. node
) {
86 gettext ( 'Could not detect a ceph installation in the cluster' ),
90 let nodes
= res
. data
. node
;
92 // can happen on ceph purge, we do not yet cleanup old version data
93 delete nodes
[ me
. nodename
];
97 let maxversiontext
= "" ;
98 for ( const [ _nodename
, data
] of Object
. entries ( nodes
)) {
99 let version
= data
. version
. parts
;
100 if ( PVE
. Utils
. compare_ceph_versions ( version
, maxversion
) > 0 ) {
101 maxversion
= version
;
102 maxversiontext
= data
. version
. str
;
105 // FIXME: get from version selector store
106 const major2release
= {
113 let release
= major2release
[ maxversion
[ 0 ]] || 'unknown' ;
114 let newestVersionTxt
= ` ${Ext.String.capitalize(release)} ( ${maxversiontext} )` ;
116 if ( release
=== 'unknown' ) {
118 gettext ( 'Could not detect a ceph installation in the cluster' ),
121 me
. setValue ( Ext
. String
. format (
122 gettext ( 'Newest ceph version in cluster is {0}' ),
126 me
. gotNewestVersion ( release
, maxversiontext
, maxversion
);
128 failure : function ( response
, opts
) {
129 Ext
. Msg
. alert ( gettext ( 'Error' ), response
. htmlStatus
);
135 Ext
. define ( 'PVE.ceph.CephInstallWizard' , {
136 extend
: 'PVE.window.Wizard' ,
137 alias
: 'widget.pveCephInstallWizard' ,
138 mixins
: [ 'Proxmox.Mixin.CBind' ],
146 cephRelease
: 'quincy' ,
155 title
: gettext ( 'Setup' ),
156 navigateNext : function () {
157 var tp
= this . down ( '#wizcontent' );
158 var atab
= tp
. getActiveTab ();
160 var next
= tp
. items
. indexOf ( atab
) + 1 ;
161 var ntab
= tp
. items
. getAt ( next
);
164 tp
. setActiveTab ( ntab
);
167 setInitialTab : function ( index
) {
168 var tp
= this . down ( '#wizcontent' );
169 var initialTab
= tp
. items
. getAt ( index
);
171 tp
. setActiveTab ( initialTab
);
174 this . callParent ( arguments
);
175 var isInstalled
= this . getViewModel (). get ( 'isInstalled' );
177 this . getViewModel (). set ( 'configuration' , false );
178 this . setInitialTab ( 2 );
184 title
: gettext ( 'Info' ),
185 viewModel
: {}, // needed to inherit parent viewModel data
188 onlineHelp
: 'chapter_pveceph' ,
199 xtype
: 'pveCephInstallWizardInfo' ,
205 xtype
: 'pveCephHighestVersionDisplay' ,
208 nodename
: '{nodename}' ,
210 gotNewestVersion : function ( release
, maxversiontext
, maxversion
) {
211 if ( release
=== 'unknown' ) {
214 let wizard
= this . up ( 'pveCephInstallWizard' );
215 wizard
. getViewModel (). set ( 'cephRelease' , release
);
219 xtype
: 'pveCephVersionSelector' ,
223 value
: '{cephRelease}' ,
226 change : function ( field
, release
) {
227 let wizard
= this . up ( 'pveCephInstallWizard' );
228 wizard
. down ( '#next' ). setText (
229 Ext
. String
. format ( gettext ( 'Start {0} installation' ), release
),
236 activate : function () {
237 // notify owning container that it should display a help button
238 if ( this . onlineHelp
) {
239 Ext
. GlobalEvents
. fireEvent ( 'proxmoxShowHelp' , this . onlineHelp
);
241 let wizard
= this . up ( 'pveCephInstallWizard' );
242 let release
= wizard
. getViewModel (). get ( 'cephRelease' );
243 wizard
. down ( '#back' ). hide ( true );
244 wizard
. down ( '#next' ). setText (
245 Ext
. String
. format ( gettext ( 'Start {0} installation' ), release
),
248 deactivate : function () {
249 if ( this . onlineHelp
) {
250 Ext
. GlobalEvents
. fireEvent ( 'proxmoxHideHelp' , this . onlineHelp
);
252 this . up ( 'pveCephInstallWizard' ). down ( '#next' ). setText ( gettext ( 'Next' ));
257 title
: gettext ( 'Installation' ),
261 nodename
: '{nodename}' ,
263 viewModel
: {}, // needed to inherit parent viewModel data
265 afterrender : function () {
267 if ( this . getViewModel (). get ( 'isInstalled' )) {
268 this . mask ( "Ceph is already installed, click next to create your configuration." , [ 'pve-static-mask' ]);
270 me
. down ( 'pveNoVncConsole' ). fireEvent ( 'activate' );
273 activate : function () {
275 const nodename
= me
. nodename
;
276 me
. updateStore
= Ext
. create ( 'Proxmox.data.UpdateStore' , {
277 storeid
: 'ceph-status-' + nodename
,
281 url
: '/api2/json/nodes/' + nodename
+ '/ceph/status' ,
284 load : function ( rec
, response
, success
, operation
) {
286 me
. updateStore
. stopUpdate ();
287 me
. down ( 'textfield' ). setValue ( 'success' );
288 } else if ( operation
. error
. statusText
. match ( "not initialized" , "i" )) {
289 me
. updateStore
. stopUpdate ();
290 me
. up ( 'pveCephInstallWizard' ). getViewModel (). set ( 'configuration' , false );
291 me
. down ( 'textfield' ). setValue ( 'success' );
292 } else if ( operation
. error
. statusText
. match ( "rados_connect failed" , "i" )) {
293 me
. updateStore
. stopUpdate ();
294 me
. up ( 'pveCephInstallWizard' ). getViewModel (). set ( 'configuration' , true );
295 me
. down ( 'textfield' ). setValue ( 'success' );
296 } else if (! operation
. error
. statusText
. match ( "not installed" , "i" )) {
297 Proxmox
. Utils
. setErrorMask ( me
, operation
. error
. statusText
);
302 me
. updateStore
. startUpdate ();
304 destroy : function () {
306 if ( me
. updateStore
) {
307 me
. updateStore
. stopUpdate ();
313 xtype
: 'pveNoVncConsole' ,
318 nodename
: '{nodename}' ,
320 beforeLoad : function () {
322 let wizard
= me
. up ( 'pveCephInstallWizard' );
323 let release
= wizard
. getViewModel (). get ( 'cephRelease' );
324 me
. cmdOpts
= `--version\0 ${release} ` ;
330 name
: 'installSuccess' ,
340 title
: gettext ( 'Configuration' ),
341 onlineHelp
: 'chapter_pveceph' ,
344 nodename
: '{nodename}' ,
349 minreplicas
: undefined ,
353 activate : function () {
354 this . up ( 'pveCephInstallWizard' ). down ( '#submit' ). setText ( gettext ( 'Next' ));
356 afterrender : function () {
357 if ( this . up ( 'pveCephInstallWizard' ). getViewModel (). get ( 'configuration' )) {
358 this . mask ( "Configuration already initialized" , [ 'pve-static-mask' ]);
363 deactivate : function () {
364 this . up ( 'pveCephInstallWizard' ). down ( '#submit' ). setText ( gettext ( 'Finish' ));
369 xtype
: 'displayfield' ,
370 value
: gettext ( 'Ceph cluster configuration' ) + ':' ,
373 xtype
: 'proxmoxNetworkSelector' ,
376 fieldLabel
: 'Public Network IP/CIDR' ,
379 allowBlank
: '{configuration}' ,
382 nodename
: '{nodename}' ,
386 xtype
: 'proxmoxNetworkSelector' ,
387 name
: 'cluster-network' ,
388 fieldLabel
: 'Cluster Network IP/CIDR' ,
391 emptyText
: gettext ( 'Same as Public Network' ),
393 nodename
: '{nodename}' ,
396 // FIXME: add hint about cluster network and/or reference user to docs??
400 xtype
: 'displayfield' ,
401 value
: gettext ( 'First Ceph monitor' ) + ':' ,
404 xtype
: 'displayfield' ,
405 fieldLabel
: gettext ( 'Monitor node' ),
411 xtype
: 'displayfield' ,
412 value
: gettext ( 'Additional monitors are recommended. They can be created at any time in the Monitor tab.' ),
418 xtype
: 'numberfield' ,
420 fieldLabel
: 'Number of replicas' ,
429 xtype
: 'numberfield' ,
431 fieldLabel
: 'Minimum replicas' ,
433 maxValue
: '{replicas}' ,
434 value
: '{minreplicas}' ,
438 setMaxValue : function ( value
) {
439 this . maxValue
= Ext
. Number
. from ( value
, 2 );
440 // allow enough to avoid split brains with max 'size', but more makes simply no sense
441 if ( this . maxValue
> 4 ) {
444 this . toggleSpinners ();
450 onGetValues : function ( values
) {
451 [ 'cluster-network' , 'size' , 'min_size' ]. forEach ( function ( field
) {
452 if (! values
[ field
]) {
453 delete values
[ field
];
458 onSubmit : function () {
460 if (! this . up ( 'pveCephInstallWizard' ). getViewModel (). get ( 'configuration' )) {
461 var wizard
= me
. up ( 'window' );
462 var kv
= wizard
. getValues ();
464 var nodename
= me
. nodename
;
466 Proxmox
. Utils
. API2Request ({
467 url
: `/nodes/ ${nodename} /ceph/init` ,
468 waitMsgTarget
: wizard
,
471 success : function () {
472 Proxmox
. Utils
. API2Request ({
473 url
: `/nodes/ ${nodename} /ceph/mon/ ${nodename} ` ,
474 waitMsgTarget
: wizard
,
476 success : function () {
477 me
. up ( 'pveCephInstallWizard' ). navigateNext ();
479 failure : function ( response
, opts
) {
480 Ext
. Msg
. alert ( gettext ( 'Error' ), response
. htmlStatus
);
484 failure : function ( response
, opts
) {
485 Ext
. Msg
. alert ( gettext ( 'Error' ), response
. htmlStatus
);
489 me
. up ( 'pveCephInstallWizard' ). navigateNext ();
494 title
: gettext ( 'Success' ),
498 onlineHelp
: 'pve_ceph_install' ,
499 html
: '<h3>Installation successful!</h3>' +
500 '<p>The basic installation and configuration is complete. Depending on your setup, some of the following steps are required to start using Ceph:</p>' +
501 '<ol><li>Install Ceph on other nodes</li>' +
502 '<li>Create additional Ceph Monitors</li>' +
503 '<li>Create Ceph OSDs</li>' +
504 '<li>Create Ceph Pools</li></ol>' +
505 '<p>To learn more, click on the help button below.</p>' ,
507 activate : function () {
508 // notify owning container that it should display a help button
509 if ( this . onlineHelp
) {
510 Ext
. GlobalEvents
. fireEvent ( 'proxmoxShowHelp' , this . onlineHelp
);
513 var tp
= this . up ( '#wizcontent' );
514 var idx
= tp
. items
. indexOf ( this )- 1 ;
515 for (; idx
>= 0 ; idx
--) {
516 var nc
= tp
. items
. getAt ( idx
);
522 deactivate : function () {
523 if ( this . onlineHelp
) {
524 Ext
. GlobalEvents
. fireEvent ( 'proxmoxHideHelp' , this . onlineHelp
);
528 onSubmit : function () {
529 var wizard
= this . up ( 'pveCephInstallWizard' );