mirror of
https://github.com/containers/youki
synced 2024-11-26 06:08:07 +01:00
commit
0378410c24
@ -6,7 +6,8 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use nix::unistd::Pid;
|
||||
use oci_spec::LinuxResources;
|
||||
use procfs::process::Process;
|
||||
@ -67,13 +68,27 @@ pub fn write_cgroup_file<P: AsRef<Path>, T: ToString>(path: P, data: T) -> Resul
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_cgroupv1_mount_path(subsystem: &str) -> Result<PathBuf> {
|
||||
Process::myself()?
|
||||
pub fn get_supported_cgroup_fs() -> Result<Vec<Cgroup>> {
|
||||
let cgroup_mount = Process::myself()?
|
||||
.mountinfo()?
|
||||
.into_iter()
|
||||
.find(|m| m.fs_type == "cgroup" && m.mount_point.ends_with(subsystem))
|
||||
.map(|m| m.mount_point)
|
||||
.ok_or_else(|| anyhow!("could not find mountpoint for {}", subsystem))
|
||||
.find(|m| m.fs_type == "cgroup");
|
||||
|
||||
let cgroup2_mount = Process::myself()?
|
||||
.mountinfo()?
|
||||
.into_iter()
|
||||
.find(|m| m.fs_type == "cgroup2");
|
||||
|
||||
let mut cgroups = vec![];
|
||||
if cgroup_mount.is_some() {
|
||||
cgroups.push(Cgroup::V1);
|
||||
}
|
||||
|
||||
if cgroup2_mount.is_some() {
|
||||
cgroups.push(Cgroup::V2);
|
||||
}
|
||||
|
||||
Ok(cgroups)
|
||||
}
|
||||
|
||||
pub fn create_cgroup_manager<P: Into<PathBuf>>(cgroup_path: P) -> Result<Box<dyn CgroupManager>> {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::string::ToString;
|
||||
use std::fmt::Display;
|
||||
|
||||
pub enum ControllerType {
|
||||
Cpu,
|
||||
@ -12,18 +12,32 @@ pub enum ControllerType {
|
||||
NetworkClassifier,
|
||||
}
|
||||
|
||||
impl ToString for ControllerType {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
Self::Cpu => "cpu".into(),
|
||||
Self::CpuSet => "cpuset".into(),
|
||||
Self::Devices => "devices".into(),
|
||||
Self::HugeTlb => "hugetlb".into(),
|
||||
Self::Pids => "pids".into(),
|
||||
Self::Memory => "memory".into(),
|
||||
Self::Blkio => "blkio".into(),
|
||||
Self::NetworkPriority => "net_prio".into(),
|
||||
Self::NetworkClassifier => "net_cls".into(),
|
||||
}
|
||||
impl Display for ControllerType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let print = match *self {
|
||||
Self::Cpu => "cpu",
|
||||
Self::CpuSet => "cpuset",
|
||||
Self::Devices => "devices",
|
||||
Self::HugeTlb => "hugetlb",
|
||||
Self::Pids => "pids",
|
||||
Self::Memory => "memory",
|
||||
Self::Blkio => "blkio",
|
||||
Self::NetworkPriority => "net_prio",
|
||||
Self::NetworkClassifier => "net_cls",
|
||||
};
|
||||
|
||||
write!(f, "{}", print)
|
||||
}
|
||||
}
|
||||
|
||||
pub const CONTROLLERS: &[ControllerType] = &[
|
||||
ControllerType::Cpu,
|
||||
ControllerType::CpuSet,
|
||||
ControllerType::Devices,
|
||||
ControllerType::HugeTlb,
|
||||
ControllerType::Memory,
|
||||
ControllerType::Pids,
|
||||
ControllerType::Blkio,
|
||||
ControllerType::NetworkPriority,
|
||||
ControllerType::NetworkClassifier,
|
||||
];
|
||||
|
@ -6,7 +6,7 @@ use oci_spec::{LinuxCpu, LinuxResources};
|
||||
|
||||
use crate::cgroups::common::{self, CGROUP_PROCS};
|
||||
|
||||
use super::{Controller, ControllerType};
|
||||
use super::{util, Controller, ControllerType};
|
||||
|
||||
const CGROUP_CPUSET_CPUS: &str = "cpuset.cpus";
|
||||
const CGROUP_CPUSET_MEMS: &str = "cpuset.mems";
|
||||
@ -46,7 +46,7 @@ impl CpuSet {
|
||||
// if a task is moved into the cgroup and a value has not been set for cpus and mems
|
||||
// Errno 28 (no space left on device) will be returned. Therefore we set the value from the parent if required.
|
||||
fn ensure_not_empty(cgroup_path: &Path, interface_file: &str) -> Result<()> {
|
||||
let mut current = common::get_cgroupv1_mount_path(&ControllerType::CpuSet.to_string())?;
|
||||
let mut current = util::get_subsystem_mount_points(&ControllerType::CpuSet.to_string())?;
|
||||
let relative_cgroup_path = cgroup_path.strip_prefix(¤t)?;
|
||||
|
||||
for component in relative_cgroup_path.components() {
|
||||
|
@ -8,28 +8,15 @@ use nix::unistd::Pid;
|
||||
use procfs::process::Process;
|
||||
|
||||
use super::{
|
||||
blkio::Blkio, cpu::Cpu, cpuset::CpuSet, devices::Devices, hugetlb::Hugetlb, memory::Memory,
|
||||
network_classifier::NetworkClassifier, network_priority::NetworkPriority, pids::Pids,
|
||||
Controller, ControllerType,
|
||||
blkio::Blkio, controller_type::CONTROLLERS, cpu::Cpu, cpuset::CpuSet, devices::Devices,
|
||||
hugetlb::Hugetlb, memory::Memory, network_classifier::NetworkClassifier,
|
||||
network_priority::NetworkPriority, pids::Pids, util, Controller,
|
||||
};
|
||||
|
||||
use crate::cgroups::common::CGROUP_PROCS;
|
||||
use crate::utils;
|
||||
use crate::{cgroups::common::CgroupManager, utils::PathBufExt};
|
||||
use oci_spec::LinuxResources;
|
||||
|
||||
const CONTROLLERS: &[ControllerType] = &[
|
||||
ControllerType::Cpu,
|
||||
ControllerType::CpuSet,
|
||||
ControllerType::Devices,
|
||||
ControllerType::HugeTlb,
|
||||
ControllerType::Memory,
|
||||
ControllerType::Pids,
|
||||
ControllerType::Blkio,
|
||||
ControllerType::NetworkPriority,
|
||||
ControllerType::NetworkClassifier,
|
||||
];
|
||||
|
||||
pub struct Manager {
|
||||
subsystems: HashMap<String, PathBuf>,
|
||||
}
|
||||
@ -49,32 +36,7 @@ impl Manager {
|
||||
|
||||
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" {
|
||||
return m.mount_point.ends_with("net_cls,net_prio")
|
||||
|| m.mount_point.ends_with("net_prio,net_cls")
|
||||
|| m.mount_point.ends_with("net_cls");
|
||||
} else if 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("net_prio");
|
||||
}
|
||||
|
||||
if subsystem == "cpu" {
|
||||
return m.mount_point.ends_with("cpu,cpuacct")
|
||||
|| m.mount_point.ends_with("cpu");
|
||||
}
|
||||
}
|
||||
m.mount_point.ends_with(subsystem)
|
||||
})
|
||||
.unwrap();
|
||||
let mount_point = util::get_subsystem_mount_points(subsystem)?;
|
||||
|
||||
let cgroup = Process::myself()?
|
||||
.cgroups()?
|
||||
@ -83,13 +45,11 @@ impl Manager {
|
||||
.unwrap();
|
||||
|
||||
let p = if cgroup_path.to_string_lossy().into_owned().is_empty() {
|
||||
mount
|
||||
.mount_point
|
||||
.join_absolute_path(Path::new(&cgroup.pathname))?
|
||||
mount_point.join_absolute_path(Path::new(&cgroup.pathname))?
|
||||
} else if cgroup_path.is_absolute() {
|
||||
mount.mount_point.join_absolute_path(&cgroup_path)?
|
||||
mount_point.join_absolute_path(&cgroup_path)?
|
||||
} else {
|
||||
mount.mount_point.join(cgroup_path)
|
||||
mount_point.join(cgroup_path)
|
||||
};
|
||||
|
||||
Ok(p)
|
||||
|
@ -10,6 +10,7 @@ mod memory;
|
||||
mod network_classifier;
|
||||
mod network_priority;
|
||||
mod pids;
|
||||
pub mod util;
|
||||
pub use controller::Controller;
|
||||
pub use controller_type::ControllerType;
|
||||
pub use manager::Manager;
|
||||
|
48
src/cgroups/v1/util.rs
Normal file
48
src/cgroups/v1/util.rs
Normal file
@ -0,0 +1,48 @@
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use procfs::process::Process;
|
||||
|
||||
use super::controller_type::CONTROLLERS;
|
||||
|
||||
pub fn list_subsystem_mount_points() -> Result<HashMap<String, PathBuf>> {
|
||||
let mut mount_paths = HashMap::with_capacity(CONTROLLERS.len());
|
||||
|
||||
for controller in CONTROLLERS {
|
||||
if let Ok(mount_point) = get_subsystem_mount_points(&controller.to_string()) {
|
||||
mount_paths.insert(controller.to_string(), mount_point);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(mount_paths)
|
||||
}
|
||||
|
||||
pub fn get_subsystem_mount_points(subsystem: &str) -> Result<PathBuf> {
|
||||
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" {
|
||||
return m.mount_point.ends_with("net_cls,net_prio")
|
||||
|| m.mount_point.ends_with("net_prio,net_cls")
|
||||
|| m.mount_point.ends_with("net_cls");
|
||||
} else if 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("net_prio");
|
||||
}
|
||||
|
||||
if subsystem == "cpu" {
|
||||
return m.mount_point.ends_with("cpu,cpuacct")
|
||||
|| m.mount_point.ends_with("cpu");
|
||||
}
|
||||
}
|
||||
m.mount_point.ends_with(&subsystem)
|
||||
})
|
||||
.map(|m| m.mount_point)
|
||||
.ok_or_else(|| anyhow!("could not find mountpoint for {}", subsystem))
|
||||
}
|
@ -7,3 +7,4 @@ mod io;
|
||||
pub mod manager;
|
||||
mod memory;
|
||||
mod pids;
|
||||
pub mod util;
|
||||
|
13
src/cgroups/v2/util.rs
Normal file
13
src/cgroups/v2/util.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use procfs::process::Process;
|
||||
|
||||
pub fn get_unified_mount_point() -> Result<PathBuf> {
|
||||
Process::myself()?
|
||||
.mountinfo()?
|
||||
.into_iter()
|
||||
.find(|m| m.fs_type == "cgroup2")
|
||||
.map(|m| m.mount_point)
|
||||
.ok_or_else(|| anyhow!("could not find mountpoint for unified"))
|
||||
}
|
44
src/main.rs
44
src/main.rs
@ -2,6 +2,7 @@
|
||||
//! Container Runtime written in Rust, inspired by [railcar](https://github.com/oracle/railcar)
|
||||
//! This crate provides a container runtime which can be used by a high-level container runtime to run containers.
|
||||
|
||||
use procfs;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
@ -66,6 +67,8 @@ enum SubCommand {
|
||||
Delete(Delete),
|
||||
#[clap(version = "0.0.1", author = "utam0k <k0ma@utam0k.jp>")]
|
||||
State(StateArgs),
|
||||
#[clap(version = "0.0.1", author = "utam0k <k0ma@utam0k.jp>")]
|
||||
Info,
|
||||
}
|
||||
|
||||
/// This is the entry point in the container runtime. The binary is run by a high-level container runtime,
|
||||
@ -162,5 +165,46 @@ fn main() -> Result<()> {
|
||||
println!("{}", serde_json::to_string_pretty(&container.state)?);
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
SubCommand::Info => {
|
||||
let uname = nix::sys::utsname::uname();
|
||||
println!("{:<18}{}", "Kernel-Release", uname.release());
|
||||
println!("{:<18}{}", "Kernel-Version", uname.version());
|
||||
println!("{:<18}{}", "Architecture", uname.machine());
|
||||
|
||||
let cpu_info = procfs::CpuInfo::new()?;
|
||||
println!("{:<18}{}", "Cores", cpu_info.num_cores());
|
||||
let mem_info = procfs::Meminfo::new()?;
|
||||
println!(
|
||||
"{:<18}{}",
|
||||
"Total Memory",
|
||||
mem_info.mem_total / u64::pow(1024, 2)
|
||||
);
|
||||
|
||||
let cgroup_fs: Vec<String> = cgroups::common::get_supported_cgroup_fs()?
|
||||
.into_iter()
|
||||
.map(|c| c.to_string())
|
||||
.collect();
|
||||
println!("{:<18}{}", "cgroup version", cgroup_fs.join(" and "));
|
||||
|
||||
println!("cgroup mounts");
|
||||
let mut cgroup_v1_mounts: Vec<String> =
|
||||
cgroups::v1::util::list_subsystem_mount_points()?
|
||||
.iter()
|
||||
.map(|kv| format!(" {:<16}{:?}", kv.0, kv.1))
|
||||
.collect();
|
||||
|
||||
cgroup_v1_mounts.sort();
|
||||
for cgroup_mount in cgroup_v1_mounts {
|
||||
println!("{}", cgroup_mount);
|
||||
}
|
||||
|
||||
let unified = cgroups::v2::util::get_unified_mount_point();
|
||||
if let Ok(mount_point) = unified {
|
||||
println!(" {:<16}{:?}", "unified", mount_point);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user