Prepare, configure, and manage Firecracker microVMs in seconds!
virtualization linux microvm firecracker
at main 137 lines 4.2 kB view raw
1use std::{process, thread}; 2 3use anyhow::{Context, Error}; 4 5use crate::{command::run_command, mqttc, types::VmOptions}; 6 7pub const COREDNS_CONFIG_PATH: &str = "/etc/coredns/Corefile"; 8pub const COREDNS_SERVICE_TEMPLATE: &str = include_str!("./systemd/coredns.service"); 9 10pub fn setup_coredns(config: &VmOptions) -> Result<(), Error> { 11 let api_socket = config.api_socket.clone(); 12 if !coredns_is_installed()? { 13 println!("[✗] CoreDNS is not installed. Please install it first to /usr/sbin."); 14 process::exit(1); 15 } 16 17 if !etcd_is_installed()? { 18 println!("[+] Installing etcd..."); 19 run_command( 20 "apt-get", 21 &["install", "-y", "etcd-server", "etcd-client"], 22 true, 23 )?; 24 } 25 26 run_command( 27 "sh", 28 &[ 29 "-c", 30 &format!( 31 "echo '{}' > {}", 32 include_str!("./coredns/Corefile"), 33 COREDNS_CONFIG_PATH 34 ), 35 ], 36 true, 37 )?; 38 39 run_command( 40 "sh", 41 &[ 42 "-c", 43 &format!( 44 "echo '{}' > /etc/systemd/system/coredns.service", 45 COREDNS_SERVICE_TEMPLATE 46 ), 47 ], 48 true, 49 )?; 50 restart_coredns()?; 51 52 let etcd_args = match config.etcd.clone() { 53 Some(etcd) => { 54 let mut args = vec![]; 55 if let Some(endpoints) = &etcd.endpoints { 56 args.push(format!("--endpoints={}", endpoints.join(","))); 57 } 58 if let Some(user) = &etcd.user { 59 args.push(format!("--user={}", user)); 60 } 61 if let Some(password) = &etcd.password { 62 args.push(format!("--password={}", password)); 63 } 64 if let Some(cacert) = &etcd.cacert { 65 args.push(format!("--cacert={}", cacert)); 66 } 67 if let Some(cert) = &etcd.cert { 68 args.push(format!("--cert={}", cert)); 69 } 70 args 71 } 72 None => vec![], 73 }; 74 75 thread::spawn(move || { 76 let runtime = tokio::runtime::Runtime::new().unwrap(); 77 match runtime.block_on(async { 78 let message = mqttc::wait_for_mqtt_message("REQUEST").await?; 79 let ip_addr = message 80 .split_whitespace() 81 .nth(2) 82 .ok_or_else(|| anyhow::anyhow!("Failed to extract IP address from MQTT message"))?; 83 84 let name = api_socket 85 .split('/') 86 .last() 87 .ok_or_else(|| anyhow::anyhow!("Failed to extract VM name from API socket path"))? 88 .replace("firecracker-", "") 89 .replace(".sock", ""); 90 91 std::fs::write(format!("/tmp/firecracker-{}.ip", name), ip_addr) 92 .with_context(|| "Failed to write IP address to file")?; 93 94 println!( 95 "[+] Assigning DNS entry: {}.firecracker -> {}", 96 name, ip_addr 97 ); 98 99 let etcd_key = format!("/skydns/firecracker/{}", name); 100 let etcd_value = format!("{{\"host\":\"{}\"}}", ip_addr); 101 let mut args = vec!["put", &etcd_key, &etcd_value]; 102 args.extend(etcd_args.iter().map(String::as_str)); 103 104 run_command("etcdctl", &args, false)?; 105 106 Ok::<(), Error>(()) 107 }) { 108 Ok(_) => {} 109 Err(e) => { 110 eprintln!("[✗] Error setting up CoreDNS: {}", e); 111 process::exit(1); 112 } 113 } 114 Ok::<(), Error>(()) 115 }); 116 117 Ok(()) 118} 119 120pub fn restart_coredns() -> Result<(), Error> { 121 println!("[+] Starting CoreDNS..."); 122 run_command("systemctl", &["enable", "coredns"], true)?; 123 run_command("systemctl", &["daemon-reload"], true)?; 124 run_command("systemctl", &["restart", "coredns"], true)?; 125 println!("[✓] CoreDNS started successfully."); 126 Ok(()) 127} 128 129pub fn coredns_is_installed() -> Result<bool, Error> { 130 let output = run_command("which", &["coredns"], false)?; 131 Ok(output.status.success()) 132} 133 134pub fn etcd_is_installed() -> Result<bool, Error> { 135 let output = run_command("ls", &["/usr/bin/etcd"], false)?; 136 Ok(output.status.success()) 137}