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]>
  • Loading branch information
omprakaash committed Feb 25, 2024
1 parent fe60f11 commit 8332eb0
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 8 deletions.
93 changes: 92 additions & 1 deletion crates/libcgroups/src/v1/util.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
use std::{collections::HashMap, path::PathBuf};
use std::{
collections::HashMap,
fs, io,
path::{Path, PathBuf},
};

use oci_spec::runtime::{LinuxMemory, LinuxMemoryBuilder};
use procfs::{process::Process, ProcError};

use super::{controller_type::CONTROLLERS, ControllerType};
Expand Down Expand Up @@ -41,6 +46,71 @@ pub fn list_supported_mount_points() -> Result<HashMap<ControllerType, PathBuf>,
Ok(mount_paths)
}

pub 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);
}
_ => {}
};
}
}
Ok(memory_data.build()?)
}

pub fn get_subsystem_mount_point(subsystem: &ControllerType) -> Result<PathBuf, V1MountPointError> {
let subsystem_name = subsystem.to_string();
Process::myself()
Expand Down Expand Up @@ -79,3 +149,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),
))
}
7 changes: 4 additions & 3 deletions tests/contest/contest/src/tests/cgroups/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ use oci_spec::runtime::{
LinuxBuilder, LinuxMemoryBuilder, LinuxResourcesBuilder, Spec, SpecBuilder,
};
use test_framework::{test_result, ConditionalTest, TestGroup, TestResult};
use utils::linux_resouce_memory::validate_linux_resource_memory;

Check warning on line 8 in tests/contest/contest/src/tests/cgroups/memory.rs

View workflow job for this annotation

GitHub Actions / check (x86_64, musl)

"resouce" should be "resource".

Check failure on line 8 in tests/contest/contest/src/tests/cgroups/memory.rs

View workflow job for this annotation

GitHub Actions / check (x86_64, musl)

`resouce` should be `resource`

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

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 +51,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 Down
8 changes: 4 additions & 4 deletions tests/contest/contest/src/tests/cgroups/relative_memory.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::path::Path;

use crate::utils::linux_resouce_memory::validate_linux_resource_memory;

Check warning on line 3 in tests/contest/contest/src/tests/cgroups/relative_memory.rs

View workflow job for this annotation

GitHub Actions / check (x86_64, musl)

"resouce" should be "resource".

Check failure on line 3 in tests/contest/contest/src/tests/cgroups/relative_memory.rs

View workflow job for this annotation

GitHub Actions / check (x86_64, musl)

`resouce` should be `resource`
use crate::utils::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";

Expand Down Expand Up @@ -42,8 +42,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
36 changes: 36 additions & 0 deletions tests/contest/contest/src/utils/linux_resouce_memory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use super::ContainerData;

Check warning on line 1 in tests/contest/contest/src/utils/linux_resouce_memory.rs

View workflow job for this annotation

GitHub Actions / check (x86_64, musl)

"resouce" should be "resource".
use anyhow::{bail, Result};
use libcgroups::v1::util::get_memory_data;
use oci_spec::runtime::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 memory.is_err() {
bail!("failed to get memory data: {:?}", memory.err().unwrap());
}

if expected_memory.limit().unwrap() != memory.as_ref().unwrap().limit().unwrap() {
bail!("expected memory {:?}, got {:?}", expected_memory, memory);
}

if expected_memory.swappiness().unwrap() != memory.as_ref().unwrap().swappiness().unwrap() {
bail!("expected memory {:?}, got {:?}", expected_memory, memory);
}

Ok(())
}
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_resouce_memory;

Check warning on line 1 in tests/contest/contest/src/utils/mod.rs

View workflow job for this annotation

GitHub Actions / check (x86_64, musl)

"resouce" should be "resource".

Check failure on line 1 in tests/contest/contest/src/utils/mod.rs

View workflow job for this annotation

GitHub Actions / check (x86_64, musl)

`resouce` should be `resource`
pub mod support;
pub mod test_utils;
pub use support::{
Expand Down

0 comments on commit 8332eb0

Please sign in to comment.