Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented hooks #187

Merged
merged 24 commits into from
Aug 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 25 additions & 17 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ systemd = { version = "0.8", default-features = false, optional = true }
dbus = "0.9.2"
tabwriter = "1"
fastrand = "1.4.1"
crossbeam-channel = "0.5"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we already do. If I understand how this crate works, there is crossbeam with feature ("crossbeam-channel/std" for example), or use crossbeam-channel directly. crossbeam with feature "crossbeam-channel/std" seems to point to crossbeam-channel underneath.

For context, to be honest, I only used crossbeam because std::sync::mpsc documentation here mentioned this unfixed issue where it mentioned crossbeam being a potential replacement for the std::sync::mpsc,


[dev-dependencies]
oci_spec = { version = "0.1.0", path = "./oci_spec", features = ["proptests"] }
Expand Down
45 changes: 35 additions & 10 deletions integration_test.sh
Original file line number Diff line number Diff line change
@@ -1,19 +1,44 @@
#!/bin/bash -eu

root=$(pwd)
ROOT=$(pwd)
RUNTIME=${ROOT}/youki
cd integration_test/src/github.com/opencontainers/runtime-tools
GOPATH=$root/integration_test make runtimetest validation-executables
test_cases=("default/default.t" "linux_cgroups_devices/linux_cgroups_devices.t" "linux_cgroups_hugetlb/linux_cgroups_hugetlb.t"
"linux_cgroups_pids/linux_cgroups_pids.t" "linux_cgroups_memory/linux_cgroups_memory.t" "linux_cgroups_network/linux_cgroups_network.t"
"linux_cgroups_cpus/linux_cgroups_cpus.t" "linux_cgroups_relative_cpus/linux_cgroups_relative_cpus.t"
"linux_cgroups_relative_devices/linux_cgroups_relative_devices.t" "linux_cgroups_relative_hugetlb/linux_cgroups_relative_hugetlb.t"
"linux_cgroups_relative_memory/linux_cgroups_relative_memory.t" "linux_cgroups_relative_network/linux_cgroups_relative_network.t"
"linux_cgroups_relative_pids/linux_cgroups_relative_pids.t" "create/create.t" "kill/kill.t" "delete/delete.t" "state/state.t" "linux_sysctl/linux_sysctl.t")
GOPATH=${ROOT}/integration_test make runtimetest validation-executables
test_cases=(
"default/default.t"
"linux_cgroups_devices/linux_cgroups_devices.t"
"linux_cgroups_hugetlb/linux_cgroups_hugetlb.t"
"linux_cgroups_pids/linux_cgroups_pids.t"
"linux_cgroups_memory/linux_cgroups_memory.t"
"linux_cgroups_network/linux_cgroups_network.t"
"linux_cgroups_cpus/linux_cgroups_cpus.t"
"linux_cgroups_relative_cpus/linux_cgroups_relative_cpus.t"
"linux_cgroups_relative_devices/linux_cgroups_relative_devices.t"
"linux_cgroups_relative_hugetlb/linux_cgroups_relative_hugetlb.t"
"linux_cgroups_relative_memory/linux_cgroups_relative_memory.t"
"linux_cgroups_relative_network/linux_cgroups_relative_network.t"
"linux_cgroups_relative_pids/linux_cgroups_relative_pids.t"
"create/create.t"
"kill/kill.t"
"delete/delete.t"
"state/state.t"
"linux_sysctl/linux_sysctl.t"
"hooks/hooks.t"
"prestart/prestart.t"
"poststart/poststart.t"
"prestart_fail/prestart_fail.t"
"poststart_fail/poststart_fail.t"
"poststop/poststop.t"
"hooks_stdin/hooks_stdin.t"
)

# Record the tests that runc also fails to pass below, maybe we will fix this by origin integration test, issue: https://github.com/containers/youki/issues/56
# no_paas_test_case=("start/start.t")
# no_paas_test_case=(
# "start/start.t"
# )
for case in "${test_cases[@]}"; do
echo "Running $case"
if [ 0 -ne $(sudo RUST_BACKTRACE=1 YOUKI_LOG_LEVEL=debug RUNTIME=$root/youki $root/integration_test/src/github.com/opencontainers/runtime-tools/validation/$case | grep "not ok" | wc -l) ]; then
if [ 0 -ne $(sudo RUST_BACKTRACE=1 YOUKI_LOG_LEVEL=debug RUNTIME=${RUNTIME} ${ROOT}/integration_test/src/github.com/opencontainers/runtime-tools/validation/$case | grep "not ok" | wc -l) ]; then
exit 1
fi
sleep 1
Expand Down
6 changes: 6 additions & 0 deletions src/commands/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use clap::Clap;
use nix::sys::signal::Signal;

use crate::container::{Container, ContainerStatus};
use crate::hooks;
use crate::utils;
use cgroups;
use nix::sys::signal as nix_signal;
Expand Down Expand Up @@ -61,6 +62,11 @@ impl Delete {
let cmanager =
cgroups::common::create_cgroup_manager(cgroups_path, systemd_cgroup)?;
cmanager.remove()?;

if let Some(hooks) = spec.hooks.as_ref() {
hooks::run_hooks(hooks.poststop.as_ref(), Some(&container))
.with_context(|| "Failed to run post stop hooks")?;
}
}
std::process::exit(0)
} else {
Expand Down
23 changes: 21 additions & 2 deletions src/commands/start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

use std::path::PathBuf;

use anyhow::{bail, Result};
use anyhow::{bail, Context, Result};
use clap::Clap;
use nix::unistd;

use crate::container::{Container, ContainerStatus};
use crate::hooks;
use crate::notify_socket::{NotifySocket, NOTIFY_FILE};

#[derive(Clap, Debug)]
Expand Down Expand Up @@ -35,12 +36,30 @@ impl Start {
bail!(err_msg);
}

let spec_path = container.root.join("config.json");
let spec = oci_spec::Spec::load(spec_path).context("failed to load spec")?;
if let Some(hooks) = spec.hooks.as_ref() {
// While prestart is marked as deprecated in the OCI spec, the docker and integration test still
// uses it.
#[allow(deprecated)]
hooks::run_hooks(hooks.prestart.as_ref(), Some(&container))
.with_context(|| "Failed to run pre start hooks")?;
}

unistd::chdir(container.root.as_os_str())?;

let mut notify_socket = NotifySocket::new(&container.root.join(NOTIFY_FILE));
notify_socket.notify_container_start()?;
let container = container.update_status(ContainerStatus::Running);
container.save()?;

// Run post start hooks. It runs after the container process is started.
// It is called in the Runtime Namespace.
if let Some(hooks) = spec.hooks.as_ref() {
hooks::run_hooks(hooks.poststart.as_ref(), Some(&container))
.with_context(|| "Failed to run post start hooks")?;
}

container.update_status(ContainerStatus::Running).save()?;
Ok(())
}
}
8 changes: 8 additions & 0 deletions src/container/builder_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use oci_spec::Spec;
use std::{fs, os::unix::prelude::RawFd, path::PathBuf};

use crate::{
hooks,
namespaces::Namespaces,
process::{child, fork, init, parent},
rootless::Rootless,
Expand Down Expand Up @@ -62,6 +63,12 @@ impl<'a> ContainerBuilderImpl<'a> {
let (mut parent, parent_channel) = parent::ParentProcess::new(&self.rootless)?;
let child = child::ChildProcess::new(parent_channel)?;

if self.init {
if let Some(hooks) = self.spec.hooks.as_ref() {
hooks::run_hooks(hooks.create_runtime.as_ref(), self.container.as_ref())?
}
}

// This init_args will be passed to the container init process,
// therefore we will have to move all the variable by value. Since self
// is a shared reference, we have to clone these variables here.
Expand All @@ -74,6 +81,7 @@ impl<'a> ContainerBuilderImpl<'a> {
is_rootless: self.rootless.is_some(),
notify_path: self.notify_path.clone(),
preserve_fds: self.preserve_fds,
container: self.container.clone(),
child,
};

Expand Down
17 changes: 16 additions & 1 deletion src/container/container.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::collections::HashMap;
use std::ffi::OsString;
use std::fs;
use std::path::{Path, PathBuf};
Expand All @@ -15,14 +16,23 @@ use crate::syscall::syscall::create_syscall;
use crate::container::{ContainerStatus, State};

/// Structure representing the container data
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Container {
// State of the container
pub state: State,
// indicated the directory for the root path in the container
pub root: PathBuf,
}

impl Default for Container {
fn default() -> Self {
Self {
state: State::default(),
root: PathBuf::from("/run/youki"),
}
}
}

impl Container {
pub fn new(
container_id: &str,
Expand Down Expand Up @@ -153,6 +163,11 @@ impl Container {
self
}

pub fn set_annotations(mut self, annotations: Option<HashMap<String, String>>) -> Self {
self.state.annotations = annotations;
self
}

pub fn systemd(&self) -> Option<bool> {
self.state.use_systemd
}
Expand Down
3 changes: 2 additions & 1 deletion src/container/init_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ impl InitContainerBuilder {

let container_state = self
.create_container_state(&container_dir)?
.set_systemd(self.use_systemd);
.set_systemd(self.use_systemd)
.set_annotations(spec.annotations.clone());

unistd::chdir(&*container_dir)?;
let notify_path = container_dir.join(NOTIFY_FILE);
Expand Down
12 changes: 9 additions & 3 deletions src/container/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ pub enum ContainerStatus {
// The container process has paused
Paused,
}
impl Default for ContainerStatus {
fn default() -> Self {
ContainerStatus::Creating
}
}

impl ContainerStatus {
pub fn can_start(&self) -> bool {
Expand Down Expand Up @@ -66,7 +71,7 @@ impl Display for ContainerStatus {
}

/// Stores the state information of the container
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
#[serde(rename_all = "camelCase")]
pub struct State {
// Version is the version of the specification that is supported.
Expand All @@ -81,7 +86,8 @@ pub struct State {
// Bundle is the path to the container's bundle directory.
pub bundle: String,
// Annotations are key values associated with the container.
pub annotations: HashMap<String, String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub annotations: Option<HashMap<String, String>>,
// Creation time of the container
#[serde(skip_serializing_if = "Option::is_none")]
pub created: Option<DateTime<Utc>>,
Expand All @@ -107,7 +113,7 @@ impl State {
status,
pid,
bundle: bundle.to_string(),
annotations: HashMap::default(),
annotations: Some(HashMap::default()),
created: None,
creator: None,
use_systemd: None,
Expand Down
Loading