1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
use std::fs;
use libcgroups::common::CgroupManager;
use libcgroups::{self};
use nix::sys::signal;
use super::{Container, ContainerStatus};
use crate::config::YoukiConfig;
use crate::error::LibcontainerError;
use crate::hooks;
use crate::process::intel_rdt::delete_resctrl_subdirectory;
impl Container {
/// Deletes the container
///
/// # Example
///
/// ```no_run
/// use libcontainer::container::builder::ContainerBuilder;
/// use libcontainer::syscall::syscall::SyscallType;
///
/// # fn main() -> anyhow::Result<()> {
/// let mut container = ContainerBuilder::new(
/// "74f1a4cb3801".to_owned(),
/// SyscallType::default(),
/// )
/// .as_init("/var/run/docker/bundle")
/// .build()?;
///
/// container.delete(true)?;
/// # Ok(())
/// # }
/// ```
pub fn delete(&mut self, force: bool) -> Result<(), LibcontainerError> {
self.refresh_status()?;
tracing::debug!("container status: {:?}", self.status());
// Check if container is allowed to be deleted based on container status.
match self.status() {
ContainerStatus::Stopped => {}
ContainerStatus::Created => {
// Here, we differ from the OCI spec, but matches the same
// behavior as `runc` and `crun`. The OCI spec does not allow
// deletion of status `created` without `force` flag. But both
// `runc` and `crun` allows deleting `created`. Therefore we
// decided to follow `runc` and `crun`.
self.do_kill(signal::Signal::SIGKILL, true)?;
self.set_status(ContainerStatus::Stopped).save()?;
}
ContainerStatus::Creating | ContainerStatus::Running | ContainerStatus::Paused => {
// Containers can't be deleted while in these status, unless
// force flag is set. In the force case, we need to clean up any
// processes associated with containers.
if force {
self.do_kill(signal::Signal::SIGKILL, true)?;
self.set_status(ContainerStatus::Stopped).save()?;
} else {
tracing::error!(
id = ?self.id(),
status = ?self.status(),
"delete requires the container state to be stopped or created",
);
return Err(LibcontainerError::IncorrectStatus);
}
}
}
// Once reached here, the container is verified that it can be deleted.
debug_assert!(self.status().can_delete());
if let Some(true) = &self.clean_up_intel_rdt_subdirectory() {
if let Err(err) = delete_resctrl_subdirectory(self.id()) {
tracing::warn!(
"failed to delete resctrl subdirectory due to: {err:?}, continue to delete"
);
}
}
if self.root.exists() {
match YoukiConfig::load(&self.root) {
Ok(config) => {
tracing::debug!("config: {:?}", config);
// remove the cgroup created for the container
// check https://man7.org/linux/man-pages/man7/cgroups.7.html
// creating and removing cgroups section for more information on cgroups
let cmanager = libcgroups::common::create_cgroup_manager(
libcgroups::common::CgroupConfig {
cgroup_path: config.cgroup_path.to_owned(),
systemd_cgroup: self.systemd(),
container_name: self.id().to_string(),
},
)?;
cmanager.remove().map_err(|err| {
tracing::error!(cgroup_path = ?config.cgroup_path, "failed to remove cgroup due to: {err:?}");
err
})?;
if let Some(hooks) = config.hooks.as_ref() {
hooks::run_hooks(hooks.poststop().as_ref(), Some(self), None).map_err(
|err| {
tracing::error!(err = ?err, "failed to run post stop hooks");
err
},
)?;
}
}
Err(err) => {
// There is a brief window where the container state is
// created, but the container config is not yet generated
// from the OCI spec. In this case, we assume as if we
// successfully deleted the config and moving on.
tracing::warn!(
"skipping loading youki config due to: {err:?}, continue to delete"
);
}
}
// remove the directory storing container state
tracing::debug!("remove dir {:?}", self.root);
fs::remove_dir_all(&self.root).map_err(|err| {
tracing::error!(?err, path = ?self.root, "failed to remove container dir");
LibcontainerError::OtherIO(err)
})?;
}
Ok(())
}
}