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 C36831FF165 for ; Thu, 22 May 2025 18:22:06 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 1B4DCAF20; Thu, 22 May 2025 18:18:26 +0200 (CEST) From: Stefan Hanreich To: pve-devel@lists.proxmox.com Date: Thu, 22 May 2025 18:16:44 +0200 Message-Id: <20250522161731.537011-29-s.hanreich@proxmox.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250522161731.537011-1-s.hanreich@proxmox.com> References: <20250522161731.537011-1-s.hanreich@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL -0.227 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 KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods RDNS_NONE 0.793 Delivered to internal network by a host with no rDNS SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record Subject: [pve-devel] [PATCH proxmox-perl-rs v3 2/5] pve-rs: sdn: fabrics: add api methods 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" The FabricConfig from proxmox-ve-config implements CRUD functionality for Fabrics and Nodes stored in the section config. We expose them via perlmod, so they can be used in the API endpoints defined in perl. they map 1:1 to the respective API endpoints. They are simply calling the respective implementation of FabricConfig, and convert from / to the API representations of the Fabrics / Nodes returned by FabricConfig. Co-authored-by: Gabriel Goller Signed-off-by: Stefan Hanreich --- pve-rs/src/bindings/sdn/fabrics.rs | 212 ++++++++++++++++++++++++++++- 1 file changed, 211 insertions(+), 1 deletion(-) diff --git a/pve-rs/src/bindings/sdn/fabrics.rs b/pve-rs/src/bindings/sdn/fabrics.rs index fac5602..2efa1c6 100644 --- a/pve-rs/src/bindings/sdn/fabrics.rs +++ b/pve-rs/src/bindings/sdn/fabrics.rs @@ -17,7 +17,20 @@ pub mod pve_rs_sdn_fabrics { use proxmox_section_config::typed::SectionConfigData; use proxmox_ve_config::common::valid::Validatable; - use proxmox_ve_config::sdn::fabric::{section_config::Section, FabricConfig}; + use proxmox_ve_config::sdn::fabric::{ + section_config::{ + fabric::{ + api::{Fabric, FabricUpdater}, + FabricId, + }, + node::{ + api::{Node, NodeUpdater}, + Node as ConfigNode, NodeId, + }, + Section, + }, + FabricConfig, FabricEntry, + }; /// A SDN Fabric config instance. #[derive(Serialize, Deserialize)] @@ -57,6 +70,203 @@ pub mod pve_rs_sdn_fabrics { ) } + /// Class method: Returns all fabrics and nodes from the configuration. + #[export] + fn list_all( + #[try_from_ref] this: &PerlFabricConfig, + ) -> (BTreeMap, BTreeMap) { + let config = this.fabric_config.lock().unwrap(); + + let mut fabrics = BTreeMap::new(); + let mut nodes = BTreeMap::new(); + + for entry in config.values() { + fabrics.insert(entry.fabric().id().to_string(), entry.fabric().clone()); + + nodes.extend( + entry + .nodes() + .map(|(_node_id, node)| (node.id().to_string(), node.clone().into())), + ); + } + + (fabrics, nodes) + } + + /// Class method: Returns all fabrics from the configuration. + #[export] + fn list_fabrics(#[try_from_ref] this: &PerlFabricConfig) -> BTreeMap { + this.fabric_config + .lock() + .unwrap() + .iter() + .map(|(id, entry)| (id.to_string(), entry.fabric().clone())) + .collect() + } + + /// Class method: Returns all fabrics configured on a specific node in the cluster. + #[export] + fn list_fabrics_by_node( + #[try_from_ref] this: &PerlFabricConfig, + node_id: NodeId, + ) -> BTreeMap { + this.fabric_config + .lock() + .unwrap() + .iter() + .filter(|(_id, entry)| entry.get_node(&node_id).is_ok()) + .map(|(id, entry)| (id.to_string(), entry.fabric().clone())) + .collect() + } + + /// Class method: Adds a new Fabric to the configuration. + #[export] + fn add_fabric(#[try_from_ref] this: &PerlFabricConfig, fabric: Fabric) -> Result<(), Error> { + this.fabric_config + .lock() + .unwrap() + .add_fabric(fabric) + .map_err(anyhow::Error::msg) + } + + /// Class method: Read a Fabric from the configuration. + #[export] + fn get_fabric(#[try_from_ref] this: &PerlFabricConfig, id: FabricId) -> Result { + this.fabric_config + .lock() + .unwrap() + .get_fabric(&id) + .map(|entry| entry.fabric().clone()) + .map_err(anyhow::Error::msg) + } + + /// Class method: Update a fabric in the configuration. + #[export] + fn update_fabric( + #[try_from_ref] this: &PerlFabricConfig, + id: FabricId, + updater: FabricUpdater, + ) -> Result<(), Error> { + this.fabric_config + .lock() + .unwrap() + .update_fabric(&id, updater) + .map_err(anyhow::Error::msg) + } + + /// Class method: Delete a fabric from the configuration. + #[export] + fn delete_fabric( + #[try_from_ref] this: &PerlFabricConfig, + id: FabricId, + ) -> Result { + this.fabric_config + .lock() + .unwrap() + .delete_fabric(&id) + .map_err(anyhow::Error::msg) + } + + /// Class method: List all nodes in the configuraiton. + #[export] + fn list_nodes( + #[try_from_ref] this: &PerlFabricConfig, + ) -> Result, Error> { + Ok(this + .fabric_config + .lock() + .unwrap() + .values() + .flat_map(|entry| { + entry + .nodes() + .map(|(id, node)| (id.to_string(), node.clone().into())) + }) + .collect()) + } + + /// Class method: List all nodes for a specific fabric. + #[export] + fn list_nodes_fabric( + #[try_from_ref] this: &PerlFabricConfig, + fabric_id: FabricId, + ) -> Result, Error> { + Ok(this + .fabric_config + .lock() + .unwrap() + .get_fabric(&fabric_id) + .map_err(anyhow::Error::msg)? + .nodes() + .map(|(id, node)| (id.to_string(), node.clone().into())) + .collect()) + } + + /// Class method: Get a node from a fabric. + #[export] + fn get_node( + #[try_from_ref] this: &PerlFabricConfig, + fabric_id: FabricId, + node_id: NodeId, + ) -> Result { + this.fabric_config + .lock() + .unwrap() + .get_fabric(&fabric_id) + .map_err(anyhow::Error::msg)? + .get_node(&node_id) + .map(|node| node.clone().into()) + .map_err(anyhow::Error::msg) + } + + /// Class method: Add a node to a fabric. + #[export] + fn add_node(#[try_from_ref] this: &PerlFabricConfig, node: Node) -> Result<(), Error> { + let node = ConfigNode::from(node); + + this.fabric_config + .lock() + .unwrap() + .get_fabric_mut(node.id().fabric_id()) + .map_err(anyhow::Error::msg)? + .add_node(node) + .map_err(anyhow::Error::msg) + } + + /// Class method: Update a node in a fabric. + #[export] + fn update_node( + #[try_from_ref] this: &PerlFabricConfig, + fabric_id: FabricId, + node_id: NodeId, + updater: NodeUpdater, + ) -> Result<(), Error> { + this.fabric_config + .lock() + .unwrap() + .get_fabric_mut(&fabric_id) + .map_err(anyhow::Error::msg)? + .update_node(&node_id, updater) + .map_err(anyhow::Error::msg) + } + + /// Class method: Delete a node in a fabric. + #[export] + fn delete_node( + #[try_from_ref] this: &PerlFabricConfig, + fabric_id: FabricId, + node_id: NodeId, + ) -> Result { + this.fabric_config + .lock() + .unwrap() + .get_fabric_mut(&fabric_id) + .map_err(anyhow::Error::msg)? + .delete_node(&node_id) + .map(Node::from) + .map_err(anyhow::Error::msg) + } + /// Class method: Convert the configuration into the section config sections. /// /// Used for writing the running configuration. -- 2.39.5 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel