From cf8f8ce93a77ea84fb46fd1ec0cf571ce669a9a5 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Sun, 24 Nov 2019 18:39:06 +0100 Subject: [PATCH] vmm: api: Add a Snapshot command Signed-off-by: Samuel Ortiz Signed-off-by: Yi Sun --- vmm/src/api/mod.rs | 31 +++++++++++++++++++++++++++++++ vmm/src/lib.rs | 12 ++++++++++++ vmm/src/vm.rs | 6 ++++++ 3 files changed, 49 insertions(+) diff --git a/vmm/src/api/mod.rs b/vmm/src/api/mod.rs index 876491919..e176f309a 100644 --- a/vmm/src/api/mod.rs +++ b/vmm/src/api/mod.rs @@ -29,6 +29,7 @@ //! 5. The thread handles the response and forwards potential errors. extern crate micro_http; +extern crate vm_device; extern crate vmm_sys_util; pub use self::http::start_http_thread; @@ -94,6 +95,9 @@ pub enum ApiError { /// The VM could not reboot. VmReboot(VmError), + /// The VM could not be snapshotted. + VmSnapshot(VmError), + /// The VMM could not shutdown. VmmShutdown(VmError), @@ -145,6 +149,12 @@ pub struct VmRemoveDeviceData { pub id: String, } +#[derive(Clone, Deserialize, Serialize)] +pub struct VmSnapshotConfig { + /// The snapshot destination URL + pub destination_url: String, +} + pub enum ApiResponsePayload { /// No data is sent on the channel. Empty, @@ -222,6 +232,9 @@ pub enum ApiRequest { /// Add a network device to the VM. VmAddNet(Arc, Sender), + + /// Take a VM snapshot + VmSnapshot(Arc, Sender), } pub fn vm_create( @@ -310,6 +323,24 @@ pub fn vm_resume(api_evt: EventFd, api_sender: Sender) -> ApiResult< vm_action(api_evt, api_sender, VmAction::Resume) } +pub fn vm_snapshot( + api_evt: EventFd, + api_sender: Sender, + data: Arc, +) -> ApiResult<()> { + let (response_sender, response_receiver) = channel(); + + // Send the VM snapshot request. + api_sender + .send(ApiRequest::VmSnapshot(data, response_sender)) + .map_err(ApiError::RequestSend)?; + api_evt.write(1).map_err(ApiError::EventFdWrite)?; + + response_receiver.recv().map_err(ApiError::ResponseRecv)??; + + Ok(()) +} + pub fn vm_info(api_evt: EventFd, api_sender: Sender) -> ApiResult { let (response_sender, response_receiver) = channel(); diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index 272788d4f..4eb37b279 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -288,6 +288,10 @@ impl Vmm { } } + fn vm_snapshot(&mut self, _destination_url: &str) -> result::Result<(), VmError> { + Ok(()) + } + fn vm_shutdown(&mut self) -> result::Result<(), VmError> { if let Some(ref mut vm) = self.vm.take() { vm.shutdown() @@ -589,6 +593,14 @@ impl Vmm { sender.send(response).map_err(Error::ApiResponseSend)?; } + ApiRequest::VmSnapshot(snapshot_data, sender) => { + let response = self + .vm_snapshot(&snapshot_data.destination_url) + .map_err(ApiError::VmSnapshot) + .map(|_| ApiResponsePayload::Empty); + + sender.send(response).map_err(Error::ApiResponseSend)?; + } ApiRequest::VmmShutdown(sender) => { let response = self .vmm_shutdown() diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 23352cccf..125c70f88 100755 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -180,6 +180,12 @@ pub enum Error { /// Eventfd write error EventfdError(std::io::Error), + + /// Cannot snapshot VM + Snapshot(MigratableError), + + /// Cannot send VM snapshot + SnapshotSend(MigratableError), } pub type Result = result::Result;