Prepare, configure, and manage Firecracker microVMs in seconds!
virtualization linux microvm firecracker

Merge pull request #13 from tsirysndr/feat/default-vmlinux

feat: update kernel handling in microvm and downloader services

authored by tsiry-sandratraina.com and committed by

GitHub a8fd32b4 462bb085

+51 -30
+3 -2
crates/fire-server/src/services/microvm.rs
··· 160 160 } 161 161 } 162 162 163 - firecracker_prepare::prepare(options.clone().into(), options.vmlinux.clone(), ssh_keys)?; 164 - let vm_id = firecracker_vm::setup(&options, pid, vm_id).await?; 163 + let kernel_file = 164 + firecracker_prepare::prepare(options.clone().into(), options.vmlinux.clone(), ssh_keys)?; 165 + let vm_id = firecracker_vm::setup(&options, pid, vm_id, &kernel_file).await?; 165 166 let vm = repo::virtual_machine::find(&pool, &vm_id) 166 167 .await? 167 168 .ok_or_else(|| Error::msg("Failed to retrieve the created VM"))?;
+19 -4
crates/firecracker-prepare/src/downloader.rs
··· 3 3 use regex::Regex; 4 4 use std::path::Path; 5 5 6 - use crate::command::{run_command, run_command_with_stdout_inherit}; 6 + use crate::{ 7 + command::{run_command, run_command_with_stdout_inherit}, 8 + get_kernel_version, 9 + }; 7 10 8 11 pub fn download_files(arch: &str) -> Result<(String, String, String)> { 9 12 let app_dir = 10 13 crate::config::get_config_dir().with_context(|| "Failed to get configuration directory")?; 11 - let kernel_file = download_kernel(arch)?; 14 + let kernel_file = download_kernel(&get_kernel_version(), arch)?; 12 15 13 16 let ci_version = get_ci_version().with_context(|| "Failed to get CI version")?; 14 17 ··· 73 76 Ok(ci_version.to_string()) 74 77 } 75 78 76 - pub fn download_kernel(arch: &str) -> Result<String> { 79 + pub fn download_kernel_from_firecracker(arch: &str) -> Result<String> { 77 80 let app_dir = 78 81 crate::config::get_config_dir().with_context(|| "Failed to get configuration directory")?; 79 82 let ci_version = ··· 99 102 Ok(kernel_file) 100 103 } 101 104 105 + pub fn download_kernel(version: &str, arch: &str) -> Result<String> { 106 + let app_dir = 107 + crate::config::get_config_dir().with_context(|| "Failed to get configuration directory")?; 108 + let kernel_file = format!("{}/vmlinux-{}.{}", app_dir, version, arch); 109 + let kernel_url = &format!( 110 + "https://github.com/tsirysndr/vmlinux-builder/releases/download/{}/vmlinux-{}.{}", 111 + version, version, arch, 112 + ); 113 + download_file(kernel_url, &kernel_file)?; 114 + Ok(kernel_file) 115 + } 116 + 102 117 fn get_latest_key(url: &str, prefix: &str) -> Result<String> { 103 118 let output = run_command( 104 119 "curl", ··· 157 172 return Ok(()); 158 173 } 159 174 println!("Downloading: {}", output.bright_green()); 160 - run_command_with_stdout_inherit("wget", &["-O", output, url], false)?; 175 + run_command_with_stdout_inherit("curl", &["-L", "-o", output, url], false)?; 161 176 Ok(()) 162 177 } 163 178
+19 -14
crates/firecracker-prepare/src/lib.rs
··· 1 - use std::fs; 1 + use std::{env, fs}; 2 2 3 3 use anyhow::Result; 4 4 use owo_colors::OwoColorize; ··· 19 19 20 20 const BRIDGE_IP: &str = "172.16.0.1"; 21 21 22 + fn get_kernel_version() -> String { 23 + env::var("KERNEL_VERSION").unwrap_or_else(|_| "6.16.7".to_string()) 24 + } 25 + 22 26 #[derive(Clone, Copy, PartialEq, Serialize, Deserialize, Debug)] 23 27 pub enum Distro { 24 28 Debian, ··· 58 62 distro: Distro, 59 63 kernel_file: Option<String>, 60 64 ssh_keys: Option<Vec<String>>, 61 - ) -> Result<()> { 65 + ) -> Result<String> { 62 66 let arch = run_command("uname", &["-m"], false)?.stdout; 63 67 let arch = String::from_utf8_lossy(&arch).trim().to_string(); 64 68 println!("[+] Detected architecture: {}", arch.bright_green()); ··· 102 106 Some(ssh_key_file) => println!("[✓] SSH Key: {}", ssh_key_file.bright_green()), 103 107 } 104 108 105 - Ok(()) 109 + Ok(kernel_file) 106 110 } 107 111 108 112 pub trait RootfsPreparer { ··· 149 153 150 154 let kernel_file = match kernel_file { 151 155 Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), 152 - None => downloader::download_kernel(arch)?, 156 + None => downloader::download_kernel(&get_kernel_version(), arch)?, 153 157 }; 158 + 154 159 let debootstrap_dir = format!("{}/debian-rootfs", app_dir); 155 160 156 161 let arch = match arch { ··· 288 293 289 294 let kernel_file = match kernel_file { 290 295 Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), 291 - None => downloader::download_kernel(arch)?, 296 + None => downloader::download_kernel(&get_kernel_version(), arch)?, 292 297 }; 293 298 let minirootfs = format!("{}/minirootfs", app_dir); 294 299 downloader::download_alpine_rootfs(&minirootfs, arch)?; ··· 513 518 ); 514 519 let kernel_file = match kernel_file { 515 520 Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), 516 - None => downloader::download_kernel(arch)?, 521 + None => downloader::download_kernel(&get_kernel_version(), arch)?, 517 522 }; 518 523 let nixos_rootfs = format!("{}/nixos-rootfs", app_dir); 519 524 let squashfs_file = format!("{}/nixos-rootfs.squashfs", app_dir); ··· 573 578 574 579 let kernel_file = match kernel_file { 575 580 Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), 576 - None => downloader::download_kernel(arch)?, 581 + None => downloader::download_kernel(&get_kernel_version(), arch)?, 577 582 }; 578 583 let fedora_rootfs = format!("{}/fedora-rootfs", app_dir); 579 584 let squashfs_file = format!("{}/fedora-rootfs.squashfs", app_dir); ··· 639 644 640 645 let kernel_file = match kernel_file { 641 646 Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), 642 - None => downloader::download_kernel(arch)?, 647 + None => downloader::download_kernel(&get_kernel_version(), arch)?, 643 648 }; 644 649 645 650 let gentoo_rootfs = format!("{}/gentoo-rootfs", app_dir); ··· 701 706 702 707 let kernel_file = match kernel_file { 703 708 Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), 704 - None => downloader::download_kernel(arch)?, 709 + None => downloader::download_kernel(&get_kernel_version(), arch)?, 705 710 }; 706 711 707 712 let slackware_rootfs = format!("{}/slackware-rootfs", app_dir); ··· 768 773 769 774 let kernel_file = match kernel_file { 770 775 Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), 771 - None => downloader::download_kernel(arch)?, 776 + None => downloader::download_kernel(&get_kernel_version(), arch)?, 772 777 }; 773 778 774 779 let opensuse_rootfs = format!("{}/opensuse-rootfs", app_dir); ··· 829 834 830 835 let kernel_file = match kernel_file { 831 836 Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), 832 - None => downloader::download_kernel(arch)?, 837 + None => downloader::download_kernel(&get_kernel_version(), arch)?, 833 838 }; 834 839 835 840 let almalinux_rootfs = format!("{}/almalinux-rootfs", app_dir); ··· 884 889 885 890 let kernel_file = match kernel_file { 886 891 Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), 887 - None => downloader::download_kernel(arch)?, 892 + None => downloader::download_kernel(&get_kernel_version(), arch)?, 888 893 }; 889 894 890 895 let rockylinux_rootfs = format!("{}/rockylinux-rootfs", app_dir); ··· 938 943 939 944 let kernel_file = match kernel_file { 940 945 Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), 941 - None => downloader::download_kernel(arch)?, 946 + None => downloader::download_kernel(&get_kernel_version(), arch)?, 942 947 }; 943 948 let archlinux_rootfs = format!("{}/archlinux-rootfs", app_dir); 944 949 let squashfs_file = format!("{}/archlinux-rootfs.squashfs", app_dir); ··· 1003 1008 1004 1009 let kernel_file = match kernel_file { 1005 1010 Some(k) => fs::canonicalize(k)?.to_str().unwrap().to_string(), 1006 - None => downloader::download_kernel(arch)?, 1011 + None => downloader::download_kernel(&get_kernel_version(), arch)?, 1007 1012 }; 1008 1013 1009 1014 let opensuse_rootfs = format!("{}/opensuse-tumbleweed-rootfs", app_dir);
+2 -2
crates/firecracker-up/src/cmd/up.rs
··· 78 78 } 79 79 } 80 80 81 - firecracker_prepare::prepare( 81 + let kernel_file = firecracker_prepare::prepare( 82 82 options.clone().into(), 83 83 options.vmlinux.clone(), 84 84 options.ssh_keys.clone(), 85 85 )?; 86 - firecracker_vm::setup(&options, pid, vm_id).await?; 86 + firecracker_vm::setup(&options, pid, vm_id, &kernel_file).await?; 87 87 Ok(()) 88 88 } 89 89
+8 -8
crates/firecracker-vm/src/lib.rs
··· 19 19 mod network; 20 20 pub mod types; 21 21 22 - pub async fn setup(options: &VmOptions, pid: u32, vm_id: Option<String>) -> Result<String> { 22 + pub async fn setup( 23 + options: &VmOptions, 24 + pid: u32, 25 + vm_id: Option<String>, 26 + kernel_file: &str, 27 + ) -> Result<String> { 23 28 let distro: Distro = options.clone().into(); 24 29 let app_dir = get_config_dir().with_context(|| "Failed to get configuration directory")?; 25 30 ··· 43 48 fs::File::create(&logfile) 44 49 .with_context(|| format!("Failed to create log file: {}", logfile))?; 45 50 46 - let kernel = glob::glob(format!("{}/vmlinux*", app_dir).as_str()) 47 - .with_context(|| "Failed to glob kernel files")? 48 - .last() 49 - .ok_or_else(|| anyhow!("No kernel file found"))? 50 - .with_context(|| "Failed to get kernel path")?; 51 - let kernel = fs::canonicalize(&kernel) 51 + let kernel = fs::canonicalize(kernel_file) 52 52 .with_context(|| { 53 53 format!( 54 54 "Failed to resolve absolute path for kernel: {}", 55 - kernel.display() 55 + kernel_file 56 56 ) 57 57 })? 58 58 .display()