diff --git a/vmm/src/api/http.rs b/vmm/src/api/http.rs index e6a0e73a3..f05c691c7 100644 --- a/vmm/src/api/http.rs +++ b/vmm/src/api/http.rs @@ -3,10 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 // -use crate::api::http_endpoint::{ - VmActionHandler, VmAddDevice, VmAddDisk, VmAddFs, VmAddNet, VmAddPmem, VmAddVsock, VmCreate, - VmInfo, VmRemoveDevice, VmResize, VmRestore, VmSnapshot, VmmPing, VmmShutdown, -}; +use crate::api::http_endpoint::{VmActionHandler, VmCreate, VmInfo, VmmPing, VmmShutdown}; use crate::api::{ApiError, ApiRequest, VmAction}; use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::{Error, Result}; @@ -16,6 +13,7 @@ use serde_json::Error as SerdeError; use std::collections::HashMap; use std::path::PathBuf; use std::sync::mpsc::Sender; +use std::sync::Arc; use std::thread; use vmm_sys_util::eventfd::EventFd; @@ -170,18 +168,18 @@ lazy_static! { r.routes.insert(endpoint!("/vm.resume"), Box::new(VmActionHandler::new(VmAction::Resume))); r.routes.insert(endpoint!("/vm.shutdown"), Box::new(VmActionHandler::new(VmAction::Shutdown))); r.routes.insert(endpoint!("/vm.reboot"), Box::new(VmActionHandler::new(VmAction::Reboot))); - r.routes.insert(endpoint!("/vm.snapshot"), Box::new(VmSnapshot {})); - r.routes.insert(endpoint!("/vm.restore"), Box::new(VmRestore {})); + r.routes.insert(endpoint!("/vm.snapshot"), Box::new(VmActionHandler::new(VmAction::Snapshot(Arc::default())))); + r.routes.insert(endpoint!("/vm.restore"), Box::new(VmActionHandler::new(VmAction::Restore(Arc::default())))); r.routes.insert(endpoint!("/vmm.shutdown"), Box::new(VmmShutdown {})); r.routes.insert(endpoint!("/vmm.ping"), Box::new(VmmPing {})); - r.routes.insert(endpoint!("/vm.resize"), Box::new(VmResize {})); - r.routes.insert(endpoint!("/vm.add-device"), Box::new(VmAddDevice {})); - r.routes.insert(endpoint!("/vm.remove-device"), Box::new(VmRemoveDevice {})); - r.routes.insert(endpoint!("/vm.add-disk"), Box::new(VmAddDisk {})); - r.routes.insert(endpoint!("/vm.add-fs"), Box::new(VmAddFs {})); - r.routes.insert(endpoint!("/vm.add-pmem"), Box::new(VmAddPmem {})); - r.routes.insert(endpoint!("/vm.add-net"), Box::new(VmAddNet {})); - r.routes.insert(endpoint!("/vm.add-vsock"), Box::new(VmAddVsock {})); + r.routes.insert(endpoint!("/vm.resize"), Box::new(VmActionHandler::new(VmAction::Resize(Arc::default())))); + r.routes.insert(endpoint!("/vm.add-device"), Box::new(VmActionHandler::new(VmAction::AddDevice(Arc::default())))); + r.routes.insert(endpoint!("/vm.remove-device"), Box::new(VmActionHandler::new(VmAction::RemoveDevice(Arc::default())))); + r.routes.insert(endpoint!("/vm.add-disk"), Box::new(VmActionHandler::new(VmAction::AddDisk(Arc::default())))); + r.routes.insert(endpoint!("/vm.add-fs"), Box::new(VmActionHandler::new(VmAction::AddFs(Arc::default())))); + r.routes.insert(endpoint!("/vm.add-pmem"), Box::new(VmActionHandler::new(VmAction::AddPmem(Arc::default())))); + r.routes.insert(endpoint!("/vm.add-net"), Box::new(VmActionHandler::new(VmAction::AddNet(Arc::default())))); + r.routes.insert(endpoint!("/vm.add-vsock"), Box::new(VmActionHandler::new(VmAction::AddVsock(Arc::default())))); r }; diff --git a/vmm/src/api/http_endpoint.rs b/vmm/src/api/http_endpoint.rs index 1442f8ca2..7cd075695 100644 --- a/vmm/src/api/http_endpoint.rs +++ b/vmm/src/api/http_endpoint.rs @@ -7,9 +7,7 @@ use crate::api::http::{error_response, EndpointHandler, HttpError}; use crate::api::{ vm_add_device, vm_add_disk, vm_add_fs, vm_add_net, vm_add_pmem, vm_add_vsock, vm_boot, vm_create, vm_delete, vm_info, vm_pause, vm_reboot, vm_remove_device, vm_resize, vm_restore, - vm_resume, vm_shutdown, vm_snapshot, vmm_ping, vmm_shutdown, ApiRequest, DeviceConfig, - DiskConfig, FsConfig, NetConfig, PmemConfig, RestoreConfig, VmAction, VmConfig, - VmRemoveDeviceData, VmResizeData, VmSnapshotConfig, VsockConfig, + vm_resume, vm_shutdown, vm_snapshot, vmm_ping, vmm_shutdown, ApiRequest, VmAction, VmConfig, }; use micro_http::{Body, Method, Request, Response, StatusCode, Version}; use std::sync::mpsc::Sender; @@ -68,31 +66,97 @@ impl VmActionHandler { } impl EndpointHandler for VmActionHandler { - fn handle_request( + fn put_handler( &self, - req: &Request, api_notifier: EventFd, api_sender: Sender, - ) -> Response { - match req.method() { - Method::Put => { - use VmAction::*; - match match self.action { - Boot => vm_boot(api_notifier, api_sender).map_err(HttpError::VmBoot), - Delete => vm_delete(api_notifier, api_sender).map_err(HttpError::VmDelete), - Shutdown => { - vm_shutdown(api_notifier, api_sender).map_err(HttpError::VmShutdown) - } - Reboot => vm_reboot(api_notifier, api_sender).map_err(HttpError::VmReboot), - Pause => vm_pause(api_notifier, api_sender).map_err(HttpError::VmPause), - Resume => vm_resume(api_notifier, api_sender).map_err(HttpError::VmResume), - _ => Err(HttpError::BadRequest) - } { - Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), - Err(e) => error_response(e, StatusCode::InternalServerError), - } + body: &Option, + ) -> std::result::Result<(), HttpError> { + use VmAction::*; + if let Some(body) = body { + match self.action { + AddDevice(_) => vm_add_device( + api_notifier, + api_sender, + Arc::new(serde_json::from_slice(body.raw())?), + ) + .map_err(HttpError::VmAddDevice), + + AddDisk(_) => vm_add_disk( + api_notifier, + api_sender, + Arc::new(serde_json::from_slice(body.raw())?), + ) + .map_err(HttpError::VmAddDisk), + + AddFs(_) => vm_add_fs( + api_notifier, + api_sender, + Arc::new(serde_json::from_slice(body.raw())?), + ) + .map_err(HttpError::VmAddFs), + + AddPmem(_) => vm_add_pmem( + api_notifier, + api_sender, + Arc::new(serde_json::from_slice(body.raw())?), + ) + .map_err(HttpError::VmAddPmem), + + AddNet(_) => vm_add_net( + api_notifier, + api_sender, + Arc::new(serde_json::from_slice(body.raw())?), + ) + .map_err(HttpError::VmAddNet), + + AddVsock(_) => vm_add_vsock( + api_notifier, + api_sender, + Arc::new(serde_json::from_slice(body.raw())?), + ) + .map_err(HttpError::VmAddVsock), + + RemoveDevice(_) => vm_remove_device( + api_notifier, + api_sender, + Arc::new(serde_json::from_slice(body.raw())?), + ) + .map_err(HttpError::VmRemoveDevice), + + Resize(_) => vm_resize( + api_notifier, + api_sender, + Arc::new(serde_json::from_slice(body.raw())?), + ) + .map_err(HttpError::VmResize), + + Restore(_) => vm_restore( + api_notifier, + api_sender, + Arc::new(serde_json::from_slice(body.raw())?), + ) + .map_err(HttpError::VmRestore), + + Snapshot(_) => vm_snapshot( + api_notifier, + api_sender, + Arc::new(serde_json::from_slice(body.raw())?), + ) + .map_err(HttpError::VmSnapshot), + + _ => Err(HttpError::BadRequest), + } + } else { + match self.action { + Boot => vm_boot(api_notifier, api_sender).map_err(HttpError::VmBoot), + Delete => vm_delete(api_notifier, api_sender).map_err(HttpError::VmDelete), + Shutdown => vm_shutdown(api_notifier, api_sender).map_err(HttpError::VmShutdown), + Reboot => vm_reboot(api_notifier, api_sender).map_err(HttpError::VmReboot), + Pause => vm_pause(api_notifier, api_sender).map_err(HttpError::VmPause), + Resume => vm_resume(api_notifier, api_sender).map_err(HttpError::VmResume), + _ => Err(HttpError::BadRequest), } - _ => Response::new(Version::Http11, StatusCode::BadRequest), } } } @@ -123,84 +187,6 @@ impl EndpointHandler for VmInfo { } } -// /api/v1/vm.snapshot handler -pub struct VmSnapshot {} - -impl EndpointHandler for VmSnapshot { - fn handle_request( - &self, - req: &Request, - api_notifier: EventFd, - api_sender: Sender, - ) -> Response { - match req.method() { - Method::Put => { - match &req.body { - Some(body) => { - // Deserialize into a VmSnapshotConfig - let vm_snapshot_data: VmSnapshotConfig = - match serde_json::from_slice(body.raw()) - .map_err(HttpError::SerdeJsonDeserialize) - { - Ok(data) => data, - Err(e) => return error_response(e, StatusCode::BadRequest), - }; - - // Call vm_snapshot() - match vm_snapshot(api_notifier, api_sender, Arc::new(vm_snapshot_data)) - .map_err(HttpError::VmSnapshot) - { - Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), - Err(e) => error_response(e, StatusCode::InternalServerError), - } - } - None => Response::new(Version::Http11, StatusCode::BadRequest), - } - } - _ => Response::new(Version::Http11, StatusCode::BadRequest), - } - } -} - -// /api/v1/vm.restore handler -pub struct VmRestore {} - -impl EndpointHandler for VmRestore { - fn handle_request( - &self, - req: &Request, - api_notifier: EventFd, - api_sender: Sender, - ) -> Response { - match req.method() { - Method::Put => { - match &req.body { - Some(body) => { - // Deserialize into a RestoreConfig - let vm_restore_data: RestoreConfig = - match serde_json::from_slice(body.raw()) - .map_err(HttpError::SerdeJsonDeserialize) - { - Ok(data) => data, - Err(e) => return error_response(e, StatusCode::BadRequest), - }; - - // Call vm_restore() - match vm_restore(api_notifier, api_sender, Arc::new(vm_restore_data)) - .map_err(HttpError::VmRestore) - { - Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), - Err(e) => error_response(e, StatusCode::InternalServerError), - } - } - None => Response::new(Version::Http11, StatusCode::BadRequest), - } - } - _ => Response::new(Version::Http11, StatusCode::BadRequest), - } - } -} - // /api/v1/vmm.info handler pub struct VmmPing {} @@ -248,319 +234,3 @@ impl EndpointHandler for VmmShutdown { } } } - -// /api/v1/vm.resize handler -pub struct VmResize {} - -impl EndpointHandler for VmResize { - fn handle_request( - &self, - req: &Request, - api_notifier: EventFd, - api_sender: Sender, - ) -> Response { - match req.method() { - Method::Put => { - match &req.body { - Some(body) => { - // Deserialize into a VmConfig - let vm_resize_data: VmResizeData = match serde_json::from_slice(body.raw()) - .map_err(HttpError::SerdeJsonDeserialize) - { - Ok(config) => config, - Err(e) => return error_response(e, StatusCode::BadRequest), - }; - - // Call vm_resize() - match vm_resize(api_notifier, api_sender, Arc::new(vm_resize_data)) - .map_err(HttpError::VmResize) - { - Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), - Err(e) => error_response(e, StatusCode::InternalServerError), - } - } - - None => Response::new(Version::Http11, StatusCode::BadRequest), - } - } - _ => Response::new(Version::Http11, StatusCode::BadRequest), - } - } -} - -// /api/v1/vm.add-device handler -pub struct VmAddDevice {} - -impl EndpointHandler for VmAddDevice { - fn handle_request( - &self, - req: &Request, - api_notifier: EventFd, - api_sender: Sender, - ) -> Response { - match req.method() { - Method::Put => { - match &req.body { - Some(body) => { - // Deserialize into a DeviceConfig - let vm_add_device_data: DeviceConfig = - match serde_json::from_slice(body.raw()) - .map_err(HttpError::SerdeJsonDeserialize) - { - Ok(config) => config, - Err(e) => return error_response(e, StatusCode::BadRequest), - }; - - // Call vm_add_device() - match vm_add_device(api_notifier, api_sender, Arc::new(vm_add_device_data)) - .map_err(HttpError::VmAddDevice) - { - Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), - Err(e) => error_response(e, StatusCode::InternalServerError), - } - } - - None => Response::new(Version::Http11, StatusCode::BadRequest), - } - } - _ => Response::new(Version::Http11, StatusCode::BadRequest), - } - } -} - -// /api/v1/vm.remove-device handler -pub struct VmRemoveDevice {} - -impl EndpointHandler for VmRemoveDevice { - fn handle_request( - &self, - req: &Request, - api_notifier: EventFd, - api_sender: Sender, - ) -> Response { - match req.method() { - Method::Put => { - match &req.body { - Some(body) => { - // Deserialize into a VmRemoveDeviceData - let vm_remove_device_data: VmRemoveDeviceData = - match serde_json::from_slice(body.raw()) - .map_err(HttpError::SerdeJsonDeserialize) - { - Ok(config) => config, - Err(e) => return error_response(e, StatusCode::BadRequest), - }; - - // Call vm_remove_device() - match vm_remove_device( - api_notifier, - api_sender, - Arc::new(vm_remove_device_data), - ) - .map_err(HttpError::VmRemoveDevice) - { - Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), - Err(e) => error_response(e, StatusCode::InternalServerError), - } - } - - None => Response::new(Version::Http11, StatusCode::BadRequest), - } - } - _ => Response::new(Version::Http11, StatusCode::BadRequest), - } - } -} - -// /api/v1/vm.add-disk handler -pub struct VmAddDisk {} - -impl EndpointHandler for VmAddDisk { - fn handle_request( - &self, - req: &Request, - api_notifier: EventFd, - api_sender: Sender, - ) -> Response { - match req.method() { - Method::Put => { - match &req.body { - Some(body) => { - // Deserialize into a DiskConfig - let vm_add_disk_data: DiskConfig = match serde_json::from_slice(body.raw()) - .map_err(HttpError::SerdeJsonDeserialize) - { - Ok(config) => config, - Err(e) => return error_response(e, StatusCode::BadRequest), - }; - - // Call vm_add_device() - match vm_add_disk(api_notifier, api_sender, Arc::new(vm_add_disk_data)) - .map_err(HttpError::VmAddDisk) - { - Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), - Err(e) => error_response(e, StatusCode::InternalServerError), - } - } - - None => Response::new(Version::Http11, StatusCode::BadRequest), - } - } - _ => Response::new(Version::Http11, StatusCode::BadRequest), - } - } -} - -// /api/v1/vm.add-fs handler -pub struct VmAddFs {} - -impl EndpointHandler for VmAddFs { - fn handle_request( - &self, - req: &Request, - api_notifier: EventFd, - api_sender: Sender, - ) -> Response { - match req.method() { - Method::Put => { - match &req.body { - Some(body) => { - // Deserialize into a FsConfig - let vm_add_fs_data: FsConfig = match serde_json::from_slice(body.raw()) - .map_err(HttpError::SerdeJsonDeserialize) - { - Ok(config) => config, - Err(e) => return error_response(e, StatusCode::BadRequest), - }; - - // Call vm_add_fs() - match vm_add_fs(api_notifier, api_sender, Arc::new(vm_add_fs_data)) - .map_err(HttpError::VmAddFs) - { - Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), - Err(e) => error_response(e, StatusCode::InternalServerError), - } - } - - None => Response::new(Version::Http11, StatusCode::BadRequest), - } - } - _ => Response::new(Version::Http11, StatusCode::BadRequest), - } - } -} - -// /api/v1/vm.add-pmem handler -pub struct VmAddPmem {} - -impl EndpointHandler for VmAddPmem { - fn handle_request( - &self, - req: &Request, - api_notifier: EventFd, - api_sender: Sender, - ) -> Response { - match req.method() { - Method::Put => { - match &req.body { - Some(body) => { - // Deserialize into a PmemConfig - let vm_add_pmem_data: PmemConfig = match serde_json::from_slice(body.raw()) - .map_err(HttpError::SerdeJsonDeserialize) - { - Ok(config) => config, - Err(e) => return error_response(e, StatusCode::BadRequest), - }; - - match vm_add_pmem(api_notifier, api_sender, Arc::new(vm_add_pmem_data)) - .map_err(HttpError::VmAddPmem) - { - Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), - Err(e) => error_response(e, StatusCode::InternalServerError), - } - } - - None => Response::new(Version::Http11, StatusCode::BadRequest), - } - } - _ => Response::new(Version::Http11, StatusCode::BadRequest), - } - } -} - -// /api/v1/vm.add-net handler -pub struct VmAddNet {} - -impl EndpointHandler for VmAddNet { - fn handle_request( - &self, - req: &Request, - api_notifier: EventFd, - api_sender: Sender, - ) -> Response { - match req.method() { - Method::Put => { - match &req.body { - Some(body) => { - // Deserialize into a NetConfig - let vm_add_net_data: NetConfig = match serde_json::from_slice(body.raw()) - .map_err(HttpError::SerdeJsonDeserialize) - { - Ok(config) => config, - Err(e) => return error_response(e, StatusCode::BadRequest), - }; - - match vm_add_net(api_notifier, api_sender, Arc::new(vm_add_net_data)) - .map_err(HttpError::VmAddNet) - { - Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), - Err(e) => error_response(e, StatusCode::InternalServerError), - } - } - - None => Response::new(Version::Http11, StatusCode::BadRequest), - } - } - _ => Response::new(Version::Http11, StatusCode::BadRequest), - } - } -} - -// /api/v1/vm.add-vsock handler -pub struct VmAddVsock {} - -impl EndpointHandler for VmAddVsock { - fn handle_request( - &self, - req: &Request, - api_notifier: EventFd, - api_sender: Sender, - ) -> Response { - match req.method() { - Method::Put => { - match &req.body { - Some(body) => { - // Deserialize into a VsockConfig - let vm_add_vsock_data: VsockConfig = - match serde_json::from_slice(body.raw()) - .map_err(HttpError::SerdeJsonDeserialize) - { - Ok(config) => config, - Err(e) => return error_response(e, StatusCode::BadRequest), - }; - - match vm_add_vsock(api_notifier, api_sender, Arc::new(vm_add_vsock_data)) - .map_err(HttpError::VmAddVsock) - { - Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), - Err(e) => error_response(e, StatusCode::InternalServerError), - } - } - - None => Response::new(Version::Http11, StatusCode::BadRequest), - } - } - _ => Response::new(Version::Http11, StatusCode::BadRequest), - } - } -} diff --git a/vmm/src/api/mod.rs b/vmm/src/api/mod.rs index b23d69e71..09de6431b 100644 --- a/vmm/src/api/mod.rs +++ b/vmm/src/api/mod.rs @@ -149,18 +149,18 @@ pub struct VmmPingResponse { pub version: String, } -#[derive(Clone, Deserialize, Serialize)] +#[derive(Clone, Deserialize, Serialize, Default)] pub struct VmResizeData { pub desired_vcpus: Option, pub desired_ram: Option, } -#[derive(Clone, Deserialize, Serialize)] +#[derive(Clone, Deserialize, Serialize, Default)] pub struct VmRemoveDeviceData { pub id: String, } -#[derive(Clone, Deserialize, Serialize)] +#[derive(Clone, Deserialize, Serialize, Default)] pub struct VmSnapshotConfig { /// The snapshot destination URL pub destination_url: String, @@ -384,7 +384,6 @@ 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, diff --git a/vmm/src/config.rs b/vmm/src/config.rs index 609c47151..c94fa32bd 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -1116,7 +1116,7 @@ impl ConsoleConfig { } } -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)] pub struct DeviceConfig { pub path: PathBuf, #[serde(default)] @@ -1147,7 +1147,7 @@ impl DeviceConfig { } } -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)] pub struct VsockConfig { pub cid: u64, pub sock: PathBuf, @@ -1189,7 +1189,7 @@ impl VsockConfig { } } -#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)] pub struct RestoreConfig { pub source_url: PathBuf, #[serde(default)]