Skip to content

Commit

Permalink
Add support for cgroups managed by systemd
Browse files Browse the repository at this point in the history
  • Loading branch information
nimrodshn committed May 29, 2021
1 parent 37243cd commit 60e81cc
Show file tree
Hide file tree
Showing 16 changed files with 152 additions and 130 deletions.
4 changes: 1 addition & 3 deletions src/capabilities.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use crate::{
command::Command,
};
use crate::command::Command;
use caps::*;

use anyhow::Result;
Expand Down
4 changes: 1 addition & 3 deletions src/cgroups/blkio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ use std::{
path::Path,
};

use crate::{
cgroups::Controller,
};
use crate::cgroups::Controller;
use oci_spec::{LinuxBlockIo, LinuxResources};

const CGROUP_BLKIO_THROTTLE_READ_BPS: &str = "blkio.throttle.read_bps_device";
Expand Down
107 changes: 107 additions & 0 deletions src/cgroups/cgroupsfs_manager.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use crate::cgroups::Manager;
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 super::{
blkio::Blkio, devices::Devices, hugetlb::Hugetlb, memory::Memory,
network_classifier::NetworkClassifier, network_priority::NetworkPriority, pids::Pids,
Controller,
};
use crate::{cgroups::ControllerType, utils::PathBufExt};
use oci_spec::LinuxResources;

const CONTROLLERS: &[ControllerType] = &[
ControllerType::Devices,
ControllerType::HugeTlb,
ControllerType::Memory,
ControllerType::Pids,
ControllerType::Blkio,
ControllerType::NetworkPriority,
ControllerType::NetworkClassifier,
];

pub struct CGroupsFSManager {
subsystems: HashMap<String, PathBuf>,
}

impl CGroupsFSManager {
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(CGroupsFSManager { subsystems })
}

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)
}
}

impl Manager for CGroupsFSManager {
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(())
}

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(())
}
}
5 changes: 1 addition & 4 deletions src/cgroups/devices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ use std::{
use anyhow::Result;
use nix::unistd::Pid;

use crate::{
cgroups::Controller,
rootfs::default_devices,
};
use crate::{cgroups::Controller, rootfs::default_devices};
use oci_spec::{LinuxDeviceCgroup, LinuxDeviceType, LinuxResources};

pub struct Devices {}
Expand Down
4 changes: 1 addition & 3 deletions src/cgroups/hugetlb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ use std::{
use anyhow::anyhow;
use regex::Regex;

use crate::{
cgroups::Controller,
};
use crate::cgroups::Controller;
use oci_spec::{LinuxHugepageLimit, LinuxResources};

pub struct Hugetlb {}
Expand Down
101 changes: 3 additions & 98 deletions src/cgroups/manager.rs
Original file line number Diff line number Diff line change
@@ -1,106 +1,11 @@
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, utils::PathBufExt};
use oci_spec::LinuxResources;
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)
}
pub trait Manager {
fn apply(&self, linux_resources: &LinuxResources, pid: Pid) -> Result<()>;
fn remove(&self) -> Result<()>;
}
4 changes: 1 addition & 3 deletions src/cgroups/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ use std::{
use anyhow::{Result, *};
use nix::{errno::Errno, unistd::Pid};

use crate::{
cgroups::Controller,
};
use crate::cgroups::Controller;
use oci_spec::{LinuxMemory, LinuxResources};

const CGROUP_MEMORY_SWAP_LIMIT: &str = "memory.memsw.limit_in_bytes";
Expand Down
6 changes: 5 additions & 1 deletion src/cgroups/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
mod blkio;
mod cgroupsfs_manager;
mod controller;
mod controller_type;
mod devices;
mod hugetlb;
mod blkio;
mod manager;
mod memory;
mod network_classifier;
mod network_priority;
mod pids;
mod systemd_manager;
pub use cgroupsfs_manager::CGroupsFSManager;
pub use controller::Controller;
pub use controller_type::ControllerType;
pub use manager::Manager;
pub use systemd_manager::SystemDCGroupManager;
4 changes: 1 addition & 3 deletions src/cgroups/network_classifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ use std::{
use anyhow::Result;
use nix::unistd::Pid;

use crate::{
cgroups::Controller,
};
use crate::cgroups::Controller;
use oci_spec::{LinuxNetwork, LinuxResources};

pub struct NetworkClassifier {}
Expand Down
4 changes: 1 addition & 3 deletions src/cgroups/pids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ use std::{

use anyhow::Result;

use crate::{
cgroups::Controller,
};
use crate::cgroups::Controller;
use oci_spec::{LinuxPids, LinuxResources};

pub struct Pids {}
Expand Down
16 changes: 16 additions & 0 deletions src/cgroups/systemd_manager.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use crate::cgroups::Manager;
use anyhow::Result;
use nix::unistd::Pid;
use oci_spec::LinuxResources;

pub struct SystemDCGroupManager;

impl Manager for SystemDCGroupManager {
fn apply(&self, linux_resources: &LinuxResources, pid: Pid) -> Result<()> {
Ok(())
}

fn remove(&self) -> Result<()> {
Ok(())
}
}
5 changes: 4 additions & 1 deletion src/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@ fn run_container<P: AsRef<Path>>(
let linux = spec.linux.as_ref().unwrap();
let namespaces: Namespaces = linux.namespaces.clone().into();

let cmanager = cgroups::Manager::new(linux.cgroups_path.clone())?;
let cmanager: Box<dyn cgroups::Manager> = match systemd_cgroup {
true => Box::new(cgroups::SystemDCGroupManager),
false => Box::new(cgroups::CGroupsFSManager::new(linux.cgroups_path.clone())?),
};

match fork::fork_first(
pid_file,
Expand Down
10 changes: 7 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ use anyhow::{bail, Result};
use clap::Clap;
use nix::sys::signal as nix_signal;

use youki::cgroups::{CGroupsFSManager, Manager, SystemDCGroupManager};
use youki::command::linux::LinuxCommand;
use youki::container::{Container, ContainerStatus};
use youki::create;
use youki::signal;
use youki::start;
use youki::{cgroups::Manager, command::linux::LinuxCommand};

/// High-level commandline option definition
/// This takes global options as well as individual commands as specified in [OCI runtime-spec](https://github.com/opencontainers/runtime-spec/blob/master/runtime.md)
Expand Down Expand Up @@ -146,8 +147,11 @@ fn main() -> Result<()> {
// 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 = Manager::new(spec.linux.unwrap().cgroups_path)?;

let cmanager: Box<dyn Manager> = match systemd_cgroup {
true => Box::new(SystemDCGroupManager),
false => Box::new(CGroupsFSManager::new(spec.linux.unwrap().cgroups_path)?),
};
cmanager.remove()?;
}
std::process::exit(0)
Expand Down
4 changes: 1 addition & 3 deletions src/namespaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ use nix::{
unistd::{self, Gid, Uid},
};

use crate::{
command::{linux::LinuxCommand, test::TestHelperCommand, Command},
};
use crate::command::{linux::LinuxCommand, test::TestHelperCommand, Command};
use oci_spec::{LinuxNamespace, LinuxNamespaceType};

pub struct Namespaces {
Expand Down
2 changes: 1 addition & 1 deletion src/process/fork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ use nix::unistd;
use crate::cgroups::Manager;
use crate::container::ContainerStatus;
use crate::process::{child, init, parent, Process};
use oci_spec;
use crate::utils;
use crate::{cond::Cond, container::Container};
use oci_spec;

pub fn fork_first<P: AsRef<Path>>(
pid_file: Option<P>,
Expand Down
Loading

0 comments on commit 60e81cc

Please sign in to comment.