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
next prev 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.