From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id 191E31FF0FD for ; Tue, 27 Oct 2026 09:59:00 +0100 (CET) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id CF9FB21887; Tue, 27 Oct 2026 09:56:33 +0100 (CET) From: Hannes Laimer To: pve-devel@lists.proxmox.com Subject: [PATCH pve-network v3 23/45] sdn: dry-run: show pending microseg changes Date: Tue, 27 Oct 2026 09:55:05 +0100 Message-ID: <20261027085527.702738-24-h.laimer@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261027085527.702738-1-h.laimer@proxmox.com> References: <20261027085527.702738-1-h.laimer@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1793091358443 X-SPAM-LEVEL: Spam detection results: 0 AWL -2.169 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 URIBL_DBL_SPAM 5 Contains a spam URL listed in the Spamhaus DBL blocklist [sdn.pm] Message-ID-Hash: Q36WGNUJ66FQCWS36CN445YCMQSUFSKR X-Message-ID-Hash: Q36WGNUJ66FQCWS36CN445YCMQSUFSKR X-MailFrom: h.laimer@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: Microseg has no per-node generated file to diff, so the dry-run summarizes the running and the pending config as text and returns the diff of the two. Both summaries resolve memberships against the guests as they are now, so the diff shows only what the pending config changes. Signed-off-by: Hannes Laimer --- src/PVE/API2/Network/SDN.pm | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/PVE/API2/Network/SDN.pm b/src/PVE/API2/Network/SDN.pm index 8640607a6b5c..8a28b2f58e85 100644 --- a/src/PVE/API2/Network/SDN.pm +++ b/src/PVE/API2/Network/SDN.pm @@ -367,11 +367,14 @@ __PACKAGE__->register_method({ }); sub get_diff { - my ($filename_one, $filename_two) = @_; + my ($filename_one, $filename_two, $label_one, $label_two) = @_; my $diff = ''; - my $cmd = ['/usr/bin/diff', '-b', '-N', '-u', $filename_one, $filename_two]; + my $cmd = ['/usr/bin/diff', '-b', '-N', '-u']; + push @$cmd, '--label', $label_one, '--label', $label_two + if defined($label_one) && defined($label_two); + push @$cmd, $filename_one, $filename_two; PVE::Tools::run_command( $cmd, noerr => 1, @@ -419,6 +422,15 @@ __PACKAGE__->register_method({ description => 'The difference between the current and pending /etc/network/interfaces.d/sdn configuration.', }, + "microseg-diff" => { + type => 'string', + optional => 1, + description => + 'The difference between the current and pending microsegmentation state. The' + . ' state covers the allocated identities, the per-NIC group membership, and' + . ' the rules, without the interfaces of guests the caller may not' + . ' audit. It is left out without SDN.Audit on /sdn/microseg.', + }, }, }, code => sub { @@ -449,6 +461,26 @@ __PACKAGE__->register_method({ $return_value->{"interfaces-diff"} = get_diff('/etc/network/interfaces.d/sdn', $interfaces_tmp_filename); + my $rpcenv = PVE::RPCEnvironment::get(); + my $authuser = $rpcenv->get_user(); + + if ($rpcenv->check($authuser, '/sdn/microseg', ['SDN.Audit'], 1)) { + my $current_cfg = PVE::Network::SDN::running_config(); + my $inventory = PVE::Network::SDN::Microseg::audited_guest_inventory(); + my $microseg_old = + PVE::RS::SDN::Microseg::summary($current_cfg->{microseg} // {}, $inventory); + my $microseg_new = + PVE::RS::SDN::Microseg::summary($running_cfg->{microseg} // {}, $inventory); + my ($microseg_old_filename, $microseg_old_fh) = + PVE::File::tempfile_contents($microseg_old, 0700); + my ($microseg_new_filename, $microseg_new_fh) = + PVE::File::tempfile_contents($microseg_new, 0700); + $return_value->{"microseg-diff"} = + get_diff($microseg_old_filename, $microseg_new_filename, 'current', 'pending'); + close($microseg_old_fh); + close($microseg_new_fh); + } + close($frr_tmp_fh); close($interfaces_tmp_fh); return $return_value; -- 2.47.3