]>
Commit | Line | Data |
---|---|---|
a6c60aed DC |
1 | Ext.define('PVE.CephCreateService', { |
2 | extend: 'Proxmox.window.Edit', | |
3 | xtype: 'pveCephCreateService', | |
4 | ||
5 | showProgress: true, | |
6 | ||
7 | setNode: function(nodename) { | |
8 | var me = this; | |
9 | ||
10 | me.nodename = nodename; | |
7ce1e64c | 11 | me.url = "/nodes/" + nodename + "/ceph/" + me.type + "/" + nodename; |
a6c60aed DC |
12 | }, |
13 | ||
14 | method: 'POST', | |
15 | isCreate: true, | |
16 | ||
17 | items: [ | |
18 | { | |
19 | xtype: 'pveNodeSelector', | |
20 | submitValue: false, | |
21 | fieldLabel: gettext('Host'), | |
22 | selectCurNode: true, | |
23 | allowBlank: false, | |
24 | listeners: { | |
25 | change: function(f, value) { | |
26 | var me = this.up('pveCephCreateService'); | |
27 | me.setNode(value); | |
28 | } | |
29 | } | |
30 | } | |
31 | ], | |
32 | ||
33 | initComponent : function() { | |
34 | var me = this; | |
35 | ||
36 | if (!me.nodename) { | |
37 | throw "no node name specified"; | |
38 | } | |
39 | ||
40 | if (!me.type) { | |
41 | throw "no type specified"; | |
42 | } | |
43 | ||
44 | me.setNode(me.nodename); | |
45 | ||
46 | me.callParent(); | |
47 | } | |
48 | }); | |
49 | ||
50 | Ext.define('PVE.node.CephServiceList', { | |
51 | extend: 'Ext.grid.GridPanel', | |
52 | xtype: 'pveNodeCephServiceList', | |
53 | ||
54 | onlineHelp: 'chapter_pveceph', | |
e148c752 | 55 | emptyText: gettext('No such service configured.'), |
a6c60aed DC |
56 | |
57 | stateful: true, | |
58 | ||
59 | // will be called when the store loads | |
60 | storeLoadCallback: Ext.emptyFn, | |
61 | ||
62 | // if set to true, does shows the ceph install mask if needed | |
63 | showCephInstallMask: false, | |
64 | ||
65 | controller: { | |
66 | xclass: 'Ext.app.ViewController', | |
67 | ||
277d6d15 DC |
68 | render_version: function(value, metadata, rec) { |
69 | let me = this.getView(); | |
70 | let host = rec.data.host; | |
71 | let icon = ""; | |
72 | let v = value; | |
73 | let nodev = [0]; | |
74 | if (me.nodeversions[host] !== undefined) { | |
75 | nodev = me.nodeversions[host].version.parts; | |
76 | } | |
77 | let maxv = me.maxversion; | |
78 | ||
79 | if (PVE.Utils.compare_ceph_versions(maxv, nodev) > 0) { | |
80 | icon = PVE.Utils.get_ceph_icon_html('HEALTH_UPGRADE'); | |
81 | } else if (PVE.Utils.compare_ceph_versions(nodev, v) > 0) { | |
82 | icon = PVE.Utils.get_ceph_icon_html('HEALTH_OLD'); | |
83 | } else if (me.mixedversions) { | |
84 | icon = PVE.Utils.get_ceph_icon_html('HEALTH_OK'); | |
85 | } | |
86 | ||
87 | return icon + v; | |
88 | }, | |
89 | ||
90 | getMaxVersions: function(store, records, success) { | |
91 | if (!success || records.length < 1) { | |
92 | return; | |
93 | } | |
94 | let me = this; | |
95 | let view = me.getView(); | |
96 | ||
97 | view.nodeversions = records[0].data.node; | |
98 | view.maxversion = []; | |
99 | view.mixedversions = false; | |
100 | for (const [nodename, data] of Object.entries(view.nodeversions)) { | |
732c147c DC |
101 | let res = PVE.Utils.compare_ceph_versions(data.version.parts, view.maxversion); |
102 | if (res !== 0 && view.maxversion.length > 0) { | |
103 | view.mixedversions = true; | |
104 | } | |
105 | if (res > 0) { | |
277d6d15 DC |
106 | view.maxversion = data.version.parts; |
107 | } | |
108 | } | |
109 | }, | |
110 | ||
a6c60aed DC |
111 | init: function(view) { |
112 | if (view.pveSelNode) { | |
113 | view.nodename = view.pveSelNode.data.node; | |
114 | } | |
115 | if (!view.nodename) { | |
116 | throw "no node name specified"; | |
117 | } | |
118 | ||
119 | if (!view.type) { | |
120 | throw "no type specified"; | |
121 | } | |
122 | ||
277d6d15 DC |
123 | view.versionsstore = Ext.create('Proxmox.data.UpdateStore', { |
124 | autoLoad: true, | |
125 | autoStart: true, | |
126 | interval: 10000, | |
127 | storeid: 'ceph-versions-' + view.type + '-list' + view.nodename, | |
128 | proxy: { | |
129 | type: 'proxmox', | |
130 | url: "/api2/json/cluster/ceph/metadata?scope=versions" | |
131 | } | |
132 | }); | |
133 | ||
134 | view.versionsstore.on('load', this.getMaxVersions, this); | |
facf9404 | 135 | view.on('destroy', view.versionsstore.stopUpdate); |
277d6d15 | 136 | |
a6c60aed DC |
137 | view.rstore = Ext.create('Proxmox.data.UpdateStore', { |
138 | autoLoad: true, | |
139 | autoStart: true, | |
140 | interval: 3000, | |
141 | storeid: 'ceph-' + view.type + '-list' + view.nodename, | |
142 | model: 'ceph-service-list', | |
143 | proxy: { | |
144 | type: 'proxmox', | |
145 | url: "/api2/json/nodes/" + view.nodename + "/ceph/" + view.type | |
146 | } | |
147 | }); | |
148 | ||
149 | view.setStore(Ext.create('Proxmox.data.DiffStore', { | |
150 | rstore: view.rstore, | |
151 | sorters: [{ property: 'name' }] | |
152 | })); | |
153 | ||
154 | if (view.storeLoadCallback) { | |
155 | view.rstore.on('load', view.storeLoadCallback, this); | |
156 | } | |
157 | view.on('destroy', view.rstore.stopUpdate); | |
158 | ||
159 | if (view.showCephInstallMask) { | |
160 | var regex = new RegExp("not (installed|initialized)", "i"); | |
161 | PVE.Utils.handleStoreErrorOrMask(view, view.rstore, regex, function(me, error) { | |
162 | view.rstore.stopUpdate(); | |
163 | PVE.Utils.showCephInstallOrMask(view.ownerCt, error.statusText, view.nodename, | |
164 | function(win){ | |
165 | me.mon(win, 'cephInstallWindowClosed', function(){ | |
166 | view.rstore.startUpdate(); | |
167 | }); | |
168 | } | |
169 | ); | |
170 | }); | |
171 | } | |
172 | }, | |
173 | ||
174 | service_cmd: function(rec, cmd) { | |
175 | var view = this.getView(); | |
176 | if (!rec.data.host) { | |
177 | Ext.Msg.alert(gettext('Error'), "entry has no host"); | |
178 | return; | |
179 | } | |
180 | Proxmox.Utils.API2Request({ | |
181 | url: "/nodes/" + rec.data.host + "/ceph/" + cmd, | |
182 | method: 'POST', | |
183 | params: { service: view.type + '.' + rec.data.name }, | |
184 | success: function(response, options) { | |
185 | var upid = response.result.data; | |
186 | var win = Ext.create('Proxmox.window.TaskProgress', { | |
187 | upid: upid, | |
188 | taskDone: function() { | |
189 | view.rstore.load(); | |
190 | } | |
191 | }); | |
192 | win.show(); | |
193 | }, | |
194 | failure: function(response, opts) { | |
195 | Ext.Msg.alert(gettext('Error'), response.htmlStatus); | |
196 | } | |
197 | }); | |
198 | }, | |
199 | onChangeService: function(btn) { | |
200 | var me = this; | |
201 | var view = this.getView(); | |
202 | var cmd = btn.action; | |
203 | var rec = view.getSelection()[0]; | |
204 | me.service_cmd(rec, cmd); | |
205 | }, | |
206 | ||
207 | showSyslog: function() { | |
208 | var view = this.getView(); | |
209 | var rec = view.getSelection()[0]; | |
210 | var servicename = 'ceph-' + view.type + '@' + rec.data.name; | |
211 | var url = "/api2/extjs/nodes/" + rec.data.host + "/syslog?service=" + encodeURIComponent(servicename); | |
212 | var win = Ext.create('Ext.window.Window', { | |
213 | title: gettext('Syslog') + ': ' + servicename, | |
214 | modal: true, | |
94b79c8e DC |
215 | width: 800, |
216 | height: 400, | |
217 | layout: 'fit', | |
a6c60aed DC |
218 | items: [{ |
219 | xtype: 'proxmoxLogView', | |
a6c60aed DC |
220 | url: url, |
221 | log_select_timespan: 1 | |
222 | }] | |
223 | }); | |
224 | win.show(); | |
225 | }, | |
226 | ||
227 | onCreate: function() { | |
228 | var view = this.getView(); | |
229 | var win = Ext.create('PVE.CephCreateService', { | |
230 | autoShow: true, | |
231 | nodename: view.nodename, | |
232 | subject: view.getTitle(), | |
233 | type: view.type, | |
234 | taskDone: function() { | |
235 | view.rstore.load(); | |
236 | } | |
237 | }); | |
238 | } | |
239 | }, | |
240 | ||
241 | tbar: [ | |
242 | { | |
243 | xtype: 'proxmoxButton', | |
244 | text: gettext('Start'), | |
245 | iconCls: 'fa fa-play', | |
246 | action: 'start', | |
247 | disabled: true, | |
248 | enableFn: function(rec) { | |
249 | return rec.data.state === 'stopped' || | |
250 | rec.data.state === 'unknown'; | |
251 | }, | |
252 | handler: 'onChangeService' | |
253 | }, | |
254 | { | |
255 | xtype: 'proxmoxButton', | |
256 | text: gettext('Stop'), | |
257 | iconCls: 'fa fa-stop', | |
258 | action: 'stop', | |
259 | enableFn: function(rec) { | |
260 | return rec.data.state !== 'stopped'; | |
261 | }, | |
262 | disabled: true, | |
263 | handler: 'onChangeService' | |
264 | }, | |
265 | { | |
266 | xtype: 'proxmoxButton', | |
267 | text: gettext('Restart'), | |
268 | iconCls: 'fa fa-refresh', | |
269 | action: 'restart', | |
270 | disabled: true, | |
271 | enableFn: function(rec) { | |
272 | return rec.data.state !== 'stopped'; | |
273 | }, | |
274 | handler: 'onChangeService' | |
275 | }, | |
276 | '-', | |
277 | { | |
278 | text: gettext('Create'), | |
279 | reference: 'createButton', | |
280 | handler: 'onCreate' | |
281 | }, | |
282 | { | |
283 | text: gettext('Destroy'), | |
284 | xtype: 'proxmoxStdRemoveButton', | |
285 | getUrl: function(rec) { | |
286 | var view = this.up('grid'); | |
287 | if (!rec.data.host) { | |
288 | Ext.Msg.alert(gettext('Error'), "entry has no host"); | |
289 | return; | |
290 | } | |
291 | return "/nodes/" + rec.data.host + "/ceph/" + view.type + "/" + rec.data.name; | |
292 | }, | |
293 | callback: function(options, success, response) { | |
294 | var view = this.up('grid'); | |
295 | if (!success) { | |
296 | Ext.Msg.alert(gettext('Error'), response.htmlStatus); | |
297 | return; | |
298 | } | |
299 | var upid = response.result.data; | |
300 | var win = Ext.create('Proxmox.window.TaskProgress', { | |
301 | upid: upid, | |
302 | taskDone: function() { | |
303 | view.rstore.load(); | |
304 | } | |
305 | }); | |
306 | win.show(); | |
307 | } | |
308 | }, | |
309 | '-', | |
310 | { | |
311 | xtype: 'proxmoxButton', | |
312 | text: gettext('Syslog'), | |
313 | disabled: true, | |
314 | handler: 'showSyslog' | |
315 | } | |
316 | ], | |
317 | ||
318 | columns: [ | |
319 | { | |
320 | header: gettext('Name'), | |
ee099a5f | 321 | flex: 1, |
a6c60aed DC |
322 | sortable: true, |
323 | renderer: function(v) { | |
324 | return this.type + '.' + v; | |
325 | }, | |
326 | dataIndex: 'name' | |
327 | }, | |
328 | { | |
329 | header: gettext('Host'), | |
ee099a5f | 330 | flex: 1, |
a6c60aed DC |
331 | sortable: true, |
332 | renderer: function(v) { | |
333 | return v || Proxmox.Utils.unknownText; | |
334 | }, | |
335 | dataIndex: 'host' | |
336 | }, | |
337 | { | |
338 | header: gettext('Status'), | |
ee099a5f | 339 | flex: 1, |
a6c60aed DC |
340 | sortable: false, |
341 | dataIndex: 'state' | |
342 | }, | |
343 | { | |
344 | header: gettext('Address'), | |
ee099a5f | 345 | flex: 3, |
a6c60aed DC |
346 | sortable: true, |
347 | renderer: function(v) { | |
348 | return v || Proxmox.Utils.unknownText; | |
349 | }, | |
350 | dataIndex: 'addr' | |
351 | }, | |
352 | { | |
353 | header: gettext('Version'), | |
ee099a5f | 354 | flex: 3, |
a6c60aed | 355 | sortable: true, |
277d6d15 DC |
356 | dataIndex: 'version', |
357 | renderer: 'render_version', | |
a6c60aed DC |
358 | } |
359 | ], | |
360 | ||
361 | initComponent: function() { | |
362 | var me = this; | |
363 | ||
364 | if (me.additionalColumns) { | |
365 | me.columns = me.columns.concat(me.additionalColumns); | |
366 | } | |
367 | ||
368 | me.callParent(); | |
369 | } | |
370 | ||
371 | }, function() { | |
372 | ||
373 | Ext.define('ceph-service-list', { | |
374 | extend: 'Ext.data.Model', | |
375 | fields: [ 'addr', 'name', 'rank', 'host', 'quorum', 'state', | |
376 | 'ceph_version', 'ceph_version_short', | |
377 | { type: 'string', name: 'version', calculate: function(data) { | |
378 | return PVE.Utils.parse_ceph_version(data); | |
379 | } } | |
380 | ], | |
381 | idProperty: 'name' | |
382 | }); | |
383 | }); |