mirror of
https://github.com/containers/youki
synced 2024-11-22 17:02:00 +01:00
commit
0378410c24
@ -6,7 +6,8 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Context, Result};
|
|
||||||
|
use anyhow::{bail, Context, Result};
|
||||||
use nix::unistd::Pid;
|
use nix::unistd::Pid;
|
||||||
use oci_spec::LinuxResources;
|
use oci_spec::LinuxResources;
|
||||||
use procfs::process::Process;
|
use procfs::process::Process;
|
||||||
@ -67,13 +68,27 @@ pub fn write_cgroup_file<P: AsRef<Path>, T: ToString>(path: P, data: T) -> Resul
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_cgroupv1_mount_path(subsystem: &str) -> Result<PathBuf> {
|
pub fn get_supported_cgroup_fs() -> Result<Vec<Cgroup>> {
|
||||||
Process::myself()?
|
let cgroup_mount = Process::myself()?
|
||||||
.mountinfo()?
|
.mountinfo()?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.find(|m| m.fs_type == "cgroup" && m.mount_point.ends_with(subsystem))
|
.find(|m| m.fs_type == "cgroup");
|
||||||
.map(|m| m.mount_point)
|
|
||||||
.ok_or_else(|| anyhow!("could not find mountpoint for {}", subsystem))
|
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>> {
|
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 {
|
pub enum ControllerType {
|
||||||
Cpu,
|
Cpu,
|
||||||
@ -12,18 +12,32 @@ pub enum ControllerType {
|
|||||||
NetworkClassifier,
|
NetworkClassifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for ControllerType {
|
impl Display for ControllerType {
|
||||||
fn to_string(&self) -> String {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
let print = match *self {
|
||||||
Self::Cpu => "cpu".into(),
|
Self::Cpu => "cpu",
|
||||||
Self::CpuSet => "cpuset".into(),
|
Self::CpuSet => "cpuset",
|
||||||
Self::Devices => "devices".into(),
|
Self::Devices => "devices",
|
||||||
Self::HugeTlb => "hugetlb".into(),
|
Self::HugeTlb => "hugetlb",
|
||||||
Self::Pids => "pids".into(),
|
Self::Pids => "pids",
|
||||||
Self::Memory => "memory".into(),
|
Self::Memory => "memory",
|
||||||
Self::Blkio => "blkio".into(),
|
Self::Blkio => "blkio",
|
||||||
Self::NetworkPriority => "net_prio".into(),
|
Self::NetworkPriority => "net_prio",
|
||||||
Self::NetworkClassifier => "net_cls".into(),
|
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 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_CPUS: &str = "cpuset.cpus";
|
||||||
const CGROUP_CPUSET_MEMS: &str = "cpuset.mems";
|
const CGROUP_CPUSET_MEMS: &str = "cpuset.mems";
|
||||||
@ -34,11 +34,11 @@ impl CpuSet {
|
|||||||
fn apply(cgroup_path: &Path, cpuset: &LinuxCpu) -> Result<()> {
|
fn apply(cgroup_path: &Path, cpuset: &LinuxCpu) -> Result<()> {
|
||||||
if let Some(cpus) = &cpuset.cpus {
|
if let Some(cpus) = &cpuset.cpus {
|
||||||
common::write_cgroup_file_str(cgroup_path.join(CGROUP_CPUSET_CPUS), cpus)?;
|
common::write_cgroup_file_str(cgroup_path.join(CGROUP_CPUSET_CPUS), cpus)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mems) = &cpuset.mems {
|
if let Some(mems) = &cpuset.mems {
|
||||||
common::write_cgroup_file_str(cgroup_path.join(CGROUP_CPUSET_MEMS), mems)?;
|
common::write_cgroup_file_str(cgroup_path.join(CGROUP_CPUSET_MEMS), mems)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -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
|
// 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.
|
// 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<()> {
|
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)?;
|
let relative_cgroup_path = cgroup_path.strip_prefix(¤t)?;
|
||||||
|
|
||||||
for component in relative_cgroup_path.components() {
|
for component in relative_cgroup_path.components() {
|
||||||
|
@ -8,28 +8,15 @@ use nix::unistd::Pid;
|
|||||||
use procfs::process::Process;
|
use procfs::process::Process;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
blkio::Blkio, cpu::Cpu, cpuset::CpuSet, devices::Devices, hugetlb::Hugetlb, memory::Memory,
|
blkio::Blkio, controller_type::CONTROLLERS, cpu::Cpu, cpuset::CpuSet, devices::Devices,
|
||||||
network_classifier::NetworkClassifier, network_priority::NetworkPriority, pids::Pids,
|
hugetlb::Hugetlb, memory::Memory, network_classifier::NetworkClassifier,
|
||||||
Controller, ControllerType,
|
network_priority::NetworkPriority, pids::Pids, util, Controller,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::cgroups::common::CGROUP_PROCS;
|
use crate::cgroups::common::CGROUP_PROCS;
|
||||||
use crate::utils;
|
use crate::utils;
|
||||||
use crate::{cgroups::common::CgroupManager, utils::PathBufExt};
|
use crate::{cgroups::common::CgroupManager, utils::PathBufExt};
|
||||||
use oci_spec::LinuxResources;
|
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 {
|
pub struct Manager {
|
||||||
subsystems: HashMap<String, PathBuf>,
|
subsystems: HashMap<String, PathBuf>,
|
||||||
}
|
}
|
||||||
@ -49,32 +36,7 @@ impl Manager {
|
|||||||
|
|
||||||
fn get_subsystem_path(cgroup_path: &Path, subsystem: &str) -> anyhow::Result<PathBuf> {
|
fn get_subsystem_path(cgroup_path: &Path, subsystem: &str) -> anyhow::Result<PathBuf> {
|
||||||
log::debug!("Get path for subsystem: {}", subsystem);
|
log::debug!("Get path for subsystem: {}", subsystem);
|
||||||
let mount = Process::myself()?
|
let mount_point = util::get_subsystem_mount_points(subsystem)?;
|
||||||
.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 cgroup = Process::myself()?
|
let cgroup = Process::myself()?
|
||||||
.cgroups()?
|
.cgroups()?
|
||||||
@ -83,13 +45,11 @@ impl Manager {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let p = if cgroup_path.to_string_lossy().into_owned().is_empty() {
|
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() {
|
} else if cgroup_path.is_absolute() {
|
||||||
mount.mount_point.join_absolute_path(&cgroup_path)?
|
mount_point.join_absolute_path(&cgroup_path)?
|
||||||
} else {
|
} else {
|
||||||
mount.mount_point.join(cgroup_path)
|
mount_point.join(cgroup_path)
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(p)
|
Ok(p)
|
||||||
|
@ -10,6 +10,7 @@ mod memory;
|
|||||||
mod network_classifier;
|
mod network_classifier;
|
||||||
mod network_priority;
|
mod network_priority;
|
||||||
mod pids;
|
mod pids;
|
||||||
|
pub mod util;
|
||||||
pub use controller::Controller;
|
pub use controller::Controller;
|
||||||
pub use controller_type::ControllerType;
|
pub use controller_type::ControllerType;
|
||||||
pub use manager::Manager;
|
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;
|
pub mod manager;
|
||||||
mod memory;
|
mod memory;
|
||||||
mod pids;
|
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)
|
//! 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.
|
//! 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::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
@ -66,6 +67,8 @@ enum SubCommand {
|
|||||||
Delete(Delete),
|
Delete(Delete),
|
||||||
#[clap(version = "0.0.1", author = "utam0k <k0ma@utam0k.jp>")]
|
#[clap(version = "0.0.1", author = "utam0k <k0ma@utam0k.jp>")]
|
||||||
State(StateArgs),
|
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,
|
/// 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)?);
|
println!("{}", serde_json::to_string_pretty(&container.state)?);
|
||||||
std::process::exit(0);
|
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