Extend Red Bear runtime tooling
Red Bear OS Team
This commit is contained in:
+60
-5
@@ -15,6 +15,42 @@ fn require_path(path: &str) -> Result<(), String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn require_wayland_smoke_marker() -> Result<(), String> {
|
||||
for path in [
|
||||
"/home/root/.qt6-bootstrap-minimal.ok",
|
||||
"/home/root/.qt6-plugin-minimal.ok",
|
||||
"/home/root/.qt6-wayland-smoke-minimal.ok",
|
||||
"/home/root/.qt6-wayland-smoke-offscreen.ok",
|
||||
"/home/root/.qt6-wayland-smoke-wayland.ok",
|
||||
] {
|
||||
let marker = Path::new(path);
|
||||
if !marker.exists() {
|
||||
return Err(format!(
|
||||
"missing required Qt smoke marker {}",
|
||||
marker.display()
|
||||
));
|
||||
}
|
||||
println!("{}", marker.display());
|
||||
}
|
||||
|
||||
let ok = Path::new("/home/root/.qt6-wayland-smoke.ok");
|
||||
if ok.exists() {
|
||||
println!("{}", ok.display());
|
||||
println!("qt6-wayland-smoke");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let err = Path::new("/home/root/.qt6-wayland-smoke.err");
|
||||
if err.exists() {
|
||||
return Err(format!(
|
||||
"qt6-wayland-smoke marker missing; failure marker present at {}",
|
||||
err.display()
|
||||
));
|
||||
}
|
||||
|
||||
Err("qt6-wayland-smoke did not leave a success marker".to_string())
|
||||
}
|
||||
|
||||
fn run() -> Result<(), String> {
|
||||
parse_args(PROGRAM, USAGE, std::env::args()).map_err(|err| {
|
||||
if err.is_empty() {
|
||||
@@ -27,16 +63,35 @@ fn run() -> Result<(), String> {
|
||||
require_path("/usr/bin/orbital-wayland")?;
|
||||
require_path("/usr/bin/wayland-session")?;
|
||||
require_path("/usr/bin/smallvil")?;
|
||||
require_path("/usr/bin/qt6-bootstrap-check")?;
|
||||
require_path("/usr/bin/qt6-plugin-check")?;
|
||||
require_path("/usr/bin/qt6-wayland-smoke")?;
|
||||
require_path("/home/root/.wayland-session.started")?;
|
||||
require_wayland_smoke_marker()?;
|
||||
|
||||
let status = Command::new("redbear-info")
|
||||
.arg("--json")
|
||||
.status()
|
||||
.output()
|
||||
.map_err(|err| format!("failed to run redbear-info --json: {err}"))?;
|
||||
if status.success() {
|
||||
Ok(())
|
||||
return if status.status.success() {
|
||||
let stdout = String::from_utf8_lossy(&status.stdout);
|
||||
if stdout.contains("virtio_net_present") {
|
||||
Ok(())
|
||||
} else {
|
||||
Err("redbear-info --json did not report virtio_net_present".to_string())
|
||||
}
|
||||
} else {
|
||||
Err(format!("redbear-info exited with status {status}"))
|
||||
}
|
||||
let stderr = String::from_utf8_lossy(&status.stderr);
|
||||
if stderr.trim().is_empty() {
|
||||
Err(format!("redbear-info exited with status {}", status.status))
|
||||
} else {
|
||||
Err(format!(
|
||||
"redbear-info exited with status {}: {}",
|
||||
status.status,
|
||||
stderr.trim()
|
||||
))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
+129
-4
@@ -2,6 +2,7 @@ use std::path::Path;
|
||||
use std::process::{self, Command};
|
||||
|
||||
use redbear_hwutils::parse_args;
|
||||
use serde_json::Value;
|
||||
|
||||
const PROGRAM: &str = "redbear-phase5-network-check";
|
||||
const USAGE: &str = "Usage: redbear-phase5-network-check\n\nShow the installed Phase 5 networking/session plumbing surface inside the guest.";
|
||||
@@ -15,6 +16,21 @@ fn require_path(path: &str) -> Result<(), String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn require_json_field(value: &Value, field: &str) -> Result<(), String> {
|
||||
if value.get(field).is_some() {
|
||||
println!("{field}=present");
|
||||
Ok(())
|
||||
} else {
|
||||
Err(format!("redbear-info --json did not report {field}"))
|
||||
}
|
||||
}
|
||||
|
||||
fn optional_require_path(path: &str, label: &str) {
|
||||
if Path::new(path).exists() {
|
||||
println!("{label}=present");
|
||||
}
|
||||
}
|
||||
|
||||
fn run() -> Result<(), String> {
|
||||
parse_args(PROGRAM, USAGE, std::env::args()).map_err(|err| {
|
||||
if err.is_empty() {
|
||||
@@ -25,16 +41,108 @@ fn run() -> Result<(), String> {
|
||||
|
||||
println!("=== Red Bear OS Phase 5 Networking Check ===");
|
||||
require_path("/usr/bin/dbus-daemon")?;
|
||||
require_path("/usr/bin/netctl")?;
|
||||
require_path("/usr/bin/redbear-wifictl")?;
|
||||
|
||||
let info_status = Command::new("redbear-info")
|
||||
let info_output = Command::new("redbear-info")
|
||||
.arg("--json")
|
||||
.status()
|
||||
.output()
|
||||
.map_err(|err| format!("failed to run redbear-info --json: {err}"))?;
|
||||
if !info_status.success() {
|
||||
return Err(format!("redbear-info exited with status {info_status}"));
|
||||
if !info_output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&info_output.stderr);
|
||||
if stderr.trim().is_empty() {
|
||||
return Err(format!(
|
||||
"redbear-info exited with status {}",
|
||||
info_output.status
|
||||
));
|
||||
}
|
||||
return Err(format!(
|
||||
"redbear-info exited with status {}: {}",
|
||||
info_output.status,
|
||||
stderr.trim()
|
||||
));
|
||||
}
|
||||
|
||||
let info_stdout = String::from_utf8_lossy(&info_output.stdout);
|
||||
let info_json: Value = serde_json::from_str(&info_stdout)
|
||||
.map_err(|err| format!("failed to parse redbear-info --json output: {err}"))?;
|
||||
if info_stdout.contains("virtio_net_present") {
|
||||
println!("virtio_net_present");
|
||||
} else {
|
||||
return Err("redbear-info --json did not report virtio_net_present".to_string());
|
||||
}
|
||||
|
||||
let network = info_json
|
||||
.get("network")
|
||||
.ok_or_else(|| "redbear-info --json did not include network section".to_string())?;
|
||||
require_json_field(network, "wifi_control_state")?;
|
||||
require_json_field(network, "wifi_connect_result")?;
|
||||
require_json_field(network, "wifi_disconnect_result")?;
|
||||
|
||||
let _ = Command::new("netctl").arg("status").status();
|
||||
|
||||
let wifictl_output = Command::new("redbear-wifictl")
|
||||
.arg("--probe")
|
||||
.output()
|
||||
.map_err(|err| format!("failed to run redbear-wifictl --probe: {err}"))?;
|
||||
if !wifictl_output.status.success() {
|
||||
return Err(format!(
|
||||
"redbear-wifictl --probe exited with status {}",
|
||||
wifictl_output.status
|
||||
));
|
||||
}
|
||||
let wifictl_stdout = String::from_utf8_lossy(&wifictl_output.stdout);
|
||||
if wifictl_stdout.contains("interfaces=") {
|
||||
println!("WIFICTL_INTERFACES=present");
|
||||
} else {
|
||||
return Err("redbear-wifictl --probe did not report interfaces=".to_string());
|
||||
}
|
||||
if wifictl_stdout.contains("capabilities=") {
|
||||
println!("WIFICTL_CAPABILITIES=present");
|
||||
} else {
|
||||
return Err("redbear-wifictl --probe did not report capabilities=".to_string());
|
||||
}
|
||||
|
||||
let wifi_check_output = Command::new("redbear-phase5-wifi-check")
|
||||
.output()
|
||||
.map_err(|err| format!("failed to run redbear-phase5-wifi-check: {err}"))?;
|
||||
if !wifi_check_output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&wifi_check_output.stderr);
|
||||
if stderr.trim().is_empty() {
|
||||
return Err(format!(
|
||||
"redbear-phase5-wifi-check exited with status {}",
|
||||
wifi_check_output.status
|
||||
));
|
||||
}
|
||||
return Err(format!(
|
||||
"redbear-phase5-wifi-check exited with status {}: {}",
|
||||
wifi_check_output.status,
|
||||
stderr.trim()
|
||||
));
|
||||
}
|
||||
let wifi_check_stdout = String::from_utf8_lossy(&wifi_check_output.stdout);
|
||||
if wifi_check_stdout.contains("PASS: bounded Intel Wi-Fi runtime path exercised on target") {
|
||||
println!("PHASE5_WIFI_CHECK=pass");
|
||||
} else {
|
||||
return Err(
|
||||
"redbear-phase5-wifi-check did not report bounded Wi-Fi runtime success".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
if let Ok(ifaces) = std::fs::read_dir("/scheme/wifictl/ifaces") {
|
||||
for entry in ifaces.flatten() {
|
||||
let iface = entry.file_name().to_string_lossy().into_owned();
|
||||
optional_require_path(
|
||||
&format!("/scheme/wifictl/ifaces/{iface}/connect-result"),
|
||||
"WIFICTL_CONNECT_RESULT_NODE",
|
||||
);
|
||||
optional_require_path(
|
||||
&format!("/scheme/wifictl/ifaces/{iface}/disconnect-result"),
|
||||
"WIFICTL_DISCONNECT_RESULT_NODE",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if Path::new("/run/dbus/system_bus_socket").exists() {
|
||||
println!("DBUS_SYSTEM_BUS=present");
|
||||
} else {
|
||||
@@ -49,3 +157,20 @@ fn main() {
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn require_json_field_accepts_present_key() {
|
||||
let value: Value = serde_json::json!({"wifi_connect_result": "unknown"});
|
||||
assert!(require_json_field(&value, "wifi_connect_result").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn require_json_field_rejects_missing_key() {
|
||||
let value: Value = serde_json::json!({"wifi_control_state": "present"});
|
||||
assert!(require_json_field(&value, "wifi_connect_result").is_err());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user