[pve-devel] [PATCH manager 4/8] add dc health panel

Dominik Csapak d.csapak at proxmox.com
Fri Oct 28 13:11:44 CEST 2016


this adds a dc health panel which will be used in the cluster dashboard

it shows the overall cluster status (or simply ok if no cluster defined)
with a symbol and text

then it shows the number of online and offline nodes

optionally it shows then the overall ceph health
of the connected node

if the api call for ceph fails 3 times, we stop it
the ceph status is hidden by default

for updating the cluster and node status, we have to call
updateStatus as a callback from a store which
loads the /api2/json/cluster/status call

we do not have our own store for this, because we will be using the store
which handles this in the component above

Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
 www/manager6/Makefile     |   1 +
 www/manager6/dc/Health.js | 184 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 185 insertions(+)
 create mode 100644 www/manager6/dc/Health.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index a851264..d9ca435 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -188,6 +188,7 @@ JSSRC= 				                 	\
 	ha/Groups.js					\
 	ha/Fencing.js					\
 	dc/Summary.js					\
+	dc/Health.js					\
 	dc/OptionView.js				\
 	dc/StorageView.js				\
 	dc/UserEdit.js					\
diff --git a/www/manager6/dc/Health.js b/www/manager6/dc/Health.js
new file mode 100644
index 0000000..1215857
--- /dev/null
+++ b/www/manager6/dc/Health.js
@@ -0,0 +1,184 @@
+Ext.define('PVE.dc.Health', {
+    extend: 'Ext.panel.Panel',
+    alias: 'widget.pveDcHealth',
+
+    title: gettext('Datacenter Health'),
+
+    bodyPadding: '0 20 0 20',
+    height: 200,
+    layout: 'column',
+
+    defaults: {
+	columnWidth: 0.5,
+	xtype: 'box',
+	style: {
+	    'text-align':'center'
+	}
+    },
+
+    cepherrors: 0,
+
+    updateStatus: function(store, records, success) {
+	var me = this;
+	if (!success) {
+	    return;
+	}
+
+	var cluster = {
+	    iconCls:'good fa-check-circle',
+	    text: gettext("Standalone node - no cluster defined")
+	};
+
+	var nodes = {
+	    online: 0,
+	    offline: 0
+	};
+
+	// by default we have one node
+	var numNodes = 1;
+	var i;
+
+	for (i = 0; i < records.length; i++) {
+	    var item = records[i];
+	    if (item.data.type === 'node') {
+		nodes[item.data.online === 1 ? 'online':'offline']++;
+	    } else if(item.data.type === 'cluster') {
+		cluster.text = gettext("Cluster") + ": ";
+		cluster.text += item.data.name + ", ";
+		cluster.text += gettext("Quorate") + ": ";
+		cluster.text += PVE.Utils.format_boolean(item.data.quorate);
+		if (item.data.quorate != 1) {
+		    cluster.iconCls = 'critical fa-times-circle';
+		}
+
+		numNodes = item.data.nodes;
+	    }
+	}
+
+	if (numNodes !== (nodes.online + nodes.offline)) {
+	    nodes.offline = numNodes - nodes.online;
+	}
+
+	me.getComponent('clusterstatus').update(cluster);
+	me.getComponent('nodestatus').update(nodes);
+    },
+
+    updateCeph: function(store, records, success) {
+	var me = this;
+	var cephstatus = me.getComponent('ceph');
+	if (!success || records.length < 1) {
+	    me.cepherrors++;
+	    cephstatus.setVisible(false);
+
+	    // after 3 unsuccessful tries of
+	    // /nodes/localhost/ceph/status
+	    // we give up (there probably is no ceph installed)
+	    if (me.cepherrors >= 3) {
+		me.cephstore.stopUpdate();
+	    }
+	    return;
+	}
+
+	me.cepherrors = 0;
+
+	var cephstate = {
+	    iconCls: 'faded fa-question-circle',
+	    text: ''
+	};
+
+	switch (records[0].data.health.overall_status) {
+	    case 'HEALTH_OK':
+		cephstate.iconCls = 'good fa-check-circle';
+		break;
+	    case 'HEALTH_WARN':
+		cephstate.iconCls = 'warning fa-info-circle';
+		break;
+	    case 'HEALTH_ERR':
+		cephstate.iconCls = 'critical fa-times-circle';
+		break;
+	    default:
+		cephstate.iconCls = 'faded fa-question-circle';
+		break;
+	}
+	cephstate.text = records[0].data.health.overall_status;
+	cephstatus.update(cephstate);
+	cephstatus.setVisible(true);
+    },
+
+    listeners: {
+	destroy: function() {
+	    var me = this;
+	    me.cephstore.stopUpdate();
+	}
+    },
+
+    items: [
+	{
+	    itemId: 'clusterstatus',
+	    data: {
+		iconCls: 'faded fa-question-circle',
+		text: ''
+	    },
+	    tpl: [
+		'<h3>' + gettext('Status') + '</h3>',
+		'<i class="fa fa-5x {iconCls}"></i>',
+		'<br /><br/>',
+		'{text}'
+	    ]
+	},
+	{
+	    itemId: 'nodestatus',
+	    data: {
+		online: 0,
+		offline: 0
+	    },
+	    tpl: [
+		'<h3>' + gettext('Nodes') + '</h3><br />',
+		'<div style="width: 150px;margin: auto;font-size: 12pt">',
+		'<div class="left-aligned">',
+		'<i class="good fa fa-fw fa-check"> </i>',
+		gettext('Online'),
+		'</div>',
+		'<div class="right-aligned">{online}</div>',
+		'<br /><br />',
+		'<div class="left-aligned">',
+		'<i class="critical fa fa-fw fa-times"> </i>',
+		gettext('Offline'),
+		'</div>',
+		'<div class="right-aligned">{offline}</div>',
+		'</div>'
+	    ]
+	},
+	{
+	    itemId: 'ceph',
+	    width: 250,
+	    columnWidth: undefined,
+	    data: {
+		text: '',
+		iconCls: 'faded fa-question-circle'
+	    },
+	    tpl: [
+		'<h3>Ceph</h3>',
+		'<i class="fa fa-5x {iconCls}"></i><br /><br />',
+		gettext("Health") + ': {text}'
+	    ],
+	    hidden: true
+	}
+    ],
+
+    initComponent: function() {
+	var me = this;
+
+	me.cephstore = Ext.create('PVE.data.UpdateStore', {
+	    interval: 3000,
+	    storeid: 'pve-cluster-ceph',
+	    proxy: {
+		type: 'pve',
+		url: '/api2/json/nodes/localhost/ceph/status'
+	    }
+	});
+	me.callParent();
+	me.cephstore.startUpdate();
+	me.mon(me.cephstore, 'load', me.updateCeph, me);
+    }
+});
-- 
2.1.4





More information about the pve-devel mailing list