mirror of
				https://github.com/kata-containers/kata-containers.git
				synced 2025-11-04 03:29:55 +00:00 
			
		
		
		
	agent: Run OCI poststart hooks after a container is launched
Run the OCI `poststart` hooks must be called after the user-specified process is executed but before the `start` operation returns in accordance with OCI runtime spec. Fixes: #4575 Signed-off-by: Manabu Sugimoto <Manabu.Sugimoto@sony.com>
This commit is contained in:
		@@ -222,7 +222,7 @@ pub trait BaseContainer {
 | 
				
			|||||||
    async fn start(&mut self, p: Process) -> Result<()>;
 | 
					    async fn start(&mut self, p: Process) -> Result<()>;
 | 
				
			||||||
    async fn run(&mut self, p: Process) -> Result<()>;
 | 
					    async fn run(&mut self, p: Process) -> Result<()>;
 | 
				
			||||||
    async fn destroy(&mut self) -> Result<()>;
 | 
					    async fn destroy(&mut self) -> Result<()>;
 | 
				
			||||||
    fn exec(&mut self) -> Result<()>;
 | 
					    async fn exec(&mut self) -> Result<()>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// LinuxContainer protected by Mutex
 | 
					// LinuxContainer protected by Mutex
 | 
				
			||||||
@@ -634,11 +634,6 @@ fn do_init_child(cwfd: RawFd) -> Result<()> {
 | 
				
			|||||||
        capabilities::drop_privileges(cfd_log, c)?;
 | 
					        capabilities::drop_privileges(cfd_log, c)?;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if init {
 | 
					 | 
				
			||||||
        // notify parent to run poststart hooks
 | 
					 | 
				
			||||||
        write_sync(cwfd, SYNC_SUCCESS, "")?;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let args = oci_process.args.to_vec();
 | 
					    let args = oci_process.args.to_vec();
 | 
				
			||||||
    let env = oci_process.env.to_vec();
 | 
					    let env = oci_process.env.to_vec();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1054,7 +1049,7 @@ impl BaseContainer for LinuxContainer {
 | 
				
			|||||||
        self.start(p).await?;
 | 
					        self.start(p).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if init {
 | 
					        if init {
 | 
				
			||||||
            self.exec()?;
 | 
					            self.exec().await?;
 | 
				
			||||||
            self.status.transition(ContainerState::Running);
 | 
					            self.status.transition(ContainerState::Running);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1102,7 +1097,7 @@ impl BaseContainer for LinuxContainer {
 | 
				
			|||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn exec(&mut self) -> Result<()> {
 | 
					    async fn exec(&mut self) -> Result<()> {
 | 
				
			||||||
        let fifo = format!("{}/{}", &self.root, EXEC_FIFO_FILENAME);
 | 
					        let fifo = format!("{}/{}", &self.root, EXEC_FIFO_FILENAME);
 | 
				
			||||||
        let fd = fcntl::open(fifo.as_str(), OFlag::O_WRONLY, Mode::from_bits_truncate(0))?;
 | 
					        let fd = fcntl::open(fifo.as_str(), OFlag::O_WRONLY, Mode::from_bits_truncate(0))?;
 | 
				
			||||||
        let data: &[u8] = &[0];
 | 
					        let data: &[u8] = &[0];
 | 
				
			||||||
@@ -1114,6 +1109,26 @@ impl BaseContainer for LinuxContainer {
 | 
				
			|||||||
            .as_secs();
 | 
					            .as_secs();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.status.transition(ContainerState::Running);
 | 
					        self.status.transition(ContainerState::Running);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let spec = self
 | 
				
			||||||
 | 
					            .config
 | 
				
			||||||
 | 
					            .spec
 | 
				
			||||||
 | 
					            .as_ref()
 | 
				
			||||||
 | 
					            .ok_or_else(|| anyhow!("OCI spec was not found"))?;
 | 
				
			||||||
 | 
					        let st = self.oci_state()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // run poststart hook
 | 
				
			||||||
 | 
					        if spec.hooks.is_some() {
 | 
				
			||||||
 | 
					            info!(self.logger, "poststart hook");
 | 
				
			||||||
 | 
					            let hooks = spec
 | 
				
			||||||
 | 
					                .hooks
 | 
				
			||||||
 | 
					                .as_ref()
 | 
				
			||||||
 | 
					                .ok_or_else(|| anyhow!("OCI hooks were not found"))?;
 | 
				
			||||||
 | 
					            for h in hooks.poststart.iter() {
 | 
				
			||||||
 | 
					                execute_hook(&self.logger, h, &st).await?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unistd::close(fd)?;
 | 
					        unistd::close(fd)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
@@ -1335,20 +1350,6 @@ async fn join_namespaces(
 | 
				
			|||||||
        // notify child run prestart hooks completed
 | 
					        // notify child run prestart hooks completed
 | 
				
			||||||
        info!(logger, "notify child run prestart hook completed!");
 | 
					        info!(logger, "notify child run prestart hook completed!");
 | 
				
			||||||
        write_async(pipe_w, SYNC_SUCCESS, "").await?;
 | 
					        write_async(pipe_w, SYNC_SUCCESS, "").await?;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        info!(logger, "notify child parent ready to run poststart hook!");
 | 
					 | 
				
			||||||
        // wait to run poststart hook
 | 
					 | 
				
			||||||
        read_async(pipe_r).await?;
 | 
					 | 
				
			||||||
        info!(logger, "get ready to run poststart hook!");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // run poststart hook
 | 
					 | 
				
			||||||
        if spec.hooks.is_some() {
 | 
					 | 
				
			||||||
            info!(logger, "poststart hook");
 | 
					 | 
				
			||||||
            let hooks = spec.hooks.as_ref().unwrap();
 | 
					 | 
				
			||||||
            for h in hooks.poststart.iter() {
 | 
					 | 
				
			||||||
                execute_hook(&logger, h, st).await?;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    info!(logger, "wait for child process ready to run exec");
 | 
					    info!(logger, "wait for child process ready to run exec");
 | 
				
			||||||
@@ -2090,9 +2091,10 @@ mod tests {
 | 
				
			|||||||
        assert!(ret.is_ok(), "Expecting Ok, Got {:?}", ret);
 | 
					        assert!(ret.is_ok(), "Expecting Ok, Got {:?}", ret);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[tokio::test]
 | 
				
			||||||
    fn test_linuxcontainer_exec() {
 | 
					    async fn test_linuxcontainer_exec() {
 | 
				
			||||||
        let ret = new_linux_container_and_then(|mut c: LinuxContainer| c.exec());
 | 
					        let (c, _dir) = new_linux_container();
 | 
				
			||||||
 | 
					        let ret = c.unwrap().exec().await;
 | 
				
			||||||
        assert!(ret.is_err(), "Expecting Err, Got {:?}", ret);
 | 
					        assert!(ret.is_err(), "Expecting Err, Got {:?}", ret);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -269,7 +269,7 @@ impl AgentService {
 | 
				
			|||||||
            .get_container(&cid)
 | 
					            .get_container(&cid)
 | 
				
			||||||
            .ok_or_else(|| anyhow!("Invalid container id"))?;
 | 
					            .ok_or_else(|| anyhow!("Invalid container id"))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ctr.exec()?;
 | 
					        ctr.exec().await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if sid == cid {
 | 
					        if sid == cid {
 | 
				
			||||||
            return Ok(());
 | 
					            return Ok(());
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user