From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id A28801FF13B for ; Wed, 20 May 2026 15:13:26 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 265F77BBB; Wed, 20 May 2026 15:13:24 +0200 (CEST) From: Dominik Csapak To: pve-devel@lists.proxmox.com Subject: [PATCH manager] ui: sdn: fabrics: node edit: prevent adding multiple ipv6 columns Date: Wed, 20 May 2026 15:12:45 +0200 Message-ID: <20260520131249.2975476-1-d.csapak@proxmox.com> X-Mailer: git-send-email 2.47.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.050 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: 3OTPEYINRSHQGELELNHXFN6JPDXN3XAA X-Message-ID-Hash: 3OTPEYINRSHQGELELNHXFN6JPDXN3XAA X-MailFrom: d.csapak@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 X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: modifying a class member is always dangerous, since it modifies the object on the original class prototype, so pushing into it happens on every instance creation. This means every time 'Add Node' is clicked for a fabric with ipv6 support another ipv6 column is added. To prevent this, create the list of common columns in initComponent and push into that instead. Slightly changes the handling of additionalColumns so we don't have to copy the common columns with 'concat'. Signed-off-by: Dominik Csapak --- www/manager6/sdn/fabrics/InterfacePanel.js | 126 +++++++++++---------- 1 file changed, 65 insertions(+), 61 deletions(-) diff --git a/www/manager6/sdn/fabrics/InterfacePanel.js b/www/manager6/sdn/fabrics/InterfacePanel.js index 5632104a..30c43ddf 100644 --- a/www/manager6/sdn/fabrics/InterfacePanel.js +++ b/www/manager6/sdn/fabrics/InterfacePanel.js @@ -15,65 +15,6 @@ Ext.define('PVE.sdn.Fabric.InterfacePanel', { maxHeight: 500, - commonColumns: [ - { - text: gettext('Status'), - dataIndex: 'status', - width: 30, - renderer: function (value, metaData, record) { - let me = this; - - let warning; - let nodeInterface = me.nodeInterfaces[record.data.name]; - - if (!nodeInterface) { - warning = gettext('Interface does not exist on node'); - } else if ( - (nodeInterface.ip && record.data.ip) || - (nodeInterface.ip6 && record.data.ip6) - ) { - warning = gettext( - 'Interface already has an address configured in /etc/network/interfaces', - ); - } else if (nodeInterface.ip || nodeInterface.ip6) { - warning = gettext( - 'Configure the IP in the fabric, instead of /etc/network/interfaces', - ); - } - - if (warning) { - metaData.tdAttr = `data-qtip="${Ext.htmlEncode(Ext.htmlEncode(warning))}"`; - return ``; - } - - return ''; - }, - }, - { - text: gettext('Name'), - dataIndex: 'name', - flex: 2, - }, - { - text: gettext('Type'), - dataIndex: 'type', - flex: 1, - }, - { - text: gettext('IP'), - xtype: 'widgetcolumn', - dataIndex: 'ip', - flex: 1, - widget: { - xtype: 'proxmoxtextfield', - isFormField: false, - bind: { - disabled: '{record.isDisabled}', - }, - }, - }, - ], - additionalColumns: [], controller: { @@ -110,8 +51,67 @@ Ext.define('PVE.sdn.Fabric.InterfacePanel', { initComponent: function () { let me = this; + let columns = [ + { + text: gettext('Status'), + dataIndex: 'status', + width: 30, + renderer: function (value, metaData, record) { + let me = this; + + let warning; + let nodeInterface = me.nodeInterfaces[record.data.name]; + + if (!nodeInterface) { + warning = gettext('Interface does not exist on node'); + } else if ( + (nodeInterface.ip && record.data.ip) || + (nodeInterface.ip6 && record.data.ip6) + ) { + warning = gettext( + 'Interface already has an address configured in /etc/network/interfaces', + ); + } else if (nodeInterface.ip || nodeInterface.ip6) { + warning = gettext( + 'Configure the IP in the fabric, instead of /etc/network/interfaces', + ); + } + + if (warning) { + metaData.tdAttr = `data-qtip="${Ext.htmlEncode(Ext.htmlEncode(warning))}"`; + return ``; + } + + return ''; + }, + }, + { + text: gettext('Name'), + dataIndex: 'name', + flex: 2, + }, + { + text: gettext('Type'), + dataIndex: 'type', + flex: 1, + }, + { + text: gettext('IP'), + xtype: 'widgetcolumn', + dataIndex: 'ip', + flex: 1, + widget: { + xtype: 'proxmoxtextfield', + isFormField: false, + bind: { + disabled: '{record.isDisabled}', + }, + }, + }, + ]; + if (me.hasIpv6Support) { - me.commonColumns.push({ + columns.push({ text: gettext('IPv6'), xtype: 'widgetcolumn', dataIndex: 'ip6', @@ -126,6 +126,10 @@ Ext.define('PVE.sdn.Fabric.InterfacePanel', { }); } + if (me.additionalColumns.length > 0) { + columns.push(...me.additionalColumns); + } + Ext.apply(me, { store: Ext.create('Ext.data.Store', { model: 'Pve.sdn.Interface', @@ -134,7 +138,7 @@ Ext.define('PVE.sdn.Fabric.InterfacePanel', { direction: 'ASC', }, }), - columns: me.commonColumns.concat(me.additionalColumns), + columns, }); me.callParent(); -- 2.47.3