From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id C17B11FF183 for ; Wed, 2 Jul 2025 16:51:31 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id CEFBA1E4E6; Wed, 2 Jul 2025 16:51:26 +0200 (CEST) From: Gabriel Goller To: pve-devel@lists.proxmox.com Date: Wed, 2 Jul 2025 16:50:10 +0200 Message-Id: <20250702145101.894299-26-g.goller@proxmox.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250702145101.894299-1-g.goller@proxmox.com> References: <20250702145101.894299-1-g.goller@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL -0.019 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: [pve-devel] [PATCH proxmox-ve-rs v4 19/22] sdn: fabrics: config: add conversion from / to section config X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox VE development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" From: Stefan Hanreich Add helper methods for populating a FabricConfig from the section config, as well as converting it back into the respective section config structs. By utilizing the Valid type, we can ensure that only valid configurations get written via the provided write_section_config method, since it is only implemented for Valid. Because validation can be expensive, particularly when doing multiple changes to the fabric config, we only validate the config directly before converting it into the section config. Co-authored-by: Gabriel Goller Signed-off-by: Stefan Hanreich --- proxmox-ve-config/src/sdn/fabric/mod.rs | 91 ++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/proxmox-ve-config/src/sdn/fabric/mod.rs b/proxmox-ve-config/src/sdn/fabric/mod.rs index a2132e8aff3f..f58094f67c5e 100644 --- a/proxmox-ve-config/src/sdn/fabric/mod.rs +++ b/proxmox-ve-config/src/sdn/fabric/mod.rs @@ -4,9 +4,12 @@ use std::collections::{BTreeMap, HashSet}; use std::marker::PhantomData; use std::ops::Deref; +use anyhow::Error; use serde::{Deserialize, Serialize}; -use crate::common::valid::Validatable; +use proxmox_section_config::typed::{ApiSectionDataEntry, SectionConfigData}; + +use crate::common::valid::{Valid, Validatable}; use crate::sdn::fabric::section_config::{ fabric::{ @@ -28,6 +31,7 @@ use crate::sdn::fabric::section_config::{ OspfNodePropertiesUpdater, OspfProperties, OspfPropertiesUpdater, }, }, + Either, Section, }; #[derive(thiserror::Error, Debug)] @@ -709,4 +713,89 @@ impl FabricConfig { _ => Err(FabricConfigError::ProtocolMismatch), } } + + /// Constructs a valid [FabricConfig] from section-config data. + /// + /// Iterates through the [SectionConfigData
] and matches on the [Section] enum. Then + /// construct the [FabricConfig] and validate it. + pub fn from_section_config( + config: SectionConfigData
, + ) -> Result, FabricConfigError> { + let mut fabrics = BTreeMap::new(); + let mut nodes = Vec::new(); + + for (_id, section) in config { + let fabric_or_node = Either::from(section); + + match fabric_or_node { + Either::Left(fabric) => { + fabrics.insert(fabric.id().clone(), FabricEntry::from(fabric)); + } + Either::Right(node) => { + nodes.push(node); + } + }; + } + + for node in nodes { + fabrics + .get_mut(node.id().fabric_id()) + .ok_or_else(|| { + FabricConfigError::FabricDoesNotExist(node.id().fabric_id().to_string()) + })? + .add_node(node)?; + } + + let config = Self { fabrics }; + config.into_valid() + } + + /// Constructs a valid [FabricConfig] from the raw section-config file content. + /// + /// This will call the [Section::parse_section_config] function to parse the raw string into a + /// [SectionConfigData
] struct. Then construct the valid [FabricConfig] with + /// [Self::from_section_config]. + pub fn parse_section_config(config: &str) -> Result, Error> { + let data = Section::parse_section_config("fabrics.cfg", config)?; + Self::from_section_config(data).map_err(anyhow::Error::msg) + } + + /// Validate [FabricConfig] and write the raw config to a String. + /// + /// Validates the config and calls [Valid::write_section_config]. + pub fn write_section_config(&self) -> Result { + self.clone().into_valid()?.write_section_config() + } +} + +impl Valid { + /// Converts a valid [FabricConfig] into a [SectionConfigData
]. + /// + /// This function is implemented on [Valid], ensuring that only a valid + /// [FabricConfig] can be written to the file. + pub fn into_section_config(self) -> SectionConfigData
{ + let config = self.into_inner(); + + let mut section_config = SectionConfigData::default(); + + for (fabric_id, fabric_entry) in config.fabrics { + let (fabric, fabric_nodes) = fabric_entry.into_section_config(); + + section_config.insert(fabric_id.to_string(), Section::from(fabric)); + + for node in fabric_nodes { + section_config.insert(node.id().to_string(), Section::from(node)); + } + } + + section_config + } + + /// Consumes the [Valid] and writes the raw section-config content to a String. + /// + /// This function is implemented on [Valid], ensuring that only a valid + /// [FabricConfig] can be written to the file. + pub fn write_section_config(self) -> Result { + Section::write_section_config("fabrics.cfg", &self.into_section_config()) + } } -- 2.39.5 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel