* [pve-devel] [PATCH manager] ui: lxc: add edit window for device passthrough
@ 2023-10-30 11:27 Filip Schauer
2023-11-21 10:23 ` Filip Schauer
0 siblings, 1 reply; 2+ messages in thread
From: Filip Schauer @ 2023-10-30 11:27 UTC (permalink / raw)
To: pve-devel
Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
---
Depends on:
https://lists.proxmox.com/pipermail/pve-devel/2023-October/059616.html
www/manager6/Makefile | 1 +
www/manager6/Utils.js | 11 +++
www/manager6/lxc/DeviceEdit.js | 158 +++++++++++++++++++++++++++++++++
www/manager6/lxc/Resources.js | 28 +++++-
4 files changed, 197 insertions(+), 1 deletion(-)
create mode 100644 www/manager6/lxc/DeviceEdit.js
diff --git a/www/manager6/Makefile b/www/manager6/Makefile
index 57e1b48f..373c8f6d 100644
--- a/www/manager6/Makefile
+++ b/www/manager6/Makefile
@@ -185,6 +185,7 @@ JSSRC= \
lxc/CmdMenu.js \
lxc/Config.js \
lxc/CreateWizard.js \
+ lxc/DeviceEdit.js \
lxc/DNS.js \
lxc/FeaturesEdit.js \
lxc/MPEdit.js \
diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
index 8f46c07e..1ea7b42a 100644
--- a/www/manager6/Utils.js
+++ b/www/manager6/Utils.js
@@ -1605,6 +1605,17 @@ Ext.define('PVE.Utils', {
}
},
+ dev_count: 256,
+
+ forEachDev: function(func) {
+ for (let i = 0; i < PVE.Utils.dev_count; i++) {
+ let cont = func(i);
+ if (!cont && cont !== undefined) {
+ return;
+ }
+ }
+ },
+
hardware_counts: {
net: 32,
usb: 14,
diff --git a/www/manager6/lxc/DeviceEdit.js b/www/manager6/lxc/DeviceEdit.js
new file mode 100644
index 00000000..e4790c4e
--- /dev/null
+++ b/www/manager6/lxc/DeviceEdit.js
@@ -0,0 +1,158 @@
+Ext.define('PVE.lxc.DeviceInputPanel', {
+ extend: 'Proxmox.panel.InputPanel',
+ mixins: ['Proxmox.Mixin.CBind'],
+
+ autoComplete: false,
+
+ cbindData: function(initialConfig) {
+ let me = this;
+ if (!me.pveSelNode) {
+ throw "no pveSelNode given";
+ }
+
+ return { nodename: me.pveSelNode.data.node };
+ },
+
+ viewModel: {
+ data: {},
+ },
+
+ setVMConfig: function(vmconfig) {
+ var me = this;
+ me.vmconfig = vmconfig;
+ },
+
+ onGetValues: function(values) {
+ var me = this;
+ if (!me.confid) {
+ let max_devices = 256;
+ for (let i = 0; i < max_devices; i++) {
+ let id = 'dev' + i.toString();
+ if (!me.vmconfig[id]) {
+ me.confid = id;
+ break;
+ }
+ }
+ }
+ var val = "";
+ var type = me.down('radiofield').getGroupValue();
+ switch (type) {
+ case 'path':
+ val = values[type];
+ delete values[type];
+ break;
+ case 'usbmapped':
+ val = 'usbmapping=' + values[type];
+ delete values[type];
+ break;
+ default:
+ throw "invalid type selected";
+ }
+
+ values[me.confid] = val;
+ return values;
+ },
+
+ items: [
+ {
+ xtype: 'fieldcontainer',
+ defaultType: 'radiofield',
+ layout: 'fit',
+ items: [
+ {
+ name: 'dev',
+ inputValue: 'usbmapped',
+ boxLabel: gettext('Use mapped USB device'),
+ reference: 'usbmapped',
+ submitValue: false,
+ checked: true,
+ },
+ {
+ xtype: 'pveUSBMapSelector',
+ disabled: true,
+ name: 'usbmapped',
+ cbind: { nodename: '{nodename}' },
+ bind: { disabled: '{!usbmapped.checked}' },
+ allowBlank: false,
+ fieldLabel: gettext('Choose Device'),
+ labelAlign: 'right',
+ },
+ {
+ name: 'dev',
+ inputValue: 'path',
+ boxLabel: gettext('Use Device Path'),
+ reference: 'path',
+ submitValue: false,
+ },
+ {
+ xtype: 'textfield',
+ disabled: true,
+ type: 'device',
+ name: 'path',
+ cbind: { pveSelNode: '{pveSelNode}' },
+ bind: { disabled: '{!path.checked}' },
+ editable: true,
+ allowBlank: false,
+ fieldLabel: gettext('Device Path'),
+ labelAlign: 'right',
+ },
+ ],
+ },
+ ],
+});
+
+Ext.define('PVE.lxc.DeviceEdit', {
+ extend: 'Proxmox.window.Edit',
+
+ vmconfig: undefined,
+
+ isAdd: true,
+ width: 400,
+ subject: gettext('Device'),
+
+ initComponent: function() {
+ var me = this;
+
+ me.isCreate = !me.confid;
+
+ var ipanel = Ext.create('PVE.lxc.DeviceInputPanel', {
+ confid: me.confid,
+ pveSelNode: me.pveSelNode,
+ });
+
+ Ext.apply(me, {
+ items: [ipanel],
+ });
+
+ me.callParent();
+
+ me.load({
+ success: function(response, options) {
+ ipanel.setVMConfig(response.result.data);
+ if (me.isCreate) {
+ return;
+ }
+
+ let data = PVE.Parser.parsePropertyString(response.result.data[me.confid], 'path');
+ let path, usbmapped;
+ let dev;
+
+ if (data.path) {
+ path = data.path;
+ dev = 'path';
+ } else if (data.usbmapping) {
+ usbmapped = data.usbmapping;
+ dev = 'usbmapped';
+ }
+
+ var values = {
+ dev,
+ path,
+ usbmapped,
+ };
+
+ ipanel.setValues(values);
+ },
+ });
+ },
+});
diff --git a/www/manager6/lxc/Resources.js b/www/manager6/lxc/Resources.js
index 85112345..9dcb74eb 100644
--- a/www/manager6/lxc/Resources.js
+++ b/www/manager6/lxc/Resources.js
@@ -135,6 +135,17 @@ Ext.define('PVE.lxc.RessourceView', {
};
}, true);
+ PVE.Utils.forEachDev(function(i) {
+ confid = 'dev' + i;
+ rows[confid] = {
+ group: 7,
+ order: i,
+ tdCls: 'pve-itype-icon-pci',
+ editor: 'PVE.lxc.DeviceEdit',
+ header: gettext('Device') + ' (' + confid + ')',
+ };
+ });
+
var baseurl = 'nodes/' + nodename + '/lxc/' + vmid + '/config';
me.selModel = Ext.create('Ext.selection.RowModel', {});
@@ -311,6 +322,7 @@ Ext.define('PVE.lxc.RessourceView', {
let isDisk = isRootFS || key.match(/^(mp|unused)\d+/);
let isUnusedDisk = key.match(/^unused\d+/);
let isUsedDisk = isDisk && !isUnusedDisk;
+ let isDevice = key.match(/^dev\d+/);
let noedit = isDelete || !rowdef.editor;
if (!noedit && Proxmox.UserName !== 'root@pam' && key.match(/^mp\d+$/)) {
@@ -326,7 +338,7 @@ Ext.define('PVE.lxc.RessourceView', {
reassign_menuitem.setDisabled(isRootFS);
resize_menuitem.setDisabled(isUnusedDisk);
- remove_btn.setDisabled(!isDisk || isRootFS || !diskCap || pending);
+ remove_btn.setDisabled(!(isDisk || isDevice) || isRootFS || !diskCap || pending);
revert_btn.setDisabled(!pending);
remove_btn.setText(isUsedDisk ? remove_btn.altText : remove_btn.defaultText);
@@ -380,6 +392,20 @@ Ext.define('PVE.lxc.RessourceView', {
});
},
},
+ {
+ text: gettext('Device Passthrough'),
+ iconCls: 'pve-itype-icon-pci',
+ handler: function() {
+ Ext.create('PVE.lxc.DeviceEdit', {
+ autoShow: true,
+ url: `/api2/extjs/${baseurl}`,
+ pveSelNode: me.pveSelNode,
+ listeners: {
+ destroy: () => me.reload(),
+ },
+ });
+ },
+ },
],
}),
},
--
2.39.2
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [pve-devel] [PATCH manager] ui: lxc: add edit window for device passthrough
2023-10-30 11:27 [pve-devel] [PATCH manager] ui: lxc: add edit window for device passthrough Filip Schauer
@ 2023-11-21 10:23 ` Filip Schauer
0 siblings, 0 replies; 2+ messages in thread
From: Filip Schauer @ 2023-11-21 10:23 UTC (permalink / raw)
To: pve-devel
Patch v2 available:
https://lists.proxmox.com/pipermail/pve-devel/2023-November/060583.html
On 30/10/2023 12:27, Filip Schauer wrote:
> Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
> ---
> Depends on:
> https://lists.proxmox.com/pipermail/pve-devel/2023-October/059616.html
>
> www/manager6/Makefile | 1 +
> www/manager6/Utils.js | 11 +++
> www/manager6/lxc/DeviceEdit.js | 158 +++++++++++++++++++++++++++++++++
> www/manager6/lxc/Resources.js | 28 +++++-
> 4 files changed, 197 insertions(+), 1 deletion(-)
> create mode 100644 www/manager6/lxc/DeviceEdit.js
>
> diff --git a/www/manager6/Makefile b/www/manager6/Makefile
> index 57e1b48f..373c8f6d 100644
> --- a/www/manager6/Makefile
> +++ b/www/manager6/Makefile
> @@ -185,6 +185,7 @@ JSSRC= \
> lxc/CmdMenu.js \
> lxc/Config.js \
> lxc/CreateWizard.js \
> + lxc/DeviceEdit.js \
> lxc/DNS.js \
> lxc/FeaturesEdit.js \
> lxc/MPEdit.js \
> diff --git a/www/manager6/Utils.js b/www/manager6/Utils.js
> index 8f46c07e..1ea7b42a 100644
> --- a/www/manager6/Utils.js
> +++ b/www/manager6/Utils.js
> @@ -1605,6 +1605,17 @@ Ext.define('PVE.Utils', {
> }
> },
>
> + dev_count: 256,
> +
> + forEachDev: function(func) {
> + for (let i = 0; i < PVE.Utils.dev_count; i++) {
> + let cont = func(i);
> + if (!cont && cont !== undefined) {
> + return;
> + }
> + }
> + },
> +
> hardware_counts: {
> net: 32,
> usb: 14,
> diff --git a/www/manager6/lxc/DeviceEdit.js b/www/manager6/lxc/DeviceEdit.js
> new file mode 100644
> index 00000000..e4790c4e
> --- /dev/null
> +++ b/www/manager6/lxc/DeviceEdit.js
> @@ -0,0 +1,158 @@
> +Ext.define('PVE.lxc.DeviceInputPanel', {
> + extend: 'Proxmox.panel.InputPanel',
> + mixins: ['Proxmox.Mixin.CBind'],
> +
> + autoComplete: false,
> +
> + cbindData: function(initialConfig) {
> + let me = this;
> + if (!me.pveSelNode) {
> + throw "no pveSelNode given";
> + }
> +
> + return { nodename: me.pveSelNode.data.node };
> + },
> +
> + viewModel: {
> + data: {},
> + },
> +
> + setVMConfig: function(vmconfig) {
> + var me = this;
> + me.vmconfig = vmconfig;
> + },
> +
> + onGetValues: function(values) {
> + var me = this;
> + if (!me.confid) {
> + let max_devices = 256;
> + for (let i = 0; i < max_devices; i++) {
> + let id = 'dev' + i.toString();
> + if (!me.vmconfig[id]) {
> + me.confid = id;
> + break;
> + }
> + }
> + }
> + var val = "";
> + var type = me.down('radiofield').getGroupValue();
> + switch (type) {
> + case 'path':
> + val = values[type];
> + delete values[type];
> + break;
> + case 'usbmapped':
> + val = 'usbmapping=' + values[type];
> + delete values[type];
> + break;
> + default:
> + throw "invalid type selected";
> + }
> +
> + values[me.confid] = val;
> + return values;
> + },
> +
> + items: [
> + {
> + xtype: 'fieldcontainer',
> + defaultType: 'radiofield',
> + layout: 'fit',
> + items: [
> + {
> + name: 'dev',
> + inputValue: 'usbmapped',
> + boxLabel: gettext('Use mapped USB device'),
> + reference: 'usbmapped',
> + submitValue: false,
> + checked: true,
> + },
> + {
> + xtype: 'pveUSBMapSelector',
> + disabled: true,
> + name: 'usbmapped',
> + cbind: { nodename: '{nodename}' },
> + bind: { disabled: '{!usbmapped.checked}' },
> + allowBlank: false,
> + fieldLabel: gettext('Choose Device'),
> + labelAlign: 'right',
> + },
> + {
> + name: 'dev',
> + inputValue: 'path',
> + boxLabel: gettext('Use Device Path'),
> + reference: 'path',
> + submitValue: false,
> + },
> + {
> + xtype: 'textfield',
> + disabled: true,
> + type: 'device',
> + name: 'path',
> + cbind: { pveSelNode: '{pveSelNode}' },
> + bind: { disabled: '{!path.checked}' },
> + editable: true,
> + allowBlank: false,
> + fieldLabel: gettext('Device Path'),
> + labelAlign: 'right',
> + },
> + ],
> + },
> + ],
> +});
> +
> +Ext.define('PVE.lxc.DeviceEdit', {
> + extend: 'Proxmox.window.Edit',
> +
> + vmconfig: undefined,
> +
> + isAdd: true,
> + width: 400,
> + subject: gettext('Device'),
> +
> + initComponent: function() {
> + var me = this;
> +
> + me.isCreate = !me.confid;
> +
> + var ipanel = Ext.create('PVE.lxc.DeviceInputPanel', {
> + confid: me.confid,
> + pveSelNode: me.pveSelNode,
> + });
> +
> + Ext.apply(me, {
> + items: [ipanel],
> + });
> +
> + me.callParent();
> +
> + me.load({
> + success: function(response, options) {
> + ipanel.setVMConfig(response.result.data);
> + if (me.isCreate) {
> + return;
> + }
> +
> + let data = PVE.Parser.parsePropertyString(response.result.data[me.confid], 'path');
> + let path, usbmapped;
> + let dev;
> +
> + if (data.path) {
> + path = data.path;
> + dev = 'path';
> + } else if (data.usbmapping) {
> + usbmapped = data.usbmapping;
> + dev = 'usbmapped';
> + }
> +
> + var values = {
> + dev,
> + path,
> + usbmapped,
> + };
> +
> + ipanel.setValues(values);
> + },
> + });
> + },
> +});
> diff --git a/www/manager6/lxc/Resources.js b/www/manager6/lxc/Resources.js
> index 85112345..9dcb74eb 100644
> --- a/www/manager6/lxc/Resources.js
> +++ b/www/manager6/lxc/Resources.js
> @@ -135,6 +135,17 @@ Ext.define('PVE.lxc.RessourceView', {
> };
> }, true);
>
> + PVE.Utils.forEachDev(function(i) {
> + confid = 'dev' + i;
> + rows[confid] = {
> + group: 7,
> + order: i,
> + tdCls: 'pve-itype-icon-pci',
> + editor: 'PVE.lxc.DeviceEdit',
> + header: gettext('Device') + ' (' + confid + ')',
> + };
> + });
> +
> var baseurl = 'nodes/' + nodename + '/lxc/' + vmid + '/config';
>
> me.selModel = Ext.create('Ext.selection.RowModel', {});
> @@ -311,6 +322,7 @@ Ext.define('PVE.lxc.RessourceView', {
> let isDisk = isRootFS || key.match(/^(mp|unused)\d+/);
> let isUnusedDisk = key.match(/^unused\d+/);
> let isUsedDisk = isDisk && !isUnusedDisk;
> + let isDevice = key.match(/^dev\d+/);
>
> let noedit = isDelete || !rowdef.editor;
> if (!noedit && Proxmox.UserName !== 'root@pam' && key.match(/^mp\d+$/)) {
> @@ -326,7 +338,7 @@ Ext.define('PVE.lxc.RessourceView', {
> reassign_menuitem.setDisabled(isRootFS);
> resize_menuitem.setDisabled(isUnusedDisk);
>
> - remove_btn.setDisabled(!isDisk || isRootFS || !diskCap || pending);
> + remove_btn.setDisabled(!(isDisk || isDevice) || isRootFS || !diskCap || pending);
> revert_btn.setDisabled(!pending);
>
> remove_btn.setText(isUsedDisk ? remove_btn.altText : remove_btn.defaultText);
> @@ -380,6 +392,20 @@ Ext.define('PVE.lxc.RessourceView', {
> });
> },
> },
> + {
> + text: gettext('Device Passthrough'),
> + iconCls: 'pve-itype-icon-pci',
> + handler: function() {
> + Ext.create('PVE.lxc.DeviceEdit', {
> + autoShow: true,
> + url: `/api2/extjs/${baseurl}`,
> + pveSelNode: me.pveSelNode,
> + listeners: {
> + destroy: () => me.reload(),
> + },
> + });
> + },
> + },
> ],
> }),
> },
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2023-11-21 10:23 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-30 11:27 [pve-devel] [PATCH manager] ui: lxc: add edit window for device passthrough Filip Schauer
2023-11-21 10:23 ` Filip Schauer
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal