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

Dominik Csapak d.csapak at proxmox.com
Thu Apr 5 11:27:52 CEST 2018


the only thing not working is the 'nodecount' since the diffstore has no 
'load' event, thus the update never triggers

but we can fix this in a followup by adding the event to the rstore 
instead, rest of the series acked by me

On 04/04/2018 02:36 PM, Thomas Lamprecht wrote:
> 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',
> 





More information about the pve-devel mailing list