Skip to content

Commit

Permalink
CONFLICT
Browse files Browse the repository at this point in the history
  • Loading branch information
YamasouA committed Dec 7, 2024
2 parents 73de531 + aa49a29 commit d3c3177
Show file tree
Hide file tree
Showing 40 changed files with 616 additions and 294 deletions.
145 changes: 72 additions & 73 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions crates/libcgroups/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,22 @@ cgroupsv2_devices = ["rbpf", "libbpf-sys", "errno", "libc", "nix/dir"]

[dependencies]
nix = { version = "0.28.0", features = ["signal", "user", "fs"] }
procfs = "0.16.0"
procfs = "0.17.0"
oci-spec = { version = "~0.7.1", features = ["runtime"] }
fixedbitset = "0.5.7"
serde = { version = "1.0", features = ["derive"] }
rbpf = { version = "0.3.0", optional = true }
libbpf-sys = { version = "1.5.0", optional = true }
errno = { version = "0.3.9", optional = true }
libc = { version = "0.2.162", optional = true }
thiserror = "2.0.3"
tracing = { version = "0.1.40", features = ["attributes"] }
errno = { version = "0.3.10", optional = true }
libc = { version = "0.2.167", optional = true }
thiserror = "2.0.4"
tracing = { version = "0.1.41", features = ["attributes"] }

[dev-dependencies]
anyhow = "1.0"
oci-spec = { version = "~0.7.1", features = ["proptests", "runtime"] }
quickcheck = "1"
mockall = { version = "0.13.0", features = [] }
mockall = { version = "0.13.1", features = [] }
clap = "4.1.6"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
Expand Down
8 changes: 4 additions & 4 deletions crates/libcontainer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ chrono = { version = "0.4", default-features = false, features = [
"serde",
] }
fastrand = "^2.1.1"
libc = "0.2.162"
libc = "0.2.167"
nix = { version = "0.28.0", features = [
"socket",
"sched",
Expand All @@ -39,16 +39,16 @@ nix = { version = "0.28.0", features = [
] }
oci-spec = { version = "0.7.1", features = ["runtime"] }
once_cell = "1.20.2"
procfs = "0.16.0"
procfs = "0.17.0"
prctl = "1.0.0"
libcgroups = { path = "../libcgroups", default-features = false, version = "0.4.1" } # MARK: Version
libseccomp = { version = "0.3.0", optional = true }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rust-criu = "0.4.0"
regex = { version = "1.10.6", default-features = false, features = ["std", "unicode-perl"] }
thiserror = "2.0.3"
tracing = { version = "0.1.40", features = ["attributes"] }
thiserror = "2.0.4"
tracing = { version = "0.1.41", features = ["attributes"] }
safe-path = "0.1.0"
nc = "0.9.5"

Expand Down
112 changes: 112 additions & 0 deletions crates/libcontainer/src/container/builder.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::os::fd::OwnedFd;
use std::path::PathBuf;

use super::init_builder::InitContainerBuilder;
Expand All @@ -24,6 +25,12 @@ pub struct ContainerBuilder {
/// The function that actually runs on the container init process. Default
/// is to execute the specified command in the oci spec.
pub(super) executor: Box<dyn Executor>,
// RawFd set to stdin of the container init process.
pub stdin: Option<OwnedFd>,
// RawFd set to stdout of the container init process.
pub stdout: Option<OwnedFd>,
// RawFd set to stderr of the container init process.
pub stderr: Option<OwnedFd>,
}

/// Builder that can be used to configure the common properties of
Expand Down Expand Up @@ -70,6 +77,9 @@ impl ContainerBuilder {
console_socket: None,
preserve_fds: 0,
executor: workload::default::get_executor(),
stdin: None,
stdout: None,
stderr: None,
}
}

Expand Down Expand Up @@ -257,13 +267,84 @@ impl ContainerBuilder {
self.executor = Box::new(executor);
self
}

/// Sets the stdin of the container, for those who use libcontainer as a library,
/// the container stdin may have to be set to an opened file descriptor
/// rather than the stdin of the current process.
/// # Example
///
/// ```no_run
/// # use libcontainer::container::builder::ContainerBuilder;
/// # use libcontainer::syscall::syscall::SyscallType;
/// # use libcontainer::workload::default::DefaultExecutor;
/// # use nix::unistd::pipe;
///
/// let (r, _w) = pipe().unwrap();
/// ContainerBuilder::new(
/// "74f1a4cb3801".to_owned(),
/// SyscallType::default(),
/// )
/// .with_stdin(r);
/// ```
pub fn with_stdin(mut self, stdin: impl Into<OwnedFd>) -> Self {
self.stdin = Some(stdin.into());
self
}

/// Sets the stdout of the container, for those who use libcontainer as a library,
/// the container stdout may have to be set to an opened file descriptor
/// rather than the stdout of the current process.
/// # Example
///
/// ```no_run
/// # use libcontainer::container::builder::ContainerBuilder;
/// # use libcontainer::syscall::syscall::SyscallType;
/// # use libcontainer::workload::default::DefaultExecutor;
/// # use nix::unistd::pipe;
///
/// let (_r, w) = pipe().unwrap();
/// ContainerBuilder::new(
/// "74f1a4cb3801".to_owned(),
/// SyscallType::default(),
/// )
/// .with_stdout(w);
/// ```
pub fn with_stdout(mut self, stdout: impl Into<OwnedFd>) -> Self {
self.stdout = Some(stdout.into());
self
}

/// Sets the stderr of the container, for those who use libcontainer as a library,
/// the container stderr may have to be set to an opened file descriptor
/// rather than the stderr of the current process.
/// # Example
///
/// ```no_run
/// # use libcontainer::container::builder::ContainerBuilder;
/// # use libcontainer::syscall::syscall::SyscallType;
/// # use libcontainer::workload::default::DefaultExecutor;
/// # use nix::unistd::pipe;
///
/// let (_r, w) = pipe().unwrap();
/// ContainerBuilder::new(
/// "74f1a4cb3801".to_owned(),
/// SyscallType::default(),
/// )
/// .with_stderr(w);
/// ```
pub fn with_stderr(mut self, stderr: impl Into<OwnedFd>) -> Self {
self.stderr = Some(stderr.into());
self
}
}

#[cfg(test)]
mod tests {
use std::os::fd::AsRawFd;
use std::path::PathBuf;

use anyhow::{Context, Result};
use nix::unistd::pipe;

use crate::container::builder::ContainerBuilder;
use crate::syscall::syscall::SyscallType;
Expand Down Expand Up @@ -334,4 +415,35 @@ mod tests {
assert!(result.is_ok());
Ok(())
}

#[test]
fn test_stdios() -> Result<()> {
let (r, _w) = pipe()?;
let stdin_raw = r.as_raw_fd();
let builder =
ContainerBuilder::new("74f1a4cb3801".to_owned(), SyscallType::default()).with_stdin(r);
assert_eq!(
builder.stdin.as_ref().map(|o| o.as_raw_fd()),
Some(stdin_raw)
);

let (_r, w) = pipe()?;
let stdout_raw = w.as_raw_fd();
let builder =
ContainerBuilder::new("74f1a4cb3801".to_owned(), SyscallType::default()).with_stdout(w);
assert_eq!(
builder.stdout.as_ref().map(|o| o.as_raw_fd()),
Some(stdout_raw)
);

let (_r, w) = pipe()?;
let stderr_raw = w.as_raw_fd();
let builder =
ContainerBuilder::new("74f1a4cb3801".to_owned(), SyscallType::default()).with_stderr(w);
assert_eq!(
builder.stderr.as_ref().map(|o| o.as_raw_fd()),
Some(stderr_raw)
);
Ok(())
}
}
31 changes: 23 additions & 8 deletions crates/libcontainer/src/container/builder_impl.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::fs;
use std::io::Write;
use std::os::unix::prelude::RawFd;
use std::os::fd::{AsRawFd, OwnedFd};
use std::path::PathBuf;
use std::rc::Rc;

Expand All @@ -9,7 +9,7 @@ use nix::unistd::Pid;
use oci_spec::runtime::Spec;

use super::{Container, ContainerStatus};
use crate::error::{LibcontainerError, MissingSpecError};
use crate::error::{CreateContainerError, LibcontainerError, MissingSpecError};
use crate::notify_socket::NotifyListener;
use crate::process::args::{ContainerArgs, ContainerType};
use crate::process::intel_rdt::delete_resctrl_subdirectory;
Expand All @@ -36,7 +36,7 @@ pub(super) struct ContainerBuilderImpl {
/// container process to the higher level runtime
pub pid_file: Option<PathBuf>,
/// Socket to communicate the file descriptor of the ptty
pub console_socket: Option<RawFd>,
pub console_socket: Option<OwnedFd>,
/// Options for new user namespace
pub user_ns_config: Option<UserNamespaceConfig>,
/// Path to the Unix Domain Socket to communicate container start
Expand All @@ -51,6 +51,12 @@ pub(super) struct ContainerBuilderImpl {
pub executor: Box<dyn Executor>,
/// If do not use pivot root to jail process inside rootfs
pub no_pivot: bool,
// RawFd set to stdin of the container init process.
pub stdin: Option<OwnedFd>,
// RawFd set to stdout of the container init process.
pub stdout: Option<OwnedFd>,
// RawFd set to stderr of the container init process.
pub stderr: Option<OwnedFd>,
}

impl ContainerBuilderImpl {
Expand All @@ -60,15 +66,21 @@ impl ContainerBuilderImpl {
Err(outer) => {
// Only the init container should be cleaned up in the case of
// an error.
if matches!(self.container_type, ContainerType::InitContainer) {
self.cleanup_container()?;
}
let cleanup_err = if self.is_init_container() {
self.cleanup_container().err()
} else {
None
};

Err(outer)
Err(CreateContainerError::new(outer, cleanup_err).into())
}
}
}

fn is_init_container(&self) -> bool {
matches!(self.container_type, ContainerType::InitContainer)
}

fn run_container(&mut self) -> Result<Pid, LibcontainerError> {
let linux = self.spec.linux().as_ref().ok_or(MissingSpecError::Linux)?;
let cgroups_path = utils::get_cgroup_path(linux.cgroups_path(), &self.container_id);
Expand Down Expand Up @@ -148,7 +160,7 @@ impl ContainerBuilderImpl {
syscall: self.syscall,
spec: Rc::clone(&self.spec),
rootfs: self.rootfs.to_owned(),
console_socket: self.console_socket,
console_socket: self.console_socket.as_ref().map(|c| c.as_raw_fd()),
notify_listener,
preserve_fds: self.preserve_fds,
container: self.container.to_owned(),
Expand All @@ -157,6 +169,9 @@ impl ContainerBuilderImpl {
detached: self.detached,
executor: self.executor.clone(),
no_pivot: self.no_pivot,
stdin: self.stdin.as_ref().map(|x| x.as_raw_fd()),
stdout: self.stdout.as_ref().map(|x| x.as_raw_fd()),
stderr: self.stderr.as_ref().map(|x| x.as_raw_fd()),
};

let (init_pid, need_to_clean_up_intel_rdt_dir) =
Expand Down
3 changes: 3 additions & 0 deletions crates/libcontainer/src/container/init_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ impl InitContainerBuilder {
detached: self.detached,
executor: self.base.executor,
no_pivot: self.no_pivot,
stdin: self.base.stdin,
stdout: self.base.stdout,
stderr: self.base.stderr,
};

builder_impl.create()?;
Expand Down
8 changes: 5 additions & 3 deletions crates/libcontainer/src/container/tenant_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ use std::convert::TryFrom;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::io::BufReader;
use std::os::fd::AsRawFd;
use std::os::unix::prelude::RawFd;
use std::os::fd::{AsRawFd, OwnedFd};
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::str::FromStr;
Expand Down Expand Up @@ -143,6 +142,9 @@ impl TenantContainerBuilder {
detached: self.detached,
executor: self.base.executor,
no_pivot: false,
stdin: self.base.stdin,
stdout: self.base.stdout,
stderr: self.base.stderr,
};

let pid = builder_impl.create()?;
Expand Down Expand Up @@ -500,7 +502,7 @@ impl TenantContainerBuilder {
Ok(socket_path)
}

fn setup_tty_socket(&self, container_dir: &Path) -> Result<Option<RawFd>, LibcontainerError> {
fn setup_tty_socket(&self, container_dir: &Path) -> Result<Option<OwnedFd>, LibcontainerError> {
let tty_name = Self::generate_name(container_dir, TENANT_TTY);
let csocketfd = if let Some(console_socket) = &self.base.console_socket {
Some(tty::setup_console_socket(
Expand Down
53 changes: 53 additions & 0 deletions crates/libcontainer/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ pub enum LibcontainerError {
CgroupGet(#[from] libcgroups::common::GetCgroupSetupError),
#[error[transparent]]
Checkpoint(#[from] crate::container::CheckpointError),
#[error[transparent]]
CreateContainerError(#[from] CreateContainerError),

// Catch all errors that are not covered by the above
#[error("syscall error")]
Expand Down Expand Up @@ -97,3 +99,54 @@ pub enum ErrInvalidSpec {
#[error("invalid scheduler config for process")]
Scheduler,
}

#[derive(Debug, thiserror::Error)]
pub struct CreateContainerError(Box<LibcontainerError>, Option<Box<LibcontainerError>>);

impl CreateContainerError {
pub(crate) fn new(
run_error: LibcontainerError,
cleanup_error: Option<LibcontainerError>,
) -> Self {
Self(Box::new(run_error), cleanup_error.map(Box::new))
}
}

impl std::fmt::Display for CreateContainerError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "failed to create container: {}", self.0)?;
if let Some(cleanup_err) = &self.1 {
write!(f, ". error during cleanup: {}", cleanup_err)?;
}
Ok(())
}
}

#[cfg(test)]
mod tests {
use libcgroups::common::CreateCgroupSetupError;

use super::{CreateContainerError, ErrInvalidID};

#[test]
fn test_create_container() {
let create_container_err =
CreateContainerError::new(CreateCgroupSetupError::NonDefault.into(), None);
let msg = format!("{}", create_container_err);
assert_eq!(
"failed to create container: non default cgroup root not supported",
msg
);

let create_container_err = CreateContainerError::new(
CreateCgroupSetupError::NonDefault.into(),
Some(ErrInvalidID::Empty.into()),
);
let msg = format!("{}", create_container_err);
assert_eq!(
"failed to create container: non default cgroup root not supported. \
error during cleanup: container id can't be empty",
msg
);
}
}
Loading

0 comments on commit d3c3177

Please sign in to comment.