[pve-devel] [PATCH manager v2 1/5] dc: add simple cluster panel

Thomas Lamprecht t.lamprecht at proxmox.com
Wed Apr 4 14:36:43 CEST 2018


Show configured cluster nodes with their addresses, votes, IDs.
Also show cluster name, config_version, and node count.

Prepares for creating and joining a cluster over the WebUI.

Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
---

changes v1 -> v2:
* re-used an already defined gettext for "no cluster configured" (Dominik)
* removed commented out code (Dominik)
* use a diff store for the node grid to avoid flickering
* ensure that the updates stores stop refreshing once the view is destroyed,
  else we got a "leaky" store which continues to load even if we do not show
  this panel anymore.

 www/manager6/Makefile      |   1 +
 www/manager6/dc/Cluster.js | 200 +++++++++++++++++++++++++++++++++++++++++++++
 www/manager6/dc/Config.js  |  13 ++-
 3 files changed, 210 insertions(+), 4 deletions(-)
 create mode 100644 www/manager6/dc/Cluster.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index a01880f7..0796aa2c 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -193,6 +193,7 @@ JSSRC= 				                 	\
 	dc/SecurityGroups.js				\
 	dc/Config.js					\
 	dc/NodeView.js					\
+	dc/Cluster.js					\
 	Workspace.js
 
 lint: ${JSSRC}
diff --git a/www/manager6/dc/Cluster.js b/www/manager6/dc/Cluster.js
new file mode 100644
index 00000000..10e25bf0
--- /dev/null
+++ b/www/manager6/dc/Cluster.js
@@ -0,0 +1,200 @@
+/*jslint confusion: true*/
+Ext.define('pve-cluster-nodes', {
+    extend: 'Ext.data.Model',
+    fields: [
+	'node', { type: 'integer', name: 'nodeid' }, 'ring0_addr', 'ring1_addr',
+	{ type: 'integer', name: 'quorum_votes' }
+    ],
+    proxy: {
+        type: 'proxmox',
+	url: "/api2/json/cluster/config/nodes"
+    },
+    idProperty: 'nodeid'
+});
+
+Ext.define('pve-cluster-info', {
+    extend: 'Ext.data.Model',
+    proxy: {
+        type: 'proxmox',
+	url: "/api2/json/cluster/config/join"
+    }
+});
+
+Ext.define('PVE.ClusterAdministration', {
+    extend: 'Ext.panel.Panel',
+    xtype: 'pveClusterAdministration',
+
+    title: gettext('Cluster Administration'),
+
+    border: false,
+    defaults: { border: false },
+
+    viewModel: {
+	parent: null,
+	data: {
+	    totem: {},
+	    nodelist: [],
+	    preferred_node: {
+		name: '',
+		fp: '',
+		addr: ''
+	    },
+	    isInCluster: false,
+	    nodecount: 0
+	}
+    },
+
+    items: [
+	{
+	    xtype: 'panel',
+	    title: gettext('Cluster Information'),
+	    controller: {
+		xclass: 'Ext.app.ViewController',
+
+		init: function(view) {
+		    view.store = Ext.create('Proxmox.data.UpdateStore', {
+			autoStart: true,
+			interval: 15 * 1000,
+			storeid: 'pve-cluster-info',
+			model: 'pve-cluster-info'
+		    });
+		    view.store.on('load', this.onLoad, this);
+		    view.on('destroy', view.store.stopUpdate);
+		},
+
+		onLoad: function(store, records, success) {
+		    var vm = this.getViewModel();
+		    if (!success || !records || !records[0].data) {
+			vm.set('totem', {});
+			vm.set('isInCluster', false);
+			vm.set('nodelist', []);
+			vm.set('preferred_node', {
+			    name: '',
+			    addr: '',
+			    fp: ''
+			});
+			return;
+		    }
+		    var data = records[0].data;
+		    vm.set('totem', data.totem);
+		    vm.set('isInCluster', !!data.totem.cluster_name);
+		    vm.set('nodelist', data.nodelist);
+
+		    var nodeinfo = Ext.Array.findBy(data.nodelist, function (el) {
+			return el.name === data.preferred_node;
+		    });
+
+		    vm.set('preferred_node', {
+			name: data.preferred_node,
+			addr: nodeinfo.pve_addr,
+			fp: nodeinfo.pve_fp
+		    });
+		},
+	    },
+	    layout: 'hbox',
+	    bodyPadding: 5,
+	    items: [
+		{
+		    xtype: 'displayfield',
+		    fieldLabel: gettext('Cluster Name'),
+		    bind: {
+			value: '{totem.cluster_name}',
+			hidden: '{!isInCluster}'
+		    },
+		    flex: 1
+		},
+		{
+		    xtype: 'displayfield',
+		    fieldLabel: gettext('Config Version'),
+		    bind: {
+			value: '{totem.config_version}',
+			hidden: '{!isInCluster}'
+		    },
+		    flex: 1
+		},
+		{
+		    xtype: 'displayfield',
+		    fieldLabel: gettext('Number of Nodes'),
+		    labelWidth: 120,
+		    bind: {
+			value: '{nodecount}',
+			hidden: '{!isInCluster}'
+		    },
+		    flex: 1
+		},
+		{
+		    xtype: 'displayfield',
+		    value: gettext('Standalone node - no cluster defined'),
+		    bind: {
+			hidden: '{isInCluster}'
+		    },
+		    flex: 1
+		}
+	    ]
+	},
+	{
+	    xtype: 'grid',
+	    title: gettext('Cluster Nodes'),
+	    controller: {
+		xclass: 'Ext.app.ViewController',
+
+		init: function(view) {
+		    view.rstore = Ext.create('Proxmox.data.UpdateStore', {
+			autoLoad: true,
+			xtype: 'update',
+			interval: 5 * 1000,
+			autoStart: true,
+			storeid: 'pve-cluster-nodes',
+			model: 'pve-cluster-nodes'
+		    });
+		    view.setStore(Ext.create('Proxmox.data.DiffStore', {
+			rstore: view.rstore,
+			sorters: {
+			    property: 'nodeid',
+			    order: 'DESC'
+			}
+		    }));
+		    Proxmox.Utils.monStoreErrors(view, view.rstore);
+		    view.store.on('load', this.onLoad, this);
+		    view.on('destroy', view.rstore.stopUpdate);
+		},
+
+		onLoad: function(store, records, success) {
+		    var vm = this.getViewModel();
+		    if (!success || !records) {
+			vm.set('nodecount', 0);
+			return;
+		    }
+		    vm.set('nodecount', records.length);
+		}
+	    },
+	    columns: [
+		{
+		    header: gettext('Nodename'),
+		    flex: 2,
+		    dataIndex: 'name'
+		},
+		{
+		    header: gettext('ID'),
+		    flex: 1,
+		    dataIndex: 'nodeid'
+		},
+		{
+		    header: gettext('Votes'),
+		    flex: 1,
+		    dataIndex: 'quorum_votes'
+		},
+		{
+		    header: gettext('Ring 0'),
+		    flex: 2,
+		    dataIndex: 'ring0_addr'
+		},
+		{
+		    header: gettext('Ring 1'),
+		    flex: 2,
+		    dataIndex: 'ring1_addr'
+		}
+	    ]
+	}
+    ]
+});
diff --git a/www/manager6/dc/Config.js b/www/manager6/dc/Config.js
index 17d7a96a..e574f5db 100644
--- a/www/manager6/dc/Config.js
+++ b/www/manager6/dc/Config.js
@@ -22,13 +22,18 @@ Ext.define('PVE.dc.Config', {
 
 	if (caps.dc['Sys.Audit']) {
 	    me.items.push({
-	    title: gettext('Summary'),
+		title: gettext('Summary'),
 		xtype: 'pveDcSummary',
 		iconCls: 'fa fa-book',
 		itemId: 'summary'
-	    });
-
-	    me.items.push({
+	    },
+	    {
+		title: gettext('Cluster'),
+		xtype: 'pveClusterAdministration',
+		iconCls: 'fa fa-server',
+		itemId: 'cluster'
+	    },
+	    {
 		xtype: 'pveDcOptionView',
 		title: gettext('Options'),
 		iconCls: 'fa fa-gear',
-- 
2.14.2





More information about the pve-devel mailing list