implemented more safeguards and autodiscovery

This commit is contained in:
2026-02-27 02:59:23 +01:00
parent f0925a3ab3
commit fe1f58b5ce
7 changed files with 248 additions and 156 deletions

View File

@@ -1,10 +1,11 @@
use super::traits::{PreflightAuditor, EnvironmentGuard, SensorBus, ActuatorBus, HardwareWatchdog, AuditError, AuditStep, SafetyStatus, EnvironmentCtx};
use crate::sal::safety::TdpLimitMicroWatts;
use crate::sal::safety::{TdpLimitMicroWatts, FanSpeedPercentage};
use anyhow::{Result, Context, anyhow};
use std::fs;
use std::path::{PathBuf};
use std::time::{Duration, Instant};
use std::sync::Mutex;
use tracing::{debug};
use crate::sal::heuristic::discovery::SystemFactSheet;
pub struct DellXps9380Sal {
@@ -22,11 +23,6 @@ pub struct DellXps9380Sal {
suppressed_services: Mutex<Vec<String>>,
msr_file: Mutex<fs::File>,
last_energy: Mutex<(u64, Instant)>,
// --- Original State for Restoration ---
original_pl1: Mutex<Option<u64>>,
original_pl2: Mutex<Option<u64>>,
original_fan_mode: Mutex<Option<String>>,
}
impl DellXps9380Sal {
@@ -58,9 +54,6 @@ impl DellXps9380Sal {
last_energy: Mutex::new((initial_energy, Instant::now())),
fact_sheet: facts,
ctx,
original_pl1: Mutex::new(None),
original_pl2: Mutex::new(None),
original_fan_mode: Mutex::new(None),
})
}
@@ -134,23 +127,11 @@ impl PreflightAuditor for DellXps9380Sal {
impl EnvironmentGuard for DellXps9380Sal {
fn suppress(&self) -> Result<()> {
// 1. Snapshot Power Limits
if let Ok(pl1) = fs::read_to_string(&self.pl1_path) {
*self.original_pl1.lock().unwrap() = pl1.trim().parse().ok();
}
if let Ok(pl2) = fs::read_to_string(&self.pl2_path) {
*self.original_pl2.lock().unwrap() = pl2.trim().parse().ok();
}
// 2. Snapshot Fan Mode (Assumption: Dell BIOS Fan Control is active)
// We can't easily read current state of dell-bios-fan-control, so we assume 'auto' (1)
*self.original_fan_mode.lock().unwrap() = Some("1".to_string());
// 3. Stop Services
let services = ["tlp", "thermald", "i8kmon"];
let mut suppressed = self.suppressed_services.lock().unwrap();
let services = ["tlp", "thermald", "i8kmon"];
for s in services {
if self.ctx.runner.run("systemctl", &["is-active", "--quiet", s]).is_ok() {
debug!("Suppressing service: {}", s);
let _ = self.ctx.runner.run("systemctl", &["stop", s]);
suppressed.push(s.to_string());
}
@@ -159,20 +140,6 @@ impl EnvironmentGuard for DellXps9380Sal {
}
fn restore(&self) -> Result<()> {
// 1. Restore Power Limits
if let Some(pl1) = *self.original_pl1.lock().unwrap() {
let _ = fs::write(&self.pl1_path, pl1.to_string());
}
if let Some(pl2) = *self.original_pl2.lock().unwrap() {
let _ = fs::write(&self.pl2_path, pl2.to_string());
}
// 2. Restore Fan Mode (BIOS Control)
if let Some(tool_path) = self.fact_sheet.paths.tools.get("dell_fan_ctrl") {
let _ = self.ctx.runner.run(&tool_path.to_string_lossy(), &["1"]);
}
// 3. Restart Services
let mut suppressed = self.suppressed_services.lock().unwrap();
for s in suppressed.drain(..) {
let _ = self.ctx.runner.run("systemctl", &["start", &s]);
@@ -196,7 +163,6 @@ impl SensorBus for DellXps9380Sal {
}
fn get_power_w(&self) -> Result<f32> {
// FIX: Ensure we always read from energy_uj if available for delta calculation
let rapl_base = self.pl1_path.parent().context("RAPL path error")?;
let energy_path = rapl_base.join("energy_uj");
@@ -212,7 +178,6 @@ impl SensorBus for DellXps9380Sal {
if delta_t < 0.05 { return Ok(0.0); }
Ok((delta_e as f32 / 1_000_000.0) / delta_t)
} else {
// Fallback to power1_average if it exists (units are µW)
let s = fs::read_to_string(&self.pwr_path)?;
Ok(s.trim().parse::<f32>()? / 1000000.0)
}
@@ -255,6 +220,17 @@ impl ActuatorBus for DellXps9380Sal {
Ok(())
}
fn set_fan_speed(&self, speed: FanSpeedPercentage) -> 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"))?;
let tool_str = tool_path.to_string_lossy();
if speed.as_u8() > 50 {
let _ = self.ctx.runner.run(&tool_str, &["0"]);
}
Ok(())
}
fn set_sustained_power_limit(&self, limit: TdpLimitMicroWatts) -> Result<()> {
fs::write(&self.pl1_path, limit.as_u64().to_string())?;
Ok(())