vmm: api: Return 404 (not 500) for unknown device/disk id

Map NoDeviceToRemove and DeviceManager(UnknownDeviceId) to 404 Not
Found, update the OpenAPI 404 descriptions, and add unit tests.

Signed-off-by: Stepan Rabotkin <epicstyt@gmail.com>
Assisted-by: Claude:Opus-4.8
This commit is contained in:
Stepan Rabotkin
2026-07-27 14:26:39 +03:00
committed by Rob Bradford
parent a5e145bdef
commit 5e01807fa2
2 changed files with 48 additions and 3 deletions

View File

@@ -33,6 +33,7 @@ use crate::api::{
VmPause, VmPowerButton, VmReboot, VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeDisk,
VmResizeZone, VmRestore, VmResume, VmSendMigration, VmShutdown, VmSnapshot,
};
use crate::device_manager::DeviceManagerError;
use crate::landlock::Landlock;
use crate::seccomp_filters::{Thread, get_seccomp_filter};
use crate::util::{error_chain_messages, flatten_error_chain_to_string};
@@ -87,7 +88,12 @@ impl HttpError {
/// Maps an [`ApiError`] to an HTTP [`StatusCode`].
fn api_error_status_code(error: &ApiError) -> StatusCode {
match error.source().and_then(|e| e.downcast_ref::<VmError>()) {
Some(VmError::VmNotCreated | VmError::VmMissingConfig) => StatusCode::NotFound,
Some(
VmError::VmNotCreated
| VmError::VmMissingConfig
| VmError::NoDeviceToRemove(_)
| VmError::DeviceManager(DeviceManagerError::UnknownDeviceId(_)),
) => StatusCode::NotFound,
_ => StatusCode::InternalServerError,
}
}
@@ -495,3 +501,42 @@ pub fn http_api_graceful_shutdown(http_handle: HttpApiHandle) -> Result<()> {
api_shutdown_fd.write(1).unwrap();
api_thread.join().map_err(VmmError::ThreadCleanup)?
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_missing_target_maps_to_not_found() {
assert_eq!(
api_error_status_code(&ApiError::VmInfo(VmError::VmNotCreated)),
StatusCode::NotFound
);
assert_eq!(
api_error_status_code(&ApiError::VmRemoveDevice(VmError::NoDeviceToRemove(
"dev0".to_string()
))),
StatusCode::NotFound
);
assert_eq!(
api_error_status_code(&ApiError::VmRemoveDevice(VmError::DeviceManager(
DeviceManagerError::UnknownDeviceId("dev0".to_string())
))),
StatusCode::NotFound
);
assert_eq!(
api_error_status_code(&ApiError::VmResizeDisk(VmError::DeviceManager(
DeviceManagerError::UnknownDeviceId("disk0".to_string())
))),
StatusCode::NotFound
);
}
#[test]
fn test_other_errors_map_to_internal_server_error() {
assert_eq!(
api_error_status_code(&ApiError::VmRemoveDevice(VmError::VmMigrating)),
StatusCode::InternalServerError
);
}
}

View File

@@ -179,7 +179,7 @@ paths:
204:
description: The disk was successfully resized.
404:
description: The disk could not be resized because the VM is not created.
description: The disk could not be resized because the VM is not created, or no disk with the given identifier exists.
500:
description: The disk could not be resized.
@@ -237,7 +237,7 @@ paths:
204:
description: The device was successfully removed from the VM instance.
404:
description: The device could not be removed from the VM instance.
description: The device could not be removed because the VM is not created, or no device with the given identifier exists.
/vm.add-disk:
put: