Load or update a VM, preserving existing statistics
(
&self,
work_dir: impl AsRef<Path>,
cids_assigned: &HashMap<String, u32>,
auto_start: bool,
)
| 745 | |
| 746 | /// Load or update a VM, preserving existing statistics |
| 747 | async fn load_or_update_vm( |
| 748 | &self, |
| 749 | work_dir: impl AsRef<Path>, |
| 750 | cids_assigned: &HashMap<String, u32>, |
| 751 | auto_start: bool, |
| 752 | ) -> Result<bool> { |
| 753 | let vm_work_dir = VmWorkDir::new(work_dir.as_ref()); |
| 754 | let manifest = vm_work_dir.manifest().context("Failed to read manifest")?; |
| 755 | if manifest.image.len() > 64 |
| 756 | || manifest.image.contains("..") |
| 757 | || !manifest |
| 758 | .image |
| 759 | .chars() |
| 760 | .all(|c| c.is_alphanumeric() || c == '_' || c == '-' || c == '.') |
| 761 | { |
| 762 | bail!("Invalid image name"); |
| 763 | } |
| 764 | let image_path = self.config.image.path.join(&manifest.image); |
| 765 | let image = Image::load(&image_path).context("Failed to load image")?; |
| 766 | let vm_id = manifest.id.clone(); |
| 767 | let already_running = cids_assigned.contains_key(&vm_id); |
| 768 | let app_compose = vm_work_dir |
| 769 | .app_compose() |
| 770 | .context("Failed to read compose file")?; |
| 771 | |
| 772 | let mut is_new = false; |
| 773 | { |
| 774 | let mut states = self.lock(); |
| 775 | |
| 776 | // For existing VMs, keep their current CID |
| 777 | // For new VMs, try to use assigned CID or allocate a new one |
| 778 | let cid = if let Some(existing_vm) = states.get(&vm_id) { |
| 779 | // Keep existing CID |
| 780 | existing_vm.config.cid |
| 781 | } else if let Some(assigned_cid) = cids_assigned.get(&vm_id) { |
| 782 | // Use assigned CID from running processes |
| 783 | *assigned_cid |
| 784 | } else { |
| 785 | // Allocate new CID only for truly new VMs |
| 786 | states.cid_pool.allocate().context("CID pool exhausted")? |
| 787 | }; |
| 788 | |
| 789 | let vm_config = VmConfig { |
| 790 | manifest, |
| 791 | image, |
| 792 | cid, |
| 793 | workdir: vm_work_dir.path().to_path_buf(), |
| 794 | gateway_enabled: app_compose.gateway_enabled(), |
| 795 | }; |
| 796 | |
| 797 | match states.get_mut(&vm_id) { |
| 798 | Some(vm) => { |
| 799 | // Update existing VM but preserve statistics and CID |
| 800 | let old_state = vm.state.clone(); |
| 801 | vm.config = vm_config.into(); |
| 802 | vm.state = old_state; // Preserve the existing state with statistics |
| 803 | } |
| 804 | None => { |
no test coverage detected