[pve-devel] [PATCH manager] ui: lxc: add edit window for device passthrough
Filip Schauer
f.schauer at proxmox.com
Tue Nov 21 11:23:26 CET 2023
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 at 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 at 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(),
> + },
> + });
> + },
> + },
> ],
> }),
> },
More information about the pve-devel
mailing list