From d0225fe68fd14146bacc3be26f0b7e548ce9c239 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= Date: Fri, 25 Apr 2025 20:21:18 +0200 Subject: [PATCH] vmm: api: Be more specific on "Still pending remove vcpu" errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although the CPU manager gives us a quite descriptive error, on the application side (the part calling Cloud Hypervisor) we have absolutely no way to distinguish such error from any other error that may happen when resizing a VM. With this in mind, let's be more specific and return a TooManyRequests (429) error, allowing the caller to have a chance to decide whether they want to retry the operation or not. https://datatracker.ietf.org/doc/html/rfc6585#section-4 Signed-off-by: Fabiano FidĂȘncio --- vmm/src/api/http/http_endpoint.rs | 33 +++++++++++++++++++++-- vmm/src/api/http/mod.rs | 5 ++++ vmm/src/api/openapi/cloud-hypervisor.yaml | 2 ++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/vmm/src/api/http/http_endpoint.rs b/vmm/src/api/http/http_endpoint.rs index 65da20674..ff1de5629 100644 --- a/vmm/src/api/http/http_endpoint.rs +++ b/vmm/src/api/http/http_endpoint.rs @@ -15,12 +15,14 @@ use crate::api::http::{error_response, EndpointHandler, HttpError}; #[cfg(all(target_arch = "x86_64", feature = "guest_debug"))] use crate::api::VmCoredump; use crate::api::{ - AddDisk, ApiAction, ApiRequest, NetConfig, VmAddDevice, VmAddFs, VmAddNet, VmAddPmem, + AddDisk, ApiAction, ApiError, ApiRequest, NetConfig, VmAddDevice, VmAddFs, VmAddNet, VmAddPmem, VmAddUserDevice, VmAddVdpa, VmAddVsock, VmBoot, VmConfig, VmCounters, VmDelete, VmNmi, VmPause, VmPowerButton, VmReboot, VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeZone, VmRestore, VmResume, VmSendMigration, VmShutdown, VmSnapshot, }; use crate::config::RestoreConfig; +use crate::cpu::Error as CpuError; +use crate::vm::Error as VmError; // /api/v1/vm.create handler pub struct VmCreate {} @@ -183,7 +185,6 @@ vm_action_put_handler_body!(VmAddVdpa); vm_action_put_handler_body!(VmAddVsock); vm_action_put_handler_body!(VmAddUserDevice); vm_action_put_handler_body!(VmRemoveDevice); -vm_action_put_handler_body!(VmResize); vm_action_put_handler_body!(VmResizeZone); vm_action_put_handler_body!(VmSnapshot); vm_action_put_handler_body!(VmReceiveMigration); @@ -220,6 +221,34 @@ impl PutHandler for VmAddNet { impl GetHandler for VmAddNet {} +impl PutHandler for VmResize { + fn handle_request( + &'static self, + api_notifier: EventFd, + api_sender: Sender, + body: &Option, + _files: Vec, + ) -> std::result::Result, HttpError> { + if let Some(body) = body { + self.send( + api_notifier, + api_sender, + serde_json::from_slice(body.raw())?, + ) + .map_err(|e| match e { + ApiError::VmResize(VmError::CpuManager(CpuError::VcpuPendingRemovedVcpu)) => { + HttpError::TooManyRequests + } + _ => HttpError::ApiError(e), + }) + } else { + Err(HttpError::BadRequest) + } + } +} + +impl GetHandler for VmResize {} + impl PutHandler for VmRestore { fn handle_request( &'static self, diff --git a/vmm/src/api/http/mod.rs b/vmm/src/api/http/mod.rs index a105fc0cf..2c4eb4c93 100644 --- a/vmm/src/api/http/mod.rs +++ b/vmm/src/api/http/mod.rs @@ -52,6 +52,9 @@ pub enum HttpError { /// Undefined endpoints NotFound, + /// Too many requests + TooManyRequests, + /// Internal Server Error InternalServerError, @@ -65,6 +68,7 @@ impl Display for HttpError { match self { BadRequest => write!(f, "Bad Request"), NotFound => write!(f, "Not Found"), + TooManyRequests => write!(f, "Too Many Requests"), InternalServerError => write!(f, "Internal Server Error"), SerdeJsonDeserialize(serde_error) => write!(f, "{}", serde_error), ApiError(api_error) => write!(f, "{}", api_error), @@ -125,6 +129,7 @@ pub trait EndpointHandler { Err(e @ HttpError::SerdeJsonDeserialize(_)) => { error_response(e, StatusCode::BadRequest) } + Err(e @ HttpError::TooManyRequests) => error_response(e, StatusCode::TooManyRequests), Err(e) => error_response(e, StatusCode::InternalServerError), } } diff --git a/vmm/src/api/openapi/cloud-hypervisor.yaml b/vmm/src/api/openapi/cloud-hypervisor.yaml index e723bee8f..15f99d303 100644 --- a/vmm/src/api/openapi/cloud-hypervisor.yaml +++ b/vmm/src/api/openapi/cloud-hypervisor.yaml @@ -160,6 +160,8 @@ paths: description: The VM instance was successfully resized. 404: description: The VM instance could not be resized because it is not created. + 429: + description: The VM instance could not be resized because a cpu removal is still pending. /vm.resize-zone: put: