From 3ba140a830ad915379b9e9c5f1e7a857ab66d8b1 Mon Sep 17 00:00:00 2001 From: ghe0 Date: Sat, 21 Dec 2024 20:10:57 +0000 Subject: [PATCH] enable kernel/dtrfs upgrade (#1) Co-authored-by: Ramil_Algayev Reviewed-on: https://gitea.detee.cloud/SNP/daemon/pulls/1 --- src/main.rs | 13 +++++---- src/state.rs | 74 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 57 insertions(+), 30 deletions(-) diff --git a/src/main.rs b/src/main.rs index a8d9e1f..1a9870e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,7 +35,9 @@ fn main() -> Result<(), Box> { let path = entry.path(); if path.is_file() { let vm_id = path.file_name().unwrap().to_str().unwrap(); - let content = std::fs::read_to_string(crate::constants::VM_CONFIG_DIR.to_string() + vm_id + ".yaml")?; + let content = std::fs::read_to_string( + crate::constants::VM_CONFIG_DIR.to_string() + vm_id + ".yaml", + )?; let vm: crate::state::VM = serde_yaml::from_str(&content)?; vm.delete(&mut res)?; println!("deleted vm {}", vm.uuid); @@ -46,14 +48,15 @@ fn main() -> Result<(), Box> { let entry = entry?; let path = entry.path(); if path.is_file() { - let new_vm_req = UpdateVMReq::from_file(path.to_str().unwrap())?; - let content = std::fs::read_to_string(crate::constants::VM_CONFIG_DIR.to_string() + &new_vm_req.uuid + ".yaml")?; + let update_vm_req = UpdateVMReq::from_file(path.to_str().unwrap())?; + let content = std::fs::read_to_string( + crate::constants::VM_CONFIG_DIR.to_string() + &update_vm_req.uuid + ".yaml", + )?; let mut vm: crate::state::VM = serde_yaml::from_str(&content)?; - vm.update(new_vm_req, &config, &mut res).unwrap(); + vm.update(update_vm_req, &config, &mut res).unwrap(); println!("updated vm {}", vm.uuid); } } - Ok(()) } diff --git a/src/state.rs b/src/state.rs index c43c12a..86ca809 100644 --- a/src/state.rs +++ b/src/state.rs @@ -239,15 +239,15 @@ impl Resources { self.reserved_storage .entry(vm.storage_dir.clone()) - .and_modify(|gb| *gb += vm.disk_size_gb) + .and_modify(|gb| *gb = gb.saturating_add(vm.disk_size_gb)) .or_insert(vm.disk_size_gb); let _ = self.save_to_disk(); } fn free_vm_resources(&mut self, vm: &VM) { self.existing_vms.remove(&vm.uuid); - self.reserved_vcpus -= vm.vcpus; - self.reserved_memory -= vm.memory_mb; + self.reserved_vcpus = self.reserved_vcpus.saturating_sub(vm.vcpus); + self.reserved_memory = self.reserved_memory.saturating_sub(vm.memory_mb); for nic in vm.nics.iter() { if let Some(vtap) = nic.if_config.vtap_name() { self.reserved_if_names.remove(&vtap); @@ -387,6 +387,11 @@ pub struct UpdateVMReq { vcpus: usize, memory_mb: usize, disk_size_gb: usize, + // we are not using Option, as these will be passed from gRPC + kernel_url: String, + kernel_sha: String, + dtrfs_url: String, + dtrfs_sha: String, } impl UpdateVMReq { @@ -439,17 +444,14 @@ impl VM { return Err(VMCreationErrors::DiskTooSmall); } - if let Err(kernel_file_error) = - res.download_boot_file(req.kernel_url, req.kernel_sha.clone()) - { + if let Err(kernel_err) = res.download_boot_file(req.kernel_url, req.kernel_sha.clone()) { return Err(VMCreationErrors::BootFileError(format!( - "Could not get kernel: {kernel_file_error:?}" + "Could not get kernel: {kernel_err:?}" ))); }; - if let Err(dtrfs_file_error) = res.download_boot_file(req.dtrfs_url, req.dtrfs_sha.clone()) - { + if let Err(dtrfs_err) = res.download_boot_file(req.dtrfs_url, req.dtrfs_sha.clone()) { return Err(VMCreationErrors::BootFileError(format!( - "Could not get dtrfs: {dtrfs_file_error:?}" + "Could not get dtrfs: {dtrfs_err:?}" ))); }; @@ -520,7 +522,6 @@ impl VM { Ok(vm) } - // TODO: test to see if this works pub fn update( &mut self, req: UpdateVMReq, @@ -550,17 +551,40 @@ impl VM { return Err(VMCreationErrors::DiskTooSmall); } - res.reserved_memory -= self.memory_mb; - res.reserved_memory += req.memory_mb; - res.reserved_vcpus -= self.vcpus; - res.reserved_vcpus += req.vcpus; + if !req.kernel_sha.is_empty() || !req.dtrfs_sha.is_empty() { + if req.kernel_sha.is_empty() || req.dtrfs_sha.is_empty() { + return Err(VMCreationErrors::BootFileError( + "Kernel and DTRFS can be upgraded only as a bundle".to_string(), + )); + } + if let Err(kern_err) = res.download_boot_file(req.kernel_url, req.kernel_sha.clone()) { + return Err(VMCreationErrors::BootFileError(format!( + "Could not get kernel: {kern_err:?}" + ))); + }; + if let Err(dtrfs_err) = res.download_boot_file(req.dtrfs_url, req.dtrfs_sha.clone()) { + return Err(VMCreationErrors::BootFileError(format!( + "Could not get dtrfs: {dtrfs_err:?}" + ))); + }; + + self.kernel_sha = req.kernel_sha; + self.dtrfs_sha = req.dtrfs_sha; + } + + // Update the resources + res.reserved_memory = res.reserved_memory.saturating_add(req.memory_mb); + res.reserved_memory = res.reserved_memory.saturating_sub(self.memory_mb); + res.reserved_vcpus = res.reserved_vcpus.saturating_add(req.vcpus); + res.reserved_vcpus = res.reserved_vcpus.saturating_sub(self.vcpus); res.reserved_storage .entry(self.storage_dir.clone()) .and_modify(|gb| { - *gb -= self.disk_size_gb; - *gb += req.disk_size_gb; + *gb = gb.saturating_add(req.disk_size_gb); + *gb = gb.saturating_sub(self.disk_size_gb); }); + let _ = res.save_to_disk(); self.memory_mb = req.memory_mb; self.vcpus = req.vcpus; @@ -582,7 +606,7 @@ impl VM { return Err(VMCreationErrors::HypervizorError(e.to_string())); } - if let Err(e) = systemctl_stop_and_disable(&self.uuid) { + if let Err(e) = systemctl_start_and_enable(&self.uuid) { return Err(VMCreationErrors::HypervizorError(e.to_string())); } @@ -599,14 +623,14 @@ impl VM { } pub fn delete(&self, res: &mut Resources) -> Result<()> { - systemctl_stop_and_disable(&self.uuid)?; + let _ = systemctl_stop_and_disable(&self.uuid); + let _ = self.delete_systemd_unit_file(); + let _ = systemctl_reload(); + let _ = self.delete_disk(); + let _ = self.delete_sh_exports(); + let _ = self.delete_vtap_interfaces(); + let _ = self.delete_config(); res.free_vm_resources(&self); - self.delete_systemd_unit_file()?; - systemctl_reload()?; - self.delete_disk()?; - self.delete_sh_exports()?; - self.delete_vtap_interfaces()?; - self.delete_config()?; Ok(()) }