diff --git a/FEATURES.md b/FEATURES.md index ede1596..04e1271 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -176,6 +176,11 @@ Supported Features * ports-* * target*/\*/block/* +* ✅ `/sys/class/sas_host//` + * device/ + * phy-* + * ports-* + * ✅ `/sys/class/scsi_tape//statistics` * write_ns * read_byte_cnt diff --git a/examples/sas_host.rs b/examples/sas_host.rs new file mode 100644 index 0000000..a8d1ee4 --- /dev/null +++ b/examples/sas_host.rs @@ -0,0 +1,13 @@ +use procsys::sysfs::class_sas_host; + +fn main() { + let sashosts = class_sas_host::collect().expect("sas hosts information"); + + match serde_json::to_string_pretty(&sashosts) { + Ok(output) => println!("{}", output), + Err(err) => { + log::error!("{}", err); + std::process::exit(1); + } + } +} diff --git a/src/sysfs/class_sas_host.rs b/src/sysfs/class_sas_host.rs new file mode 100644 index 0000000..984ff09 --- /dev/null +++ b/src/sysfs/class_sas_host.rs @@ -0,0 +1,88 @@ +use regex::Regex; +use serde::Serialize; +use std::{collections::HashMap, path::PathBuf}; + +use crate::{ + error::{CollectResult, MetricError}, + utils, +}; + +#[derive(Debug, Serialize, Clone, Default)] +pub struct SASHost { + /// /sys/class/sas_host//device/phy-* + pub sas_phys: Vec, + + /// /sys/class/sas_host//device/ports-* + pub sas_ports: Vec, +} + +impl SASHost { + fn new() -> Self { + Default::default() + } +} + +/// collects sas hosts information +/// # Example +/// ``` +/// use procsys::sysfs::class_sas_host; +/// +/// let sashosts = class_sas_host::collect().expect("sas hosts information"); +/// let json_output = serde_json::to_string_pretty(&sashosts).unwrap(); +/// println!("{}", json_output); +/// +/// ``` +pub fn collect() -> CollectResult> { + collect_from("/sys/class/sas_host/") +} + +fn collect_from(dirname: &str) -> CollectResult> { + let mut sashosts: HashMap = HashMap::new(); + let sas_host_path = PathBuf::from(dirname); + + let re_phy = match Regex::new(r"^phy-[0-9:]+$") { + Ok(r) => r, + Err(err) => return Err(MetricError::RegexError(err)), + }; + + let re_port = match Regex::new(r"^port-[0-9:]+$") { + Ok(r) => r, + Err(err) => return Err(MetricError::RegexError(err)), + }; + + for item in utils::list_dir_content(&sas_host_path, "", "sas_host") { + let mut sas_host = SASHost::new(); + let mut item_host_path = sas_host_path.clone(); + item_host_path.push(&item); + item_host_path.push("device"); + + for device_item in utils::list_dir_content(&item_host_path, "", &item) { + if re_phy.is_match(&device_item) { + sas_host.sas_phys.push(device_item); + } else if re_port.is_match(&device_item) { + sas_host.sas_ports.push(device_item); + } + } + + sashosts.insert(item.clone(), sas_host); + } + + Ok(sashosts) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn sas_host_information() { + let sashosts = + collect_from("test_data/fixtures/sys/class/sas_host/").expect("sas hosts information"); + + assert_eq!(sashosts.len(), 1); + + let sashost = sashosts.get("host11").unwrap(); + assert_eq!(sashost.sas_phys.len(), 9); + assert_eq!(sashost.sas_ports.len(), 3); + } +} diff --git a/src/sysfs/mod.rs b/src/sysfs/mod.rs index d186031..ea62212 100644 --- a/src/sysfs/mod.rs +++ b/src/sysfs/mod.rs @@ -4,6 +4,7 @@ pub mod class_fibrechannel; pub mod class_nvme; pub mod class_power_supply; pub mod class_sas_device; +pub mod class_sas_host; pub mod class_scsi_tape; pub mod class_thermal; pub mod class_watchdog;