Prepare, configure, and manage Firecracker microVMs in seconds!
virtualization linux microvm firecracker
at main 105 lines 3.0 kB view raw
1use std::{process, thread}; 2 3use anyhow::Error; 4use fire_config::read_config; 5use firecracker_state::repo; 6use firecracker_vm::types::VmOptions; 7use owo_colors::OwoColorize; 8 9use crate::command::run_command; 10 11pub async fn up(options: VmOptions) -> Result<(), Error> { 12 check_kvm_support()?; 13 14 let mut options = match read_config() { 15 Ok(config) => VmOptions::from(config), 16 Err(_) => options.clone(), 17 }; 18 19 let current_dir = std::env::current_dir()?; 20 let fire_toml = current_dir.join("fire.toml"); 21 let mut vm_id = None; 22 let pool = firecracker_state::create_connection_pool().await?; 23 let vm = repo::virtual_machine::find_by_api_socket(&pool, &options.api_socket).await?; 24 25 if let Some(vm) = vm { 26 vm_id = Some(vm.id.clone()); 27 } 28 29 if fire_toml.exists() { 30 let vm = 31 repo::virtual_machine::find_by_project_dir(&pool, &current_dir.display().to_string()) 32 .await?; 33 34 if let Some(vm) = vm { 35 options.api_socket = vm.api_socket.clone(); 36 vm_id = Some(vm.id.clone()); 37 } 38 } 39 40 let vms = repo::virtual_machine::all(&pool).await?; 41 if options.tap.is_empty() { 42 let vms = vms 43 .into_iter() 44 .filter(|vm| vm.tap.starts_with("tap")) 45 .collect::<Vec<_>>(); 46 options.tap = format!("tap{}", vms.len()); 47 48 while vms.iter().any(|vm| vm.tap == options.tap) { 49 let tap_num: u32 = options 50 .tap 51 .trim_start_matches("tap") 52 .parse::<u32>() 53 .unwrap_or(0) 54 .checked_add(1) 55 .unwrap_or(0); 56 options.tap = format!("tap{}", tap_num); 57 } 58 } else { 59 if vms 60 .iter() 61 .any(|vm| vm.tap == options.tap && vm.api_socket != options.api_socket) 62 { 63 println!( 64 "[!] Tap device name {} is already in use. Please choose a different name.", 65 options.tap.cyan() 66 ); 67 process::exit(1); 68 } 69 } 70 71 let pid = firecracker_process::start(&options).await?; 72 73 loop { 74 thread::sleep(std::time::Duration::from_secs(1)); 75 if firecracker_process::is_running() { 76 println!("[+] Firecracker is running."); 77 break; 78 } 79 } 80 81 let kernel_file = firecracker_prepare::prepare( 82 options.clone().into(), 83 options.vmlinux.clone(), 84 options.ssh_keys.clone(), 85 )?; 86 firecracker_vm::setup(&options, pid, vm_id, &kernel_file).await?; 87 Ok(()) 88} 89 90pub fn check_kvm_support() -> Result<(), Error> { 91 print!("[+] Checking for kvm support... "); 92 93 if !run_command("sh", &["-c", "lsmod | grep kvm"], false) 94 .map(|output| output.status.success()) 95 .unwrap_or(false) 96 { 97 return Err(anyhow::anyhow!( 98 "KVM is not available. Please ensure KVM is enabled in your system." 99 )); 100 } 101 102 println!("{}", "[✓] OK".bright_green()); 103 104 Ok(()) 105}