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
This commit is contained in:
Christoffer Martinsson 2025-10-23 18:50:40 +02:00
parent 7f5949b818
commit 5134c5320a
2 changed files with 36 additions and 3 deletions

View File

@ -36,6 +36,7 @@ struct DriveInfo {
pub struct DiskCollector {
config: DiskConfig,
temperature_thresholds: HysteresisThresholds,
detected_devices: std::collections::HashMap<String, Vec<String>>, // 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<Vec<String>> {
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<u64> {
let output = Command::new("du")

View File

@ -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<String>, // ["sda", "sdb", "sdc"] or ["nvme0n1"]
}