1
0
mirror of https://github.com/containers/youki synced 2024-11-26 06:08:07 +01:00

Merge pull request #83 from Furisto/info-cmd

Add info command
This commit is contained in:
Furisto 2021-06-12 11:03:50 +02:00 committed by GitHub
commit 0378410c24
Signed by: GitHub
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 167 additions and 71 deletions

@ -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(&current)?;
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

@ -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

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

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