From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [IPv6:2a0f:8001:1:32::40]) by lore.proxmox.com (Postfix) with ESMTPS id 2A5AB1FF0C2 for ; Thu, 22 Oct 2026 14:50:41 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 0731521A72; Thu, 22 Oct 2026 14:48:36 +0200 (CEST) From: Arthur Bied-Charreton To: pve-devel@lists.proxmox.com Subject: [PATCH pve-manager v4 23/27] ui: sdn: apply: add control for dangling IPSet references Date: Thu, 22 Oct 2026 14:47:04 +0200 Message-ID: <20261022124708.429069-24-a.bied-charreton@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261022124708.429069-1-a.bied-charreton@proxmox.com> References: <20261022124708.429069-1-a.bied-charreton@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1792673238003 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.826 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust 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: ZNYOG4MNM6DPRC64LOERV64P543NZWU3 X-Message-ID-Hash: ZNYOG4MNM6DPRC64LOERV64P543NZWU3 X-MailFrom: a.bied-charreton@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: Applying an SDN configuration that removes a VNet also removes the four IPSets auto-generated for it [0], so rules referencing those no longer resolve and are dropped from the generated ruleset. Replace the plain confirmation message box with a window carrying the shared selector, so those rules can be disabled or deleted in the same step. The Apply button first queries the pending VNets, and the window only shows the selector if the apply actually removes one, since there is nothing to decide otherwise. [0] https://pve.proxmox.com/wiki/Software-Defined_Network#pvesdn_firewall_integration Signed-off-by: Arthur Bied-Charreton --- www/manager6/sdn/StatusView.js | 118 +++++++++++++++++++++++++++------ 1 file changed, 98 insertions(+), 20 deletions(-) diff --git a/www/manager6/sdn/StatusView.js b/www/manager6/sdn/StatusView.js index fada5041..ce919639 100644 --- a/www/manager6/sdn/StatusView.js +++ b/www/manager6/sdn/StatusView.js @@ -1,3 +1,87 @@ +// scanned by asciidoc-pve, so the anchor lands in the documentation index +const VNET_IPSETS_HELP = { + onlineHelp: 'pve_firewall_automatically_generated_ipsets', +}; + +Ext.define('PVE.sdn.ApplyWindow', { + extend: 'Proxmox.window.Edit', + alias: 'widget.pveSdnApplyWindow', + + title: gettext('Apply SDN Configuration'), + + url: '/cluster/sdn', + method: 'PUT', + isCreate: true, + submitText: gettext('Apply'), + width: 600, + + removedVnets: [], + + initComponent: function () { + let me = this; + + me.items = [ + { + xtype: 'displayfield', + value: gettext( + 'Applying pending SDN changes will also apply any pending local node network changes.', + ), + }, + ]; + + if (me.removedVnets.length !== 0) { + let removedHint = Ext.htmlEncode( + Ext.String.format( + gettext('This removes the following VNet(s): {0}.'), + me.removedVnets.join(', '), + ), + ); + let helpLink = Ext.htmlEncode(Proxmox.Utils.get_help_link(VNET_IPSETS_HELP.onlineHelp)); + let helpLabel = Ext.htmlEncode(gettext('their auto-generated IPSets')); + let refsHint = Ext.String.format( + gettext('Firewall rules referencing {0} will no longer resolve.'), + `${helpLabel}`, + ); + + me.items.push( + { + xtype: 'displayfield', + userCls: 'pmx-hint', + value: `${removedHint}
${refsHint}`, + }, + { + xtype: 'pveFirewallReferenceAction', + name: 'dangling-ipset-references', + preferredValue: 'drop', + fieldLabel: gettext('Referencing rules'), + labelWidth: 200, + referenceActions: [ + { + text: gettext('Keep'), + value: 'keep', + description: gettext( + "Do not touch firewall rules referencing this VNet's IPSets.", + ), + }, + { + text: gettext('Disable'), + value: 'disable', + description: gettext("Disable firewall rules referencing this VNet's IPSets."), + }, + { + text: gettext('Delete'), + value: 'drop', + description: gettext("Delete firewall rules referencing this VNet's IPSets."), + }, + ], + }, + ); + } + + me.callParent(); + }, +}); + Ext.define( 'PVE.sdn.StatusView', { @@ -45,26 +129,20 @@ Ext.define( { text: gettext('Apply'), handler: function () { - Ext.Msg.show({ - title: gettext('Confirm'), - icon: Ext.Msg.QUESTION, - msg: gettext( - 'Applying pending SDN changes will also apply any pending local node network changes. Proceed?', - ), - buttons: Ext.Msg.YESNO, - callback: function (btn) { - if (btn === 'yes') { - Proxmox.Utils.API2Request({ - url: '/cluster/sdn/', - method: 'PUT', - waitMsgTarget: me, - failure: (response) => - Ext.Msg.alert( - gettext('Error'), - response.htmlStatus, - ), - }); - } + Proxmox.Utils.API2Request({ + url: '/cluster/sdn/vnets', + method: 'GET', + params: { pending: 1 }, + waitMsgTarget: me, + failure: (response) => + Ext.Msg.alert(gettext('Error'), response.htmlStatus), + success: function (response) { + Ext.create('PVE.sdn.ApplyWindow', { + removedVnets: response.result.data + .filter((vnet) => vnet.state === 'deleted') + .map((vnet) => vnet.vnet), + autoShow: true, + }); }, }); }, -- 2.47.3