From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id 486771FF1A6 for ; Fri, 5 Dec 2025 12:26:23 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 4F6F2157C3; Fri, 5 Dec 2025 12:26:51 +0100 (CET) From: Christoph Heiss To: pdm-devel@lists.proxmox.com Date: Fri, 5 Dec 2025 12:25:11 +0100 Message-ID: <20251205112528.373387-10-c.heiss@proxmox.com> X-Mailer: git-send-email 2.51.2 In-Reply-To: <20251205112528.373387-1-c.heiss@proxmox.com> References: <20251205112528.373387-1-c.heiss@proxmox.com> MIME-Version: 1.0 X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1764933930059 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.052 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pdm-devel] [PATCH datacenter-manager v2 09/14] config: add auto-installer configuration module X-BeenThere: pdm-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Datacenter Manager development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox Datacenter Manager development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pdm-devel-bounces@lists.proxmox.com Sender: "pdm-devel" Provides some primitives for the auto-installer integration to save state about - individual installations (as plain JSON, as these aren't configurations files) and - prepared answer file configurations, as section config The new files (including lock files) are placed under `/etc/proxmox-datacenter-manager/autoinst`. Signed-off-by: Christoph Heiss --- Changes v1 -> v2: * no changes lib/pdm-config/Cargo.toml | 2 + lib/pdm-config/src/auto_install.rs | 85 ++++++++++++++++++++++++++++++ lib/pdm-config/src/lib.rs | 1 + lib/pdm-config/src/setup.rs | 7 +++ 4 files changed, 95 insertions(+) create mode 100644 lib/pdm-config/src/auto_install.rs diff --git a/lib/pdm-config/Cargo.toml b/lib/pdm-config/Cargo.toml index d39c2ad..c43579d 100644 --- a/lib/pdm-config/Cargo.toml +++ b/lib/pdm-config/Cargo.toml @@ -12,6 +12,7 @@ nix.workspace = true once_cell.workspace = true openssl.workspace = true serde.workspace = true +serde_json.workspace = true proxmox-config-digest = { workspace = true, features = [ "openssl" ] } proxmox-http = { workspace = true, features = [ "http-helpers" ] } @@ -23,5 +24,6 @@ proxmox-shared-memory.workspace = true proxmox-simple-config.workspace = true proxmox-sys = { workspace = true, features = [ "acl", "crypt", "timer" ] } proxmox-acme-api.workspace = true +proxmox-serde.workspace = true pdm-api-types.workspace = true pdm-buildcfg.workspace = true diff --git a/lib/pdm-config/src/auto_install.rs b/lib/pdm-config/src/auto_install.rs new file mode 100644 index 0000000..0374a70 --- /dev/null +++ b/lib/pdm-config/src/auto_install.rs @@ -0,0 +1,85 @@ +//! Implements configuration for the auto-installer integration. + +use anyhow::Result; +use proxmox_schema::ApiType; +use proxmox_section_config::{SectionConfig, SectionConfigData, SectionConfigPlugin}; +use std::{fs::File, sync::LazyLock}; + +use pdm_api_types::{ + auto_installer::{Installation, PreparedInstallationConfig, PREPARED_INSTALL_CONFIG_ID_SCHEMA}, + ConfigDigest, +}; +use proxmox_product_config::{open_api_lockfile, replace_config, ApiLockGuard}; +use proxmox_sys::error::SysError; + +pub const CONFIG_PATH: &str = pdm_buildcfg::configdir!("/autoinst"); + +static CONFIG: LazyLock = LazyLock::new(|| { + let mut config = SectionConfig::new(&PREPARED_INSTALL_CONFIG_ID_SCHEMA); + + config.register_plugin(SectionConfigPlugin::new( + "prepared-answer".into(), + Some("id".into()), + PreparedInstallationConfig::API_SCHEMA.unwrap_object_schema(), + )); + config +}); + +const PREPARED_CONF_FILE: &str = pdm_buildcfg::configdir!("/autoinst/prepared.cfg"); +const PREPARED_LOCK_FILE: &str = pdm_buildcfg::configdir!("/autoinst/.prepared.lock"); + +// Information about installations themselves are not configuration files and thus are saved +// as JSON. +const INSTALLATIONS_CONF_FILE: &str = pdm_buildcfg::configdir!("/autoinst/installations.json"); +const INSTALLATIONS_LOCK_FILE: &str = pdm_buildcfg::configdir!("/autoinst/.installations.lock"); + +pub fn installations_read_lock() -> Result { + open_api_lockfile(INSTALLATIONS_LOCK_FILE, None, false) +} + +pub fn installations_write_lock() -> Result { + open_api_lockfile(INSTALLATIONS_LOCK_FILE, None, true) +} + +pub fn read_installations() -> Result<(Vec, ConfigDigest)> { + let content: serde_json::Value = match File::open(INSTALLATIONS_CONF_FILE) { + Ok(file) => serde_json::from_reader(std::io::BufReader::new(file))?, + Err(ref err) if err.not_found() => serde_json::json!([]), + Err(err) => return Err(err.into()), + }; + + let digest = proxmox_serde::json::to_canonical_json(&content).map(ConfigDigest::from_slice)?; + let data = serde_json::from_value(content)?; + + Ok((data, digest)) +} + +/// Write lock must be already held. +pub fn save_installations(config: &[Installation]) -> Result<()> { + let raw = serde_json::to_string(&config)?; + replace_config(INSTALLATIONS_CONF_FILE, raw.as_bytes()) +} + +pub fn prepared_answers_read_lock() -> Result { + open_api_lockfile(PREPARED_LOCK_FILE, None, false) +} + +pub fn prepared_answers_write_lock() -> Result { + open_api_lockfile(PREPARED_LOCK_FILE, None, true) +} + +pub fn read_prepared_answers() -> Result<(SectionConfigData, ConfigDigest)> { + let content = + proxmox_sys::fs::file_read_optional_string(PREPARED_CONF_FILE)?.unwrap_or_default(); + + let digest = ConfigDigest::from_slice(content.as_bytes()); + let data = CONFIG.parse(PREPARED_CONF_FILE, &content)?; + + Ok((data, digest)) +} + +/// Write lock must be already held. +pub fn save_prepared_answers(config: &SectionConfigData) -> Result<()> { + let raw = CONFIG.write(PREPARED_CONF_FILE, config)?; + replace_config(PREPARED_CONF_FILE, raw.as_bytes()) +} diff --git a/lib/pdm-config/src/lib.rs b/lib/pdm-config/src/lib.rs index 4c49054..5b9bcca 100644 --- a/lib/pdm-config/src/lib.rs +++ b/lib/pdm-config/src/lib.rs @@ -2,6 +2,7 @@ use anyhow::{format_err, Error}; use nix::unistd::{Gid, Group, Uid, User}; pub use pdm_buildcfg::{BACKUP_GROUP_NAME, BACKUP_USER_NAME}; +pub mod auto_install; pub mod certificate_config; pub mod domains; pub mod node; diff --git a/lib/pdm-config/src/setup.rs b/lib/pdm-config/src/setup.rs index 5f920c8..5adb05f 100644 --- a/lib/pdm-config/src/setup.rs +++ b/lib/pdm-config/src/setup.rs @@ -24,6 +24,13 @@ pub fn create_configdir() -> Result<(), Error> { 0o750, )?; + mkdir_perms( + crate::auto_install::CONFIG_PATH, + api_user.uid, + api_user.gid, + 0o750, + )?; + Ok(()) } -- 2.51.2 _______________________________________________ pdm-devel mailing list pdm-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel