use crate::api::AgentInfo;
use log::{error, info, warn};
use std::env;
use std::fs;
use std::path::Path;
use std::process::Command as StdCommand;
use sysinfo::{Disks, System};
use uuid::Uuid;
pub fn get_hostname() -> String {
if let Ok(hostname) = env::var("HOSTNAME") {
return hostname;
}
if let Ok(output) = StdCommand::new("hostname").output() {
if let Ok(hostname) = String::from_utf8(output.stdout) {
return hostname.trim().to_string();
}
}
"unknown-host".to_string()
}
pub fn check_sshpass_installed() -> bool {
match StdCommand::new("which").arg("sshpass").output() {
Ok(output) => {
if output.status.success() {
info!("[OK] sshpass is installed");
true
} else {
error!("✘ sshpass is not installed");
error!("VM provisioning requires sshpass for SSH authentication");
error!("Install it using: brew install sshpass");
false
}
}
Err(e) => {
warn!("Failed to check for sshpass: {}", e);
false
}
}
}
pub fn get_agent_info(id_file: &str) -> AgentInfo {
let id = if Path::new(id_file).exists() {
match fs::read_to_string(id_file) {
Ok(id) => {
let id = id.trim().to_string();
info!("Using existing agent ID: {}", id);
id
}
Err(e) => {
error!("Failed to read agent ID file: {}", e);
let new_id = Uuid::new_v4().to_string();
info!("Generated new agent ID: {}", new_id);
if let Err(e) = fs::write(id_file, &new_id) {
error!("Failed to write agent ID to file: {}", e);
}
new_id
}
}
} else {
let new_id = Uuid::new_v4().to_string();
info!("Generated new agent ID: {}", new_id);
if let Err(e) = fs::write(id_file, &new_id) {
error!("Failed to write agent ID to file: {}", e);
}
new_id
};
let os = env::var("CIRUN_AGENT_OS").unwrap_or_else(|_| env::consts::OS.to_string());
let sys = System::new_all();
AgentInfo {
id,
hostname: get_hostname(),
os,
arch: env::consts::ARCH.to_string(),
version: env!("CARGO_PKG_VERSION").to_string(),
cpu_cores: sys.cpus().len() as u32,
memory_gb: (sys.total_memory() / BYTES_PER_GB) as u32,
disk_gb: root_disk_capacity_gb(),
}
}
const BYTES_PER_GB: u64 = 1024 * 1024 * 1024;
fn root_disk_capacity_gb() -> u32 {
let disks = Disks::new_with_refreshed_list();
let root = disks
.list()
.iter()
.find(|d| d.mount_point() == Path::new("/"))
.or_else(|| disks.list().first());
match root {
Some(disk) => (disk.total_space() / BYTES_PER_GB) as u32,
None => 0,
}
}