use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use arcbox_vm_driver::ShutdownMode;
use arcbox_vm_driver::net::GuestNetwork;
use crate::config::RuntimeConfig;
use crate::error::{ComputerError, Result};
use crate::lifecycle::runtime::ComputerRuntime;
use crate::sandbox;
use crate::snapshot_cow::CowManager;
pub async fn release_runtime_resources(
id: &str,
arc: &Arc<Mutex<ComputerRuntime>>,
network: &Arc<dyn GuestNetwork>,
cow_manager: &Arc<CowManager>,
) -> Result<()> {
kill_computer_process(id, arc).await?;
{
let cow_handle = arc.lock().unwrap().cow_handle.take();
if let Some(handle) = cow_handle
&& let Err(error) = cow_manager.teardown_checked(&handle).await
{
arc.lock().unwrap().cow_handle = Some(handle);
return Err(error.into());
}
}
cow_manager.cleanup_setup_orphan(id).await?;
let lease = arc.lock().unwrap().network.take();
if let Some(lease) = lease
&& let Err(error) = network.quarantine(lease.clone()).await
{
arc.lock().unwrap().network = Some(lease);
return Err(error.into());
}
Ok(())
}
pub fn resource_owner(id: &str, arc: &Arc<Mutex<ComputerRuntime>>) -> String {
arc.lock()
.unwrap()
.pool_slot_id
.clone()
.unwrap_or_else(|| id.to_owned())
}
pub async fn kill_computer_process(id: &str, arc: &Arc<Mutex<ComputerRuntime>>) -> Result<()> {
let (prepared, handle) = {
let mut inst = arc.lock().unwrap();
let prepared = inst.prepared.take();
let handle = prepared.is_none().then(|| inst.handle.clone()).flatten();
(prepared, handle)
};
if let Some(prepared) = prepared {
if let Err(error) = prepared.discard().await {
arc.lock().unwrap().prepared = Some(prepared);
return Err(ComputerError::Process(format!(
"release the vmm of sandbox {id}: {error}"
)));
}
} else if let Some(handle) = handle
&& let Err(error) = handle.shutdown(ShutdownMode::Kill).await
{
return Err(ComputerError::Process(format!(
"release the adopted vmm of sandbox {id}: {error}"
)));
}
{
let mut inst = arc.lock().unwrap();
inst.handle = None;
inst.net_identity = None;
}
Ok(())
}
pub async fn release_everything(
id: &str,
arc: &Arc<Mutex<ComputerRuntime>>,
network: &Arc<dyn GuestNetwork>,
config: &Arc<RuntimeConfig>,
cow_manager: &Arc<CowManager>,
snapshots: &Arc<crate::snapshot::SnapshotCatalog>,
) -> Result<()> {
release_runtime_resources(id, arc, network, cow_manager).await?;
cow_manager.remove_preserved_cow(id).await?;
sandbox::pause::delete_pause_snapshots(snapshots, id)?;
let vm_dir = PathBuf::from(&config.firecracker.data_dir)
.join("sandboxes")
.join(id);
if let Err(e) = tokio::fs::remove_dir_all(&vm_dir).await
&& e.kind() != std::io::ErrorKind::NotFound
{
return Err(ComputerError::Io(e));
}
Ok(())
}