Skip to content

Commit

Permalink
Add validate_linux_resource_memory test helper
Browse files Browse the repository at this point in the history
Signed-off-by: omprakaash <[email protected]>
Signed-off-by: om prakaash <[email protected]>
  • Loading branch information
omprakaash committed May 27, 2024
1 parent fe60f11 commit dc03b9d
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 11 deletions.
27 changes: 26 additions & 1 deletion crates/libcgroups/src/v1/util.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::{collections::HashMap, path::PathBuf};
use std::{
collections::HashMap,
fs, io,
path::{Path, PathBuf},
};

use procfs::{process::Process, ProcError};

Expand Down Expand Up @@ -79,3 +83,24 @@ pub fn get_subsystem_mount_point(subsystem: &ControllerType) -> Result<PathBuf,
subsystem: *subsystem,
})
}

pub fn get_subsystem_path(pid: i32, subsystem: &str) -> Result<PathBuf, io::Error> {
let contents = fs::read_to_string(Path::new(&format!("/proc/{}/cgroup", pid)))
.unwrap_or_else(|_| panic!("failed to read /proc/{}/cgroup", pid));
for line in contents.lines() {
let parts: Vec<&str> = line.splitn(3, ':').collect();
if parts.len() < 3 {
continue;
}
let subparts: Vec<&str> = parts[1].split(',').collect();
for subpart in subparts {
if subpart == subsystem {
return Ok(PathBuf::from(parts[2].to_string()));
}
}
}
Err(io::Error::new(
io::ErrorKind::Other,
format!("subsystem {} not found", subsystem),
))
}
13 changes: 8 additions & 5 deletions tests/contest/contest/src/tests/cgroups/memory.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::path::Path;

use crate::utils::{linux_resource_memory::validate_linux_resource_memory, test_outside_container};
use anyhow::{Context, Result};
use libcgroups::common::{get_cgroup_setup, CgroupSetup};
use oci_spec::runtime::{
LinuxBuilder, LinuxMemoryBuilder, LinuxResourcesBuilder, Spec, SpecBuilder,
};
use test_framework::{test_result, ConditionalTest, TestGroup, TestResult};

use crate::utils::{test_outside_container, test_utils::check_container_created};

const CGROUP_MEMORY_LIMIT: &str = "/sys/fs/cgroup/memory/memory.limit_in_bytes";
const CGROUP_MEMORY_SWAPPINESS: &str = "/sys/fs/cgroup/memory/memory.swappiness";

Expand Down Expand Up @@ -50,8 +50,8 @@ fn test_memory_cgroups() -> TestResult {
];

for spec in cases.into_iter() {
let test_result = test_outside_container(spec, &|data| {
test_result!(check_container_created(&data));
let test_result = test_outside_container(spec.clone(), &|data| {
test_result!(validate_linux_resource_memory(&spec, data));

TestResult::Passed
});
Expand All @@ -64,7 +64,10 @@ fn test_memory_cgroups() -> TestResult {
}

fn can_run() -> bool {
Path::new(CGROUP_MEMORY_LIMIT).exists() && Path::new(CGROUP_MEMORY_SWAPPINESS).exists()
let cgroup_setup = get_cgroup_setup();
matches!(cgroup_setup, Ok(CgroupSetup::Legacy))
&& Path::new(CGROUP_MEMORY_LIMIT).exists()
&& Path::new(CGROUP_MEMORY_SWAPPINESS).exists()
}

pub fn get_test_group() -> TestGroup {
Expand Down
11 changes: 6 additions & 5 deletions tests/contest/contest/src/tests/cgroups/relative_memory.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
use std::path::Path;

use crate::utils::{linux_resource_memory::validate_linux_resource_memory, test_outside_container};
use anyhow::{Context, Result};
use oci_spec::runtime::{
LinuxBuilder, LinuxMemoryBuilder, LinuxResourcesBuilder, Spec, SpecBuilder,
};
use test_framework::{test_result, ConditionalTest, TestGroup, TestResult};

use crate::utils::{test_outside_container, test_utils::check_container_created};

const CGROUP_MEMORY_LIMIT: &str = "/sys/fs/cgroup/memory/memory.limit_in_bytes";
const CGROUP_MEMORY_SWAPPINESS: &str = "/sys/fs/cgroup/memory/memory.swappiness";

const RELATIVE_CGROUPS_PATH: &str = "/testdir/runtime-test/container";

fn create_spec(cgroup_name: &str, limit: i64, swappiness: u64) -> Result<Spec> {
let spec = SpecBuilder::default()
.linux(
LinuxBuilder::default()
.cgroups_path(Path::new("/testdir/runtime-test/container").join(cgroup_name))
.cgroups_path(Path::new(RELATIVE_CGROUPS_PATH).join(cgroup_name))
.resources(
LinuxResourcesBuilder::default()
.memory(
Expand All @@ -42,8 +43,8 @@ fn test_relative_memory_cgroups() -> TestResult {

let spec = test_result!(create_spec(cgroup_name, 50593792, 10));

test_outside_container(spec, &|data| {
test_result!(check_container_created(&data));
test_outside_container(spec.clone(), &|data| {
test_result!(validate_linux_resource_memory(&spec, data));

TestResult::Passed
})
Expand Down
108 changes: 108 additions & 0 deletions tests/contest/contest/src/utils/linux_resource_memory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use super::ContainerData;
use anyhow::{bail, Result};
use libcgroups::v1::{
util::{get_subsystem_mount_point, get_subsystem_path},
ControllerType,
};
use oci_spec::runtime::{LinuxMemory, LinuxMemoryBuilder, Spec};

pub(crate) fn validate_linux_resource_memory(spec: &Spec, data: ContainerData) -> Result<()> {
let expected_memory = spec
.linux()
.as_ref()
.unwrap()
.resources()
.as_ref()
.unwrap()
.memory()
.as_ref();
let expected_memory = match expected_memory {
Some(m) => m,
None => bail!("expected memory to be set, but it was not"),
};

let memory = get_memory_data(data.state.unwrap().pid.unwrap());

if let Err(e) = memory {
bail!("failed to get memory data: {:?}", e);
}

let expected_limit = expected_memory.limit().unwrap();
let actual_limit = memory.as_ref().unwrap().limit().unwrap();
if expected_limit != actual_limit {
bail!("expected memory limit {expected_limit}, but got {actual_limit} instead");
}

let expected_swappiness = expected_memory.swappiness().unwrap();
let actual_swappiness = memory.as_ref().unwrap().swappiness().unwrap();
if expected_memory.swappiness().unwrap() != actual_swappiness {
bail!("expected memory swappiness {expected_swappiness}, got {actual_swappiness}");
}

Ok(())
}

fn get_memory_data(pid: i32) -> Result<LinuxMemory, Box<dyn std::error::Error>> {
let cgroup_mount_point = get_subsystem_mount_point(&ControllerType::Memory)?;
let mut cgroup_path = get_subsystem_path(pid, "memory")?;

// Removing the leading slash to convert the path to be relative to the cgroup mount point
if cgroup_path.is_absolute() {
cgroup_path = cgroup_path.strip_prefix("/")?.to_path_buf();
}

let mut memory_data = LinuxMemoryBuilder::default();
let cgroup_memory_files = vec![
"memory.limit_in_bytes",
"memory.soft_limit_in_bytes",
"memory.memsw.limit_in_bytes",
"memory.kmem.limit_in_bytes",
"memory.kmem.tcp.limit_in_bytes",
"memory.swappiness",
"memory.oom_control",
];

let path = cgroup_mount_point.join(&cgroup_path);
for file in cgroup_memory_files {
let file_path = path.join(file);
if file_path.exists() {
let value = std::fs::read_to_string(&file_path)?;
match file {
"memory.limit_in_bytes" => {
let limit = value.trim().parse::<i64>()?;
memory_data = memory_data.limit(limit);
}
"memory.soft_limit_in_bytes" => {
let reservation = value.trim().parse::<i64>()?;
memory_data = memory_data.reservation(reservation);
}
"memory.memsw.limit_in_bytes" => {
let swap = value.trim().parse::<i64>()?;
memory_data = memory_data.swap(swap);
}
"memory.kmem.limit_in_bytes" => {
let kernel = value.trim().parse::<i64>()?;
memory_data = memory_data.kernel(kernel);
}
"memory.kmem.tcp.limit_in_bytes" => {
let kernel_tcp = value.trim().parse::<i64>()?;
memory_data = memory_data.kernel_tcp(kernel_tcp);
}
"memory.swappiness" => {
let swappiness = value.trim().parse::<u64>()?;
memory_data = memory_data.swappiness(swappiness);
}
"memory.oom_control" => {
let oom_control = value.split_whitespace().collect::<Vec<&str>>();
let oom_control = oom_control
.get(1)
.ok_or("Failed to get oom_control")?
.parse::<u64>()?;
memory_data = memory_data.disable_oom_killer(oom_control == 1);
}
_ => unreachable!(),
};
}
}
Ok(memory_data.build()?)
}
1 change: 1 addition & 0 deletions tests/contest/contest/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod linux_resource_memory;
pub mod support;
pub mod test_utils;
pub use support::{
Expand Down

0 comments on commit dc03b9d

Please sign in to comment.