From df34fc719c4dd3d19d2cf92cf18d4a852fb84fe1 Mon Sep 17 00:00:00 2001 From: ghe0 Date: Thu, 12 Dec 2024 02:48:18 +0200 Subject: [PATCH] writing files correctly --- scripts/start_qemu_vm.sh | 4 +- src/main.rs | 8 +--- src/state.rs | 97 +++++++++++++++++++++++++------------- test_data/new_vm_req4.yaml | 2 +- 4 files changed, 68 insertions(+), 43 deletions(-) diff --git a/scripts/start_qemu_vm.sh b/scripts/start_qemu_vm.sh index d8d2016..29bece9 100644 --- a/scripts/start_qemu_vm.sh +++ b/scripts/start_qemu_vm.sh @@ -7,7 +7,7 @@ source "/etc/detee/daemon/vms/$VM_UUID" mandatory_vars=("KERNEL" "INITRD" "PARAMS" "CPU_TYPE" \ - "VCPUS" "MEMORY" "MAX_MEMORY" "DISK" "DISK_SIZE") + "VCPUS" "MEMORY" "MAX_MEMORY" "DISK") for var in "${mandatory_vars[@]}"; do if [ -z "${!var}" ]; then echo "Environment variable $var is not set." @@ -51,8 +51,6 @@ done <<< "$( echo "$interfaces" )" vm_disk="/root/dtrfs/arch-1-ghe0.qcow2" -[[ -f $DISK ]] || qemu-img create -f qcow2 ${DISK} ${DISK_SIZE} - qemu-system-x86_64 $qemu_device_params \ -enable-kvm -cpu $CPU_TYPE -vga none \ -machine q35,confidential-guest-support=sev0,memory-backend=ram1 \ diff --git a/src/main.rs b/src/main.rs index c5306b2..2cf5f14 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,7 +19,7 @@ fn main() -> Result<(), Box> { // println!("{:#?}", config); // let config = Config::from_file("test_data/config5.yaml")?; // println!("{:#?}", config); - let new_vm_req = NewVMRequest::from_file("test_data/new_vm_req4.yaml")?; + let new_vm_req = NewVMRequest::from_file("test_data/new_vm_req2.yaml")?; // println!("{:#?}", new_vm_req); // let new_vm_req = NewVMRequest::from_file("test_data/new_vm_req2.yaml")?; @@ -29,11 +29,7 @@ fn main() -> Result<(), Box> { // let new_vm_req = NewVMRequest::from_file("test_data/new_vm_req4.yaml")?; // println!("{:#?}", new_vm_req); let vm = state::VM::new(new_vm_req, &config, &mut res); - let new_vm_req = NewVMRequest::from_file("test_data/new_vm_req4.yaml")?; - let vm = state::VM::new(new_vm_req, &config, &mut res); - let new_vm_req = NewVMRequest::from_file("test_data/new_vm_req4.yaml")?; - let vm = state::VM::new(new_vm_req, &config, &mut res); println!("vm: {:#?}", vm); - println!("res: {:#?}", res); + println!("{:?}", vm.unwrap().start()); Ok(()) } diff --git a/src/state.rs b/src/state.rs index 20d0625..22f1b7b 100644 --- a/src/state.rs +++ b/src/state.rs @@ -205,6 +205,22 @@ impl Resources { self.reserved_ports.insert(*host_port); } } + + fn free_vm_resources(&mut self, vm: &VM) { + self.reserved_vcpus -= vm.vcpus; + self.reserved_memory -= vm.memory; + for nic in vm.nics.iter() { + if let Some(vtap) = nic.if_config.vtap_name() { + self.reserved_if_names.remove(&vtap); + } + for ip in nic.ips.iter() { + self.reserved_ips.remove(&ip.address.clone()); + } + } + for (host_port, _) in vm.fw_ports.iter() { + self.reserved_ports.remove(host_port); + } + } } #[derive(Debug)] @@ -427,6 +443,28 @@ impl VM { Ok(vm) } + pub fn start(&self) -> Result<()> { + self.create_disk()?; + self.write_vm_config()?; + self.write_systemd_unit_file()?; + // TODO: systemctl daemon-reload + // TODO: systemctl start + // TODO: systemctl enable + Ok(()) + } + + pub fn delete(&self, res: &mut Resources) -> Result<()> { + // TODO: systemctl stop + // TODO: systemctl disable + res.free_vm_resources(&self); + self.delete_systemd_unit_file()?; + // TODO: systemctl daemon-reload + self.delete_disk()?; + self.delete_vm_config()?; + self.delete_vtap_interfaces()?; + Ok(()) + } + pub fn deploy(&self) -> Result<()> { self.create_disk()?; self.write_vm_config()?; @@ -435,20 +473,11 @@ impl VM { Ok(()) } - pub fn delete(&self) -> Result<()> { - // TODO: systemctl disable, systemctl stop - self.delete_disk()?; - self.delete_vtap_interfaces()?; - self.delete_systemd_unit_file()?; - // TODO: systemctl daemon-reload - Ok(()) - } - // For the MVP, the T-Contract offers VM+IP+Disk as a bundle. // This means we can enforce the path to the disk. // This may change in the future as the VM is allowed to have multiple disks. pub fn disk_path(&self) -> String { - VM_DISK_DIR.to_string() + "/" + &self.uuid + ".qcow2" + VM_DISK_DIR.to_string() + &self.uuid + ".qcow2" } pub fn kernel_params(&self) -> String { @@ -493,11 +522,11 @@ impl VM { vars += &format!( "KERNEL={}\n", - VM_BOOT_DIR.to_string() + "/" + &self.kernel_sha + VM_BOOT_DIR.to_string() + &self.kernel_sha ); vars += &format!( "INITRD={}\n", - VM_BOOT_DIR.to_string() + "/" + &self.dtrfs_sha + VM_BOOT_DIR.to_string() + &self.dtrfs_sha ); vars += &format!("PARAMS={}\n", self.kernel_params()); vars += &format!("CPU_TYPE={}\n", QEMU_VM_CPU_TYPE); @@ -505,15 +534,14 @@ impl VM { vars += &format!("MEMORY={}MB\n", self.memory); vars += &format!("MAX_MEMORY={}MB\n", self.memory + 256); vars += &format!("DISK={}\n", self.disk_path()); - vars += &format!("DISK_SIZE={}GB\n", self.disk_size); - let mut file = File::create(VM_CONFIG_DIR.to_string() + "/" + &self.uuid)?; + let mut file = File::create(VM_CONFIG_DIR.to_string() + &self.uuid)?; file.write_all(vars.as_bytes())?; Ok(()) } pub fn delete_vm_config(&self) -> Result<()> { - remove_file(VM_CONFIG_DIR.to_string() + "/" + &self.uuid)?; + remove_file(VM_CONFIG_DIR.to_string() + &self.uuid)?; Ok(()) } @@ -540,27 +568,27 @@ impl VM { pub fn write_systemd_unit_file(&self) -> Result<()> { let mut contents = String::new(); - contents += &format!("[Unit]"); - contents += &format!("Description=DeTEE {}", self.uuid); - contents += &format!("After=network.target"); - contents += &format!(""); - contents += &format!("[Service]"); - contents += &format!("Type=simple"); - contents += &format!("Environment=VM_UUID={}", self.uuid); - contents += &format!("ExecStart={}", START_VM_SCRIPT); - contents += &format!("ExecStop=/bin/kill -s SIGINT $MAINPID"); - contents += &format!("Restart=always"); - contents += &format!(""); - contents += &format!("[Install]"); - contents += &format!("WantedBy=multi-user.target"); + contents += &format!("[Unit]\n"); + contents += &format!("Description=DeTEE {}\n", self.uuid); + contents += &format!("After=network.target\n"); + contents += &format!("\n"); + contents += &format!("[Service]\n"); + contents += &format!("Type=simple\n"); + contents += &format!("Environment=VM_UUID={}\n", self.uuid); + contents += &format!("ExecStart={}\n", START_VM_SCRIPT); + contents += &format!("ExecStop=/bin/kill -s SIGINT $MAINPID\n"); + contents += &format!("Restart=always\n"); + contents += &format!("\n"); + contents += &format!("[Install]\n"); + contents += &format!("WantedBy=multi-user.target\n"); - let mut file = File::create("/etc/systemd/system/".to_string() + &self.uuid + ".service")?; + let mut file = File::create("/tmp/etc/systemd/system/".to_string() + &self.uuid + ".service")?; file.write_all(contents.as_bytes())?; Ok(()) } pub fn delete_systemd_unit_file(&self) -> Result<()> { - remove_file("/etc/systemd/system/".to_string() + &self.uuid + ".service")?; + remove_file("/tmp/etc/systemd/system/".to_string() + &self.uuid + ".service")?; Ok(()) } @@ -568,14 +596,17 @@ impl VM { let result = Command::new("qemu-img") .arg("create") .arg("-f") + .arg("qcow2") .arg(self.disk_path()) .arg(self.disk_size.to_string() + "G") .output()?; if !result.status.success() { return Err(anyhow!( "Could not create VM Disk:\n{:?}\n{:?}", - result.stdout, - result.stderr + String::from_utf8(result.stdout) + .unwrap_or("Could not grab stdout from creation script.".to_string()), + String::from_utf8(result.stderr) + .unwrap_or("Could not grab stderr from creation script.".to_string()), )); } Ok(()) @@ -592,7 +623,7 @@ fn download_and_check_sha(url: &str, sha: &str) -> Result<()> { use std::fs::File; use std::io::copy; use std::path::Path; - let save_path = VM_BOOT_DIR.to_string() + "/" + sha; + let save_path = VM_BOOT_DIR.to_string() + sha; let response = get(url)?; if !response.status().is_success() { return Err(anyhow!("Failed to download file: {}", response.status())); diff --git a/test_data/new_vm_req4.yaml b/test_data/new_vm_req4.yaml index 91f5217..9bca679 100644 --- a/test_data/new_vm_req4.yaml +++ b/test_data/new_vm_req4.yaml @@ -1,4 +1,4 @@ -uuid: "default-uuid" +uuid: "DuTenPulaMeaCuUUIDulTauCuTot" hostname: "testing-vm" admin_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAAKeyExampleForTesting" extra_ports: [1234, 5678]