From cf8cf7e85d772629251c58560ae882550b21b04f Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Fri, 4 Oct 2024 17:04:40 +0200 Subject: [PATCH 1/3] try to optimize getting all controllers --- rust/agama-lib/src/storage/client/zfcp.rs | 68 ++++++++++++++++++++--- 1 file changed, 61 insertions(+), 7 deletions(-) diff --git a/rust/agama-lib/src/storage/client/zfcp.rs b/rust/agama-lib/src/storage/client/zfcp.rs index 1e16aef86d..3cf565aa6b 100644 --- a/rust/agama-lib/src/storage/client/zfcp.rs +++ b/rust/agama-lib/src/storage/client/zfcp.rs @@ -34,6 +34,60 @@ use crate::{ }, }; +pub async fn get_wwpns(controller_id: &str) -> Result, ServiceError> { + let output = std::process::Command::new("zfcp_san_disc") + .arg("-b") + .arg(controller_id) + .arg("-W") + .output() + .expect("zfcp_san_disc failed"); // TODO: real error handling + Ok(String::from_utf8_lossy(&output.stdout) + .split_whitespace() + .map(|s| s.to_string()) + .collect()) +} + +pub async fn get_luns(controller_id: String, wwpn: String) -> Result, ServiceError> { + let output = std::process::Command::new("zfcp_san_disc") + .arg("-b") + .arg(controller_id) + .arg("-p") + .arg(wwpn) + .arg("-W") + .output() + .expect("zfcp_san_disc failed"); // TODO: real error handling + Ok(String::from_utf8_lossy(&output.stdout) + .split_whitespace() + .map(|s| s.to_string()) + .collect()) +} + +/// Obtains a LUNs map for the given controller +/// +/// Given a controller id it returns a HashMap with each of its WWPNs as keys and the list of +/// LUNS corresponding to that specific WWPN as values. +/// +/// Arguments: +/// +/// `controller_id`: controller id +pub async fn get_luns_map( + controller_id: &str, +) -> Result>, ServiceError> { + let wwpns = get_wwpns(controller_id).await?; + let mut tasks = vec![]; + for wwpn in wwpns { + tasks.push(( + wwpn.clone(), + tokio::spawn(get_luns(controller_id.to_string(), wwpn.clone())), + )); + } + let mut result = HashMap::with_capacity(tasks.len()); + for (wwpn, task) in tasks { + result.insert(wwpn.clone(), task.await.expect("thread join failed")?); + } + Ok(result) +} + const ZFCP_CONTROLLER_PREFIX: &'static str = "/org/opensuse/Agama/Storage1/zfcp_controllers"; /// Client to connect to Agama's D-Bus API for zFCP management. @@ -110,7 +164,7 @@ impl<'a> ZFCPClient<'a> { channel: get_property(properties, "Channel")?, lun_scan: get_property(properties, "LUNScan")?, active: get_property(properties, "Active")?, - luns_map: self.get_luns_map(id.as_str()).await?, + luns_map: get_luns_map(id.as_str()).await?, // try to use optimized thred version here }, )) } @@ -129,12 +183,6 @@ impl<'a> ZFCPClient<'a> { Ok(dbus) } - pub async fn activate_controller(&self, controller_id: &str) -> Result<(), ServiceError> { - let controller = self.get_controller_proxy(controller_id).await?; - controller.activate().await?; - Ok(()) - } - pub async fn get_wwpns(&self, controller_id: &str) -> Result, ServiceError> { let controller = self.get_controller_proxy(controller_id).await?; let result = controller.get_wwpns().await?; @@ -176,6 +224,12 @@ impl<'a> ZFCPClient<'a> { .collect::>, _>>() } + pub async fn activate_controller(&self, controller_id: &str) -> Result<(), ServiceError> { + let controller = self.get_controller_proxy(controller_id).await?; + controller.activate().await?; + Ok(()) + } + pub async fn activate_disk( &self, controller_id: &str, From 26758fb8c3cde35623f22d8894a31aa4cd07ad8b Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Tue, 8 Oct 2024 22:31:51 +0200 Subject: [PATCH 2/3] fix calling zfcp --- rust/agama-lib/src/storage/client/zfcp.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/rust/agama-lib/src/storage/client/zfcp.rs b/rust/agama-lib/src/storage/client/zfcp.rs index 3cf565aa6b..e71322f339 100644 --- a/rust/agama-lib/src/storage/client/zfcp.rs +++ b/rust/agama-lib/src/storage/client/zfcp.rs @@ -53,7 +53,7 @@ pub async fn get_luns(controller_id: String, wwpn: String) -> Result .arg(controller_id) .arg("-p") .arg(wwpn) - .arg("-W") + .arg("-L") .output() .expect("zfcp_san_disc failed"); // TODO: real error handling Ok(String::from_utf8_lossy(&output.stdout) @@ -157,14 +157,16 @@ impl<'a> ZFCPClient<'a> { for (path, ifaces) in managed_objects { if let Some(properties) = ifaces.get("org.opensuse.Agama.Storage1.ZFCP.Controller") { let id = extract_id_from_path(&path)?.to_string(); + let channel: String = get_property(properties, "Channel")?; + let luns_map = get_luns_map(id.as_str()).await?; devices.push(( path, ZFCPController { - id: id.clone(), - channel: get_property(properties, "Channel")?, + id: id, + channel: channel, lun_scan: get_property(properties, "LUNScan")?, active: get_property(properties, "Active")?, - luns_map: get_luns_map(id.as_str()).await?, // try to use optimized thred version here + luns_map: luns_map, // try to use optimized thred version here }, )) } From 9c9e80e8d4c0fde56735df86fbb7232a68ef7d03 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Fri, 25 Oct 2024 16:24:04 +0200 Subject: [PATCH 3/3] try to paralelize also controllers level --- rust/agama-lib/src/storage/client/zfcp.rs | 38 ++++++++++++++++++----- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/rust/agama-lib/src/storage/client/zfcp.rs b/rust/agama-lib/src/storage/client/zfcp.rs index e71322f339..dd8b285912 100644 --- a/rust/agama-lib/src/storage/client/zfcp.rs +++ b/rust/agama-lib/src/storage/client/zfcp.rs @@ -71,9 +71,9 @@ pub async fn get_luns(controller_id: String, wwpn: String) -> Result /// /// `controller_id`: controller id pub async fn get_luns_map( - controller_id: &str, + controller_id: String, ) -> Result>, ServiceError> { - let wwpns = get_wwpns(controller_id).await?; + let wwpns = get_wwpns(controller_id.as_str()).await?; let mut tasks = vec![]; for wwpn in wwpns { tasks.push(( @@ -90,6 +90,15 @@ pub async fn get_luns_map( const ZFCP_CONTROLLER_PREFIX: &'static str = "/org/opensuse/Agama/Storage1/zfcp_controllers"; +/// Partial zfcp controller data used for thread processing +/// TODO: for final version move all those thread related methods to this struct to procude final result +struct PartialZFCPController { + pub id: String, + pub channel: String, + pub lun_scan: bool, + pub active: bool +} + /// Client to connect to Agama's D-Bus API for zFCP management. #[derive(Clone)] pub struct ZFCPClient<'a> { @@ -153,25 +162,40 @@ impl<'a> ZFCPClient<'a> { ) -> Result, ServiceError> { let managed_objects = self.object_manager_proxy.get_managed_objects().await?; - let mut devices: Vec<(OwnedObjectPath, ZFCPController)> = vec![]; + let mut devices: Vec<(OwnedObjectPath, PartialZFCPController)> = vec![]; for (path, ifaces) in managed_objects { if let Some(properties) = ifaces.get("org.opensuse.Agama.Storage1.ZFCP.Controller") { let id = extract_id_from_path(&path)?.to_string(); let channel: String = get_property(properties, "Channel")?; - let luns_map = get_luns_map(id.as_str()).await?; devices.push(( path, - ZFCPController { + PartialZFCPController { id: id, channel: channel, lun_scan: get_property(properties, "LUNScan")?, active: get_property(properties, "Active")?, - luns_map: luns_map, // try to use optimized thred version here }, )) } } - Ok(devices) + let mut tasks = vec![]; + for (_path, partial_controller) in &devices { + tasks.push( + tokio::spawn(get_luns_map(partial_controller.channel.clone())) + ) + } + let mut result = Vec::with_capacity(devices.len()); + for (index, task) in tasks.into_iter().enumerate() { + let (path, partial) = devices.get(index).unwrap(); + result.push((path.clone(), ZFCPController { + id: partial.id.clone(), + channel: partial.channel.clone(), + lun_scan: partial.lun_scan, + active: partial.active, + luns_map: task.await.expect("thread join failed")?, + })); + } + Ok(result) } async fn get_controller_proxy(