agent: support guest hooks

Scan guest hooks upon creating new sandbox and append
them to guest OCI spec before running containers.

Fixes: #485
Signed-off-by: Peng Tao <bergwolf@hyper.sh>
This commit is contained in:
Peng Tao 2020-08-24 19:15:01 +08:00
parent e7bfeb418a
commit 03a4d107ba
2 changed files with 80 additions and 1 deletions

View File

@ -129,6 +129,9 @@ impl agentService {
// Add the root partition to the device cgroup to prevent access
update_device_cgroup(&mut oci)?;
// Append guest hooks
append_guest_hooks(&s, &mut oci);
// write spec to bundle path, hooks might
// read ocispec
let olddir = setup_bundle(&cid, &mut oci)?;
@ -1084,6 +1087,15 @@ impl protocols::agent_ttrpc::AgentService for agentService {
s.hostname = req.hostname.clone();
s.running = true;
if !req.guest_hook_path.is_empty() {
if let Err(e) = s.add_hooks(&req.guest_hook_path) {
error!(
sl!(),
"add guest hook {} failed: {:?}", req.guest_hook_path, e
);
}
}
if req.sandbox_id.len() > 0 {
s.id = req.sandbox_id.clone();
}
@ -1523,6 +1535,18 @@ fn update_container_namespaces(
Ok(())
}
fn append_guest_hooks(s: &Sandbox, oci: &mut Spec) {
if s.hooks.is_none() {
return;
}
let guest_hooks = s.hooks.as_ref().unwrap();
let mut hooks = oci.hooks.take().unwrap_or_default();
hooks.prestart.append(&mut guest_hooks.prestart.clone());
hooks.poststart.append(&mut guest_hooks.poststart.clone());
hooks.poststop.append(&mut guest_hooks.poststop.clone());
oci.hooks = Some(hooks);
}
// Check is the container process installed the
// handler for specific signal.
fn is_signal_handled(pid: pid_t, signum: u32) -> bool {

View File

@ -11,7 +11,7 @@ use crate::namespace::NSTYPEPID;
use crate::network::Network;
use libc::pid_t;
use netlink::{RtnlHandle, NETLINK_ROUTE};
use oci::LinuxNamespace;
use oci::{Hook, Hooks};
use protocols::agent::OnlineCPUMemRequest;
use regex::Regex;
use rustjail::cgroups;
@ -22,6 +22,8 @@ use rustjail::process::Process;
use slog::Logger;
use std::collections::HashMap;
use std::fs;
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
use std::sync::mpsc::Sender;
#[derive(Debug)]
@ -42,6 +44,7 @@ pub struct Sandbox {
pub no_pivot_root: bool,
pub sender: Option<Sender<i32>>,
pub rtnl: Option<RtnlHandle>,
pub hooks: Option<Hooks>,
}
impl Sandbox {
@ -66,6 +69,7 @@ impl Sandbox {
no_pivot_root: fs_type.eq(TYPEROOTFS),
sender: None,
rtnl: Some(RtnlHandle::new(NETLINK_ROUTE, 0).unwrap()),
hooks: None,
})
}
@ -261,6 +265,57 @@ impl Sandbox {
Ok(())
}
pub fn add_hooks(&mut self, dir: &str) -> Result<()> {
let mut hooks = Hooks::default();
if let Ok(hook) = self.find_hooks(dir, "prestart") {
hooks.prestart = hook;
}
if let Ok(hook) = self.find_hooks(dir, "poststart") {
hooks.poststart = hook;
}
if let Ok(hook) = self.find_hooks(dir, "poststop") {
hooks.poststop = hook;
}
self.hooks = Some(hooks);
Ok(())
}
fn find_hooks(&self, hook_path: &str, hook_type: &str) -> Result<Vec<Hook>> {
let mut hooks = Vec::new();
for entry in fs::read_dir(Path::new(hook_path).join(hook_type))? {
let entry = entry?;
// Reject non-file, symlinks and non-executable files
if !entry.file_type()?.is_file()
|| entry.file_type()?.is_symlink()
|| entry.metadata()?.permissions().mode() & 0o777 & 0o111 == 0
{
continue;
}
let name = entry.file_name();
let hook = Hook {
path: Path::new(hook_path)
.join(hook_type)
.join(&name)
.to_str()
.unwrap()
.to_owned(),
args: vec![name.to_str().unwrap().to_owned(), hook_type.to_owned()],
..Default::default()
};
info!(
self.logger,
"found {} hook {:?} mode {:o}",
hook_type,
hook,
entry.metadata()?.permissions().mode()
);
hooks.push(hook);
}
Ok(hooks)
}
}
fn online_resources(logger: &Logger, path: &str, pattern: &str, num: i32) -> Result<i32> {