From 5134c5320a6afc2ac356e11f005246fff96691a1 Mon Sep 17 00:00:00 2001 From: Christoffer Martinsson Date: Thu, 23 Oct 2025 18:50:40 +0200 Subject: [PATCH] Fix disk collector to use dynamic device detection - Remove underlying_devices field from FilesystemConfig - Add device detection at startup using findmnt command - Store detected devices in HashMap for reuse during collection - Keep all existing functionality (StoragePool, DriveInfo, SMART data) - Detect devices only once at initialization, not every collection cycle - Fixes agent startup failure due to missing underlying_devices config --- agent/src/collectors/disk.rs | 38 ++++++++++++++++++++++++++++++++++-- agent/src/config/mod.rs | 1 - 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/agent/src/collectors/disk.rs b/agent/src/collectors/disk.rs index 546feb9..225a31a 100644 --- a/agent/src/collectors/disk.rs +++ b/agent/src/collectors/disk.rs @@ -36,6 +36,7 @@ struct DriveInfo { pub struct DiskCollector { config: DiskConfig, temperature_thresholds: HysteresisThresholds, + detected_devices: std::collections::HashMap>, // mount_point -> devices } impl DiskCollector { @@ -48,9 +49,20 @@ impl DiskCollector { 5.0, // 5°C gap for recovery ); + // Detect devices for all configured filesystems at startup + let mut detected_devices = std::collections::HashMap::new(); + for fs_config in &config.filesystems { + if fs_config.monitor { + if let Ok(devices) = Self::detect_device_for_mount_point_static(&fs_config.mount_point) { + detected_devices.insert(fs_config.mount_point.clone(), devices); + } + } + } + Self { config, temperature_thresholds, + detected_devices, } } @@ -84,8 +96,9 @@ impl DiskCollector { let used = self.bytes_to_human_readable(used_bytes); let available = self.bytes_to_human_readable(available_bytes); - // Get individual drive information - let underlying_drives = self.get_drive_info_for_devices(&fs_config.underlying_devices)?; + // Get individual drive information using pre-detected devices + let device_names = self.detected_devices.get(&fs_config.mount_point).cloned().unwrap_or_default(); + let underlying_drives = self.get_drive_info_for_devices(&device_names)?; storage_pools.push(StoragePool { name: fs_config.name.clone(), @@ -249,6 +262,27 @@ impl DiskCollector { } } + /// Detect device backing a mount point using findmnt (static version for startup) + fn detect_device_for_mount_point_static(mount_point: &str) -> Result> { + let output = Command::new("findmnt") + .args(&["-n", "-o", "SOURCE", mount_point]) + .output()?; + + if !output.status.success() { + return Ok(Vec::new()); + } + + let output_str = String::from_utf8_lossy(&output.stdout); + let device_path = output_str.trim(); + + // Extract device name from path (e.g., /dev/nvme0n1 -> nvme0n1) + if let Some(device_name) = device_path.strip_prefix("/dev/") { + Ok(vec![device_name.to_string()]) + } else { + Ok(Vec::new()) + } + } + /// Get directory size using du command (efficient for single directory) fn get_directory_size(&self, path: &str) -> Result { let output = Command::new("du") diff --git a/agent/src/config/mod.rs b/agent/src/config/mod.rs index 0053f70..c54cd3b 100644 --- a/agent/src/config/mod.rs +++ b/agent/src/config/mod.rs @@ -86,7 +86,6 @@ pub struct FilesystemConfig { pub fs_type: String, // "ext4", "zfs", "xfs", "mergerfs", "btrfs" pub monitor: bool, pub storage_type: String, // "single", "raid", "mirror", "mergerfs", "zfs" - pub underlying_devices: Vec, // ["sda", "sdb", "sdc"] or ["nvme0n1"] }