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