From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id C41181FF146 for ; Tue, 12 May 2026 16:57:53 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 61C9B18994; Tue, 12 May 2026 16:57:51 +0200 (CEST) Date: Tue, 12 May 2026 16:57:46 +0200 From: Wolfgang Bumiller To: Filip Schauer Subject: Re: [PATCH manager v3 3/3] ui: lxc/MPEdit: add "idmap" option Message-ID: References: <20260512140126.171755-1-f.schauer@proxmox.com> <20260512140126.171755-4-f.schauer@proxmox.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20260512140126.171755-4-f.schauer@proxmox.com> X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1778597754055 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.087 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 Message-ID-Hash: 5YSR7EMKY5TH4INUZ7BTUVRI67GSLD43 X-Message-ID-Hash: 5YSR7EMKY5TH4INUZ7BTUVRI67GSLD43 X-MailFrom: w.bumiller@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: pve-devel@lists.proxmox.com X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: On Tue, May 12, 2026 at 04:01:21PM +0200, Filip Schauer wrote: > Integrate UID/GID mapping for container mount points into the web UI. Seems better than v1. Some things to consider, though: Checking and then unchecking `passthrough` wipes the list. I wonder if the last state of the list should be kept around as long as the window is open? On the other hand, at least it's a quick and easy way clear and get rid of id mapping, but users would probably be looking for an explicit clear button instead. Then again the list cannot be huge anyway, so it's not really important. (Although the kernel has raised the limit from 5 to 340 lines long ago...) > > Signed-off-by: Filip Schauer > --- > www/manager6/Makefile | 1 + > www/manager6/lxc/IdMapField.js | 187 +++++++++++++++++++++++++++++++++ > www/manager6/lxc/MPEdit.js | 8 ++ > 3 files changed, 196 insertions(+) > create mode 100644 www/manager6/lxc/IdMapField.js > > diff --git a/www/manager6/Makefile b/www/manager6/Makefile > index f63437d6..85d973fe 100644 > --- a/www/manager6/Makefile > +++ b/www/manager6/Makefile > @@ -210,6 +210,7 @@ JSSRC= \ > lxc/DNS.js \ > lxc/FeaturesEdit.js \ > lxc/EnvEdit.js \ > + lxc/IdMapField.js \ > lxc/MPEdit.js \ > lxc/MPResize.js \ > lxc/Network.js \ > diff --git a/www/manager6/lxc/IdMapField.js b/www/manager6/lxc/IdMapField.js > new file mode 100644 > index 00000000..93731ae2 > --- /dev/null > +++ b/www/manager6/lxc/IdMapField.js > @@ -0,0 +1,187 @@ > +Ext.define('PVE.lxc.IdMapField', { > + extend: 'Ext.form.FieldContainer', > + xtype: 'pveLxcIdMapField', > + > + layout: { type: 'vbox', align: 'stretch' }, > + > + controller: { > + xclass: 'Ext.app.ViewController', > + > + control: { > + 'grid proxmoxintegerfield,grid proxmoxKVComboBox': { > + change: function (widget, value) { > + let me = this; > + let record = widget.getWidgetRecord(); > + let column = widget.getWidgetColumn(); > + if (!record || !column) { > + return; > + } > + record.set(column.dataIndex, value); > + record.commit(); > + me.updateIdMapField(); > + }, > + }, > + }, > + > + onIdMapFieldChange: function (field, value) { > + let me = this; > + let passthrough = value === 'passthrough'; > + let checkbox = me.lookup('passthrough'); > + checkbox.suspendEvent('change'); > + checkbox.setValue(passthrough); > + checkbox.resumeEvent('change'); > + me.lookup('idmaps').setVisible(!passthrough); > + me.lookup('addIdmapButton').setVisible(!passthrough); > + > + let store = me.lookup('idmaps').getStore(); > + if (!passthrough && value) { > + store.setData( > + value.split(';').map((v) => { > + let [type, ct, host, length] = v.split(':'); > + return { type, ct, host, length }; > + }), > + ); > + } else { > + store.removeAll(); > + } > + }, > + > + onPassthroughCheckboxChange: function (checkbox, checked) { > + let me = this; > + me.lookup('idmap').setValue(checked ? 'passthrough' : ''); > + }, > + > + addIdMap: function () { > + let me = this; > + me.lookup('idmaps').getStore().add({ type: 'u', ct: '', host: '', length: '' }); > + me.updateIdMapField(); > + }, > + > + removeIdMap: function (button) { > + let me = this; > + me.lookup('idmaps').getStore().remove(button.getWidgetRecord()); > + me.updateIdMapField(); > + }, > + > + updateIdMapField: function () { > + let me = this; > + let value = me > + .lookup('idmaps') > + .getStore() > + .getRange() > + .map(({ data: { type, ct, host, length } }) => `${type}:${ct}:${host}:${length}`) > + .join(';'); > + let field = me.lookup('idmap'); > + field.suspendEvent('change'); > + field.setValue(value); > + field.resumeEvent('change'); > + }, > + }, > + > + items: [ > + { > + xtype: 'proxmoxcheckbox', > + reference: 'passthrough', > + fieldLabel: gettext('ID Mapping'), > + boxLabel: gettext('Passthrough'), > + isFormField: false, > + listeners: { > + change: 'onPassthroughCheckboxChange', > + }, > + }, > + { > + xtype: 'grid', > + height: 170, > + scrollable: true, > + reference: 'idmaps', > + viewConfig: { > + emptyText: gettext('No ID maps configured'), > + }, > + store: { > + fields: ['type', 'ct', 'host', 'length'], > + data: [], > + }, > + columns: [ > + { > + text: gettext('ID Type'), > + xtype: 'widgetcolumn', > + dataIndex: 'type', > + widget: { > + xtype: 'proxmoxKVComboBox', > + margin: '4 0', > + allowBlank: false, > + comboItems: [ > + ['u', 'UID'], > + ['g', 'GID'], > + ], > + }, > + flex: 1, > + }, > + { > + text: gettext('Container'), > + xtype: 'widgetcolumn', > + dataIndex: 'ct', > + widget: { > + xtype: 'proxmoxintegerfield', > + margin: '4 0', > + emptyText: gettext('Container'), > + allowBlank: false, > + minValue: 0, > + }, > + flex: 1, > + }, > + { > + text: gettext('Host'), > + xtype: 'widgetcolumn', > + dataIndex: 'host', > + widget: { > + xtype: 'proxmoxintegerfield', > + margin: '4 0', > + emptyText: gettext('Host'), > + allowBlank: false, > + minValue: 0, > + }, > + flex: 1, > + }, > + { > + text: gettext('Range Size'), > + xtype: 'widgetcolumn', > + dataIndex: 'length', > + widget: { > + xtype: 'proxmoxintegerfield', > + margin: '4 0', > + emptyText: gettext('Range Size'), > + allowBlank: false, > + minValue: 1, > + }, > + flex: 1, > + }, > + { > + xtype: 'widgetcolumn', > + width: 40, > + widget: { > + xtype: 'button', > + margin: '4 0', > + iconCls: 'fa fa-trash-o', > + handler: 'removeIdMap', > + }, > + }, > + ], > + }, > + { > + xtype: 'button', > + reference: 'addIdmapButton', > + text: gettext('Add'), > + iconCls: 'fa fa-plus-circle', > + handler: 'addIdMap', > + }, > + { > + xtype: 'hidden', > + reference: 'idmap', > + name: 'idmap', > + listeners: { > + change: 'onIdMapFieldChange', > + }, > + }, > + ], > +}); > diff --git a/www/manager6/lxc/MPEdit.js b/www/manager6/lxc/MPEdit.js > index b1f67741..b193ff89 100644 > --- a/www/manager6/lxc/MPEdit.js > +++ b/www/manager6/lxc/MPEdit.js > @@ -47,6 +47,7 @@ Ext.define('PVE.lxc.MountPointInputPanel', { > setMPOpt('acl', values.acl); > setMPOpt('replicate', values.replicate); > setMPOpt('keepattrs', values.keepattrs); > + setMPOpt('idmap', values.idmap); > > let res = {}; > res[confid] = PVE.Parser.printLxcMountPoint(me.mp); > @@ -353,6 +354,13 @@ Ext.define('PVE.lxc.MountPointInputPanel', { > }, > }, > ], > + > + advancedColumnB: [ > + { > + xtype: 'pveLxcIdMapField', > + name: 'idmap', > + }, > + ], > }); > > Ext.define('PVE.lxc.MountPointEdit', { > -- > 2.47.3