]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/ceph/CephInstallWizard.js
bcb44815940670aec013190d5acfd18b31c2caef
[pve-manager.git] / www / manager6 / ceph / CephInstallWizard.js
1 /*jslint confusion: true*/
2 Ext.define('PVE.ceph.CephInstallWizard', {
3 extend: 'PVE.window.Wizard',
4 alias: 'widget.pveCephInstallWizard',
5 mixins: ['Proxmox.Mixin.CBind'],
6 resizable: false,
7 nodename: undefined,
8 viewModel: {
9 data: {
10 nodename: '',
11 configuration: true,
12 isInstalled: false
13 }
14 },
15 cbindData: {
16 nodename: undefined
17 },
18 title: gettext('Setup'),
19 navigateNext: function() {
20 var tp = this.down('#wizcontent');
21 var atab = tp.getActiveTab();
22
23 var next = tp.items.indexOf(atab) + 1;
24 var ntab = tp.items.getAt(next);
25 if (ntab) {
26 ntab.enable();
27 tp.setActiveTab(ntab);
28 }
29 },
30 setInitialTab: function (index) {
31 var tp = this.down('#wizcontent');
32 var initialTab = tp.items.getAt(index);
33 initialTab.enable();
34 tp.setActiveTab(initialTab);
35 },
36 onShow: function() {
37 this.callParent(arguments);
38 var isInstalled = this.getViewModel().get('isInstalled');
39 if (isInstalled) {
40 this.getViewModel().set('configuration', false);
41 this.setInitialTab(2);
42 }
43 },
44 items: [
45 {
46 title: gettext('Info'),
47 xtype: 'panel',
48 border: false,
49 bodyBorder: false,
50 onlineHelp: 'chapter_pveceph',
51 html: '<h3>Ceph?</h3>'+
52 '<blockquote cite="https://ceph.com/"><p>"<b>Ceph</b> is a unified, distributed storage system designed for excellent performance, reliability and scalability."</p></blockquote>'+
53 '<p><b>Ceph</b> is currently <b>not installed</b> on this node, click on the next button below to start the installation.'+
54 ' This wizard will guide you through the necessary steps, after the initial installation you will be offered to create an initial configuration.'+
55 ' The configuration step is only needed once per cluster and will be skipped if a config is already present.</p>'+
56 '<p>Please take a look at our documentation, by clicking the help button below, before starting the installation, '+
57 'if you want to gain deeper knowledge about Ceph visit <a target="_blank" href="http://docs.ceph.com/docs/master/">ceph.com</a>.</p>',
58 listeners: {
59 activate: function() {
60 // notify owning container that it should display a help button
61 if (this.onlineHelp) {
62 Ext.GlobalEvents.fireEvent('proxmoxShowHelp', this.onlineHelp);
63 }
64 this.up('pveCephInstallWizard').down('#back').hide(true);
65 this.up('pveCephInstallWizard').down('#next').setText(gettext('Start installation'));
66 },
67 deactivate: function() {
68 if (this.onlineHelp) {
69 Ext.GlobalEvents.fireEvent('proxmoxHideHelp', this.onlineHelp);
70 }
71 this.up('pveCephInstallWizard').down('#next').setText(gettext('Next'));
72 }
73 }
74 },
75 {
76 title: gettext('Installation'),
77 xtype: 'panel',
78 layout: 'fit',
79 cbind:{
80 nodename: '{nodename}'
81 },
82 viewModel: {}, // needed to inherit parent viewModel data
83 listeners: {
84 afterrender: function() {
85 var me = this;
86 if (this.getViewModel().get('isInstalled')) {
87 this.mask("Ceph is already installed, click next to create your configuration.",['pve-static-mask']);
88 } else {
89 me.down('pveNoVncConsole').fireEvent('activate');
90 }
91 },
92 activate: function() {
93 var me = this;
94 var nodename = me.nodename;
95 me.updateStore = Ext.create('Proxmox.data.UpdateStore', {
96 storeid: 'ceph-status-' + nodename,
97 interval: 1000,
98 proxy: {
99 type: 'proxmox',
100 url: '/api2/json/nodes/' + nodename + '/ceph/status'
101 },
102 listeners: {
103 load: function(rec, response, success, operation) {
104
105 if (success) {
106 me.updateStore.stopUpdate();
107 me.down('textfield').setValue('success');
108 } else if (operation.error.statusText.match("not initialized", "i")) {
109 me.updateStore.stopUpdate();
110 me.up('pveCephInstallWizard').getViewModel().set('configuration',false);
111 me.down('textfield').setValue('success');
112 } else if (operation.error.statusText.match("rados_connect failed", "i")) {
113 me.updateStore.stopUpdate();
114 me.up('pveCephInstallWizard').getViewModel().set('configuration',true);
115 me.down('textfield').setValue('success');
116 } else if (!operation.error.statusText.match("not installed", "i")) {
117 Proxmox.Utils.setErrorMask(me, operation.error.statusText);
118 }
119 }
120 }
121 });
122 me.updateStore.startUpdate();
123 },
124 destroy: function() {
125 var me = this;
126 if (me.updateStore) {
127 me.updateStore.stopUpdate();
128 }
129 }
130 },
131 items: [
132 {
133 itemId: 'jsconsole',
134 consoleType: 'cmd',
135 xtermjs: true,
136 xtype: 'pveNoVncConsole',
137 cbind:{
138 nodename: '{nodename}'
139 },
140 cmd: 'ceph_install'
141 },
142 {
143 xtype: 'textfield',
144 name: 'installSuccess',
145 value: '',
146 allowBlank: false,
147 submitValue: false,
148 hidden: true
149 }
150 ]
151 },
152 {
153 xtype: 'inputpanel',
154 title: gettext('Configuration'),
155 onlineHelp: 'chapter_pveceph',
156 cbind: {
157 nodename: '{nodename}'
158 },
159 viewModel: {
160 data: {
161 replicas: undefined,
162 minreplicas: undefined
163 }
164 },
165 listeners: {
166 activate: function() {
167 this.up('pveCephInstallWizard').down('#submit').setText(gettext('Next'));
168 },
169 beforeshow: function() {
170 if (this.up('pveCephInstallWizard').getViewModel().get('configuration')) {
171 this.mask("Configuration already initialized",['pve-static-mask']);
172 } else {
173 this.unmask();
174 }
175 },
176 deactivate: function() {
177 this.up('pveCephInstallWizard').down('#submit').setText(gettext('Finish'));
178 }
179 },
180 column1: [
181 {
182 xtype: 'displayfield',
183 value: gettext('Ceph cluster configuration') + ':'
184 },
185 {
186 xtype: 'proxmoxNetworkSelector',
187 name: 'network',
188 value: '',
189 fieldLabel: 'Public Network IP/CIDR',
190 bind: {
191 allowBlank: '{configuration}'
192 },
193 cbind: {
194 nodename: '{nodename}'
195 }
196 },
197 {
198 xtype: 'proxmoxNetworkSelector',
199 name: 'cluster-network',
200 fieldLabel: 'Cluster Network IP/CIDR',
201 allowBlank: true,
202 autoSelect: false,
203 emptyText: gettext('Same as Public Network'),
204 cbind: {
205 nodename: '{nodename}'
206 }
207 }
208 // FIXME: add hint about cluster network and/or reference user to docs??
209 ],
210 column2: [
211 {
212 xtype: 'displayfield',
213 value: gettext('First Ceph monitor') + ':'
214 },
215 {
216 xtype: 'pveNodeSelector',
217 fieldLabel: gettext('Monitor node'),
218 name: 'mon-node',
219 selectCurNode: true,
220 allowBlank: false
221 },
222 {
223 xtype: 'displayfield',
224 value: gettext('Additional monitors are recommended. They can be created at any time in the Monitor tab.'),
225 userCls: 'pmx-hint'
226 }
227 ],
228 advancedColumn1: [
229 {
230 xtype: 'numberfield',
231 name: 'size',
232 fieldLabel: 'Number of replicas',
233 bind: {
234 value: '{replicas}'
235 },
236 maxValue: 7,
237 minValue: 2,
238 emptyText: '3'
239 },
240 {
241 xtype: 'numberfield',
242 name: 'min_size',
243 fieldLabel: 'Minimum replicas',
244 bind: {
245 maxValue: '{replicas}',
246 value: '{minreplicas}'
247 },
248 minValue: 2,
249 maxValue: 3,
250 setMaxValue: function(value) {
251 this.maxValue = Ext.Number.from(value, 2);
252 // allow enough to avoid split brains with max 'size', but more makes simply no sense
253 if (this.maxValue > 4) {
254 this.maxValue = 4;
255 }
256 this.toggleSpinners();
257 this.validate();
258 },
259 emptyText: '2'
260 }
261 ],
262 onGetValues: function(values) {
263 ['cluster-network', 'size', 'min_size'].forEach(function(field) {
264 if (!values[field]) {
265 delete values[field];
266 }
267 });
268 return values;
269 },
270 onSubmit: function() {
271 var me = this;
272 if (!this.up('pveCephInstallWizard').getViewModel().get('configuration')) {
273 var wizard = me.up('window');
274 var kv = wizard.getValues();
275 delete kv['delete'];
276 var monNode = kv['mon-node'];
277 delete kv['mon-node'];
278 var nodename = me.nodename;
279 delete kv.nodename;
280 Proxmox.Utils.API2Request({
281 url: '/nodes/' + nodename + '/ceph/init',
282 waitMsgTarget: wizard,
283 method: 'POST',
284 params: kv,
285 success: function() {
286 Proxmox.Utils.API2Request({
287 url: '/nodes/' + monNode + '/ceph/mon/' + monNode,
288 waitMsgTarget: wizard,
289 method: 'POST',
290 success: function() {
291 me.up('pveCephInstallWizard').navigateNext();
292 },
293 failure: function(response, opts) {
294 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
295 }
296 });
297 },
298 failure: function(response, opts) {
299 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
300 }
301 });
302
303 } else {
304 me.up('pveCephInstallWizard').navigateNext();
305 }
306 }
307 },
308 {
309 title: gettext('Success'),
310 xtype: 'panel',
311 border: false,
312 bodyBorder: false,
313 onlineHelp: 'pve_ceph_install',
314 html: '<h3>Installation successful!</h3>'+
315 '<p>The basic installation and configuration is completed, depending on your setup some of the following steps are required to start using Ceph:</p>'+
316 '<ol><li>Install Ceph on other nodes</li>'+
317 '<li>Create additional Ceph Monitors</li>'+
318 '<li>Create Ceph OSDs</li>'+
319 '<li>Create Ceph Pools</li></ol>'+
320 '<p>To learn more click on the help button below.</p>',
321 listeners: {
322 activate: function() {
323 // notify owning container that it should display a help button
324 if (this.onlineHelp) {
325 Ext.GlobalEvents.fireEvent('proxmoxShowHelp', this.onlineHelp);
326 }
327
328 var tp = this.up('#wizcontent');
329 var idx = tp.items.indexOf(this)-1;
330 for(;idx >= 0;idx--) {
331 var nc = tp.items.getAt(idx);
332 if (nc) {
333 nc.disable();
334 }
335 }
336 },
337 deactivate: function() {
338 if (this.onlineHelp) {
339 Ext.GlobalEvents.fireEvent('proxmoxHideHelp', this.onlineHelp);
340 }
341 }
342 },
343 onSubmit: function() {
344 var wizard = this.up('pveCephInstallWizard');
345 wizard.close();
346 }
347 }
348 ]
349 });