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