mirror of
https://github.com/containers/youki
synced 2024-05-24 16:36:07 +02:00
601df9ecd3
* Set cgroups path for tenant containers from main container Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com> * Ignore new_user_ns for creating cgroups path Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com> * Remove user_ns param completely Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com> * Add tests in podman rootless for exec Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com> * Fix add_task implementation for cgroups v2 and systemd Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com> * minor refactor in tenant builder Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com> * Add unit test for systemd add_task function Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com> * Fix task addition to properly add tasks via dbus api Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com> * Fix cross cotainers for tests running Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com> --------- Signed-off-by: Yashodhan Joshi <yjdoc2@gmail.com>
130 lines
3.6 KiB
Rust
130 lines
3.6 KiB
Rust
use crate::utils;
|
|
use oci_spec::runtime::{Hooks, Spec};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::{
|
|
fs,
|
|
io::{BufReader, BufWriter, Write},
|
|
path::{Path, PathBuf},
|
|
};
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
pub enum ConfigError {
|
|
#[error("failed to save config")]
|
|
SaveIO {
|
|
source: std::io::Error,
|
|
path: PathBuf,
|
|
},
|
|
#[error("failed to save config")]
|
|
SaveEncode {
|
|
source: serde_json::Error,
|
|
path: PathBuf,
|
|
},
|
|
#[error("failed to parse config")]
|
|
LoadIO {
|
|
source: std::io::Error,
|
|
path: PathBuf,
|
|
},
|
|
#[error("failed to parse config")]
|
|
LoadParse {
|
|
source: serde_json::Error,
|
|
path: PathBuf,
|
|
},
|
|
#[error("missing linux in spec")]
|
|
MissingLinux,
|
|
}
|
|
|
|
type Result<T> = std::result::Result<T, ConfigError>;
|
|
|
|
const YOUKI_CONFIG_NAME: &str = "youki_config.json";
|
|
|
|
/// A configuration for passing information obtained during container creation to other commands.
|
|
/// Keeping the information to a minimum improves performance.
|
|
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
|
#[non_exhaustive]
|
|
pub struct YoukiConfig {
|
|
pub hooks: Option<Hooks>,
|
|
pub cgroup_path: PathBuf,
|
|
}
|
|
|
|
impl<'a> YoukiConfig {
|
|
pub fn from_spec(spec: &'a Spec, container_id: &str) -> Result<Self> {
|
|
Ok(YoukiConfig {
|
|
hooks: spec.hooks().clone(),
|
|
cgroup_path: utils::get_cgroup_path(
|
|
spec.linux()
|
|
.as_ref()
|
|
.ok_or(ConfigError::MissingLinux)?
|
|
.cgroups_path(),
|
|
container_id,
|
|
),
|
|
})
|
|
}
|
|
|
|
pub fn save<P: AsRef<Path>>(&self, path: P) -> Result<()> {
|
|
let file = fs::File::create(path.as_ref().join(YOUKI_CONFIG_NAME)).map_err(|err| {
|
|
ConfigError::SaveIO {
|
|
source: err,
|
|
path: path.as_ref().to_owned(),
|
|
}
|
|
})?;
|
|
let mut writer = BufWriter::new(file);
|
|
serde_json::to_writer(&mut writer, self).map_err(|err| ConfigError::SaveEncode {
|
|
source: err,
|
|
path: path.as_ref().to_owned(),
|
|
})?;
|
|
writer.flush().map_err(|err| ConfigError::SaveIO {
|
|
source: err,
|
|
path: path.as_ref().to_owned(),
|
|
})?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn load<P: AsRef<Path>>(path: P) -> Result<Self> {
|
|
let path = path.as_ref();
|
|
let file =
|
|
fs::File::open(path.join(YOUKI_CONFIG_NAME)).map_err(|err| ConfigError::LoadIO {
|
|
source: err,
|
|
path: path.to_owned(),
|
|
})?;
|
|
let reader = BufReader::new(file);
|
|
let config = serde_json::from_reader(reader).map_err(|err| ConfigError::LoadParse {
|
|
source: err,
|
|
path: path.to_owned(),
|
|
})?;
|
|
Ok(config)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use anyhow::Result;
|
|
|
|
#[test]
|
|
fn test_config_from_spec() -> Result<()> {
|
|
let container_id = "sample";
|
|
let spec = Spec::default();
|
|
let config = YoukiConfig::from_spec(&spec, container_id)?;
|
|
assert_eq!(&config.hooks, spec.hooks());
|
|
dbg!(&config.cgroup_path);
|
|
assert_eq!(
|
|
config.cgroup_path,
|
|
PathBuf::from(format!(":youki:{container_id}"))
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_config_save_and_load() -> Result<()> {
|
|
let container_id = "sample";
|
|
let tmp = tempfile::tempdir().expect("create temp dir");
|
|
let spec = Spec::default();
|
|
let config = YoukiConfig::from_spec(&spec, container_id)?;
|
|
config.save(&tmp)?;
|
|
let act = YoukiConfig::load(&tmp)?;
|
|
assert_eq!(act, config);
|
|
Ok(())
|
|
}
|
|
}
|