/*! A Van is a moving van, or an installation ISO */ use tokio::process::Command; use std::process::ExitStatus; use std::os::unix::process::ExitStatusExt; use std::str::FromStr; use crate::errors::Error; /// Describes a hash of a file pub struct Sha256(pub String); impl FromStr for Sha256 { type Err = Error; fn from_str(s: &str) -> Result { let sum = s.clone(); Ok(Sha256(sum.to_string())) } } impl ToString for Sha256 { fn to_string(&self) -> String { self.0.clone() } } /// Describes a moving Van, or a way to install a distribution pub struct Van { /// The common name of the distribution (e.g "Arch Linux") pub name: String, /// The SHA-256 hash of the downloaded file pub shasum: Sha256, /// Where the ISO can be downloaded from pub download_url: String, /// The commonly accepted version (e.g "rolling", "21.11", "unstable") pub version: String, } impl Van { pub fn new(name: String, shasum: String, download_url: String, version: String ) -> Self { Self { name, shasum: Sha256(shasum), download_url, version } } pub async fn download(&self, target: String) -> Result<(), Error> { let output = Command::new("ssh") .args([ "-oStrictHostKeyChecking=accept-new", &target.clone(), "wget", "-O", &self.download_url.clone(), &format!("/var/lib/libvirt/images/{}", self.make_pretty_name().clone()) ]) .output() .await?; if output.status != ExitStatus::from_raw(0) { Err(Error::RemoteCommand(String::from_utf8(output.stdout).unwrap())) } else { Ok(()) } } pub fn make_pretty_name(&self) -> String { let safe_name = self.name.clone().to_lowercase().replace(" ", "-"); let file_name = format!("{}-{}-{}.van", safe_name, self.version.clone(), self.shasum.0.clone()); file_name } }