public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Jakob Klocker <j.klocker@proxmox.com>
To: pve-devel@lists.proxmox.com
Cc: Jakob Klocker <j.klocker@proxmox.com>
Subject: [PATCH pve-manager 9/9] www: storage: display custom summary for failed plugins
Date: Fri, 31 Jul 2026 17:36:17 +0200	[thread overview]
Message-ID: <20260731153617.358265-10-j.klocker@proxmox.com> (raw)
In-Reply-To: <20260731153617.358265-1-j.klocker@proxmox.com>

Currently there is only a generic summary for storages, which doesn't
mention that a plugin failed to load.

Add a dedicated summary view for storages whose plugin failed to load.

Signed-off-by: Jakob Klocker <j.klocker@proxmox.com>
---
 www/manager6/Makefile               |   1 +
 www/manager6/storage/Browser.js     |  33 ++++++---
 www/manager6/storage/PluginError.js | 111 ++++++++++++++++++++++++++++
 3 files changed, 136 insertions(+), 9 deletions(-)
 create mode 100644 www/manager6/storage/PluginError.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index eb0e9d9c..7eb187e9 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -370,6 +370,7 @@ JSSRC= 							\
 	storage/BTRFSEdit.js				\
 	storage/NFSEdit.js				\
 	storage/PBSEdit.js				\
+	storage/PluginError.js				\
 	storage/RBDEdit.js				\
 	storage/StatusView.js				\
 	storage/Summary.js				\
diff --git a/www/manager6/storage/Browser.js b/www/manager6/storage/Browser.js
index d0237948..2e3cfb42 100644
--- a/www/manager6/storage/Browser.js
+++ b/www/manager6/storage/Browser.js
@@ -29,6 +29,30 @@ Ext.define('PVE.storage.Browser', {
         let plugin = res.plugintype;
 
         let isEsxi = plugin === 'esxi';
+        let pluginFailed = res.pluginstate === 'load-error';
+
+        Ext.apply(me, {
+            title: Ext.String.format(
+                gettext('Storage {0} on node {1}'),
+                `'${storeid}'`,
+                `'${nodename}'`,
+            ),
+            hstateid: 'storagetab',
+        });
+
+        if (pluginFailed) {
+            me.items = [
+                {
+                    xtype: 'pveStoragePluginError',
+                    title: gettext('Summary'),
+                    iconCls: 'fa fa-book',
+                    itemId: 'summary',
+                },
+            ];
+
+            me.callParent();
+            return;
+        }
 
         me.items = !isEsxi
             ? [
@@ -43,15 +67,6 @@ Ext.define('PVE.storage.Browser', {
 
         let caps = Ext.state.Manager.get('GuiCap');
 
-        Ext.apply(me, {
-            title: Ext.String.format(
-                gettext('Storage {0} on node {1}'),
-                `'${storeid}'`,
-                `'${nodename}'`,
-            ),
-            hstateid: 'storagetab',
-        });
-
         if (
             caps.storage['Datastore.Allocate'] ||
             caps.storage['Datastore.AllocateSpace'] ||
diff --git a/www/manager6/storage/PluginError.js b/www/manager6/storage/PluginError.js
new file mode 100644
index 00000000..a797631a
--- /dev/null
+++ b/www/manager6/storage/PluginError.js
@@ -0,0 +1,111 @@
+Ext.define('PVE.storage.PluginError', {
+    extend: 'Ext.panel.Panel',
+    alias: 'widget.pveStoragePluginError',
+
+    scrollable: true,
+    bodyPadding: 5,
+    layout: { type: 'column' },
+    defaults: { padding: 5, columnWidth: 1 },
+
+    initComponent: function () {
+        let me = this;
+
+        let nodename = me.pveSelNode.data.node;
+        if (!nodename) {
+            throw 'no node name specified';
+        }
+        let storage = me.pveSelNode.data.storage;
+        if (!storage) {
+            throw 'no storage ID specified';
+        }
+
+        let res = me.pveSelNode.data;
+        let type = res.plugintype || gettext('unknown');
+        let content = res.content || '-';
+
+        let rows = [
+            {
+                xtype: 'pmxInfoWidget',
+                itemId: 'enabled',
+                title: gettext('Enabled'),
+                printBar: false,
+            },
+            { xtype: 'pmxInfoWidget', itemId: 'active', title: gettext('Active'), printBar: false },
+            {
+                xtype: 'pmxInfoWidget',
+                itemId: 'content',
+                title: gettext('Content'),
+                printBar: false,
+            },
+            { xtype: 'pmxInfoWidget', itemId: 'type', title: gettext('Type'), printBar: false },
+            {
+                xtype: 'pmxInfoWidget',
+                itemId: 'external',
+                title: gettext('External'),
+                printBar: false,
+            },
+            {
+                xtype: 'pmxInfoWidget',
+                itemId: 'plugstatus',
+                title: gettext('Plugin Status'),
+                printBar: false,
+            },
+            {
+                xtype: 'pmxInfoWidget',
+                itemId: 'plugin-url',
+                title: gettext('Plugin URL'),
+                printBar: false,
+                hidden: true,
+            },
+        ];
+
+        let explanation = Ext.String.format(
+            gettext(
+                "The plugin for storage type '{0}' could not be loaded on node '{1}', " +
+                    'so live status and usage are unavailable. Install or update a compatible ' +
+                    'version of the plugin to restore access.',
+            ),
+            Ext.htmlEncode(type),
+            Ext.htmlEncode(nodename),
+        );
+
+        Ext.apply(me, {
+            items: [
+                {
+                    xtype: 'panel',
+                    title: gettext('Status'),
+                    layout: { type: 'vbox', align: 'stretch' },
+                    bodyPadding: 5,
+                    defaults: { padding: '2 25' },
+                    items: rows,
+                    listeners: {
+                        afterrender: function (panel) {
+                            panel.down('#enabled').updateValue(gettext('No'));
+                            panel.down('#active').updateValue(gettext('No'));
+                            panel
+                                .down('#content')
+                                .updateValue(PVE.Utils.format_content_types(content));
+                            panel.down('#type').updateValue(PVE.Utils.format_storage_type(type));
+                            panel.down('#external').updateValue(gettext('Yes'));
+                            panel.down('#plugstatus').updateValue(gettext('Error loading Plugin'));
+
+                            let url = res['plugin-url'];
+                            if (url) {
+                                let row = panel.down('#plugin-url');
+                                row.updateValue(PVE.Utils.render_plugin_url(url, res.plugintype));
+                                row.setHidden(false);
+                            }
+                        },
+                    },
+                },
+                {
+                    xtype: 'box',
+                    padding: 15,
+                    html: explanation,
+                },
+            ],
+        });
+
+        me.callParent();
+    },
+});
-- 
2.47.3




      parent reply	other threads:[~2026-07-31 15:37 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-31 15:36 [PATCH manager/storage 0/9] storage: plugins: display failed and outdated storage plugins in the GUI Jakob Klocker
2026-07-31 15:36 ` [PATCH pve-storage 1/9] storage: drop unused variable in storage_info Jakob Klocker
2026-07-31 15:36 ` [PATCH pve-storage 2/9] storage: add `plugin-url` to built-in plugins Jakob Klocker
2026-07-31 15:36 ` [PATCH pve-storage 3/9] storage: add `unknown` flag to parse_config Jakob Klocker
2026-07-31 15:36 ` [PATCH pve-storage 4/9] storage: plugins: cache and classify custom storage plugins Jakob Klocker
2026-07-31 15:36 ` [PATCH pve-storage 5/9] storage: expose plugin metadata in storage status Jakob Klocker
2026-07-31 15:36 ` [PATCH pve-manager 6/9] cluster: backend: include storages with unloadable plugins Jakob Klocker
2026-07-31 15:36 ` [PATCH pve-manager 7/9] www: storage: show plugin state/external/url in StatusView Jakob Klocker
2026-07-31 15:36 ` [PATCH pve-manager 8/9] www: storage: distinguish failed/outdated storage plugins in resource tree Jakob Klocker
2026-07-31 15:36 ` Jakob Klocker [this message]

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=20260731153617.358265-10-j.klocker@proxmox.com \
    --to=j.klocker@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
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal