1c505cfaeSSamuel Ortiz // Copyright © 2019 Intel Corporation 24ca18c08SAlyssa Ross // Copyright 2024 Alyssa Ross <hi@alyssa.is> 3c505cfaeSSamuel Ortiz // 4c505cfaeSSamuel Ortiz // SPDX-License-Identifier: Apache-2.0 5c505cfaeSSamuel Ortiz // 6c505cfaeSSamuel Ortiz 788a9f799SRob Bradford use std::fs::File; 888a9f799SRob Bradford use std::os::unix::io::IntoRawFd; 988a9f799SRob Bradford use std::sync::mpsc::Sender; 1088a9f799SRob Bradford 1188a9f799SRob Bradford use micro_http::{Body, Method, Request, Response, StatusCode, Version}; 1288a9f799SRob Bradford use vmm_sys_util::eventfd::EventFd; 1388a9f799SRob Bradford 14c652625bSRob Bradford use crate::api::http::{error_response, EndpointHandler, HttpError}; 15cefbf6b4SRob Bradford #[cfg(all(target_arch = "x86_64", feature = "guest_debug"))] 164ca18c08SAlyssa Ross use crate::api::VmCoredump; 1743b36429SSamuel Ortiz use crate::api::{ 18*d0225fe6SFabiano Fidêncio AddDisk, ApiAction, ApiError, ApiRequest, NetConfig, VmAddDevice, VmAddFs, VmAddNet, VmAddPmem, 1933c15ca2SSongqian Li VmAddUserDevice, VmAddVdpa, VmAddVsock, VmBoot, VmConfig, VmCounters, VmDelete, VmNmi, VmPause, 2033c15ca2SSongqian Li VmPowerButton, VmReboot, VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeZone, VmRestore, 2133c15ca2SSongqian Li VmResume, VmSendMigration, VmShutdown, VmSnapshot, 2243b36429SSamuel Ortiz }; 2333c15ca2SSongqian Li use crate::config::RestoreConfig; 24*d0225fe6SFabiano Fidêncio use crate::cpu::Error as CpuError; 25*d0225fe6SFabiano Fidêncio use crate::vm::Error as VmError; 26c505cfaeSSamuel Ortiz 27c505cfaeSSamuel Ortiz // /api/v1/vm.create handler 28c505cfaeSSamuel Ortiz pub struct VmCreate {} 29c505cfaeSSamuel Ortiz 30c505cfaeSSamuel Ortiz impl EndpointHandler for VmCreate { handle_request( &self, req: &Request, api_notifier: EventFd, api_sender: Sender<ApiRequest>, ) -> Response31c505cfaeSSamuel Ortiz fn handle_request( 32c505cfaeSSamuel Ortiz &self, 33c505cfaeSSamuel Ortiz req: &Request, 34c505cfaeSSamuel Ortiz api_notifier: EventFd, 35c505cfaeSSamuel Ortiz api_sender: Sender<ApiRequest>, 36c505cfaeSSamuel Ortiz ) -> Response { 37c505cfaeSSamuel Ortiz match req.method() { 38c505cfaeSSamuel Ortiz Method::Put => { 39c505cfaeSSamuel Ortiz match &req.body { 40c505cfaeSSamuel Ortiz Some(body) => { 41c505cfaeSSamuel Ortiz // Deserialize into a VmConfig 42cc9899e0SSongqian Li let mut vm_config: Box<VmConfig> = match serde_json::from_slice(body.raw()) 43c505cfaeSSamuel Ortiz .map_err(HttpError::SerdeJsonDeserialize) 44c505cfaeSSamuel Ortiz { 45c505cfaeSSamuel Ortiz Ok(config) => config, 46c505cfaeSSamuel Ortiz Err(e) => return error_response(e, StatusCode::BadRequest), 47c505cfaeSSamuel Ortiz }; 48c505cfaeSSamuel Ortiz 49fba0b5f9SAlyssa Ross if let Some(ref mut nets) = vm_config.net { 50fba0b5f9SAlyssa Ross if nets.iter().any(|net| net.fds.is_some()) { 51fba0b5f9SAlyssa Ross warn!("Ignoring FDs sent via the HTTP request body"); 52fba0b5f9SAlyssa Ross } 53fba0b5f9SAlyssa Ross for net in nets { 54fba0b5f9SAlyssa Ross net.fds = None; 55fba0b5f9SAlyssa Ross } 56fba0b5f9SAlyssa Ross } 57fba0b5f9SAlyssa Ross 584ca18c08SAlyssa Ross match crate::api::VmCreate 59cc9899e0SSongqian Li .send(api_notifier, api_sender, vm_config) 604ca066f0SRob Bradford .map_err(HttpError::ApiError) 61c505cfaeSSamuel Ortiz { 62f34ace76SSamuel Ortiz Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), 63c505cfaeSSamuel Ortiz Err(e) => error_response(e, StatusCode::InternalServerError), 64c505cfaeSSamuel Ortiz } 65c505cfaeSSamuel Ortiz } 66c505cfaeSSamuel Ortiz 67c505cfaeSSamuel Ortiz None => Response::new(Version::Http11, StatusCode::BadRequest), 68c505cfaeSSamuel Ortiz } 69c505cfaeSSamuel Ortiz } 70c505cfaeSSamuel Ortiz 71b0be5ff8SLiHui _ => error_response(HttpError::BadRequest, StatusCode::BadRequest), 72c505cfaeSSamuel Ortiz } 73c505cfaeSSamuel Ortiz } 74c505cfaeSSamuel Ortiz } 75c505cfaeSSamuel Ortiz 764ca18c08SAlyssa Ross pub trait GetHandler { handle_request( &'static self, _api_notifier: EventFd, _api_sender: Sender<ApiRequest>, ) -> std::result::Result<Option<Body>, HttpError>774ca18c08SAlyssa Ross fn handle_request( 784ca18c08SAlyssa Ross &'static self, 794ca18c08SAlyssa Ross _api_notifier: EventFd, 804ca18c08SAlyssa Ross _api_sender: Sender<ApiRequest>, 814ca18c08SAlyssa Ross ) -> std::result::Result<Option<Body>, HttpError> { 824ca18c08SAlyssa Ross Err(HttpError::BadRequest) 834ca18c08SAlyssa Ross } 844ca18c08SAlyssa Ross } 854ca18c08SAlyssa Ross 864ca18c08SAlyssa Ross pub trait PutHandler { handle_request( &'static self, _api_notifier: EventFd, _api_sender: Sender<ApiRequest>, _body: &Option<Body>, _files: Vec<File>, ) -> std::result::Result<Option<Body>, HttpError>874ca18c08SAlyssa Ross fn handle_request( 884ca18c08SAlyssa Ross &'static self, 894ca18c08SAlyssa Ross _api_notifier: EventFd, 904ca18c08SAlyssa Ross _api_sender: Sender<ApiRequest>, 914ca18c08SAlyssa Ross _body: &Option<Body>, 924ca18c08SAlyssa Ross _files: Vec<File>, 934ca18c08SAlyssa Ross ) -> std::result::Result<Option<Body>, HttpError> { 944ca18c08SAlyssa Ross Err(HttpError::BadRequest) 954ca18c08SAlyssa Ross } 964ca18c08SAlyssa Ross } 974ca18c08SAlyssa Ross 984ca18c08SAlyssa Ross pub trait HttpVmAction: GetHandler + PutHandler + Sync {} 994ca18c08SAlyssa Ross 1004ca18c08SAlyssa Ross impl<T: GetHandler + PutHandler + Sync> HttpVmAction for T {} 1014ca18c08SAlyssa Ross 1024ca18c08SAlyssa Ross macro_rules! vm_action_get_handler { 1034ca18c08SAlyssa Ross ($action:ty) => { 1044ca18c08SAlyssa Ross impl GetHandler for $action { 1054ca18c08SAlyssa Ross fn handle_request( 1064ca18c08SAlyssa Ross &'static self, 1074ca18c08SAlyssa Ross api_notifier: EventFd, 1084ca18c08SAlyssa Ross api_sender: Sender<ApiRequest>, 1094ca18c08SAlyssa Ross ) -> std::result::Result<Option<Body>, HttpError> { 1104ca18c08SAlyssa Ross self.send(api_notifier, api_sender, ()) 1114ca18c08SAlyssa Ross .map_err(HttpError::ApiError) 1124ca18c08SAlyssa Ross } 1134ca18c08SAlyssa Ross } 1144ca18c08SAlyssa Ross 1154ca18c08SAlyssa Ross impl PutHandler for $action {} 1164ca18c08SAlyssa Ross }; 1174ca18c08SAlyssa Ross } 1184ca18c08SAlyssa Ross 1194ca18c08SAlyssa Ross macro_rules! vm_action_put_handler { 1204ca18c08SAlyssa Ross ($action:ty) => { 1214ca18c08SAlyssa Ross impl PutHandler for $action { 1224ca18c08SAlyssa Ross fn handle_request( 1234ca18c08SAlyssa Ross &'static self, 1244ca18c08SAlyssa Ross api_notifier: EventFd, 1254ca18c08SAlyssa Ross api_sender: Sender<ApiRequest>, 1264ca18c08SAlyssa Ross body: &Option<Body>, 1274ca18c08SAlyssa Ross _files: Vec<File>, 1284ca18c08SAlyssa Ross ) -> std::result::Result<Option<Body>, HttpError> { 1294ca18c08SAlyssa Ross if body.is_some() { 1304ca18c08SAlyssa Ross Err(HttpError::BadRequest) 1314ca18c08SAlyssa Ross } else { 1324ca18c08SAlyssa Ross self.send(api_notifier, api_sender, ()) 1334ca18c08SAlyssa Ross .map_err(HttpError::ApiError) 1344ca18c08SAlyssa Ross } 1354ca18c08SAlyssa Ross } 1364ca18c08SAlyssa Ross } 1374ca18c08SAlyssa Ross 1384ca18c08SAlyssa Ross impl GetHandler for $action {} 1394ca18c08SAlyssa Ross }; 1404ca18c08SAlyssa Ross } 1414ca18c08SAlyssa Ross 1424ca18c08SAlyssa Ross macro_rules! vm_action_put_handler_body { 1434ca18c08SAlyssa Ross ($action:ty) => { 1444ca18c08SAlyssa Ross impl PutHandler for $action { 1454ca18c08SAlyssa Ross fn handle_request( 1464ca18c08SAlyssa Ross &'static self, 1474ca18c08SAlyssa Ross api_notifier: EventFd, 1484ca18c08SAlyssa Ross api_sender: Sender<ApiRequest>, 1494ca18c08SAlyssa Ross body: &Option<Body>, 1504ca18c08SAlyssa Ross _files: Vec<File>, 1514ca18c08SAlyssa Ross ) -> std::result::Result<Option<Body>, HttpError> { 1524ca18c08SAlyssa Ross if let Some(body) = body { 1534ca18c08SAlyssa Ross self.send( 1544ca18c08SAlyssa Ross api_notifier, 1554ca18c08SAlyssa Ross api_sender, 1564ca18c08SAlyssa Ross serde_json::from_slice(body.raw())?, 1574ca18c08SAlyssa Ross ) 1584ca18c08SAlyssa Ross .map_err(HttpError::ApiError) 1594ca18c08SAlyssa Ross } else { 1604ca18c08SAlyssa Ross Err(HttpError::BadRequest) 1614ca18c08SAlyssa Ross } 1624ca18c08SAlyssa Ross } 1634ca18c08SAlyssa Ross } 1644ca18c08SAlyssa Ross 1654ca18c08SAlyssa Ross impl GetHandler for $action {} 1664ca18c08SAlyssa Ross }; 1674ca18c08SAlyssa Ross } 1684ca18c08SAlyssa Ross 1694ca18c08SAlyssa Ross vm_action_get_handler!(VmCounters); 1704ca18c08SAlyssa Ross 1714ca18c08SAlyssa Ross vm_action_put_handler!(VmBoot); 1724ca18c08SAlyssa Ross vm_action_put_handler!(VmDelete); 1734ca18c08SAlyssa Ross vm_action_put_handler!(VmShutdown); 1744ca18c08SAlyssa Ross vm_action_put_handler!(VmReboot); 1754ca18c08SAlyssa Ross vm_action_put_handler!(VmPause); 1764ca18c08SAlyssa Ross vm_action_put_handler!(VmResume); 1774ca18c08SAlyssa Ross vm_action_put_handler!(VmPowerButton); 178f40dd4a9SYi Wang vm_action_put_handler!(VmNmi); 1794ca18c08SAlyssa Ross 1804ca18c08SAlyssa Ross vm_action_put_handler_body!(VmAddDevice); 1814ca18c08SAlyssa Ross vm_action_put_handler_body!(AddDisk); 1824ca18c08SAlyssa Ross vm_action_put_handler_body!(VmAddFs); 1834ca18c08SAlyssa Ross vm_action_put_handler_body!(VmAddPmem); 1844ca18c08SAlyssa Ross vm_action_put_handler_body!(VmAddVdpa); 1854ca18c08SAlyssa Ross vm_action_put_handler_body!(VmAddVsock); 1864ca18c08SAlyssa Ross vm_action_put_handler_body!(VmAddUserDevice); 1874ca18c08SAlyssa Ross vm_action_put_handler_body!(VmRemoveDevice); 1884ca18c08SAlyssa Ross vm_action_put_handler_body!(VmResizeZone); 1894ca18c08SAlyssa Ross vm_action_put_handler_body!(VmSnapshot); 1904ca18c08SAlyssa Ross vm_action_put_handler_body!(VmReceiveMigration); 1914ca18c08SAlyssa Ross vm_action_put_handler_body!(VmSendMigration); 1924ca18c08SAlyssa Ross 1934ca18c08SAlyssa Ross #[cfg(all(target_arch = "x86_64", feature = "guest_debug"))] 1944ca18c08SAlyssa Ross vm_action_put_handler_body!(VmCoredump); 1954ca18c08SAlyssa Ross 1964ca18c08SAlyssa Ross impl PutHandler for VmAddNet { handle_request( &'static self, api_notifier: EventFd, api_sender: Sender<ApiRequest>, body: &Option<Body>, mut files: Vec<File>, ) -> std::result::Result<Option<Body>, HttpError>1974ca18c08SAlyssa Ross fn handle_request( 1984ca18c08SAlyssa Ross &'static self, 1994ca18c08SAlyssa Ross api_notifier: EventFd, 2004ca18c08SAlyssa Ross api_sender: Sender<ApiRequest>, 2014ca18c08SAlyssa Ross body: &Option<Body>, 2024ca18c08SAlyssa Ross mut files: Vec<File>, 2034ca18c08SAlyssa Ross ) -> std::result::Result<Option<Body>, HttpError> { 2044ca18c08SAlyssa Ross if let Some(body) = body { 2054ca18c08SAlyssa Ross let mut net_cfg: NetConfig = serde_json::from_slice(body.raw())?; 2064ca18c08SAlyssa Ross if net_cfg.fds.is_some() { 2074ca18c08SAlyssa Ross warn!("Ignoring FDs sent via the HTTP request body"); 2084ca18c08SAlyssa Ross net_cfg.fds = None; 2094ca18c08SAlyssa Ross } 2104ca18c08SAlyssa Ross if !files.is_empty() { 2114ca18c08SAlyssa Ross let fds = files.drain(..).map(|f| f.into_raw_fd()).collect(); 2124ca18c08SAlyssa Ross net_cfg.fds = Some(fds); 2134ca18c08SAlyssa Ross } 2144ca18c08SAlyssa Ross self.send(api_notifier, api_sender, net_cfg) 2154ca18c08SAlyssa Ross .map_err(HttpError::ApiError) 2164ca18c08SAlyssa Ross } else { 2174ca18c08SAlyssa Ross Err(HttpError::BadRequest) 2184ca18c08SAlyssa Ross } 2194ca18c08SAlyssa Ross } 2204ca18c08SAlyssa Ross } 2214ca18c08SAlyssa Ross 2224ca18c08SAlyssa Ross impl GetHandler for VmAddNet {} 2234ca18c08SAlyssa Ross 224*d0225fe6SFabiano Fidêncio impl PutHandler for VmResize { handle_request( &'static self, api_notifier: EventFd, api_sender: Sender<ApiRequest>, body: &Option<Body>, _files: Vec<File>, ) -> std::result::Result<Option<Body>, HttpError>225*d0225fe6SFabiano Fidêncio fn handle_request( 226*d0225fe6SFabiano Fidêncio &'static self, 227*d0225fe6SFabiano Fidêncio api_notifier: EventFd, 228*d0225fe6SFabiano Fidêncio api_sender: Sender<ApiRequest>, 229*d0225fe6SFabiano Fidêncio body: &Option<Body>, 230*d0225fe6SFabiano Fidêncio _files: Vec<File>, 231*d0225fe6SFabiano Fidêncio ) -> std::result::Result<Option<Body>, HttpError> { 232*d0225fe6SFabiano Fidêncio if let Some(body) = body { 233*d0225fe6SFabiano Fidêncio self.send( 234*d0225fe6SFabiano Fidêncio api_notifier, 235*d0225fe6SFabiano Fidêncio api_sender, 236*d0225fe6SFabiano Fidêncio serde_json::from_slice(body.raw())?, 237*d0225fe6SFabiano Fidêncio ) 238*d0225fe6SFabiano Fidêncio .map_err(|e| match e { 239*d0225fe6SFabiano Fidêncio ApiError::VmResize(VmError::CpuManager(CpuError::VcpuPendingRemovedVcpu)) => { 240*d0225fe6SFabiano Fidêncio HttpError::TooManyRequests 241*d0225fe6SFabiano Fidêncio } 242*d0225fe6SFabiano Fidêncio _ => HttpError::ApiError(e), 243*d0225fe6SFabiano Fidêncio }) 244*d0225fe6SFabiano Fidêncio } else { 245*d0225fe6SFabiano Fidêncio Err(HttpError::BadRequest) 246*d0225fe6SFabiano Fidêncio } 247*d0225fe6SFabiano Fidêncio } 248*d0225fe6SFabiano Fidêncio } 249*d0225fe6SFabiano Fidêncio 250*d0225fe6SFabiano Fidêncio impl GetHandler for VmResize {} 251*d0225fe6SFabiano Fidêncio 252b82f2557SPurna Pavan Chandra impl PutHandler for VmRestore { handle_request( &'static self, api_notifier: EventFd, api_sender: Sender<ApiRequest>, body: &Option<Body>, mut files: Vec<File>, ) -> std::result::Result<Option<Body>, HttpError>253b82f2557SPurna Pavan Chandra fn handle_request( 254b82f2557SPurna Pavan Chandra &'static self, 255b82f2557SPurna Pavan Chandra api_notifier: EventFd, 256b82f2557SPurna Pavan Chandra api_sender: Sender<ApiRequest>, 257b82f2557SPurna Pavan Chandra body: &Option<Body>, 258b82f2557SPurna Pavan Chandra mut files: Vec<File>, 259b82f2557SPurna Pavan Chandra ) -> std::result::Result<Option<Body>, HttpError> { 260b82f2557SPurna Pavan Chandra if let Some(body) = body { 261b82f2557SPurna Pavan Chandra let mut restore_cfg: RestoreConfig = serde_json::from_slice(body.raw())?; 262b82f2557SPurna Pavan Chandra 263b82f2557SPurna Pavan Chandra let mut fds = Vec::new(); 264b82f2557SPurna Pavan Chandra if !files.is_empty() { 265b82f2557SPurna Pavan Chandra fds = files.drain(..).map(|f| f.into_raw_fd()).collect(); 266b82f2557SPurna Pavan Chandra } 267b82f2557SPurna Pavan Chandra let expected_fds = match restore_cfg.net_fds { 268b82f2557SPurna Pavan Chandra Some(ref net_fds) => net_fds.iter().map(|net| net.num_fds).sum(), 269b82f2557SPurna Pavan Chandra None => 0, 270b82f2557SPurna Pavan Chandra }; 271b82f2557SPurna Pavan Chandra if fds.len() != expected_fds { 272b82f2557SPurna Pavan Chandra error!( 273b82f2557SPurna Pavan Chandra "Number of FDs expected: {}, but received: {}", 274b82f2557SPurna Pavan Chandra expected_fds, 275b82f2557SPurna Pavan Chandra fds.len() 276b82f2557SPurna Pavan Chandra ); 277b82f2557SPurna Pavan Chandra return Err(HttpError::BadRequest); 278b82f2557SPurna Pavan Chandra } 279b82f2557SPurna Pavan Chandra if let Some(ref mut nets) = restore_cfg.net_fds { 280b82f2557SPurna Pavan Chandra warn!("Ignoring FDs sent via the HTTP request body"); 281b82f2557SPurna Pavan Chandra let mut start_idx = 0; 282b82f2557SPurna Pavan Chandra for restored_net in nets.iter_mut() { 283b82f2557SPurna Pavan Chandra let end_idx = start_idx + restored_net.num_fds; 284b82f2557SPurna Pavan Chandra restored_net.fds = Some(fds[start_idx..end_idx].to_vec()); 285b82f2557SPurna Pavan Chandra start_idx = end_idx; 286b82f2557SPurna Pavan Chandra } 287b82f2557SPurna Pavan Chandra } 288b82f2557SPurna Pavan Chandra 289b82f2557SPurna Pavan Chandra self.send(api_notifier, api_sender, restore_cfg) 290b82f2557SPurna Pavan Chandra .map_err(HttpError::ApiError) 291b82f2557SPurna Pavan Chandra } else { 292b82f2557SPurna Pavan Chandra Err(HttpError::BadRequest) 293b82f2557SPurna Pavan Chandra } 294b82f2557SPurna Pavan Chandra } 295b82f2557SPurna Pavan Chandra } 296b82f2557SPurna Pavan Chandra 297b82f2557SPurna Pavan Chandra impl GetHandler for VmRestore {} 298b82f2557SPurna Pavan Chandra 299c505cfaeSSamuel Ortiz // Common handler for boot, shutdown and reboot 300c505cfaeSSamuel Ortiz pub struct VmActionHandler { 3014ca18c08SAlyssa Ross action: &'static dyn HttpVmAction, 302c505cfaeSSamuel Ortiz } 303c505cfaeSSamuel Ortiz 304c505cfaeSSamuel Ortiz impl VmActionHandler { new(action: &'static dyn HttpVmAction) -> Self3054ca18c08SAlyssa Ross pub fn new(action: &'static dyn HttpVmAction) -> Self { 3066ec605a7SRob Bradford VmActionHandler { action } 307c505cfaeSSamuel Ortiz } 308c505cfaeSSamuel Ortiz } 309c505cfaeSSamuel Ortiz 310c505cfaeSSamuel Ortiz impl EndpointHandler for VmActionHandler { put_handler( &self, api_notifier: EventFd, api_sender: Sender<ApiRequest>, body: &Option<Body>, files: Vec<File>, ) -> std::result::Result<Option<Body>, HttpError>3116aa29bdbSRob Bradford fn put_handler( 312c505cfaeSSamuel Ortiz &self, 313c505cfaeSSamuel Ortiz api_notifier: EventFd, 314c505cfaeSSamuel Ortiz api_sender: Sender<ApiRequest>, 3156aa29bdbSRob Bradford body: &Option<Body>, 3164ca18c08SAlyssa Ross files: Vec<File>, 31703818026SSebastien Boeuf ) -> std::result::Result<Option<Body>, HttpError> { 3184ca18c08SAlyssa Ross PutHandler::handle_request(self.action, api_notifier, api_sender, body, files) 319c505cfaeSSamuel Ortiz } 320bca8a192SRob Bradford get_handler( &self, api_notifier: EventFd, api_sender: Sender<ApiRequest>, _body: &Option<Body>, ) -> std::result::Result<Option<Body>, HttpError>321bca8a192SRob Bradford fn get_handler( 322bca8a192SRob Bradford &self, 323bca8a192SRob Bradford api_notifier: EventFd, 324bca8a192SRob Bradford api_sender: Sender<ApiRequest>, 325bca8a192SRob Bradford _body: &Option<Body>, 326bca8a192SRob Bradford ) -> std::result::Result<Option<Body>, HttpError> { 3274ca18c08SAlyssa Ross GetHandler::handle_request(self.action, api_notifier, api_sender) 328bca8a192SRob Bradford } 329c505cfaeSSamuel Ortiz } 33042758244SSamuel Ortiz 33142758244SSamuel Ortiz // /api/v1/vm.info handler 33242758244SSamuel Ortiz pub struct VmInfo {} 33342758244SSamuel Ortiz 33442758244SSamuel Ortiz impl EndpointHandler for VmInfo { handle_request( &self, req: &Request, api_notifier: EventFd, api_sender: Sender<ApiRequest>, ) -> Response33542758244SSamuel Ortiz fn handle_request( 33642758244SSamuel Ortiz &self, 33742758244SSamuel Ortiz req: &Request, 33842758244SSamuel Ortiz api_notifier: EventFd, 33942758244SSamuel Ortiz api_sender: Sender<ApiRequest>, 34042758244SSamuel Ortiz ) -> Response { 34142758244SSamuel Ortiz match req.method() { 3424ca18c08SAlyssa Ross Method::Get => match crate::api::VmInfo 3434ca18c08SAlyssa Ross .send(api_notifier, api_sender, ()) 3444ca18c08SAlyssa Ross .map_err(HttpError::ApiError) 3454ca18c08SAlyssa Ross { 34642758244SSamuel Ortiz Ok(info) => { 34742758244SSamuel Ortiz let mut response = Response::new(Version::Http11, StatusCode::OK); 34842758244SSamuel Ortiz let info_serialized = serde_json::to_string(&info).unwrap(); 34942758244SSamuel Ortiz 35042758244SSamuel Ortiz response.set_body(Body::new(info_serialized)); 35142758244SSamuel Ortiz response 35242758244SSamuel Ortiz } 35342758244SSamuel Ortiz Err(e) => error_response(e, StatusCode::InternalServerError), 35442758244SSamuel Ortiz }, 355b0be5ff8SLiHui _ => error_response(HttpError::BadRequest, StatusCode::BadRequest), 35642758244SSamuel Ortiz } 35742758244SSamuel Ortiz } 35842758244SSamuel Ortiz } 359a95fa1c4SSamuel Ortiz 360a5186514SJose Carlos Venegas Munoz // /api/v1/vmm.info handler 361a5186514SJose Carlos Venegas Munoz pub struct VmmPing {} 362a5186514SJose Carlos Venegas Munoz 363a5186514SJose Carlos Venegas Munoz impl EndpointHandler for VmmPing { handle_request( &self, req: &Request, api_notifier: EventFd, api_sender: Sender<ApiRequest>, ) -> Response364a5186514SJose Carlos Venegas Munoz fn handle_request( 365a5186514SJose Carlos Venegas Munoz &self, 366a5186514SJose Carlos Venegas Munoz req: &Request, 367a5186514SJose Carlos Venegas Munoz api_notifier: EventFd, 368a5186514SJose Carlos Venegas Munoz api_sender: Sender<ApiRequest>, 369a5186514SJose Carlos Venegas Munoz ) -> Response { 370a5186514SJose Carlos Venegas Munoz match req.method() { 3714ca18c08SAlyssa Ross Method::Get => match crate::api::VmmPing 3724ca18c08SAlyssa Ross .send(api_notifier, api_sender, ()) 3734ca18c08SAlyssa Ross .map_err(HttpError::ApiError) 3744ca18c08SAlyssa Ross { 375a5186514SJose Carlos Venegas Munoz Ok(pong) => { 376a5186514SJose Carlos Venegas Munoz let mut response = Response::new(Version::Http11, StatusCode::OK); 377a5186514SJose Carlos Venegas Munoz let info_serialized = serde_json::to_string(&pong).unwrap(); 378a5186514SJose Carlos Venegas Munoz 379a5186514SJose Carlos Venegas Munoz response.set_body(Body::new(info_serialized)); 380a5186514SJose Carlos Venegas Munoz response 381a5186514SJose Carlos Venegas Munoz } 382a5186514SJose Carlos Venegas Munoz Err(e) => error_response(e, StatusCode::InternalServerError), 383a5186514SJose Carlos Venegas Munoz }, 384b0be5ff8SLiHui 385b0be5ff8SLiHui _ => error_response(HttpError::BadRequest, StatusCode::BadRequest), 386a5186514SJose Carlos Venegas Munoz } 387a5186514SJose Carlos Venegas Munoz } 388a5186514SJose Carlos Venegas Munoz } 389a5186514SJose Carlos Venegas Munoz 390a95fa1c4SSamuel Ortiz // /api/v1/vmm.shutdown handler 391a95fa1c4SSamuel Ortiz pub struct VmmShutdown {} 392a95fa1c4SSamuel Ortiz 393a95fa1c4SSamuel Ortiz impl EndpointHandler for VmmShutdown { handle_request( &self, req: &Request, api_notifier: EventFd, api_sender: Sender<ApiRequest>, ) -> Response394a95fa1c4SSamuel Ortiz fn handle_request( 395a95fa1c4SSamuel Ortiz &self, 396a95fa1c4SSamuel Ortiz req: &Request, 397a95fa1c4SSamuel Ortiz api_notifier: EventFd, 398a95fa1c4SSamuel Ortiz api_sender: Sender<ApiRequest>, 399a95fa1c4SSamuel Ortiz ) -> Response { 400a95fa1c4SSamuel Ortiz match req.method() { 401a95fa1c4SSamuel Ortiz Method::Put => { 4024ca18c08SAlyssa Ross match crate::api::VmmShutdown 4034ca18c08SAlyssa Ross .send(api_notifier, api_sender, ()) 4044ca18c08SAlyssa Ross .map_err(HttpError::ApiError) 4054ca18c08SAlyssa Ross { 406a95fa1c4SSamuel Ortiz Ok(_) => Response::new(Version::Http11, StatusCode::OK), 407a95fa1c4SSamuel Ortiz Err(e) => error_response(e, StatusCode::InternalServerError), 408a95fa1c4SSamuel Ortiz } 409a95fa1c4SSamuel Ortiz } 410b0be5ff8SLiHui _ => error_response(HttpError::BadRequest, StatusCode::BadRequest), 411a95fa1c4SSamuel Ortiz } 412a95fa1c4SSamuel Ortiz } 413a95fa1c4SSamuel Ortiz } 414