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