html: `<h3>Ceph?</h3>
<blockquote cite="https://ceph.com/"><p>"<b>Ceph</b> is a unified,
- distributed storage system designed for excellent performance, reliability
+ distributed storage system, designed for excellent performance, reliability,
and scalability."</p></blockquote>
<p>
- <b>Ceph</b> is currently <b>not installed</b> on this node, click on the
- next button below to start the installation. This wizard will guide you
- through the necessary steps, after the initial installation you will be
- offered to create an initial configuration. The configuration step is only
+ <b>Ceph</b> is currently <b>not installed</b> on this node. This wizard
+ will guide you through the installation. Click on the next button below
+ to begin. After the initial installation, the wizard will offer to create
+ an initial configuration. This configuration step is only
needed once per cluster and will be skipped if a config is already present.
</p>
<p>
- Please take a look at our documentation, by clicking the help button below,
- before starting the installation, if you want to gain deeper knowledge about
- Ceph visit <a target="_blank" href="http://docs.ceph.com/docs/master/">ceph.com</a>.
+ Before starting the installation, please take a look at our documentation,
+ by clicking the help button below. If you want to gain deeper knowledge about
+ Ceph, visit <a target="_blank" href="https://docs.ceph.com/en/latest/">ceph.com</a>.
</p>`,
});
},
},
data: [
- {release: "nautilus", version: "14.2"},
- {release: "octopus", version: "15.2"},
- //{release: "pacific", version: "16.1"},
+ { release: "quincy", version: "17.2" },
+ { release: "reef", version: "18.2" },
],
},
});
let maxversion = [];
let maxversiontext = "";
- for (const [nodename, data] of Object.entries(nodes)) {
+ for (const [_nodename, data] of Object.entries(nodes)) {
let version = data.version.parts;
if (PVE.Utils.compare_ceph_versions(version, maxversion) > 0) {
maxversion = version;
14: 'nautilus',
15: 'octopus',
16: 'pacific',
+ 17: 'quincy',
+ 18: 'reef',
+ 19: 'squid',
};
let release = major2release[maxversion[0]] || 'unknown';
let newestVersionTxt = `${Ext.String.capitalize(release)} (${maxversiontext})`;
},
failure: function(response, opts) {
Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
+ },
});
},
});
Ext.define('PVE.ceph.CephInstallWizard', {
- extend: 'PVE.window.Wizard',
- alias: 'widget.pveCephInstallWizard',
- mixins: ['Proxmox.Mixin.CBind'],
-
- resizable: false,
- nodename: undefined,
+ extend: 'PVE.window.Wizard',
+ alias: 'widget.pveCephInstallWizard',
+ mixins: ['Proxmox.Mixin.CBind'],
- viewModel: {
- data: {
- nodename: '',
- cephRelease: 'octopus',
- configuration: true,
- isInstalled: false,
- }
- },
- cbindData: {
- nodename: undefined
- },
+ resizable: false,
+ nodename: undefined,
- title: gettext('Setup'),
- navigateNext: function() {
- var tp = this.down('#wizcontent');
- var atab = tp.getActiveTab();
+ width: 760, // 4:3
+ height: 570,
- var next = tp.items.indexOf(atab) + 1;
- var ntab = tp.items.getAt(next);
- if (ntab) {
- ntab.enable();
- tp.setActiveTab(ntab);
- }
+ viewModel: {
+ data: {
+ nodename: '',
+ cephRelease: 'quincy',
+ cephRepo: 'enterprise',
+ configuration: true,
+ isInstalled: false,
+ nodeHasSubscription: true, // avoid warning hint until fully loaded
+ allHaveSubscription: true, // avoid warning hint until fully loaded
},
- setInitialTab: function (index) {
- var tp = this.down('#wizcontent');
- var initialTab = tp.items.getAt(index);
- initialTab.enable();
- tp.setActiveTab(initialTab);
- },
- onShow: function() {
- this.callParent(arguments);
- var isInstalled = this.getViewModel().get('isInstalled');
- if (isInstalled) {
- this.getViewModel().set('configuration', false);
- this.setInitialTab(2);
+ formulas: {
+ repoHintHidden: get => get('allHaveSubscription') && get('cephRepo') === 'enterprise',
+ repoHint: function(get) {
+ let repo = get('cephRepo');
+ let nodeSub = get('nodeHasSubscription'), allSub = get('allHaveSubscription');
+
+ if (repo === 'enterprise') {
+ if (!nodeSub) {
+ return gettext('The enterprise repository is enabled, but there is no active subscription!');
+ } else if (!allSub) {
+ return gettext('Not all nodes have an active subscription, which is required for cluster-wide enterprise repo access');
+ }
+ return ''; // should be hidden
+ } else if (repo === 'no-subscription') {
+ return allSub
+ ? gettext("Cluster has active subscriptions and would be elligible for using the enterprise repository.")
+ : gettext("The no-subscription repository is not the best choice for production setups.");
+ } else {
+ return gettext('The test repository should only be used for test setups or after consulting the official Proxmox support!');
}
+ },
},
- items: [
- {
- xtype: 'panel',
- title: gettext('Info'),
- viewModel: {}, // needed to inherit parent viewModel data
+ },
+ cbindData: {
+ nodename: undefined,
+ },
+
+ title: gettext('Setup'),
+ navigateNext: function() {
+ var tp = this.down('#wizcontent');
+ var atab = tp.getActiveTab();
+
+ var next = tp.items.indexOf(atab) + 1;
+ var ntab = tp.items.getAt(next);
+ if (ntab) {
+ ntab.enable();
+ tp.setActiveTab(ntab);
+ }
+ },
+ setInitialTab: function(index) {
+ var tp = this.down('#wizcontent');
+ var initialTab = tp.items.getAt(index);
+ initialTab.enable();
+ tp.setActiveTab(initialTab);
+ },
+ onShow: function() {
+ this.callParent(arguments);
+ let viewModel = this.getViewModel();
+ var isInstalled = this.getViewModel().get('isInstalled');
+ if (isInstalled) {
+ viewModel.set('configuration', false);
+ this.setInitialTab(2);
+ }
+
+ PVE.Utils.getClusterSubscriptionLevel().then(subcriptionMap => {
+ viewModel.set('nodeHasSubscription', !!subcriptionMap[this.nodename]);
+
+ let allHaveSubscription = Object.values(subcriptionMap).every(level => !!level);
+ viewModel.set('allHaveSubscription', allHaveSubscription);
+ });
+ },
+ items: [
+ {
+ xtype: 'panel',
+ title: gettext('Info'),
+ viewModel: {}, // needed to inherit parent viewModel data
+ border: false,
+ bodyBorder: false,
+ onlineHelp: 'chapter_pveceph',
+ layout: {
+ type: 'vbox',
+ align: 'stretch',
+ },
+ defaults: {
border: false,
bodyBorder: false,
- onlineHelp: 'chapter_pveceph',
- layout: {
- type: 'vbox',
- align: 'stretch',
+ },
+ items: [
+ {
+ xtype: 'pveCephInstallWizardInfo',
},
- defaults: {
- border: false,
- bodyBorder: false,
+ {
+ flex: 1,
},
- items: [
- {
- xtype: 'pveCephInstallWizardInfo',
+ {
+ xtype: 'displayfield',
+ fieldLabel: gettext('Hint'),
+ labelClsExtra: 'pmx-hint',
+ submitValue: false,
+ labelWidth: 50,
+ bind: {
+ value: '{repoHint}',
+ hidden: '{repoHintHidden}',
},
- {
- flex: 1,
+ },
+ {
+ xtype: 'pveCephHighestVersionDisplay',
+ labelWidth: 150,
+ cbind: {
+ nodename: '{nodename}',
},
- {
- xtype: 'pveCephHighestVersionDisplay',
- labelWidth: 180,
- cbind:{
- nodename: '{nodename}'
- },
- gotNewestVersion: function(release, maxversiontext, maxversion) {
- if (release === 'unknown') {
- return;
- }
- let wizard = this.up('pveCephInstallWizard');
- wizard.getViewModel().set('cephRelease', release);
- },
+ gotNewestVersion: function(release, maxversiontext, maxversion) {
+ if (release === 'unknown') {
+ return;
+ }
+ let wizard = this.up('pveCephInstallWizard');
+ wizard.getViewModel().set('cephRelease', release);
},
- {
+ },
+ {
+ xtype: 'container',
+ layout: 'hbox',
+ defaults: {
+ border: false,
+ layout: 'anchor',
+ flex: 1,
+ },
+ items: [{
xtype: 'pveCephVersionSelector',
- labelWidth: 180,
+ labelWidth: 150,
+ padding: '0 10 0 0',
submitValue: false,
bind: {
value: '{cephRelease}',
},
},
},
- ],
- listeners: {
- activate: function() {
- // notify owning container that it should display a help button
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxShowHelp', this.onlineHelp);
- }
- let wizard = this.up('pveCephInstallWizard');
- let release = wizard.getViewModel().get('cephRelease');
- wizard.down('#back').hide(true);
- wizard.down('#next').setText(
- Ext.String.format(gettext('Start {0} installation'), release),
- );
- },
- deactivate: function() {
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxHideHelp', this.onlineHelp);
- }
- this.up('pveCephInstallWizard').down('#next').setText(gettext('Next'));
+ {
+ xtype: 'proxmoxKVComboBox',
+ fieldLabel: gettext('Repository'),
+ padding: '0 0 0 10',
+ comboItems: [
+ ['enterprise', gettext('Enterprise (recommended)')],
+ ['no-subscription', gettext('No-Subscription')],
+ ['test', gettext('Test')],
+ ],
+ labelWidth: 150,
+ submitValue: false,
+ value: 'enterprise',
+ bind: {
+ value: '{cephRepo}',
+ },
+ }],
+ },
+ ],
+ listeners: {
+ activate: function() {
+ // notify owning container that it should display a help button
+ if (this.onlineHelp) {
+ Ext.GlobalEvents.fireEvent('proxmoxShowHelp', this.onlineHelp);
}
- }
- },
- {
- title: gettext('Installation'),
- xtype: 'panel',
- layout: 'fit',
- cbind:{
- nodename: '{nodename}'
+ let wizard = this.up('pveCephInstallWizard');
+ let release = wizard.getViewModel().get('cephRelease');
+ wizard.down('#back').hide(true);
+ wizard.down('#next').setText(
+ Ext.String.format(gettext('Start {0} installation'), release),
+ );
},
- viewModel: {}, // needed to inherit parent viewModel data
- listeners: {
- afterrender: function() {
- var me = this;
- if (this.getViewModel().get('isInstalled')) {
- this.mask("Ceph is already installed, click next to create your configuration.",['pve-static-mask']);
- } else {
- me.down('pveNoVncConsole').fireEvent('activate');
- }
- },
- activate: function() {
- let me = this;
- const nodename = me.nodename;
- me.updateStore = Ext.create('Proxmox.data.UpdateStore', {
- storeid: 'ceph-status-' + nodename,
- interval: 1000,
- proxy: {
- type: 'proxmox',
- url: '/api2/json/nodes/' + nodename + '/ceph/status'
- },
- listeners: {
- load: function(rec, response, success, operation) {
-
- if (success) {
- me.updateStore.stopUpdate();
- me.down('textfield').setValue('success');
- } else if (operation.error.statusText.match("not initialized", "i")) {
- me.updateStore.stopUpdate();
- me.up('pveCephInstallWizard').getViewModel().set('configuration',false);
- me.down('textfield').setValue('success');
- } else if (operation.error.statusText.match("rados_connect failed", "i")) {
- me.updateStore.stopUpdate();
- me.up('pveCephInstallWizard').getViewModel().set('configuration',true);
- me.down('textfield').setValue('success');
- } else if (!operation.error.statusText.match("not installed", "i")) {
- Proxmox.Utils.setErrorMask(me, operation.error.statusText);
- }
- }
- }
- });
- me.updateStore.startUpdate();
- },
- destroy: function() {
- var me = this;
- if (me.updateStore) {
- me.updateStore.stopUpdate();
- }
+ deactivate: function() {
+ if (this.onlineHelp) {
+ Ext.GlobalEvents.fireEvent('proxmoxHideHelp', this.onlineHelp);
}
+ this.up('pveCephInstallWizard').down('#next').setText(gettext('Next'));
},
- items: [
- {
- xtype: 'pveNoVncConsole',
- itemId: 'jsconsole',
- consoleType: 'cmd',
- xtermjs: true,
- cbind: {
- nodename: '{nodename}',
+ },
+ },
+ {
+ title: gettext('Installation'),
+ xtype: 'panel',
+ layout: 'fit',
+ cbind: {
+ nodename: '{nodename}',
+ },
+ viewModel: {}, // needed to inherit parent viewModel data
+ listeners: {
+ afterrender: function() {
+ var me = this;
+ if (this.getViewModel().get('isInstalled')) {
+ this.mask("Ceph is already installed, click next to create your configuration.", ['pve-static-mask']);
+ } else {
+ me.down('pveNoVncConsole').fireEvent('activate');
+ }
+ },
+ activate: function() {
+ let me = this;
+ const nodename = me.nodename;
+ me.updateStore = Ext.create('Proxmox.data.UpdateStore', {
+ storeid: 'ceph-status-' + nodename,
+ interval: 1000,
+ proxy: {
+ type: 'proxmox',
+ url: '/api2/json/nodes/' + nodename + '/ceph/status',
},
- beforeLoad: function() {
- let me = this;
- let wizard = me.up('pveCephInstallWizard');
- let release = wizard.getViewModel().get('cephRelease');
- me.cmdOpts = `--version\0${release}`;
+ listeners: {
+ load: function(rec, response, success, operation) {
+ if (success) {
+ me.updateStore.stopUpdate();
+ me.down('textfield').setValue('success');
+ } else if (operation.error.statusText.match("not initialized", "i")) {
+ me.updateStore.stopUpdate();
+ me.up('pveCephInstallWizard').getViewModel().set('configuration', false);
+ me.down('textfield').setValue('success');
+ } else if (operation.error.statusText.match("rados_connect failed", "i")) {
+ me.updateStore.stopUpdate();
+ me.up('pveCephInstallWizard').getViewModel().set('configuration', true);
+ me.down('textfield').setValue('success');
+ } else if (!operation.error.statusText.match("not installed", "i")) {
+ Proxmox.Utils.setErrorMask(me, operation.error.statusText);
+ }
+ },
},
- cmd: 'ceph_install',
- },
- {
- xtype: 'textfield',
- name: 'installSuccess',
- value: '',
- allowBlank: false,
- submitValue: false,
- hidden: true
+ });
+ me.updateStore.startUpdate();
+ },
+ destroy: function() {
+ var me = this;
+ if (me.updateStore) {
+ me.updateStore.stopUpdate();
}
- ]
+ },
},
- {
- xtype: 'inputpanel',
- title: gettext('Configuration'),
- onlineHelp: 'chapter_pveceph',
- cbind: {
- nodename: '{nodename}'
+ items: [
+ {
+ xtype: 'pveNoVncConsole',
+ itemId: 'jsconsole',
+ consoleType: 'cmd',
+ xtermjs: true,
+ cbind: {
+ nodename: '{nodename}',
+ },
+ beforeLoad: function() {
+ let me = this;
+ let wizard = me.up('pveCephInstallWizard');
+ let release = wizard.getViewModel().get('cephRelease');
+ let repo = wizard.getViewModel().get('cephRepo');
+ me.cmdOpts = `--version\0${release}\0--repository\0${repo}`;
+ },
+ cmd: 'ceph_install',
},
- viewModel: {
- data: {
- replicas: undefined,
- minreplicas: undefined
+ {
+ xtype: 'textfield',
+ name: 'installSuccess',
+ value: '',
+ allowBlank: false,
+ submitValue: false,
+ hidden: true,
+ },
+ ],
+ },
+ {
+ xtype: 'inputpanel',
+ title: gettext('Configuration'),
+ onlineHelp: 'chapter_pveceph',
+ height: 300,
+ cbind: {
+ nodename: '{nodename}',
+ },
+ viewModel: {
+ data: {
+ replicas: undefined,
+ minreplicas: undefined,
+ },
+ },
+ listeners: {
+ activate: function() {
+ this.up('pveCephInstallWizard').down('#submit').setText(gettext('Next'));
+ },
+ afterrender: function() {
+ if (this.up('pveCephInstallWizard').getViewModel().get('configuration')) {
+ this.mask("Configuration already initialized", ['pve-static-mask']);
+ } else {
+ this.unmask();
}
},
- listeners: {
- activate: function() {
- this.up('pveCephInstallWizard').down('#submit').setText(gettext('Next'));
+ deactivate: function() {
+ this.up('pveCephInstallWizard').down('#submit').setText(gettext('Finish'));
+ },
+ },
+ column1: [
+ {
+ xtype: 'displayfield',
+ value: gettext('Ceph cluster configuration') + ':',
+ },
+ {
+ xtype: 'proxmoxNetworkSelector',
+ name: 'network',
+ value: '',
+ fieldLabel: 'Public Network IP/CIDR',
+ autoSelect: false,
+ bind: {
+ allowBlank: '{configuration}',
},
- beforeshow: function() {
- if (this.up('pveCephInstallWizard').getViewModel().get('configuration')) {
- this.mask("Configuration already initialized",['pve-static-mask']);
- } else {
- this.unmask();
- }
+ cbind: {
+ nodename: '{nodename}',
},
- deactivate: function() {
- this.up('pveCephInstallWizard').down('#submit').setText(gettext('Finish'));
- }
},
- column1: [
- {
- xtype: 'displayfield',
- value: gettext('Ceph cluster configuration') + ':'
+ {
+ xtype: 'proxmoxNetworkSelector',
+ name: 'cluster-network',
+ fieldLabel: 'Cluster Network IP/CIDR',
+ allowBlank: true,
+ autoSelect: false,
+ emptyText: gettext('Same as Public Network'),
+ cbind: {
+ nodename: '{nodename}',
},
- {
- xtype: 'proxmoxNetworkSelector',
- name: 'network',
- value: '',
- fieldLabel: 'Public Network IP/CIDR',
- bind: {
- allowBlank: '{configuration}'
- },
- cbind: {
- nodename: '{nodename}'
- }
+ },
+ // FIXME: add hint about cluster network and/or reference user to docs??
+ ],
+ column2: [
+ {
+ xtype: 'displayfield',
+ value: gettext('First Ceph monitor') + ':',
+ },
+ {
+ xtype: 'displayfield',
+ fieldLabel: gettext('Monitor node'),
+ cbind: {
+ value: '{nodename}',
},
- {
- xtype: 'proxmoxNetworkSelector',
- name: 'cluster-network',
- fieldLabel: 'Cluster Network IP/CIDR',
- allowBlank: true,
- autoSelect: false,
- emptyText: gettext('Same as Public Network'),
- cbind: {
- nodename: '{nodename}'
- }
- }
- // FIXME: add hint about cluster network and/or reference user to docs??
- ],
- column2: [
- {
- xtype: 'displayfield',
- value: gettext('First Ceph monitor') + ':'
+ },
+ {
+ xtype: 'displayfield',
+ value: gettext('Additional monitors are recommended. They can be created at any time in the Monitor tab.'),
+ userCls: 'pmx-hint',
+ },
+ ],
+ advancedColumn1: [
+ {
+ xtype: 'numberfield',
+ name: 'size',
+ fieldLabel: 'Number of replicas',
+ bind: {
+ value: '{replicas}',
},
- {
- xtype: 'pveNodeSelector',
- fieldLabel: gettext('Monitor node'),
- name: 'mon-node',
- selectCurNode: true,
- allowBlank: false
+ maxValue: 7,
+ minValue: 2,
+ emptyText: '3',
+ },
+ {
+ xtype: 'numberfield',
+ name: 'min_size',
+ fieldLabel: 'Minimum replicas',
+ bind: {
+ maxValue: '{replicas}',
+ value: '{minreplicas}',
},
- {
- xtype: 'displayfield',
- value: gettext('Additional monitors are recommended. They can be created at any time in the Monitor tab.'),
- userCls: 'pmx-hint'
- }
- ],
- advancedColumn1: [
- {
- xtype: 'numberfield',
- name: 'size',
- fieldLabel: 'Number of replicas',
- bind: {
- value: '{replicas}'
- },
- maxValue: 7,
- minValue: 2,
- emptyText: '3'
+ minValue: 2,
+ maxValue: 3,
+ setMaxValue: function(value) {
+ this.maxValue = Ext.Number.from(value, 2);
+ // allow enough to avoid split brains with max 'size', but more makes simply no sense
+ if (this.maxValue > 4) {
+ this.maxValue = 4;
+ }
+ this.toggleSpinners();
+ this.validate();
},
- {
- xtype: 'numberfield',
- name: 'min_size',
- fieldLabel: 'Minimum replicas',
- bind: {
- maxValue: '{replicas}',
- value: '{minreplicas}'
+ emptyText: '2',
+ },
+ ],
+ onGetValues: function(values) {
+ ['cluster-network', 'size', 'min_size'].forEach(function(field) {
+ if (!values[field]) {
+ delete values[field];
+ }
+ });
+ return values;
+ },
+ onSubmit: function() {
+ var me = this;
+ if (!this.up('pveCephInstallWizard').getViewModel().get('configuration')) {
+ var wizard = me.up('window');
+ var kv = wizard.getValues();
+ delete kv.delete;
+ var nodename = me.nodename;
+ delete kv.nodename;
+ Proxmox.Utils.API2Request({
+ url: `/nodes/${nodename}/ceph/init`,
+ waitMsgTarget: wizard,
+ method: 'POST',
+ params: kv,
+ success: function() {
+ Proxmox.Utils.API2Request({
+ url: `/nodes/${nodename}/ceph/mon/${nodename}`,
+ waitMsgTarget: wizard,
+ method: 'POST',
+ success: function() {
+ me.up('pveCephInstallWizard').navigateNext();
+ },
+ failure: function(response, opts) {
+ Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+ },
+ });
},
- minValue: 2,
- maxValue: 3,
- setMaxValue: function(value) {
- this.maxValue = Ext.Number.from(value, 2);
- // allow enough to avoid split brains with max 'size', but more makes simply no sense
- if (this.maxValue > 4) {
- this.maxValue = 4;
- }
- this.toggleSpinners();
- this.validate();
+ failure: function(response, opts) {
+ Ext.Msg.alert(gettext('Error'), response.htmlStatus);
},
- emptyText: '2'
- }
- ],
- onGetValues: function(values) {
- ['cluster-network', 'size', 'min_size'].forEach(function(field) {
- if (!values[field]) {
- delete values[field];
- }
});
- return values;
- },
- onSubmit: function() {
- var me = this;
- if (!this.up('pveCephInstallWizard').getViewModel().get('configuration')) {
- var wizard = me.up('window');
- var kv = wizard.getValues();
- delete kv['delete'];
- var monNode = kv['mon-node'];
- delete kv['mon-node'];
- var nodename = me.nodename;
- delete kv.nodename;
- Proxmox.Utils.API2Request({
- url: '/nodes/' + nodename + '/ceph/init',
- waitMsgTarget: wizard,
- method: 'POST',
- params: kv,
- success: function() {
- Proxmox.Utils.API2Request({
- url: '/nodes/' + monNode + '/ceph/mon/' + monNode,
- waitMsgTarget: wizard,
- method: 'POST',
- success: function() {
- me.up('pveCephInstallWizard').navigateNext();
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
- },
- failure: function(response, opts) {
- Ext.Msg.alert(gettext('Error'), response.htmlStatus);
- }
- });
-
- } else {
- me.up('pveCephInstallWizard').navigateNext();
- }
+ } else {
+ me.up('pveCephInstallWizard').navigateNext();
}
},
- {
- title: gettext('Success'),
- xtype: 'panel',
- border: false,
- bodyBorder: false,
- onlineHelp: 'pve_ceph_install',
- html: '<h3>Installation successful!</h3>'+
- '<p>The basic installation and configuration is completed, depending on your setup some of the following steps are required to start using Ceph:</p>'+
- '<ol><li>Install Ceph on other nodes</li>'+
- '<li>Create additional Ceph Monitors</li>'+
- '<li>Create Ceph OSDs</li>'+
- '<li>Create Ceph Pools</li></ol>'+
- '<p>To learn more click on the help button below.</p>',
- listeners: {
- activate: function() {
- // notify owning container that it should display a help button
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxShowHelp', this.onlineHelp);
- }
+ },
+ {
+ title: gettext('Success'),
+ xtype: 'panel',
+ border: false,
+ bodyBorder: false,
+ onlineHelp: 'pve_ceph_install',
+ html: '<h3>Installation successful!</h3>'+
+ '<p>The basic installation and configuration is complete. Depending on your setup, some of the following steps are required to start using Ceph:</p>'+
+ '<ol><li>Install Ceph on other nodes</li>'+
+ '<li>Create additional Ceph Monitors</li>'+
+ '<li>Create Ceph OSDs</li>'+
+ '<li>Create Ceph Pools</li></ol>'+
+ '<p>To learn more, click on the help button below.</p>',
+ listeners: {
+ activate: function() {
+ // notify owning container that it should display a help button
+ if (this.onlineHelp) {
+ Ext.GlobalEvents.fireEvent('proxmoxShowHelp', this.onlineHelp);
+ }
- var tp = this.up('#wizcontent');
- var idx = tp.items.indexOf(this)-1;
- for(;idx >= 0;idx--) {
- var nc = tp.items.getAt(idx);
- if (nc) {
- nc.disable();
- }
- }
- },
- deactivate: function() {
- if (this.onlineHelp) {
- Ext.GlobalEvents.fireEvent('proxmoxHideHelp', this.onlineHelp);
+ var tp = this.up('#wizcontent');
+ var idx = tp.items.indexOf(this)-1;
+ for (;idx >= 0; idx--) {
+ var nc = tp.items.getAt(idx);
+ if (nc) {
+ nc.disable();
}
}
},
- onSubmit: function() {
- var wizard = this.up('pveCephInstallWizard');
- wizard.close();
- }
- }
- ]
+ deactivate: function() {
+ if (this.onlineHelp) {
+ Ext.GlobalEvents.fireEvent('proxmoxHideHelp', this.onlineHelp);
+ }
+ },
+ },
+ onSubmit: function() {
+ var wizard = this.up('pveCephInstallWizard');
+ wizard.close();
+ },
+ },
+ ],
});