On Wed, Jul 02, 2025 at 04:50:18PM +0200, Gabriel Goller wrote: > From: Stefan Hanreich <s.hanre...@proxmox.com> > > In PVE we use the GET /nodes/{node}/network API endpoint to return all > currently configured network interfaces on a specific node. In order > to be able to use SDN fabrics in Ceph and the migration settings, we > add a helper method that returns all fabrics formatted in the same > format as the pre-existing PVE API call. This enables us to return the > SDN fabrics in the endpoint so users can select the fabrics from the > UI, integrating the fabrics with the existing UI components. > > Co-authored-by: Gabriel Goller <g.gol...@proxmox.com> > Signed-off-by: Stefan Hanreich <s.hanre...@proxmox.com> > --- > pve-rs/src/bindings/sdn/fabrics.rs | 54 ++++++++++++++++++++++++++++-- > 1 file changed, 52 insertions(+), 2 deletions(-) > > diff --git a/pve-rs/src/bindings/sdn/fabrics.rs > b/pve-rs/src/bindings/sdn/fabrics.rs > index 099c1a7ab515..f5abb1b72099 100644 > --- a/pve-rs/src/bindings/sdn/fabrics.rs > +++ b/pve-rs/src/bindings/sdn/fabrics.rs > @@ -17,7 +17,7 @@ pub mod pve_rs_sdn_fabrics { > > use perlmod::Value; > use proxmox_frr::serializer::to_raw_config; > - use proxmox_network_types::ip_address::Cidr; > + use proxmox_network_types::ip_address::{Cidr, Ipv4Cidr, Ipv6Cidr}; > use proxmox_section_config::typed::SectionConfigData; > use proxmox_ve_config::common::valid::Validatable; > > @@ -25,7 +25,7 @@ pub mod pve_rs_sdn_fabrics { > section_config::{ > fabric::{ > api::{Fabric, FabricUpdater}, > - FabricId, > + Fabric as ConfigFabric, FabricId, > }, > node::{ > api::{Node, NodeUpdater}, > @@ -46,6 +46,34 @@ pub mod pve_rs_sdn_fabrics { > > perlmod::declare_magic!(Box<PerlFabricConfig> : &PerlFabricConfig as > "PVE::RS::SDN::Fabrics::Config"); > > + /// Represents a interface as returned by the `GET > /nodes/{node}/network` endpoint in PVE.
an* > + /// > + /// This is used for returning fabrics in the endpoint, so they can be > used from various places > + /// in the PVE UI (e.g. migration network settings). > + #[derive(Serialize, Deserialize)] It seems we currently only serialize this, so could drop the `Deserialize` here since it's a private helper type anyway right now. > + struct PveInterface { > + iface: String, > + #[serde(rename = "type")] > + ty: String, > + active: bool, > + #[serde(skip_serializing_if = "Option::is_none")] > + cidr: Option<Ipv4Cidr>, > + #[serde(skip_serializing_if = "Option::is_none")] > + cidr6: Option<Ipv6Cidr>, > + } > + > + impl From<ConfigFabric> for PveInterface { > + fn from(fabric: ConfigFabric) -> Self { > + Self { > + iface: fabric.id().to_string(), > + ty: "fabric".to_string(), > + active: true, > + cidr: fabric.ip_prefix(), > + cidr6: fabric.ip6_prefix(), > + } > + } > + } > + > /// Parse the raw configuration from `/etc/pve/sdn/fabrics.cfg`. > #[export] > fn config(#[raw] class: Value, raw_config: &[u8]) -> > Result<perlmod::Value, Error> { > @@ -308,6 +336,28 @@ pub mod pve_rs_sdn_fabrics { > Ok(hex::encode(hash)) > } > > + /// Class method: Return all interfaces of a node, that are part of a > fabric. > + #[export] > + fn get_interfaces_for_node( > + #[try_from_ref] this: &PerlFabricConfig, > + node_id: NodeId, > + ) -> BTreeMap<String, PveInterface> { > + let config = this.fabric_config.lock().unwrap(); > + > + let mut ifaces = BTreeMap::new(); > + > + for entry in config.values() { > + if entry.get_node(&node_id).is_ok() { > + ifaces.insert( > + entry.fabric().id().to_string(), > + entry.fabric().clone().into(), > + ); > + } > + } > + > + ifaces > + } > + > /// Class method: Return all FRR daemons that need to be enabled for > this fabric configuration > /// instance. > #[export] > -- > 2.39.5 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel