[pve-devel] [PATCH manager 2/2] gui: ceph osd: rewrite osd panel and add scrub button

Dominik Csapak d.csapak at proxmox.com
Wed Jul 10 15:13:52 CEST 2019


this rewrite of the osd panel converts it to a static declaration of
the layout with a controller/viewmodel logic

while doing this, add icons to buttons, and add a scrub/deep scrub entry

Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
i guess it would be easiest to review the result and not the diff,
since it is simply a big rewrite of the whole component..

 www/manager6/ceph/OSD.js | 789 +++++++++++++++++++++------------------
 1 file changed, 420 insertions(+), 369 deletions(-)

diff --git a/www/manager6/ceph/OSD.js b/www/manager6/ceph/OSD.js
index 31cd3ea3..b7c88475 100644
--- a/www/manager6/ceph/OSD.js
+++ b/www/manager6/ceph/OSD.js
@@ -167,8 +167,271 @@ Ext.define('PVE.node.CephOsdTree', {
     extend: 'Ext.tree.Panel',
     alias: ['widget.pveNodeCephOsdTree'],
     onlineHelp: 'chapter_pveceph',
+
+    viewModel: {
+	data: {
+	    nodename: '',
+	    flags: [],
+	    maxversion: '0',
+	    versions: {},
+	    isOsd: false,
+	    downOsd: false,
+	    upOsd: false,
+	    inOsd: false,
+	    outOsd: false,
+	    osdid: '',
+	    osdhost: '',
+	}
+    },
+
+    controller: {
+	xclass: 'Ext.app.ViewController',
+
+	reload: function() {
+	    var me = this.getView();
+	    var vm = this.getViewModel();
+	    var nodename = vm.get('nodename');
+	    var sm = me.getSelectionModel();
+	    Proxmox.Utils.API2Request({
+                url: "/nodes/" + nodename + "/ceph/osd",
+		waitMsgTarget: me,
+		method: 'GET',
+		failure: function(response, opts) {
+		    var msg = response.htmlStatus;
+		    PVE.Utils.showCephInstallOrMask(me, msg, nodename,
+			function(win){
+			    me.mon(win, 'cephInstallWindowClosed', this.reload);
+			}
+		    );
+		},
+		success: function(response, opts) {
+		    var data = response.result.data;
+		    var selected = me.getSelection();
+		    var name;
+		    if (selected.length) {
+			name = selected[0].data.name;
+		    }
+		    vm.set('versions', data.versions);
+		    // extract max version
+		    var maxversion = vm.get('maxversion');
+		    Object.values(data.versions || {}).forEach(function(version) {
+			if (PVE.Utils.compare_ceph_versions(version, maxversion) > 0) {
+			    maxversion = version;
+			}
+		    });
+		    vm.set('maxversion', maxversion);
+		    sm.deselectAll();
+		    me.setRootNode(data.root);
+		    me.expandAll();
+		    if (name) {
+			var node = me.getRootNode().findChild('name', name, true);
+			if (node) {
+			    me.setSelection([node]);
+			}
+		    }
+
+		    var flags = data.flags.split(',');
+		    vm.set('flags', flags);
+		    var noout = flags.includes('noout');
+		    me.down('#nooutBtn').setText(noout ? gettext("Unset noout") : gettext("Set noout"));
+		}
+	    });
+	},
+
+	osd_cmd: function(comp) {
+	    var me = this;
+	    var vm = this.getViewModel();
+	    var cmd = comp.cmd;
+	    var params = comp.params || {};
+	    var osdid = vm.get('osdid');
+
+	    var doRequest = function() {
+		Proxmox.Utils.API2Request({
+		    url: "/nodes/" + vm.get('osdhost') + "/ceph/osd/" + osdid + '/' + cmd,
+		    waitMsgTarget: me.getView(),
+		    method: 'POST',
+		    params: params,
+		    success: () => { me.reload(); },
+		    failure: function(response, opts) {
+			Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+		    }
+		});
+	    };
+
+	    if (cmd === 'scrub') {
+		Ext.MessageBox.defaultButton = params.deep === 1 ? 2 : 1;
+		Ext.Msg.show({
+		    title: gettext('Confirm'),
+		    icon: params.deep === 1 ? Ext.Msg.WARNING : Ext.Msg.QUESTION,
+		    msg: params.deep !== 1 ?
+		       Ext.String.format(gettext("Scrub OSD.{0}"), osdid) :
+		       Ext.String.format(gettext("Deep Scrub OSD.{0}"), osdid) +
+			   "<br>Caution: This can reduce performance while it is running.",
+		    buttons: Ext.Msg.YESNO,
+		    callback: function(btn) {
+			if (btn !== 'yes') {
+			    return;
+			}
+			doRequest();
+		    }
+		});
+	    } else {
+		doRequest();
+	    }
+	},
+
+	create_osd: function() {
+	    var me = this;
+	    var vm = this.getViewModel();
+	    Ext.create('PVE.CephCreateOsd', {
+		nodename: vm.get('nodename'),
+		taskDone: () => { me.reload(); }
+	    }).show();
+	},
+
+	destroy_osd: function() {
+	    var me = this;
+	    var vm = this.getViewModel();
+	    Ext.create('PVE.CephRemoveOsd', {
+		nodename: vm.get('osdhost'),
+		osdid: vm.get('osdid'),
+		taskDone: () => { me.reload(); }
+	    }).show();
+	},
+
+	set_flag: function() {
+	    var me = this;
+	    var vm = this.getViewModel();
+	    var flags = vm.get('flags');
+	    Proxmox.Utils.API2Request({
+		url: "/nodes/" + vm.get('nodename') + "/ceph/flags/noout",
+		waitMsgTarget: me.getView(),
+		method: flags.includes('noout') ? 'DELETE' : 'POST',
+		failure: function(response, opts) {
+		    Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+		},
+		success: () => { me.reload(); }
+	    });
+	},
+
+	service_cmd: function(comp) {
+	    var me = this;
+	    var vm = this.getViewModel();
+	    var cmd = comp.cmd || comp;
+	    Proxmox.Utils.API2Request({
+                url: "/nodes/" + vm.get('osdhost') + "/ceph/" + cmd,
+		params: { service: "osd." + vm.get('osdid') },
+		waitMsgTarget: me.getView(),
+		method: 'POST',
+		success: function(response, options) {
+		    var upid = response.result.data;
+		    var win = Ext.create('Proxmox.window.TaskProgress', {
+			upid: upid,
+			taskDone: () => { me.reload(); }
+		    });
+		    win.show();
+		},
+		failure: function(response, opts) {
+		    Ext.Msg.alert(gettext('Error'), response.htmlStatus);
+		}
+	    });
+	},
+
+	set_selection_status: function(tp, selection) {
+	    if (selection.length < 1) {
+		return;
+	    }
+	    var rec = selection[0];
+	    var vm = this.getViewModel();
+
+	    var isOsd = (rec.data.host && (rec.data.type === 'osd') && (rec.data.id >= 0));
+
+	    vm.set('isOsd', isOsd);
+	    vm.set('downOsd', isOsd && rec.data.status === 'down');
+	    vm.set('upOsd', isOsd && rec.data.status !== 'down');
+	    vm.set('inOsd', isOsd && rec.data.in);
+	    vm.set('outOsd', isOsd && !rec.data.in);
+	    vm.set('osdid', isOsd ? rec.data.id : undefined);
+	    vm.set('osdhost', isOsd ? rec.data.host : undefined);
+	    vm.notify();
+	},
+
+	render_status: function(value, metaData, rec) {
+	    if (!value) {
+		return value;
+	    }
+	    var inout = rec.data['in'] ? 'in' : 'out';
+	    var updownicon = value === 'up' ? 'good fa-arrow-circle-up' :
+		'critical fa-arrow-circle-down';
+
+	    var inouticon = rec.data['in'] ? 'good fa-circle' :
+		'warning fa-circle-o';
+
+	    var text = value + ' <i class="fa ' + updownicon + '"></i> / ' +
+		inout + ' <i class="fa ' + inouticon + '"></i>';
+
+	    return text;
+	},
+
+	render_wal: function(value, metaData, rec) {
+	    if (!value &&
+		rec.data.osdtype === 'bluestore' &&
+		rec.data.type === 'osd') {
+		return 'N/A';
+	    }
+	    return value;
+	},
+
+	render_version: function(value, metadata, rec) {
+	    var vm = this.getViewModel();
+	    var versions = vm.get('versions');
+	    var icon = "";
+	    var version = value || "";
+	    if (value && value != vm.get('maxversion')) {
+		icon = PVE.Utils.get_ceph_icon_html('HEALTH_OLD');
+	    }
+
+	    if (!value && rec.data.type == 'host') {
+		version = versions[rec.data.name] || Proxmox.Utils.unknownText;
+	    }
+
+	    return icon + version;
+	},
+
+	render_osd_val: function(value, metaData, rec) {
+	    return (rec.data.type === 'osd') ? value : '';
+	},
+
+	render_osd_size: function(value, metaData, rec) {
+	    return this.render_osd_val(PVE.Utils.render_size(value), metaData, rec);
+	},
+
+	control: {
+	    '#': {
+		selectionchange: 'set_selection_status'
+	    }
+	},
+
+	init: function(view) {
+	    var me = this;
+	    var vm = this.getViewModel();
+
+	    if (!view.pveSelNode.data.node) {
+		throw "no node name specified";
+	    }
+
+	    vm.set('nodename', view.pveSelNode.data.node);
+
+	    me.callParent();
+	    me.reload();
+	}
+    },
+
     stateful: true,
     stateId: 'grid-ceph-osd',
+    rootVisible: false,
+    useArrows: true,
+
     columns: [
 	{
 	    xtype: 'treecolumn',
@@ -212,14 +475,7 @@ Ext.define('PVE.node.CephOsdTree', {
 	    text: "WAL Device",
 	    dataIndex: 'waldev',
 	    align: 'right',
-	    renderer: function(value, metaData, rec) {
-		if (!value &&
-		    rec.data.osdtype === 'bluestore' &&
-		    rec.data.type === 'osd') {
-		    return 'N/A';
-		}
-		return value;
-	    },
+	    renderer: 'render_wal',
 	    width: 40,
 	    hidden: true
 	},
@@ -227,94 +483,34 @@ Ext.define('PVE.node.CephOsdTree', {
 	    text: 'Status',
 	    dataIndex: 'status',
 	    align: 'right',
-	    renderer: function(value, metaData, rec) {
-		if (!value) {
-		    return value;
-		}
-		var inout = rec.data['in'] ? 'in' : 'out';
-		var updownicon = value === 'up' ? 'good fa-arrow-circle-up' :
-						  'critical fa-arrow-circle-down';
-
-		var inouticon = rec.data['in'] ? 'good fa-circle' :
-						 'warning fa-circle-o';
-
-		var text = value + ' <i class="fa ' + updownicon + '"></i> / ' +
-			   inout + ' <i class="fa ' + inouticon + '"></i>';
-
-		return text;
-	    },
+	    renderer: 'render_status',
 	    width: 80
 	},
 	{
 	    text: gettext('Version'),
 	    dataIndex: 'version',
-	    renderer: function(value, metadata, rec) {
-		var me = this;
-		var icon = "";
-		var version = value || "";
-		if (value && value != me.maxversion) {
-		    icon = PVE.Utils.get_ceph_icon_html('HEALTH_OLD');
-		}
-
-		if (!value && rec.data.type == 'host') {
-		    version = me.versions[rec.data.name] || Proxmox.Utils.unknownText;
-		}
-
-		return icon + version;
-	    }
+	    renderer: 'render_version'
 	},
 	{
 	    text: 'weight',
 	    dataIndex: 'crush_weight',
 	    align: 'right',
-	    renderer: function(value, metaData, rec) {
-		if (rec.data.type !== 'osd') {
-		    return '';
-		}
-		return value;
-	    },
+	    renderer: 'render_osd_val',
 	    width: 80
 	},
 	{
 	    text: 'reweight',
 	    dataIndex: 'reweight',
 	    align: 'right',
-	    renderer: function(value, metaData, rec) {
-		if (rec.data.type !== 'osd') {
-		    return '';
-		}
-		return value;
-	    },
+	    renderer: 'render_osd_val',
 	    width: 90
 	},
 	{
-	    header: gettext('Used'),
-	    columns: [
-		{
-		    text: '%',
-		    dataIndex: 'percent_used',
-		    align: 'right',
-		    renderer: function(value, metaData, rec) {
-			if (rec.data.type !== 'osd') {
-			    return '';
-			}
-			return Ext.util.Format.number(value, '0.00');
-		    },
-		    width: 80
-		},
-		{
-		    text: gettext('Total'),
-		    dataIndex: 'total_space',
-		    align: 'right',
-		    renderer: function(value, metaData, rec) {
-			if (rec.data.type !== 'osd') {
-			    return '';
-			}
-			return PVE.Utils.render_size(value);
-		    },
-		    width: 100
-		}
-	    ]
+	    text: gettext('Total'),
+	    dataIndex: 'total_space',
+	    align: 'right',
+	    renderer: 'render_osd_size',
+	    width: 100
 	},
 	{
 	    header: gettext('Latency (ms)'),
@@ -323,314 +519,169 @@ Ext.define('PVE.node.CephOsdTree', {
 		    text: 'Apply',
 		    dataIndex: 'apply_latency_ms',
 		    align: 'right',
-		    renderer: function(value, metaData, rec) {
-			if (rec.data.type !== 'osd') {
-			    return '';
-			}
-			return value;
-		    },
+		    renderer: 'render_osd_val',
 		    width: 60
 		},
 		{
 		    text: 'Commit',
 		    dataIndex: 'commit_latency_ms',
 		    align: 'right',
-		    renderer: function(value, metaData, rec) {
-			if (rec.data.type !== 'osd') {
-			    return '';
-			}
-			return value;
-		    },
+		    renderer: 'render_osd_val',
 		    width: 60
 		}
 	    ]
 	}
     ],
-    initComponent: function() {
-	 /*jslint confusion: true */
-        var me = this;
-
-	// we expect noout to be not set by default
-	var noout = false;
-	me.maxversion = "0";
-
-	var nodename = me.pveSelNode.data.node;
-	if (!nodename) {
-	    throw "no node name specified";
-	}
-
-	var sm = Ext.create('Ext.selection.TreeModel', {});
 
-	var set_button_status; // defined later
 
-	var reload = function() {
-	    Proxmox.Utils.API2Request({
-                url: "/nodes/" + nodename + "/ceph/osd",
-		waitMsgTarget: me,
-		method: 'GET',
-		failure: function(response, opts) {
-		    var msg = response.htmlStatus;
-		    PVE.Utils.showCephInstallOrMask(me, msg, me.pveSelNode.data.node,
-			function(win){
-			    me.mon(win, 'cephInstallWindowClosed', function(){
-				reload();
-			    });
-			}
-		    );
+    tbar: {
+	items: [
+	    {
+		text: gettext('Reload'),
+		iconCls: 'fa fa-refresh',
+		handler: 'reload'
+	    },
+	    {
+		text: gettext('Create') + ': OSD',
+		handler: 'create_osd',
+	    },
+	    {
+		text: gettext('Set noout'),
+		itemId: 'nooutBtn',
+		handler: 'set_flag',
+	    },
+	    '->',
+	    {
+		xtype: 'tbtext',
+		data: {
+		    osd: undefined
 		},
-		success: function(response, opts) {
-		    var data = response.result.data;
-		    var selected = me.getSelection();
-		    var name;
-		    if (selected.length) {
-			name = selected[0].data.name;
-		    }
-		    sm.deselectAll();
-		    me.setRootNode(data.root);
-		    me.expandAll();
-		    if (name) {
-			var node = me.getRootNode().findChild('name', name, true);
-			if (node) {
-			    me.setSelection([node]);
-			}
+		bind: {
+		    data: {
+			osd: "{osdid}"
 		    }
-		    // extract noout flag
-		    if (data.flags && data.flags.search(/noout/) !== -1) {
-			noout = true;
-		    } else {
-			noout = false;
-		    }
-
-		    me.versions = data.versions;
-		    // extract max version
-		    Object.values(data.versions || {}).forEach(function(version) {
-			if (PVE.Utils.compare_ceph_versions(version, me.maxversion) > 0) {
-			    me.maxversion = version;
-			}
-		    });
-		    set_button_status();
-		}
-	    });
-	};
-
-	var osd_cmd = function(cmd) {
-	    var rec = sm.getSelection()[0];
-	    if (!(rec && (rec.data.id >= 0) && rec.data.host)) {
-		return;
-	    }
-	    Proxmox.Utils.API2Request({
-                url: "/nodes/" + rec.data.host + "/ceph/osd/" +
-		    rec.data.id + '/' + cmd,
-		waitMsgTarget: me,
-		method: 'POST',
-		success: reload,
-		failure: function(response, opts) {
-		    Ext.Msg.alert(gettext('Error'), response.htmlStatus);
-		}
-	    });
-	};
-
-	var service_cmd = function(cmd) {
-	    var rec = sm.getSelection()[0];
-	    if (!(rec && rec.data.name && rec.data.host)) {
-		return;
-	    }
-	    Proxmox.Utils.API2Request({
-                url: "/nodes/" + rec.data.host + "/ceph/" + cmd,
-		params: { service: rec.data.name },
-		waitMsgTarget: me,
-		method: 'POST',
-		success: function(response, options) {
-		    var upid = response.result.data;
-		    var win = Ext.create('Proxmox.window.TaskProgress', {
-			upid: upid,
-			taskDone: function() {
-			    reload();
-			}
-		    });
-		    win.show();
 		},
-		failure: function(response, opts) {
-		    Ext.Msg.alert(gettext('Error'), response.htmlStatus);
-		}
-	    });
-	};
-
-	var create_btn = new Proxmox.button.Button({
-	    text: gettext('Create') + ': OSD',
-	    handler: function() {
-		var rec = sm.getSelection()[0];
-
-		var win = Ext.create('PVE.CephCreateOsd', {
-                    nodename: nodename,
-		    taskDone: function(success) {
-			reload();
-		    }
-		});
-		win.show();
-	    }
-	});
-
-	var start_btn = new Ext.Button({
-	    text: gettext('Start'),
-	    disabled: true,
-	    handler: function(){ service_cmd('start'); }
-	});
-
-	var stop_btn = new Ext.Button({
-	    text: gettext('Stop'),
-	    disabled: true,
-	    handler: function(){ service_cmd('stop'); }
-	});
-
-	var restart_btn = new Ext.Button({
-	    text: gettext('Restart'),
-	    disabled: true,
-	    handler: function(){ service_cmd('restart'); }
-	});
-
-	var osd_out_btn = new Ext.Button({
-	    text: 'Out',
-	    disabled: true,
-	    handler: function(){ osd_cmd('out'); }
-	});
-
-	var osd_in_btn = new Ext.Button({
-	    text: 'In',
-	    disabled: true,
-	    handler: function(){ osd_cmd('in'); }
-	});
-
-	var remove_btn = new Ext.Button({
-	    text: gettext('Destroy'),
-	    disabled: true,
-	    handler: function(){
-		var rec = sm.getSelection()[0];
-		if (!(rec && (rec.data.id >= 0) && rec.data.host)) {
-		    return;
-		}
-
-		var win = Ext.create('PVE.CephRemoveOsd', {
-                    nodename: rec.data.host,
-		    osdid: rec.data.id,
-		    taskDone: function(success) {
-			reload();
-		    }
-		});
-		win.show();
-	    }
-	});
-
-	var noout_btn = new Ext.Button({
-	    text: gettext('Set noout'),
-	    handler: function() {
-		Proxmox.Utils.API2Request({
-		    url: "/nodes/" + nodename + "/ceph/flags/noout",
-		    waitMsgTarget: me,
-		    method: noout ? 'DELETE' : 'POST',
-		    failure: function(response, opts) {
-			Ext.Msg.alert(gettext('Error'), response.htmlStatus);
-		    },
-		    success: reload
-		});
-	    }
-	});
-
-	var osd_label = new Ext.toolbar.TextItem({
-	    data: {
-		osd: undefined
+		tpl: [
+		    '<tpl if="osd">',
+		    'osd.{osd}:',
+		    '<tpl else>',
+		    gettext('No OSD selected'),
+		    '</tpl>'
+		]
 	    },
-	    tpl: [
-		'<tpl if="osd">',
-		'{osd}:',
-		'<tpl else>',
-		gettext('No OSD selected'),
-		'</tpl>'
-	    ]
-	});
-
-	set_button_status = function() {
-	    var rec = sm.getSelection()[0];
-	    noout_btn.setText(noout?gettext('Unset noout'):gettext('Set noout'));
-
-	    if (!rec) {
-		start_btn.setDisabled(true);
-		stop_btn.setDisabled(true);
-		restart_btn.setDisabled(true);
-		remove_btn.setDisabled(true);
-		osd_out_btn.setDisabled(true);
-		osd_in_btn.setDisabled(true);
-		return;
-	    }
-
-	    var isOsd = (rec.data.host && (rec.data.type === 'osd') && (rec.data.id >= 0));
-
-	    start_btn.setDisabled(!(isOsd && (rec.data.status !== 'up')));
-	    stop_btn.setDisabled(!(isOsd && (rec.data.status !== 'down')));
-	    restart_btn.setDisabled(!(isOsd && (rec.data.status !== 'down')));
-	    remove_btn.setDisabled(!(isOsd && (rec.data.status === 'down')));
-
-	    osd_out_btn.setDisabled(!(isOsd && rec.data['in']));
-	    osd_in_btn.setDisabled(!(isOsd && !rec.data['in']));
-
-	    osd_label.update(isOsd?{osd:rec.data.name}:undefined);
-	};
-
-	sm.on('selectionchange', set_button_status);
-
-	var reload_btn = new Ext.Button({
-	    text: gettext('Reload'),
-	    handler: reload
-	});
-
-	Ext.apply(me, {
-	    tbar: [ create_btn, reload_btn, noout_btn, '->', osd_label, start_btn, stop_btn, restart_btn, osd_out_btn, osd_in_btn, remove_btn ],
-	    rootVisible: false,
-	    useArrows: true,
-	    fields: ['name', 'type', 'status', 'host', 'in', 'id' ,
-		     { type: 'number', name: 'reweight' },
-		     { type: 'number', name: 'percent_used' },
-		     { type: 'integer', name: 'bytes_used' },
-		     { type: 'integer', name: 'total_space' },
-		     { type: 'integer', name: 'apply_latency_ms' },
-		     { type: 'integer', name: 'commit_latency_ms' },
-		     { type: 'string', name: 'device_class' },
-		     { type: 'string', name: 'osdtype' },
-		     { type: 'string', name: 'blfsdev' },
-		     { type: 'string', name: 'dbdev' },
-		     { type: 'string', name: 'waldev' },
-		     { type: 'string', name: 'version', calculate: function(data) {
-			 return PVE.Utils.parse_ceph_version(data);
-		     } },
-		     { type: 'string', name: 'iconCls', calculate: function(data) {
-			 var iconCls = 'fa x-fa-tree fa-';
-			 switch (data.type) {
-			    case 'host':
-				 iconCls += 'building';
-				 break;
-			    case 'osd':
-				 iconCls += 'hdd-o';
-				 break;
-			    case 'root':
-				 iconCls += 'server';
-				 break;
-			    default:
-				 return undefined;
-			 }
-			 return iconCls;
-		     } },
-		     { type: 'number', name: 'crush_weight' }],
-	    selModel: sm,
-
-	    listeners: {
-		activate: function() {
-		    reload();
-		}
+	    {
+		text: gettext('Start'),
+		iconCls: 'fa fa-play',
+		disabled: true,
+		bind: {
+		    disabled: '{!downOsd}'
+		},
+		cmd: 'start',
+		handler: 'service_cmd'
+	    },
+	    {
+		text: gettext('Stop'),
+		iconCls: 'fa fa-stop',
+		disabled: true,
+		bind: {
+		    disabled: '{!upOsd}'
+		},
+		cmd: 'stop',
+		handler: 'service_cmd'
+	    },
+	    {
+		text: gettext('Restart'),
+		iconCls: 'fa fa-refresh',
+		disabled: true,
+		bind: {
+		    disabled: '{!upOsd}'
+		},
+		cmd: 'restart',
+		handler: 'service_cmd'
+	    },
+	    '-',
+	    {
+		text: 'Out',
+		iconCls: 'fa fa-circle-o',
+		disabled: true,
+		bind: {
+		    disabled: '{!inOsd}'
+		},
+		cmd: 'out',
+		handler: 'osd_cmd'
+	    },
+	    {
+		text: 'In',
+		iconCls: 'fa fa-circle',
+		disabled: true,
+		bind: {
+		    disabled: '{!outOsd}'
+		},
+		cmd: 'in',
+		handler: 'osd_cmd'
+	    },
+	    '-',
+	    {
+		text: gettext('Actions'),
+		iconCls: 'fa fa-bars',
+		disabled: true,
+		bind: {
+		    disabled: '{!isOsd}'
+		},
+		menu: [
+		    {
+			text: gettext('Scrub'),
+			iconCls: 'fa fa-shower',
+			cmd: 'scrub',
+			handler: 'osd_cmd'
+		    },
+		    {
+			text: gettext('Deep Scrub'),
+			iconCls: 'fa fa-bath',
+			cmd: 'scrub',
+			params: {
+			    deep: 1,
+			},
+			handler: 'osd_cmd'
+		    },
+		    {
+			text: gettext('Destroy'),
+			itemId: 'remove',
+			iconCls: 'fa fa-fw fa-trash-o',
+			bind: {
+			    disabled: '{!downOsd}'
+			},
+			handler: 'destroy_osd'
+		    }
+		],
 	    }
-	});
-
-	me.callParent();
-
-	reload();
-    }
+	]
+    },
+
+    fields: [
+	'name', 'type', 'status', 'host', 'in', 'id' ,
+	{ type: 'number', name: 'reweight' },
+	{ type: 'number', name: 'percent_used' },
+	{ type: 'integer', name: 'bytes_used' },
+	{ type: 'integer', name: 'total_space' },
+	{ type: 'integer', name: 'apply_latency_ms' },
+	{ type: 'integer', name: 'commit_latency_ms' },
+	{ type: 'string', name: 'device_class' },
+	{ type: 'string', name: 'osdtype' },
+	{ type: 'string', name: 'blfsdev' },
+	{ type: 'string', name: 'dbdev' },
+	{ type: 'string', name: 'waldev' },
+	{ type: 'string', name: 'version', calculate: function(data) {
+	    return PVE.Utils.parse_ceph_version(data);
+	} },
+	{ type: 'string', name: 'iconCls', calculate: function(data) {
+	    var iconMap = {
+		host: 'fa-building',
+		osd: 'fa-hdd-o',
+		root: 'fa-server',
+	    };
+	    return 'fa x-fa-tree ' + iconMap[data.type];
+	} },
+	{ type: 'number', name: 'crush_weight' }
+    ],
 });
-- 
2.20.1





More information about the pve-devel mailing list