diff --git a/src/agent/rustjail/src/container.rs b/src/agent/rustjail/src/container.rs index 7cd00e1856..c7241ecea9 100644 --- a/src/agent/rustjail/src/container.rs +++ b/src/agent/rustjail/src/container.rs @@ -281,12 +281,58 @@ pub struct SyncPC { pub trait Container: BaseContainer { // fn checkpoint(&self, opts: &CriuOpts) -> Result<()>; // fn restore(&self, p: &Process, opts: &CriuOpts) -> Result<()>; - fn pause(&self) -> Result<()>; - fn resume(&self) -> Result<()>; + fn pause(&mut self) -> Result<()>; + fn resume(&mut self) -> Result<()>; // fn notify_oom(&self) -> Result<(Sender, Receiver)>; // fn notify_memory_pressure(&self, lvl: PressureLevel) -> Result<(Sender, Receiver)>; } +impl Container for LinuxContainer { + fn pause(&mut self) -> Result<()> { + let status = self.status(); + if status != Status::RUNNING && status != Status::CREATED { + return Err(ErrorKind::ErrorCode(format!( + "failed to pause container: current status is: {:?}", + status + )) + .into()); + } + + if self.cgroup_manager.is_some() { + self.cgroup_manager + .as_ref() + .unwrap() + .freeze(fscgroup::FROZEN)?; + + self.status.transition(Status::PAUSED); + return Ok(()); + } + Err(ErrorKind::ErrorCode(String::from("failed to get container's cgroup manager")).into()) + } + + fn resume(&mut self) -> Result<()> { + let status = self.status(); + if status != Status::PAUSED { + return Err(ErrorKind::ErrorCode(format!( + "container status is: {:?}, not paused", + status + )) + .into()); + } + + if self.cgroup_manager.is_some() { + self.cgroup_manager + .as_ref() + .unwrap() + .freeze(fscgroup::THAWED)?; + + self.status.transition(Status::RUNNING); + return Ok(()); + } + Err(ErrorKind::ErrorCode(String::from("failed to get container's cgroup manager")).into()) + } +} + pub fn init_child() { let cwfd = std::env::var(CWFD_FD).unwrap().parse::().unwrap(); let cfd_log = std::env::var(CLOG_FD).unwrap().parse::().unwrap(); diff --git a/src/agent/src/rpc.rs b/src/agent/src/rpc.rs index 6a8d96d668..126647ff82 100644 --- a/src/agent/src/rpc.rs +++ b/src/agent/src/rpc.rs @@ -18,7 +18,7 @@ use protocols::health::{ }; use protocols::types::Interface; use rustjail; -use rustjail::container::{BaseContainer, LinuxContainer}; +use rustjail::container::{BaseContainer, Container, LinuxContainer}; use rustjail::errors::*; use rustjail::process::Process; use rustjail::specconv::CreateOpts; @@ -754,6 +754,59 @@ impl protocols::agent_ttrpc::AgentService for agentService { Ok(resp) => Ok(resp), } } + + fn pause_container( + &self, + ctx: &ttrpc::TtrpcContext, + req: protocols::agent::PauseContainerRequest, + ) -> ttrpc::Result { + let cid = req.get_container_id(); + let s = Arc::clone(&self.sandbox); + let mut sandbox = s.lock().unwrap(); + if let Some(ctr) = sandbox.get_container(cid) { + match ctr.pause() { + Err(e) => { + return Err(ttrpc::Error::RpcStatus(ttrpc::get_status( + ttrpc::Code::INTERNAL, + e.to_string(), + ))) + } + Ok(_) => return Ok(Empty::new()), + } + }; + + Err(ttrpc::Error::RpcStatus(ttrpc::get_status( + ttrpc::Code::INVALID_ARGUMENT, + "invalid argument".to_string(), + ))) + } + + fn resume_container( + &self, + ctx: &ttrpc::TtrpcContext, + req: protocols::agent::ResumeContainerRequest, + ) -> ttrpc::Result { + let cid = req.get_container_id(); + let s = Arc::clone(&self.sandbox); + let mut sandbox = s.lock().unwrap(); + if let Some(ctr) = sandbox.get_container(cid) { + match ctr.resume() { + Err(e) => { + return Err(ttrpc::Error::RpcStatus(ttrpc::get_status( + ttrpc::Code::INTERNAL, + e.to_string(), + ))) + } + Ok(_) => return Ok(Empty::new()), + } + }; + + Err(ttrpc::Error::RpcStatus(ttrpc::get_status( + ttrpc::Code::INVALID_ARGUMENT, + "invalid argument: ".to_string(), + ))) + } + fn write_stdin( &self, _ctx: &ttrpc::TtrpcContext,