public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH manager v2 0/3] add ZFS over NVMe/TCP storage editor
@ 2026-08-02  3:35 Joaquin Varela
  2026-08-02  3:35 ` [PATCH manager v2 1/3] ui: " Joaquin Varela
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Joaquin Varela @ 2026-08-02  3:35 UTC (permalink / raw)
  To: pve-devel; +Cc: Joaquin Varela

Hi,

this is the UI companion series for the `zfsnvme` backend proposed in the
pve-storage series. It registers the new storage type and exposes ZFS,
NVMe/TCP, native multipath and DH-HMAC-CHAP settings.

Since the RFC, the editor gained the optional fast-I/O-fail policy and the
complete cluster Host NQN allow-list needed to reconstruct target ACLs before
publishing a restarted target.

The series passes `make check`; Biome checked 376 files. The exact branch is:

https://github.com/joaquinv98/pve-manager/tree/submission/zfs-nvme-tcp-rfc-v2

Joaquin Varela (3):
  ui: add ZFS over NVMe/TCP storage editor
  ui: expose NVMe fast I/O fail policy
  ui: configure zfsnvme host NQN allow-list

 www/manager6/Makefile               |   1 +
 www/manager6/Utils.js               |   6 +
 www/manager6/storage/ZFSNVMeEdit.js | 164 ++++++++++++++++++++++++++++
 3 files changed, 171 insertions(+)
 create mode 100644 www/manager6/storage/ZFSNVMeEdit.js

-- 
2.54.0.windows.1



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH manager v2 1/3] ui: add ZFS over NVMe/TCP storage editor
  2026-08-02  3:35 [PATCH manager v2 0/3] add ZFS over NVMe/TCP storage editor Joaquin Varela
@ 2026-08-02  3:35 ` Joaquin Varela
  2026-08-02  3:35 ` [PATCH manager v2 2/3] ui: expose NVMe fast I/O fail policy Joaquin Varela
  2026-08-02  3:35 ` [PATCH manager v2 3/3] ui: configure zfsnvme host NQN allow-list Joaquin Varela
  2 siblings, 0 replies; 4+ messages in thread
From: Joaquin Varela @ 2026-08-02  3:35 UTC (permalink / raw)
  To: pve-devel; +Cc: Joaquin Varela

Register the zfsnvme storage type and add an ExtJS editor for
its ZFS, NVMe/TCP, native multipath and DH-HMAC-CHAP properties.

Keep immutable target identity fields read-only after creation.
Expose portal-to-interface ordering so all cluster nodes use the
intended independent data paths.

Signed-off-by: Joaquin Varela <joaquinvarela@neatech.ar>
---
 www/manager6/Makefile               |   1 +
 www/manager6/Utils.js               |   6 ++
 www/manager6/storage/ZFSNVMeEdit.js | 148 ++++++++++++++++++++++++++++
 3 files changed, 155 insertions(+)
 create mode 100644 www/manager6/storage/ZFSNVMeEdit.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index eb0e9d9c..a93eb57b 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -375,6 +375,7 @@ JSSRC= 							\
 	storage/Summary.js				\
 	storage/TemplateView.js				\
 	storage/ZFSEdit.js				\
+	storage/ZFSNVMeEdit.js			\
 	storage/ZFSPoolEdit.js				\
 	storage/ESXIEdit.js				\
 	Workspace.js					\
diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 040b5ae0..82b9ecae 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -880,6 +880,12 @@ Ext.define('PVE.Utils', {
                 faIcon: 'building',
                 backups: false,
             },
+            zfsnvme: {
+                name: 'ZFS over NVMe/TCP',
+                ipanel: 'ZFSNVMeInputPanel',
+                faIcon: 'building',
+                backups: false,
+            },
             zfspool: {
                 name: 'ZFS',
                 ipanel: 'ZFSPoolInputPanel',
diff --git a/www/manager6/storage/ZFSNVMeEdit.js b/www/manager6/storage/ZFSNVMeEdit.js
new file mode 100644
index 00000000..db6e559f
--- /dev/null
+++ b/www/manager6/storage/ZFSNVMeEdit.js
@@ -0,0 +1,148 @@
+Ext.define('PVE.storage.ZFSNVMeInputPanel', {
+    extend: 'PVE.panel.StorageBase',
+
+    onlineHelp: 'storage_zfsnvme',
+
+    onGetValues: function (values) {
+        if (this.isCreate) {
+            values.content = 'images';
+        }
+        return this.callParent([values]);
+    },
+
+    initComponent: function () {
+        let me = this;
+
+        me.type = 'zfsnvme';
+
+        me.column1 = [
+            {
+                xtype: me.isCreate ? 'textfield' : 'displayfield',
+                name: 'server',
+                fieldLabel: gettext('SSH Server'),
+                allowBlank: false,
+            },
+            {
+                xtype: me.isCreate ? 'textfield' : 'displayfield',
+                name: 'pool',
+                fieldLabel: gettext('ZFS Pool'),
+                emptyText: 'tank/pve-nvme',
+                allowBlank: false,
+            },
+            {
+                xtype: me.isCreate ? 'textfield' : 'displayfield',
+                name: 'subsysnqn',
+                fieldLabel: gettext('Subsystem NQN'),
+                emptyText: 'nqn.2026-07.example:pve-storage',
+                allowBlank: false,
+            },
+            {
+                xtype: me.isCreate ? 'textfield' : 'displayfield',
+                name: 'blocksize',
+                value: '16k',
+                fieldLabel: gettext('Block Size'),
+                validator: PVE.Utils.validateZfsBlocksize,
+                allowBlank: false,
+            },
+            {
+                xtype: 'proxmoxcheckbox',
+                name: 'sparse',
+                checked: true,
+                uncheckedValue: 0,
+                fieldLabel: gettext('Thin provision'),
+            },
+        ];
+
+        me.column2 = [
+            {
+                xtype: me.isCreate ? 'textfield' : 'displayfield',
+                name: 'nvme-portals',
+                fieldLabel: gettext('NVMe/TCP Portals'),
+                emptyText: '10.90.1.11:4420,10.90.2.11:4420',
+                allowBlank: false,
+            },
+            {
+                xtype: 'textfield',
+                name: 'nvme-host-ifaces',
+                fieldLabel: gettext('Host Interfaces'),
+                emptyText: 'ens20,ens21',
+                allowBlank: false,
+            },
+            {
+                xtype: me.isCreate ? 'textfield' : 'displayfield',
+                inputType: me.isCreate ? 'password' : 'text',
+                name: 'dhchap-key',
+                value: me.isCreate ? '' : gettext('Configured'),
+                submitValue: me.isCreate,
+                fieldLabel: gettext('DHCHAP Key'),
+                allowBlank: !me.isCreate,
+            },
+            {
+                xtype: 'proxmoxKVComboBox',
+                name: 'nvme-iopolicy',
+                value: 'round-robin',
+                fieldLabel: gettext('I/O Policy'),
+                comboItems: [
+                    ['round-robin', 'round-robin'],
+                    ['queue-depth', 'queue-depth'],
+                    ['numa', 'numa'],
+                ],
+                allowBlank: false,
+            },
+        ];
+
+        me.advancedColumn1 = [
+            {
+                xtype: 'proxmoxintegerfield',
+                name: 'nvme-keep-alive-tmo',
+                value: 5,
+                minValue: 1,
+                maxValue: 120,
+                fieldLabel: gettext('Keep Alive Timeout'),
+                allowBlank: false,
+            },
+            {
+                xtype: 'proxmoxintegerfield',
+                name: 'nvme-reconnect-delay',
+                value: 2,
+                minValue: 1,
+                maxValue: 120,
+                fieldLabel: gettext('Reconnect Delay'),
+                allowBlank: false,
+            },
+        ];
+
+        me.advancedColumn2 = [
+            {
+                xtype: 'proxmoxintegerfield',
+                name: 'nvme-ctrl-loss-tmo',
+                value: 600,
+                minValue: -1,
+                maxValue: 86400,
+                fieldLabel: gettext('Controller Loss Timeout'),
+                allowBlank: false,
+            },
+            {
+                xtype: 'proxmoxintegerfield',
+                name: 'nvme-nr-io-queues',
+                minValue: 1,
+                maxValue: 1024,
+                fieldLabel: gettext('I/O Queues'),
+                deleteEmpty: !me.isCreate,
+                allowBlank: true,
+            },
+        ];
+
+        me.columnB = [
+            {
+                xtype: 'displayfield',
+                userCls: 'pmx-hint',
+                value: gettext(
+                    'Host interface names are matched to portals by position and must exist on every selected node.',
+                ),
+            },
+        ];
+
+        me.callParent();
+    },
+});
-- 
2.54.0.windows.1




^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH manager v2 2/3] ui: expose NVMe fast I/O fail policy
  2026-08-02  3:35 [PATCH manager v2 0/3] add ZFS over NVMe/TCP storage editor Joaquin Varela
  2026-08-02  3:35 ` [PATCH manager v2 1/3] ui: " Joaquin Varela
@ 2026-08-02  3:35 ` Joaquin Varela
  2026-08-02  3:35 ` [PATCH manager v2 3/3] ui: configure zfsnvme host NQN allow-list Joaquin Varela
  2 siblings, 0 replies; 4+ messages in thread
From: Joaquin Varela @ 2026-08-02  3:35 UTC (permalink / raw)
  To: pve-devel; +Cc: Joaquin Varela

Add the optional fast I/O fail timeout to the advanced zfsnvme
form. Explain that leaving it empty queues I/O until the
controller-loss timeout, so administrators select all-path
outage behavior deliberately.

Signed-off-by: Joaquin Varela <joaquinvarela@neatech.ar>
---
 www/manager6/storage/ZFSNVMeEdit.js | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/www/manager6/storage/ZFSNVMeEdit.js b/www/manager6/storage/ZFSNVMeEdit.js
index db6e559f..1d95c324 100644
--- a/www/manager6/storage/ZFSNVMeEdit.js
+++ b/www/manager6/storage/ZFSNVMeEdit.js
@@ -131,6 +131,15 @@ Ext.define('PVE.storage.ZFSNVMeInputPanel', {
                 deleteEmpty: !me.isCreate,
                 allowBlank: true,
             },
+            {
+                xtype: 'proxmoxintegerfield',
+                name: 'nvme-fast-io-fail-tmo',
+                minValue: 0,
+                maxValue: 86400,
+                fieldLabel: gettext('Fast I/O Fail Timeout'),
+                deleteEmpty: !me.isCreate,
+                allowBlank: true,
+            },
         ];
 
         me.columnB = [
@@ -138,7 +147,7 @@ Ext.define('PVE.storage.ZFSNVMeInputPanel', {
                 xtype: 'displayfield',
                 userCls: 'pmx-hint',
                 value: gettext(
-                    'Host interface names are matched to portals by position and must exist on every selected node.',
+                    'Host interface names are matched to portals by position and must exist on every selected node. Leave Fast I/O Fail Timeout empty to queue I/O until Controller Loss Timeout.',
                 ),
             },
         ];
-- 
2.54.0.windows.1




^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH manager v2 3/3] ui: configure zfsnvme host NQN allow-list
  2026-08-02  3:35 [PATCH manager v2 0/3] add ZFS over NVMe/TCP storage editor Joaquin Varela
  2026-08-02  3:35 ` [PATCH manager v2 1/3] ui: " Joaquin Varela
  2026-08-02  3:35 ` [PATCH manager v2 2/3] ui: expose NVMe fast I/O fail policy Joaquin Varela
@ 2026-08-02  3:35 ` Joaquin Varela
  2 siblings, 0 replies; 4+ messages in thread
From: Joaquin Varela @ 2026-08-02  3:35 UTC (permalink / raw)
  To: pve-devel; +Cc: Joaquin Varela

Expose the complete cluster Host NQN allow-list in the zfsnvme editor.
Explain that administrators must collect /etc/nvme/hostnqn from every node
allowed to activate the shared storage.

Signed-off-by: Joaquin Varela <joaquinvarela@neatech.ar>
---
 www/manager6/storage/ZFSNVMeEdit.js | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/www/manager6/storage/ZFSNVMeEdit.js b/www/manager6/storage/ZFSNVMeEdit.js
index 1d95c324..d5b66a1f 100644
--- a/www/manager6/storage/ZFSNVMeEdit.js
+++ b/www/manager6/storage/ZFSNVMeEdit.js
@@ -68,6 +68,13 @@ Ext.define('PVE.storage.ZFSNVMeInputPanel', {
                 emptyText: 'ens20,ens21',
                 allowBlank: false,
             },
+            {
+                xtype: 'textfield',
+                name: 'nvme-host-nqns',
+                fieldLabel: gettext('Allowed Host NQNs'),
+                emptyText: 'nqn.2014-08.org.nvmexpress:uuid:...',
+                allowBlank: false,
+            },
             {
                 xtype: me.isCreate ? 'textfield' : 'displayfield',
                 inputType: me.isCreate ? 'password' : 'text',
@@ -147,7 +154,7 @@ Ext.define('PVE.storage.ZFSNVMeInputPanel', {
                 xtype: 'displayfield',
                 userCls: 'pmx-hint',
                 value: gettext(
-                    'Host interface names are matched to portals by position and must exist on every selected node. Leave Fast I/O Fail Timeout empty to queue I/O until Controller Loss Timeout.',
+                    'List /etc/nvme/hostnqn from every allowed cluster node. Host interface names are matched to portals by position and must exist on every selected node. Leave Fast I/O Fail Timeout empty to queue I/O until Controller Loss Timeout.',
                 ),
             },
         ];
-- 
2.54.0.windows.1




^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-08-02  3:36 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-02  3:35 [PATCH manager v2 0/3] add ZFS over NVMe/TCP storage editor Joaquin Varela
2026-08-02  3:35 ` [PATCH manager v2 1/3] ui: " Joaquin Varela
2026-08-02  3:35 ` [PATCH manager v2 2/3] ui: expose NVMe fast I/O fail policy Joaquin Varela
2026-08-02  3:35 ` [PATCH manager v2 3/3] ui: configure zfsnvme host NQN allow-list Joaquin Varela

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