pve-manager/www/manager6/dc/Summary.js
Dominik Csapak f734486b70 add subscription panel on dc summary
So that the users have a good and fast feedback about ther
support and subscripttion status, especially if they have
mistakenly different levels of susbscriptions in their cluster.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
2019-03-05 14:25:33 +01:00

271 lines
5.8 KiB
JavaScript

Ext.define('PVE.dc.Summary', {
extend: 'Ext.panel.Panel',
alias: 'widget.pveDcSummary',
scrollable: true,
bodyPadding: 5,
layout: 'column',
defaults: {
padding: 5,
plugins: 'responsive',
responsiveConfig: {
'width < 1900': {
columnWidth: 1
},
'width >= 1900': {
columnWidth: 0.5
}
}
},
items: [
{
itemId: 'dcHealth',
xtype: 'pveDcHealth'
},
{
itemId: 'dcGuests',
xtype: 'pveDcGuests'
},
{
title: gettext('Resources'),
xtype: 'panel',
minHeight: 250,
bodyPadding: 5,
layout: 'hbox',
defaults: {
xtype: 'proxmoxGauge',
flex: 1
},
items:[
{
title: gettext('CPU'),
itemId: 'cpu'
},
{
title: gettext('Memory'),
itemId: 'memory'
},
{
title: gettext('Storage'),
itemId: 'storage'
}
]
},
{
itemId: 'nodeview',
xtype: 'pveDcNodeView',
height: 250
},
{
title: gettext('Subscriptions'),
height: 220,
items: [
{
itemId: 'subscriptions',
xtype: 'pveHealthWidget'
}
]
}
],
initComponent: function() {
var me = this;
var rstore = Ext.create('Proxmox.data.UpdateStore', {
interval: 3000,
storeid: 'pve-cluster-status',
model: 'pve-dc-nodes',
proxy: {
type: 'proxmox',
url: "/api2/json/cluster/status"
}
});
var gridstore = Ext.create('Proxmox.data.DiffStore', {
rstore: rstore,
filters: {
property: 'type',
value: 'node'
},
sorters: {
property: 'id',
direction: 'ASC'
}
});
me.callParent();
me.getComponent('nodeview').setStore(gridstore);
var gueststatus = me.getComponent('dcGuests');
var cpustat = me.down('#cpu');
var memorystat = me.down('#memory');
var storagestat = me.down('#storage');
var sp = Ext.state.Manager.getProvider();
me.mon(PVE.data.ResourceStore, 'load', function(curstore, results) {
me.suspendLayout = true;
var cpu = 0;
var maxcpu = 0;
var nodes = 0;
var memory = 0;
var maxmem = 0;
var countedStorages = {};
var used = 0;
var total = 0;
var usableStorages = {};
var storages = sp.get('dash-storages') || '';
storages.split(',').forEach(function(storage){
if (storage !== '') {
usableStorages[storage] = true;
}
});
var qemu = {
running: 0,
paused: 0,
stopped: 0,
template: 0
};
var lxc = {
running: 0,
paused: 0,
stopped: 0,
template: 0
};
var error = 0;
var i;
for (i = 0; i < results.length; i++) {
var item = results[i];
switch(item.data.type) {
case 'node':
cpu += (item.data.cpu * item.data.maxcpu);
maxcpu += item.data.maxcpu || 0;
memory += item.data.mem || 0;
maxmem += item.data.maxmem || 0;
nodes++;
// update grid also
var griditem = gridstore.getById(item.data.id);
if (griditem) {
griditem.set('cpuusage', item.data.cpu);
var max = item.data.maxmem || 1;
var val = item.data.mem || 0;
griditem.set('memoryusage', val/max);
griditem.set('uptime', item.data.uptime);
griditem.commit(); //else it marks the fields as dirty
}
break;
case 'storage':
if (!Ext.Object.isEmpty(usableStorages)) {
if (usableStorages[item.data.id] === true) {
used += item.data.disk;
total += item.data.maxdisk;
}
break;
}
if (!countedStorages[item.data.storage] ||
(item.data.storage === 'local' &&
!countedStorages[item.data.id])) {
used += item.data.disk;
total += item.data.maxdisk;
countedStorages[item.data.storage === 'local'?item.data.id:item.data.storage] = true;
}
break;
case 'qemu':
qemu[item.data.template ? 'template' : item.data.status]++;
if (item.data.hastate === 'error') {
error++;
}
break;
case 'lxc':
lxc[item.data.template ? 'template' : item.data.status]++;
if (item.data.hastate === 'error') {
error++;
}
break;
default: break;
}
}
var text = Ext.String.format(gettext('of {0} CPU(s)'), maxcpu);
cpustat.updateValue((cpu/maxcpu), text);
text = Ext.String.format(gettext('{0} of {1}'), PVE.Utils.render_size(memory), PVE.Utils.render_size(maxmem));
memorystat.updateValue((memory/maxmem), text);
text = Ext.String.format(gettext('{0} of {1}'), PVE.Utils.render_size(used), PVE.Utils.render_size(total));
storagestat.updateValue((used/total), text);
gueststatus.updateValues(qemu,lxc,error);
me.suspendLayout = false;
me.updateLayout(true);
});
var dcHealth = me.getComponent('dcHealth');
me.mon(rstore, 'load', dcHealth.updateStatus, dcHealth);
var subs = me.down('#subscriptions');
me.mon(rstore, 'load', function(store, records, success) {
var i;
var level;
var curlevel;
for (i = 0; i < records.length; i++) {
if (records[i].get('type') !== 'node') {
continue;
}
curlevel = records[i].get('level');
if (level === undefined) {
level = curlevel;
continue;
}
if (level !== curlevel) {
break;
}
}
if (level === '') {
subs.setData({
title: gettext('No Subscription'),
iconCls: PVE.Utils.get_health_icon('critical', true),
text: gettext('You have at least one node without subscription.')
});
} else if (level !== curlevel) {
subs.setData({
title: gettext('Mixed Subscriptions'),
iconCls: PVE.Utils.get_health_icon('warning', true),
text: gettext('Warning: Your subscription levels are not the same.')
});
} else {
subs.setData({
title: PVE.Utils.render_support_level(level),
iconCls: PVE.Utils.get_health_icon('good', true),
text: gettext('Your subscription status is valid.')
});
}
});
me.on('destroy', function(){
rstore.stopUpdate();
});
rstore.startUpdate();
}
});