Christoffer Martinsson 08d3454683 Enhance disk collector with individual drive health monitoring
- Add StoragePool and DriveInfo structures for grouping drives by mount point
- Implement SMART data collection for individual drives (health, temperature, wear)
- Support for ext4, zfs, xfs, mergerfs, btrfs filesystem types
- Generate individual drive metrics: disk_[pool]_[drive]_health/temperature/wear
- Add storage_type and underlying_devices to filesystem configuration
- Move hardcoded service directory mappings to NixOS configuration
- Move hardcoded host-to-user mapping to NixOS configuration
- Remove all unused code and fix compilation warnings
- Clean implementation with zero warnings and no dead code

Individual drives now show health status per storage pool:
Storage root (ext4): nvme0n1 PASSED 42°C 5% wear
Storage steampool (mergerfs): sda/sdb/sdc with individual health data
2025-10-22 19:59:25 +02:00

151 lines
4.2 KiB
Rust

use anyhow::Result;
use cm_dashboard_shared::CacheConfig;
use serde::{Deserialize, Serialize};
use std::path::Path;
pub mod loader;
pub mod validation;
use crate::status::HostStatusConfig;
/// Main agent configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentConfig {
pub zmq: ZmqConfig,
pub collectors: CollectorConfig,
pub cache: CacheConfig,
pub notifications: NotificationConfig,
pub status_aggregation: HostStatusConfig,
pub collection_interval_seconds: u64,
}
/// ZMQ communication configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ZmqConfig {
pub publisher_port: u16,
pub command_port: u16,
pub bind_address: String,
pub timeout_ms: u64,
pub heartbeat_interval_ms: u64,
}
/// Collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CollectorConfig {
pub cpu: CpuConfig,
pub memory: MemoryConfig,
pub disk: DiskConfig,
pub systemd: SystemdConfig,
pub smart: SmartConfig,
pub backup: BackupConfig,
pub network: NetworkConfig,
}
/// CPU collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CpuConfig {
pub enabled: bool,
pub interval_seconds: u64,
pub load_warning_threshold: f32,
pub load_critical_threshold: f32,
pub temperature_warning_threshold: f32,
pub temperature_critical_threshold: f32,
}
/// Memory collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryConfig {
pub enabled: bool,
pub interval_seconds: u64,
/// Memory usage warning threshold (percentage)
pub usage_warning_percent: f32,
/// Memory usage critical threshold (percentage)
pub usage_critical_percent: f32,
}
/// Disk collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiskConfig {
pub enabled: bool,
pub interval_seconds: u64,
/// Disk usage warning threshold (percentage)
pub usage_warning_percent: f32,
/// Disk usage critical threshold (percentage)
pub usage_critical_percent: f32,
/// Filesystem configurations
pub filesystems: Vec<FilesystemConfig>,
}
/// Filesystem configuration entry
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FilesystemConfig {
pub name: String,
pub uuid: String,
pub mount_point: String,
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"]
}
/// Systemd services collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemdConfig {
pub enabled: bool,
pub interval_seconds: u64,
pub service_name_filters: Vec<String>,
pub excluded_services: Vec<String>,
pub memory_warning_mb: f32,
pub memory_critical_mb: f32,
pub service_directories: std::collections::HashMap<String, Vec<String>>,
pub host_user_mapping: String,
}
/// SMART collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SmartConfig {
pub enabled: bool,
pub interval_seconds: u64,
pub temperature_warning_celsius: f32,
pub temperature_critical_celsius: f32,
pub wear_warning_percent: f32,
pub wear_critical_percent: f32,
}
/// Backup collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BackupConfig {
pub enabled: bool,
pub interval_seconds: u64,
pub backup_paths: Vec<String>,
pub max_age_hours: u64,
}
/// Network collector configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkConfig {
pub enabled: bool,
pub interval_seconds: u64,
}
/// Notification configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NotificationConfig {
pub enabled: bool,
pub smtp_host: String,
pub smtp_port: u16,
pub from_email: String,
pub to_email: String,
pub rate_limit_minutes: u64,
}
impl AgentConfig {
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
loader::load_config(path)
}
pub fn validate(&self) -> Result<()> {
validation::validate_config(self)
}
}