From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id BD12A96B36 for ; Tue, 16 Apr 2024 14:10:43 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 6C955192C2 for ; Tue, 16 Apr 2024 14:10:13 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS for ; Tue, 16 Apr 2024 14:10:12 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id E31BC45029 for ; Tue, 16 Apr 2024 14:10:11 +0200 (CEST) From: Filip Schauer To: pve-devel@lists.proxmox.com Date: Tue, 16 Apr 2024 14:10:02 +0200 Message-Id: <20240416121002.135845-3-f.schauer@proxmox.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240416121002.135845-1-f.schauer@proxmox.com> References: <20240416121002.135845-1-f.schauer@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL -0.073 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pve-devel] [PATCH v4 manager 2/2] ui: lxc: add edit window for device passthrough X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 16 Apr 2024 12:10:43 -0000 Signed-off-by: Filip Schauer --- www/manager6/Makefile | 1 + www/manager6/Utils.js | 11 ++ www/manager6/lxc/DeviceEdit.js | 180 +++++++++++++++++++++++++++++++++ www/manager6/lxc/Resources.js | 31 +++++- 4 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 www/manager6/lxc/DeviceEdit.js diff --git a/www/manager6/Makefile b/www/manager6/Makefile index c756cae6..5e16f2a5 100644 --- a/www/manager6/Makefile +++ b/www/manager6/Makefile @@ -188,6 +188,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 8205598a..2c3c56ca 100644 --- a/www/manager6/Utils.js +++ b/www/manager6/Utils.js @@ -1615,6 +1615,17 @@ Ext.define('PVE.Utils', { } }, + lxc_dev_count: 256, + + forEachLxcDev: function(func) { + for (let i = 0; i < PVE.Utils.lxc_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..e3bfcfd0 --- /dev/null +++ b/www/manager6/lxc/DeviceEdit.js @@ -0,0 +1,180 @@ +Ext.define('PVE.lxc.DeviceInputPanel', { + extend: 'Proxmox.panel.InputPanel', + mixins: ['Proxmox.Mixin.CBind'], + + autoComplete: false, + + controller: { + xclass: 'Ext.app.ViewController', + }, + + cbind: { + confid: '{confid}', + isCreate: get => !get('confid'), + }, + + setVMConfig: function(vmconfig) { + let me = this; + me.vmconfig = vmconfig; + + if (me.isCreate) { + PVE.Utils.forEachLxcDev((i) => { + let name = "dev" + i.toString(); + if (!Ext.isDefined(vmconfig[name])) { + me.confid = name; + me.down('field[name=devid]').setValue(i); + return false; + } + return undefined; + }); + } + }, + + onGetValues: function(values) { + let me = this; + delete values.devid; + let val = PVE.Parser.printPropertyString(values, 'path'); + let ret = {}; + ret[me.confid] = val; + return ret; + }, + + items: [ + { + xtype: 'proxmoxintegerfield', + name: 'devid', + fieldLabel: gettext('Passthrough ID'), + minValue: 0, + maxValue: PVE.Utils.dev_count - 1, + hidden: true, + allowBlank: false, + disabled: true, + labelAlign: 'right', + bind: { + hidden: '{!isCreate}', + disabled: '{!isCreate}', + }, + validator: function(value) { + let view = this.up('inputpanel'); + if (!view.vmconfig) { + return undefined; + } + if (Ext.isDefined(view.vmconfig["dev" + value])) { + return "Device passthrough is already in use."; + } + return true; + }, + }, + { + xtype: 'textfield', + type: 'device', + name: 'path', + editable: true, + allowBlank: false, + fieldLabel: gettext('Device Path'), + emptyText: '/dev/xyz', + labelAlign: 'right', + validator: function(value) { + if (value.startsWith('/dev/')) { + return true; + } + + return "Path has to start with /dev/"; + }, + }, + ], + + advancedColumn1: [ + { + xtype: 'proxmoxintegerfield', + name: 'uid', + editable: true, + fieldLabel: 'UID', + emptyText: '0', + minValue: 0, + labelAlign: 'right', + }, + { + xtype: 'proxmoxintegerfield', + name: 'gid', + editable: true, + fieldLabel: 'GID', + emptyText: '0', + minValue: 0, + labelAlign: 'right', + }, + ], + + advancedColumn2: [ + { + xtype: 'textfield', + name: 'mode', + editable: true, + fieldLabel: gettext('Access Mode'), + emptyText: '0660', + labelAlign: 'right', + validator: function(value) { + if (/^0[0-7]{3}$|^$/i.test(value)) { + return true; + } + + return "Access mode has to be an octal number"; + }, + }, + ], +}); + +Ext.define('PVE.lxc.DeviceEdit', { + extend: 'Proxmox.window.Edit', + + vmconfig: undefined, + + isAdd: true, + width: 400, + + initComponent: function() { + let me = this; + + me.isCreate = !me.confid; + + let ipanel = Ext.create('PVE.lxc.DeviceInputPanel', { + confid: me.confid, + isCreate: me.isCreate, + pveSelNode: me.pveSelNode, + }); + + let subject; + if (me.isCreate) { + subject = gettext('Device'); + } else { + subject = gettext('Device') + ' (' + me.confid + ')'; + } + + Ext.apply(me, { + subject: subject, + 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 values = { + path: data.path, + mode: data.mode, + uid: data.uid, + gid: data.gid, + }; + + ipanel.setValues(values); + }, + }); + }, +}); diff --git a/www/manager6/lxc/Resources.js b/www/manager6/lxc/Resources.js index 61182ef3..8203d32b 100644 --- a/www/manager6/lxc/Resources.js +++ b/www/manager6/lxc/Resources.js @@ -135,6 +135,19 @@ Ext.define('PVE.lxc.RessourceView', { }; }, true); + let deveditor = Proxmox.UserName === 'root@pam' ? 'PVE.lxc.DeviceEdit' : undefined; + + PVE.Utils.forEachLxcDev(function(i) { + confid = 'dev' + i; + rows[confid] = { + group: 7, + order: i, + tdCls: 'pve-itype-icon-pci', + editor: deveditor, + header: gettext('Device') + ' (' + confid + ')', + }; + }); + var baseurl = 'nodes/' + nodename + '/lxc/' + vmid + '/config'; me.selModel = Ext.create('Ext.selection.RowModel', {}); @@ -311,6 +324,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 +340,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 +394,21 @@ Ext.define('PVE.lxc.RessourceView', { }); }, }, + { + text: gettext('Device Passthrough'), + iconCls: 'pve-itype-icon-pci', + disabled: Proxmox.UserName !== 'root@pam', + handler: function() { + Ext.create('PVE.lxc.DeviceEdit', { + autoShow: true, + url: `/api2/extjs/${baseurl}`, + pveSelNode: me.pveSelNode, + listeners: { + destroy: () => me.reload(), + }, + }); + }, + }, ], }), }, -- 2.39.2