Files
harmony/brocade/examples/main_vlan_demo.rs
2026-04-10 15:41:09 -04:00

243 lines
7.5 KiB
Rust

use std::io::{self, Write};
use brocade::{
BrocadeOptions, InterfaceConfig, InterfaceSpeed, InterfaceType, PortOperatingMode,
SwitchInterface, Vlan, VlanList, ssh,
};
use harmony_secret::{Secret, SecretManager};
use harmony_types::switch::PortLocation;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Secret, Clone, Debug, JsonSchema, Serialize, Deserialize)]
struct BrocadeSwitchAuth {
username: String,
password: String,
}
fn wait_for_enter() {
println!("\n--- Press ENTER to continue ---");
io::stdout().flush().unwrap();
io::stdin().read_line(&mut String::new()).unwrap();
}
#[tokio::main]
async fn main() {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
let ip0 = std::net::IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 12, 147));
let ip1 = std::net::IpAddr::V4(std::net::Ipv4Addr::new(192, 168, 12, 109));
let switch_addresses = vec![ip0, ip1];
let config = SecretManager::get_or_prompt::<BrocadeSwitchAuth>()
.await
.unwrap();
let brocade = brocade::init(
&switch_addresses,
&config.username,
&config.password,
&BrocadeOptions {
dry_run: false,
ssh: ssh::SshOptions {
port: 22,
..Default::default()
},
..Default::default()
},
)
.await
.expect("Brocade client failed to connect");
println!("=== Connecting to Brocade switches ===");
let version = brocade.version().await.unwrap();
println!("Version: {version:?}");
let entries = brocade.get_stack_topology().await.unwrap();
println!("Stack topology: {entries:#?}");
println!("\n=== Creating VLANs 100, 200, 300 ===");
brocade
.create_vlan(&Vlan {
id: 100,
name: "vlan100".to_string(),
})
.await
.unwrap();
println!("Created VLAN 100 (vlan100)");
brocade
.create_vlan(&Vlan {
id: 200,
name: "vlan200".to_string(),
})
.await
.unwrap();
println!("Created VLAN 200 (vlan200)");
brocade
.create_vlan(&Vlan {
id: 300,
name: "vlan300".to_string(),
})
.await
.unwrap();
println!("Created VLAN 300 (vlan300)");
println!("\n=== Press ENTER to continue to port configuration tests ---");
wait_for_enter();
println!("\n=== TEST 1: Trunk port (all VLANs, speed 10Gbps) on TenGigabitEthernet 1/0/1 ===");
println!("Configuring port as trunk with all VLANs and speed 10Gbps...");
let configs = vec![InterfaceConfig {
interface: SwitchInterface::Ethernet(
InterfaceType::TenGigabitEthernet,
PortLocation(1, 0, 1),
),
mode: PortOperatingMode::Trunk,
access_vlan: None,
trunk_vlans: Some(VlanList::All),
speed: Some(InterfaceSpeed::Gbps10),
}];
brocade.configure_interfaces(&configs).await.unwrap();
println!("Querying interfaces...");
let interfaces = brocade.get_interfaces().await.unwrap();
for iface in &interfaces {
if iface.name.contains("1/0/1") {
println!(" {iface:?}");
}
}
wait_for_enter();
println!("\n=== TEST 2: Trunk port (specific VLANs) on TenGigabitEthernet 1/0/2 ===");
println!("Configuring port as trunk with VLANs 100, 200...");
let configs = vec![InterfaceConfig {
interface: SwitchInterface::Ethernet(
InterfaceType::TenGigabitEthernet,
PortLocation(1, 0, 2),
),
mode: PortOperatingMode::Trunk,
access_vlan: None,
trunk_vlans: Some(VlanList::Specific(vec![
Vlan {
id: 100,
name: "vlan100".to_string(),
},
Vlan {
id: 200,
name: "vlan200".to_string(),
},
])),
speed: None,
}];
brocade.configure_interfaces(&configs).await.unwrap();
println!("Querying interfaces...");
let interfaces = brocade.get_interfaces().await.unwrap();
for iface in &interfaces {
if iface.name.contains("1/0/2") {
println!(" {iface:?}");
}
}
wait_for_enter();
println!("\n=== TEST 3: Access port (default VLAN 1) on TenGigabitEthernet 1/0/3 ===");
println!("Configuring port as access (default VLAN 1)...");
let configs = vec![InterfaceConfig {
interface: SwitchInterface::Ethernet(
InterfaceType::TenGigabitEthernet,
PortLocation(1, 0, 3),
),
mode: PortOperatingMode::Access,
access_vlan: None,
trunk_vlans: None,
speed: None,
}];
brocade.configure_interfaces(&configs).await.unwrap();
println!("Querying interfaces...");
let interfaces = brocade.get_interfaces().await.unwrap();
for iface in &interfaces {
if iface.name.contains("1/0/3") {
println!(" {iface:?}");
}
}
wait_for_enter();
println!("\n=== TEST 4: Access port (custom VLAN 100) on TenGigabitEthernet 1/0/4 ===");
println!("Configuring port as access with VLAN 100...");
let configs = vec![InterfaceConfig {
interface: SwitchInterface::Ethernet(
InterfaceType::TenGigabitEthernet,
PortLocation(1, 0, 4),
),
mode: PortOperatingMode::Access,
access_vlan: Some(100),
trunk_vlans: None,
speed: None,
}];
brocade.configure_interfaces(&configs).await.unwrap();
println!("Querying interfaces...");
let interfaces = brocade.get_interfaces().await.unwrap();
for iface in &interfaces {
if iface.name.contains("1/0/4") {
println!(" {iface:?}");
}
}
wait_for_enter();
println!("\n=== TEST 5: Port-channel on TenGigabitEthernet 1/0/5 and 1/0/6 ===");
let channel_id = 1;
println!("Using channel ID: {channel_id}");
println!("Creating port-channel with ports 1/0/5 and 1/0/6...");
let ports = [PortLocation(1, 0, 5), PortLocation(1, 0, 6)];
brocade
.create_port_channel(channel_id, "HARMONY_LAG", &ports, None)
.await
.unwrap();
println!("Port-channel created.");
println!("Querying port-channel summary...");
let interfaces = brocade.get_interfaces().await.unwrap();
for iface in &interfaces {
if iface.name.contains("1/0/5") || iface.name.contains("1/0/6") {
println!(" {iface:?}");
}
}
wait_for_enter();
println!("\n=== TEARDOWN: Clearing port-channels and deleting VLANs ===");
println!("Clearing port-channel {channel_id}...");
brocade
.clear_port_channel(&channel_id.to_string())
.await
.unwrap();
println!("Resetting interfaces...");
for port in 1..=6 {
let interface = format!("TenGigabitEthernet 1/0/{port}");
println!(" Resetting {interface}...");
brocade.reset_interface(&interface).await.unwrap();
}
println!("Deleting VLAN 100...");
brocade
.delete_vlan(&Vlan {
id: 100,
name: "vlan100".to_string(),
})
.await
.unwrap();
println!("Deleting VLAN 200...");
brocade
.delete_vlan(&Vlan {
id: 200,
name: "vlan200".to_string(),
})
.await
.unwrap();
println!("Deleting VLAN 300...");
brocade
.delete_vlan(&Vlan {
id: 300,
name: "vlan300".to_string(),
})
.await
.unwrap();
println!("\n=== DONE ===");
}