]> git.proxmox.com Git - pve-manager.git/blame - www/manager6/ceph/OSD.js
ceph: set/unset flag: remove unused variable
[pve-manager.git] / www / manager6 / ceph / OSD.js
CommitLineData
4ea09218 1Ext.define('PVE.CephCreateOsd', {
9fccc702 2 extend: 'Proxmox.window.Edit',
4d3e918a 3 xtype: 'pveCephCreateOsd',
4ea09218
DM
4
5 subject: 'Ceph OSD',
6
7 showProgress: true,
8
35085f4a
TL
9 onlineHelp: 'pve_ceph_osds',
10
4ea09218 11 initComponent : function() {
4ea09218
DM
12 var me = this;
13
14 if (!me.nodename) {
15 throw "no node name specified";
16 }
17
d5e771ce 18 me.isCreate = true;
c474314e 19
4ea09218
DM
20 Ext.applyIf(me, {
21 url: "/nodes/" + me.nodename + "/ceph/osd",
9ad28182
DC
22 method: 'POST',
23 items: [
24 {
4d3e918a 25 xtype: 'inputpanel',
4c94e9de
DC
26 onGetValues: function(values) {
27 Object.keys(values || {}).forEach(function(name) {
28 if (values[name] === '') {
29 delete values[name];
30 }
31 });
32
33 return values;
34 },
4d3e918a
DC
35 column1: [
36 {
37 xtype: 'pveDiskSelector',
38 name: 'dev',
39 nodename: me.nodename,
40 diskType: 'unused',
41 fieldLabel: gettext('Disk'),
42 allowBlank: false
43 }
44 ],
45 column2: [
46 {
47 xtype: 'pveDiskSelector',
48 name: 'db_dev',
49 nodename: me.nodename,
50 diskType: 'journal_disks',
51 fieldLabel: gettext('DB Disk'),
52 value: '',
53 autoSelect: false,
54 allowBlank: true,
55 emptyText: 'use OSD disk',
56 listeners: {
57 change: function(field, val) {
58 me.down('field[name=db_size]').setDisabled(!val);
59 }
60 }
61 },
62 {
63 xtype: 'numberfield',
64 name: 'db_size',
65 fieldLabel: gettext('DB size') + ' (GiB)',
66 minValue: 1,
67 maxValue: 128*1024,
68 decimalPrecision: 2,
69 allowBlank: true,
70 disabled: true,
71 emptyText: gettext('Automatic')
72 }
73 ],
74 advancedColumn1: [
6c311f2c
DC
75 {
76 xtype: 'proxmoxcheckbox',
77 name: 'encrypted',
78 fieldLabel: gettext('Encrypt OSD')
79 },
80 ],
81 advancedColumn2: [
4d3e918a
DC
82 {
83 xtype: 'pveDiskSelector',
84 name: 'wal_dev',
85 nodename: me.nodename,
86 diskType: 'journal_disks',
87 fieldLabel: gettext('WAL Disk'),
88 value: '',
89 autoSelect: false,
90 allowBlank: true,
91 emptyText: 'use OSD/DB disk',
92 listeners: {
93 change: function(field, val) {
94 me.down('field[name=wal_size]').setDisabled(!val);
95 }
96 }
97 },
98 {
99 xtype: 'numberfield',
100 name: 'wal_size',
101 fieldLabel: gettext('WAL size') + ' (GiB)',
102 minValue: 0.5,
103 maxValue: 128*1024,
104 decimalPrecision: 2,
105 allowBlank: true,
106 disabled: true,
107 emptyText: gettext('Automatic')
108 }
109 ]
deca45c1
TL
110 },
111 {
112 xtype: 'displayfield',
113 padding: '5 0 0 0',
114 userCls: 'pve-hint',
115 value: 'Note: Ceph is not compatible with disks backed by a hardware ' +
116 'RAID controller. For details see ' +
117 '<a target="_blank" href="' + Proxmox.Utils.get_help_link('chapter_pveceph') + '">the reference documentation</a>.',
fddeb25b 118 }
4d3e918a
DC
119 ]
120 });
4ea09218 121
4d3e918a 122 me.callParent();
4ea09218
DM
123 }
124});
125
126Ext.define('PVE.CephRemoveOsd', {
9fccc702 127 extend: 'Proxmox.window.Edit',
4ea09218
DM
128 alias: ['widget.pveCephRemoveOsd'],
129
130 isRemove: true,
131
132 showProgress: true,
89cd5a3f
DC
133 method: 'DELETE',
134 items: [
135 {
896c0d50 136 xtype: 'proxmoxcheckbox',
89cd5a3f
DC
137 name: 'cleanup',
138 checked: true,
139 labelWidth: 130,
c56634f1 140 fieldLabel: gettext('Cleanup Disks')
89cd5a3f
DC
141 }
142 ],
4ea09218 143 initComponent : function() {
d5e771ce 144
4ea09218
DM
145 var me = this;
146
147 if (!me.nodename) {
148 throw "no node name specified";
149 }
150 if (me.osdid === undefined || me.osdid < 0) {
151 throw "no osdid specified";
152 }
153
d5e771ce 154 me.isCreate = true;
4ea09218 155
fb0e1813 156 me.title = gettext('Destroy') + ': Ceph OSD osd.' + me.osdid.toString();
c474314e 157
4ea09218 158 Ext.applyIf(me, {
d5e771ce 159 url: "/nodes/" + me.nodename + "/ceph/osd/" + me.osdid.toString()
4ea09218
DM
160 });
161
162 me.callParent();
163 }
164});
165
166Ext.define('PVE.node.CephOsdTree', {
167 extend: 'Ext.tree.Panel',
168 alias: ['widget.pveNodeCephOsdTree'],
ba93a9c6 169 onlineHelp: 'chapter_pveceph',
3982a214
DC
170
171 viewModel: {
172 data: {
173 nodename: '',
174 flags: [],
175 maxversion: '0',
0b88c18a 176 mixedversions: false,
3982a214
DC
177 versions: {},
178 isOsd: false,
179 downOsd: false,
180 upOsd: false,
181 inOsd: false,
182 outOsd: false,
183 osdid: '',
184 osdhost: '',
185 }
186 },
187
188 controller: {
189 xclass: 'Ext.app.ViewController',
190
191 reload: function() {
192 var me = this.getView();
193 var vm = this.getViewModel();
194 var nodename = vm.get('nodename');
195 var sm = me.getSelectionModel();
196 Proxmox.Utils.API2Request({
197 url: "/nodes/" + nodename + "/ceph/osd",
198 waitMsgTarget: me,
199 method: 'GET',
200 failure: function(response, opts) {
201 var msg = response.htmlStatus;
202 PVE.Utils.showCephInstallOrMask(me, msg, nodename,
203 function(win){
204 me.mon(win, 'cephInstallWindowClosed', this.reload);
205 }
206 );
207 },
208 success: function(response, opts) {
209 var data = response.result.data;
210 var selected = me.getSelection();
211 var name;
212 if (selected.length) {
213 name = selected[0].data.name;
214 }
215 vm.set('versions', data.versions);
216 // extract max version
0b88c18a
DC
217 var maxversion = "0";
218 var mixedversions = false;
219 var traverse;
220 traverse = function(node, fn) {
221 fn(node);
222 if (Array.isArray(node.children)) {
223 node.children.forEach(c => { traverse(c, fn); });
3982a214 224 }
0b88c18a
DC
225 };
226 traverse(data.root, node => {
227 // compatibility for old api call
228 if (node.type === 'host' && node.version === undefined) {
229 node.version = data.versions[node.name];
230 }
231
232 if (node.version === undefined) {
233 return;
234 }
235
236 if (node.version !== maxversion && maxversion !== "0") {
237 mixedversions = true;
238 }
239
240 if (PVE.Utils.compare_ceph_versions(node.version, maxversion) > 0) {
241 maxversion = node.version;
242 }
243
3982a214
DC
244 });
245 vm.set('maxversion', maxversion);
0b88c18a 246 vm.set('mixedversions', mixedversions);
3982a214
DC
247 sm.deselectAll();
248 me.setRootNode(data.root);
249 me.expandAll();
250 if (name) {
251 var node = me.getRootNode().findChild('name', name, true);
252 if (node) {
253 me.setSelection([node]);
254 }
255 }
256
257 var flags = data.flags.split(',');
258 vm.set('flags', flags);
259 var noout = flags.includes('noout');
260 me.down('#nooutBtn').setText(noout ? gettext("Unset noout") : gettext("Set noout"));
261 }
262 });
263 },
264
265 osd_cmd: function(comp) {
266 var me = this;
267 var vm = this.getViewModel();
268 var cmd = comp.cmd;
269 var params = comp.params || {};
270 var osdid = vm.get('osdid');
271
272 var doRequest = function() {
273 Proxmox.Utils.API2Request({
274 url: "/nodes/" + vm.get('osdhost') + "/ceph/osd/" + osdid + '/' + cmd,
275 waitMsgTarget: me.getView(),
276 method: 'POST',
277 params: params,
278 success: () => { me.reload(); },
279 failure: function(response, opts) {
280 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
281 }
282 });
283 };
284
285 if (cmd === 'scrub') {
286 Ext.MessageBox.defaultButton = params.deep === 1 ? 2 : 1;
287 Ext.Msg.show({
288 title: gettext('Confirm'),
289 icon: params.deep === 1 ? Ext.Msg.WARNING : Ext.Msg.QUESTION,
290 msg: params.deep !== 1 ?
291 Ext.String.format(gettext("Scrub OSD.{0}"), osdid) :
292 Ext.String.format(gettext("Deep Scrub OSD.{0}"), osdid) +
293 "<br>Caution: This can reduce performance while it is running.",
294 buttons: Ext.Msg.YESNO,
295 callback: function(btn) {
296 if (btn !== 'yes') {
297 return;
298 }
299 doRequest();
300 }
301 });
302 } else {
303 doRequest();
304 }
305 },
306
307 create_osd: function() {
308 var me = this;
309 var vm = this.getViewModel();
310 Ext.create('PVE.CephCreateOsd', {
311 nodename: vm.get('nodename'),
312 taskDone: () => { me.reload(); }
313 }).show();
314 },
315
316 destroy_osd: function() {
317 var me = this;
318 var vm = this.getViewModel();
319 Ext.create('PVE.CephRemoveOsd', {
320 nodename: vm.get('osdhost'),
321 osdid: vm.get('osdid'),
322 taskDone: () => { me.reload(); }
323 }).show();
324 },
325
326 set_flag: function() {
327 var me = this;
328 var vm = this.getViewModel();
329 var flags = vm.get('flags');
330 Proxmox.Utils.API2Request({
331 url: "/nodes/" + vm.get('nodename') + "/ceph/flags/noout",
332 waitMsgTarget: me.getView(),
333 method: flags.includes('noout') ? 'DELETE' : 'POST',
334 failure: function(response, opts) {
335 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
336 },
337 success: () => { me.reload(); }
338 });
339 },
340
341 service_cmd: function(comp) {
342 var me = this;
343 var vm = this.getViewModel();
344 var cmd = comp.cmd || comp;
345 Proxmox.Utils.API2Request({
346 url: "/nodes/" + vm.get('osdhost') + "/ceph/" + cmd,
347 params: { service: "osd." + vm.get('osdid') },
348 waitMsgTarget: me.getView(),
349 method: 'POST',
350 success: function(response, options) {
351 var upid = response.result.data;
352 var win = Ext.create('Proxmox.window.TaskProgress', {
353 upid: upid,
354 taskDone: () => { me.reload(); }
355 });
356 win.show();
357 },
358 failure: function(response, opts) {
359 Ext.Msg.alert(gettext('Error'), response.htmlStatus);
360 }
361 });
362 },
363
364 set_selection_status: function(tp, selection) {
365 if (selection.length < 1) {
366 return;
367 }
368 var rec = selection[0];
369 var vm = this.getViewModel();
370
371 var isOsd = (rec.data.host && (rec.data.type === 'osd') && (rec.data.id >= 0));
372
373 vm.set('isOsd', isOsd);
374 vm.set('downOsd', isOsd && rec.data.status === 'down');
375 vm.set('upOsd', isOsd && rec.data.status !== 'down');
376 vm.set('inOsd', isOsd && rec.data.in);
377 vm.set('outOsd', isOsd && !rec.data.in);
378 vm.set('osdid', isOsd ? rec.data.id : undefined);
379 vm.set('osdhost', isOsd ? rec.data.host : undefined);
3982a214
DC
380 },
381
382 render_status: function(value, metaData, rec) {
383 if (!value) {
384 return value;
385 }
386 var inout = rec.data['in'] ? 'in' : 'out';
387 var updownicon = value === 'up' ? 'good fa-arrow-circle-up' :
388 'critical fa-arrow-circle-down';
389
390 var inouticon = rec.data['in'] ? 'good fa-circle' :
391 'warning fa-circle-o';
392
393 var text = value + ' <i class="fa ' + updownicon + '"></i> / ' +
394 inout + ' <i class="fa ' + inouticon + '"></i>';
395
396 return text;
397 },
398
399 render_wal: function(value, metaData, rec) {
400 if (!value &&
401 rec.data.osdtype === 'bluestore' &&
402 rec.data.type === 'osd') {
403 return 'N/A';
404 }
405 return value;
406 },
407
408 render_version: function(value, metadata, rec) {
409 var vm = this.getViewModel();
410 var versions = vm.get('versions');
411 var icon = "";
412 var version = value || "";
0b88c18a
DC
413 var maxversion = vm.get('maxversion');
414 if (value && value != maxversion) {
415 if (rec.data.type === 'host' || versions[rec.data.host] !== maxversion) {
416 icon = PVE.Utils.get_ceph_icon_html('HEALTH_UPGRADE');
417 } else {
418 icon = PVE.Utils.get_ceph_icon_html('HEALTH_OLD');
419 }
420 } else if (value && vm.get('mixedversions')) {
421 icon = PVE.Utils.get_ceph_icon_html('HEALTH_OK');
3982a214
DC
422 }
423
424 return icon + version;
425 },
426
427 render_osd_val: function(value, metaData, rec) {
428 return (rec.data.type === 'osd') ? value : '';
429 },
a3368752
TL
430 render_osd_weight: function(value, metaData, rec) {
431 if (rec.data.type !== 'osd') {
432 return '';
433 }
434 return Ext.util.Format.number(value, '0.00###');
435 },
3982a214 436
a9e23b28
TL
437 render_osd_latency: function(value, metaData, rec) {
438 if (rec.data.type !== 'osd') {
439 return '';
440 }
441 let commit_ms = rec.data.commit_latency_ms,
442 apply_ms = rec.data.apply_latency_ms;
443 return apply_ms + ' / ' + commit_ms;
444 },
445
3982a214
DC
446 render_osd_size: function(value, metaData, rec) {
447 return this.render_osd_val(PVE.Utils.render_size(value), metaData, rec);
448 },
449
450 control: {
451 '#': {
452 selectionchange: 'set_selection_status'
453 }
454 },
455
456 init: function(view) {
457 var me = this;
458 var vm = this.getViewModel();
459
460 if (!view.pveSelNode.data.node) {
461 throw "no node name specified";
462 }
463
464 vm.set('nodename', view.pveSelNode.data.node);
465
466 me.callParent();
467 me.reload();
468 }
469 },
470
361aafd0
DC
471 stateful: true,
472 stateId: 'grid-ceph-osd',
3982a214
DC
473 rootVisible: false,
474 useArrows: true,
475
89cd5a3f
DC
476 columns: [
477 {
478 xtype: 'treecolumn',
479 text: 'Name',
480 dataIndex: 'name',
481 width: 150
482 },
483 {
484 text: 'Type',
485 dataIndex: 'type',
413ada0f 486 hidden: true,
89cd5a3f 487 align: 'right',
a3f146fc 488 width: 75
89cd5a3f 489 },
33a7e157
DC
490 {
491 text: gettext("Class"),
492 dataIndex: 'device_class',
493 align: 'right',
a3f146fc 494 width: 75
33a7e157 495 },
7d406f18
DC
496 {
497 text: "OSD Type",
498 dataIndex: 'osdtype',
499 align: 'right',
a3f146fc 500 width: 100
7d406f18
DC
501 },
502 {
503 text: "Bluestore Device",
504 dataIndex: 'blfsdev',
505 align: 'right',
a3f146fc 506 width: 75,
7d406f18
DC
507 hidden: true
508 },
509 {
510 text: "DB Device",
511 dataIndex: 'dbdev',
512 align: 'right',
a3f146fc 513 width: 75,
7d406f18
DC
514 hidden: true
515 },
516 {
517 text: "WAL Device",
518 dataIndex: 'waldev',
519 align: 'right',
3982a214 520 renderer: 'render_wal',
a3f146fc 521 width: 75,
7d406f18
DC
522 hidden: true
523 },
89cd5a3f
DC
524 {
525 text: 'Status',
526 dataIndex: 'status',
527 align: 'right',
3982a214 528 renderer: 'render_status',
a3f146fc 529 width: 120
89cd5a3f 530 },
e0297023
DC
531 {
532 text: gettext('Version'),
533 dataIndex: 'version',
a3f146fc 534 align: 'right',
3982a214 535 renderer: 'render_version'
e0297023 536 },
89cd5a3f
DC
537 {
538 text: 'weight',
539 dataIndex: 'crush_weight',
540 align: 'right',
a3368752 541 renderer: 'render_osd_weight',
a3f146fc 542 width: 90
89cd5a3f
DC
543 },
544 {
545 text: 'reweight',
546 dataIndex: 'reweight',
547 align: 'right',
a3368752 548 renderer: 'render_osd_weight',
89cd5a3f
DC
549 width: 90
550 },
551 {
cfb10313
TL
552 text: gettext('Used') + ' (%)',
553 dataIndex: 'percent_used',
554 align: 'right',
555 renderer: function(value, metaData, rec) {
556 if (rec.data.type !== 'osd') {
557 return '';
35c9c3d6 558 }
cfb10313
TL
559 return Ext.util.Format.number(value, '0.00');
560 },
561 width: 100
562 },
563 {
564 text: gettext('Total'),
565 dataIndex: 'total_space',
566 align: 'right',
567 renderer: 'render_osd_size',
568 width: 100
89cd5a3f
DC
569 },
570 {
a9e23b28
TL
571 text: 'Apply/Commit<br>Latency (ms)',
572 dataIndex: 'apply_latency_ms',
573 align: 'right',
574 renderer: 'render_osd_latency',
575 width: 120
89cd5a3f
DC
576 }
577 ],
4ea09218 578
4ea09218 579
3982a214
DC
580 tbar: {
581 items: [
582 {
583 text: gettext('Reload'),
584 iconCls: 'fa fa-refresh',
585 handler: 'reload'
586 },
a3f146fc 587 '-',
3982a214
DC
588 {
589 text: gettext('Create') + ': OSD',
590 handler: 'create_osd',
591 },
592 {
593 text: gettext('Set noout'),
594 itemId: 'nooutBtn',
595 handler: 'set_flag',
596 },
597 '->',
598 {
599 xtype: 'tbtext',
600 data: {
601 osd: undefined
4ea09218 602 },
3982a214
DC
603 bind: {
604 data: {
605 osd: "{osdid}"
e2924302 606 }
4ea09218 607 },
3982a214
DC
608 tpl: [
609 '<tpl if="osd">',
610 'osd.{osd}:',
611 '<tpl else>',
612 gettext('No OSD selected'),
613 '</tpl>'
614 ]
6f82e1b6 615 },
3982a214
DC
616 {
617 text: gettext('Start'),
618 iconCls: 'fa fa-play',
619 disabled: true,
620 bind: {
621 disabled: '{!downOsd}'
622 },
623 cmd: 'start',
624 handler: 'service_cmd'
625 },
626 {
627 text: gettext('Stop'),
628 iconCls: 'fa fa-stop',
629 disabled: true,
630 bind: {
631 disabled: '{!upOsd}'
632 },
633 cmd: 'stop',
634 handler: 'service_cmd'
635 },
636 {
637 text: gettext('Restart'),
638 iconCls: 'fa fa-refresh',
639 disabled: true,
640 bind: {
641 disabled: '{!upOsd}'
642 },
643 cmd: 'restart',
644 handler: 'service_cmd'
645 },
646 '-',
647 {
648 text: 'Out',
649 iconCls: 'fa fa-circle-o',
650 disabled: true,
651 bind: {
652 disabled: '{!inOsd}'
653 },
654 cmd: 'out',
655 handler: 'osd_cmd'
656 },
657 {
658 text: 'In',
659 iconCls: 'fa fa-circle',
660 disabled: true,
661 bind: {
662 disabled: '{!outOsd}'
663 },
664 cmd: 'in',
665 handler: 'osd_cmd'
666 },
667 '-',
668 {
3b0ae6b2 669 text: gettext('More'),
3982a214
DC
670 iconCls: 'fa fa-bars',
671 disabled: true,
672 bind: {
673 disabled: '{!isOsd}'
674 },
675 menu: [
676 {
677 text: gettext('Scrub'),
678 iconCls: 'fa fa-shower',
679 cmd: 'scrub',
680 handler: 'osd_cmd'
681 },
682 {
683 text: gettext('Deep Scrub'),
684 iconCls: 'fa fa-bath',
685 cmd: 'scrub',
686 params: {
687 deep: 1,
688 },
689 handler: 'osd_cmd'
690 },
691 {
692 text: gettext('Destroy'),
693 itemId: 'remove',
694 iconCls: 'fa fa-fw fa-trash-o',
695 bind: {
696 disabled: '{!downOsd}'
697 },
698 handler: 'destroy_osd'
699 }
700 ],
4ea09218 701 }
3982a214
DC
702 ]
703 },
704
705 fields: [
706 'name', 'type', 'status', 'host', 'in', 'id' ,
707 { type: 'number', name: 'reweight' },
708 { type: 'number', name: 'percent_used' },
709 { type: 'integer', name: 'bytes_used' },
710 { type: 'integer', name: 'total_space' },
711 { type: 'integer', name: 'apply_latency_ms' },
712 { type: 'integer', name: 'commit_latency_ms' },
713 { type: 'string', name: 'device_class' },
714 { type: 'string', name: 'osdtype' },
715 { type: 'string', name: 'blfsdev' },
716 { type: 'string', name: 'dbdev' },
717 { type: 'string', name: 'waldev' },
718 { type: 'string', name: 'version', calculate: function(data) {
719 return PVE.Utils.parse_ceph_version(data);
720 } },
721 { type: 'string', name: 'iconCls', calculate: function(data) {
722 var iconMap = {
723 host: 'fa-building',
724 osd: 'fa-hdd-o',
725 root: 'fa-server',
726 };
727 return 'fa x-fa-tree ' + iconMap[data.type];
728 } },
729 { type: 'number', name: 'crush_weight' }
730 ],
4ea09218 731});