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 BAA5A1FF16F for ; Tue, 8 Jul 2025 10:15:25 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 69B1610D5A; Tue, 8 Jul 2025 10:16:08 +0200 (CEST) Date: Tue, 8 Jul 2025 10:15:33 +0200 From: Wolfgang Bumiller To: Gabriel Goller Message-ID: References: <20250702145101.894299-1-g.goller@proxmox.com> <20250702145101.894299-22-g.goller@proxmox.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20250702145101.894299-22-g.goller@proxmox.com> X-SPAM-LEVEL: Spam detection results: 0 AWL 0.077 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 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_RPBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_SAFE_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [fabric.rs, node.rs] Subject: Re: [pve-devel] [PATCH proxmox-ve-rs v4 15/22] config: sdn: fabrics: add api types 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 Cc: pve-devel@lists.proxmox.com Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" minor doc nits On Wed, Jul 02, 2025 at 04:50:06PM +0200, Gabriel Goller wrote: > From: Stefan Hanreich > > Add an api submodule to the section config module, that provides the > types that are intended to be returned and accepted by the Perl API in > Proxmox VE. This allows us to decouple the format returned in the API > from the configuration format. > > This is particularly relevant in the case of the NodeSection type. > While the section config stores the composite ID of the node as the ID > of the section in the section config (and therefore as a single string > / property), we want to be able to return them as independent fields > from the API, to avoid having to parse the ID everywhere else we want > to use it. Thanks to the generic NodeSection type we only have to > define the conversion from / to the API type once, while the > protocol-specific types can stay the same. > > For the fabrics, we simply re-use the section_config types for now, > but by re-exporting them as type alias we are more flexible in > possibly changing the API types or the underlying section config types > later on. > > Co-authored-by: Gabriel Goller > Signed-off-by: Stefan Hanreich > --- > .../src/sdn/fabric/section_config/fabric.rs | 5 + > .../src/sdn/fabric/section_config/node.rs | 159 ++++++++++++++++++ > 2 files changed, 164 insertions(+) > > diff --git a/proxmox-ve-config/src/sdn/fabric/section_config/fabric.rs b/proxmox-ve-config/src/sdn/fabric/section_config/fabric.rs > index 8ecf725c4641..75a309398ca2 100644 > --- a/proxmox-ve-config/src/sdn/fabric/section_config/fabric.rs > +++ b/proxmox-ve-config/src/sdn/fabric/section_config/fabric.rs > @@ -233,3 +233,8 @@ pub enum FabricDeletableProperties { > #[serde(untagged)] > Protocol(T), > } > + > +pub mod api { > + pub type Fabric = super::Fabric; > + pub type FabricUpdater = super::FabricUpdater; > +} > diff --git a/proxmox-ve-config/src/sdn/fabric/section_config/node.rs b/proxmox-ve-config/src/sdn/fabric/section_config/node.rs > index bd5ffea854d7..6bccbb7468ed 100644 > --- a/proxmox-ve-config/src/sdn/fabric/section_config/node.rs > +++ b/proxmox-ve-config/src/sdn/fabric/section_config/node.rs > @@ -223,3 +223,162 @@ impl From> for Node { > Self::Ospf(value) > } > } > + > +/// API types for SDN fabric node configurations. > +/// > +/// This module provides specialized types that are used for API interactions when retrieving, > +/// creating, or updating fabric/node configurations. These types serialize differently than their > +/// section-config configuration counterparts to be nicer client-side. > +/// > +/// The module includes: > +/// - [NodeData]: API-friendly version of [NodeSection] that flattens the node identifier > +/// into separate `fabric_id` and `node_id` fields > +/// - [Node]: API-version of [super::Node] > +/// - [NodeDataUpdater] > +/// - [NodeDeletableProperties] ^ The types in those links should also be in backticks. > +/// > +/// These types include conversion methods to transform between API representations and internal > +/// configuration objects. > +pub mod api { > + use serde::{Deserialize, Serialize}; > + > + use proxmox_schema::{Updater, UpdaterType}; > + > + use crate::sdn::fabric::section_config::protocol::{ > + openfabric::{ > + OpenfabricNodeDeletableProperties, OpenfabricNodeProperties, > + OpenfabricNodePropertiesUpdater, > + }, > + ospf::{OspfNodeDeletableProperties, OspfNodeProperties, OspfNodePropertiesUpdater}, > + }; > + > + use super::*; > + > + /// API-equivalent to [NodeSection]. ^ backticks > + /// > + /// The difference is that instead of serializing fabric_id and node_id into a single string > + /// (`{fabric_id}_{node_id}`), are serialized normally as two distinct properties. This > + /// prevents us from needing to parse the node_id in the frontend using `split("_")`. > + #[derive(Debug, Clone, Serialize, Deserialize)] > + pub struct NodeData { > + fabric_id: FabricId, > + node_id: NodeId, > + > + /// IPv4 for this node in the Ospf fabric > + #[serde(skip_serializing_if = "Option::is_none")] > + ip: Option, > + > + /// IPv6 for this node in the Ospf fabric > + #[serde(skip_serializing_if = "Option::is_none")] > + ip6: Option, > + > + #[serde(flatten)] > + properties: T, > + } > + > + impl From> for NodeData { > + fn from(value: NodeSection) -> Self { > + Self { > + fabric_id: value.id.fabric_id, > + node_id: value.id.node_id, > + ip: value.ip, > + ip6: value.ip6, > + properties: value.properties, > + } > + } > + } > + > + impl From> for NodeSection { > + fn from(value: NodeData) -> Self { > + let id = NodeSectionId::new(value.fabric_id, value.node_id); > + > + Self { > + id, > + ip: value.ip, > + ip6: value.ip6, > + properties: value.properties, > + } > + } > + } > + > + /// API-equivalent to [super::Node]. ^ backticks > + #[derive(Debug, Clone, Serialize, Deserialize)] > + #[serde(rename_all = "snake_case", tag = "protocol")] > + pub enum Node { > + Openfabric(NodeData), > + Ospf(NodeData), > + } > + > + impl From for Node { > + fn from(value: super::Node) -> Self { > + match value { > + super::Node::Openfabric(node_section) => Self::Openfabric(node_section.into()), > + super::Node::Ospf(node_section) => Self::Ospf(node_section.into()), > + } > + } > + } > + > + impl From for super::Node { > + fn from(value: Node) -> Self { > + match value { > + Node::Openfabric(node_section) => Self::Openfabric(node_section.into()), > + Node::Ospf(node_section) => Self::Ospf(node_section.into()), > + } > + } > + } > + > + impl UpdaterType for NodeData { > + type Updater = > + NodeDataUpdater; > + } > + > + impl UpdaterType for NodeData { > + type Updater = NodeDataUpdater; > + } > + > + #[derive(Debug, Clone, Serialize, Deserialize)] > + pub struct NodeDataUpdater { > + #[serde(skip_serializing_if = "Option::is_none")] > + pub(crate) ip: Option, > + > + #[serde(skip_serializing_if = "Option::is_none")] > + pub(crate) ip6: Option, > + > + #[serde(flatten)] > + pub(crate) properties: T, > + > + #[serde(skip_serializing_if = "Vec::is_empty", default = "Vec::new")] (^ the `= "Vec::new"` should not be necessary, but doesn't matter either - new is `const` so it's probably more efficient this way anyawy...) > + pub(crate) delete: Vec>, > + } > + > + impl UpdaterType for NodeDataUpdater { > + type Updater = NodeDataUpdater; > + } > + > + impl Updater for NodeDataUpdater { > + fn is_empty(&self) -> bool { > + T::is_empty(&self.properties) > + && self.ip.is_none() > + && self.ip6.is_none() > + && self.delete.is_empty() > + } > + } > + > + #[derive(Debug, Clone, Serialize, Deserialize)] > + #[serde(rename_all = "snake_case", tag = "protocol")] > + pub enum NodeUpdater { > + Openfabric( > + NodeDataUpdater, > + ), > + Ospf(NodeDataUpdater), > + } > + > + #[derive(Debug, Clone, Serialize, Deserialize)] > + #[serde(rename_all = "snake_case")] > + pub enum NodeDeletableProperties { > + Ip, > + Ip6, > + #[serde(untagged)] > + Protocol(T), > + } > +} > -- > 2.39.5 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel