From 0f59f29ac40408ab95bf871f9a954ba9ed532d03 Mon Sep 17 00:00:00 2001 From: Jean-Gabriel Gill-Couture Date: Fri, 22 Aug 2025 11:52:51 -0400 Subject: [PATCH] fix(inventory_agent): Inventory agent now fallsback on error messages when it cant find values --- harmony_inventory_agent/src/hwinfo.rs | 55 +++++++++++++++++---------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/harmony_inventory_agent/src/hwinfo.rs b/harmony_inventory_agent/src/hwinfo.rs index 21045cc..d381a14 100644 --- a/harmony_inventory_agent/src/hwinfo.rs +++ b/harmony_inventory_agent/src/hwinfo.rs @@ -1,4 +1,4 @@ -use log::debug; +use log::{debug, warn}; use serde::{Deserialize, Serialize}; use serde_json::Value; use std::fs; @@ -104,48 +104,58 @@ impl PhysicalHost { fn all_tools_available() -> Result<(), String> { let required_tools = [ - ("lsblk", "--version"), - ("lspci", "--version"), - ("lsmod", "--version"), - ("dmidecode", "--version"), - ("smartctl", "--version"), - ("ip", "route"), // No version flag available + ("lsblk", Some("--version")), + ("lspci", Some("--version")), + ("lsmod", None), + ("dmidecode", Some("--version")), + ("smartctl", Some("--version")), + ("ip", Some("route")), // No version flag available ]; let mut missing_tools = Vec::new(); + debug!("Looking for required_tools {required_tools:?}"); for (tool, tool_arg) in required_tools.iter() { // First check if tool exists in PATH using which(1) - let exists = if let Ok(output) = Command::new("which").arg(tool).output() { + let mut exists = if let Ok(output) = Command::new("which").arg(tool).output() { output.status.success() } else { - // Fallback: manual PATH search if which(1) is unavailable - if let Ok(path_var) = std::env::var("PATH") { - path_var.split(':').any(|dir| { - let tool_path = std::path::Path::new(dir).join(tool); - tool_path.exists() && Self::is_executable(&tool_path) - }) - } else { - false - } + false }; if !exists { + // Fallback: manual PATH search if which(1) is unavailable + debug!("Looking for {tool} in path"); + if let Ok(path_var) = std::env::var("PATH") { + debug!("PATH is {path_var}"); + exists = path_var.split(':').any(|dir| { + let tool_path = std::path::Path::new(dir).join(tool); + tool_path.exists() && Self::is_executable(&tool_path) + }) + } + } + + if !exists { + warn!("Unable to find tool {tool} from PATH"); missing_tools.push(*tool); continue; } // Verify tool is functional by checking version/help output let mut cmd = Command::new(tool); - cmd.arg(tool_arg); + if let Some(tool_arg) = tool_arg { + cmd.arg(tool_arg); + } cmd.stdout(std::process::Stdio::null()); cmd.stderr(std::process::Stdio::null()); if let Ok(status) = cmd.status() { if !status.success() { + warn!("Unable to test {tool} status failed"); missing_tools.push(*tool); } } else { + warn!("Unable to test {tool}"); missing_tools.push(*tool); } } @@ -167,6 +177,7 @@ impl PhysicalHost { #[cfg(unix)] fn is_executable(path: &std::path::Path) -> bool { + debug!("Checking if {} is executable", path.to_string_lossy()); use std::os::unix::fs::PermissionsExt; match std::fs::metadata(path) { @@ -285,11 +296,11 @@ impl PhysicalHost { if device_path.exists() { if drive.model.is_empty() { drive.model = Self::read_sysfs_string(&device_path.join("device/model")) - .map_err(|e| format!("Failed to read model for {}: {}", name, e))?; + .unwrap_or(format!("Failed to read model for {}", name)); } if drive.serial.is_empty() { drive.serial = Self::read_sysfs_string(&device_path.join("device/serial")) - .map_err(|e| format!("Failed to read serial for {}: {}", name, e))?; + .unwrap_or(format!("Failed to read serial for {}", name)); } } @@ -655,6 +666,10 @@ impl PhysicalHost { Ok("IDE".to_string()) } else if device_name.starts_with("vd") { Ok("VirtIO".to_string()) + } else if device_name.starts_with("sr") { + Ok("CDROM".to_string()) + } else if device_name.starts_with("zram") { + Ok("Ramdisk".to_string()) } else { // Try to determine from device path let subsystem = Self::read_sysfs_string(&device_path.join("device/subsystem"))?;