diff --git a/examples/brocade_switch/src/main.rs b/examples/brocade_switch/src/main.rs index a99263de..0fff8460 100644 --- a/examples/brocade_switch/src/main.rs +++ b/examples/brocade_switch/src/main.rs @@ -1,22 +1,25 @@ use std::str::FromStr; -use async_trait::async_trait; use brocade::{BrocadeOptions, PortOperatingMode}; use harmony::{ - data::Version, - infra::brocade::BrocadeSwitchClient, - interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, + infra::brocade::BrocadeSwitchConfig, inventory::Inventory, - score::Score, - topology::{ - HostNetworkConfig, PortConfig, PreparationError, PreparationOutcome, Switch, SwitchClient, - SwitchError, Topology, - }, + modules::brocade::{BrocadeSwitchScore, SwitchTopology}, }; use harmony_macros::ip; -use harmony_types::{id::Id, net::MacAddress, switch::PortLocation}; -use log::{debug, info}; -use serde::Serialize; +use harmony_types::{id::Id, switch::PortLocation}; + +fn get_switch_config() -> BrocadeSwitchConfig { + let mut options = BrocadeOptions::default(); + options.ssh.port = 2222; + + BrocadeSwitchConfig { + ips: vec![ip!("127.0.0.1")], + username: "admin".to_string(), + password: "password".to_string(), + options, + } +} #[tokio::main] async fn main() { @@ -32,126 +35,13 @@ async fn main() { (PortLocation(1, 0, 18), PortOperatingMode::Trunk), ], }; + harmony_cli::run( Inventory::autoload(), - SwitchTopology::new().await, + SwitchTopology::new(get_switch_config()).await, vec![Box::new(switch_score)], None, ) .await .unwrap(); } - -#[derive(Clone, Debug, Serialize)] -struct BrocadeSwitchScore { - port_channels_to_clear: Vec, - ports_to_configure: Vec, -} - -impl Score for BrocadeSwitchScore { - fn name(&self) -> String { - "BrocadeSwitchScore".to_string() - } - - #[doc(hidden)] - fn create_interpret(&self) -> Box> { - Box::new(BrocadeSwitchInterpret { - score: self.clone(), - }) - } -} - -#[derive(Debug)] -struct BrocadeSwitchInterpret { - score: BrocadeSwitchScore, -} - -#[async_trait] -impl Interpret for BrocadeSwitchInterpret { - async fn execute( - &self, - _inventory: &Inventory, - topology: &T, - ) -> Result { - info!("Applying switch configuration {:?}", self.score); - debug!( - "Clearing port channel {:?}", - self.score.port_channels_to_clear - ); - topology - .clear_port_channel(&self.score.port_channels_to_clear) - .await - .map_err(|e| InterpretError::new(e.to_string()))?; - debug!("Configuring interfaces {:?}", self.score.ports_to_configure); - topology - .configure_interface(&self.score.ports_to_configure) - .await - .map_err(|e| InterpretError::new(e.to_string()))?; - Ok(Outcome::success("switch configured".to_string())) - } - fn get_name(&self) -> InterpretName { - InterpretName::Custom("BrocadeSwitchInterpret") - } - fn get_version(&self) -> Version { - todo!() - } - fn get_status(&self) -> InterpretStatus { - todo!() - } - fn get_children(&self) -> Vec { - todo!() - } -} - -struct SwitchTopology { - client: Box, -} - -#[async_trait] -impl Topology for SwitchTopology { - fn name(&self) -> &str { - "SwitchTopology" - } - - async fn ensure_ready(&self) -> Result { - Ok(PreparationOutcome::Noop) - } -} - -impl SwitchTopology { - async fn new() -> Self { - let mut options = BrocadeOptions::default(); - options.ssh.port = 2222; - let client = - BrocadeSwitchClient::init(&vec![ip!("127.0.0.1")], &"admin", &"password", options) - .await - .expect("Failed to connect to switch"); - - let client = Box::new(client); - Self { client } - } -} - -#[async_trait] -impl Switch for SwitchTopology { - async fn setup_switch(&self) -> Result<(), SwitchError> { - todo!() - } - - async fn get_port_for_mac_address( - &self, - _mac_address: &MacAddress, - ) -> Result, SwitchError> { - todo!() - } - - async fn configure_port_channel(&self, _config: &HostNetworkConfig) -> Result<(), SwitchError> { - todo!() - } - async fn clear_port_channel(&self, ids: &Vec) -> Result<(), SwitchError> { - self.client.clear_port_channel(ids).await - } - async fn configure_interface(&self, ports: &Vec) -> Result<(), SwitchError> { - self.client.configure_interface(ports).await - } -} diff --git a/harmony/src/infra/brocade.rs b/harmony/src/infra/brocade.rs index 2bc90d2b..26935afb 100644 --- a/harmony/src/infra/brocade.rs +++ b/harmony/src/infra/brocade.rs @@ -9,6 +9,14 @@ use option_ext::OptionExt; use crate::topology::{PortConfig, SwitchClient, SwitchError}; +#[derive(Debug, Clone)] +pub struct BrocadeSwitchConfig { + pub ips: Vec, + pub username: String, + pub password: String, + pub options: BrocadeOptions, +} + #[derive(Debug)] pub struct BrocadeSwitchClient { brocade: Box, diff --git a/harmony/src/modules/brocade/brocade.rs b/harmony/src/modules/brocade/brocade.rs new file mode 100644 index 00000000..b1331e53 --- /dev/null +++ b/harmony/src/modules/brocade/brocade.rs @@ -0,0 +1,143 @@ +use async_trait::async_trait; +use brocade::{BrocadeOptions, PortOperatingMode}; + +use crate::{ + data::Version, + infra::brocade::{BrocadeSwitchClient, BrocadeSwitchConfig}, + interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome}, + inventory::Inventory, + score::Score, + topology::{ + HostNetworkConfig, PortConfig, PreparationError, PreparationOutcome, Switch, SwitchClient, + SwitchError, Topology, + }, +}; +use harmony_macros::ip; +use harmony_types::{id::Id, net::MacAddress, switch::PortLocation}; +use log::{debug, info}; +use serde::Serialize; + +#[derive(Clone, Debug, Serialize)] +pub struct BrocadeSwitchScore { + pub port_channels_to_clear: Vec, + pub ports_to_configure: Vec, +} + +impl Score for BrocadeSwitchScore { + fn name(&self) -> String { + "BrocadeSwitchScore".to_string() + } + + #[doc(hidden)] + fn create_interpret(&self) -> Box> { + Box::new(BrocadeSwitchInterpret { + score: self.clone(), + }) + } +} + +#[derive(Debug)] +pub struct BrocadeSwitchInterpret { + score: BrocadeSwitchScore, +} + +#[async_trait] +impl Interpret for BrocadeSwitchInterpret { + async fn execute( + &self, + _inventory: &Inventory, + topology: &T, + ) -> Result { + info!("Applying switch configuration {:?}", self.score); + debug!( + "Clearing port channel {:?}", + self.score.port_channels_to_clear + ); + topology + .clear_port_channel(&self.score.port_channels_to_clear) + .await + .map_err(|e| InterpretError::new(e.to_string()))?; + debug!("Configuring interfaces {:?}", self.score.ports_to_configure); + topology + .configure_interface(&self.score.ports_to_configure) + .await + .map_err(|e| InterpretError::new(e.to_string()))?; + Ok(Outcome::success("switch configured".to_string())) + } + fn get_name(&self) -> InterpretName { + InterpretName::Custom("BrocadeSwitchInterpret") + } + fn get_version(&self) -> Version { + todo!() + } + fn get_status(&self) -> InterpretStatus { + todo!() + } + fn get_children(&self) -> Vec { + todo!() + } +} + +/* +pub struct BrocadeSwitchConfig { + pub ips: Vec, + pub username: String, + pub password: String, + pub options: BrocadeOptions, +} +*/ + +pub struct SwitchTopology { + client: Box, +} + +#[async_trait] +impl Topology for SwitchTopology { + fn name(&self) -> &str { + "SwitchTopology" + } + + async fn ensure_ready(&self) -> Result { + Ok(PreparationOutcome::Noop) + } +} + +impl SwitchTopology { + pub async fn new(config: BrocadeSwitchConfig) -> Self { + let client = BrocadeSwitchClient::init( + &config.ips, + &config.username, + &config.password, + config.options, + ) + .await + .expect("Failed to connect to switch"); + + let client = Box::new(client); + Self { client } + } +} + +#[async_trait] +impl Switch for SwitchTopology { + async fn setup_switch(&self) -> Result<(), SwitchError> { + todo!() + } + + async fn get_port_for_mac_address( + &self, + _mac_address: &MacAddress, + ) -> Result, SwitchError> { + todo!() + } + + async fn configure_port_channel(&self, _config: &HostNetworkConfig) -> Result<(), SwitchError> { + todo!() + } + async fn clear_port_channel(&self, ids: &Vec) -> Result<(), SwitchError> { + self.client.clear_port_channel(ids).await + } + async fn configure_interface(&self, ports: &Vec) -> Result<(), SwitchError> { + self.client.configure_interface(ports).await + } +} diff --git a/harmony/src/modules/brocade.rs b/harmony/src/modules/brocade/brocade_snmp.rs similarity index 100% rename from harmony/src/modules/brocade.rs rename to harmony/src/modules/brocade/brocade_snmp.rs diff --git a/harmony/src/modules/brocade/mod.rs b/harmony/src/modules/brocade/mod.rs new file mode 100644 index 00000000..1f197b9b --- /dev/null +++ b/harmony/src/modules/brocade/mod.rs @@ -0,0 +1,5 @@ +pub mod brocade; +pub use brocade::*; + +pub mod brocade_snmp; +pub use brocade_snmp::*;