[pve-devel] [PATCH installer v2 2/5] fix #5579: setup: introduce 'first_boot' low-level installer options

Christoph Heiss c.heiss at proxmox.com
Mon Nov 18 13:38:38 CET 2024


.. to enable the setup of the 'proxmox-first-boot' service, as well as
optionally setting the ordering.

Signed-off-by: Christoph Heiss <c.heiss at proxmox.com>
---
Changes v1 -> v2:
  * add tests
  * introduce `first_boot.enabled` low-level option to tell the
    installer explicitly about it

 Proxmox/Install/Config.pm                     | 20 +++++++++++++++++++
 proxmox-auto-installer/src/utils.rs           |  6 ++++--
 .../tests/resources/parse_answer/btrfs.json   |  3 ++-
 .../resources/parse_answer/disk_match.json    |  3 ++-
 .../parse_answer/disk_match_all.json          |  3 ++-
 .../parse_answer/disk_match_any.json          |  3 ++-
 .../resources/parse_answer/first-boot.json    | 19 ++++++++++++++++++
 .../resources/parse_answer/first-boot.toml    | 18 +++++++++++++++++
 .../parse_answer/hashed_root_password.json    |  3 ++-
 .../tests/resources/parse_answer/minimal.json |  3 ++-
 .../resources/parse_answer/nic_matching.json  |  3 ++-
 .../resources/parse_answer/specific_nic.json  |  3 ++-
 .../tests/resources/parse_answer/zfs.json     |  3 ++-
 proxmox-installer-common/src/setup.rs         | 17 ++++++++++++++++
 proxmox-tui-installer/src/setup.rs            |  4 +++-
 15 files changed, 99 insertions(+), 12 deletions(-)
 create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/first-boot.json
 create mode 100644 proxmox-auto-installer/tests/resources/parse_answer/first-boot.toml

diff --git a/Proxmox/Install/Config.pm b/Proxmox/Install/Config.pm
index 6d47b75..b3a257e 100644
--- a/Proxmox/Install/Config.pm
+++ b/Proxmox/Install/Config.pm
@@ -111,6 +111,14 @@ my sub init_cfg {
 	gateway => undef,
 	dns => undef,
 	target_cmdline => undef,
+
+	# proxmox-first-boot setup
+	first_boot => {
+	    enabled => 0,
+	    # Must be kept in sync with proxmox_auto_installer::answer::FirstBootHookServiceOrdering
+	    # and the service files in the proxmox-first-boot package
+	    ordering_target => 'multi-user', # one of `network-pre`, `network-online` or `multi-user`
+	},
     };
 
     $initial = parse_kernel_cmdline($initial);
@@ -279,4 +287,16 @@ sub get_target_cmdline { return get('target_cmdline'); }
 sub set_existing_storage_auto_rename { set_key('existing_storage_auto_rename', $_[0]); }
 sub get_existing_storage_auto_rename { return get('existing_storage_auto_rename'); }
 
+sub set_first_boot_opt {
+    my ($k, $v) = @_;
+    my $opts = get('first_boot');
+    croak "unknown first boot override key '$k'" if !exists($opts->{$k});
+    $opts->{$k} = $v;
+}
+sub get_first_boot_opt {
+    my ($k) = @_;
+    my $opts = get('first_boot');
+    return defined($k) ? $opts->{$k} : $opts;
+}
+
 1;
diff --git a/proxmox-auto-installer/src/utils.rs b/proxmox-auto-installer/src/utils.rs
index dd686c0..9c399a5 100644
--- a/proxmox-auto-installer/src/utils.rs
+++ b/proxmox-auto-installer/src/utils.rs
@@ -11,8 +11,8 @@ use crate::{
 use proxmox_installer_common::{
     options::{email_validate, FsType, NetworkOptions, ZfsChecksumOption, ZfsCompressOption},
     setup::{
-        InstallBtrfsOption, InstallConfig, InstallRootPassword, InstallZfsOption, LocaleInfo,
-        RuntimeInfo, SetupInfo,
+        InstallBtrfsOption, InstallConfig, InstallFirstBootSetup, InstallRootPassword,
+        InstallZfsOption, LocaleInfo, RuntimeInfo, SetupInfo,
     },
 };
 use serde::{Deserialize, Serialize};
@@ -374,6 +374,8 @@ pub fn parse_answer(
         cidr: network_settings.address,
         gateway: network_settings.gateway,
         dns: network_settings.dns_server,
+
+        first_boot: InstallFirstBootSetup::default(),
     };
 
     set_disks(answer, udev_info, runtime_info, &mut config)?;
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/btrfs.json b/proxmox-auto-installer/tests/resources/parse_answer/btrfs.json
index 0330a38..de4c6e5 100644
--- a/proxmox-auto-installer/tests/resources/parse_answer/btrfs.json
+++ b/proxmox-auto-installer/tests/resources/parse_answer/btrfs.json
@@ -20,5 +20,6 @@
   "timezone": "Europe/Vienna",
   "btrfs_opts": {
     "compress": "zlib"
-  }
+  },
+  "first_boot": { "enabled": 0 }
 }
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/disk_match.json b/proxmox-auto-installer/tests/resources/parse_answer/disk_match.json
index 6c8d6d9..48a82e6 100644
--- a/proxmox-auto-installer/tests/resources/parse_answer/disk_match.json
+++ b/proxmox-auto-installer/tests/resources/parse_answer/disk_match.json
@@ -26,5 +26,6 @@
       "checksum": "on",
       "compress": "on",
       "copies": 1
-  }
+  },
+  "first_boot": { "enabled": 0 }
 }
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/disk_match_all.json b/proxmox-auto-installer/tests/resources/parse_answer/disk_match_all.json
index 2d2e94e..f012eb1 100644
--- a/proxmox-auto-installer/tests/resources/parse_answer/disk_match_all.json
+++ b/proxmox-auto-installer/tests/resources/parse_answer/disk_match_all.json
@@ -23,5 +23,6 @@
       "checksum": "on",
       "compress": "on",
       "copies": 1
-  }
+  },
+  "first_boot": { "enabled": 0 }
 }
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/disk_match_any.json b/proxmox-auto-installer/tests/resources/parse_answer/disk_match_any.json
index 1f3b2eb..ad3e304 100644
--- a/proxmox-auto-installer/tests/resources/parse_answer/disk_match_any.json
+++ b/proxmox-auto-installer/tests/resources/parse_answer/disk_match_any.json
@@ -30,5 +30,6 @@
       "checksum": "on",
       "compress": "on",
       "copies": 1
-  }
+  },
+  "first_boot": { "enabled": 0 }
 }
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/first-boot.json b/proxmox-auto-installer/tests/resources/parse_answer/first-boot.json
new file mode 100644
index 0000000..ff3f859
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer/first-boot.json
@@ -0,0 +1,19 @@
+{
+  "autoreboot": 1,
+  "cidr": "192.168.1.114/24",
+  "country": "at",
+  "dns": "192.168.1.254",
+  "domain": "testinstall",
+  "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": "123456" },
+  "target_hd": "/dev/sda",
+  "timezone": "Europe/Vienna",
+  "first_boot": { "enabled": 1, "ordering_target": "network-pre" }
+}
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/first-boot.toml b/proxmox-auto-installer/tests/resources/parse_answer/first-boot.toml
new file mode 100644
index 0000000..75c6a5d
--- /dev/null
+++ b/proxmox-auto-installer/tests/resources/parse_answer/first-boot.toml
@@ -0,0 +1,18 @@
+[global]
+keyboard = "de"
+country = "at"
+fqdn = "pveauto.testinstall"
+mailto = "mail at no.invalid"
+timezone = "Europe/Vienna"
+root_password = "123456"
+
+[first-boot]
+source = "from-iso"
+ordering = "before-network"
+
+[network]
+source = "from-dhcp"
+
+[disk-setup]
+filesystem = "ext4"
+disk_list = ["sda"]
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/hashed_root_password.json b/proxmox-auto-installer/tests/resources/parse_answer/hashed_root_password.json
index 4cae547..4e049bd 100644
--- a/proxmox-auto-installer/tests/resources/parse_answer/hashed_root_password.json
+++ b/proxmox-auto-installer/tests/resources/parse_answer/hashed_root_password.json
@@ -16,5 +16,6 @@
     "hashed": "$y$j9T$VgMv8lsz/TEvzesCZU3xD.$SK.h4QW51Jr/EmjuaTz5Bt4kYiX2Iezz6omzoqVEwj9"
   },
   "target_hd": "/dev/sda",
-  "timezone": "Europe/Vienna"
+  "timezone": "Europe/Vienna",
+  "first_boot": { "enabled": 0 }
 }
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/minimal.json b/proxmox-auto-installer/tests/resources/parse_answer/minimal.json
index 9fe9150..62b45c9 100644
--- a/proxmox-auto-installer/tests/resources/parse_answer/minimal.json
+++ b/proxmox-auto-installer/tests/resources/parse_answer/minimal.json
@@ -14,5 +14,6 @@
   "mngmt_nic": "eno1",
   "root_password": { "plain": "123456" },
   "target_hd": "/dev/sda",
-  "timezone": "Europe/Vienna"
+  "timezone": "Europe/Vienna",
+  "first_boot": { "enabled": 0 }
 }
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/nic_matching.json b/proxmox-auto-installer/tests/resources/parse_answer/nic_matching.json
index 610060e..e8b5424 100644
--- a/proxmox-auto-installer/tests/resources/parse_answer/nic_matching.json
+++ b/proxmox-auto-installer/tests/resources/parse_answer/nic_matching.json
@@ -14,5 +14,6 @@
   "mngmt_nic": "enp65s0f0",
   "root_password": { "plain": "123456" },
   "target_hd": "/dev/sda",
-  "timezone": "Europe/Vienna"
+  "timezone": "Europe/Vienna",
+  "first_boot": { "enabled": 0 }
 }
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/specific_nic.json b/proxmox-auto-installer/tests/resources/parse_answer/specific_nic.json
index 5f456bb..a5a4e0b 100644
--- a/proxmox-auto-installer/tests/resources/parse_answer/specific_nic.json
+++ b/proxmox-auto-installer/tests/resources/parse_answer/specific_nic.json
@@ -14,5 +14,6 @@
   "mngmt_nic": "enp129s0f1np1",
   "root_password": { "plain": "123456" },
   "target_hd": "/dev/sda",
-  "timezone": "Europe/Vienna"
+  "timezone": "Europe/Vienna",
+  "first_boot": { "enabled": 0 }
 }
diff --git a/proxmox-auto-installer/tests/resources/parse_answer/zfs.json b/proxmox-auto-installer/tests/resources/parse_answer/zfs.json
index 025dd8f..090b58d 100644
--- a/proxmox-auto-installer/tests/resources/parse_answer/zfs.json
+++ b/proxmox-auto-installer/tests/resources/parse_answer/zfs.json
@@ -24,5 +24,6 @@
       "checksum": "on",
       "compress": "lz4",
       "copies": 2
-  }
+  },
+  "first_boot": { "enabled": 0 }
 }
diff --git a/proxmox-installer-common/src/setup.rs b/proxmox-installer-common/src/setup.rs
index 79b17ed..fefedf6 100644
--- a/proxmox-installer-common/src/setup.rs
+++ b/proxmox-installer-common/src/setup.rs
@@ -339,6 +339,13 @@ where
     serializer.collect_str(value)
 }
 
+fn serialize_bool_as_u32<S>(value: &bool, serializer: S) -> Result<S::Ok, S::Error>
+where
+    S: Serializer,
+{
+    serializer.serialize_u32(if *value { 1 } else { 0 })
+}
+
 #[derive(Clone, Deserialize)]
 pub struct RuntimeInfo {
     /// Whether is system was booted in (legacy) BIOS or UEFI mode.
@@ -464,6 +471,14 @@ pub struct InstallRootPassword {
     pub hashed: Option<String>,
 }
 
+#[derive(Clone, Default, Deserialize, Serialize)]
+pub struct InstallFirstBootSetup {
+    #[serde(serialize_with = "serialize_bool_as_u32")]
+    pub enabled: bool,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub ordering_target: Option<String>,
+}
+
 pub fn spawn_low_level_installer(test_mode: bool) -> io::Result<process::Child> {
     let (path, args, envs): (&str, &[&str], Vec<(&str, &str)>) = if test_mode {
         (
@@ -530,4 +545,6 @@ pub struct InstallConfig {
     pub cidr: CidrAddress,
     pub gateway: IpAddr,
     pub dns: IpAddr,
+
+    pub first_boot: InstallFirstBootSetup,
 }
diff --git a/proxmox-tui-installer/src/setup.rs b/proxmox-tui-installer/src/setup.rs
index 8146511..b2a3511 100644
--- a/proxmox-tui-installer/src/setup.rs
+++ b/proxmox-tui-installer/src/setup.rs
@@ -3,7 +3,7 @@ use std::collections::BTreeMap;
 use crate::options::InstallerOptions;
 use proxmox_installer_common::{
     options::AdvancedBootdiskOptions,
-    setup::{InstallConfig, InstallRootPassword},
+    setup::{InstallConfig, InstallFirstBootSetup, InstallRootPassword},
 };
 
 impl From<InstallerOptions> for InstallConfig {
@@ -44,6 +44,8 @@ impl From<InstallerOptions> for InstallConfig {
             cidr: options.network.address,
             gateway: options.network.gateway,
             dns: options.network.dns_server,
+
+            first_boot: InstallFirstBootSetup::default(),
         };
 
         match &options.bootdisk.advanced {
-- 
2.47.0





More information about the pve-devel mailing list