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