1
0
Fork 0
mirror of https://github.com/containers/youki synced 2024-05-06 15:46:17 +02:00
youki/cgroups/src/v1/devices.rs
Takashi IIGUNI 97848f1ce6
Updated cgroups oci-spec-rs to 0.5.1 or later (#303)
* Updated cgroup oci-spec-rs to 0.5.1

Signed-off-by: Takashi IIGUNI <iiguni.tks@gmail.com>
2021-09-26 18:08:56 -07:00

179 lines
6.6 KiB
Rust

use std::path::Path;
use anyhow::Result;
use super::controller::Controller;
use crate::common::{self, default_allow_devices, default_devices, ControllerOpt};
use oci_spec::runtime::LinuxDeviceCgroup;
pub struct Devices {}
impl Controller for Devices {
type Resource = ();
fn apply(controller_opt: &ControllerOpt, cgroup_root: &Path) -> Result<()> {
log::debug!("Apply Devices cgroup config");
if let Some(devices) = controller_opt.resources.devices().as_ref() {
for d in devices {
Self::apply_device(d, cgroup_root)?;
}
}
for d in [
default_devices().iter().map(|d| d.into()).collect(),
default_allow_devices(),
]
.concat()
{
Self::apply_device(&d, cgroup_root)?;
}
Ok(())
}
// always needs to be called due to default devices
fn needs_to_handle<'a>(_controller_opt: &'a ControllerOpt) -> Option<&'a Self::Resource> {
Some(&())
}
}
impl Devices {
fn apply_device(device: &LinuxDeviceCgroup, cgroup_root: &Path) -> Result<()> {
let path = if device.allow() {
cgroup_root.join("devices.allow")
} else {
cgroup_root.join("devices.deny")
};
common::write_cgroup_file_str(path, &device.to_string())?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test::create_temp_dir;
use crate::test::set_fixture;
use oci_spec::runtime::{LinuxDeviceCgroupBuilder, LinuxDeviceType};
use std::fs::read_to_string;
#[test]
fn test_set_default_devices() {
let tmp =
create_temp_dir("test_set_default_devices").expect("create temp directory for test");
default_allow_devices().iter().for_each(|d| {
// NOTE: We reset the fixtures every iteration because files aren't appended
// so what happens in the tests is you get strange overwrites which can contain
// remaining bytes from the last iteration. Resetting the files more appropriately
// mocks the behavior of cgroup files.
set_fixture(&tmp, "devices.allow", "").expect("create allowed devices list");
set_fixture(&tmp, "devices.deny", "").expect("create denied devices list");
Devices::apply_device(d, &tmp).expect("Apply default device");
println!("Device: {}", d.to_string());
if d.allow() {
let allowed_content =
read_to_string(tmp.join("devices.allow")).expect("read to string");
assert_eq!(allowed_content, d.to_string());
} else {
let denied_content =
read_to_string(tmp.join("devices.deny")).expect("read to string");
assert_eq!(denied_content, d.to_string());
}
});
}
#[test]
fn test_set_mock_devices() {
let tmp = create_temp_dir("test_set_mock_devices").expect("create temp directory for test");
[
LinuxDeviceCgroupBuilder::default()
.allow(true)
.typ(LinuxDeviceType::C)
.major(10)
.access("rwm")
.build()
.unwrap(),
LinuxDeviceCgroupBuilder::default()
.allow(true)
.typ(LinuxDeviceType::A)
.minor(200)
.access("rwm")
.build()
.unwrap(),
LinuxDeviceCgroupBuilder::default()
.allow(false)
.typ(LinuxDeviceType::P)
.major(10)
.minor(200)
.access("m")
.build()
.unwrap(),
LinuxDeviceCgroupBuilder::default()
.allow(false)
.typ(LinuxDeviceType::U)
.access("rw")
.build()
.unwrap(),
]
.iter()
.for_each(|d| {
set_fixture(&tmp, "devices.allow", "").expect("create allowed devices list");
set_fixture(&tmp, "devices.deny", "").expect("create denied devices list");
Devices::apply_device(d, &tmp).expect("Apply default device");
println!("Device: {}", d.to_string());
if d.allow() {
let allowed_content =
read_to_string(tmp.join("devices.allow")).expect("read to string");
assert_eq!(allowed_content, d.to_string());
} else {
let denied_content =
read_to_string(tmp.join("devices.deny")).expect("read to string");
assert_eq!(denied_content, d.to_string());
}
});
}
quickcheck! {
fn property_test_apply_device(device: LinuxDeviceCgroup) -> bool {
let tmp = create_temp_dir("property_test_apply_device").expect("create temp directory for test");
set_fixture(&tmp, "devices.allow", "").expect("create allowed devices list");
set_fixture(&tmp, "devices.deny", "").expect("create denied devices list");
Devices::apply_device(&device, &tmp).expect("Apply default device");
if device.allow() {
let allowed_content =
read_to_string(tmp.join("devices.allow")).expect("read to string");
allowed_content == device.to_string()
} else {
let denied_content =
read_to_string(tmp.join("devices.deny")).expect("read to string");
denied_content == device.to_string()
}
}
fn property_test_apply_multiple_devices(devices: Vec<LinuxDeviceCgroup>) -> bool {
let tmp = create_temp_dir("property_test_apply_multiple_devices").expect("create temp directory for test");
devices.iter()
.map(|device| {
set_fixture(&tmp, "devices.allow", "").expect("create allowed devices list");
set_fixture(&tmp, "devices.deny", "").expect("create denied devices list");
Devices::apply_device(device, &tmp).expect("Apply default device");
if device.allow() {
let allowed_content =
read_to_string(tmp.join("devices.allow")).expect("read to string");
allowed_content == device.to_string()
} else {
let denied_content =
read_to_string(tmp.join("devices.deny")).expect("read to string");
denied_content == device.to_string()
}
})
.all(|is_ok| is_ok)
}
}
}