]>
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 | 123 | view.versionsstore = Ext.create('Proxmox.data.UpdateStore', { |
277d6d15 DC |
124 | autoStart: true, |
125 | interval: 10000, | |
126 | storeid: 'ceph-versions-' + view.type + '-list' + view.nodename, | |
127 | proxy: { | |
128 | type: 'proxmox', | |
129 | url: "/api2/json/cluster/ceph/metadata?scope=versions" | |
130 | } | |
131 | }); | |
132 | ||
133 | view.versionsstore.on('load', this.getMaxVersions, this); | |
facf9404 | 134 | view.on('destroy', view.versionsstore.stopUpdate); |
277d6d15 | 135 | |
a6c60aed | 136 | view.rstore = Ext.create('Proxmox.data.UpdateStore', { |
a6c60aed DC |
137 | autoStart: true, |
138 | interval: 3000, | |
139 | storeid: 'ceph-' + view.type + '-list' + view.nodename, | |
140 | model: 'ceph-service-list', | |
141 | proxy: { | |
142 | type: 'proxmox', | |
143 | url: "/api2/json/nodes/" + view.nodename + "/ceph/" + view.type | |
144 | } | |
145 | }); | |
146 | ||
147 | view.setStore(Ext.create('Proxmox.data.DiffStore', { | |
148 | rstore: view.rstore, | |
149 | sorters: [{ property: 'name' }] | |
150 | })); | |
151 | ||
152 | if (view.storeLoadCallback) { | |
153 | view.rstore.on('load', view.storeLoadCallback, this); | |
154 | } | |
155 | view.on('destroy', view.rstore.stopUpdate); | |
156 | ||
157 | if (view.showCephInstallMask) { | |
158 | var regex = new RegExp("not (installed|initialized)", "i"); | |
159 | PVE.Utils.handleStoreErrorOrMask(view, view.rstore, regex, function(me, error) { | |
160 | view.rstore.stopUpdate(); | |
161 | PVE.Utils.showCephInstallOrMask(view.ownerCt, error.statusText, view.nodename, | |
162 | function(win){ | |
163 | me.mon(win, 'cephInstallWindowClosed', function(){ | |
164 | view.rstore.startUpdate(); | |
165 | }); | |
166 | } | |
167 | ); | |
168 | }); | |
169 | } | |
170 | }, | |
171 | ||
172 | service_cmd: function(rec, cmd) { | |
173 | var view = this.getView(); | |
174 | if (!rec.data.host) { | |
175 | Ext.Msg.alert(gettext('Error'), "entry has no host"); | |
176 | return; | |
177 | } | |
178 | Proxmox.Utils.API2Request({ | |
179 | url: "/nodes/" + rec.data.host + "/ceph/" + cmd, | |
180 | method: 'POST', | |
181 | params: { service: view.type + '.' + rec.data.name }, | |
182 | success: function(response, options) { | |
183 | var upid = response.result.data; | |
184 | var win = Ext.create('Proxmox.window.TaskProgress', { | |
185 | upid: upid, | |
186 | taskDone: function() { | |
187 | view.rstore.load(); | |
188 | } | |
189 | }); | |
190 | win.show(); | |
191 | }, | |
192 | failure: function(response, opts) { | |
193 | Ext.Msg.alert(gettext('Error'), response.htmlStatus); | |
194 | } | |
195 | }); | |
196 | }, | |
197 | onChangeService: function(btn) { | |
198 | var me = this; | |
199 | var view = this.getView(); | |
200 | var cmd = btn.action; | |
201 | var rec = view.getSelection()[0]; | |
202 | me.service_cmd(rec, cmd); | |
203 | }, | |
204 | ||
205 | showSyslog: function() { | |
206 | var view = this.getView(); | |
207 | var rec = view.getSelection()[0]; | |
208 | var servicename = 'ceph-' + view.type + '@' + rec.data.name; | |
209 | var url = "/api2/extjs/nodes/" + rec.data.host + "/syslog?service=" + encodeURIComponent(servicename); | |
210 | var win = Ext.create('Ext.window.Window', { | |
211 | title: gettext('Syslog') + ': ' + servicename, | |
212 | modal: true, | |
94b79c8e DC |
213 | width: 800, |
214 | height: 400, | |
215 | layout: 'fit', | |
a6c60aed DC |
216 | items: [{ |
217 | xtype: 'proxmoxLogView', | |
a6c60aed DC |
218 | url: url, |
219 | log_select_timespan: 1 | |
220 | }] | |
221 | }); | |
222 | win.show(); | |
223 | }, | |
224 | ||
225 | onCreate: function() { | |
226 | var view = this.getView(); | |
227 | var win = Ext.create('PVE.CephCreateService', { | |
228 | autoShow: true, | |
229 | nodename: view.nodename, | |
230 | subject: view.getTitle(), | |
231 | type: view.type, | |
232 | taskDone: function() { | |
233 | view.rstore.load(); | |
234 | } | |
235 | }); | |
236 | } | |
237 | }, | |
238 | ||
239 | tbar: [ | |
240 | { | |
241 | xtype: 'proxmoxButton', | |
242 | text: gettext('Start'), | |
243 | iconCls: 'fa fa-play', | |
244 | action: 'start', | |
245 | disabled: true, | |
246 | enableFn: function(rec) { | |
247 | return rec.data.state === 'stopped' || | |
248 | rec.data.state === 'unknown'; | |
249 | }, | |
250 | handler: 'onChangeService' | |
251 | }, | |
252 | { | |
253 | xtype: 'proxmoxButton', | |
254 | text: gettext('Stop'), | |
255 | iconCls: 'fa fa-stop', | |
256 | action: 'stop', | |
257 | enableFn: function(rec) { | |
258 | return rec.data.state !== 'stopped'; | |
259 | }, | |
260 | disabled: true, | |
261 | handler: 'onChangeService' | |
262 | }, | |
263 | { | |
264 | xtype: 'proxmoxButton', | |
265 | text: gettext('Restart'), | |
266 | iconCls: 'fa fa-refresh', | |
267 | action: 'restart', | |
268 | disabled: true, | |
269 | enableFn: function(rec) { | |
270 | return rec.data.state !== 'stopped'; | |
271 | }, | |
272 | handler: 'onChangeService' | |
273 | }, | |
274 | '-', | |
275 | { | |
276 | text: gettext('Create'), | |
277 | reference: 'createButton', | |
278 | handler: 'onCreate' | |
279 | }, | |
280 | { | |
281 | text: gettext('Destroy'), | |
282 | xtype: 'proxmoxStdRemoveButton', | |
283 | getUrl: function(rec) { | |
284 | var view = this.up('grid'); | |
285 | if (!rec.data.host) { | |
286 | Ext.Msg.alert(gettext('Error'), "entry has no host"); | |
287 | return; | |
288 | } | |
289 | return "/nodes/" + rec.data.host + "/ceph/" + view.type + "/" + rec.data.name; | |
290 | }, | |
291 | callback: function(options, success, response) { | |
292 | var view = this.up('grid'); | |
293 | if (!success) { | |
294 | Ext.Msg.alert(gettext('Error'), response.htmlStatus); | |
295 | return; | |
296 | } | |
297 | var upid = response.result.data; | |
298 | var win = Ext.create('Proxmox.window.TaskProgress', { | |
299 | upid: upid, | |
300 | taskDone: function() { | |
301 | view.rstore.load(); | |
302 | } | |
303 | }); | |
304 | win.show(); | |
305 | } | |
306 | }, | |
307 | '-', | |
308 | { | |
309 | xtype: 'proxmoxButton', | |
310 | text: gettext('Syslog'), | |
311 | disabled: true, | |
312 | handler: 'showSyslog' | |
313 | } | |
314 | ], | |
315 | ||
316 | columns: [ | |
317 | { | |
318 | header: gettext('Name'), | |
ee099a5f | 319 | flex: 1, |
a6c60aed DC |
320 | sortable: true, |
321 | renderer: function(v) { | |
322 | return this.type + '.' + v; | |
323 | }, | |
324 | dataIndex: 'name' | |
325 | }, | |
326 | { | |
327 | header: gettext('Host'), | |
ee099a5f | 328 | flex: 1, |
a6c60aed DC |
329 | sortable: true, |
330 | renderer: function(v) { | |
331 | return v || Proxmox.Utils.unknownText; | |
332 | }, | |
333 | dataIndex: 'host' | |
334 | }, | |
335 | { | |
336 | header: gettext('Status'), | |
ee099a5f | 337 | flex: 1, |
a6c60aed DC |
338 | sortable: false, |
339 | dataIndex: 'state' | |
340 | }, | |
341 | { | |
342 | header: gettext('Address'), | |
ee099a5f | 343 | flex: 3, |
a6c60aed DC |
344 | sortable: true, |
345 | renderer: function(v) { | |
346 | return v || Proxmox.Utils.unknownText; | |
347 | }, | |
348 | dataIndex: 'addr' | |
349 | }, | |
350 | { | |
351 | header: gettext('Version'), | |
ee099a5f | 352 | flex: 3, |
a6c60aed | 353 | sortable: true, |
277d6d15 DC |
354 | dataIndex: 'version', |
355 | renderer: 'render_version', | |
a6c60aed DC |
356 | } |
357 | ], | |
358 | ||
359 | initComponent: function() { | |
360 | var me = this; | |
361 | ||
362 | if (me.additionalColumns) { | |
363 | me.columns = me.columns.concat(me.additionalColumns); | |
364 | } | |
365 | ||
366 | me.callParent(); | |
367 | } | |
368 | ||
369 | }, function() { | |
370 | ||
371 | Ext.define('ceph-service-list', { | |
372 | extend: 'Ext.data.Model', | |
373 | fields: [ 'addr', 'name', 'rank', 'host', 'quorum', 'state', | |
374 | 'ceph_version', 'ceph_version_short', | |
375 | { type: 'string', name: 'version', calculate: function(data) { | |
376 | return PVE.Utils.parse_ceph_version(data); | |
377 | } } | |
378 | ], | |
379 | idProperty: 'name' | |
380 | }); | |
381 | }); |