configure bond with NMState

This commit is contained in:
2025-09-25 16:31:40 -04:00
parent 0de52aedbf
commit ffe3c09907
13 changed files with 658 additions and 95 deletions

View File

@@ -7,7 +7,8 @@ license.workspace = true
[dependencies]
async-trait.workspace = true
harmony_types = { version = "0.1.0", path = "../harmony_types" }
harmony_types = { path = "../harmony_types" }
russh.workspace = true
russh-keys.workspace = true
tokio.workspace = true
log.workspace = true

View File

@@ -5,6 +5,7 @@ use std::{
use async_trait::async_trait;
use harmony_types::net::{IpAddress, MacAddress};
use log::{debug, info};
use russh::client::{Handle, Handler};
use russh_keys::key;
use std::str::FromStr;
@@ -21,7 +22,12 @@ pub struct BrocadeClient {
}
impl BrocadeClient {
pub async fn init(ip: IpAddress, username: &str, password: &str) -> Result<Self, Error> {
pub async fn init(
ip_addresses: &[IpAddress],
username: &str,
password: &str,
) -> Result<Self, Error> {
let ip = ip_addresses[0];
let config = russh::client::Config::default();
let mut client = russh::client::connect(Arc::new(config), (ip, 22), Client {}).await?;
@@ -64,6 +70,8 @@ impl BrocadeClient {
}
pub async fn configure_port_channel(&self, ports: &[String]) -> Result<u8, Error> {
info!("[Brocade] Configuring port-channel with ports: {ports:?}");
let channel_id = self.find_available_channel_id().await?;
let mut commands = Vec::new();
@@ -93,7 +101,8 @@ impl BrocadeClient {
}
pub async fn find_available_channel_id(&self) -> Result<u8, Error> {
// FIXME: The command might vary slightly by Brocade OS version.
debug!("[Brocade] Finding next available channel id...");
let output = self.run_command("show port-channel summary").await?;
let mut used_ids = Vec::new();
@@ -121,10 +130,13 @@ impl BrocadeClient {
}
}
debug!("[Brocade] Found channel id '{next_id}'");
Ok(next_id)
}
async fn run_command(&self, command: &str) -> Result<String, Error> {
debug!("[Brocade] Running command: '{command}'...");
let mut channel = self.client.channel_open_session().await?;
let mut output = Vec::new();
@@ -142,9 +154,9 @@ impl BrocadeClient {
}
russh::ChannelMsg::ExitStatus { exit_status } => {
if exit_status != 0 {
let output_str = String::from_utf8(output).unwrap_or_default();
return Err(Error::CommandError(format!(
"Command failed with exit status {exit_status}, output {}",
String::from_utf8(output).unwrap_or_default()
"Command failed with exit status {exit_status}, output {output_str}",
)));
}
}
@@ -170,6 +182,8 @@ impl BrocadeClient {
// Execute commands sequentially and check for errors immediately.
for command in commands {
debug!("[Brocade] Running command: '{command}'...");
let mut output = Vec::new();
channel.exec(true, command.as_str()).await?;
@@ -187,7 +201,7 @@ impl BrocadeClient {
if exit_status != 0 {
let output_str = String::from_utf8(output).unwrap_or_default();
return Err(Error::CommandError(format!(
"Command '{command}' failed with exit status {exit_status}: {output_str}",
"Command failed with exit status {exit_status}: {output_str}",
)));
}
}