public inbox for pdm-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Christoph Heiss <c.heiss@proxmox.com>
To: pdm-devel@lists.proxmox.com
Subject: [PATCH proxmox v3 12/38] installer-types: implement api type for all externally-used types
Date: Fri,  3 Apr 2026 18:53:44 +0200	[thread overview]
Message-ID: <20260403165437.2166551-13-c.heiss@proxmox.com> (raw)
In-Reply-To: <20260403165437.2166551-1-c.heiss@proxmox.com>

PDM will (re-)use most of these types directly in the API, thus make
them compatible.

Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
Changes v2 -> v3:
  * describe all API properties, some fields were previously missing
  * implement api for a few more types as necessary

Changes v1 -> v2:
  * no changes

 proxmox-installer-types/Cargo.toml       |   4 +
 proxmox-installer-types/debian/control   |  21 ++
 proxmox-installer-types/src/answer.rs    | 268 ++++++++++++++++++++++-
 proxmox-installer-types/src/lib.rs       |  37 ++++
 proxmox-installer-types/src/post_hook.rs |  55 +++++
 5 files changed, 384 insertions(+), 1 deletion(-)

diff --git a/proxmox-installer-types/Cargo.toml b/proxmox-installer-types/Cargo.toml
index b4906fc9..c37e1baf 100644
--- a/proxmox-installer-types/Cargo.toml
+++ b/proxmox-installer-types/Cargo.toml
@@ -15,10 +15,14 @@ rust-version.workspace = true
 anyhow.workspace = true
 serde = { workspace = true, features = ["derive"] }
 serde_plain.workspace = true
+regex = { workspace = true, optional = true }
 proxmox-network-types.workspace = true
+proxmox-schema = { workspace = true, optional = true, features = ["api-macro"] }
+proxmox-section-config = { workspace = true, optional = true }
 proxmox-node-status.workspace = true
 
 [features]
 default = []
+api-types = ["dep:regex", "dep:proxmox-schema", "dep:proxmox-section-config", "proxmox-network-types/api-types"]
 # enable old-style answer file keys with underscores for backwards compatibility
 legacy = []
diff --git a/proxmox-installer-types/debian/control b/proxmox-installer-types/debian/control
index 5971fd6a..2c6be448 100644
--- a/proxmox-installer-types/debian/control
+++ b/proxmox-installer-types/debian/control
@@ -30,6 +30,8 @@ Depends:
  librust-serde-1+default-dev,
  librust-serde-1+derive-dev,
  librust-serde-plain-1+default-dev
+Suggests:
+ librust-proxmox-installer-types+api-types-dev (= ${binary:Version})
 Provides:
  librust-proxmox-installer-types+default-dev (= ${binary:Version}),
  librust-proxmox-installer-types+legacy-dev (= ${binary:Version}),
@@ -44,3 +46,22 @@ Provides:
  librust-proxmox-installer-types-0.1.0+legacy-dev (= ${binary:Version})
 Description: Type definitions used within the installer - Rust source code
  Source code for Debianized Rust crate "proxmox-installer-types"
+
+Package: librust-proxmox-installer-types+api-types-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-proxmox-installer-types-dev (= ${binary:Version}),
+ librust-proxmox-network-types-1+api-types-dev (>= 1.0.2-~~),
+ librust-proxmox-schema-5+api-macro-dev (>= 5.1.1-~~),
+ librust-proxmox-schema-5+default-dev (>= 5.1.1-~~),
+ librust-proxmox-section-config-3+default-dev (>= 3.1.0-~~),
+ librust-regex-1+default-dev (>= 1.5-~~)
+Provides:
+ librust-proxmox-installer-types-0+api-types-dev (= ${binary:Version}),
+ librust-proxmox-installer-types-0.1+api-types-dev (= ${binary:Version}),
+ librust-proxmox-installer-types-0.1.0+api-types-dev (= ${binary:Version})
+Description: Type definitions used within the installer - feature "api-types"
+ This metapackage enables feature "api-types" for the Rust proxmox-installer-
+ types crate, by pulling in any additional dependencies needed by that feature.
diff --git a/proxmox-installer-types/src/answer.rs b/proxmox-installer-types/src/answer.rs
index 10cd57a0..975063ba 100644
--- a/proxmox-installer-types/src/answer.rs
+++ b/proxmox-installer-types/src/answer.rs
@@ -15,15 +15,37 @@ use std::{
 };
 
 use proxmox_network_types::{fqdn::Fqdn, ip_address::Cidr};
+
+#[cfg(feature = "api-types")]
+use proxmox_schema::{
+    api,
+    api_types::{DISK_ARRAY_SCHEMA, PASSWORD_FORMAT},
+    ApiType, IntegerSchema, NumberSchema, ObjectSchema, OneOfSchema, Schema, StringSchema, Updater,
+    UpdaterType,
+};
+
+#[cfg(feature = "api-types")]
+type IpAddr = proxmox_network_types::ip_address::api_types::IpAddr;
+#[cfg(not(feature = "api-types"))]
 type IpAddr = std::net::IpAddr;
 
+#[cfg(feature = "api-types")]
+proxmox_schema::const_regex! {
+    /// A unique two-letter country code, according to ISO 3166-1 (alpha-2).
+    pub COUNTRY_CODE_REGEX = r"^[a-z]{2}$";
+}
+
 /// Defines API types used by proxmox-fetch-answer, the first part of the
 /// auto-installer.
 pub mod fetch {
     use serde::{Deserialize, Serialize};
 
+    #[cfg(feature = "api-types")]
+    use proxmox_schema::api;
+
     use crate::SystemInfo;
 
+    #[cfg_attr(feature = "api-types", api)]
     #[derive(Deserialize, Serialize)]
     #[serde(rename_all = "kebab-case")]
     /// Metadata of the HTTP POST payload, such as schema version of the document.
@@ -50,6 +72,13 @@ pub mod fetch {
         }
     }
 
+    #[cfg_attr(feature = "api-types", api(
+            properties: {
+                sysinfo: {
+                    flatten: true,
+                },
+            },
+    ))]
     #[derive(Deserialize, Serialize)]
     #[serde(rename_all = "kebab-case")]
     /// Data sent in the body of POST request when retrieving the answer file via HTTP(S).
@@ -68,6 +97,7 @@ pub mod fetch {
     }
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Deserialize, Debug, Serialize, PartialEq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// Top-level answer file structure, describing all possible options for an
@@ -91,6 +121,25 @@ pub struct AutoInstallerConfig {
     pub first_boot: Option<FirstBootHookInfo>,
 }
 
+/// Machine root password schema.
+#[cfg(feature = "api-types")]
+pub const ROOT_PASSWORD_SCHEMA: proxmox_schema::Schema = StringSchema::new("Root Password.")
+    .format(&PASSWORD_FORMAT)
+    .min_length(8)
+    .max_length(64)
+    .schema();
+
+#[cfg_attr(feature = "api-types", api(
+    properties: {
+        "root-ssh-keys": {
+            type: Array,
+            items: {
+                description: "Public SSH key.",
+                type: String,
+            }
+        },
+    },
+))]
 #[derive(Clone, Default, Deserialize, Debug, Serialize, PartialEq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// General target system options for setting up the system in an automated
@@ -130,6 +179,7 @@ pub struct GlobalOptions {
     pub root_ssh_keys: Vec<String>,
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Copy, Clone, Deserialize, Serialize, Debug, Default, PartialEq, Eq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// Action to take after the installation completed successfully.
@@ -144,6 +194,7 @@ pub enum RebootMode {
 serde_plain::derive_fromstr_from_deserialize!(RebootMode);
 
 #[derive(Clone, Deserialize, Debug, Serialize, PartialEq)]
+#[cfg_attr(feature = "api-types", derive(Updater))]
 #[serde(
     untagged,
     expecting = "either a fully-qualified domain name or extendend configuration for usage with DHCP must be specified"
@@ -163,6 +214,23 @@ impl Default for FqdnConfig {
     }
 }
 
+#[cfg(feature = "api-types")]
+impl ApiType for FqdnConfig {
+    const API_SCHEMA: Schema = OneOfSchema::new(
+        "Either a FQDN as string or an object describing the retrieval method.",
+        &(
+            "type",
+            false,
+            &StringSchema::new("A string or an object").schema(),
+        ),
+        &[
+            ("from-dhcp", &<FqdnFromDhcpConfig as ApiType>::API_SCHEMA),
+            ("simple", &StringSchema::new("Plain FQDN").schema()),
+        ],
+    )
+    .schema();
+}
+
 impl FqdnConfig {
     /// Constructs a new "simple" FQDN configuration, i.e. a fixed hostname.
     pub fn simple<S: Into<String>>(fqdn: S) -> Result<Self> {
@@ -183,6 +251,7 @@ impl FqdnConfig {
     }
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Default, Deserialize, Debug, Serialize, PartialEq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// Extended configuration for retrieving the FQDN from external sources.
@@ -195,6 +264,7 @@ pub struct FqdnFromDhcpConfig {
     pub domain: Option<String>,
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Deserialize, Debug, Default, PartialEq, Serialize)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// Describes the source to retrieve the FQDN of the installation.
@@ -204,6 +274,7 @@ pub enum FqdnSourceMode {
     FromDhcp,
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Deserialize, Debug, Serialize, PartialEq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// Configuration for the post-installation hook, which runs after an
@@ -216,6 +287,7 @@ pub struct PostNotificationHookInfo {
     pub cert_fingerprint: Option<String>,
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Deserialize, Debug, PartialEq, Serialize)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// Possible sources for the optional first-boot hook script/executable file.
@@ -227,6 +299,7 @@ pub enum FirstBootHookSourceMode {
     FromIso,
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Default, Deserialize, Debug, PartialEq, Serialize)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// Possible orderings for the `proxmox-first-boot` systemd service.
@@ -256,6 +329,7 @@ impl FirstBootHookServiceOrdering {
     }
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Deserialize, Debug, Serialize, PartialEq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// Describes from where to fetch the first-boot hook script, either being baked into the ISO or
@@ -276,6 +350,15 @@ pub struct FirstBootHookInfo {
     pub cert_fingerprint: Option<String>,
 }
 
+#[cfg_attr(feature = "api-types", api(
+    properties: {
+        mapping: {
+            type: Object,
+            properties: {},
+            additional_properties: true,
+        }
+    },
+))]
 #[derive(Clone, Deserialize, Debug, Serialize, PartialEq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// Options controlling the behaviour of the network interface pinning (by
@@ -288,6 +371,15 @@ pub struct NetworkInterfacePinningOptionsAnswer {
     pub mapping: HashMap<String, String>,
 }
 
+#[cfg_attr(feature = "api-types", api(
+    properties: {
+        filter: {
+            type: Object,
+            properties: {},
+            additional_properties: true,
+        }
+    },
+))]
 #[derive(Clone, Deserialize, Debug, Serialize, PartialEq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// Static network configuration given by the user.
@@ -307,6 +399,7 @@ pub struct NetworkConfigFromAnswer {
     pub interface_name_pinning: Option<NetworkInterfacePinningOptionsAnswer>,
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Deserialize, Debug, Serialize, PartialEq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// Use the network configuration received from the DHCP server.
@@ -317,6 +410,13 @@ pub struct NetworkConfigFromDhcp {
     pub interface_name_pinning: Option<NetworkInterfacePinningOptionsAnswer>,
 }
 
+#[cfg_attr(feature = "api-types", api(
+    "id-property": "source",
+    "id-schema": {
+        type: String,
+        description: "'from-dhcp' or 'from-answer'",
+    }
+))]
 #[derive(Clone, Deserialize, Debug, Serialize, PartialEq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields, tag = "source")]
 /// Network configuration to set up inside the target installation.
@@ -339,6 +439,7 @@ impl NetworkConfig {
 }
 
 #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
+#[cfg_attr(feature = "api-types", derive(UpdaterType))]
 #[serde(rename_all = "kebab-case", tag = "filesystem")]
 /// Filesystem-specific options to set on the root disk.
 pub enum FilesystemOptions {
@@ -368,6 +469,66 @@ impl FilesystemOptions {
     }
 }
 
+#[cfg(feature = "api-types")]
+impl ApiType for FilesystemOptions {
+    // FIXME: proxmox-schema can not correctly differentiate between different
+    // enums in struct members with the same name.
+    const API_SCHEMA: Schema = ObjectSchema::new(
+        "Filesystem-specific options to set on the root disk.",
+        &[
+            (
+                "ashift",
+                true,
+                &IntegerSchema::new("`ashift` value to create the zpool with.")
+                    .minimum(9)
+                    .maximum(16)
+                    .default(12)
+                    .schema(),
+            ),
+            ("filesystem", false, &Filesystem::API_SCHEMA),
+            (
+                "hdsize",
+                true,
+                &NumberSchema::new("Size of the root disk to use, in GiB.")
+                    .minimum(2.)
+                    .schema(),
+            ),
+            (
+                "maxfree",
+                true,
+                &NumberSchema::new(
+                    "Minimum amount of free space to leave on the LVM volume group, in GiB.",
+                )
+                .minimum(0.)
+                .schema(),
+            ),
+            (
+                "maxroot",
+                true,
+                &NumberSchema::new("Maximum size of the `root` volume, in GiB.")
+                    .minimum(2.)
+                    .schema(),
+            ),
+            (
+                "maxvz",
+                true,
+                &NumberSchema::new("Maximum size of the `data` volume, in GiB.")
+                    .minimum(0.)
+                    .schema(),
+            ),
+            (
+                "swapsize",
+                true,
+                &NumberSchema::new("Size of the swap volume, in GiB.")
+                    .minimum(0.)
+                    .schema(),
+            ),
+        ],
+    )
+    .additional_properties(true)
+    .schema();
+}
+
 #[derive(Clone, Debug, Serialize)]
 /// Defines the disks to use for the installation. Can either be a fixed list
 /// of disk names or a dynamic filter list.
@@ -393,6 +554,7 @@ impl Display for DiskSelection {
     }
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Copy, Clone, Default, Deserialize, Debug, PartialEq, Serialize)]
 #[serde(rename_all = "lowercase", deny_unknown_fields)]
 /// Whether the associated filters must all match for a device or if any one
@@ -407,6 +569,18 @@ pub enum FilterMatch {
 
 serde_plain::derive_fromstr_from_deserialize!(FilterMatch);
 
+#[cfg_attr(feature = "api-types", api(
+    properties: {
+        "disk-list": {
+            schema: DISK_ARRAY_SCHEMA,
+        },
+        filter: {
+            type: Object,
+            properties: {},
+            additional_properties: true,
+        }
+    },
+))]
 #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// Disk configuration for the target installation.
@@ -502,7 +676,7 @@ impl DiskSetup {
     }
 }
 
-
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Copy, Clone, Deserialize, Serialize, Debug, PartialEq)]
 #[serde(rename_all = "lowercase", deny_unknown_fields)]
 /// Available filesystem during installation.
@@ -531,6 +705,46 @@ impl From<FilesystemType> for Filesystem {
 serde_plain::derive_display_from_serialize!(Filesystem);
 serde_plain::derive_fromstr_from_deserialize!(Filesystem);
 
+#[cfg_attr(feature = "api-types", api(
+    properties: {
+        raid: {
+            type: ZfsRaidLevel,
+            optional: true,
+        },
+        ashift: {
+            type: Integer,
+            minimum: 9,
+            maximum: 16,
+            default: 12,
+            optional: true,
+        },
+        "arc-max": {
+            type: Integer,
+            // ZFS specifies 64 MiB as the absolute minimum.
+            minimum: 64,
+            optional: true,
+        },
+        checksum: {
+            type: ZfsChecksumOption,
+            optional: true,
+        },
+        compress: {
+            type: ZfsChecksumOption,
+            optional: true,
+        },
+        copies: {
+            type: Integer,
+            minimum: 1,
+            maximum: 3,
+            optional: true,
+        },
+        hdsize: {
+            type: Number,
+            minimum: 2.,
+            optional: true,
+        },
+    },
+), derive(Updater))]
 #[derive(Clone, Copy, Default, Deserialize, Debug, Serialize, PartialEq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// ZFS-specific filesystem options.
@@ -561,6 +775,35 @@ pub struct ZfsOptions {
     pub hdsize: Option<f64>,
 }
 
+#[cfg_attr(feature = "api-types", api(
+    properties: {
+        hdsize: {
+            type: Number,
+            minimum: 2.,
+            optional: true,
+        },
+        swapsize: {
+            type: Number,
+            minimum: 0.,
+            optional: true,
+        },
+        maxroot: {
+            type: Number,
+            minimum: 2.,
+            optional: true,
+        },
+        maxvz: {
+            type: Number,
+            minimum: 0.,
+            optional: true,
+        },
+        minfree: {
+            type: Number,
+            minimum: 0.,
+            optional: true,
+        },
+    },
+), derive(Updater))]
 #[derive(Clone, Copy, Default, Deserialize, Serialize, Debug, PartialEq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// LVM-specific filesystem options, when using ext4 or xfs as filesystem.
@@ -588,6 +831,23 @@ pub struct LvmOptions {
     pub minfree: Option<f64>,
 }
 
+#[cfg_attr(feature = "api-types", api(
+    properties: {
+        hdsize: {
+            type: Number,
+            minimum: 2.,
+            optional: true,
+        },
+        raid: {
+            type: BtrfsRaidLevel,
+            optional: true,
+        },
+        compress: {
+            type: BtrfsCompressOption,
+            optional: true,
+        },
+    },
+), derive(Updater))]
 #[derive(Clone, Copy, Default, Deserialize, Debug, Serialize, PartialEq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// Btrfs-specific filesystem options.
@@ -604,6 +864,7 @@ pub struct BtrfsOptions {
     pub compress: Option<BtrfsCompressOption>,
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Copy, Clone, Deserialize, Serialize, Debug, Default, PartialEq)]
 #[serde(rename_all = "kebab-case", deny_unknown_fields)]
 /// Keyboard layout of the system.
@@ -697,6 +958,7 @@ impl KeyboardLayout {
 serde_plain::derive_fromstr_from_deserialize!(KeyboardLayout);
 serde_plain::derive_display_from_serialize!(KeyboardLayout);
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Copy, Clone, Debug, Default, Deserialize, Serialize, Eq, PartialEq)]
 #[serde(rename_all = "UPPERCASE")]
 /// Available Btrfs RAID levels.
@@ -715,6 +977,7 @@ pub enum BtrfsRaidLevel {
 
 serde_plain::derive_display_from_serialize!(BtrfsRaidLevel);
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Copy, Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
 #[serde(rename_all = "lowercase")]
 /// Possible compression algorithms usable with Btrfs. See the accompanying
@@ -742,6 +1005,7 @@ pub const BTRFS_COMPRESS_OPTIONS: &[BtrfsCompressOption] = {
     &[On, Off, Zlib, Lzo, Zstd]
 };
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Copy, Clone, Debug, Default, Deserialize, Serialize, Eq, PartialEq)]
 #[serde(rename_all = "UPPERCASE")]
 /// Available ZFS RAID levels.
@@ -769,6 +1033,7 @@ pub enum ZfsRaidLevel {
 
 serde_plain::derive_display_from_serialize!(ZfsRaidLevel);
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Copy, Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
 #[serde(rename_all = "lowercase")]
 /// Possible compression algorithms usable with ZFS.
@@ -799,6 +1064,7 @@ pub const ZFS_COMPRESS_OPTIONS: &[ZfsCompressOption] = {
     &[On, Off, Lzjb, Lz4, Zle, Gzip, Zstd]
 };
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Copy, Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
 #[serde(rename_all = "kebab-case")]
 /// Possible checksum algorithms usable with ZFS.
diff --git a/proxmox-installer-types/src/lib.rs b/proxmox-installer-types/src/lib.rs
index 40c61252..df1f7944 100644
--- a/proxmox-installer-types/src/lib.rs
+++ b/proxmox-installer-types/src/lib.rs
@@ -10,6 +10,9 @@
 pub mod answer;
 pub mod post_hook;
 
+#[cfg(feature = "api-types")]
+use proxmox_schema::api;
+
 use serde::{Deserialize, Serialize};
 use std::collections::{BTreeMap, HashMap};
 
@@ -18,6 +21,7 @@ use proxmox_network_types::mac_address::MacAddress;
 /// Default placeholder value for the administrator email address.
 pub const EMAIL_DEFAULT_PLACEHOLDER: &str = "mail@example.invalid";
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Copy, Clone, Eq, Deserialize, PartialEq, Serialize)]
 #[serde(rename_all = "lowercase")]
 /// Whether the system boots using legacy BIOS or (U)EFI.
@@ -40,6 +44,16 @@ pub struct UdevInfo {
     pub nics: BTreeMap<String, UdevProperties>,
 }
 
+#[cfg_attr(feature = "api-types", api(
+    properties: {
+        network_interfaces: {
+            type: Array,
+            items: {
+                type: NetworkInterface,
+            },
+        },
+    },
+))]
 #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
 /// Information about the hardware and installer in use.
 pub struct SystemInfo {
@@ -53,6 +67,7 @@ pub struct SystemInfo {
     pub network_interfaces: Vec<NetworkInterface>,
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
 /// The per-product configuration of the installer.
 pub struct ProductConfig {
@@ -75,6 +90,7 @@ impl ProductConfig {
     }
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
 /// Information about the ISO itself.
 pub struct IsoInfo {
@@ -94,6 +110,25 @@ impl IsoInfo {
     }
 }
 
+#[cfg_attr(feature = "api-types", api(
+    properties: {
+        baseboard: {
+            type: Object,
+            properties: {},
+            additional_properties: true,
+        },
+        chassis: {
+            type: Object,
+            properties: {},
+            additional_properties: true,
+        },
+        system: {
+            type: Object,
+            properties: {},
+            additional_properties: true,
+        },
+    },
+))]
 #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
 /// Collection of various DMI information categories.
 pub struct SystemDMI {
@@ -105,6 +140,7 @@ pub struct SystemDMI {
     pub system: HashMap<String, String>,
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
 /// A unique network interface.
 pub struct NetworkInterface {
@@ -114,6 +150,7 @@ pub struct NetworkInterface {
     pub mac: MacAddress,
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[allow(clippy::upper_case_acronyms)]
 #[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq, PartialOrd, Ord, Serialize)]
 #[serde(rename_all = "lowercase")]
diff --git a/proxmox-installer-types/src/post_hook.rs b/proxmox-installer-types/src/post_hook.rs
index a307cf7b..e505a5cf 100644
--- a/proxmox-installer-types/src/post_hook.rs
+++ b/proxmox-installer-types/src/post_hook.rs
@@ -3,6 +3,8 @@
 use serde::{Deserialize, Serialize};
 
 use proxmox_network_types::ip_address::Cidr;
+#[cfg(feature = "api-types")]
+use proxmox_schema::api;
 
 use crate::{
     answer::{FilesystemType, RebootMode},
@@ -12,6 +14,13 @@ use crate::{
 /// Re-export for convenience, since this is public API
 pub use proxmox_node_status::KernelVersionInformation;
 
+#[cfg_attr(feature = "api-types", api(
+    properties: {
+        "secureboot": {
+            optional: true,
+        },
+    },
+))]
 #[derive(Clone, Serialize, Deserialize, PartialEq)]
 /// Information about the system boot status.
 pub struct BootInfo {
@@ -22,6 +31,7 @@ pub struct BootInfo {
     pub secureboot: bool,
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Serialize, Deserialize, PartialEq)]
 /// Holds all the public keys for the different algorithms available.
 pub struct SshPublicHostKeys {
@@ -33,6 +43,18 @@ pub struct SshPublicHostKeys {
     pub rsa: String,
 }
 
+#[cfg_attr(feature = "api-types", api(
+    properties: {
+        "udev-properties": {
+            type: Object,
+            additional_properties: true,
+            properties: {},
+        },
+        "is-bootdisk": {
+            optional: true,
+        },
+    },
+))]
 #[derive(Clone, Serialize, Deserialize, PartialEq)]
 #[serde(rename_all = "kebab-case")]
 /// Holds information about a single disk in the system.
@@ -46,6 +68,21 @@ pub struct DiskInfo {
     pub udev_properties: UdevProperties,
 }
 
+#[cfg_attr(feature = "api-types", api(
+    properties: {
+        "udev-properties": {
+            type: Object,
+            additional_properties: true,
+            properties: {},
+        },
+        "is-management": {
+            optional: true,
+        },
+        "is-pinned": {
+            optional: true,
+        },
+    },
+))]
 /// Holds information about the management network interface.
 #[derive(Clone, Serialize, Deserialize, PartialEq)]
 #[serde(rename_all = "kebab-case")]
@@ -69,6 +106,7 @@ pub struct NetworkInterfaceInfo {
     pub udev_properties: UdevProperties,
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Serialize, Deserialize, PartialEq)]
 #[serde(rename_all = "kebab-case")]
 /// Information about the installed product itself.
@@ -81,6 +119,7 @@ pub struct ProductInfo {
     pub version: String,
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Serialize, Deserialize, PartialEq)]
 /// Information about the CPU(s) installed in the system
 pub struct CpuInfo {
@@ -98,6 +137,7 @@ pub struct CpuInfo {
     pub sockets: usize,
 }
 
+#[cfg_attr(feature = "api-types", api)]
 #[derive(Clone, Serialize, Deserialize, PartialEq)]
 #[serde(rename_all = "kebab-case")]
 /// Metadata of the hook, such as schema version of the document.
@@ -112,6 +152,21 @@ pub struct PostHookInfoSchema {
     pub version: String,
 }
 
+#[cfg_attr(feature = "api-types", api(
+    properties: {
+        filesystem: {
+            type: String,
+        },
+        disks: {
+            type: Array,
+            items: { type: DiskInfo },
+        },
+        "network-interfaces": {
+            type: Array,
+            items: { type: NetworkInterfaceInfo },
+        }
+    },
+))]
 #[derive(Clone, Serialize, Deserialize, PartialEq)]
 #[serde(rename_all = "kebab-case")]
 /// All data sent as request payload with the post-installation-webhook POST request.
-- 
2.53.0





  parent reply	other threads:[~2026-04-03 16:55 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-03 16:53 [PATCH proxmox/yew-pwt/datacenter-manager/installer v3 00/38] add auto-installer integration Christoph Heiss
2026-04-03 16:53 ` [PATCH proxmox v3 01/38] api-macro: allow $ in identifier name Christoph Heiss
2026-04-03 16:53 ` [PATCH proxmox v3 02/38] schema: oneOf: allow single string variant Christoph Heiss
2026-04-03 16:53 ` [PATCH proxmox v3 03/38] schema: implement UpdaterType for HashMap and BTreeMap Christoph Heiss
2026-04-03 16:53 ` [PATCH proxmox v3 04/38] network-types: move `Fqdn` type from proxmox-installer-common Christoph Heiss
2026-04-03 16:53 ` [PATCH proxmox v3 05/38] network-types: implement api type for Fqdn Christoph Heiss
2026-04-03 16:53 ` [PATCH proxmox v3 06/38] network-types: add api wrapper type for std::net::IpAddr Christoph Heiss
2026-04-03 16:53 ` [PATCH proxmox v3 07/38] network-types: cidr: implement generic `IpAddr::new` constructor Christoph Heiss
2026-04-03 16:53 ` [PATCH proxmox v3 08/38] network-types: fqdn: implement standard library Error for Fqdn Christoph Heiss
2026-04-03 16:53 ` [PATCH proxmox v3 09/38] node-status: make KernelVersionInformation Clone + PartialEq Christoph Heiss
2026-04-03 16:53 ` [PATCH proxmox v3 10/38] installer-types: add common types used by the installer Christoph Heiss
2026-04-03 16:53 ` [PATCH proxmox v3 11/38] installer-types: add types used by the auto-installer Christoph Heiss
2026-04-03 16:53 ` Christoph Heiss [this message]
2026-04-03 16:53 ` [PATCH yew-widget-toolkit v3 13/38] widget: kvlist: add widget for user-modifiable data tables Christoph Heiss
2026-04-03 16:53 ` [PATCH datacenter-manager v3 14/38] api-types, cli: use ReturnType::new() instead of constructing it manually Christoph Heiss
2026-04-03 16:53 ` [PATCH datacenter-manager v3 15/38] api-types: add api types for auto-installer integration Christoph Heiss
2026-04-03 16:53 ` [PATCH datacenter-manager v3 16/38] config: add auto-installer configuration module Christoph Heiss
2026-04-03 16:53 ` [PATCH datacenter-manager v3 17/38] acl: wire up new /system/auto-installation acl path Christoph Heiss
2026-04-03 16:53 ` [PATCH datacenter-manager v3 18/38] server: api: add auto-installer integration module Christoph Heiss
2026-04-03 16:53 ` [PATCH datacenter-manager v3 19/38] server: api: auto-installer: add access token management endpoints Christoph Heiss
2026-04-03 16:53 ` [PATCH datacenter-manager v3 20/38] client: add bindings for auto-installer endpoints Christoph Heiss
2026-04-03 16:53 ` [PATCH datacenter-manager v3 21/38] ui: auto-installer: add installations overview panel Christoph Heiss
2026-04-03 16:53 ` [PATCH datacenter-manager v3 22/38] ui: auto-installer: add prepared answer configuration panel Christoph Heiss
2026-04-03 16:53 ` [PATCH datacenter-manager v3 23/38] ui: auto-installer: add access token " Christoph Heiss
2026-04-03 16:53 ` [PATCH datacenter-manager v3 24/38] docs: add documentation for auto-installer integration Christoph Heiss
2026-04-03 16:53 ` [PATCH installer v3 25/38] install: iso env: use JSON boolean literals for product config Christoph Heiss
2026-04-03 16:53 ` [PATCH installer v3 26/38] common: http: allow passing custom headers to post() Christoph Heiss
2026-04-03 16:53 ` [PATCH installer v3 27/38] common: options: move regex construction out of loop Christoph Heiss
2026-04-03 16:54 ` [PATCH installer v3 28/38] assistant: support adding an authorization token for HTTP-based answers Christoph Heiss
2026-04-03 16:54 ` [PATCH installer v3 29/38] tree-wide: used moved `Fqdn` type to proxmox-network-types Christoph Heiss
2026-04-03 16:54 ` [PATCH installer v3 30/38] tree-wide: use `Cidr` type from proxmox-network-types Christoph Heiss
2026-04-03 16:54 ` [PATCH installer v3 31/38] tree-wide: switch to filesystem types from proxmox-installer-types Christoph Heiss
2026-04-03 16:54 ` [PATCH installer v3 32/38] post-hook: switch to types in proxmox-installer-types Christoph Heiss
2026-04-03 16:54 ` [PATCH installer v3 33/38] auto: sysinfo: switch to types from proxmox-installer-types Christoph Heiss
2026-04-03 16:54 ` [PATCH installer v3 34/38] fetch-answer: " Christoph Heiss
2026-04-03 16:54 ` [PATCH installer v3 35/38] fetch-answer: http: prefer json over toml for answer format Christoph Heiss
2026-04-03 16:54 ` [PATCH installer v3 36/38] fetch-answer: send auto-installer HTTP authorization token if set Christoph Heiss
2026-04-03 16:54 ` [PATCH installer v3 37/38] tree-wide: switch out `Answer` -> `AutoInstallerConfig` types Christoph Heiss
2026-04-03 16:54 ` [PATCH installer v3 38/38] auto: drop now-dead answer file definitions Christoph Heiss

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=20260403165437.2166551-13-c.heiss@proxmox.com \
    --to=c.heiss@proxmox.com \
    --cc=pdm-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