Compare commits
2 Commits
fix/opnsen
...
feat/broca
| Author | SHA1 | Date | |
|---|---|---|---|
| 93ac89157a | |||
| 5953bc58f4 |
@@ -1,7 +1,8 @@
|
|||||||
use super::BrocadeClient;
|
use super::BrocadeClient;
|
||||||
use crate::{
|
use crate::{
|
||||||
BrocadeInfo, Error, ExecutionMode, InterSwitchLink, InterfaceInfo, MacAddressEntry,
|
BrocadeInfo, Error, ExecutionMode, InterSwitchLink, InterfaceInfo, MacAddressEntry,
|
||||||
PortChannelId, PortOperatingMode, parse_brocade_mac_address, shell::BrocadeShell,
|
PortChannelId, PortOperatingMode, SecurityLevel, parse_brocade_mac_address,
|
||||||
|
shell::BrocadeShell,
|
||||||
};
|
};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
@@ -209,4 +210,20 @@ impl BrocadeClient for FastIronClient {
|
|||||||
info!("[Brocade] Port-channel '{channel_name}' cleared.");
|
info!("[Brocade] Port-channel '{channel_name}' cleared.");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn enable_snmp(&self, user_name: &str, auth: &str, des: &str) -> Result<(), Error> {
|
||||||
|
let commands = vec![
|
||||||
|
"configure terminal".into(),
|
||||||
|
"snmp-server view ALL 1 included".into(),
|
||||||
|
"snmp-server group public v3 priv read ALL".into(),
|
||||||
|
format!(
|
||||||
|
"snmp-server user {user_name} groupname public auth md5 auth-password {auth} priv des priv-password {des}"
|
||||||
|
),
|
||||||
|
"exit".into(),
|
||||||
|
];
|
||||||
|
self.shell
|
||||||
|
.run_commands(commands, ExecutionMode::Regular)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -237,6 +237,15 @@ pub trait BrocadeClient: std::fmt::Debug {
|
|||||||
ports: &[PortLocation],
|
ports: &[PortLocation],
|
||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Enables Simple Network Management Protocol (SNMP) server for switch
|
||||||
|
///
|
||||||
|
/// # Parameters
|
||||||
|
///
|
||||||
|
/// * `user_name`: The user name for the snmp server
|
||||||
|
/// * `auth`: The password for authentication process for verifying the identity of a device
|
||||||
|
/// * `des`: The Data Encryption Standard algorithm key
|
||||||
|
async fn enable_snmp(&self, user_name: &str, auth: &str, des: &str) -> Result<(), Error>;
|
||||||
|
|
||||||
/// Removes all configuration associated with the specified Port-Channel name.
|
/// Removes all configuration associated with the specified Port-Channel name.
|
||||||
///
|
///
|
||||||
/// This operation should be idempotent; attempting to clear a non-existent
|
/// This operation should be idempotent; attempting to clear a non-existent
|
||||||
@@ -300,6 +309,11 @@ fn parse_brocade_mac_address(value: &str) -> Result<MacAddress, String> {
|
|||||||
Ok(MacAddress(bytes))
|
Ok(MacAddress(bytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SecurityLevel {
|
||||||
|
AuthPriv(String),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
NetworkError(String),
|
NetworkError(String),
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use regex::Regex;
|
|||||||
use crate::{
|
use crate::{
|
||||||
BrocadeClient, BrocadeInfo, Error, ExecutionMode, InterSwitchLink, InterfaceInfo,
|
BrocadeClient, BrocadeInfo, Error, ExecutionMode, InterSwitchLink, InterfaceInfo,
|
||||||
InterfaceStatus, InterfaceType, MacAddressEntry, PortChannelId, PortOperatingMode,
|
InterfaceStatus, InterfaceType, MacAddressEntry, PortChannelId, PortOperatingMode,
|
||||||
parse_brocade_mac_address, shell::BrocadeShell,
|
SecurityLevel, parse_brocade_mac_address, shell::BrocadeShell,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -330,4 +330,20 @@ impl BrocadeClient for NetworkOperatingSystemClient {
|
|||||||
info!("[Brocade] Port-channel '{channel_name}' cleared.");
|
info!("[Brocade] Port-channel '{channel_name}' cleared.");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn enable_snmp(&self, user_name: &str, auth: &str, des: &str) -> Result<(), Error> {
|
||||||
|
let commands = vec![
|
||||||
|
"configure terminal".into(),
|
||||||
|
"snmp-server view ALL 1 included".into(),
|
||||||
|
"snmp-server group public v3 priv read ALL".into(),
|
||||||
|
format!(
|
||||||
|
"snmp-server user {user_name} groupname public auth md5 auth-password {auth} priv des priv-password {des}"
|
||||||
|
),
|
||||||
|
"exit".into(),
|
||||||
|
];
|
||||||
|
self.shell
|
||||||
|
.run_commands(commands, ExecutionMode::Regular)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
examples/brocade_snmp_server/Cargo.toml
Normal file
20
examples/brocade_snmp_server/Cargo.toml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
[package]
|
||||||
|
name = "brocade-snmp-server"
|
||||||
|
edition = "2024"
|
||||||
|
version.workspace = true
|
||||||
|
readme.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
harmony = { path = "../../harmony" }
|
||||||
|
brocade = { path = "../../brocade" }
|
||||||
|
harmony_secret = { path = "../../harmony_secret" }
|
||||||
|
harmony_cli = { path = "../../harmony_cli" }
|
||||||
|
harmony_types = { path = "../../harmony_types" }
|
||||||
|
harmony_macros = { path = "../../harmony_macros" }
|
||||||
|
tokio = { workspace = true }
|
||||||
|
log = { workspace = true }
|
||||||
|
env_logger = { workspace = true }
|
||||||
|
url = { workspace = true }
|
||||||
|
base64.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
22
examples/brocade_snmp_server/src/main.rs
Normal file
22
examples/brocade_snmp_server/src/main.rs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
use std::net::{IpAddr, Ipv4Addr};
|
||||||
|
|
||||||
|
use harmony::{
|
||||||
|
inventory::Inventory, modules::brocade::BrocadeEnableSnmpScore, topology::K8sAnywhereTopology,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let brocade_snmp_server = BrocadeEnableSnmpScore {
|
||||||
|
server_ips: vec![IpAddr::V4(Ipv4Addr::new(192, 168, 1, 111))],
|
||||||
|
dry_run: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
harmony_cli::run(
|
||||||
|
Inventory::autoload(),
|
||||||
|
K8sAnywhereTopology::from_env(),
|
||||||
|
vec![Box::new(brocade_snmp_server)],
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
@@ -121,7 +121,7 @@ mod tests {
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use brocade::{
|
use brocade::{
|
||||||
BrocadeClient, BrocadeInfo, Error, InterSwitchLink, InterfaceInfo, InterfaceStatus,
|
BrocadeClient, BrocadeInfo, Error, InterSwitchLink, InterfaceInfo, InterfaceStatus,
|
||||||
InterfaceType, MacAddressEntry, PortChannelId, PortOperatingMode,
|
InterfaceType, MacAddressEntry, PortChannelId, PortOperatingMode, SecurityLevel,
|
||||||
};
|
};
|
||||||
use harmony_types::switch::PortLocation;
|
use harmony_types::switch::PortLocation;
|
||||||
|
|
||||||
@@ -279,6 +279,10 @@ mod tests {
|
|||||||
async fn clear_port_channel(&self, _channel_name: &str) -> Result<(), Error> {
|
async fn clear_port_channel(&self, _channel_name: &str) -> Result<(), Error> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn enable_snmp(&self, user_name: &str, auth: &str, des: &str) -> Result<(), Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FakeBrocadeClient {
|
impl FakeBrocadeClient {
|
||||||
|
|||||||
117
harmony/src/modules/brocade.rs
Normal file
117
harmony/src/modules/brocade.rs
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
use std::net::{IpAddr, Ipv4Addr};
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use brocade::BrocadeOptions;
|
||||||
|
use harmony_secret::{Secret, SecretManager};
|
||||||
|
use harmony_types::id::Id;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
data::Version,
|
||||||
|
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
||||||
|
inventory::Inventory,
|
||||||
|
score::Score,
|
||||||
|
topology::Topology,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct BrocadeEnableSnmpScore {
|
||||||
|
pub server_ips: Vec<IpAddr>,
|
||||||
|
pub dry_run: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Topology> Score<T> for BrocadeEnableSnmpScore {
|
||||||
|
fn name(&self) -> String {
|
||||||
|
"BrocadeEnableSnmpScore".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_interpret(&self) -> Box<dyn Interpret<T>> {
|
||||||
|
Box::new(BrocadeEnableSnmpInterpret {
|
||||||
|
score: self.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct BrocadeEnableSnmpInterpret {
|
||||||
|
score: BrocadeEnableSnmpScore,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Secret, Clone, Debug, Serialize, Deserialize)]
|
||||||
|
struct BrocadeSwitchAuth {
|
||||||
|
username: String,
|
||||||
|
password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Secret, Clone, Debug, Serialize, Deserialize)]
|
||||||
|
struct BrocadeSnmpAuth {
|
||||||
|
username: String,
|
||||||
|
auth_password: String,
|
||||||
|
des_password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<T: Topology> Interpret<T> for BrocadeEnableSnmpInterpret {
|
||||||
|
async fn execute(
|
||||||
|
&self,
|
||||||
|
_inventory: &Inventory,
|
||||||
|
_topology: &T,
|
||||||
|
) -> Result<Outcome, InterpretError> {
|
||||||
|
let switch_addresses = &self.score.server_ips;
|
||||||
|
|
||||||
|
let snmp_auth = SecretManager::get_or_prompt::<BrocadeSnmpAuth>()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let config = SecretManager::get_or_prompt::<BrocadeSwitchAuth>()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let brocade = brocade::init(
|
||||||
|
&switch_addresses,
|
||||||
|
22,
|
||||||
|
&config.username,
|
||||||
|
&config.password,
|
||||||
|
Some(BrocadeOptions {
|
||||||
|
dry_run: self.score.dry_run,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("Brocade client failed to connect");
|
||||||
|
|
||||||
|
brocade
|
||||||
|
.enable_snmp(
|
||||||
|
&snmp_auth.username,
|
||||||
|
&snmp_auth.auth_password,
|
||||||
|
&snmp_auth.des_password,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|e| InterpretError::new(e.to_string()))?;
|
||||||
|
|
||||||
|
Ok(Outcome::success(format!(
|
||||||
|
"Activated snmp server for Brocade at {}",
|
||||||
|
switch_addresses
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_name(&self) -> InterpretName {
|
||||||
|
InterpretName::Custom("BrocadeEnableSnmpInterpret")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_version(&self) -> Version {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_status(&self) -> InterpretStatus {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_children(&self) -> Vec<Id> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod application;
|
pub mod application;
|
||||||
|
pub mod brocade;
|
||||||
pub mod cert_manager;
|
pub mod cert_manager;
|
||||||
pub mod dhcp;
|
pub mod dhcp;
|
||||||
pub mod dns;
|
pub mod dns;
|
||||||
|
|||||||
Reference in New Issue
Block a user