From: David Riley <d.riley@proxmox.com>
To: Erik Fastermann <e.fastermann@proxmox.com>, pve-devel@lists.proxmox.com
Subject: Re: [PATCH pve-manager] fix #7794: ui: dc summary: add per-node VM/CT count columns
Date: Mon, 27 Jul 2026 14:49:07 +0200 [thread overview]
Message-ID: <3772ea7c-b974-4b07-891d-681b749dfb96@proxmox.com> (raw)
In-Reply-To: <20260724113506.150278-1-e.fastermann@proxmox.com>
Thanks for sending in this patch, this looks like a nice addition.
some comments inline.
On 7/24/26 1:34 PM, Erik Fastermann wrote:
> The datacenter summary aggregates VM and CT counts cluster-wide but
> gives no per-node breakdown. Add columns to the node list showing the
> number of running and total VMs and CTs per node, so the workload
> distribution across the cluster is visible at a glance.
>
> The running columns are shown by default, the totals are hidden and can
> be enabled per profile. Templates are excluded from the totals, matching
> the guest status panel that accounts for them separately.
>
> Combined guest columns (VMs plus CTs) were suggested but left out on
> purpose, as one does not gain a lot of information from them and to
> avoid column clutter.
>
> Signed-off-by: Erik Fastermann<e.fastermann@proxmox.com>
> ---
> www/manager6/dc/NodeView.js | 26 ++++++++++++++++++++++++
> www/manager6/dc/Summary.js | 40 +++++++++++++++++++++++++++++++++++++
> 2 files changed, 66 insertions(+)
>
> diff --git a/www/manager6/dc/NodeView.js b/www/manager6/dc/NodeView.js
> index 2c9574fb..4ea76bb7 100644
> --- a/www/manager6/dc/NodeView.js
> +++ b/www/manager6/dc/NodeView.js
> @@ -68,6 +68,32 @@ Ext.define(
> criticalThreshold: 0.975,
> },
> },
> + {
> + header: gettext('VMs (running)'),
> + width: 100,
> + sortable: true,
> + dataIndex: 'qemurunning',
> + },
> + {
> + header: gettext('VMs (total)'),
> + width: 100,
> + sortable: true,
> + dataIndex: 'qemutotal',
> + hidden: true,
> + },
> + {
> + header: gettext('CTs (running)'),
> + width: 100,
> + sortable: true,
> + dataIndex: 'lxcrunning',
> + },
> + {
> + header: gettext('CTs (total)'),
> + width: 100,
> + sortable: true,
> + dataIndex: 'lxctotal',
> + hidden: true,
> + },
> {
> header: gettext('Uptime'),
> sortable: true,
> diff --git a/www/manager6/dc/Summary.js b/www/manager6/dc/Summary.js
> index bf7e99c6..a27dfa3a 100644
> --- a/www/manager6/dc/Summary.js
> +++ b/www/manager6/dc/Summary.js
> @@ -146,12 +146,16 @@ Ext.define('PVE.dc.Summary', {
> stopped: 0,
> template: 0,
> };
> + const qemuPerNodeRunning = {};
> + const qemuPerNodeTotal = {};
> let lxc = {
> running: 0,
> paused: 0,
> stopped: 0,
> template: 0,
> };
> + const lxcPerNodeRunning = {};
> + const lxcPerNodeTotal = {};
> let error = 0;
>
> for (const { data } of results) {
> @@ -194,12 +198,36 @@ Ext.define('PVE.dc.Summary', {
> }
> case 'qemu':
> qemu[data.template ? 'template' : data.status]++;
> +
> + if (!(data.node in qemuPerNodeTotal)) {
> + qemuPerNodeRunning[data.node] = 0;
> + qemuPerNodeTotal[data.node] = 0;
> + }
> + if (data.status === 'running') {
> + qemuPerNodeRunning[data.node] += 1;
> + }
> + if (!data.template) {
> + qemuPerNodeTotal[data.node] += 1;
> + }
> +
> if (data.hastate === 'error') {
> error++;
> }
> break;
> case 'lxc':
> lxc[data.template ? 'template' : data.status]++;
> +
> + if (!(data.node in lxcPerNodeTotal)) {
> + lxcPerNodeRunning[data.node] = 0;
> + lxcPerNodeTotal[data.node] = 0;
> + }
> + if (data.status === 'running') {
> + lxcPerNodeRunning[data.node] += 1;
> + }
> + if (!data.template) {
> + lxcPerNodeTotal[data.node] += 1;
> + }
> +
> if (data.hastate === 'error') {
> error++;
> }
> @@ -228,6 +256,18 @@ Ext.define('PVE.dc.Summary', {
>
> gueststatus.updateValues(qemu, lxc, error);
>
> + gridstore.each((item) => {
> + const node = item.getId().replace(/^node\//, '');
> +
> + item.set('qemurunning', qemuPerNodeRunning[node] ?? 0);
> + item.set('qemutotal', qemuPerNodeTotal[node] ?? 0);
> +
> + item.set('lxcrunning', lxcPerNodeRunning[node] ?? 0);
> + item.set('lxctotal', lxcPerNodeTotal[node] ?? 0);
> +
> + item.commit();
> + });
nit: This could benefit from 'item.beginEdit()' [0] and 'endEdit()' [1] as well as passing
an object to 'item.set()' [2] to avoid firing multiple field update events per record.
item.beginEdit();
item.set({
qemurunning: qemuPerNodeRunning[node] ?? 0,
qemutotal: qemuPerNodeTotal[node] ?? 0,
lxcrunning: lxcPerNodeRunning[node] ?? 0,
lxctotal: lxcPerNodeTotal[node] ?? 0,
});
item.commit();
item.endEdit();
Wrapping the loop with 'gridstore.beginUpdate()' [3] and 'gridstore.endUpdate()' [4]
would also prevent the store from triggering grid redraws on every iteration.
No hard feelings on this, though.
[0] https://docs.sencha.com/extjs/7.0.0/classic/Ext.data.Model.html#method-beginEdit
[1] https://docs.sencha.com/extjs/7.0.0/classic/Ext.data.Model.html#method-endEdit
[2] https://docs.sencha.com/extjs/7.0.0/classic/Ext.data.Model.html#method-set
[3] https://docs.sencha.com/extjs/7.0.0/classic/Ext.data.Store.html#method-beginUpdate
[4] https://docs.sencha.com/extjs/7.0.0/classic/Ext.data.Store.html#method-endUpdate
> +
> me.suspendLayout = false;
> me.updateLayout(true);
> });
next prev parent reply other threads:[~2026-07-27 12:49 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-24 11:35 [PATCH pve-manager] fix #7794: ui: dc summary: add per-node VM/CT count columns Erik Fastermann
2026-07-27 12:49 ` David Riley [this message]
2026-07-28 7:56 ` superseded: " Erik Fastermann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3772ea7c-b974-4b07-891d-681b749dfb96@proxmox.com \
--to=d.riley@proxmox.com \
--cc=e.fastermann@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox