xref: /cloud-hypervisor/vmm/src/api/mod.rs (revision 3f3489e38e32a652241e889a9a1f6c67823d584b)
1 // Copyright © 2019 Intel Corporation
2 // Copyright 2024 Alyssa Ross <hi@alyssa.is>
3 //
4 // SPDX-License-Identifier: Apache-2.0
5 //
6 
7 //! The internal VMM API for Cloud Hypervisor.
8 //!
9 //! This API is a synchronous, [mpsc](https://doc.rust-lang.org/std/sync/mpsc/)
10 //! based IPC for sending commands to the VMM thread, from other
11 //! Cloud Hypervisor threads. The IPC follows a command-response protocol, i.e.
12 //! each command will receive a response back.
13 //!
14 //! The main Cloud Hypervisor thread creates an API event file descriptor
15 //! to notify the VMM thread about pending API commands, together with an
16 //! API mpsc channel. The former is the IPC control plane, the latter is the
17 //! IPC data plane.
18 //! In order to use the IPC, a Cloud Hypervisor thread needs to have a clone
19 //! of both the API event file descriptor and the channel Sender. Then it must
20 //! go through the following steps:
21 //!
22 //! 1. The thread creates an mpsc channel for receiving the command response.
23 //! 2. The thread sends an ApiRequest to the Sender endpoint. The ApiRequest
24 //!    encapsulates the response channel Sender, for the VMM API server to be
25 //!    able to send the response back.
26 //! 3. The thread writes to the API event file descriptor to notify the VMM
27 //!    API server about a pending command.
28 //! 4. The thread reads the response back from the VMM API server, from the
29 //!    response channel Receiver.
30 //! 5. The thread handles the response and forwards potential errors.
31 
32 #[cfg(feature = "dbus_api")]
33 pub mod dbus;
34 pub mod http;
35 
36 use std::io;
37 use std::sync::mpsc::{channel, RecvError, SendError, Sender};
38 
39 use micro_http::Body;
40 use serde::{Deserialize, Serialize};
41 use thiserror::Error;
42 use vm_migration::MigratableError;
43 use vmm_sys_util::eventfd::EventFd;
44 
45 #[cfg(feature = "dbus_api")]
46 pub use self::dbus::start_dbus_thread;
47 pub use self::http::{start_http_fd_thread, start_http_path_thread};
48 use crate::config::RestoreConfig;
49 use crate::device_tree::DeviceTree;
50 use crate::vm::{Error as VmError, VmState};
51 use crate::vm_config::{
52     DeviceConfig, DiskConfig, FsConfig, NetConfig, PmemConfig, UserDeviceConfig, VdpaConfig,
53     VmConfig, VsockConfig,
54 };
55 use crate::Error as VmmError;
56 
57 /// API errors are sent back from the VMM API server through the ApiResponse.
58 #[derive(Error, Debug)]
59 pub enum ApiError {
60     /// Cannot write to EventFd.
61     #[error("Cannot write to EventFd")]
62     EventFdWrite(#[source] io::Error),
63 
64     /// API request send error
65     #[error("API request send error")]
66     RequestSend(#[source] SendError<ApiRequest>),
67 
68     /// Wrong response payload type
69     #[error("Wrong response payload type")]
70     ResponsePayloadType,
71 
72     /// API response receive error
73     #[error("API response receive error")]
74     ResponseRecv(#[source] RecvError),
75 
76     /// The VM could not boot.
77     #[error("The VM could not boot")]
78     VmBoot(#[source] VmError),
79 
80     /// The VM could not be created.
81     #[error("The VM could not be created")]
82     VmCreate(#[source] VmError),
83 
84     /// The VM could not be deleted.
85     #[error("The VM could not be deleted")]
86     VmDelete(#[source] VmError),
87 
88     /// The VM info is not available.
89     #[error("The VM info is not available")]
90     VmInfo(#[source] VmError),
91 
92     /// The VM could not be paused.
93     #[error("The VM could not be paused")]
94     VmPause(#[source] VmError),
95 
96     /// The VM could not resume.
97     #[error("The VM could not resume")]
98     VmResume(#[source] VmError),
99 
100     /// The VM is not booted.
101     #[error("The VM is not booted")]
102     VmNotBooted,
103 
104     /// The VM is not created.
105     #[error("The VM is not created")]
106     VmNotCreated,
107 
108     /// The VM could not shutdown.
109     #[error("The VM could not shutdown")]
110     VmShutdown(#[source] VmError),
111 
112     /// The VM could not reboot.
113     #[error("The VM could not reboot")]
114     VmReboot(#[source] VmError),
115 
116     /// The VM could not be snapshotted.
117     #[error("The VM could not be snapshotted")]
118     VmSnapshot(#[source] VmError),
119 
120     /// The VM could not restored.
121     #[error("The VM could not restored")]
122     VmRestore(#[source] VmError),
123 
124     /// The VM could not be coredumped.
125     #[error("The VM could not be coredumped")]
126     VmCoredump(#[source] VmError),
127 
128     /// The VMM could not shutdown.
129     #[error("The VMM could not shutdown")]
130     VmmShutdown(#[source] VmError),
131 
132     /// The VM could not be resized
133     #[error("The VM could not be resized")]
134     VmResize(#[source] VmError),
135 
136     /// The memory zone could not be resized.
137     #[error("The memory zone could not be resized")]
138     VmResizeZone(#[source] VmError),
139 
140     /// The device could not be added to the VM.
141     #[error("The device could not be added to the VM")]
142     VmAddDevice(#[source] VmError),
143 
144     /// The user device could not be added to the VM.
145     #[error("The user device could not be added to the VM")]
146     VmAddUserDevice(#[source] VmError),
147 
148     /// The device could not be removed from the VM.
149     #[error("The device could not be removed from the VM")]
150     VmRemoveDevice(#[source] VmError),
151 
152     /// Cannot create seccomp filter
153     #[error("Cannot create seccomp filter")]
154     CreateSeccompFilter(#[source] seccompiler::Error),
155 
156     /// Cannot apply seccomp filter
157     #[error("Cannot apply seccomp filter")]
158     ApplySeccompFilter(#[source] seccompiler::Error),
159 
160     /// The disk could not be added to the VM.
161     #[error("The disk could not be added to the VM")]
162     VmAddDisk(#[source] VmError),
163 
164     /// The fs could not be added to the VM.
165     #[error("The fs could not be added to the VM")]
166     VmAddFs(#[source] VmError),
167 
168     /// The pmem device could not be added to the VM.
169     #[error("The pmem device could not be added to the VM")]
170     VmAddPmem(#[source] VmError),
171 
172     /// The network device could not be added to the VM.
173     #[error("The network device could not be added to the VM")]
174     VmAddNet(#[source] VmError),
175 
176     /// The vDPA device could not be added to the VM.
177     #[error("The vDPA device could not be added to the VM")]
178     VmAddVdpa(#[source] VmError),
179 
180     /// The vsock device could not be added to the VM.
181     #[error("The vsock device could not be added to the VM")]
182     VmAddVsock(#[source] VmError),
183 
184     /// Error starting migration receiver
185     #[error("Error starting migration receiver")]
186     VmReceiveMigration(#[source] MigratableError),
187 
188     /// Error starting migration sender
189     #[error("Error starting migration sender")]
190     VmSendMigration(#[source] MigratableError),
191 
192     /// Error triggering power button
193     #[error("Error triggering power button")]
194     VmPowerButton(#[source] VmError),
195 
196     /// Error triggering NMI
197     #[error("Error triggering NMI")]
198     VmNmi(#[source] VmError),
199 }
200 pub type ApiResult<T> = Result<T, ApiError>;
201 
202 #[derive(Clone, Deserialize, Serialize)]
203 pub struct VmInfoResponse {
204     pub config: Box<VmConfig>,
205     pub state: VmState,
206     pub memory_actual_size: u64,
207     pub device_tree: Option<DeviceTree>,
208 }
209 
210 #[derive(Clone, Deserialize, Serialize)]
211 pub struct VmmPingResponse {
212     pub build_version: String,
213     pub version: String,
214     pub pid: i64,
215     pub features: Vec<String>,
216 }
217 
218 #[derive(Clone, Deserialize, Serialize, Default, Debug)]
219 pub struct VmResizeData {
220     pub desired_vcpus: Option<u8>,
221     pub desired_ram: Option<u64>,
222     pub desired_balloon: Option<u64>,
223 }
224 
225 #[derive(Clone, Deserialize, Serialize, Default, Debug)]
226 pub struct VmResizeZoneData {
227     pub id: String,
228     pub desired_ram: u64,
229 }
230 
231 #[derive(Clone, Deserialize, Serialize, Default, Debug)]
232 pub struct VmRemoveDeviceData {
233     pub id: String,
234 }
235 
236 #[derive(Clone, Deserialize, Serialize, Default, Debug)]
237 pub struct VmSnapshotConfig {
238     /// The snapshot destination URL
239     pub destination_url: String,
240 }
241 
242 #[derive(Clone, Deserialize, Serialize, Default, Debug)]
243 pub struct VmCoredumpData {
244     /// The coredump destination file
245     pub destination_url: String,
246 }
247 
248 #[derive(Clone, Deserialize, Serialize, Default, Debug)]
249 pub struct VmReceiveMigrationData {
250     /// URL for the reception of migration state
251     pub receiver_url: String,
252 }
253 
254 #[derive(Clone, Deserialize, Serialize, Default, Debug)]
255 pub struct VmSendMigrationData {
256     /// URL to migrate the VM to
257     pub destination_url: String,
258     /// Send memory across socket without copying
259     #[serde(default)]
260     pub local: bool,
261 }
262 
263 pub enum ApiResponsePayload {
264     /// No data is sent on the channel.
265     Empty,
266 
267     /// Virtual machine information
268     VmInfo(VmInfoResponse),
269 
270     /// Vmm ping response
271     VmmPing(VmmPingResponse),
272 
273     /// Vm action response
274     VmAction(Option<Vec<u8>>),
275 }
276 
277 /// This is the response sent by the VMM API server through the mpsc channel.
278 pub type ApiResponse = Result<ApiResponsePayload, ApiError>;
279 
280 pub trait RequestHandler {
281     fn vm_create(&mut self, config: Box<VmConfig>) -> Result<(), VmError>;
282 
283     fn vm_boot(&mut self) -> Result<(), VmError>;
284 
285     fn vm_pause(&mut self) -> Result<(), VmError>;
286 
287     fn vm_resume(&mut self) -> Result<(), VmError>;
288 
289     fn vm_snapshot(&mut self, destination_url: &str) -> Result<(), VmError>;
290 
291     fn vm_restore(&mut self, restore_cfg: RestoreConfig) -> Result<(), VmError>;
292 
293     #[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
294     fn vm_coredump(&mut self, destination_url: &str) -> Result<(), VmError>;
295 
296     fn vm_shutdown(&mut self) -> Result<(), VmError>;
297 
298     fn vm_reboot(&mut self) -> Result<(), VmError>;
299 
300     fn vm_info(&self) -> Result<VmInfoResponse, VmError>;
301 
302     fn vmm_ping(&self) -> VmmPingResponse;
303 
304     fn vm_delete(&mut self) -> Result<(), VmError>;
305 
306     fn vmm_shutdown(&mut self) -> Result<(), VmError>;
307 
308     fn vm_resize(
309         &mut self,
310         desired_vcpus: Option<u8>,
311         desired_ram: Option<u64>,
312         desired_balloon: Option<u64>,
313     ) -> Result<(), VmError>;
314 
315     fn vm_resize_zone(&mut self, id: String, desired_ram: u64) -> Result<(), VmError>;
316 
317     fn vm_add_device(&mut self, device_cfg: DeviceConfig) -> Result<Option<Vec<u8>>, VmError>;
318 
319     fn vm_add_user_device(
320         &mut self,
321         device_cfg: UserDeviceConfig,
322     ) -> Result<Option<Vec<u8>>, VmError>;
323 
324     fn vm_remove_device(&mut self, id: String) -> Result<(), VmError>;
325 
326     fn vm_add_disk(&mut self, disk_cfg: DiskConfig) -> Result<Option<Vec<u8>>, VmError>;
327 
328     fn vm_add_fs(&mut self, fs_cfg: FsConfig) -> Result<Option<Vec<u8>>, VmError>;
329 
330     fn vm_add_pmem(&mut self, pmem_cfg: PmemConfig) -> Result<Option<Vec<u8>>, VmError>;
331 
332     fn vm_add_net(&mut self, net_cfg: NetConfig) -> Result<Option<Vec<u8>>, VmError>;
333 
334     fn vm_add_vdpa(&mut self, vdpa_cfg: VdpaConfig) -> Result<Option<Vec<u8>>, VmError>;
335 
336     fn vm_add_vsock(&mut self, vsock_cfg: VsockConfig) -> Result<Option<Vec<u8>>, VmError>;
337 
338     fn vm_counters(&mut self) -> Result<Option<Vec<u8>>, VmError>;
339 
340     fn vm_power_button(&mut self) -> Result<(), VmError>;
341 
342     fn vm_receive_migration(
343         &mut self,
344         receive_data_migration: VmReceiveMigrationData,
345     ) -> Result<(), MigratableError>;
346 
347     fn vm_send_migration(
348         &mut self,
349         send_data_migration: VmSendMigrationData,
350     ) -> Result<(), MigratableError>;
351 
352     fn vm_nmi(&mut self) -> Result<(), VmError>;
353 }
354 
355 /// It would be nice if we could pass around an object like this:
356 ///
357 /// ```
358 /// # use vmm::api::ApiAction;
359 /// struct ApiRequest<Action: ApiAction + 'static> {
360 ///     action: &'static Action,
361 ///     body: Action::RequestBody,
362 /// }
363 /// ```
364 ///
365 /// Unfortunately, it's not possible to use such a type in a trait object,
366 /// so as a workaround, we instead encapsulate that data in a closure, and have
367 /// the event loop call that closure to process a request.
368 pub type ApiRequest =
369     Box<dyn FnOnce(&mut dyn RequestHandler) -> Result<bool, VmmError> + Send + 'static>;
370 
371 fn get_response<Action: ApiAction>(
372     action: &Action,
373     api_evt: EventFd,
374     api_sender: Sender<ApiRequest>,
375     data: Action::RequestBody,
376 ) -> ApiResult<ApiResponsePayload> {
377     let (response_sender, response_receiver) = channel();
378 
379     let request = action.request(data, response_sender);
380 
381     // Send the VM request.
382     api_sender.send(request).map_err(ApiError::RequestSend)?;
383     api_evt.write(1).map_err(ApiError::EventFdWrite)?;
384 
385     response_receiver.recv().map_err(ApiError::ResponseRecv)?
386 }
387 
388 fn get_response_body<Action: ApiAction<ResponseBody = Option<Body>>>(
389     action: &Action,
390     api_evt: EventFd,
391     api_sender: Sender<ApiRequest>,
392     data: Action::RequestBody,
393 ) -> ApiResult<Option<Body>> {
394     let body = match get_response(action, api_evt, api_sender, data)? {
395         ApiResponsePayload::VmAction(response) => response.map(Body::new),
396         ApiResponsePayload::Empty => None,
397         _ => return Err(ApiError::ResponsePayloadType),
398     };
399 
400     Ok(body)
401 }
402 
403 pub trait ApiAction: Send + Sync {
404     type RequestBody: Send + Sync + Sized;
405     type ResponseBody: Send + Sized;
406 
407     fn request(&self, body: Self::RequestBody, response_sender: Sender<ApiResponse>) -> ApiRequest;
408 
409     fn send(
410         &self,
411         api_evt: EventFd,
412         api_sender: Sender<ApiRequest>,
413         data: Self::RequestBody,
414     ) -> ApiResult<Self::ResponseBody>;
415 }
416 
417 pub struct VmAddDevice;
418 
419 impl ApiAction for VmAddDevice {
420     type RequestBody = DeviceConfig;
421     type ResponseBody = Option<Body>;
422 
423     fn request(
424         &self,
425         config: Self::RequestBody,
426         response_sender: Sender<ApiResponse>,
427     ) -> ApiRequest {
428         Box::new(move |vmm| {
429             info!("API request event: VmAddDevice {:?}", config);
430 
431             let response = vmm
432                 .vm_add_device(config)
433                 .map_err(ApiError::VmAddDevice)
434                 .map(ApiResponsePayload::VmAction);
435 
436             response_sender
437                 .send(response)
438                 .map_err(VmmError::ApiResponseSend)?;
439 
440             Ok(false)
441         })
442     }
443 
444     fn send(
445         &self,
446         api_evt: EventFd,
447         api_sender: Sender<ApiRequest>,
448         data: Self::RequestBody,
449     ) -> ApiResult<Self::ResponseBody> {
450         get_response_body(self, api_evt, api_sender, data)
451     }
452 }
453 
454 pub struct AddDisk;
455 
456 impl ApiAction for AddDisk {
457     type RequestBody = DiskConfig;
458     type ResponseBody = Option<Body>;
459 
460     fn request(
461         &self,
462         config: Self::RequestBody,
463         response_sender: Sender<ApiResponse>,
464     ) -> ApiRequest {
465         Box::new(move |vmm| {
466             info!("API request event: AddDisk {:?}", config);
467 
468             let response = vmm
469                 .vm_add_disk(config)
470                 .map_err(ApiError::VmAddDisk)
471                 .map(ApiResponsePayload::VmAction);
472 
473             response_sender
474                 .send(response)
475                 .map_err(VmmError::ApiResponseSend)?;
476 
477             Ok(false)
478         })
479     }
480 
481     fn send(
482         &self,
483         api_evt: EventFd,
484         api_sender: Sender<ApiRequest>,
485         data: Self::RequestBody,
486     ) -> ApiResult<Self::ResponseBody> {
487         get_response_body(self, api_evt, api_sender, data)
488     }
489 }
490 
491 pub struct VmAddFs;
492 
493 impl ApiAction for VmAddFs {
494     type RequestBody = FsConfig;
495     type ResponseBody = Option<Body>;
496 
497     fn request(
498         &self,
499         config: Self::RequestBody,
500         response_sender: Sender<ApiResponse>,
501     ) -> ApiRequest {
502         Box::new(move |vmm| {
503             info!("API request event: VmAddFs {:?}", config);
504 
505             let response = vmm
506                 .vm_add_fs(config)
507                 .map_err(ApiError::VmAddFs)
508                 .map(ApiResponsePayload::VmAction);
509 
510             response_sender
511                 .send(response)
512                 .map_err(VmmError::ApiResponseSend)?;
513 
514             Ok(false)
515         })
516     }
517 
518     fn send(
519         &self,
520         api_evt: EventFd,
521         api_sender: Sender<ApiRequest>,
522         data: Self::RequestBody,
523     ) -> ApiResult<Self::ResponseBody> {
524         get_response_body(self, api_evt, api_sender, data)
525     }
526 }
527 
528 pub struct VmAddPmem;
529 
530 impl ApiAction for VmAddPmem {
531     type RequestBody = PmemConfig;
532     type ResponseBody = Option<Body>;
533 
534     fn request(
535         &self,
536         config: Self::RequestBody,
537         response_sender: Sender<ApiResponse>,
538     ) -> ApiRequest {
539         Box::new(move |vmm| {
540             info!("API request event: VmAddPmem {:?}", config);
541 
542             let response = vmm
543                 .vm_add_pmem(config)
544                 .map_err(ApiError::VmAddPmem)
545                 .map(ApiResponsePayload::VmAction);
546 
547             response_sender
548                 .send(response)
549                 .map_err(VmmError::ApiResponseSend)?;
550 
551             Ok(false)
552         })
553     }
554 
555     fn send(
556         &self,
557         api_evt: EventFd,
558         api_sender: Sender<ApiRequest>,
559         data: Self::RequestBody,
560     ) -> ApiResult<Self::ResponseBody> {
561         get_response_body(self, api_evt, api_sender, data)
562     }
563 }
564 
565 pub struct VmAddNet;
566 
567 impl ApiAction for VmAddNet {
568     type RequestBody = NetConfig;
569     type ResponseBody = Option<Body>;
570 
571     fn request(
572         &self,
573         config: Self::RequestBody,
574         response_sender: Sender<ApiResponse>,
575     ) -> ApiRequest {
576         Box::new(move |vmm| {
577             info!("API request event: VmAddNet {:?}", config);
578 
579             let response = vmm
580                 .vm_add_net(config)
581                 .map_err(ApiError::VmAddNet)
582                 .map(ApiResponsePayload::VmAction);
583 
584             response_sender
585                 .send(response)
586                 .map_err(VmmError::ApiResponseSend)?;
587 
588             Ok(false)
589         })
590     }
591 
592     fn send(
593         &self,
594         api_evt: EventFd,
595         api_sender: Sender<ApiRequest>,
596         data: Self::RequestBody,
597     ) -> ApiResult<Self::ResponseBody> {
598         get_response_body(self, api_evt, api_sender, data)
599     }
600 }
601 
602 pub struct VmAddVdpa;
603 
604 impl ApiAction for VmAddVdpa {
605     type RequestBody = VdpaConfig;
606     type ResponseBody = Option<Body>;
607 
608     fn request(
609         &self,
610         config: Self::RequestBody,
611         response_sender: Sender<ApiResponse>,
612     ) -> ApiRequest {
613         Box::new(move |vmm| {
614             info!("API request event: VmAddVdpa {:?}", config);
615 
616             let response = vmm
617                 .vm_add_vdpa(config)
618                 .map_err(ApiError::VmAddVdpa)
619                 .map(ApiResponsePayload::VmAction);
620 
621             response_sender
622                 .send(response)
623                 .map_err(VmmError::ApiResponseSend)?;
624 
625             Ok(false)
626         })
627     }
628 
629     fn send(
630         &self,
631         api_evt: EventFd,
632         api_sender: Sender<ApiRequest>,
633         data: Self::RequestBody,
634     ) -> ApiResult<Self::ResponseBody> {
635         get_response_body(self, api_evt, api_sender, data)
636     }
637 }
638 
639 pub struct VmAddVsock;
640 
641 impl ApiAction for VmAddVsock {
642     type RequestBody = VsockConfig;
643     type ResponseBody = Option<Body>;
644 
645     fn request(
646         &self,
647         config: Self::RequestBody,
648         response_sender: Sender<ApiResponse>,
649     ) -> ApiRequest {
650         Box::new(move |vmm| {
651             info!("API request event: VmAddVsock {:?}", config);
652 
653             let response = vmm
654                 .vm_add_vsock(config)
655                 .map_err(ApiError::VmAddVsock)
656                 .map(ApiResponsePayload::VmAction);
657 
658             response_sender
659                 .send(response)
660                 .map_err(VmmError::ApiResponseSend)?;
661 
662             Ok(false)
663         })
664     }
665 
666     fn send(
667         &self,
668         api_evt: EventFd,
669         api_sender: Sender<ApiRequest>,
670         data: Self::RequestBody,
671     ) -> ApiResult<Self::ResponseBody> {
672         get_response_body(self, api_evt, api_sender, data)
673     }
674 }
675 
676 pub struct VmAddUserDevice;
677 
678 impl ApiAction for VmAddUserDevice {
679     type RequestBody = UserDeviceConfig;
680     type ResponseBody = Option<Body>;
681 
682     fn request(
683         &self,
684         config: Self::RequestBody,
685         response_sender: Sender<ApiResponse>,
686     ) -> ApiRequest {
687         Box::new(move |vmm| {
688             info!("API request event: VmAddUserDevice {:?}", config);
689 
690             let response = vmm
691                 .vm_add_user_device(config)
692                 .map_err(ApiError::VmAddUserDevice)
693                 .map(ApiResponsePayload::VmAction);
694 
695             response_sender
696                 .send(response)
697                 .map_err(VmmError::ApiResponseSend)?;
698 
699             Ok(false)
700         })
701     }
702 
703     fn send(
704         &self,
705         api_evt: EventFd,
706         api_sender: Sender<ApiRequest>,
707         data: Self::RequestBody,
708     ) -> ApiResult<Self::ResponseBody> {
709         get_response_body(self, api_evt, api_sender, data)
710     }
711 }
712 
713 pub struct VmBoot;
714 
715 impl ApiAction for VmBoot {
716     type RequestBody = ();
717     type ResponseBody = Option<Body>;
718 
719     fn request(&self, _: Self::RequestBody, response_sender: Sender<ApiResponse>) -> ApiRequest {
720         Box::new(move |vmm| {
721             info!("API request event: VmBoot");
722 
723             let response = vmm
724                 .vm_boot()
725                 .map_err(ApiError::VmBoot)
726                 .map(|_| ApiResponsePayload::Empty);
727 
728             response_sender
729                 .send(response)
730                 .map_err(VmmError::ApiResponseSend)?;
731 
732             Ok(false)
733         })
734     }
735 
736     fn send(
737         &self,
738         api_evt: EventFd,
739         api_sender: Sender<ApiRequest>,
740         data: Self::RequestBody,
741     ) -> ApiResult<Self::ResponseBody> {
742         get_response_body(self, api_evt, api_sender, data)
743     }
744 }
745 
746 #[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
747 pub struct VmCoredump;
748 
749 #[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
750 impl ApiAction for VmCoredump {
751     type RequestBody = VmCoredumpData;
752     type ResponseBody = Option<Body>;
753 
754     fn request(
755         &self,
756         coredump_data: Self::RequestBody,
757         response_sender: Sender<ApiResponse>,
758     ) -> ApiRequest {
759         Box::new(move |vmm| {
760             info!("API request event: VmCoredump {:?}", coredump_data);
761 
762             let response = vmm
763                 .vm_coredump(&coredump_data.destination_url)
764                 .map_err(ApiError::VmCoredump)
765                 .map(|_| ApiResponsePayload::Empty);
766 
767             response_sender
768                 .send(response)
769                 .map_err(VmmError::ApiResponseSend)?;
770 
771             Ok(false)
772         })
773     }
774 
775     fn send(
776         &self,
777         api_evt: EventFd,
778         api_sender: Sender<ApiRequest>,
779         data: Self::RequestBody,
780     ) -> ApiResult<Self::ResponseBody> {
781         get_response_body(self, api_evt, api_sender, data)
782     }
783 }
784 
785 pub struct VmCounters;
786 
787 impl ApiAction for VmCounters {
788     type RequestBody = ();
789     type ResponseBody = Option<Body>;
790 
791     fn request(&self, _: Self::RequestBody, response_sender: Sender<ApiResponse>) -> ApiRequest {
792         Box::new(move |vmm| {
793             info!("API request event: VmCounters");
794 
795             let response = vmm
796                 .vm_counters()
797                 .map_err(ApiError::VmInfo)
798                 .map(ApiResponsePayload::VmAction);
799 
800             response_sender
801                 .send(response)
802                 .map_err(VmmError::ApiResponseSend)?;
803 
804             Ok(false)
805         })
806     }
807 
808     fn send(
809         &self,
810         api_evt: EventFd,
811         api_sender: Sender<ApiRequest>,
812         data: Self::RequestBody,
813     ) -> ApiResult<Self::ResponseBody> {
814         get_response_body(self, api_evt, api_sender, data)
815     }
816 }
817 
818 pub struct VmCreate;
819 
820 impl ApiAction for VmCreate {
821     type RequestBody = Box<VmConfig>;
822     type ResponseBody = ();
823 
824     fn request(
825         &self,
826         config: Self::RequestBody,
827         response_sender: Sender<ApiResponse>,
828     ) -> ApiRequest {
829         Box::new(move |vmm| {
830             info!("API request event: VmCreate {:?}", config);
831 
832             let response = vmm
833                 .vm_create(config)
834                 .map_err(ApiError::VmCreate)
835                 .map(|_| ApiResponsePayload::Empty);
836 
837             response_sender
838                 .send(response)
839                 .map_err(VmmError::ApiResponseSend)?;
840 
841             Ok(false)
842         })
843     }
844 
845     fn send(
846         &self,
847         api_evt: EventFd,
848         api_sender: Sender<ApiRequest>,
849         data: Self::RequestBody,
850     ) -> ApiResult<()> {
851         get_response(self, api_evt, api_sender, data)?;
852 
853         Ok(())
854     }
855 }
856 
857 pub struct VmDelete;
858 
859 impl ApiAction for VmDelete {
860     type RequestBody = ();
861     type ResponseBody = Option<Body>;
862 
863     fn request(&self, _: Self::RequestBody, response_sender: Sender<ApiResponse>) -> ApiRequest {
864         Box::new(move |vmm| {
865             info!("API request event: VmDelete");
866 
867             let response = vmm
868                 .vm_delete()
869                 .map_err(ApiError::VmDelete)
870                 .map(|_| ApiResponsePayload::Empty);
871 
872             response_sender
873                 .send(response)
874                 .map_err(VmmError::ApiResponseSend)?;
875 
876             Ok(false)
877         })
878     }
879 
880     fn send(
881         &self,
882         api_evt: EventFd,
883         api_sender: Sender<ApiRequest>,
884         data: Self::RequestBody,
885     ) -> ApiResult<Self::ResponseBody> {
886         get_response_body(self, api_evt, api_sender, data)
887     }
888 }
889 
890 pub struct VmInfo;
891 
892 impl ApiAction for VmInfo {
893     type RequestBody = ();
894     type ResponseBody = VmInfoResponse;
895 
896     fn request(&self, _: Self::RequestBody, response_sender: Sender<ApiResponse>) -> ApiRequest {
897         Box::new(move |vmm| {
898             info!("API request event: VmInfo");
899 
900             let response = vmm
901                 .vm_info()
902                 .map_err(ApiError::VmInfo)
903                 .map(ApiResponsePayload::VmInfo);
904 
905             response_sender
906                 .send(response)
907                 .map_err(VmmError::ApiResponseSend)?;
908 
909             Ok(false)
910         })
911     }
912 
913     fn send(
914         &self,
915         api_evt: EventFd,
916         api_sender: Sender<ApiRequest>,
917         data: (),
918     ) -> ApiResult<VmInfoResponse> {
919         let vm_info = get_response(self, api_evt, api_sender, data)?;
920 
921         match vm_info {
922             ApiResponsePayload::VmInfo(info) => Ok(info),
923             _ => Err(ApiError::ResponsePayloadType),
924         }
925     }
926 }
927 
928 pub struct VmPause;
929 
930 impl ApiAction for VmPause {
931     type RequestBody = ();
932     type ResponseBody = Option<Body>;
933 
934     fn request(&self, _: Self::RequestBody, response_sender: Sender<ApiResponse>) -> ApiRequest {
935         Box::new(move |vmm| {
936             info!("API request event: VmPause");
937 
938             let response = vmm
939                 .vm_pause()
940                 .map_err(ApiError::VmPause)
941                 .map(|_| ApiResponsePayload::Empty);
942 
943             response_sender
944                 .send(response)
945                 .map_err(VmmError::ApiResponseSend)?;
946 
947             Ok(false)
948         })
949     }
950 
951     fn send(
952         &self,
953         api_evt: EventFd,
954         api_sender: Sender<ApiRequest>,
955         data: Self::RequestBody,
956     ) -> ApiResult<Self::ResponseBody> {
957         get_response_body(self, api_evt, api_sender, data)
958     }
959 }
960 
961 pub struct VmPowerButton;
962 
963 impl ApiAction for VmPowerButton {
964     type RequestBody = ();
965     type ResponseBody = Option<Body>;
966 
967     fn request(&self, _: Self::RequestBody, response_sender: Sender<ApiResponse>) -> ApiRequest {
968         Box::new(move |vmm| {
969             info!("API request event: VmPowerButton");
970 
971             let response = vmm
972                 .vm_power_button()
973                 .map_err(ApiError::VmPowerButton)
974                 .map(|_| ApiResponsePayload::Empty);
975 
976             response_sender
977                 .send(response)
978                 .map_err(VmmError::ApiResponseSend)?;
979 
980             Ok(false)
981         })
982     }
983 
984     fn send(
985         &self,
986         api_evt: EventFd,
987         api_sender: Sender<ApiRequest>,
988         data: Self::RequestBody,
989     ) -> ApiResult<Self::ResponseBody> {
990         get_response_body(self, api_evt, api_sender, data)
991     }
992 }
993 
994 pub struct VmReboot;
995 
996 impl ApiAction for VmReboot {
997     type RequestBody = ();
998     type ResponseBody = Option<Body>;
999 
1000     fn request(&self, _: Self::RequestBody, response_sender: Sender<ApiResponse>) -> ApiRequest {
1001         Box::new(move |vmm| {
1002             info!("API request event: VmReboot");
1003 
1004             let response = vmm
1005                 .vm_reboot()
1006                 .map_err(ApiError::VmReboot)
1007                 .map(|_| ApiResponsePayload::Empty);
1008 
1009             response_sender
1010                 .send(response)
1011                 .map_err(VmmError::ApiResponseSend)?;
1012 
1013             Ok(false)
1014         })
1015     }
1016 
1017     fn send(
1018         &self,
1019         api_evt: EventFd,
1020         api_sender: Sender<ApiRequest>,
1021         data: Self::RequestBody,
1022     ) -> ApiResult<Self::ResponseBody> {
1023         get_response_body(self, api_evt, api_sender, data)
1024     }
1025 }
1026 
1027 pub struct VmReceiveMigration;
1028 
1029 impl ApiAction for VmReceiveMigration {
1030     type RequestBody = VmReceiveMigrationData;
1031     type ResponseBody = Option<Body>;
1032 
1033     fn request(&self, data: Self::RequestBody, response_sender: Sender<ApiResponse>) -> ApiRequest {
1034         Box::new(move |vmm| {
1035             info!("API request event: VmReceiveMigration {:?}", data);
1036 
1037             let response = vmm
1038                 .vm_receive_migration(data)
1039                 .map_err(ApiError::VmReceiveMigration)
1040                 .map(|_| ApiResponsePayload::Empty);
1041 
1042             response_sender
1043                 .send(response)
1044                 .map_err(VmmError::ApiResponseSend)?;
1045 
1046             Ok(false)
1047         })
1048     }
1049 
1050     fn send(
1051         &self,
1052         api_evt: EventFd,
1053         api_sender: Sender<ApiRequest>,
1054         data: Self::RequestBody,
1055     ) -> ApiResult<Self::ResponseBody> {
1056         get_response_body(self, api_evt, api_sender, data)
1057     }
1058 }
1059 
1060 pub struct VmRemoveDevice;
1061 
1062 impl ApiAction for VmRemoveDevice {
1063     type RequestBody = VmRemoveDeviceData;
1064     type ResponseBody = Option<Body>;
1065 
1066     fn request(
1067         &self,
1068         remove_device_data: Self::RequestBody,
1069         response_sender: Sender<ApiResponse>,
1070     ) -> ApiRequest {
1071         Box::new(move |vmm| {
1072             info!("API request event: VmRemoveDevice {:?}", remove_device_data);
1073 
1074             let response = vmm
1075                 .vm_remove_device(remove_device_data.id)
1076                 .map_err(ApiError::VmRemoveDevice)
1077                 .map(|_| ApiResponsePayload::Empty);
1078 
1079             response_sender
1080                 .send(response)
1081                 .map_err(VmmError::ApiResponseSend)?;
1082 
1083             Ok(false)
1084         })
1085     }
1086 
1087     fn send(
1088         &self,
1089         api_evt: EventFd,
1090         api_sender: Sender<ApiRequest>,
1091         data: Self::RequestBody,
1092     ) -> ApiResult<Self::ResponseBody> {
1093         get_response_body(self, api_evt, api_sender, data)
1094     }
1095 }
1096 
1097 pub struct VmResize;
1098 
1099 impl ApiAction for VmResize {
1100     type RequestBody = VmResizeData;
1101     type ResponseBody = Option<Body>;
1102 
1103     fn request(
1104         &self,
1105         resize_data: Self::RequestBody,
1106         response_sender: Sender<ApiResponse>,
1107     ) -> ApiRequest {
1108         Box::new(move |vmm| {
1109             info!("API request event: VmResize {:?}", resize_data);
1110 
1111             let response = vmm
1112                 .vm_resize(
1113                     resize_data.desired_vcpus,
1114                     resize_data.desired_ram,
1115                     resize_data.desired_balloon,
1116                 )
1117                 .map_err(ApiError::VmResize)
1118                 .map(|_| ApiResponsePayload::Empty);
1119 
1120             response_sender
1121                 .send(response)
1122                 .map_err(VmmError::ApiResponseSend)?;
1123 
1124             Ok(false)
1125         })
1126     }
1127 
1128     fn send(
1129         &self,
1130         api_evt: EventFd,
1131         api_sender: Sender<ApiRequest>,
1132         data: Self::RequestBody,
1133     ) -> ApiResult<Self::ResponseBody> {
1134         get_response_body(self, api_evt, api_sender, data)
1135     }
1136 }
1137 
1138 pub struct VmResizeZone;
1139 
1140 impl ApiAction for VmResizeZone {
1141     type RequestBody = VmResizeZoneData;
1142     type ResponseBody = Option<Body>;
1143 
1144     fn request(
1145         &self,
1146         resize_zone_data: Self::RequestBody,
1147         response_sender: Sender<ApiResponse>,
1148     ) -> ApiRequest {
1149         Box::new(move |vmm| {
1150             info!("API request event: VmResizeZone {:?}", resize_zone_data);
1151 
1152             let response = vmm
1153                 .vm_resize_zone(resize_zone_data.id, resize_zone_data.desired_ram)
1154                 .map_err(ApiError::VmResizeZone)
1155                 .map(|_| ApiResponsePayload::Empty);
1156 
1157             response_sender
1158                 .send(response)
1159                 .map_err(VmmError::ApiResponseSend)?;
1160 
1161             Ok(false)
1162         })
1163     }
1164 
1165     fn send(
1166         &self,
1167         api_evt: EventFd,
1168         api_sender: Sender<ApiRequest>,
1169         data: Self::RequestBody,
1170     ) -> ApiResult<Self::ResponseBody> {
1171         get_response_body(self, api_evt, api_sender, data)
1172     }
1173 }
1174 
1175 pub struct VmRestore;
1176 
1177 impl ApiAction for VmRestore {
1178     type RequestBody = RestoreConfig;
1179     type ResponseBody = Option<Body>;
1180 
1181     fn request(
1182         &self,
1183         config: Self::RequestBody,
1184         response_sender: Sender<ApiResponse>,
1185     ) -> ApiRequest {
1186         Box::new(move |vmm| {
1187             info!("API request event: VmRestore {:?}", config);
1188 
1189             let response = vmm
1190                 .vm_restore(config)
1191                 .map_err(ApiError::VmRestore)
1192                 .map(|_| ApiResponsePayload::Empty);
1193 
1194             response_sender
1195                 .send(response)
1196                 .map_err(VmmError::ApiResponseSend)?;
1197 
1198             Ok(false)
1199         })
1200     }
1201 
1202     fn send(
1203         &self,
1204         api_evt: EventFd,
1205         api_sender: Sender<ApiRequest>,
1206         data: Self::RequestBody,
1207     ) -> ApiResult<Self::ResponseBody> {
1208         get_response_body(self, api_evt, api_sender, data)
1209     }
1210 }
1211 
1212 pub struct VmResume;
1213 
1214 impl ApiAction for VmResume {
1215     type RequestBody = ();
1216     type ResponseBody = Option<Body>;
1217 
1218     fn request(&self, _: Self::RequestBody, response_sender: Sender<ApiResponse>) -> ApiRequest {
1219         Box::new(move |vmm| {
1220             info!("API request event: VmResume");
1221 
1222             let response = vmm
1223                 .vm_resume()
1224                 .map_err(ApiError::VmResume)
1225                 .map(|_| ApiResponsePayload::Empty);
1226 
1227             response_sender
1228                 .send(response)
1229                 .map_err(VmmError::ApiResponseSend)?;
1230 
1231             Ok(false)
1232         })
1233     }
1234 
1235     fn send(
1236         &self,
1237         api_evt: EventFd,
1238         api_sender: Sender<ApiRequest>,
1239         data: Self::RequestBody,
1240     ) -> ApiResult<Self::ResponseBody> {
1241         get_response_body(self, api_evt, api_sender, data)
1242     }
1243 }
1244 
1245 pub struct VmSendMigration;
1246 
1247 impl ApiAction for VmSendMigration {
1248     type RequestBody = VmSendMigrationData;
1249     type ResponseBody = Option<Body>;
1250 
1251     fn request(&self, data: Self::RequestBody, response_sender: Sender<ApiResponse>) -> ApiRequest {
1252         Box::new(move |vmm| {
1253             info!("API request event: VmSendMigration {:?}", data);
1254 
1255             let response = vmm
1256                 .vm_send_migration(data)
1257                 .map_err(ApiError::VmSendMigration)
1258                 .map(|_| ApiResponsePayload::Empty);
1259 
1260             response_sender
1261                 .send(response)
1262                 .map_err(VmmError::ApiResponseSend)?;
1263 
1264             Ok(false)
1265         })
1266     }
1267 
1268     fn send(
1269         &self,
1270         api_evt: EventFd,
1271         api_sender: Sender<ApiRequest>,
1272         data: Self::RequestBody,
1273     ) -> ApiResult<Self::ResponseBody> {
1274         get_response_body(self, api_evt, api_sender, data)
1275     }
1276 }
1277 
1278 pub struct VmShutdown;
1279 
1280 impl ApiAction for VmShutdown {
1281     type RequestBody = ();
1282     type ResponseBody = Option<Body>;
1283 
1284     fn request(
1285         &self,
1286         config: Self::RequestBody,
1287         response_sender: Sender<ApiResponse>,
1288     ) -> ApiRequest {
1289         Box::new(move |vmm| {
1290             info!("API request event: VmShutdown {:?}", config);
1291 
1292             let response = vmm
1293                 .vm_shutdown()
1294                 .map_err(ApiError::VmShutdown)
1295                 .map(|_| ApiResponsePayload::Empty);
1296 
1297             response_sender
1298                 .send(response)
1299                 .map_err(VmmError::ApiResponseSend)?;
1300 
1301             Ok(false)
1302         })
1303     }
1304 
1305     fn send(
1306         &self,
1307         api_evt: EventFd,
1308         api_sender: Sender<ApiRequest>,
1309         data: Self::RequestBody,
1310     ) -> ApiResult<Self::ResponseBody> {
1311         get_response_body(self, api_evt, api_sender, data)
1312     }
1313 }
1314 
1315 pub struct VmSnapshot;
1316 
1317 impl ApiAction for VmSnapshot {
1318     type RequestBody = VmSnapshotConfig;
1319     type ResponseBody = Option<Body>;
1320 
1321     fn request(
1322         &self,
1323         config: Self::RequestBody,
1324         response_sender: Sender<ApiResponse>,
1325     ) -> ApiRequest {
1326         Box::new(move |vmm| {
1327             info!("API request event: VmSnapshot {:?}", config);
1328 
1329             let response = vmm
1330                 .vm_snapshot(&config.destination_url)
1331                 .map_err(ApiError::VmSnapshot)
1332                 .map(|_| ApiResponsePayload::Empty);
1333 
1334             response_sender
1335                 .send(response)
1336                 .map_err(VmmError::ApiResponseSend)?;
1337 
1338             Ok(false)
1339         })
1340     }
1341 
1342     fn send(
1343         &self,
1344         api_evt: EventFd,
1345         api_sender: Sender<ApiRequest>,
1346         data: Self::RequestBody,
1347     ) -> ApiResult<Self::ResponseBody> {
1348         get_response_body(self, api_evt, api_sender, data)
1349     }
1350 }
1351 
1352 pub struct VmmPing;
1353 
1354 impl ApiAction for VmmPing {
1355     type RequestBody = ();
1356     type ResponseBody = VmmPingResponse;
1357 
1358     fn request(&self, _: Self::RequestBody, response_sender: Sender<ApiResponse>) -> ApiRequest {
1359         Box::new(move |vmm| {
1360             info!("API request event: VmmPing");
1361 
1362             let response = ApiResponsePayload::VmmPing(vmm.vmm_ping());
1363 
1364             response_sender
1365                 .send(Ok(response))
1366                 .map_err(VmmError::ApiResponseSend)?;
1367 
1368             Ok(false)
1369         })
1370     }
1371 
1372     fn send(
1373         &self,
1374         api_evt: EventFd,
1375         api_sender: Sender<ApiRequest>,
1376         data: (),
1377     ) -> ApiResult<VmmPingResponse> {
1378         let vmm_pong = get_response(self, api_evt, api_sender, data)?;
1379 
1380         match vmm_pong {
1381             ApiResponsePayload::VmmPing(pong) => Ok(pong),
1382             _ => Err(ApiError::ResponsePayloadType),
1383         }
1384     }
1385 }
1386 
1387 pub struct VmmShutdown;
1388 
1389 impl ApiAction for VmmShutdown {
1390     type RequestBody = ();
1391     type ResponseBody = ();
1392 
1393     fn request(&self, _: Self::RequestBody, response_sender: Sender<ApiResponse>) -> ApiRequest {
1394         Box::new(move |vmm| {
1395             info!("API request event: VmmShutdown");
1396 
1397             let response = vmm
1398                 .vmm_shutdown()
1399                 .map_err(ApiError::VmmShutdown)
1400                 .map(|_| ApiResponsePayload::Empty);
1401 
1402             response_sender
1403                 .send(response)
1404                 .map_err(VmmError::ApiResponseSend)?;
1405 
1406             Ok(true)
1407         })
1408     }
1409 
1410     fn send(&self, api_evt: EventFd, api_sender: Sender<ApiRequest>, data: ()) -> ApiResult<()> {
1411         get_response(self, api_evt, api_sender, data)?;
1412 
1413         Ok(())
1414     }
1415 }
1416 
1417 pub struct VmNmi;
1418 
1419 impl ApiAction for VmNmi {
1420     type RequestBody = ();
1421     type ResponseBody = Option<Body>;
1422 
1423     fn request(&self, _: Self::RequestBody, response_sender: Sender<ApiResponse>) -> ApiRequest {
1424         Box::new(move |vmm| {
1425             info!("API request event: VmNmi");
1426 
1427             let response = vmm
1428                 .vm_nmi()
1429                 .map_err(ApiError::VmNmi)
1430                 .map(|_| ApiResponsePayload::Empty);
1431 
1432             response_sender
1433                 .send(response)
1434                 .map_err(VmmError::ApiResponseSend)?;
1435 
1436             Ok(false)
1437         })
1438     }
1439 
1440     fn send(
1441         &self,
1442         api_evt: EventFd,
1443         api_sender: Sender<ApiRequest>,
1444         data: Self::RequestBody,
1445     ) -> ApiResult<Self::ResponseBody> {
1446         get_response_body(self, api_evt, api_sender, data)
1447     }
1448 }
1449