From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <pve-devel-bounces@lists.proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68])
	by lore.proxmox.com (Postfix) with ESMTPS id 12DEA1FF15C
	for <inbox@lore.proxmox.com>; Fri,  4 Apr 2025 18:30:11 +0200 (CEST)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
	by firstgate.proxmox.com (Proxmox) with ESMTP id 9FAE6375EE;
	Fri,  4 Apr 2025 18:29:22 +0200 (CEST)
From: Gabriel Goller <g.goller@proxmox.com>
To: pve-devel@lists.proxmox.com
Date: Fri,  4 Apr 2025 18:28:21 +0200
Message-Id: <20250404162908.563060-11-g.goller@proxmox.com>
X-Mailer: git-send-email 2.39.5
In-Reply-To: <20250404162908.563060-1-g.goller@proxmox.com>
References: <20250404162908.563060-1-g.goller@proxmox.com>
MIME-Version: 1.0
X-SPAM-LEVEL: Spam detection results:  0
 AWL -0.023 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 v2 09/15] ve-config: add common
 section-config types for OpenFabric and OSPF
X-BeenThere: pve-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox VE development discussion <pve-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pve-devel/>
List-Post: <mailto:pve-devel@lists.proxmox.com>
List-Help: <mailto:pve-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=subscribe>
Reply-To: Proxmox VE development discussion <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" <pve-devel-bounces@lists.proxmox.com>

Introduce shared types for SDN fabric configuration:
- FabricId: String identifier used in both OpenFabric and OSPF configurations
- NodeId: Composite identifier for fabric nodes consisting of FabricId and Hostname
- SectionType: Enum differentiating between fabric and node sections, automatically
  added as a "type" property

These allow us to be somewhat generic over the protocol type (in e.g.
permissions).

Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
---
 proxmox-ve-config/src/sdn/fabric/mod.rs | 111 ++++++++++++++++++++++++
 1 file changed, 111 insertions(+)
 create mode 100644 proxmox-ve-config/src/sdn/fabric/mod.rs

diff --git a/proxmox-ve-config/src/sdn/fabric/mod.rs b/proxmox-ve-config/src/sdn/fabric/mod.rs
new file mode 100644
index 000000000000..5b24a3be8c17
--- /dev/null
+++ b/proxmox-ve-config/src/sdn/fabric/mod.rs
@@ -0,0 +1,111 @@
+pub mod openfabric;
+pub mod ospf;
+
+use proxmox_network_types::debian::Hostname;
+use proxmox_section_config::typed::ApiSectionDataEntry;
+use proxmox_section_config::typed::SectionConfigData;
+
+use std::ops::Deref;
+
+use serde::de::DeserializeOwned;
+use serde_with::{DeserializeFromStr, SerializeDisplay};
+
+#[derive(
+    SerializeDisplay, DeserializeFromStr, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
+)]
+pub struct FabricId(String);
+
+impl FabricId {
+    pub fn new(id: impl Into<String>) -> Result<Self, anyhow::Error> {
+        let value = id.into();
+        if value.len() <= 8 {
+            Ok(Self(value))
+        } else {
+            anyhow::bail!("FabricId has to be shorter than 8 characters");
+        }
+    }
+}
+
+impl AsRef<str> for FabricId {
+    fn as_ref(&self) -> &str {
+        &self.0
+    }
+}
+
+impl std::str::FromStr for FabricId {
+    type Err = anyhow::Error;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        Self::new(s)
+    }
+}
+
+impl std::fmt::Display for FabricId {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+#[derive(SerializeDisplay, DeserializeFromStr, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct NodeId {
+    pub fabric_id: FabricId,
+    pub node_id: Hostname,
+}
+
+impl std::fmt::Display for NodeId {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{}_{}", self.fabric_id, self.node_id)
+    }
+}
+
+impl NodeId {
+    pub fn new(fabric_id: FabricId, node_id: Hostname) -> NodeId {
+        NodeId { fabric_id, node_id }
+    }
+}
+
+impl std::str::FromStr for NodeId {
+    type Err = anyhow::Error;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        if let Some((fabric_id, node_id)) = s.split_once('_') {
+            return Ok(NodeId {
+                fabric_id: fabric_id.parse()?,
+                node_id: node_id.parse()?,
+            });
+        }
+
+        anyhow::bail!("invalid node id");
+    }
+}
+
+#[derive(
+    SerializeDisplay, DeserializeFromStr, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
+)]
+pub enum SectionType {
+    Fabric,
+    Node,
+}
+
+impl std::fmt::Display for SectionType {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let name = match self {
+            Self::Fabric => "fabric",
+            Self::Node => "node",
+        };
+
+        write!(f, "{name}")
+    }
+}
+
+impl std::str::FromStr for SectionType {
+    type Err = anyhow::Error;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        Ok(match s {
+            "fabric" => Self::Fabric,
+            "node" => Self::Node,
+            _ => anyhow::bail!("invalid fabric type: {s}"),
+        })
+    }
+}
-- 
2.39.5



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel