public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH pve-manager/pve-storage 0/4] extend iscsi configuration
       [not found] <f53ca227-2275-443f-84f8-48b2785269b2.2bc2ceb6-a3a3-4c49-9566-519c7d2ab20e.21103ee5-34fe-43b6-b130-08f8ab2b25ae@emailsignatures365.codetwo.com>
@ 2026-03-27 10:14 ` Felix Driessler
       [not found]   ` <f53ca227-2275-443f-84f8-48b2785269b2.2bc2ceb6-a3a3-4c49-9566-519c7d2ab20e.d935a384-10c1-4974-ba2a-7adab51bb127@emailsignatures365.codetwo.com>
                     ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Felix Driessler @ 2026-03-27 10:14 UTC (permalink / raw)
  To: pve-devel

This patch series adds a WWID field and CHAP Authentication boxes for iScsi.

pve-manager:

The WWID field is added to:
 - storage view
 - file selector

The WWID field is made to be only visible if a iScsi Storage is being viewed.

For CHAP authentication a checkbox as well as username/password field are added, 
to allow for togglin CHAP authentication on/off.

pve-storage:

Adds wwid return value to iscsi_device_list to make volumes of a iScsi Storage
easier to identify

Adds required functions to allow the configuration of CHAP through the proxmox web ui.

Felix Driessler (4):
  ui: Add Display of iScsi WWID
  ui: Add iScsi Chap Auth
  iscsiPlugin: add WWID
  iscsiPlugin: add chap auth

pve-manager:
 www/manager6/Utils.js               |  8 +++
 www/manager6/form/FileSelector.js   | 81 +++++++++++++++++++++--------
 www/manager6/storage/ContentView.js | 24 ++++++++-
 www/manager6/storage/IScsiEdit.js   | 43 +++++++++++++++
 4 files changed, 132 insertions(+), 24 deletions(-)
pve-storage:
 src/PVE/Storage/ISCSIPlugin.pm      | 142 ++++++++++++++++++++++++++++++---
 1 file changed, 133 insertions(+), 9 deletions(-)


-- 
2.52.0



Felix Driessler
Junior Systems Engineer // #GernPerDU

Linux - Open Source - IT Solutions

T: +49-681-410993-0
E: fdriessler@inett.de
https://www.inett.de



inett GmbH | Altenkesseler Strasse 17 / B8 | 66115 Saarbrücken | Germany

Vertrieb: vertrieb@inett.de // +49-681-410993-33
Support: support@inett.de // +49-681-410993-42





Geschäftsführung: Marco Gabriel | Amtsgericht Saarbrücken HRB 16588



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

* [PATCH pve-manager 1/4] ui: Add Display of WWID for ISCSI
       [not found]   ` <f53ca227-2275-443f-84f8-48b2785269b2.2bc2ceb6-a3a3-4c49-9566-519c7d2ab20e.d935a384-10c1-4974-ba2a-7adab51bb127@emailsignatures365.codetwo.com>
@ 2026-03-27 10:14     ` Felix Driessler
  0 siblings, 0 replies; 5+ messages in thread
From: Felix Driessler @ 2026-03-27 10:14 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Felix Driessler <fdriessler@inett.de>
---
 www/manager6/Utils.js               |  8 +++
 www/manager6/form/FileSelector.js   | 81 +++++++++++++++++++++--------
 www/manager6/storage/ContentView.js | 24 ++++++++-
 3 files changed, 89 insertions(+), 24 deletions(-)

diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 77dae42e..aa766f85 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -1056,6 +1056,14 @@ Ext.define('PVE.Utils', {
             return Ext.String.htmlEncode(result);
         },
 
+        render_storage_wwid: function (value, metaData, record) {
+            let data = record.data;
+            if ('wwid' in data) {
+                return Ext.String.htmlEncode(data.wwid);
+            } else {
+                return undefined;
+            }
+        },
         render_serverity: function (value) {
             return PVE.Utils.log_severity_hash[value] || value;
         },
diff --git a/www/manager6/form/FileSelector.js b/www/manager6/form/FileSelector.js
index b8f6a8c2..47c187e8 100644
--- a/www/manager6/form/FileSelector.js
+++ b/www/manager6/form/FileSelector.js
@@ -15,6 +15,45 @@ Ext.define('PVE.form.FileSelector', {
         },
     },
 
+    initComponent: function () {
+        var me = this;
+
+        me.listConfig = Ext.apply({
+            width: 600,
+            columns: this.getColumns(false),
+        }, me.listConfig);
+
+        me.callParent();
+    },
+
+    getColumns: function (isIscsi) {
+        return [
+            {
+                header: gettext('Name'),
+                dataIndex: 'text',
+                hideable: false,
+                flex: 1,
+            },
+            ...isIscsi ? [{
+                header: 'WWID',
+                flex: 1,
+                renderer: PVE.Utils.render_storage_wwid,
+                dataIndex: 'wwid',
+            }] : [],
+            {
+                header: gettext('Format'),
+                width: 60,
+                dataIndex: 'format',
+            },
+            {
+                header: gettext('Size'),
+                width: 100,
+                dataIndex: 'size',
+                renderer: Proxmox.Utils.format_size,
+            },
+        ];
+    },
+
     setStorage: function (storage, nodename) {
         var me = this;
 
@@ -52,6 +91,25 @@ Ext.define('PVE.form.FileSelector', {
 
         me.store.removeAll();
         me.store.load();
+
+        let storageInfo = PVE.data.ResourceStore.findRecord(
+            'id',
+            `storage/${me.nodename}/${me.storage}`,
+            0, // startIndex
+            false, // anyMatch
+            true, // caseSensitive
+            true, // exactMatch
+        );
+
+        let res = storageInfo.data;
+        let plugin = res.plugintype;
+        let isIscsi = plugin === 'iscsi';
+
+        let grid = me.getPicker();
+
+        if (grid) {
+            grid.reconfigure(me.store, me.getColumns(isIscsi));
+        }
     },
 
     setNodename: function (nodename) {
@@ -69,27 +127,4 @@ Ext.define('PVE.form.FileSelector', {
 
     // An optional filter function
     filter: undefined,
-
-    listConfig: {
-        width: 600,
-        columns: [
-            {
-                header: gettext('Name'),
-                dataIndex: 'text',
-                hideable: false,
-                flex: 1,
-            },
-            {
-                header: gettext('Format'),
-                width: 60,
-                dataIndex: 'format',
-            },
-            {
-                header: gettext('Size'),
-                width: 100,
-                dataIndex: 'size',
-                renderer: Proxmox.Utils.format_size,
-            },
-        ],
-    },
 });
diff --git a/www/manager6/storage/ContentView.js b/www/manager6/storage/ContentView.js
index 75b81e69..94dd2f08 100644
--- a/www/manager6/storage/ContentView.js
+++ b/www/manager6/storage/ContentView.js
@@ -30,6 +30,19 @@ Ext.define(
             }
             const storage = me.storage;
 
+            let storageInfo = PVE.data.ResourceStore.findRecord(
+                'id',
+                `storage/${nodename}/${storage}`,
+                0, // startIndex
+                false, // anyMatch
+                true, // caseSensitive
+                true, // exactMatch
+            );
+
+            let res = storageInfo.data;
+            let plugin = res.plugintype;
+            let isIscsi = plugin === 'iscsi';
+
             var content = me.content;
             if (!content) {
                 throw 'no content type specified';
@@ -159,6 +172,12 @@ Ext.define(
                             .localeCompare(b.data.text.toString(), undefined, { numeric: true }),
                     dataIndex: 'text',
                 },
+                wwid: {
+                    header: 'WWID',
+                    flex: 2,
+                    renderer: PVE.Utils.render_storage_wwid,
+                    dataIndex: 'wwid',
+                },
                 notes: {
                     header: gettext('Notes'),
                     flex: 1,
@@ -192,7 +211,9 @@ Ext.define(
                 },
             };
 
-            let showColumns = me.showColumns || ['name', 'date', 'format', 'size'];
+            let showColumns = me.showColumns || isIscsi ?
+                ['name', 'date', 'format', 'size', 'wwid'] :
+                ['name', 'date', 'format', 'size'];
 
             Object.keys(availableColumns).forEach(function (key) {
                 if (!showColumns.includes(key)) {
@@ -224,6 +245,7 @@ Ext.define(
             extend: 'Ext.data.Model',
             fields: [
                 'volid',
+                'wwid',
                 'content',
                 'format',
                 'size',
-- 
2.52.0



Felix Driessler
Junior Systems Engineer // #GernPerDU

Linux - Open Source - IT Solutions

T: +49-681-410993-0
E: fdriessler@inett.de
https://www.inett.de



inett GmbH | Altenkesseler Strasse 17 / B8 | 66115 Saarbrücken | Germany

Vertrieb: vertrieb@inett.de // +49-681-410993-33
Support: support@inett.de // +49-681-410993-42





Geschäftsführung: Marco Gabriel | Amtsgericht Saarbrücken HRB 16588



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

* [PATCH pve-manager 2/4] ui: Add CHAP Authentication for ISCSI
       [not found]   ` <f53ca227-2275-443f-84f8-48b2785269b2.2bc2ceb6-a3a3-4c49-9566-519c7d2ab20e.5ac71d0a-bc32-41c3-8898-7681716f7a92@emailsignatures365.codetwo.com>
@ 2026-03-27 10:14     ` Felix Driessler
  0 siblings, 0 replies; 5+ messages in thread
From: Felix Driessler @ 2026-03-27 10:14 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Felix Driessler <fdriessler@inett.de>
---
 www/manager6/storage/IScsiEdit.js | 43 +++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/www/manager6/storage/IScsiEdit.js b/www/manager6/storage/IScsiEdit.js
index cd474f7d..a08efdda 100644
--- a/www/manager6/storage/IScsiEdit.js
+++ b/www/manager6/storage/IScsiEdit.js
@@ -136,6 +136,25 @@ Ext.define('PVE.storage.IScsiInputPanel', {
                 },
             },
         },
+        {
+            xtype: 'proxmoxcheckbox',
+            name: 'enablechap',
+            fieldLabel: gettext('Enable CHAP'),
+            uncheckedValue: 0,
+            listeners: {
+                change:  {
+                    fn: function (f, value) {
+                        let panel = this.up('inputpanel');
+                        let usernameField = panel.lookup('username');
+                        let passwordField = panel.lookup('password');
+                        if (usernameField && passwordField) {
+                            usernameField.setDisabled(!value);
+                            passwordField.setDisabled(!value);
+                        }
+                    }
+                }
+            }
+        },
     ],
 
     column2: [
@@ -145,5 +164,29 @@ Ext.define('PVE.storage.IScsiInputPanel', {
             checked: true,
             fieldLabel: gettext('Use LUNs directly'),
         },
+        {
+            xtype: 'textfield',
+            value: '',
+            emptyText: gettext('Example'),
+            name: 'username',
+            allowBlank: false,
+            fieldLabel: gettext('Username'),
+            reference: 'username',
+            disabled: true,
+        },
+        {
+            xtype: 'textfield',
+            name: 'password',
+            cbind: {
+                emptyText: (get) => (get('isCreate') ? gettext('None') : '********'),
+                allowBlank: (get) => (!get('isCreate')),
+            },
+            allowBlank: true,
+            inputType: 'password',
+            fieldLabel: gettext('Password'),
+            reference: 'password',
+            disabled: true,
+            value: '',
+        },
     ],
 });
-- 
2.52.0



Felix Driessler
Junior Systems Engineer // #GernPerDU

Linux - Open Source - IT Solutions

T: +49-681-410993-0
E: fdriessler@inett.de
https://www.inett.de



inett GmbH | Altenkesseler Strasse 17 / B8 | 66115 Saarbrücken | Germany

Vertrieb: vertrieb@inett.de // +49-681-410993-33
Support: support@inett.de // +49-681-410993-42





Geschäftsführung: Marco Gabriel | Amtsgericht Saarbrücken HRB 16588



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

* [PATCH pve-stoage 3/4] iscsiPlugin: add wwid
       [not found]   ` <f53ca227-2275-443f-84f8-48b2785269b2.2bc2ceb6-a3a3-4c49-9566-519c7d2ab20e.24fbb610-73bc-4d0e-8ec7-c0b5fbde4ff8@emailsignatures365.codetwo.com>
@ 2026-03-27 10:14     ` Felix Driessler
  0 siblings, 0 replies; 5+ messages in thread
From: Felix Driessler @ 2026-03-27 10:14 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Felix Driessler <fdriessler@inett.de>
---
 src/PVE/Storage/ISCSIPlugin.pm | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/src/PVE/Storage/ISCSIPlugin.pm b/src/PVE/Storage/ISCSIPlugin.pm
index 30f4178..bb5576b 100644
--- a/src/PVE/Storage/ISCSIPlugin.pm
+++ b/src/PVE/Storage/ISCSIPlugin.pm
@@ -305,13 +305,21 @@ sub iscsi_device_list {
 
                     my $volid = "$channel.$id.$lun.$blockdev";
 
+                    my $wwid = '';
+                    my $dev = "/dev/$bdev";
+                    $dev =~ m|^(/dev/[A-Za-z0-9_\-./]+)$|
+                        or die "Invalid device path";
+                    $dev = $1;
+                    run_command(['/lib/udev/scsi_id', '-g', '-u', '-d', $dev], outfunc => sub { $wwid .= "$_[0]" });
+
                     $res->{$target}->{$volid} = {
-                        'format' => 'raw',
-                        'size' => int($size * 512),
-                        'vmid' => 0, # not assigned to any vm
-                        'channel' => int($channel),
-                        'id' => int($id),
-                        'lun' => int($lun),
+                        'format'    => 'raw',
+                        'size'      => int($size * 512),
+                        'vmid'      => 0, # not assigned to any vm
+                        'channel'   => int($channel),
+                        'id'        => int($id),
+                        'lun'       => int($lun),
+                        'wwid'      => $wwid
                     };
 
                     #print "TEST: $target $session $host,$bus,$tg,$lun $blockdev\n";
-- 
2.52.0



Felix Driessler
Junior Systems Engineer // #GernPerDU

Linux - Open Source - IT Solutions

T: +49-681-410993-0
E: fdriessler@inett.de
https://www.inett.de



inett GmbH | Altenkesseler Strasse 17 / B8 | 66115 Saarbrücken | Germany

Vertrieb: vertrieb@inett.de // +49-681-410993-33
Support: support@inett.de // +49-681-410993-42





Geschäftsführung: Marco Gabriel | Amtsgericht Saarbrücken HRB 16588



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

* [PATCH pve-stoage 4/4] iscsiPlugin: add chap auth
       [not found]   ` <f53ca227-2275-443f-84f8-48b2785269b2.2bc2ceb6-a3a3-4c49-9566-519c7d2ab20e.6c58b149-eb37-45dd-84d7-651f4453edab@emailsignatures365.codetwo.com>
@ 2026-03-27 10:14     ` Felix Driessler
  0 siblings, 0 replies; 5+ messages in thread
From: Felix Driessler @ 2026-03-27 10:14 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Felix Driessler <fdriessler@inett.de>
---
 src/PVE/Storage/ISCSIPlugin.pm | 122 ++++++++++++++++++++++++++++++++-
 1 file changed, 119 insertions(+), 3 deletions(-)

diff --git a/src/PVE/Storage/ISCSIPlugin.pm b/src/PVE/Storage/ISCSIPlugin.pm
index bb5576b..777c3b0 100644
--- a/src/PVE/Storage/ISCSIPlugin.pm
+++ b/src/PVE/Storage/ISCSIPlugin.pm
@@ -159,13 +159,21 @@ sub iscsi_discovery {
 }
 
 sub iscsi_login {
-    my ($target, $portals, $cache) = @_;
+    my ($target, $portals, $cache, $scfg, $storeid) = @_;
 
     assert_iscsi_support();
 
     eval { iscsi_discovery($target, $portals, $cache); };
     warn $@ if $@;
 
+    if ($scfg->{enablechap}) {
+        eval { iscsi_chap_enable($scfg, $storeid) };
+        warn $@ if $@;
+    } else {
+        eval { iscsi_chap_disable($target); };
+        warn $@ if $@;
+    }
+
     # Disable retries to avoid blocking pvestatd for too long, next iteration will retry anyway
     eval {
         my $cmd = [
@@ -193,9 +201,42 @@ sub iscsi_logout {
 
     assert_iscsi_support();
 
+    eval { iscsi_chap_disable($target); };
+    warn $@ if $@;
+
     run_command([$ISCSIADM, '--mode', 'node', '--targetname', $target, '--logout']);
 }
 
+sub iscsi_chap_enable {
+    my ($scfg, $storeid) = @_;
+
+    my $password = iscsi_get_password($scfg, $storeid);
+    my $target = $scfg->{target};
+    my $username = $scfg->{username};
+
+    $password =~ m|^(.*)$|
+        or die "incorrect Password.";
+    $password = $1;
+
+    run_command([
+        $ISCSIADM, '--mode', 'node', '--targetname', $target,
+        '-o', 'update', '-n', 'node.session.auth.authmethod', '-v', 'CHAP',
+        '-o', 'update', '-n', 'node.session.auth.username', '-v', $username,
+        '-o', 'update', '-n', 'node.session.auth.password', '-v', $password,
+    ]);
+}
+
+sub iscsi_chap_disable {
+    my ($target) = @_;
+
+    run_command([
+        $ISCSIADM, '--mode', 'node', '--targetname', $target,
+        '-o', 'update', '-n', 'node.session.auth.authmethod', '-v', 'None',
+        '-o', 'update', '-n', 'node.session.auth.username', '-v', '""',
+        '-o', 'update', '-n', 'node.session.auth.password', '-v', '""',
+    ]);
+}
+
 my $rescan_filename = "/var/run/pve-iscsi-rescan.lock";
 
 sub iscsi_session_rescan {
@@ -342,7 +383,9 @@ sub plugindata {
     return {
         content => [{ images => 1, none => 1 }, { images => 1 }],
         select_existing => 1,
-        'sensitive-properties' => {},
+        'sensitive-properties' => {
+            password => 1,
+        },
     };
 }
 
@@ -357,6 +400,11 @@ sub properties {
             type => 'string',
             format => 'pve-storage-portal-dns',
         },
+        enablechap => {
+            description => "Enable CHAP Authentication.",
+            type => 'boolean',
+            default => 0,
+        },
     };
 }
 
@@ -368,9 +416,47 @@ sub options {
         disable => { optional => 1 },
         content => { optional => 1 },
         bwlimit => { optional => 1 },
+        enablechap => { optional => 1 },
+        username => { optional => 1 },
+        password => { optional => 1 },
     };
 }
 
+# Helpers
+
+sub iscsi_password_file_name {
+    my ($scfg, $storeid) = @_;
+
+    return "/etc/pve/priv/storage/${storeid}.pw";
+}
+
+sub iscsi_set_password {
+    my ($scfg, $storeid, $password) = @_;
+
+    my $pwfile = iscsi_password_file_name($scfg, $storeid);
+    mkdir "/etc/pve/priv/storage";
+
+    PVE::Tools::file_set_contents($pwfile, "$password\n", 0600, 1);
+}
+
+sub iscsi_delete_password {
+    my ($scfg, $storeid) = @_;
+
+    my $pwfile = iscsi_password_file_name($scfg, $storeid);
+
+    unlink $pwfile;
+}
+
+sub iscsi_get_password {
+    my ($scfg, $storeid) = @_;
+
+    my $pwfile = iscsi_password_file_name($scfg, $storeid);
+
+    my $contents = PVE::Tools::file_read_firstline($pwfile);
+
+    return eval { decode('UTF-8', $contents, 1) } // $contents;
+}
+
 # Storage implementation
 
 sub parse_volname {
@@ -505,7 +591,7 @@ sub activate_storage {
     }
 
     if ($do_login) {
-        eval { iscsi_login($scfg->{target}, $portals, $cache); };
+        eval { iscsi_login($scfg->{target}, $portals, $cache, $scfg, $storeid); };
         warn $@ if $@;
     } else {
         # make sure we get all devices
@@ -711,4 +797,34 @@ sub volume_import {
     die "volume import is not possible on iscsi storage\n";
 }
 
+sub on_add_hook {
+    my ($class, $storeid, $scfg, %param) = @_;
+    if (defined(my $password = $param{password}) && $scfg->{enablechap}) {
+        iscsi_set_password($scfg, $storeid, $password);
+    }
+    else {
+        iscsi_delete_password($scfg, $storeid);
+    }
+}
+
+sub on_update_hook {
+    return if !assert_iscsi_support(1);
+
+    my ($class, $storeid, $scfg, %param) = @_;
+    if (exists($param{password})) {
+        if (defined(my $password = $param{password}) && $scfg->{enablechap}) {
+            if ($password != "") {
+                iscsi_set_password($scfg, $storeid, $password);
+            }
+        }
+        else {
+            iscsi_delete_password($scfg, $storeid);
+        }
+    }
+
+    eval { iscsi_logout($scfg->{target}); };
+    activate_storage($class, $storeid, $scfg)
+}
+
+
 1;
-- 
2.52.0



Felix Driessler
Junior Systems Engineer // #GernPerDU

Linux - Open Source - IT Solutions

T: +49-681-410993-0
E: fdriessler@inett.de
https://www.inett.de



inett GmbH | Altenkesseler Strasse 17 / B8 | 66115 Saarbrücken | Germany

Vertrieb: vertrieb@inett.de // +49-681-410993-33
Support: support@inett.de // +49-681-410993-42





Geschäftsführung: Marco Gabriel | Amtsgericht Saarbrücken HRB 16588



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

end of thread, other threads:[~2026-03-27 10:47 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <f53ca227-2275-443f-84f8-48b2785269b2.2bc2ceb6-a3a3-4c49-9566-519c7d2ab20e.21103ee5-34fe-43b6-b130-08f8ab2b25ae@emailsignatures365.codetwo.com>
2026-03-27 10:14 ` [PATCH pve-manager/pve-storage 0/4] extend iscsi configuration Felix Driessler
     [not found]   ` <f53ca227-2275-443f-84f8-48b2785269b2.2bc2ceb6-a3a3-4c49-9566-519c7d2ab20e.d935a384-10c1-4974-ba2a-7adab51bb127@emailsignatures365.codetwo.com>
2026-03-27 10:14     ` [PATCH pve-manager 1/4] ui: Add Display of WWID for ISCSI Felix Driessler
     [not found]   ` <f53ca227-2275-443f-84f8-48b2785269b2.2bc2ceb6-a3a3-4c49-9566-519c7d2ab20e.5ac71d0a-bc32-41c3-8898-7681716f7a92@emailsignatures365.codetwo.com>
2026-03-27 10:14     ` [PATCH pve-manager 2/4] ui: Add CHAP Authentication " Felix Driessler
     [not found]   ` <f53ca227-2275-443f-84f8-48b2785269b2.2bc2ceb6-a3a3-4c49-9566-519c7d2ab20e.24fbb610-73bc-4d0e-8ec7-c0b5fbde4ff8@emailsignatures365.codetwo.com>
2026-03-27 10:14     ` [PATCH pve-stoage 3/4] iscsiPlugin: add wwid Felix Driessler
     [not found]   ` <f53ca227-2275-443f-84f8-48b2785269b2.2bc2ceb6-a3a3-4c49-9566-519c7d2ab20e.6c58b149-eb37-45dd-84d7-651f4453edab@emailsignatures365.codetwo.com>
2026-03-27 10:14     ` [PATCH pve-stoage 4/4] iscsiPlugin: add chap auth Felix Driessler

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