use crate::{dgx_pull, dgx_status};
pub(super) trait SshExec {
fn run(&self, user: &str, host: &str, port: Option<u16>, command: &str) -> anyhow::Result<()>;
}
pub(super) struct RealSsh;
impl SshExec for RealSsh {
fn run(&self, user: &str, host: &str, port: Option<u16>, command: &str) -> anyhow::Result<()> {
let argv = dgx_pull::ssh_argv(user, host, port, command);
let (prog, rest) = argv.split_first().expect("ssh argv non-empty");
let status = std::process::Command::new(prog)
.args(rest)
.status()
.map_err(|e| anyhow::anyhow!("failed to spawn ssh: {e}"))?;
if !status.success() {
anyhow::bail!("ssh command failed: {status}");
}
Ok(())
}
}
pub(super) struct RealSshCapture;
impl dgx_status::SshCapture for RealSshCapture {
fn capture(
&self,
user: &str,
host: &str,
port: Option<u16>,
command: &str,
) -> anyhow::Result<String> {
let argv = dgx_pull::ssh_argv(user, host, port, command);
let (prog, rest) = argv.split_first().expect("ssh argv non-empty");
let out = std::process::Command::new(prog)
.args(rest)
.output()
.map_err(|e| anyhow::anyhow!("failed to spawn ssh: {e}"))?;
if !out.status.success() {
anyhow::bail!("ssh command failed: {}", out.status);
}
Ok(String::from_utf8_lossy(&out.stdout).into_owned())
}
}
pub(super) const MEM_TOTAL_AWK: &str = "$2";
pub(super) const MEM_AVAILABLE_AWK: &str = "$7";
pub(super) fn node_mem_probe(awk_field: &str) -> String {
format!("free -b | awk '/Mem:/{{print {awk_field}}}'")
}
fn detect_node_mem_col(user: &str, host: &str, port: Option<u16>, awk_field: &str) -> Option<u64> {
let argv = dgx_pull::ssh_argv(user, host, port, &node_mem_probe(awk_field));
let (prog, rest) = argv.split_first()?;
let out = std::process::Command::new(prog).args(rest).output().ok()?;
if !out.status.success() {
return None;
}
dgx_pull::parse_free_bytes(&String::from_utf8_lossy(&out.stdout))
}
pub(super) fn detect_node_mem(user: &str, host: &str, port: Option<u16>) -> Option<u64> {
detect_node_mem_col(user, host, port, MEM_TOTAL_AWK)
}
pub(super) fn detect_node_mem_available(user: &str, host: &str, port: Option<u16>) -> Option<u64> {
detect_node_mem_col(user, host, port, MEM_AVAILABLE_AWK)
}