diff --git a/crates/fire-server/src/services/microvm.rs b/crates/fire-server/src/services/microvm.rs index 552a6fb..79e8d3b 100644 --- a/crates/fire-server/src/services/microvm.rs +++ b/crates/fire-server/src/services/microvm.rs @@ -160,8 +160,9 @@ async fn start( } } - firecracker_prepare::prepare(options.clone().into(), options.vmlinux.clone(), ssh_keys)?; - let vm_id = firecracker_vm::setup(&options, pid, vm_id).await?; + let kernel_file = + firecracker_prepare::prepare(options.clone().into(), options.vmlinux.clone(), ssh_keys)?; + let vm_id = firecracker_vm::setup(&options, pid, vm_id, &kernel_file).await?; let vm = repo::virtual_machine::find(&pool, &vm_id) .await? .ok_or_else(|| Error::msg("Failed to retrieve the created VM"))?; diff --git a/crates/firecracker-prepare/src/downloader.rs b/crates/firecracker-prepare/src/downloader.rs index c184dd3..4be4958 100644 --- a/crates/firecracker-prepare/src/downloader.rs +++ b/crates/firecracker-prepare/src/downloader.rs @@ -3,12 +3,15 @@ use owo_colors::OwoColorize; use regex::Regex; use std::path::Path; -use crate::command::{run_command, run_command_with_stdout_inherit}; +use crate::{ + command::{run_command, run_command_with_stdout_inherit}, + get_kernel_version, +}; pub fn download_files(arch: &str) -> Result<(String, String, String)> { let app_dir = crate::config::get_config_dir().with_context(|| "Failed to get configuration directory")?; - let kernel_file = download_kernel(arch)?; + let kernel_file = download_kernel(&get_kernel_version(), arch)?; let ci_version = get_ci_version().with_context(|| "Failed to get CI version")?; @@ -73,7 +76,7 @@ fn get_ci_version() -> Result { Ok(ci_version.to_string()) } -pub fn download_kernel(arch: &str) -> Result { +pub fn download_kernel_from_firecracker(arch: &str) -> Result { let app_dir = crate::config::get_config_dir().with_context(|| "Failed to get configuration directory")?; let ci_version = @@ -99,6 +102,18 @@ pub fn download_kernel(arch: &str) -> Result { Ok(kernel_file) } +pub fn download_kernel(version: &str, arch: &str) -> Result { + let app_dir = + crate::config::get_config_dir().with_context(|| "Failed to get configuration directory")?; + let kernel_file = format!("{}/vmlinux-{}.{}", app_dir, version, arch); + let kernel_url = &format!( + "https://github.com/tsirysndr/vmlinux-builder/releases/download/{}/vmlinux-{}.{}", + version, version, arch, + ); + download_file(kernel_url, &kernel_file)?; + Ok(kernel_file) +} + fn get_latest_key(url: &str, prefix: &str) -> Result { let output = run_command( "curl", @@ -157,7 +172,7 @@ fn download_file(url: &str, output: &str) -> Result<()> { return Ok(()); } println!("Downloading: {}", output.bright_green()); - run_command_with_stdout_inherit("wget", &["-O", output, url], false)?; + run_command_with_stdout_inherit("curl", &["-L", "-o", output, url], false)?; Ok(()) } diff --git a/crates/firecracker-prepare/src/lib.rs b/crates/firecracker-prepare/src/lib.rs index 9fb31d2..1f96762 100644 --- a/crates/firecracker-prepare/src/lib.rs +++ b/crates/firecracker-prepare/src/lib.rs @@ -1,4 +1,4 @@ -use std::fs; +use std::{env, fs}; use anyhow::Result; use owo_colors::OwoColorize; @@ -19,6 +19,10 @@ pub mod vmlinuz; const BRIDGE_IP: &str = "172.16.0.1"; +fn get_kernel_version() -> String { + env::var("KERNEL_VERSION").unwrap_or_else(|_| "6.16.7".to_string()) +} + #[derive(Clone, Copy, PartialEq, Serialize, Deserialize, Debug)] pub enum Distro { Debian, @@ -58,7 +62,7 @@ pub fn prepare( distro: Distro, kernel_file: Option, ssh_keys: Option>, -) -> Result<()> { +) -> Result { let arch = run_command("uname", &["-m"], false)?.stdout; let arch = String::from_utf8_lossy(&arch).trim().to_string(); println!("[+] Detected architecture: {}", arch.bright_green()); @@ -102,7 +106,7 @@ pub fn prepare( Some(ssh_key_file) => println!("[✓] SSH Key: {}", ssh_key_file.bright_green()), } - Ok(()) + Ok(kernel_file) } pub trait RootfsPreparer { @@ -149,8 +153,9 @@ impl RootfsPreparer for DebianPreparer { let kernel_file = match kernel_file { Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), - None => downloader::download_kernel(arch)?, + None => downloader::download_kernel(&get_kernel_version(), arch)?, }; + let debootstrap_dir = format!("{}/debian-rootfs", app_dir); let arch = match arch { @@ -288,7 +293,7 @@ impl RootfsPreparer for AlpinePreparer { let kernel_file = match kernel_file { Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), - None => downloader::download_kernel(arch)?, + None => downloader::download_kernel(&get_kernel_version(), arch)?, }; let minirootfs = format!("{}/minirootfs", app_dir); downloader::download_alpine_rootfs(&minirootfs, arch)?; @@ -513,7 +518,7 @@ impl RootfsPreparer for NixOSPreparer { ); let kernel_file = match kernel_file { Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), - None => downloader::download_kernel(arch)?, + None => downloader::download_kernel(&get_kernel_version(), arch)?, }; let nixos_rootfs = format!("{}/nixos-rootfs", app_dir); let squashfs_file = format!("{}/nixos-rootfs.squashfs", app_dir); @@ -573,7 +578,7 @@ impl RootfsPreparer for FedoraPreparer { let kernel_file = match kernel_file { Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), - None => downloader::download_kernel(arch)?, + None => downloader::download_kernel(&get_kernel_version(), arch)?, }; let fedora_rootfs = format!("{}/fedora-rootfs", app_dir); let squashfs_file = format!("{}/fedora-rootfs.squashfs", app_dir); @@ -639,7 +644,7 @@ impl RootfsPreparer for GentooPreparer { let kernel_file = match kernel_file { Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), - None => downloader::download_kernel(arch)?, + None => downloader::download_kernel(&get_kernel_version(), arch)?, }; let gentoo_rootfs = format!("{}/gentoo-rootfs", app_dir); @@ -701,7 +706,7 @@ impl RootfsPreparer for SlackwarePreparer { let kernel_file = match kernel_file { Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), - None => downloader::download_kernel(arch)?, + None => downloader::download_kernel(&get_kernel_version(), arch)?, }; let slackware_rootfs = format!("{}/slackware-rootfs", app_dir); @@ -768,7 +773,7 @@ impl RootfsPreparer for OpensusePreparer { let kernel_file = match kernel_file { Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), - None => downloader::download_kernel(arch)?, + None => downloader::download_kernel(&get_kernel_version(), arch)?, }; let opensuse_rootfs = format!("{}/opensuse-rootfs", app_dir); @@ -829,7 +834,7 @@ impl RootfsPreparer for AlmalinuxPreparer { let kernel_file = match kernel_file { Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), - None => downloader::download_kernel(arch)?, + None => downloader::download_kernel(&get_kernel_version(), arch)?, }; let almalinux_rootfs = format!("{}/almalinux-rootfs", app_dir); @@ -884,7 +889,7 @@ impl RootfsPreparer for RockyLinuxPreparer { let kernel_file = match kernel_file { Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), - None => downloader::download_kernel(arch)?, + None => downloader::download_kernel(&get_kernel_version(), arch)?, }; let rockylinux_rootfs = format!("{}/rockylinux-rootfs", app_dir); @@ -938,7 +943,7 @@ impl RootfsPreparer for ArchlinuxPreparer { let kernel_file = match kernel_file { Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), - None => downloader::download_kernel(arch)?, + None => downloader::download_kernel(&get_kernel_version(), arch)?, }; let archlinux_rootfs = format!("{}/archlinux-rootfs", app_dir); let squashfs_file = format!("{}/archlinux-rootfs.squashfs", app_dir); @@ -1003,7 +1008,7 @@ impl RootfsPreparer for OpensuseTumbleweedPreparer { let kernel_file = match kernel_file { Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), - None => downloader::download_kernel(arch)?, + None => downloader::download_kernel(&get_kernel_version(), arch)?, }; let opensuse_rootfs = format!("{}/opensuse-tumbleweed-rootfs", app_dir); diff --git a/crates/firecracker-up/src/cmd/up.rs b/crates/firecracker-up/src/cmd/up.rs index 19f3216..9cfc339 100644 --- a/crates/firecracker-up/src/cmd/up.rs +++ b/crates/firecracker-up/src/cmd/up.rs @@ -78,12 +78,12 @@ pub async fn up(options: VmOptions) -> Result<(), Error> { } } - firecracker_prepare::prepare( + let kernel_file = firecracker_prepare::prepare( options.clone().into(), options.vmlinux.clone(), options.ssh_keys.clone(), )?; - firecracker_vm::setup(&options, pid, vm_id).await?; + firecracker_vm::setup(&options, pid, vm_id, &kernel_file).await?; Ok(()) } diff --git a/crates/firecracker-vm/src/lib.rs b/crates/firecracker-vm/src/lib.rs index aadae45..8a646fd 100644 --- a/crates/firecracker-vm/src/lib.rs +++ b/crates/firecracker-vm/src/lib.rs @@ -19,7 +19,12 @@ mod mqttc; mod network; pub mod types; -pub async fn setup(options: &VmOptions, pid: u32, vm_id: Option) -> Result { +pub async fn setup( + options: &VmOptions, + pid: u32, + vm_id: Option, + kernel_file: &str, +) -> Result { let distro: Distro = options.clone().into(); let app_dir = get_config_dir().with_context(|| "Failed to get configuration directory")?; @@ -43,16 +48,11 @@ pub async fn setup(options: &VmOptions, pid: u32, vm_id: Option) -> Resu fs::File::create(&logfile) .with_context(|| format!("Failed to create log file: {}", logfile))?; - let kernel = glob::glob(format!("{}/vmlinux*", app_dir).as_str()) - .with_context(|| "Failed to glob kernel files")? - .last() - .ok_or_else(|| anyhow!("No kernel file found"))? - .with_context(|| "Failed to get kernel path")?; - let kernel = fs::canonicalize(&kernel) + let kernel = fs::canonicalize(kernel_file) .with_context(|| { format!( "Failed to resolve absolute path for kernel: {}", - kernel.display() + kernel_file ) })? .display()