From: Luca Vornheder <luca@vornheder.cloud>
To: pve-devel@lists.proxmox.com
Cc: Luca Vornheder <luca@vornheder.cloud>
Subject: [PATCH manager 2/3] fix #7656: ui: node: add opt-in IPMI SEL log tab
Date: Fri, 18 Sep 2026 18:45:08 +0200 [thread overview]
Message-ID: <20260918164509.46468-3-luca@vornheder.cloud> (raw)
In-Reply-To: <20260918164509.46468-1-luca@vornheder.cloud>
Add an 'IPMI' tab next to the system log of a node, listing the entries
of the node's IPMI System Event Log, with a reload and an export
button.
The tab is enabled per node through a new 'IPMI SEL Log' row in the
node options. Its edit window notes that this is a technology preview
and that 'ipmitool' needs to be installed. While the feature is
disabled, the tab shows a hint instead of an error.
Signed-off-by: Luca Vornheder <luca@vornheder.cloud>
---
www/manager6/Makefile | 1 +
www/manager6/node/Config.js | 9 ++
www/manager6/node/IPMI.js | 134 +++++++++++++++++++++++++++
www/manager6/node/NodeOptionsView.js | 31 +++++++
4 files changed, 175 insertions(+)
create mode 100644 www/manager6/node/IPMI.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index d2ea786..d83fa20 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -244,6 +244,7 @@ JSSRC= \
node/CmdMenu.js \
node/Config.js \
node/Directory.js \
+ node/IPMI.js \
node/LVM.js \
node/LVMThin.js \
node/StatusView.js \
diff --git a/www/manager6/node/Config.js b/www/manager6/node/Config.js
index 217ee28..ee8277e 100644
--- a/www/manager6/node/Config.js
+++ b/www/manager6/node/Config.js
@@ -257,6 +257,15 @@ Ext.define('PVE.node.Config', {
url: '/api2/extjs/nodes/' + nodename + '/journal',
});
+ me.items.push({
+ xtype: 'pveNodeIPMIView',
+ title: gettext('IPMI'),
+ iconCls: 'fa fa-server',
+ groups: ['services'],
+ itemId: 'ipmi-sel',
+ nodename: nodename,
+ });
+
if (caps.nodes['Sys.Modify']) {
me.items.push({
xtype: 'proxmoxNodeAPT',
diff --git a/www/manager6/node/IPMI.js b/www/manager6/node/IPMI.js
new file mode 100644
index 0000000..48228ae
--- /dev/null
+++ b/www/manager6/node/IPMI.js
@@ -0,0 +1,134 @@
+Ext.define('PVE.node.IPMIView', {
+ extend: 'Ext.grid.Panel',
+ alias: 'widget.pveNodeIPMIView',
+
+ onlineHelp: 'proxmox_node_management',
+
+ stateful: true,
+ stateId: 'grid-node-ipmi-sel',
+
+ // we drive all loading/error/disabled feedback ourselves via emptyText and
+ // setErrorMask below, so the grid's own spinner must stay out of the way
+ loadMask: false,
+
+ viewConfig: {
+ loadMask: false,
+ emptyText: gettext('No entries found'),
+ deferEmptyText: false,
+ },
+
+ columns: [
+ {
+ header: gettext('ID'),
+ dataIndex: 'id',
+ width: 60,
+ },
+ {
+ header: gettext('Timestamp'),
+ dataIndex: 'timestamp',
+ width: 160,
+ },
+ {
+ header: gettext('Sensor'),
+ dataIndex: 'sensor',
+ width: 200,
+ },
+ {
+ header: gettext('Event'),
+ dataIndex: 'description',
+ flex: 1,
+ },
+ {
+ header: gettext('Direction'),
+ dataIndex: 'direction',
+ width: 100,
+ },
+ ],
+
+ tbar: [
+ {
+ text: gettext('Reload'),
+ iconCls: 'fa fa-refresh',
+ handler: function () {
+ this.up('grid').reload();
+ },
+ },
+ {
+ itemId: 'exportBtn',
+ text: gettext('Export'),
+ iconCls: 'fa fa-download',
+ disabled: true,
+ handler: function () {
+ let me = this.up('grid');
+ Proxmox.Utils.downloadAsFile(
+ `/api2/json/nodes/${me.nodename}/ipmi-sel?download=1`,
+ );
+ },
+ },
+ ],
+
+ reload: function () {
+ let me = this;
+ me.getStore().load();
+ },
+
+ listeners: {
+ activate: function () {
+ this.reload();
+ },
+ },
+
+ initComponent: function () {
+ let me = this;
+
+ me.nodename = me.pveSelNode.data.node;
+ if (!me.nodename) {
+ throw 'no node name specified';
+ }
+
+ Ext.apply(me, {
+ store: {
+ fields: ['id', 'timestamp', 'sensor', 'description', 'direction'],
+ proxy: {
+ type: 'proxmox',
+ url: `/api2/json/nodes/${me.nodename}/ipmi-sel`,
+ },
+ },
+ });
+
+ me.callParent();
+
+ let store = me.getStore();
+ let view = me.getView();
+ let exportBtn = me.down('#exportBtn');
+
+ me.mon(store, 'beforeload', () => Proxmox.Utils.setErrorMask(me, false));
+
+ // only works with the 'proxmox' proxy
+ me.mon(store.proxy, 'afterload', (proxy, request, success) => {
+ if (success) {
+ Proxmox.Utils.setErrorMask(me, false);
+ exportBtn.setDisabled(false);
+ return;
+ }
+
+ exportBtn.setDisabled(true);
+
+ let error = request._operation.getError();
+
+ if (error && error.status === 501) {
+ // feature disabled for this node -- not an error, just say so
+ view.emptyText = Ext.htmlEncode(
+ gettext(
+ "IPMI SEL log is not enabled for this node. Enable it in the" +
+ " node's 'Options' tab first.",
+ ),
+ );
+ view.refresh();
+ return;
+ }
+
+ Proxmox.Utils.setErrorMask(me, Proxmox.Utils.getResponseErrorMessage(error));
+ });
+ },
+});
diff --git a/www/manager6/node/NodeOptionsView.js b/www/manager6/node/NodeOptionsView.js
index 5e9ce79..98fdb70 100644
--- a/www/manager6/node/NodeOptionsView.js
+++ b/www/manager6/node/NodeOptionsView.js
@@ -55,6 +55,37 @@ Ext.define('Proxmox.node.NodeOptionsView', {
xtype: 'pmxLocationEditWindow',
},
},
+ 'ipmi-sel': {
+ required: true,
+ defaultValue: 0,
+ header: gettext('IPMI SEL Log'),
+ renderer: Proxmox.Utils.format_boolean,
+ editor: {
+ xtype: 'proxmoxWindowEdit',
+ subject: gettext('IPMI SEL Log'),
+ fieldDefaults: {
+ labelWidth: 130,
+ },
+ items: [
+ {
+ xtype: 'displayfield',
+ userCls: 'pmx-hint',
+ value: gettext(
+ "Technology preview. Requires 'ipmitool' to be installed on" +
+ ' this node.',
+ ),
+ },
+ {
+ xtype: 'proxmoxcheckbox',
+ name: 'ipmi-sel',
+ uncheckedValue: 0,
+ defaultValue: 0,
+ checked: false,
+ fieldLabel: gettext('IPMI SEL Log'),
+ },
+ ],
+ },
+ },
},
gridRows: [
--
2.50.1 (Apple Git-155)
next prev parent reply other threads:[~2026-09-21 7:55 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-18 16:45 [PATCH manager 0/3] add opt-in IPMI SEL log tab for nodes Luca Vornheder
2026-09-18 16:45 ` [PATCH manager 1/3] api: nodes: add opt-in endpoint to read the local IPMI SEL Luca Vornheder
2026-09-18 16:45 ` Luca Vornheder [this message]
2026-09-18 16:45 ` [PATCH manager 3/3] d/control: recommend ipmitool Luca Vornheder
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=20260918164509.46468-3-luca@vornheder.cloud \
--to=luca@vornheder.cloud \
--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