This adds a dropdown box for iSCSI, LVM, LVMThin & ZFS storage options where a
cluster node needs to be chosen. As default the current node is
selected. It restricts the the storage to be only availabe on the
selected node.

Signed-off-by: Stefan Hrdlicka <s.hrdli...@proxmox.com>
---
 www/manager6/Makefile                        |  2 +
 www/manager6/form/ComboBoxSetStoreNode.js    | 16 ++++++
 www/manager6/form/StorageScanNodeSelector.js | 31 ++++++++++++
 www/manager6/storage/Base.js                 |  1 +
 www/manager6/storage/IScsiEdit.js            | 28 ++++++++---
 www/manager6/storage/LVMEdit.js              | 28 +++++++++--
 www/manager6/storage/LvmThinEdit.js          | 51 +++++++++++++++-----
 www/manager6/storage/ZFSPoolEdit.js          | 27 +++++++++--
 8 files changed, 160 insertions(+), 24 deletions(-)
 create mode 100644 www/manager6/form/ComboBoxSetStoreNode.js
 create mode 100644 www/manager6/form/StorageScanNodeSelector.js

diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index d16770b1..81f5e5d8 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -27,6 +27,7 @@ JSSRC=                                                        
\
        form/CalendarEvent.js                           \
        form/CephPoolSelector.js                        \
        form/CephFSSelector.js                          \
+       form/ComboBoxSetStoreNode.js                    \
        form/CompressionSelector.js                     \
        form/ContentTypeSelector.js                     \
        form/ControllerSelector.js                      \
@@ -62,6 +63,7 @@ JSSRC=                                                        
\
        form/SecurityGroupSelector.js                   \
        form/SnapshotSelector.js                        \
        form/SpiceEnhancementSelector.js                \
+       form/StorageScanNodeSelector.js                 \
        form/StorageSelector.js                         \
        form/TFASelector.js                             \
        form/TokenSelector.js                           \
diff --git a/www/manager6/form/ComboBoxSetStoreNode.js 
b/www/manager6/form/ComboBoxSetStoreNode.js
new file mode 100644
index 00000000..3490ddd7
--- /dev/null
+++ b/www/manager6/form/ComboBoxSetStoreNode.js
@@ -0,0 +1,16 @@
+Ext.define('PVE.form.ComboBoxSetStoreNode', {
+    extend: 'Ext.form.field.ComboBox',
+    config: {
+       apiBaseUrl: '/api2/json/nodes/',
+       apiSuffix: '',
+    },
+
+    setNodeName: function(value) {
+       let me = this;
+       value ||= Proxmox.NodeName;
+
+       
me.getStore().getProxy().setUrl(`${me.apiBaseUrl}${value}${me.apiSuffix}`);
+       this.clearValue();
+    },
+
+});
diff --git a/www/manager6/form/StorageScanNodeSelector.js 
b/www/manager6/form/StorageScanNodeSelector.js
new file mode 100644
index 00000000..d6c9508a
--- /dev/null
+++ b/www/manager6/form/StorageScanNodeSelector.js
@@ -0,0 +1,31 @@
+Ext.define('PVE.form.StorageScanNodeSelector', {
+    extend: 'PVE.form.NodeSelector',
+    xtype: 'pveStorageScanNodeSelector',
+
+    name: 'storageScanNode',
+    itemId: 'pveStorageScanNodeSelector',
+    fieldLabel: gettext('Scan node'),
+    allowBlank: true,
+    disallowedNodes: undefined,
+    autoSelect: false,
+    submitValue: false,
+    value: "",
+    autoEl: {
+       tag: 'div',
+       'data-qtip': gettext('Scan for available storages on the selected 
node'),
+    },
+    triggers: {
+       clear: {
+           handler: function() {
+               let me = this;
+               me.setValue("");
+           },
+       },
+    },
+
+    setValue: function(value) {
+       let me = this;
+       me.callParent([value]);
+       me.triggers.clear.setVisible(value !== "");
+    },
+});
diff --git a/www/manager6/storage/Base.js b/www/manager6/storage/Base.js
index 7f6d7a09..1df7a8dd 100644
--- a/www/manager6/storage/Base.js
+++ b/www/manager6/storage/Base.js
@@ -36,6 +36,7 @@ Ext.define('PVE.panel.StorageBase', {
            {
                xtype: 'pveNodeSelector',
                name: 'nodes',
+               reference: 'storageNodeRestriction',
                disabled: me.storageId === 'local',
                fieldLabel: gettext('Nodes'),
                emptyText: gettext('All') + ' (' + gettext('No restrictions') 
+')',
diff --git a/www/manager6/storage/IScsiEdit.js 
b/www/manager6/storage/IScsiEdit.js
index 2f35f882..af0afe60 100644
--- a/www/manager6/storage/IScsiEdit.js
+++ b/www/manager6/storage/IScsiEdit.js
@@ -1,5 +1,5 @@
 Ext.define('PVE.storage.IScsiScan', {
-    extend: 'Ext.form.field.ComboBox',
+    extend: 'PVE.form.ComboBoxSetStoreNode',
     alias: 'widget.pveIScsiScan',
 
     queryParam: 'portal',
@@ -10,6 +10,9 @@ Ext.define('PVE.storage.IScsiScan', {
        loadingText: gettext('Scanning...'),
        width: 350,
     },
+    config: {
+       apiSuffix: '/scan/iscsi',
+    },
     doRawQuery: function() {
        // do nothing
     },
@@ -42,7 +45,7 @@ Ext.define('PVE.storage.IScsiScan', {
            fields: ['target', 'portal'],
            proxy: {
                type: 'proxmox',
-               url: `/api2/json/nodes/${me.nodename}/scan/iscsi`,
+               url: `${me.apiBaseUrl}${me.nodename}${me.apiSuffix}`,
            },
        });
        store.sort('target', 'ASC');
@@ -78,6 +81,19 @@ Ext.define('PVE.storage.IScsiInputPanel', {
        var me = this;
 
        me.column1 = [
+           {
+               xtype: 'pveStorageScanNodeSelector',
+               disabled: !me.isCreate,
+               hidden: !me.isCreate,
+               listeners: {
+                   change: {
+                       fn: function(field, value) {
+                           me.lookup('iScsiTargetScan').setNodeName(value);
+                           me.lookup('storageNodeRestriction').setValue(value);
+                       },
+                   },
+               },
+           },
            {
                xtype: me.isCreate ? 'textfield' : 'displayfield',
                name: 'portal',
@@ -94,14 +110,14 @@ Ext.define('PVE.storage.IScsiInputPanel', {
                    },
                },
            },
-           {
+           Ext.createWidget(me.isCreate ? 'pveIScsiScan' : 'displayfield', {
                readOnly: !me.isCreate,
-               xtype: me.isCreate ? 'pveIScsiScan' : 'displayfield',
                name: 'target',
                value: '',
-               fieldLabel: 'Target',
+               fieldLabel: gettext('Target'),
                allowBlank: false,
-           },
+               reference: 'iScsiTargetScan',
+           }),
        ];
 
        me.column2 = [
diff --git a/www/manager6/storage/LVMEdit.js b/www/manager6/storage/LVMEdit.js
index 2a9cd283..2cc78621 100644
--- a/www/manager6/storage/LVMEdit.js
+++ b/www/manager6/storage/LVMEdit.js
@@ -1,10 +1,20 @@
 Ext.define('PVE.storage.VgSelector', {
-    extend: 'Ext.form.field.ComboBox',
+    extend: 'PVE.form.ComboBoxSetStoreNode',
     alias: 'widget.pveVgSelector',
     valueField: 'vg',
     displayField: 'vg',
     queryMode: 'local',
     editable: false,
+    config: {
+       apiSuffix: '/scan/lvm',
+    },
+
+    setNodeName: function(value) {
+       let me = this;
+       me.callParent([value]);
+       me.getStore().load();
+    },
+
     initComponent: function() {
        var me = this;
 
@@ -17,7 +27,7 @@ Ext.define('PVE.storage.VgSelector', {
            fields: ['vg', 'size', 'free'],
            proxy: {
                type: 'proxmox',
-               url: '/api2/json/nodes/' + me.nodename + '/scan/lvm',
+               url: `${me.apiBaseUrl}${me.nodename}${me.apiSuffix}`,
            },
        });
 
@@ -103,11 +113,23 @@ Ext.define('PVE.storage.LVMInputPanel', {
        });
 
        if (me.isCreate) {
-           var vgField = Ext.create('PVE.storage.VgSelector', {
+           let vgField = Ext.create('PVE.storage.VgSelector', {
                name: 'vgname',
                fieldLabel: gettext('Volume group'),
+               reference: 'volumeGroupSelector',
                allowBlank: false,
            });
+           me.column1.push({
+               xtype: 'pveStorageScanNodeSelector',
+               listeners: {
+                   change: {
+                       fn: function(field, value) {
+                           me.lookup('volumeGroupSelector').setNodeName(value);
+                           me.lookup('storageNodeRestriction').setValue(value);
+                       },
+                   },
+               },
+           });
 
            var baseField = Ext.createWidget('pveFileSelector', {
                name: 'base',
diff --git a/www/manager6/storage/LvmThinEdit.js 
b/www/manager6/storage/LvmThinEdit.js
index 4eab7740..7c9aa285 100644
--- a/www/manager6/storage/LvmThinEdit.js
+++ b/www/manager6/storage/LvmThinEdit.js
@@ -1,5 +1,5 @@
 Ext.define('PVE.storage.TPoolSelector', {
-    extend: 'Ext.form.field.ComboBox',
+    extend: 'PVE.form.ComboBoxSetStoreNode',
     alias: 'widget.pveTPSelector',
 
     queryParam: 'vg',
@@ -7,6 +7,10 @@ Ext.define('PVE.storage.TPoolSelector', {
     displayField: 'lv',
     editable: false,
 
+    config: {
+       apiSuffix: '/scan/lvmthin',
+    },
+
     doRawQuery: function() {
        // nothing
     },
@@ -40,7 +44,7 @@ Ext.define('PVE.storage.TPoolSelector', {
            fields: ['lv'],
            proxy: {
                type: 'proxmox',
-               url: '/api2/json/nodes/' + me.nodename + '/scan/lvmthin',
+               url: `${me.apiBaseUrl}${me.nodename}${me.apiSuffix}`,
            },
        });
 
@@ -58,13 +62,23 @@ Ext.define('PVE.storage.TPoolSelector', {
 });
 
 Ext.define('PVE.storage.BaseVGSelector', {
-    extend: 'Ext.form.field.ComboBox',
+    extend: 'PVE.form.ComboBoxSetStoreNode',
     alias: 'widget.pveBaseVGSelector',
 
     valueField: 'vg',
     displayField: 'vg',
     queryMode: 'local',
     editable: false,
+    config: {
+       apiSuffix: '/scan/lvm',
+    },
+
+    setNodeName: function(value) {
+       let me = this;
+       me.callParent([value]);
+       me.getStore().load();
+    },
+
     initComponent: function() {
        var me = this;
 
@@ -77,7 +91,7 @@ Ext.define('PVE.storage.BaseVGSelector', {
            fields: ['vg', 'size', 'free'],
            proxy: {
                type: 'proxmox',
-               url: '/api2/json/nodes/' + me.nodename + '/scan/lvm',
+               url: `${me.apiBaseUrl}${me.nodename}${me.apiSuffix}`,
            },
        });
 
@@ -121,27 +135,40 @@ Ext.define('PVE.storage.LvmThinInputPanel', {
        });
 
        if (me.isCreate) {
-           var vgField = Ext.create('PVE.storage.TPoolSelector', {
-               name: 'thinpool',
-               fieldLabel: gettext('Thin Pool'),
-               allowBlank: false,
+           me.column1.push({
+               xtype: 'pveStorageScanNodeSelector',
+               listeners: {
+                   change: {
+                       fn: function(field, value) {
+                           me.lookup('thinPoolSelector').setNodeName(value);
+                           me.lookup('volumeGroupSelector').setNodeName(value);
+                           me.lookup('storageNodeRestriction').setValue(value);
+                       },
+                   },
+               },
            });
 
-           me.column1.push({
-               xtype: 'pveBaseVGSelector',
+           me.column1.push(Ext.create('PVE.storage.BaseVGSelector', {
                name: 'vgname',
                fieldLabel: gettext('Volume group'),
+               reference: 'volumeGroupSelector',
                listeners: {
                    change: function(f, value) {
                        if (me.isCreate) {
+                           let vgField = me.lookup('thinPoolSelector');
                            vgField.setVG(value);
                            vgField.setValue('');
                        }
                    },
                },
-           });
+           }));
 
-           me.column1.push(vgField);
+           me.column1.push(Ext.create('PVE.storage.TPoolSelector', {
+               name: 'thinpool',
+               fieldLabel: gettext('Thin Pool'),
+               reference: 'thinPoolSelector',
+               allowBlank: false,
+           }));
        }
 
        me.column1.push(vgnameField);
diff --git a/www/manager6/storage/ZFSPoolEdit.js 
b/www/manager6/storage/ZFSPoolEdit.js
index 8e689f0c..3499ce94 100644
--- a/www/manager6/storage/ZFSPoolEdit.js
+++ b/www/manager6/storage/ZFSPoolEdit.js
@@ -1,5 +1,5 @@
 Ext.define('PVE.storage.ZFSPoolSelector', {
-    extend: 'Ext.form.field.ComboBox',
+    extend: 'PVE.form.ComboBoxSetStoreNode',
     alias: 'widget.pveZFSPoolSelector',
     valueField: 'pool',
     displayField: 'pool',
@@ -8,6 +8,16 @@ Ext.define('PVE.storage.ZFSPoolSelector', {
     listConfig: {
        loadingText: gettext('Scanning...'),
     },
+    config: {
+       apiSuffix: '/scan/zfs',
+    },
+
+    setNodeName: function(value) {
+       let me = this;
+       me.callParent([value]);
+       me.getStore().load();
+    },
+
     initComponent: function() {
        var me = this;
 
@@ -20,10 +30,9 @@ Ext.define('PVE.storage.ZFSPoolSelector', {
            fields: ['pool', 'size', 'free'],
            proxy: {
                type: 'proxmox',
-               url: '/api2/json/nodes/' + me.nodename + '/scan/zfs',
+               url: `${me.apiBaseUrl}${me.nodename}${me.apiSuffix}`,
            },
        });
-
        store.sort('pool', 'ASC');
 
        Ext.apply(me, {
@@ -45,9 +54,21 @@ Ext.define('PVE.storage.ZFSPoolInputPanel', {
        me.column1 = [];
 
        if (me.isCreate) {
+           me.column1.push({
+               xtype: 'pveStorageScanNodeSelector',
+               listeners: {
+                   change: {
+                       fn: function(field, value) {
+                           me.lookup('zfsPoolSelector').setNodeName(value);
+                           me.lookup('storageNodeRestriction').setValue(value);
+                       },
+                   },
+               },
+           });
            me.column1.push(Ext.create('PVE.storage.ZFSPoolSelector', {
                name: 'pool',
                fieldLabel: gettext('ZFS Pool'),
+               reference: 'zfsPoolSelector',
                allowBlank: false,
            }));
        } else {
-- 
2.30.2



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to