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