this PR will port the original PR to kata 2.0.

Signed-off-by: bin liu <bin@hyper.sh>
This commit is contained in:
bin liu 2020-05-26 09:49:25 +00:00
parent 83f116b483
commit 9b9f2b2ff0
3 changed files with 1142 additions and 877 deletions

View File

@ -271,6 +271,14 @@ message TtyWinResizeRequest {
uint32 column = 4;
}
message KernelModule {
// This field is the name of the kernel module.
string name = 1;
// This field are the parameters for the kernel module which are
// whitespace-delimited key=value pairs passed to modprobe(8).
repeated string parameters = 2;
}
message CreateSandboxRequest {
string hostname = 1;
repeated string dns = 2;
@ -288,6 +296,8 @@ message CreateSandboxRequest {
// This field, if non-empty, designates an absolute path to a directory
// that the agent will search for OCI hooks to run within the guest.
string guest_hook_path = 6;
// This field is the list of kernel modules to be loaded in the guest kernel.
repeated KernelModule kernel_modules = 7;
}
message DestroySandboxRequest {

File diff suppressed because it is too large Load Diff

View File

@ -57,6 +57,7 @@ use std::os::unix::fs::FileExt;
use std::path::PathBuf;
const CONTAINER_BASE: &str = "/run/kata-containers";
const MODPROBE_PATH: &str = "/sbin/modprobe";
// Convenience macro to obtain the scope logger
macro_rules! sl {
@ -871,6 +872,7 @@ impl protocols::agent_ttrpc::AgentService for agentService {
Ok(Empty::new())
}
fn update_interface(
&self,
_ctx: &ttrpc::TtrpcContext,
@ -1024,6 +1026,18 @@ impl protocols::agent_ttrpc::AgentService for agentService {
s.id = req.sandbox_id.clone();
}
for m in req.kernel_modules.iter() {
match load_kernel_module(m) {
Ok(_) => (),
Err(e) => {
return Err(ttrpc::Error::RpcStatus(ttrpc::get_status(
ttrpc::Code::INTERNAL,
e.to_string(),
)))
}
}
}
match s.setup_shared_namespaces() {
Ok(_) => (),
Err(e) => {
@ -1546,3 +1560,71 @@ fn setup_bundle(spec: &Spec) -> Result<PathBuf> {
Ok(olddir)
}
fn load_kernel_module(module: &protocols::agent::KernelModule) -> Result<()> {
if module.name == "" {
return Err(ErrorKind::ErrorCode("Kernel module name is empty".to_string()).into());
}
info!(
sl!(),
"load_kernel_module {}: {:?}", module.name, module.parameters
);
let mut args = vec!["-v".to_string(), module.name.clone()];
if module.parameters.len() > 0 {
args.extend(module.parameters.to_vec())
}
let output = Command::new(MODPROBE_PATH)
.args(args.as_slice())
.stdout(Stdio::piped())
.output()?;
let status = output.status;
if status.success() {
return Ok(());
}
match status.code() {
Some(code) => {
let std_out: String = String::from_utf8(output.stdout).unwrap();
let std_err: String = String::from_utf8(output.stderr).unwrap();
let msg = format!(
"load_kernel_module return code: {} stdout:{} stderr:{}",
code, std_out, std_err
);
return Err(ErrorKind::ErrorCode(msg).into());
}
None => {
return Err(ErrorKind::ErrorCode("Process terminated by signal".to_string()).into())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_load_kernel_module() {
let mut m = protocols::agent::KernelModule::default();
// case 1: module not exists
m.name = "module_not_exists".to_string();
let result = load_kernel_module(&m);
assert!(result.is_err(), "load module should failed");
// case 2: module name is empty
m.name = "".to_string();
let result = load_kernel_module(&m);
assert!(result.is_err(), "load module should failed");
// case 3: normal module.
// normally this module should eixsts...
m.name = "bridge".to_string();
let result = load_kernel_module(&m);
assert!(result.is_ok(), "load module should success");
}
}