[pve-devel] [PATCH installer 6/6] fix #5811: auto: add option to retrieve FQDN from DHCP configuration
Christoph Heiss
c.heiss at proxmox.com
Thu Mar 27 16:17:17 CET 2025
Fixes #5811 [0].
Adds a new option to the answer file for specifying to use the
DHCP-provided hostname and domain. For the domain, an additional
fallback/default can be specified, in case the DHCP server only provides
hostnames. The hostname is always required in this mode.
The addition to the answer file format is done in a backwards-compatible
way.
Users can now either directly specify the desired FQDN in the answer
file as before through
```
[global]
fqdn = "node.example.local"
```
or, with the new mechanism, if the DHCP server provides all the
information already:
```
[global]
fqdn.source = "from-dhcp"
```
or additionally with a custom domain:
```
[global.fqdn]
source = "from-dhcp"
domain = "custom.domain.local"
```
The DHCP-provided hostname and domain are already provided to the
auto-installer through the runtime environment, so its just a matter of
using them.
The test suite is extended quite a bit, to cover all the different
cases.
[0] https://bugzilla.proxmox.com/show_bug.cgi?id=5811
Signed-off-by: Christoph Heiss <c.heiss at proxmox.com>
---
proxmox-auto-installer/src/answer.rs | 36 +++++++++++++++++-
proxmox-auto-installer/src/utils.rs | 37 ++++++++++++++++---
proxmox-auto-installer/tests/parse-answer.rs | 8 ++++
.../parse_answer/fqdn_from_dhcp.json | 19 ++++++++++
.../parse_answer/fqdn_from_dhcp.toml | 14 +++++++
...cp_no_dhcp_domain_with_default_domain.json | 19 ++++++++++
...cp_no_dhcp_domain_with_default_domain.toml | 17 +++++++++
...ll_fqdn_from_dhcp_with_default_domain.json | 19 ++++++++++
...ll_fqdn_from_dhcp_with_default_domain.toml | 17 +++++++++
.../fqdn_from_dhcp_no_default_domain.json | 3 ++
...n_from_dhcp_no_default_domain.run-env.json | 1 +
.../fqdn_from_dhcp_no_default_domain.toml | 14 +++++++
.../parse_answer_fail/fqdn_hostname_only.json | 3 ++
.../parse_answer_fail/fqdn_hostname_only.toml | 14 +++++++
.../parse_answer_fail/no_fqdn_from_dhcp.json | 3 ++
.../no_fqdn_from_dhcp.run-env.json | 1 +
.../parse_answer_fail/no_fqdn_from_dhcp.toml | 14 +++++++
.../tests/resources/run-env-info.json | 2 +-
proxmox-post-hook/src/main.rs | 19 ++++++++--
19 files changed, 250 insertions(+), 10 deletions(-)
create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/fqdn_from_dhcp.json
create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/fqdn_from_dhcp.toml
create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/fqdn_from_dhcp_no_dhcp_domain_with_default_domain.json
create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/fqdn_from_dhcp_no_dhcp_domain_with_default_domain.toml
create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/full_fqdn_from_dhcp_with_default_domain.json
create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/full_fqdn_from_dhcp_with_default_domain.toml
create mode 100644 proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_from_dhcp_no_default_domain.json
create mode 100644 proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_from_dhcp_no_default_domain.run-env.json
create mode 100644 proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_from_dhcp_no_default_domain.toml
create mode 100644 proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_hostname_only.json
create mode 100644 proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_hostname_only.toml
create mode 100644 proxmox-auto-installer/tests/resources/parse_answer_fail/no_fqdn_from_dhcp.json
create mode 100644 proxmox-auto-installer/tests/resources/parse_answer_fail/no_fqdn_from_dhcp.run-env.json
create mode 100644 proxmox-auto-installer/tests/resources/parse_answer_fail/no_fqdn_from_dhcp.toml
diff --git a/proxmox-auto-installer/src/answer.rs b/proxmox-auto-installer/src/answer.rs
index c11818e..dd7fa06 100644
--- a/proxmox-auto-installer/src/answer.rs
+++ b/proxmox-auto-installer/src/answer.rs
@@ -46,7 +46,8 @@ impl Answer {
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct Global {
pub country: String,
- pub fqdn: Fqdn,
+ /// FQDN to set for the installed system.
+ pub fqdn: FqdnConfig,
pub keyboard: KeyboardLayout,
pub mailto: String,
pub timezone: String,
@@ -60,6 +61,39 @@ pub struct Global {
pub root_ssh_keys: Vec<String>,
}
+/// Allow the user to either set the FQDN of the installation to either some
+/// fixed value or retrieve it dynamically via e.g.DHCP.
+#[derive(Clone, Deserialize, Debug)]
+#[serde(
+ untagged,
+ expecting = "either a fully-qualified domain name or extendend configuration for usage with DHCP must be specified"
+)]
+pub enum FqdnConfig {
+ /// Sets the FQDN to the exact value.
+ Simple(Fqdn),
+ /// Extended configuration, e.g. to use hostname and domain from DHCP.
+ Extended(FqdnExtendedConfig),
+}
+
+/// Extended configuration for retrieving the FQDN from external sources.
+#[derive(Clone, Deserialize, Debug)]
+#[serde(rename_all = "kebab-case", deny_unknown_fields)]
+pub struct FqdnExtendedConfig {
+ /// Source to gather the FQDN from.
+ #[serde(default)]
+ pub source: FqdnSourceMode,
+ /// Domain to use if none is received via DHCP.
+ pub domain: Option<String>,
+}
+
+/// Describes the source to retrieve the FQDN of the installation.
+#[derive(Clone, Deserialize, Debug, Default, PartialEq)]
+#[serde(rename_all = "kebab-case", deny_unknown_fields)]
+pub enum FqdnSourceMode {
+ #[default]
+ FromDhcp,
+}
+
#[derive(Clone, Deserialize, Debug)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct PostNotificationHookInfo {
diff --git a/proxmox-auto-installer/src/utils.rs b/proxmox-auto-installer/src/utils.rs
index cf072b8..5bff8b2 100644
--- a/proxmox-auto-installer/src/utils.rs
+++ b/proxmox-auto-installer/src/utils.rs
@@ -5,7 +5,9 @@ use log::info;
use std::{collections::BTreeMap, process::Command};
use crate::{
- answer::{self, Answer, FirstBootHookSourceMode},
+ answer::{
+ self, Answer, FirstBootHookSourceMode, FqdnConfig, FqdnExtendedConfig, FqdnSourceMode,
+ },
udevinfo::UdevInfo,
};
use proxmox_installer_common::{
@@ -24,12 +26,37 @@ fn get_network_settings(
runtime_info: &RuntimeInfo,
setup_info: &SetupInfo,
) -> Result<NetworkOptions> {
- let mut network_options = NetworkOptions::defaults_from(setup_info, &runtime_info.network, None);
+ info!("Setting up network configuration");
- info!("Setting network configuration");
+ let mut network_options = match &answer.global.fqdn {
+ // If the user set a static FQDN in the answer file, override it
+ FqdnConfig::Simple(name) => {
+ let mut opts = NetworkOptions::defaults_from(setup_info, &runtime_info.network, None);
+ opts.fqdn = name.to_owned();
+ opts
+ }
+ FqdnConfig::Extended(FqdnExtendedConfig {
+ source: FqdnSourceMode::FromDhcp,
+ domain,
+ }) => {
+ // A FQDN from DHCP information and/or defaults is constructed in
+ // `NetworkOptions::defaults_from()` below, just check that the DHCP server actually
+ // provided a hostname.
+ if runtime_info.network.hostname.is_none() {
+ bail!(
+ "`global.fqdn.source` set to \"from-dhcp\", but DHCP server did not provide a hostname!"
+ );
+ }
- // Always use the FQDN from the answer file
- network_options.fqdn = answer.global.fqdn.clone();
+ // Either a domain must be received from the DHCP server or it must be set manually
+ // (even just as fallback) in the answer file.
+ if runtime_info.network.dns.domain.is_none() && domain.is_none() {
+ bail!("no domain received from DHCP server and `global.fqdn.domain` is unset!");
+ }
+
+ NetworkOptions::defaults_from(setup_info, &runtime_info.network, domain.as_deref())
+ }
+ };
if let answer::NetworkSettings::Manual(settings) = &answer.network.network_settings {
network_options.address = settings.cidr.clone();
diff --git a/proxmox-auto-installer/tests/parse-answer.rs b/proxmox-auto-installer/tests/parse-answer.rs
index 57e20b3..34bc969 100644
--- a/proxmox-auto-installer/tests/parse-answer.rs
+++ b/proxmox-auto-installer/tests/parse-answer.rs
@@ -116,12 +116,16 @@ mod tests {
declare_tests!(
run_named_test,
+ // Keep below entries alphabetically sorted
btrfs,
btrfs_raid_level_uppercase,
disk_match,
disk_match_all,
disk_match_any,
first_boot,
+ fqdn_from_dhcp,
+ fqdn_from_dhcp_no_dhcp_domain_with_default_domain,
+ full_fqdn_from_dhcp_with_default_domain,
hashed_root_password,
minimal,
nic_matching,
@@ -136,7 +140,11 @@ mod tests {
declare_tests!(
run_named_fail_parse_test,
+ // Keep below entries alphabetically sorted
both_password_and_hashed_set,
+ fqdn_from_dhcp_no_default_domain,
+ fqdn_hostname_only,
+ no_fqdn_from_dhcp,
no_root_password_set,
short_password
);
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/fqdn_from_dhcp.json b/proxmox-auto-installer/tests/resources/parse_answer/fqdn_from_dhcp.json
new file mode 100644
index 0000000..5ec6656
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer/fqdn_from_dhcp.json
@@ -0,0 +1,19 @@
+{
+ "autoreboot": 1,
+ "cidr": "192.168.1.114/24",
+ "country": "at",
+ "dns": "192.168.1.254",
+ "domain": "test.local",
+ "filesys": "ext4",
+ "gateway": "192.168.1.1",
+ "hdsize": 223.57088470458984,
+ "existing_storage_auto_rename": 1,
+ "hostname": "pveauto",
+ "keymap": "de",
+ "mailto": "mail at 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/fqdn_from_dhcp.toml b/proxmox-auto-installer/tests/resources/parse_answer/fqdn_from_dhcp.toml
new file mode 100644
index 0000000..9d13a5f
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer/fqdn_from_dhcp.toml
@@ -0,0 +1,14 @@
+[global]
+keyboard = "de"
+country = "at"
+fqdn.source = "from-dhcp"
+mailto = "mail at no.invalid"
+timezone = "Europe/Vienna"
+root_password = "12345678"
+
+[network]
+source = "from-dhcp"
+
+[disk-setup]
+filesystem = "ext4"
+disk_list = ["sda"]
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/fqdn_from_dhcp_no_dhcp_domain_with_default_domain.json b/proxmox-auto-installer/tests/resources/parse_answer/fqdn_from_dhcp_no_dhcp_domain_with_default_domain.json
new file mode 100644
index 0000000..7ed46a2
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer/fqdn_from_dhcp_no_dhcp_domain_with_default_domain.json
@@ -0,0 +1,19 @@
+{
+ "autoreboot": 1,
+ "cidr": "192.168.1.114/24",
+ "country": "at",
+ "dns": "192.168.1.254",
+ "domain": "custom.local",
+ "filesys": "ext4",
+ "gateway": "192.168.1.1",
+ "hdsize": 223.57088470458984,
+ "existing_storage_auto_rename": 1,
+ "hostname": "pveauto",
+ "keymap": "de",
+ "mailto": "mail at 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/fqdn_from_dhcp_no_dhcp_domain_with_default_domain.toml b/proxmox-auto-installer/tests/resources/parse_answer/fqdn_from_dhcp_no_dhcp_domain_with_default_domain.toml
new file mode 100644
index 0000000..8fbbede
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer/fqdn_from_dhcp_no_dhcp_domain_with_default_domain.toml
@@ -0,0 +1,17 @@
+[global]
+keyboard = "de"
+country = "at"
+mailto = "mail at no.invalid"
+timezone = "Europe/Vienna"
+root_password = "12345678"
+
+[global.fqdn]
+source = "from-dhcp"
+domain = "custom.local"
+
+[network]
+source = "from-dhcp"
+
+[disk-setup]
+filesystem = "ext4"
+disk_list = ["sda"]
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/full_fqdn_from_dhcp_with_default_domain.json b/proxmox-auto-installer/tests/resources/parse_answer/full_fqdn_from_dhcp_with_default_domain.json
new file mode 100644
index 0000000..7ed46a2
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer/full_fqdn_from_dhcp_with_default_domain.json
@@ -0,0 +1,19 @@
+{
+ "autoreboot": 1,
+ "cidr": "192.168.1.114/24",
+ "country": "at",
+ "dns": "192.168.1.254",
+ "domain": "custom.local",
+ "filesys": "ext4",
+ "gateway": "192.168.1.1",
+ "hdsize": 223.57088470458984,
+ "existing_storage_auto_rename": 1,
+ "hostname": "pveauto",
+ "keymap": "de",
+ "mailto": "mail at 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/full_fqdn_from_dhcp_with_default_domain.toml b/proxmox-auto-installer/tests/resources/parse_answer/full_fqdn_from_dhcp_with_default_domain.toml
new file mode 100644
index 0000000..8fbbede
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer/full_fqdn_from_dhcp_with_default_domain.toml
@@ -0,0 +1,17 @@
+[global]
+keyboard = "de"
+country = "at"
+mailto = "mail at no.invalid"
+timezone = "Europe/Vienna"
+root_password = "12345678"
+
+[global.fqdn]
+source = "from-dhcp"
+domain = "custom.local"
+
+[network]
+source = "from-dhcp"
+
+[disk-setup]
+filesystem = "ext4"
+disk_list = ["sda"]
diff --git a/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_from_dhcp_no_default_domain.json b/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_from_dhcp_no_default_domain.json
new file mode 100644
index 0000000..da7850f
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_from_dhcp_no_default_domain.json
@@ -0,0 +1,3 @@
+{
+ "error": "no domain received from DHCP server and `global.fqdn.domain` is unset!"
+}
diff --git a/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_from_dhcp_no_default_domain.run-env.json b/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_from_dhcp_no_default_domain.run-env.json
new file mode 100644
index 0000000..eb17092
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_from_dhcp_no_default_domain.run-env.json
@@ -0,0 +1 @@
+{"boot_type":"efi","country":"at","disks":[[0,"/dev/nvme0n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme0n1"],[1,"/dev/nvme1n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme1n1"],[2,"/dev/nvme2n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme2n1"],[3,"/dev/nvme3n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme3n1"],[4,"/dev/nvme4n1",976773168,"Samsung SSD 970 EVO Plus 500GB",512,"/sys/block/nvme4n1"],[5,"/dev/nvme5n1",732585168,"INTEL SSDPED1K375GA",512,"/sys/block/nvme5n1"],[6,"/dev/sda",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sda"],[7,"/dev/sdb",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sdb"],[8,"/dev/sdc",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sdc"],[9,"/dev/sdd",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sdd"]],"hvm_supported":1,"ipconf":{"default":"4","dnsserver":"192.168.1.254","domain":null,"gateway":"192.168.1.1","ifaces":{"10":{"driver":"mlx5_core","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"24:8a:07:1e:05:bd","name":"enp193s0f1np1","state":"DOWN"},"2":{"driver":"igb","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"a0:36:9f:0a:b3:82","name":"enp65s0f0","state":"DOWN"},"3":{"driver":"igb","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"a0:36:9f:0a:b3:83","name":"enp65s0f1","state":"DOWN"},"4":{"driver":"igb","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","inet":{"addr":"192.168.1.114","mask":"255.255.240.0","prefix":20},"mac":"b4:2e:99:ac:ad:b4","name":"eno1","state":"UP"},"5":{"driver":"cdc_ether","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","mac":"5a:47:32:dd:c7:47","name":"enx5a4732ddc747","state":"UNKNOWN"},"6":{"driver":"igb","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","mac":"b4:2e:99:ac:ad:b5","name":"eno2","state":"UP"},"7":{"driver":"mlx5_core","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"1c:34:da:5c:5e:24","name":"enp129s0f0np0","state":"DOWN"},"8":{"driver":"mlx5_core","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"1c:34:da:5c:5e:25","name":"enp129s0f1np1","state":"DOWN"},"9":{"driver":"mlx5_core","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","mac":"24:8a:07:1e:05:bc","name":"enp193s0f0np0","state":"UP"}}},"kernel_cmdline":"BOOT_IMAGE=/boot/linux26 ro ramdisk_size=16777216 rw splash=verbose proxdebug vga=788","network":{"hostname":"pveauto","dns":{"dns":["192.168.1.254"],"domain":null},"interfaces":{"eno1":{"addresses":[{"address":"192.168.1.114","family":"inet","prefix":24}],"index":4,"mac":"b4:2e:99:ac:ad:b4","name":"eno1","state":"UP"},"eno2":{"index":6,"mac":"b4:2e:99:ac:ad:b5","name":"eno2","state":"UP"},"enp129s0f0np0":{"index":7,"mac":"1c:34:da:5c:5e:24","name":"enp129s0f0np0","state":"DOWN"},"enp129s0f1np1":{"index":8,"mac":"1c:34:da:5c:5e:25","name":"enp129s0f1np1","state":"DOWN"},"enp193s0f0np0":{"index":9,"mac":"24:8a:07:1e:05:bc","name":"enp193s0f0np0","state":"UP"},"enp193s0f1np1":{"index":10,"mac":"24:8a:07:1e:05:bd","name":"enp193s0f1np1","state":"DOWN"},"enp65s0f0":{"index":2,"mac":"a0:36:9f:0a:b3:82","name":"enp65s0f0","state":"DOWN"},"enp65s0f1":{"index":3,"mac":"a0:36:9f:0a:b3:83","name":"enp65s0f1","state":"DOWN"},"enx5a4732ddc747":{"index":5,"mac":"5a:47:32:dd:c7:47","name":"enx5a4732ddc747","state":"UNKNOWN"}},"routes":{"gateway4":{"dev":"eno1","gateway":"192.168.1.1"}}},"total_memory":257597}
diff --git a/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_from_dhcp_no_default_domain.toml b/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_from_dhcp_no_default_domain.toml
new file mode 100644
index 0000000..9d13a5f
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_from_dhcp_no_default_domain.toml
@@ -0,0 +1,14 @@
+[global]
+keyboard = "de"
+country = "at"
+fqdn.source = "from-dhcp"
+mailto = "mail at no.invalid"
+timezone = "Europe/Vienna"
+root_password = "12345678"
+
+[network]
+source = "from-dhcp"
+
+[disk-setup]
+filesystem = "ext4"
+disk_list = ["sda"]
diff --git a/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_hostname_only.json b/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_hostname_only.json
new file mode 100644
index 0000000..5293b40
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_hostname_only.json
@@ -0,0 +1,3 @@
+{
+ "parse-error": "error parsing answer.toml: either a fully-qualified domain name or extendend configuration for usage with DHCP must be specified"
+}
diff --git a/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_hostname_only.toml b/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_hostname_only.toml
new file mode 100644
index 0000000..a0a22ef
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer_fail/fqdn_hostname_only.toml
@@ -0,0 +1,14 @@
+[global]
+keyboard = "de"
+country = "at"
+fqdn = "foobar"
+mailto = "mail at no.invalid"
+timezone = "Europe/Vienna"
+root_password = "12345678"
+
+[network]
+source = "from-dhcp"
+
+[disk-setup]
+filesystem = "ext4"
+disk_list = ["sda"]
diff --git a/proxmox-auto-installer/tests/resources/parse_answer_fail/no_fqdn_from_dhcp.json b/proxmox-auto-installer/tests/resources/parse_answer_fail/no_fqdn_from_dhcp.json
new file mode 100644
index 0000000..49a64e5
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer_fail/no_fqdn_from_dhcp.json
@@ -0,0 +1,3 @@
+{
+ "error": "`global.fqdn.source` set to \"from-dhcp\", but DHCP server did not provide a hostname!"
+}
diff --git a/proxmox-auto-installer/tests/resources/parse_answer_fail/no_fqdn_from_dhcp.run-env.json b/proxmox-auto-installer/tests/resources/parse_answer_fail/no_fqdn_from_dhcp.run-env.json
new file mode 100644
index 0000000..6762470
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer_fail/no_fqdn_from_dhcp.run-env.json
@@ -0,0 +1 @@
+{"boot_type":"efi","country":"at","disks":[[0,"/dev/nvme0n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme0n1"],[1,"/dev/nvme1n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme1n1"],[2,"/dev/nvme2n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme2n1"],[3,"/dev/nvme3n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme3n1"],[4,"/dev/nvme4n1",976773168,"Samsung SSD 970 EVO Plus 500GB",512,"/sys/block/nvme4n1"],[5,"/dev/nvme5n1",732585168,"INTEL SSDPED1K375GA",512,"/sys/block/nvme5n1"],[6,"/dev/sda",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sda"],[7,"/dev/sdb",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sdb"],[8,"/dev/sdc",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sdc"],[9,"/dev/sdd",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sdd"]],"hvm_supported":1,"ipconf":{"default":"4","dnsserver":"192.168.1.254","domain":null,"gateway":"192.168.1.1","ifaces":{"10":{"driver":"mlx5_core","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"24:8a:07:1e:05:bd","name":"enp193s0f1np1","state":"DOWN"},"2":{"driver":"igb","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"a0:36:9f:0a:b3:82","name":"enp65s0f0","state":"DOWN"},"3":{"driver":"igb","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"a0:36:9f:0a:b3:83","name":"enp65s0f1","state":"DOWN"},"4":{"driver":"igb","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","inet":{"addr":"192.168.1.114","mask":"255.255.240.0","prefix":20},"mac":"b4:2e:99:ac:ad:b4","name":"eno1","state":"UP"},"5":{"driver":"cdc_ether","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","mac":"5a:47:32:dd:c7:47","name":"enx5a4732ddc747","state":"UNKNOWN"},"6":{"driver":"igb","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","mac":"b4:2e:99:ac:ad:b5","name":"eno2","state":"UP"},"7":{"driver":"mlx5_core","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"1c:34:da:5c:5e:24","name":"enp129s0f0np0","state":"DOWN"},"8":{"driver":"mlx5_core","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"1c:34:da:5c:5e:25","name":"enp129s0f1np1","state":"DOWN"},"9":{"driver":"mlx5_core","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","mac":"24:8a:07:1e:05:bc","name":"enp193s0f0np0","state":"UP"}}},"kernel_cmdline":"BOOT_IMAGE=/boot/linux26 ro ramdisk_size=16777216 rw splash=verbose proxdebug vga=788","network":{"dns":{"dns":["192.168.1.254"],"domain":null},"interfaces":{"eno1":{"addresses":[{"address":"192.168.1.114","family":"inet","prefix":24}],"index":4,"mac":"b4:2e:99:ac:ad:b4","name":"eno1","state":"UP"},"eno2":{"index":6,"mac":"b4:2e:99:ac:ad:b5","name":"eno2","state":"UP"},"enp129s0f0np0":{"index":7,"mac":"1c:34:da:5c:5e:24","name":"enp129s0f0np0","state":"DOWN"},"enp129s0f1np1":{"index":8,"mac":"1c:34:da:5c:5e:25","name":"enp129s0f1np1","state":"DOWN"},"enp193s0f0np0":{"index":9,"mac":"24:8a:07:1e:05:bc","name":"enp193s0f0np0","state":"UP"},"enp193s0f1np1":{"index":10,"mac":"24:8a:07:1e:05:bd","name":"enp193s0f1np1","state":"DOWN"},"enp65s0f0":{"index":2,"mac":"a0:36:9f:0a:b3:82","name":"enp65s0f0","state":"DOWN"},"enp65s0f1":{"index":3,"mac":"a0:36:9f:0a:b3:83","name":"enp65s0f1","state":"DOWN"},"enx5a4732ddc747":{"index":5,"mac":"5a:47:32:dd:c7:47","name":"enx5a4732ddc747","state":"UNKNOWN"}},"routes":{"gateway4":{"dev":"eno1","gateway":"192.168.1.1"}}},"total_memory":257597}
diff --git a/proxmox-auto-installer/tests/resources/parse_answer_fail/no_fqdn_from_dhcp.toml b/proxmox-auto-installer/tests/resources/parse_answer_fail/no_fqdn_from_dhcp.toml
new file mode 100644
index 0000000..9d13a5f
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer_fail/no_fqdn_from_dhcp.toml
@@ -0,0 +1,14 @@
+[global]
+keyboard = "de"
+country = "at"
+fqdn.source = "from-dhcp"
+mailto = "mail at no.invalid"
+timezone = "Europe/Vienna"
+root_password = "12345678"
+
+[network]
+source = "from-dhcp"
+
+[disk-setup]
+filesystem = "ext4"
+disk_list = ["sda"]
diff --git a/proxmox-auto-installer/tests/resources/run-env-info.json b/proxmox-auto-installer/tests/resources/run-env-info.json
index 6762470..2687a8a 100644
--- a/proxmox-auto-installer/tests/resources/run-env-info.json
+++ b/proxmox-auto-installer/tests/resources/run-env-info.json
@@ -1 +1 @@
-{"boot_type":"efi","country":"at","disks":[[0,"/dev/nvme0n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme0n1"],[1,"/dev/nvme1n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme1n1"],[2,"/dev/nvme2n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme2n1"],[3,"/dev/nvme3n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme3n1"],[4,"/dev/nvme4n1",976773168,"Samsung SSD 970 EVO Plus 500GB",512,"/sys/block/nvme4n1"],[5,"/dev/nvme5n1",732585168,"INTEL SSDPED1K375GA",512,"/sys/block/nvme5n1"],[6,"/dev/sda",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sda"],[7,"/dev/sdb",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sdb"],[8,"/dev/sdc",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sdc"],[9,"/dev/sdd",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sdd"]],"hvm_supported":1,"ipconf":{"default":"4","dnsserver":"192.168.1.254","domain":null,"gateway":"192.168.1.1","ifaces":{"10":{"driver":"mlx5_core","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"24:8a:07:1e:05:bd","name":"enp193s0f1np1","state":"DOWN"},"2":{"driver":"igb","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"a0:36:9f:0a:b3:82","name":"enp65s0f0","state":"DOWN"},"3":{"driver":"igb","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"a0:36:9f:0a:b3:83","name":"enp65s0f1","state":"DOWN"},"4":{"driver":"igb","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","inet":{"addr":"192.168.1.114","mask":"255.255.240.0","prefix":20},"mac":"b4:2e:99:ac:ad:b4","name":"eno1","state":"UP"},"5":{"driver":"cdc_ether","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","mac":"5a:47:32:dd:c7:47","name":"enx5a4732ddc747","state":"UNKNOWN"},"6":{"driver":"igb","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","mac":"b4:2e:99:ac:ad:b5","name":"eno2","state":"UP"},"7":{"driver":"mlx5_core","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"1c:34:da:5c:5e:24","name":"enp129s0f0np0","state":"DOWN"},"8":{"driver":"mlx5_core","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"1c:34:da:5c:5e:25","name":"enp129s0f1np1","state":"DOWN"},"9":{"driver":"mlx5_core","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","mac":"24:8a:07:1e:05:bc","name":"enp193s0f0np0","state":"UP"}}},"kernel_cmdline":"BOOT_IMAGE=/boot/linux26 ro ramdisk_size=16777216 rw splash=verbose proxdebug vga=788","network":{"dns":{"dns":["192.168.1.254"],"domain":null},"interfaces":{"eno1":{"addresses":[{"address":"192.168.1.114","family":"inet","prefix":24}],"index":4,"mac":"b4:2e:99:ac:ad:b4","name":"eno1","state":"UP"},"eno2":{"index":6,"mac":"b4:2e:99:ac:ad:b5","name":"eno2","state":"UP"},"enp129s0f0np0":{"index":7,"mac":"1c:34:da:5c:5e:24","name":"enp129s0f0np0","state":"DOWN"},"enp129s0f1np1":{"index":8,"mac":"1c:34:da:5c:5e:25","name":"enp129s0f1np1","state":"DOWN"},"enp193s0f0np0":{"index":9,"mac":"24:8a:07:1e:05:bc","name":"enp193s0f0np0","state":"UP"},"enp193s0f1np1":{"index":10,"mac":"24:8a:07:1e:05:bd","name":"enp193s0f1np1","state":"DOWN"},"enp65s0f0":{"index":2,"mac":"a0:36:9f:0a:b3:82","name":"enp65s0f0","state":"DOWN"},"enp65s0f1":{"index":3,"mac":"a0:36:9f:0a:b3:83","name":"enp65s0f1","state":"DOWN"},"enx5a4732ddc747":{"index":5,"mac":"5a:47:32:dd:c7:47","name":"enx5a4732ddc747","state":"UNKNOWN"}},"routes":{"gateway4":{"dev":"eno1","gateway":"192.168.1.1"}}},"total_memory":257597}
+{"boot_type":"efi","country":"at","disks":[[0,"/dev/nvme0n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme0n1"],[1,"/dev/nvme1n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme1n1"],[2,"/dev/nvme2n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme2n1"],[3,"/dev/nvme3n1",6251233968,"Micron_9300_MTFDHAL3T2TDR",4096,"/sys/block/nvme3n1"],[4,"/dev/nvme4n1",976773168,"Samsung SSD 970 EVO Plus 500GB",512,"/sys/block/nvme4n1"],[5,"/dev/nvme5n1",732585168,"INTEL SSDPED1K375GA",512,"/sys/block/nvme5n1"],[6,"/dev/sda",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sda"],[7,"/dev/sdb",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sdb"],[8,"/dev/sdc",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sdc"],[9,"/dev/sdd",468862128,"SAMSUNG MZ7KM240",512,"/sys/block/sdd"]],"hvm_supported":1,"ipconf":{"default":"4","dnsserver":"192.168.1.254","domain":"test.local","gateway":"192.168.1.1","ifaces":{"10":{"driver":"mlx5_core","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"24:8a:07:1e:05:bd","name":"enp193s0f1np1","state":"DOWN"},"2":{"driver":"igb","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"a0:36:9f:0a:b3:82","name":"enp65s0f0","state":"DOWN"},"3":{"driver":"igb","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"a0:36:9f:0a:b3:83","name":"enp65s0f1","state":"DOWN"},"4":{"driver":"igb","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","inet":{"addr":"192.168.1.114","mask":"255.255.240.0","prefix":20},"mac":"b4:2e:99:ac:ad:b4","name":"eno1","state":"UP"},"5":{"driver":"cdc_ether","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","mac":"5a:47:32:dd:c7:47","name":"enx5a4732ddc747","state":"UNKNOWN"},"6":{"driver":"igb","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","mac":"b4:2e:99:ac:ad:b5","name":"eno2","state":"UP"},"7":{"driver":"mlx5_core","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"1c:34:da:5c:5e:24","name":"enp129s0f0np0","state":"DOWN"},"8":{"driver":"mlx5_core","flags":"NO-CARRIER,BROADCAST,MULTICAST,UP","mac":"1c:34:da:5c:5e:25","name":"enp129s0f1np1","state":"DOWN"},"9":{"driver":"mlx5_core","flags":"BROADCAST,MULTICAST,UP,LOWER_UP","mac":"24:8a:07:1e:05:bc","name":"enp193s0f0np0","state":"UP"}}},"kernel_cmdline":"BOOT_IMAGE=/boot/linux26 ro ramdisk_size=16777216 rw splash=verbose proxdebug vga=788","network":{"hostname":"pveauto","dns":{"dns":["192.168.1.254"],"domain":"test.local"},"interfaces":{"eno1":{"addresses":[{"address":"192.168.1.114","family":"inet","prefix":24}],"index":4,"mac":"b4:2e:99:ac:ad:b4","name":"eno1","state":"UP"},"eno2":{"index":6,"mac":"b4:2e:99:ac:ad:b5","name":"eno2","state":"UP"},"enp129s0f0np0":{"index":7,"mac":"1c:34:da:5c:5e:24","name":"enp129s0f0np0","state":"DOWN"},"enp129s0f1np1":{"index":8,"mac":"1c:34:da:5c:5e:25","name":"enp129s0f1np1","state":"DOWN"},"enp193s0f0np0":{"index":9,"mac":"24:8a:07:1e:05:bc","name":"enp193s0f0np0","state":"UP"},"enp193s0f1np1":{"index":10,"mac":"24:8a:07:1e:05:bd","name":"enp193s0f1np1","state":"DOWN"},"enp65s0f0":{"index":2,"mac":"a0:36:9f:0a:b3:82","name":"enp65s0f0","state":"DOWN"},"enp65s0f1":{"index":3,"mac":"a0:36:9f:0a:b3:83","name":"enp65s0f1","state":"DOWN"},"enx5a4732ddc747":{"index":5,"mac":"5a:47:32:dd:c7:47","name":"enx5a4732ddc747","state":"UNKNOWN"}},"routes":{"gateway4":{"dev":"eno1","gateway":"192.168.1.1"}}},"total_memory":257597}
diff --git a/proxmox-post-hook/src/main.rs b/proxmox-post-hook/src/main.rs
index d03ce21..959a0d7 100644
--- a/proxmox-post-hook/src/main.rs
+++ b/proxmox-post-hook/src/main.rs
@@ -21,11 +21,11 @@ use std::{
use anyhow::{Context, Result, anyhow, bail};
use proxmox_auto_installer::{
- answer::{Answer, PostNotificationHookInfo},
+ answer::{Answer, FqdnConfig, FqdnExtendedConfig, FqdnSourceMode, PostNotificationHookInfo},
udevinfo::{UdevInfo, UdevProperties},
};
use proxmox_installer_common::{
- options::{Disk, FsType},
+ options::{Disk, FsType, NetworkOptions},
setup::{
BootType, InstallConfig, IsoInfo, ProxmoxProduct, RuntimeInfo, SetupInfo,
load_installer_setup_files,
@@ -247,6 +247,19 @@ impl PostHookInfo {
.and_then(|r| Ok(String::from_utf8(r.stdout)?))
};
+ let fqdn = match &answer.global.fqdn {
+ FqdnConfig::Simple(name) => name.to_string(),
+ FqdnConfig::Extended(FqdnExtendedConfig {
+ source: FqdnSourceMode::FromDhcp,
+ domain,
+ }) => NetworkOptions::construct_fqdn(
+ &run_env.network,
+ setup_info.config.product.default_hostname(),
+ domain.as_deref(),
+ )
+ .to_string(),
+ };
+
Ok(Self {
schema: PostHookInfoSchema::default(),
debian_version: read_file("/etc/debian_version")?,
@@ -260,7 +273,7 @@ impl PostHookInfo {
cpu_info: Self::gather_cpu_info(&run_env)?,
dmi: SystemDMI::get()?,
filesystem: answer.disks.fs_type,
- fqdn: answer.global.fqdn.to_string(),
+ fqdn,
machine_id: read_file("/etc/machine-id")?,
disks: Self::gather_disks(&config, &run_env, &udev)?,
network_interfaces: Self::gather_nic(&config, &run_env, &udev)?,
--
2.48.1
More information about the pve-devel
mailing list