mirror of
https://github.com/containers/youki
synced 2024-05-10 17:46:15 +02:00
107 lines
3.5 KiB
Rust
107 lines
3.5 KiB
Rust
use std::{collections::HashMap, path::PathBuf};
|
|
use std::{fs::remove_dir, path::Path};
|
|
|
|
use anyhow::Result;
|
|
use nix::unistd::Pid;
|
|
use procfs::process::Process;
|
|
|
|
use crate::{cgroups::ControllerType, spec::LinuxResources, utils::PathBufExt};
|
|
|
|
use super::{
|
|
blkio::Blkio, devices::Devices, hugetlb::Hugetlb, memory::Memory,
|
|
network_classifier::NetworkClassifier, network_priority::NetworkPriority, pids::Pids,
|
|
Controller,
|
|
};
|
|
|
|
const CONTROLLERS: &[ControllerType] = &[
|
|
ControllerType::Devices,
|
|
ControllerType::HugeTlb,
|
|
ControllerType::Memory,
|
|
ControllerType::Pids,
|
|
ControllerType::Blkio,
|
|
ControllerType::NetworkPriority,
|
|
ControllerType::NetworkClassifier,
|
|
];
|
|
|
|
pub struct Manager {
|
|
subsystems: HashMap<String, PathBuf>,
|
|
}
|
|
|
|
impl Manager {
|
|
pub fn new(cgroup_path: PathBuf) -> Result<Self> {
|
|
let mut subsystems = HashMap::<String, PathBuf>::new();
|
|
for subsystem in CONTROLLERS.iter().map(|c| c.to_string()) {
|
|
subsystems.insert(
|
|
subsystem.to_owned(),
|
|
Self::get_subsystem_path(&cgroup_path, &subsystem)?,
|
|
);
|
|
}
|
|
|
|
Ok(Manager { subsystems })
|
|
}
|
|
|
|
pub fn apply(&self, linux_resources: &LinuxResources, pid: Pid) -> Result<()> {
|
|
for subsys in &self.subsystems {
|
|
match subsys.0.as_str() {
|
|
"devices" => Devices::apply(linux_resources, &subsys.1, pid)?,
|
|
"hugetlb" => Hugetlb::apply(linux_resources, &subsys.1, pid)?,
|
|
"memory" => Memory::apply(linux_resources, &subsys.1, pid)?,
|
|
"pids" => Pids::apply(linux_resources, &subsys.1, pid)?,
|
|
"blkio" => Blkio::apply(linux_resources, &subsys.1, pid)?,
|
|
"net_prio" => NetworkPriority::apply(linux_resources, &subsys.1, pid)?,
|
|
"net_cls" => NetworkClassifier::apply(linux_resources, &subsys.1, pid)?,
|
|
_ => continue,
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn remove(&self) -> Result<()> {
|
|
for cgroup_path in &self.subsystems {
|
|
if cgroup_path.1.exists() {
|
|
log::debug!("remove cgroup {:?}", cgroup_path.1);
|
|
remove_dir(&cgroup_path.1)?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn get_subsystem_path(cgroup_path: &Path, subsystem: &str) -> anyhow::Result<PathBuf> {
|
|
log::debug!("Get path for subsystem: {}", subsystem);
|
|
let mount = Process::myself()?
|
|
.mountinfo()?
|
|
.into_iter()
|
|
.find(|m| {
|
|
if m.fs_type == "cgroup" {
|
|
// Some systems mount net_prio and net_cls in the same directory
|
|
// other systems mount them in their own diretories. This
|
|
// should handle both cases.
|
|
if subsystem == "net_cls" || subsystem == "net_prio" {
|
|
return m.mount_point.ends_with("net_cls,net_prio")
|
|
|| m.mount_point.ends_with("net_prio,net_cls");
|
|
}
|
|
}
|
|
m.mount_point.ends_with(subsystem)
|
|
})
|
|
.unwrap();
|
|
|
|
let cgroup = Process::myself()?
|
|
.cgroups()?
|
|
.into_iter()
|
|
.find(|c| c.controllers.contains(&subsystem.to_owned()))
|
|
.unwrap();
|
|
|
|
let p = if cgroup_path.to_string_lossy().into_owned().is_empty() {
|
|
mount
|
|
.mount_point
|
|
.join_absolute_path(Path::new(&cgroup.pathname))?
|
|
} else {
|
|
mount.mount_point.join_absolute_path(&cgroup_path)?
|
|
};
|
|
|
|
Ok(p)
|
|
}
|
|
}
|