]> git.proxmox.com Git - pve-manager.git/blob - www/manager6/ceph/ServiceList.js
ui: eslint: fix trailing comma and comma related whitespaces errors
[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 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,
213 width: 800,
214 height: 400,
215 layout: 'fit',
216 items: [{
217 xtype: 'proxmoxLogView',
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'),
319 flex: 1,
320 sortable: true,
321 renderer: function(v) {
322 return this.type + '.' + v;
323 },
324 dataIndex: 'name',
325 },
326 {
327 header: gettext('Host'),
328 flex: 1,
329 sortable: true,
330 renderer: function(v) {
331 return v || Proxmox.Utils.unknownText;
332 },
333 dataIndex: 'host',
334 },
335 {
336 header: gettext('Status'),
337 flex: 1,
338 sortable: false,
339 dataIndex: 'state',
340 },
341 {
342 header: gettext('Address'),
343 flex: 3,
344 sortable: true,
345 renderer: function(v) {
346 return v || Proxmox.Utils.unknownText;
347 },
348 dataIndex: 'addr',
349 },
350 {
351 header: gettext('Version'),
352 flex: 3,
353 sortable: true,
354 dataIndex: 'version',
355 renderer: 'render_version',
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 });