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