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