diff --git a/pbs-api-types/src/network.rs b/pbs-api-types/src/network.rs index e3a5e481..fe083dc6 100644 --- a/pbs-api-types/src/network.rs +++ b/pbs-api-types/src/network.rs @@ -224,6 +224,15 @@ pub const NETWORK_INTERFACE_LIST_SCHEMA: Schema = schema: NETWORK_INTERFACE_ARRAY_SCHEMA, optional: true, }, + "vlan-id": { + description: "VLAN ID.", + type: u16, + optional: true, + }, + "vlan-raw-device": { + schema: NETWORK_INTERFACE_NAME_SCHEMA, + optional: true, + }, bond_mode: { type: LinuxBondMode, optional: true, @@ -287,6 +296,12 @@ pub struct Interface { /// Enable bridge vlan support. #[serde(skip_serializing_if = "Option::is_none")] pub bridge_vlan_aware: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(rename = "vlan-id")] + pub vlan_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(rename = "vlan-raw-device")] + pub vlan_raw_device: Option, #[serde(skip_serializing_if = "Option::is_none")] pub slaves: Option>, @@ -319,6 +334,8 @@ impl Interface { mtu: None, bridge_ports: None, bridge_vlan_aware: None, + vlan_id: None, + vlan_raw_device: None, slaves: None, bond_mode: None, bond_primary: None, diff --git a/pbs-config/src/network/mod.rs b/pbs-config/src/network/mod.rs index 08abe23b..02117535 100644 --- a/pbs-config/src/network/mod.rs +++ b/pbs-config/src/network/mod.rs @@ -79,6 +79,14 @@ fn write_iface_attributes(iface: &Interface, w: &mut dyn Write) -> Result<(), Er writeln!(w, "\tbond-slaves {}", slaves.join(" "))?; } } + NetworkInterfaceType::Vlan => { + if let Some(vlan_id) = iface.vlan_id { + writeln!(w, "\tvlan-id {vlan_id}")?; + } + if let Some(vlan_raw_device) = &iface.vlan_raw_device { + writeln!(w, "\tvlan-raw-device {vlan_raw_device}")?; + } + } _ => {} } @@ -580,4 +588,68 @@ iface enp3s0 inet static .trim() ); } + + #[test] + fn test_write_network_config_vlan_id_in_name() { + let iface_name = String::from("vmbr0.100"); + let mut iface = Interface::new(iface_name.clone()); + iface.interface_type = Vlan; + iface.method = Some(Manual); + iface.active = true; + + let nw_config = NetworkConfig { + interfaces: BTreeMap::from([(iface_name.clone(), iface)]), + order: vec![Iface(iface_name.clone())], + }; + assert_eq!( + String::try_from(nw_config).unwrap().trim(), + "iface vmbr0.100 inet manual" + ); + } + + #[test] + fn test_write_network_config_vlan_with_raw_device() { + let iface_name = String::from("vlan100"); + let mut iface = Interface::new(iface_name.clone()); + iface.interface_type = Vlan; + iface.vlan_raw_device = Some(String::from("vmbr0")); + iface.method = Some(Manual); + iface.active = true; + + let nw_config = NetworkConfig { + interfaces: BTreeMap::from([(iface_name.clone(), iface)]), + order: vec![Iface(iface_name.clone())], + }; + assert_eq!( + String::try_from(nw_config).unwrap().trim(), + r#" +iface vlan100 inet manual + vlan-raw-device vmbr0"# + .trim() + ); + } + + #[test] + fn test_write_network_config_vlan_with_individual_name() { + let iface_name = String::from("individual_name"); + let mut iface = Interface::new(iface_name.clone()); + iface.interface_type = Vlan; + iface.vlan_raw_device = Some(String::from("vmbr0")); + iface.vlan_id = Some(100); + iface.method = Some(Manual); + iface.active = true; + + let nw_config = NetworkConfig { + interfaces: BTreeMap::from([(iface_name.clone(), iface)]), + order: vec![Iface(iface_name.clone())], + }; + assert_eq!( + String::try_from(nw_config).unwrap().trim(), + r#" +iface individual_name inet manual + vlan-id 100 + vlan-raw-device vmbr0"# + .trim() + ); + } }