mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 11:05:46 +00:00
vmm: Only build a new VM when booting it
In order to support further use cases where a VM configuration could be modified through the HTTP API, we only store the passed VM config when being asked to create a VM. The actual creation will happen when booting a new config for the first time. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
9a93f4f0a6
commit
7e0cb078ed
@ -52,6 +52,12 @@ pub enum ApiError {
|
|||||||
/// The VM could not boot.
|
/// The VM could not boot.
|
||||||
VmBoot(VmError),
|
VmBoot(VmError),
|
||||||
|
|
||||||
|
/// The VM is already created.
|
||||||
|
VmAlreadyCreated,
|
||||||
|
|
||||||
|
/// The VM config is missing.
|
||||||
|
VmMissingConfig,
|
||||||
|
|
||||||
/// The VM could not shutdown.
|
/// The VM could not shutdown.
|
||||||
VmShutdown(VmError),
|
VmShutdown(VmError),
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ extern crate serde_json;
|
|||||||
extern crate vmm_sys_util;
|
extern crate vmm_sys_util;
|
||||||
|
|
||||||
use crate::api::{ApiError, ApiRequest, ApiResponse, ApiResponsePayload};
|
use crate::api::{ApiError, ApiRequest, ApiResponse, ApiResponsePayload};
|
||||||
|
use crate::config::VmConfig;
|
||||||
use crate::vm::{Error as VmError, ExitBehaviour, Vm};
|
use crate::vm::{Error as VmError, ExitBehaviour, Vm};
|
||||||
use libc::EFD_NONBLOCK;
|
use libc::EFD_NONBLOCK;
|
||||||
use std::io;
|
use std::io;
|
||||||
@ -219,6 +220,7 @@ pub struct Vmm {
|
|||||||
reset_evt: EventFd,
|
reset_evt: EventFd,
|
||||||
api_evt: EventFd,
|
api_evt: EventFd,
|
||||||
vm: Option<Vm>,
|
vm: Option<Vm>,
|
||||||
|
vm_config: Option<Arc<VmConfig>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vmm {
|
impl Vmm {
|
||||||
@ -249,6 +251,7 @@ impl Vmm {
|
|||||||
reset_evt,
|
reset_evt,
|
||||||
api_evt,
|
api_evt,
|
||||||
vm: None,
|
vm: None,
|
||||||
|
vm_config: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,21 +343,57 @@ impl Vmm {
|
|||||||
|
|
||||||
match api_request {
|
match api_request {
|
||||||
ApiRequest::VmCreate(config, sender) => {
|
ApiRequest::VmCreate(config, sender) => {
|
||||||
let exit_evt =
|
// We only store the passed VM config.
|
||||||
self.exit_evt.try_clone().map_err(Error::EventFdClone)?;
|
// The VM will be created when being asked to boot it.
|
||||||
let reset_evt =
|
let response = if self.vm_config.is_none() {
|
||||||
self.reset_evt.try_clone().map_err(Error::EventFdClone)?;
|
self.vm_config = Some(config);
|
||||||
let response = match Vm::new(config, exit_evt, reset_evt) {
|
Ok(ApiResponsePayload::Empty)
|
||||||
Ok(vm) => {
|
} else {
|
||||||
self.vm = Some(vm);
|
Err(ApiError::VmAlreadyCreated)
|
||||||
Ok(ApiResponsePayload::Empty)
|
|
||||||
}
|
|
||||||
Err(e) => Err(ApiError::VmCreate(e)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
sender.send(response).map_err(Error::ApiResponseSend)?;
|
sender.send(response).map_err(Error::ApiResponseSend)?;
|
||||||
}
|
}
|
||||||
ApiRequest::VmBoot(sender) => {
|
ApiRequest::VmBoot(sender) => {
|
||||||
|
// If we don't have a config, we can not boot a VM.
|
||||||
|
if self.vm_config.is_none() {
|
||||||
|
sender
|
||||||
|
.send(Err(ApiError::VmMissingConfig))
|
||||||
|
.map_err(Error::ApiResponseSend)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new VM is we don't have one yet.
|
||||||
|
if self.vm.is_none() {
|
||||||
|
let exit_evt = self
|
||||||
|
.exit_evt
|
||||||
|
.try_clone()
|
||||||
|
.map_err(Error::EventFdClone)?;
|
||||||
|
let reset_evt = self
|
||||||
|
.reset_evt
|
||||||
|
.try_clone()
|
||||||
|
.map_err(Error::EventFdClone)?;
|
||||||
|
|
||||||
|
if let Some(ref vm_config) = self.vm_config {
|
||||||
|
match Vm::new(
|
||||||
|
Arc::clone(vm_config),
|
||||||
|
exit_evt,
|
||||||
|
reset_evt,
|
||||||
|
) {
|
||||||
|
Ok(vm) => {
|
||||||
|
self.vm = Some(vm);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
sender
|
||||||
|
.send(Err(ApiError::VmCreate(e)))
|
||||||
|
.map_err(Error::ApiResponseSend)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now let's boot it.
|
||||||
if let Some(ref mut vm) = self.vm {
|
if let Some(ref mut vm) = self.vm {
|
||||||
let response = match vm.boot() {
|
let response = match vm.boot() {
|
||||||
Ok(_) => Ok(ApiResponsePayload::Empty),
|
Ok(_) => Ok(ApiResponsePayload::Empty),
|
||||||
|
Loading…
Reference in New Issue
Block a user