(&self, id: &str)
| 219 | } |
| 220 | |
| 221 | pub async fn start_vm(&self, id: &str) -> Result<()> { |
| 222 | { |
| 223 | let state = self.lock(); |
| 224 | if let Some(vm) = state.get(id) { |
| 225 | if vm.state.removing { |
| 226 | bail!("VM is being removed"); |
| 227 | } |
| 228 | } |
| 229 | } |
| 230 | self.sync_dynamic_config(id)?; |
| 231 | let is_running = self |
| 232 | .supervisor |
| 233 | .info(id) |
| 234 | .await? |
| 235 | .is_some_and(|info| info.state.status.is_running()); |
| 236 | self.set_started(id, true)?; |
| 237 | let vm_config = { |
| 238 | let mut state = self.lock(); |
| 239 | let vm_state = state.get_mut(id).context("VM not found")?; |
| 240 | // Older images does not support for progress reporting |
| 241 | if vm_state.config.image.info.shared_ro { |
| 242 | vm_state.state.start(is_running); |
| 243 | } else { |
| 244 | vm_state.state.reset_na(); |
| 245 | } |
| 246 | vm_state.config.clone() |
| 247 | }; |
| 248 | if !is_running { |
| 249 | let work_dir = self.work_dir(id); |
| 250 | for path in [work_dir.serial_pty(), work_dir.qmp_socket()] { |
| 251 | if path.symlink_metadata().is_ok() { |
| 252 | fs::remove_file(path)?; |
| 253 | } |
| 254 | } |
| 255 | // Append current serial.log to serial.history.log before QEMU truncates it. |
| 256 | rotate_serial_log(&work_dir, self.config.cvm.serial_history_max_bytes); |
| 257 | // Add boot separator to stdout/stderr (they are opened in append mode). |
| 258 | append_boot_separator(&work_dir.stdout_file()); |
| 259 | append_boot_separator(&work_dir.stderr_file()); |
| 260 | |
| 261 | let devices = self.try_allocate_gpus(&vm_config.manifest)?; |
| 262 | let processes = vm_config.config_qemu(&work_dir, &self.config.cvm, &devices)?; |
| 263 | for process in processes { |
| 264 | self.supervisor |
| 265 | .deploy(&process) |
| 266 | .await |
| 267 | .with_context(|| format!("Failed to start process {}", process.id))?; |
| 268 | } |
| 269 | |
| 270 | let mut state = self.lock(); |
| 271 | let vm_state = state.get_mut(id).context("VM not found")?; |
| 272 | vm_state.state.devices = devices; |
| 273 | } |
| 274 | Ok(()) |
| 275 | } |
| 276 | |
| 277 | fn set_started(&self, id: &str, started: bool) -> Result<()> { |
| 278 | let work_dir = self.work_dir(id); |
no test coverage detected