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