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 56E0C1FF13A for ; Wed, 10 Jun 2026 15:27:22 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 470ECEF53; Wed, 10 Jun 2026 15:27:20 +0200 (CEST) From: Christoph Heiss To: pve-devel@lists.proxmox.com Subject: [PATCH installer 1/2] sys: net: make routes hash always defined Date: Wed, 10 Jun 2026 15:27:01 +0200 Message-ID: <20260610132710.199825-1-c.heiss@proxmox.com> X-Mailer: git-send-email 2.54.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1781097987302 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.075 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 URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [bar.com,options.rs,setup.rs,parse-answer.rs,net.pm] Message-ID-Hash: VIRFRTB6RIQYGGE57HLOQD74TVZYL3Q7 X-Message-ID-Hash: VIRFRTB6RIQYGGE57HLOQD74TVZYL3Q7 X-MailFrom: c.heiss@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: The 'dst' key was never set or used, so drop from subroutine documentation. This especially simplifies the network setup in Rust, dropping an additional (and unneeded) level of `Option<>`. No functional changes. Signed-off-by: Christoph Heiss --- Small cleanup patch. Optional, can be skipped if desired, i.e. the second patch does not depend on it. Proxmox/Sys/Net.pm | 12 +--- proxinstall | 2 +- proxmox-auto-installer/tests/parse-answer.rs | 1 + .../resources/parse_answer/no_network.json | 19 +++++ .../parse_answer/no_network.run-env.json | 45 ++++++++++++ .../resources/parse_answer/no_network.toml | 14 ++++ proxmox-installer-common/src/options.rs | 69 +++++++++---------- proxmox-installer-common/src/setup.rs | 2 +- 8 files changed, 118 insertions(+), 46 deletions(-) create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/no_network.json create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/no_network.run-env.json create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/no_network.toml diff --git a/Proxmox/Sys/Net.pm b/Proxmox/Sys/Net.pm index ed7744b..d175742 100644 --- a/Proxmox/Sys/Net.pm +++ b/Proxmox/Sys/Net.pm @@ -277,24 +277,22 @@ sub query_netdevs : prototype() { # # { # gateway4 => { -# dst => "default", # gateway => , # dev => , # }, # gateway6 => { -# dst => "default", # gateway => , # dev => , # }, # } sub query_routes : prototype() { - my ($gateway4, $gateway6); + my $routes = {}; log_info("query routes"); my $route4 = from_json(qx/ip -4 --json route show/, { utf8 => 1 }); for my $route (@$route4) { if ($route->{dst} eq 'default') { - $gateway4 = { + $routes->{gateway4} = { dev => $route->{dev}, gateway => $route->{gateway}, }; @@ -305,7 +303,7 @@ sub query_routes : prototype() { my $route6 = from_json(qx/ip -6 --json route show/, { utf8 => 1 }); for my $route (@$route6) { if ($route->{dst} eq 'default') { - $gateway6 = { + $routes->{gateway6} = { dev => $route->{dev}, gateway => $route->{gateway}, }; @@ -313,10 +311,6 @@ sub query_routes : prototype() { } } - my $routes; - $routes->{gateway4} = $gateway4 if $gateway4; - $routes->{gateway6} = $gateway6 if $gateway6; - return $routes; } diff --git a/proxinstall b/proxinstall index db95b8a..49b1612 100755 --- a/proxinstall +++ b/proxinstall @@ -435,7 +435,7 @@ sub create_ipconf_view { my $network = $run_env->{network}; # prefer ipv4 gateway and fallback to ipv6 - my $routes = $network->{routes} // {}; + my $routes = $network->{routes}; my $default_gateway = $routes->{gateway4} // $routes->{gateway6}; my $default_gateway_ipversion; diff --git a/proxmox-auto-installer/tests/parse-answer.rs b/proxmox-auto-installer/tests/parse-answer.rs index 675678a..8b0bae7 100644 --- a/proxmox-auto-installer/tests/parse-answer.rs +++ b/proxmox-auto-installer/tests/parse-answer.rs @@ -130,6 +130,7 @@ mod tests { network_interface_pinning, network_interface_pinning_uppercase_mac_address, nic_matching, + no_network, specific_nic, zfs, zfs_raid_level_uppercase, diff --git a/proxmox-auto-installer/tests/resources/parse_answer/no_network.json b/proxmox-auto-installer/tests/resources/parse_answer/no_network.json new file mode 100644 index 0000000..de5f263 --- /dev/null +++ b/proxmox-auto-installer/tests/resources/parse_answer/no_network.json @@ -0,0 +1,19 @@ +{ + "autoreboot": 1, + "cidr": "192.168.100.2/24", + "country": "at", + "dns": "192.168.100.1", + "domain": "test", + "filesys": "ext4", + "gateway": "192.168.100.1", + "hdsize": 223.57088470458984, + "existing_storage_auto_rename": 1, + "hostname": "no-gateways", + "keymap": "de", + "mailto": "mail@no.invalid", + "mngmt_nic": "eno1", + "root_password": { "plain": "12345678" }, + "target_hd": "/dev/sda", + "timezone": "Europe/Vienna", + "first_boot": { "enabled": 0 } +} diff --git a/proxmox-auto-installer/tests/resources/parse_answer/no_network.run-env.json b/proxmox-auto-installer/tests/resources/parse_answer/no_network.run-env.json new file mode 100644 index 0000000..9c7d2e3 --- /dev/null +++ b/proxmox-auto-installer/tests/resources/parse_answer/no_network.run-env.json @@ -0,0 +1,45 @@ +{ + "boot_type": "efi", + "country": "at", + "disks": [ + [ + 0, + "/dev/sda", + 468862128, + "SAMSUNG MZ7KM240", + 512, + "/sys/block/sda" + ] + ], + "hvm_supported": 1, + "kernel_cmdline": "BOOT_IMAGE=/boot/linux26 ro ramdisk_size=16777216 rw splash=verbose proxdebug vga=788", + "network": { + "hostname": "no-gateways.test", + "dns": { + "dns": [], + "domain": "test.local" + }, + "interfaces": { + "eno1": { + "addresses": [], + "index": 4, + "mac": "b4:2e:99:ac:ad:b4", + "name": "eno1", + "state": "UP", + "driver": "igb", + "pinned_id": "0" + }, + "eno2": { + "index": 6, + "mac": "b4:2e:99:ac:ad:b5", + "name": "eno2", + "state": "UP", + "driver": "igb", + "pinned_id": "1" + } + }, + "routes": {} + }, + "total_memory": 257597, + "default_zfs_arc_max": 128798 +} diff --git a/proxmox-auto-installer/tests/resources/parse_answer/no_network.toml b/proxmox-auto-installer/tests/resources/parse_answer/no_network.toml new file mode 100644 index 0000000..dc434fa --- /dev/null +++ b/proxmox-auto-installer/tests/resources/parse_answer/no_network.toml @@ -0,0 +1,14 @@ +[global] +keyboard = "de" +country = "at" +fqdn = "no-gateways.test" +mailto = "mail@no.invalid" +timezone = "Europe/Vienna" +root-password = "12345678" + +[network] +source = "from-dhcp" + +[disk-setup] +filesystem = "ext4" +disk-list = ["sda"] diff --git a/proxmox-installer-common/src/options.rs b/proxmox-installer-common/src/options.rs index 69ad217..c7f0baf 100644 --- a/proxmox-installer-common/src/options.rs +++ b/proxmox-installer-common/src/options.rs @@ -425,38 +425,34 @@ impl NetworkOptions { pinning_opts: pinning_opts.cloned(), }; - let iface = if let Some(routes) = &network.routes { - if let Some(gw) = &routes.gateway4 - && let Some(iface) = network.interfaces.get(&gw.dev) - { - this.gateway = gw.gateway; + let iface = if let Some(gw) = &network.routes.gateway4 + && let Some(iface) = network.interfaces.get(&gw.dev) + { + this.gateway = gw.gateway; - if let Some(addr) = iface.addresses.iter().find(|addr| addr.is_ipv4()) { - this.address = *addr; - } - - if let Some(addr) = network.dns.dns.iter().find(|addr| addr.is_ipv4()) { - this.dns_server = *addr; - } - - Some(iface) - } else if let Some(gw) = &routes.gateway6 - && let Some(iface) = network.interfaces.get(&gw.dev) - { - this.gateway = gw.gateway; - - if let Some(addr) = iface.addresses.iter().find(|addr| addr.is_ipv6()) { - this.address = *addr; - } - - if let Some(addr) = network.dns.dns.iter().find(|addr| addr.is_ipv6()) { - this.dns_server = *addr; - } - - Some(iface) - } else { - None + if let Some(addr) = iface.addresses.iter().find(|addr| addr.is_ipv4()) { + this.address = *addr; } + + if let Some(addr) = network.dns.dns.iter().find(|addr| addr.is_ipv4()) { + this.dns_server = *addr; + } + + Some(iface) + } else if let Some(gw) = &network.routes.gateway6 + && let Some(iface) = network.interfaces.get(&gw.dev) + { + this.gateway = gw.gateway; + + if let Some(addr) = iface.addresses.iter().find(|addr| addr.is_ipv6()) { + this.address = *addr; + } + + if let Some(addr) = network.dns.dns.iter().find(|addr| addr.is_ipv6()) { + this.dns_server = *addr; + } + + Some(iface) } else { None } @@ -623,13 +619,13 @@ mod tests { domain: Some("bar.com".to_owned()), dns: Vec::new(), }, - routes: Some(Routes { + routes: Routes { gateway4: Some(Gateway { dev: "eth0".to_owned(), gateway: IpAddr::V4(Ipv4Addr::new(192, 168, 0, 1)), }), gateway6: None, - }), + }, interfaces, hostname: Some("foo".to_owned()), }; @@ -717,13 +713,13 @@ mod tests { 0x2001, 0xdb8, 0, 0, 0, 0, 0, 0x53, ))], }, - routes: Some(Routes { + routes: Routes { gateway4: None, gateway6: Some(Gateway { dev: "eth0".to_owned(), gateway: IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)), }), - }), + }, interfaces, hostname: Some("foo".to_owned()), }; @@ -812,7 +808,10 @@ mod tests { domain: None, dns: vec![], }, - routes: None, + routes: Routes { + gateway4: None, + gateway6: None, + }, interfaces, hostname: None, }; diff --git a/proxmox-installer-common/src/setup.rs b/proxmox-installer-common/src/setup.rs index 4249794..b8af4e3 100644 --- a/proxmox-installer-common/src/setup.rs +++ b/proxmox-installer-common/src/setup.rs @@ -324,7 +324,7 @@ pub struct RuntimeInfo { #[derive(Clone, Deserialize)] pub struct NetworkInfo { pub dns: Dns, - pub routes: Option, + pub routes: Routes, /// Maps devices to their configuration, if it has a usable configuration. /// (Contains no entries for devices with only link-local addresses.) -- 2.54.0