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