diff --git a/cloud-hypervisor/src/main.rs b/cloud-hypervisor/src/main.rs index 06ef1fe30..51b1f38fd 100644 --- a/cloud-hypervisor/src/main.rs +++ b/cloud-hypervisor/src/main.rs @@ -373,6 +373,12 @@ fn get_cli_options_sorted( .num_args(1..) .action(ArgAction::Append) .group("vm-config"), + Arg::new("no-shutdown") + .long("no-shutdown") + .help("Do not exit the VMM when the guest shuts down") + .num_args(0) + .action(ArgAction::SetTrue) + .group("vmm-config"), Arg::new("numa") .long("numa") .help(NumaConfig::SYNTAX) @@ -637,6 +643,7 @@ fn start_vmm( let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateExitEventFd)?; let landlock_enable = cmd_arguments.get_flag("landlock"); + let no_shutdown = cmd_arguments.get_flag("no-shutdown"); #[allow(unused_mut)] let mut event_monitor = cmd_arguments @@ -733,6 +740,7 @@ fn start_vmm( exit_evt.try_clone().unwrap(), &seccomp_action, hypervisor, + no_shutdown, landlock_enable, ) .map_err(Error::StartVmmThread)?; diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index eec56c5c1..5dfea07e7 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -162,6 +162,10 @@ pub enum Error { #[error("Error rebooting VM")] VmReboot(#[source] VmError), + /// Cannot shut the VM down + #[error("Error shutting down VM")] + VmShutdown(#[source] VmError), + /// Cannot create VMM thread #[error("Error spawning VMM thread")] VmmThreadSpawn(#[source] io::Error), @@ -449,6 +453,7 @@ pub fn start_vmm_thread( exit_event: EventFd, seccomp_action: &SeccompAction, hypervisor: Arc, + no_shutdown: bool, landlock_enable: bool, ) -> Result { #[cfg(feature = "guest_debug")] @@ -488,6 +493,7 @@ pub fn start_vmm_thread( vmm_seccomp_action, hypervisor, exit_event, + no_shutdown, )?; vmm.setup_signal_handler(landlock_enable)?; @@ -627,6 +633,7 @@ pub struct Vmm { original_termios_opt: Arc>>, console_resize_pipe: Option>, console_info: Option, + no_shutdown: bool, } /// Just a wrapper for the data that goes into @@ -781,6 +788,7 @@ impl Vmm { seccomp_action: SeccompAction, hypervisor: Arc, exit_evt: EventFd, + no_shutdown: bool, ) -> Result { let mut epoll = EpollContext::new().map_err(Error::Epoll)?; let reset_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?; @@ -833,6 +841,7 @@ impl Vmm { original_termios_opt: Arc::new(Mutex::new(None)), console_resize_pipe: None, console_info: None, + no_shutdown, }) } @@ -1688,9 +1697,12 @@ impl Vmm { EpollDispatch::GuestExit => { info!("VM guest exit event"); self.guest_exit_evt.read().map_err(Error::EventFdRead)?; - self.vmm_shutdown().map_err(Error::VmmShutdown)?; - - break 'outer; + if self.no_shutdown { + self.vm_shutdown().map_err(Error::VmShutdown)?; + } else { + self.vmm_shutdown().map_err(Error::VmmShutdown)?; + break 'outer; + } } EpollDispatch::ActivateVirtioDevices => { if let Some(ref vm) = self.vm { @@ -2630,6 +2642,7 @@ mod unit_tests { SeccompAction::Allow, hypervisor::new().unwrap(), EventFd::new(EFD_NONBLOCK).unwrap(), + false, ) .unwrap() }