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