]> git.proxmox.com Git - pve-manager.git/commitdiff
add dc health panel
authorDominik Csapak <d.csapak@proxmox.com>
Fri, 28 Oct 2016 11:11:44 +0000 (13:11 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Sat, 29 Oct 2016 06:38:18 +0000 (08:38 +0200)
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@proxmox.com>
www/manager6/Makefile
www/manager6/dc/Health.js [new file with mode: 0644]

index a851264a486da45d1a59b5ad62c52b5c15a8c953..d9ca43521c9129e1345067fc280ab76ebe1e23a6 100644 (file)
@@ -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 (file)
index 0000000..1215857
--- /dev/null
@@ -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">&nbsp;</i>',
+               gettext('Online'),
+               '</div>',
+               '<div class="right-aligned">{online}</div>',
+               '<br /><br />',
+               '<div class="left-aligned">',
+               '<i class="critical fa fa-fw fa-times">&nbsp;</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);
+    }
+});