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

run cargo fmt

+72 -51
+21 -19
crates/firecracker-state/src/repo/virtual_machine.rs
··· 43 pub async fn create(pool: Pool<Sqlite>, vm: VirtualMachine) -> Result<(), Error> { 44 let id = xid::new().to_string(); 45 let project_dir = match Path::exists(Path::new("fire.toml")) { 46 - true => Some(std::env::current_dir()?.display().to_string()), 47 - false => None, 48 }; 49 - sqlx::query("INSERT INTO virtual_machines ( 50 name, 51 id, 52 project_dir, ··· 59 distro, 60 pid, 61 status 62 - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") 63 - .bind(&vm.name) 64 - .bind(&id) 65 - .bind(project_dir) 66 - .bind(&vm.bridge) 67 - .bind(&vm.tap) 68 - .bind(&vm.api_socket) 69 - .bind(&vm.mac_address) 70 - .bind(&vm.vcpu) 71 - .bind(&vm.memory) 72 - .bind(&vm.distro) 73 - .bind(&vm.pid) 74 - .bind("RUNNING") 75 - .execute(&pool) 76 - .await 77 - .with_context(|| "Failed to create virtual machine")?; 78 Ok(()) 79 } 80
··· 43 pub async fn create(pool: Pool<Sqlite>, vm: VirtualMachine) -> Result<(), Error> { 44 let id = xid::new().to_string(); 45 let project_dir = match Path::exists(Path::new("fire.toml")) { 46 + true => Some(std::env::current_dir()?.display().to_string()), 47 + false => None, 48 }; 49 + sqlx::query( 50 + "INSERT INTO virtual_machines ( 51 name, 52 id, 53 project_dir, ··· 60 distro, 61 pid, 62 status 63 + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 64 + ) 65 + .bind(&vm.name) 66 + .bind(&id) 67 + .bind(project_dir) 68 + .bind(&vm.bridge) 69 + .bind(&vm.tap) 70 + .bind(&vm.api_socket) 71 + .bind(&vm.mac_address) 72 + .bind(&vm.vcpu) 73 + .bind(&vm.memory) 74 + .bind(&vm.distro) 75 + .bind(&vm.pid) 76 + .bind("RUNNING") 77 + .execute(&pool) 78 + .await 79 + .with_context(|| "Failed to create virtual machine")?; 80 Ok(()) 81 } 82
+6 -2
crates/firecracker-up/src/cmd/ssh.rs
··· 15 let vm = repo::virtual_machine::find_by_project_dir(pool, &current_dir).await?; 16 match vm { 17 Some(vm) => format!("{}.firecracker.local", vm.name), 18 - None => return Err(Error::msg("No virtual machine found with the given name or project directory.")), 19 } 20 - }, 21 }; 22 let app_dir = get_config_dir()?; 23 let private_key = glob(format!("{}/id_rsa", app_dir).as_str())
··· 15 let vm = repo::virtual_machine::find_by_project_dir(pool, &current_dir).await?; 16 match vm { 17 Some(vm) => format!("{}.firecracker.local", vm.name), 18 + None => { 19 + return Err(Error::msg( 20 + "No virtual machine found with the given name or project directory.", 21 + )) 22 + } 23 } 24 + } 25 }; 26 let app_dir = get_config_dir()?; 27 let private_key = glob(format!("{}/id_rsa", app_dir).as_str())
+27 -17
crates/firecracker-up/src/main.rs
··· 1 use anyhow::Result; 2 use clap::{arg, Arg, Command}; 3 use firecracker_vm::{ 4 - constants::{BRIDGE_DEV, TAP_DEV}, mac::generate_unique_mac, types::VmOptions 5 }; 6 use owo_colors::OwoColorize; 7 ··· 67 ) 68 .subcommand( 69 Command::new("down") 70 - .arg( 71 - arg!([name] "Name of the Firecracker MicroVM to reset") 72 - .required(false), 73 - ) 74 .about("Stop Firecracker MicroVM"), 75 ) 76 .subcommand(Command::new("status").about("Check the status of Firecracker MicroVM")) ··· 84 ) 85 .about("View the logs of the Firecracker MicroVM"), 86 ) 87 - .subcommand(Command::new("ssh") 88 - .arg(arg!([name] "Name of the Firecracker MicroVM to SSH into")) 89 - .about("SSH into the Firecracker MicroVM")) 90 .subcommand( 91 Command::new("reset") 92 - .arg( 93 - arg!([name] "Name of the Firecracker MicroVM to reset") 94 - .required(false), 95 - ) 96 .about("Reset the Firecracker MicroVM"), 97 ) 98 .arg(arg!(--debian "Prepare Debian MicroVM").default_value("false")) ··· 150 let bootargs = matches.get_one::<String>("boot-args").cloned(); 151 let bridge = args.get_one::<String>("bridge").cloned().unwrap(); 152 let tap = args.get_one::<String>("tap").cloned().unwrap(); 153 - let api_socket = args.get_one::<String>("api-socket").cloned().unwrap_or(default_socket); 154 - let mac_address = args.get_one::<String>("mac-address").cloned().unwrap_or(default_mac); 155 let options = VmOptions { 156 debian: args.get_one::<bool>("debian").copied(), 157 alpine: args.get_one::<bool>("alpine").copied(), ··· 185 Some(("ssh", args)) => { 186 let name = args.get_one::<String>("name").cloned(); 187 ssh(pool, name).await? 188 - }, 189 Some(("reset", args)) => { 190 let name = args.get_one::<String>("name").cloned().unwrap(); 191 let api_socket = format!("/tmp/firecracker-{}.sock", name); ··· 212 let bootargs = matches.get_one::<String>("boot-args").cloned(); 213 let bridge = matches.get_one::<String>("bridge").cloned().unwrap(); 214 let tap = matches.get_one::<String>("tap").cloned().unwrap(); 215 - let api_socket = matches.get_one::<String>("api-socket").cloned().unwrap_or(default_socket); 216 - let mac_address = matches.get_one::<String>("mac-address").cloned().unwrap_or(default_mac); 217 218 let options = VmOptions { 219 debian: Some(debian),
··· 1 use anyhow::Result; 2 use clap::{arg, Arg, Command}; 3 use firecracker_vm::{ 4 + constants::{BRIDGE_DEV, TAP_DEV}, 5 + mac::generate_unique_mac, 6 + types::VmOptions, 7 }; 8 use owo_colors::OwoColorize; 9 ··· 69 ) 70 .subcommand( 71 Command::new("down") 72 + .arg(arg!([name] "Name of the Firecracker MicroVM to reset").required(false)) 73 .about("Stop Firecracker MicroVM"), 74 ) 75 .subcommand(Command::new("status").about("Check the status of Firecracker MicroVM")) ··· 83 ) 84 .about("View the logs of the Firecracker MicroVM"), 85 ) 86 + .subcommand( 87 + Command::new("ssh") 88 + .arg(arg!([name] "Name of the Firecracker MicroVM to SSH into")) 89 + .about("SSH into the Firecracker MicroVM"), 90 + ) 91 .subcommand( 92 Command::new("reset") 93 + .arg(arg!([name] "Name of the Firecracker MicroVM to reset").required(false)) 94 .about("Reset the Firecracker MicroVM"), 95 ) 96 .arg(arg!(--debian "Prepare Debian MicroVM").default_value("false")) ··· 148 let bootargs = matches.get_one::<String>("boot-args").cloned(); 149 let bridge = args.get_one::<String>("bridge").cloned().unwrap(); 150 let tap = args.get_one::<String>("tap").cloned().unwrap(); 151 + let api_socket = args 152 + .get_one::<String>("api-socket") 153 + .cloned() 154 + .unwrap_or(default_socket); 155 + let mac_address = args 156 + .get_one::<String>("mac-address") 157 + .cloned() 158 + .unwrap_or(default_mac); 159 let options = VmOptions { 160 debian: args.get_one::<bool>("debian").copied(), 161 alpine: args.get_one::<bool>("alpine").copied(), ··· 189 Some(("ssh", args)) => { 190 let name = args.get_one::<String>("name").cloned(); 191 ssh(pool, name).await? 192 + } 193 Some(("reset", args)) => { 194 let name = args.get_one::<String>("name").cloned().unwrap(); 195 let api_socket = format!("/tmp/firecracker-{}.sock", name); ··· 216 let bootargs = matches.get_one::<String>("boot-args").cloned(); 217 let bridge = matches.get_one::<String>("bridge").cloned().unwrap(); 218 let tap = matches.get_one::<String>("tap").cloned().unwrap(); 219 + let api_socket = matches 220 + .get_one::<String>("api-socket") 221 + .cloned() 222 + .unwrap_or(default_socket); 223 + let mac_address = matches 224 + .get_one::<String>("mac-address") 225 + .cloned() 226 + .unwrap_or(default_mac); 227 228 let options = VmOptions { 229 debian: Some(debian),
+18 -13
crates/firecracker-vm/src/lib.rs
··· 20 let distro: Distro = options.clone().into(); 21 let app_dir = get_config_dir().with_context(|| "Failed to get configuration directory")?; 22 23 - let name = options.api_socket 24 .split('/') 25 .last() 26 .ok_or_else(|| anyhow!("Failed to extract VM name from API socket path"))? ··· 108 Distro::NixOS => "nixos".into(), 109 Distro::Ubuntu => "ubuntu".into(), 110 }; 111 - repo::virtual_machine::create(pool, VirtualMachine { 112 - vcpu: options.vcpu, 113 - memory: options.memory, 114 - api_socket: options.api_socket.clone(), 115 - bridge: options.bridge.clone(), 116 - tap: options.tap.clone(), 117 - mac_address: options.mac_address.clone(), 118 - name: name.clone(), 119 - pid: Some(pid), 120 - distro, 121 - ..Default::default() 122 - }).await?; 123 124 println!("[✓] MicroVM booted and network is configured 🎉"); 125
··· 20 let distro: Distro = options.clone().into(); 21 let app_dir = get_config_dir().with_context(|| "Failed to get configuration directory")?; 22 23 + let name = options 24 + .api_socket 25 .split('/') 26 .last() 27 .ok_or_else(|| anyhow!("Failed to extract VM name from API socket path"))? ··· 109 Distro::NixOS => "nixos".into(), 110 Distro::Ubuntu => "ubuntu".into(), 111 }; 112 + repo::virtual_machine::create( 113 + pool, 114 + VirtualMachine { 115 + vcpu: options.vcpu, 116 + memory: options.memory, 117 + api_socket: options.api_socket.clone(), 118 + bridge: options.bridge.clone(), 119 + tap: options.tap.clone(), 120 + mac_address: options.mac_address.clone(), 121 + name: name.clone(), 122 + pid: Some(pid), 123 + distro, 124 + ..Default::default() 125 + }, 126 + ) 127 + .await?; 128 129 println!("[✓] MicroVM booted and network is configured 🎉"); 130