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