use std::path::PathBuf;
use anyhow::{Result, bail};
use crate::config::{Arch, Os, Vm};
pub struct Image {
pub url: String,
pub checksum_url: String,
pub file_name: String,
pub cache_path: PathBuf,
}
pub fn check_supported(os: Os) -> Result<()> {
match os {
Os::FreeBSD => Ok(()),
Os::NetBSD | Os::OpenBSD => bail!("{os} guests are planned but not supported yet; only freebsd works for now"),
}
}
pub fn image(vm: &Vm) -> Result<Image> {
check_supported(vm.os)?;
let arch = vm.arch.resolve();
let version = &vm.version;
let (dir, file_arch) = match arch {
Arch::Aarch64 => ("aarch64", "arm64-aarch64"),
_ => ("amd64", "amd64"),
};
let base = format!("https://download.freebsd.org/releases/VM-IMAGES/{version}-RELEASE/{dir}/Latest");
let file_name = format!("FreeBSD-{version}-RELEASE-{file_arch}-BASIC-CLOUDINIT-{}.qcow2.xz", vm.filesystem);
Ok(Image {
url: format!("{base}/{file_name}"),
checksum_url: format!("{base}/CHECKSUM.SHA256"),
cache_path: PathBuf::from(format!("freebsd/{version}/{arch}-{}.qcow2", vm.filesystem)),
file_name,
})
}
pub fn install_packages(os: Os, packages: &[String]) -> String {
let mut cmd = match os {
Os::FreeBSD => String::from("env ASSUME_ALWAYS_YES=yes pkg install -y rsync"),
Os::NetBSD | Os::OpenBSD => unreachable!("checked by check_supported"),
};
for package in packages {
cmd.push(' ');
cmd.push_str(&crate::ssh::quote(package));
}
cmd
}
#[cfg(test)]
mod tests {
use super::*;
use crate::config::Config;
fn vm(extra: &str) -> Vm {
let config: Config = toml::from_str(&format!("[vm]\nos = \"freebsd\"\nversion = \"15.1\"\n{extra}")).unwrap();
config.vm
}
#[test]
fn freebsd_image_urls() {
let img = image(&vm("arch = \"amd64\"")).unwrap();
assert_eq!(
img.url,
"https://download.freebsd.org/releases/VM-IMAGES/15.1-RELEASE/amd64/Latest/FreeBSD-15.1-RELEASE-amd64-BASIC-CLOUDINIT-ufs.qcow2.xz"
);
assert_eq!(img.cache_path, PathBuf::from("freebsd/15.1/amd64-ufs.qcow2"));
let img = image(&vm("arch = \"aarch64\"\nfilesystem = \"zfs\"")).unwrap();
assert_eq!(
img.url,
"https://download.freebsd.org/releases/VM-IMAGES/15.1-RELEASE/aarch64/Latest/FreeBSD-15.1-RELEASE-arm64-aarch64-BASIC-CLOUDINIT-zfs.qcow2.xz"
);
}
#[test]
fn package_names_are_quoted() {
assert_eq!(
install_packages(Os::FreeBSD, &["git".into(), "rust".into()]),
"env ASSUME_ALWAYS_YES=yes pkg install -y rsync 'git' 'rust'"
);
}
}