added dynamic discovery of configurations
This commit is contained in:
@@ -1,13 +1,15 @@
|
||||
use super::traits::{PreflightAuditor, EnvironmentGuard, SensorBus, ActuatorBus, HardwareWatchdog, AuditError, AuditStep, SafetyStatus};
|
||||
use anyhow::{Result, Context};
|
||||
use anyhow::{Result, Context, anyhow};
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::path::{PathBuf};
|
||||
use std::process::Command;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::sync::Mutex;
|
||||
use tracing::{debug, warn};
|
||||
use tracing::{debug};
|
||||
use crate::sal::heuristic::discovery::SystemFactSheet;
|
||||
|
||||
pub struct DellXps9380Sal {
|
||||
fact_sheet: SystemFactSheet,
|
||||
temp_path: PathBuf,
|
||||
pwr_path: PathBuf,
|
||||
fan_paths: Vec<PathBuf>,
|
||||
@@ -23,72 +25,30 @@ pub struct DellXps9380Sal {
|
||||
}
|
||||
|
||||
impl DellXps9380Sal {
|
||||
pub fn init() -> Result<Self> {
|
||||
let mut temp_path = None;
|
||||
let mut pwr_path = None;
|
||||
let mut fan_paths = Vec::new();
|
||||
let mut rapl_base_path = None;
|
||||
|
||||
// Dynamic hwmon discovery
|
||||
if let Ok(entries) = fs::read_dir("/sys/class/hwmon") {
|
||||
for entry in entries.flatten() {
|
||||
let p = entry.path();
|
||||
let name = fs::read_to_string(p.join("name")).unwrap_or_default().trim().to_string();
|
||||
|
||||
if name == "dell_smm" {
|
||||
temp_path = Some(p.join("temp1_input"));
|
||||
if let Ok(fan_entries) = fs::read_dir(&p) {
|
||||
for fan_entry in fan_entries.flatten() {
|
||||
let fan_p = fan_entry.path();
|
||||
if fan_p.file_name().unwrap_or_default().to_string_lossy().starts_with("fan") &&
|
||||
fan_p.file_name().unwrap_or_default().to_string_lossy().ends_with("_input") {
|
||||
fan_paths.push(fan_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
fan_paths.sort();
|
||||
}
|
||||
|
||||
if name == "intel_rapl" || name == "rapl" {
|
||||
pwr_path = Some(p.join("power1_average"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(entries) = fs::read_dir("/sys/class/powercap") {
|
||||
for entry in entries.flatten() {
|
||||
let p = entry.path();
|
||||
if let Ok(name) = fs::read_to_string(p.join("name")) {
|
||||
if name.trim() == "package-0" {
|
||||
rapl_base_path = Some(p.clone());
|
||||
if pwr_path.is_none() {
|
||||
pwr_path = Some(p.join("energy_uj"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let rapl_base = rapl_base_path.context("Could not find RAPL package-0 path in powercap")?;
|
||||
pub fn init(facts: SystemFactSheet) -> Result<Self> {
|
||||
let temp_path = facts.temp_path.clone().context("Dell SAL requires temperature sensor")?;
|
||||
let pwr_base = facts.rapl_paths.first().cloned().context("Dell SAL requires RAPL interface")?;
|
||||
let fan_paths = facts.fan_paths.clone();
|
||||
|
||||
let freq_path = PathBuf::from("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq");
|
||||
|
||||
let msr_file = fs::OpenOptions::new().read(true).write(true).open("/dev/cpu/0/msr")
|
||||
.context("Failed to open /dev/cpu/0/msr. Is the 'msr' module loaded?")?;
|
||||
|
||||
Ok(Self {
|
||||
temp_path: temp_path.context("Could not find dell_smm temperature path")?,
|
||||
pwr_path: pwr_path.context("Could not find RAPL power path")?,
|
||||
temp_path,
|
||||
pwr_path: pwr_base.join("power1_average"),
|
||||
fan_paths,
|
||||
freq_path,
|
||||
pl1_path: rapl_base.join("constraint_0_power_limit_uw"),
|
||||
pl2_path: rapl_base.join("constraint_1_power_limit_uw"),
|
||||
pl1_path: pwr_base.join("constraint_0_power_limit_uw"),
|
||||
pl2_path: pwr_base.join("constraint_1_power_limit_uw"),
|
||||
last_poll: Mutex::new(Instant::now() - Duration::from_secs(2)),
|
||||
last_temp: Mutex::new(0.0),
|
||||
last_fans: Mutex::new(Vec::new()),
|
||||
suppressed_services: Mutex::new(Vec::new()),
|
||||
msr_file: Mutex::new(msr_file),
|
||||
last_energy: Mutex::new((0, Instant::now())),
|
||||
fact_sheet: facts,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -148,6 +108,13 @@ impl PreflightAuditor for DellXps9380Sal {
|
||||
}
|
||||
});
|
||||
|
||||
// Tool availability check
|
||||
let tool_check = self.fact_sheet.paths.tools.contains_key("dell_fan_ctrl");
|
||||
steps.push(AuditStep {
|
||||
description: "Dell Fan Control Tool".to_string(),
|
||||
outcome: if tool_check { Ok(()) } else { Err(AuditError::ToolMissing("dell-bios-fan-control not found in PATH".to_string())) }
|
||||
});
|
||||
|
||||
Box::new(steps.into_iter())
|
||||
}
|
||||
}
|
||||
@@ -189,20 +156,15 @@ impl SensorBus for DellXps9380Sal {
|
||||
}
|
||||
|
||||
fn get_power_w(&self) -> Result<f32> {
|
||||
if self.pwr_path.to_string_lossy().contains("energy_uj") {
|
||||
let mut last = self.last_energy.lock().unwrap();
|
||||
let e2 = fs::read_to_string(&self.pwr_path)?.trim().parse::<u64>()?;
|
||||
let t2 = Instant::now();
|
||||
let (e1, t1) = *last;
|
||||
let delta_e = e2.wrapping_sub(e1);
|
||||
let delta_t = t2.duration_since(t1).as_secs_f32();
|
||||
*last = (e2, t2);
|
||||
if delta_t < 0.01 { return Ok(0.0); }
|
||||
Ok((delta_e as f32 / 1_000_000.0) / delta_t)
|
||||
} else {
|
||||
let s = fs::read_to_string(&self.pwr_path)?;
|
||||
Ok(s.trim().parse::<f32>()? / 1000000.0)
|
||||
}
|
||||
let mut last = self.last_energy.lock().unwrap();
|
||||
let e2 = fs::read_to_string(&self.pwr_path)?.trim().parse::<u64>()?;
|
||||
let t2 = Instant::now();
|
||||
let (e1, t1) = *last;
|
||||
let delta_e = e2.wrapping_sub(e1);
|
||||
let delta_t = t2.duration_since(t1).as_secs_f32();
|
||||
*last = (e2, t2);
|
||||
if delta_t < 0.01 { return Ok(0.0); }
|
||||
Ok((delta_e as f32 / 1_000_000.0) / delta_t)
|
||||
}
|
||||
|
||||
fn get_fan_rpms(&self) -> Result<Vec<u32>> {
|
||||
@@ -230,9 +192,12 @@ impl SensorBus for DellXps9380Sal {
|
||||
|
||||
impl ActuatorBus for DellXps9380Sal {
|
||||
fn set_fan_mode(&self, mode: &str) -> Result<()> {
|
||||
let tool_path = self.fact_sheet.paths.tools.get("dell_fan_ctrl")
|
||||
.ok_or_else(|| anyhow!("Dell fan control tool not found in PATH"))?;
|
||||
|
||||
match mode {
|
||||
"max" | "Manual" => { Command::new("dell-bios-fan-control").arg("0").status()?; }
|
||||
"auto" | "Auto" => { Command::new("dell-bios-fan-control").arg("1").status()?; }
|
||||
"max" | "Manual" => { Command::new(tool_path).arg("0").status()?; }
|
||||
"auto" | "Auto" => { Command::new(tool_path).arg("1").status()?; }
|
||||
_ => { debug!("Unknown fan mode: {}", mode); }
|
||||
}
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user