public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Christoph Heiss <c.heiss@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH installer 5/6] tui: network: only display pinnable devices in pinning options dialog
Date: Thu, 13 Nov 2025 14:49:53 +0100	[thread overview]
Message-ID: <20251113135023.1038305-6-c.heiss@proxmox.com> (raw)
In-Reply-To: <20251113135023.1038305-1-c.heiss@proxmox.com>

Virtual devices such as e.g. bridges, bonds etc. otherwise also show up,
where name pinning does not make sense.

The `pinned_id` property has been made optional, thus adapt to that.

Not really an issue during bare-metal installations, as there aren't any
bridges/bonds set up yet - no changes there.
But it's a nice future-proofing and improves developing/testing
experience, as such interfaces are now suppressed).

Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
 proxmox-installer-common/src/options.rs    | 31 ++++++++++++--------
 proxmox-installer-common/src/setup.rs      | 33 +++++++++++++---------
 proxmox-tui-installer/src/views/network.rs | 33 +++++++++++++++-------
 3 files changed, 61 insertions(+), 36 deletions(-)

diff --git a/proxmox-installer-common/src/options.rs b/proxmox-installer-common/src/options.rs
index a07fe58..8f3b3aa 100644
--- a/proxmox-installer-common/src/options.rs
+++ b/proxmox-installer-common/src/options.rs
@@ -595,8 +595,10 @@ impl NetworkOptions {
         {
             // we got some ipv4 connectivity, so use that
 
-            if let Some(opts) = pinning_opts {
-                this.ifname.clone_from(&iface.to_pinned(opts).name);
+            if let Some(opts) = pinning_opts
+                && let Some(pinned) = iface.to_pinned(opts)
+            {
+                this.ifname.clone_from(&pinned.name);
             } else {
                 this.ifname.clone_from(&iface.name);
             }
@@ -609,8 +611,10 @@ impl NetworkOptions {
                 && let Some(addr) = iface.addresses.iter().find(|addr| addr.is_ipv6())
             {
                 // no ipv4, but ipv6 connectivity
-                if let Some(opts) = pinning_opts {
-                    this.ifname.clone_from(&iface.to_pinned(opts).name);
+                if let Some(opts) = pinning_opts
+                    && let Some(pinned) = iface.to_pinned(opts)
+                {
+                    this.ifname.clone_from(&pinned.name);
                 } else {
                     this.ifname.clone_from(&iface.name);
                 }
@@ -627,19 +631,22 @@ impl NetworkOptions {
         if this.ifname.is_empty()
             && let Some(iface) = network.interfaces.values().min_by_key(|v| v.index)
         {
-            if let Some(opts) = pinning_opts {
-                this.ifname.clone_from(&iface.to_pinned(opts).name);
+            if let Some(opts) = pinning_opts
+                && let Some(pinned) = iface.to_pinned(opts)
+            {
+                this.ifname.clone_from(&pinned.name);
             } else {
                 this.ifname.clone_from(&iface.name);
             }
         }
 
         if let Some(ref mut opts) = this.pinning_opts {
-            // Ensure that all unique interfaces indeed have an entry in the map,
-            // as required by the low-level installer
+            // Ensure that all unique, pinnable interfaces indeed have an entry in the map, as
+            // required by the low-level installer
             for iface in network.interfaces.values() {
-                let pinned_name = iface.to_pinned(opts).name;
-                opts.mapping.entry(iface.mac.clone()).or_insert(pinned_name);
+                if let Some(pinned) = iface.to_pinned(opts) {
+                    opts.mapping.entry(iface.mac.clone()).or_insert(pinned.name);
+                }
             }
         }
 
@@ -767,7 +774,7 @@ mod tests {
             Interface {
                 name: "eth0".to_owned(),
                 index: 0,
-                pinned_id: "0".to_owned(),
+                pinned_id: Some("0".to_owned()),
                 state: InterfaceState::Up,
                 driver: "dummy".to_owned(),
                 mac: "01:23:45:67:89:ab".to_owned(),
@@ -901,7 +908,7 @@ mod tests {
             Interface {
                 name: "eth0".to_owned(),
                 index: 0,
-                pinned_id: "0".to_owned(),
+                pinned_id: Some("0".to_owned()),
                 state: InterfaceState::Up,
                 driver: "dummy".to_owned(),
                 mac: "01:23:45:67:89:ab".to_owned(),
diff --git a/proxmox-installer-common/src/setup.rs b/proxmox-installer-common/src/setup.rs
index c93ee30..35949f0 100644
--- a/proxmox-installer-common/src/setup.rs
+++ b/proxmox-installer-common/src/setup.rs
@@ -465,8 +465,9 @@ pub struct Interface {
 
     pub index: usize,
 
-    /// Sequential interface ID for pinning interface names.
-    pub pinned_id: String,
+    /// Sequential interface ID for pinning interface names. If unset, the
+    /// interface name cannot/should not be pinned due to being e.g. a non-physical link.
+    pub pinned_id: Option<String>,
 
     pub mac: String,
 
@@ -492,19 +493,23 @@ impl Interface {
         )
     }
 
-    pub fn to_pinned(&self, options: &NetworkInterfacePinningOptions) -> Self {
-        let mut this = self.clone();
-        this.name = options
-            .mapping
-            .get(&this.mac)
-            .unwrap_or(&format!(
-                "{}{}",
-                NetworkInterfacePinningOptions::DEFAULT_PREFIX,
-                this.pinned_id
-            ))
-            .clone();
+    pub fn to_pinned(&self, options: &NetworkInterfacePinningOptions) -> Option<Self> {
+        if let Some(pinned_id) = &self.pinned_id {
+            let mut this = self.clone();
+            this.name = options
+                .mapping
+                .get(&this.mac)
+                .unwrap_or(&format!(
+                    "{}{}",
+                    NetworkInterfacePinningOptions::DEFAULT_PREFIX,
+                    pinned_id
+                ))
+                .clone();
 
-        this
+            Some(this)
+        } else {
+            None
+        }
     }
 }
 
diff --git a/proxmox-tui-installer/src/views/network.rs b/proxmox-tui-installer/src/views/network.rs
index 4388c7d..970c353 100644
--- a/proxmox-tui-installer/src/views/network.rs
+++ b/proxmox-tui-installer/src/views/network.rs
@@ -189,9 +189,12 @@ impl NetworkOptionsView {
             .map(|opt| opt.pinning_enabled.then_some(opt.pinning_options.clone()))
             .map_err(|err| err.to_string())?;
 
-        let ifname = match &pinning_opts {
-            Some(opts) => iface.to_pinned(opts).name,
-            None => iface.name,
+        let ifname = if let Some(opts) = &pinning_opts
+            && let Some(pinned) = iface.to_pinned(opts)
+        {
+            pinned.name
+        } else {
+            iface.name
         };
 
         if address.addr().is_ipv4() != gateway.is_ipv4() {
@@ -291,13 +294,13 @@ impl NetworkOptionsView {
         let ifnames = ifaces
             .iter()
             .map(|iface| {
-                let iface = if options.pinning_enabled {
-                    &iface.to_pinned(&options.pinning_options)
+                if options.pinning_enabled
+                    && let Some(pinned) = iface.to_pinned(&options.pinning_options)
+                {
+                    (pinned.render(), pinned.clone())
                 } else {
-                    iface
-                };
-
-                (iface.render(), iface.clone())
+                    (iface.render(), (*iface).clone())
+                }
             })
             .collect::<Vec<(String, Interface)>>();
 
@@ -337,6 +340,11 @@ impl InterfacePinningOptionsView {
     fn new(interfaces: &[&Interface], options_ref: NetworkViewOptionsRef) -> Self {
         let options = options_ref.lock().expect("unpoisoned lock");
 
+        // Filter out all non-physical links, as it does not make sense to pin their names
+        // in this way.
+        // The low-level installer will skip them anyway.
+        let interfaces = interfaces.iter().filter(|iface| iface.pinned_id.is_some());
+
         let mut form = FormView::<String>::new();
 
         for iface in interfaces {
@@ -349,7 +357,12 @@ impl InterfacePinningOptionsView {
                 .child(DummyView.full_width()) // right align below form elements
                 .child(
                     EditView::new()
-                        .content(iface.to_pinned(&options.pinning_options).name)
+                        .content(
+                            iface
+                                .to_pinned(&options.pinning_options)
+                                .expect("always pinnable interface")
+                                .name,
+                        )
                         .max_content_width(MAX_IFNAME_LEN)
                         .fixed_width(MAX_IFNAME_LEN),
                 );
-- 
2.51.0



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


  parent reply	other threads:[~2025-11-13 13:50 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-13 13:49 [pve-devel] [PATCH installer 0/6] interface name pinning followups Christoph Heiss
2025-11-13 13:49 ` [pve-devel] [PATCH installer 1/6] sys: net: pinning: make interface name checks stricter Christoph Heiss
2025-11-13 13:49 ` [pve-devel] [PATCH installer 2/6] common: " Christoph Heiss
2025-11-13 13:49 ` [pve-devel] [PATCH installer 3/6] test: validate-link-pin-map: give all tests a name Christoph Heiss
2025-11-13 13:49 ` [pve-devel] [PATCH installer 4/6] gui: network: only display pinnable devices in pinning options dialog Christoph Heiss
2025-11-13 13:49 ` Christoph Heiss [this message]
2025-11-13 13:49 ` [pve-devel] [PATCH installer 6/6] tree-wide: run cargo fmt Christoph Heiss
2025-11-13 20:00 ` [pve-devel] applied: [PATCH installer 0/6] interface name pinning followups Thomas Lamprecht

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251113135023.1038305-6-c.heiss@proxmox.com \
    --to=c.heiss@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal