mirror of
https://git.proxmox.com/git/pve-manager
synced 2025-08-07 08:16:25 +00:00
dc: add simple cluster panel
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@proxmox.com>
This commit is contained in:
parent
f28ec3e4b3
commit
2f13e1d201
@ -193,6 +193,7 @@ JSSRC= \
|
|||||||
dc/SecurityGroups.js \
|
dc/SecurityGroups.js \
|
||||||
dc/Config.js \
|
dc/Config.js \
|
||||||
dc/NodeView.js \
|
dc/NodeView.js \
|
||||||
|
dc/Cluster.js \
|
||||||
Workspace.js
|
Workspace.js
|
||||||
|
|
||||||
lint: ${JSSRC}
|
lint: ${JSSRC}
|
||||||
|
200
www/manager6/dc/Cluster.js
Normal file
200
www/manager6/dc/Cluster.js
Normal file
@ -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'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
@ -22,13 +22,18 @@ Ext.define('PVE.dc.Config', {
|
|||||||
|
|
||||||
if (caps.dc['Sys.Audit']) {
|
if (caps.dc['Sys.Audit']) {
|
||||||
me.items.push({
|
me.items.push({
|
||||||
title: gettext('Summary'),
|
title: gettext('Summary'),
|
||||||
xtype: 'pveDcSummary',
|
xtype: 'pveDcSummary',
|
||||||
iconCls: 'fa fa-book',
|
iconCls: 'fa fa-book',
|
||||||
itemId: 'summary'
|
itemId: 'summary'
|
||||||
});
|
},
|
||||||
|
{
|
||||||
me.items.push({
|
title: gettext('Cluster'),
|
||||||
|
xtype: 'pveClusterAdministration',
|
||||||
|
iconCls: 'fa fa-server',
|
||||||
|
itemId: 'cluster'
|
||||||
|
},
|
||||||
|
{
|
||||||
xtype: 'pveDcOptionView',
|
xtype: 'pveDcOptionView',
|
||||||
title: gettext('Options'),
|
title: gettext('Options'),
|
||||||
iconCls: 'fa fa-gear',
|
iconCls: 'fa fa-gear',
|
||||||
|
Loading…
Reference in New Issue
Block a user