vmm: api: Simplify error reporting from HTTP to internal API calls

Use a single enum member for representing errors from the internal API.
This avoids the ugly duplication of the API call name in the error
message:

e.g.

$ target/debug/ch-remote --api-socket /tmp/api resize --cpus 2
Error running command: Server responded with an error: InternalServerError: VmResize(VmResize(CpuManager(DesiredVCpuCountExceedsMax)))

Becomes:

$ target/debug/ch-remote --api-socket /tmp/api resize --cpus 2
Error running command: Server responded with an error: InternalServerError: ApiError(VmResize(CpuManager(DesiredVCpuCountExceedsMax)))

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2022-04-20 15:54:26 +01:00
parent 88ed85247e
commit 4ca066f077
2 changed files with 31 additions and 142 deletions

View File

@ -36,89 +36,8 @@ pub enum HttpError {
/// Internal Server Error /// Internal Server Error
InternalServerError, InternalServerError,
/// Could not create a VM /// Error from internal API
VmCreate(ApiError), ApiError(ApiError),
/// Could not boot a VM
VmBoot(ApiError),
/// Could not delete a VM
VmDelete(ApiError),
/// Could not get the VM information
VmInfo(ApiError),
/// Could not pause the VM
VmPause(ApiError),
/// Could not pause the VM
VmResume(ApiError),
/// Could not shut a VM down
VmShutdown(ApiError),
/// Could not reboot a VM
VmReboot(ApiError),
/// Could not snapshot a VM
VmSnapshot(ApiError),
/// Could not restore a VM
VmRestore(ApiError),
/// Could not act on a VM
VmAction(ApiError),
/// Could not resize a VM
VmResize(ApiError),
/// Could not resize a memory zone
VmResizeZone(ApiError),
/// Could not add a device to a VM
VmAddDevice(ApiError),
/// Could not add a user device to the VM
VmAddUserDevice(ApiError),
/// Could not remove a device from a VM
VmRemoveDevice(ApiError),
/// Could not shut the VMM down
VmmShutdown(ApiError),
/// Could not handle VMM ping
VmmPing(ApiError),
/// Could not add a disk to a VM
VmAddDisk(ApiError),
/// Could not add a fs to a VM
VmAddFs(ApiError),
/// Could not add a pmem device to a VM
VmAddPmem(ApiError),
/// Could not add a network device to a VM
VmAddNet(ApiError),
/// Could not add a vDPA device to a VM
VmAddVdpa(ApiError),
/// Could not add a vsock device to a VM
VmAddVsock(ApiError),
/// Could not get counters from VM
VmCounters(ApiError),
/// Error setting up migration received
VmReceiveMigration(ApiError),
/// Error setting up migration sender
VmSendMigration(ApiError),
/// Error activating power button
VmPowerButton(ApiError),
} }
impl From<serde_json::Error> for HttpError { impl From<serde_json::Error> for HttpError {

View File

@ -43,7 +43,7 @@ impl EndpointHandler for VmCreate {
// Call vm_create() // Call vm_create()
match vm_create(api_notifier, api_sender, Arc::new(Mutex::new(vm_config))) match vm_create(api_notifier, api_sender, Arc::new(Mutex::new(vm_config)))
.map_err(HttpError::VmCreate) .map_err(HttpError::ApiError)
{ {
Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), Ok(_) => Response::new(Version::Http11, StatusCode::NoContent),
Err(e) => error_response(e, StatusCode::InternalServerError), Err(e) => error_response(e, StatusCode::InternalServerError),
@ -85,30 +85,22 @@ impl EndpointHandler for VmActionHandler {
api_notifier, api_notifier,
api_sender, api_sender,
Arc::new(serde_json::from_slice(body.raw())?), Arc::new(serde_json::from_slice(body.raw())?),
) ),
.map_err(HttpError::VmAddDevice),
AddDisk(_) => vm_add_disk( AddDisk(_) => vm_add_disk(
api_notifier, api_notifier,
api_sender, api_sender,
Arc::new(serde_json::from_slice(body.raw())?), Arc::new(serde_json::from_slice(body.raw())?),
) ),
.map_err(HttpError::VmAddDisk),
AddFs(_) => vm_add_fs( AddFs(_) => vm_add_fs(
api_notifier, api_notifier,
api_sender, api_sender,
Arc::new(serde_json::from_slice(body.raw())?), Arc::new(serde_json::from_slice(body.raw())?),
) ),
.map_err(HttpError::VmAddFs),
AddPmem(_) => vm_add_pmem( AddPmem(_) => vm_add_pmem(
api_notifier, api_notifier,
api_sender, api_sender,
Arc::new(serde_json::from_slice(body.raw())?), Arc::new(serde_json::from_slice(body.raw())?),
) ),
.map_err(HttpError::VmAddPmem),
AddNet(_) => { AddNet(_) => {
let mut net_cfg: NetConfig = serde_json::from_slice(body.raw())?; let mut net_cfg: NetConfig = serde_json::from_slice(body.raw())?;
// Update network config with optional files that might have // Update network config with optional files that might have
@ -118,95 +110,73 @@ impl EndpointHandler for VmActionHandler {
net_cfg.fds = Some(fds); net_cfg.fds = Some(fds);
} }
vm_add_net(api_notifier, api_sender, Arc::new(net_cfg)) vm_add_net(api_notifier, api_sender, Arc::new(net_cfg))
.map_err(HttpError::VmAddNet)
} }
AddVdpa(_) => vm_add_vdpa( AddVdpa(_) => vm_add_vdpa(
api_notifier, api_notifier,
api_sender, api_sender,
Arc::new(serde_json::from_slice(body.raw())?), Arc::new(serde_json::from_slice(body.raw())?),
) ),
.map_err(HttpError::VmAddVdpa),
AddVsock(_) => vm_add_vsock( AddVsock(_) => vm_add_vsock(
api_notifier, api_notifier,
api_sender, api_sender,
Arc::new(serde_json::from_slice(body.raw())?), Arc::new(serde_json::from_slice(body.raw())?),
) ),
.map_err(HttpError::VmAddVsock),
AddUserDevice(_) => vm_add_user_device( AddUserDevice(_) => vm_add_user_device(
api_notifier, api_notifier,
api_sender, api_sender,
Arc::new(serde_json::from_slice(body.raw())?), Arc::new(serde_json::from_slice(body.raw())?),
) ),
.map_err(HttpError::VmAddUserDevice),
RemoveDevice(_) => vm_remove_device( RemoveDevice(_) => vm_remove_device(
api_notifier, api_notifier,
api_sender, api_sender,
Arc::new(serde_json::from_slice(body.raw())?), Arc::new(serde_json::from_slice(body.raw())?),
) ),
.map_err(HttpError::VmRemoveDevice),
Resize(_) => vm_resize( Resize(_) => vm_resize(
api_notifier, api_notifier,
api_sender, api_sender,
Arc::new(serde_json::from_slice(body.raw())?), Arc::new(serde_json::from_slice(body.raw())?),
) ),
.map_err(HttpError::VmResize),
ResizeZone(_) => vm_resize_zone( ResizeZone(_) => vm_resize_zone(
api_notifier, api_notifier,
api_sender, api_sender,
Arc::new(serde_json::from_slice(body.raw())?), Arc::new(serde_json::from_slice(body.raw())?),
) ),
.map_err(HttpError::VmResizeZone),
Restore(_) => vm_restore( Restore(_) => vm_restore(
api_notifier, api_notifier,
api_sender, api_sender,
Arc::new(serde_json::from_slice(body.raw())?), Arc::new(serde_json::from_slice(body.raw())?),
) ),
.map_err(HttpError::VmRestore),
Snapshot(_) => vm_snapshot( Snapshot(_) => vm_snapshot(
api_notifier, api_notifier,
api_sender, api_sender,
Arc::new(serde_json::from_slice(body.raw())?), Arc::new(serde_json::from_slice(body.raw())?),
) ),
.map_err(HttpError::VmSnapshot),
ReceiveMigration(_) => vm_receive_migration( ReceiveMigration(_) => vm_receive_migration(
api_notifier, api_notifier,
api_sender, api_sender,
Arc::new(serde_json::from_slice(body.raw())?), Arc::new(serde_json::from_slice(body.raw())?),
) ),
.map_err(HttpError::VmReceiveMigration),
SendMigration(_) => vm_send_migration( SendMigration(_) => vm_send_migration(
api_notifier, api_notifier,
api_sender, api_sender,
Arc::new(serde_json::from_slice(body.raw())?), Arc::new(serde_json::from_slice(body.raw())?),
) ),
.map_err(HttpError::VmSendMigration),
_ => Err(HttpError::BadRequest), _ => return Err(HttpError::BadRequest),
} }
} else { } else {
match self.action { match self.action {
Boot => vm_boot(api_notifier, api_sender).map_err(HttpError::VmBoot), Boot => vm_boot(api_notifier, api_sender),
Delete => vm_delete(api_notifier, api_sender).map_err(HttpError::VmDelete), Delete => vm_delete(api_notifier, api_sender),
Shutdown => vm_shutdown(api_notifier, api_sender).map_err(HttpError::VmShutdown), Shutdown => vm_shutdown(api_notifier, api_sender),
Reboot => vm_reboot(api_notifier, api_sender).map_err(HttpError::VmReboot), Reboot => vm_reboot(api_notifier, api_sender),
Pause => vm_pause(api_notifier, api_sender).map_err(HttpError::VmPause), Pause => vm_pause(api_notifier, api_sender),
Resume => vm_resume(api_notifier, api_sender).map_err(HttpError::VmResume), Resume => vm_resume(api_notifier, api_sender),
PowerButton => { PowerButton => vm_power_button(api_notifier, api_sender),
vm_power_button(api_notifier, api_sender).map_err(HttpError::VmPowerButton) _ => return Err(HttpError::BadRequest),
}
_ => Err(HttpError::BadRequest),
} }
} }
.map_err(HttpError::ApiError)
} }
fn get_handler( fn get_handler(
@ -217,7 +187,7 @@ impl EndpointHandler for VmActionHandler {
) -> std::result::Result<Option<Body>, HttpError> { ) -> std::result::Result<Option<Body>, HttpError> {
use VmAction::*; use VmAction::*;
match self.action { match self.action {
Counters => vm_counters(api_notifier, api_sender).map_err(HttpError::VmCounters), Counters => vm_counters(api_notifier, api_sender).map_err(HttpError::ApiError),
_ => Err(HttpError::BadRequest), _ => Err(HttpError::BadRequest),
} }
} }
@ -234,7 +204,7 @@ impl EndpointHandler for VmInfo {
api_sender: Sender<ApiRequest>, api_sender: Sender<ApiRequest>,
) -> Response { ) -> Response {
match req.method() { match req.method() {
Method::Get => match vm_info(api_notifier, api_sender).map_err(HttpError::VmInfo) { Method::Get => match vm_info(api_notifier, api_sender).map_err(HttpError::ApiError) {
Ok(info) => { Ok(info) => {
let mut response = Response::new(Version::Http11, StatusCode::OK); let mut response = Response::new(Version::Http11, StatusCode::OK);
let info_serialized = serde_json::to_string(&info).unwrap(); let info_serialized = serde_json::to_string(&info).unwrap();
@ -260,7 +230,7 @@ impl EndpointHandler for VmmPing {
api_sender: Sender<ApiRequest>, api_sender: Sender<ApiRequest>,
) -> Response { ) -> Response {
match req.method() { match req.method() {
Method::Get => match vmm_ping(api_notifier, api_sender).map_err(HttpError::VmmPing) { Method::Get => match vmm_ping(api_notifier, api_sender).map_err(HttpError::ApiError) {
Ok(pong) => { Ok(pong) => {
let mut response = Response::new(Version::Http11, StatusCode::OK); let mut response = Response::new(Version::Http11, StatusCode::OK);
let info_serialized = serde_json::to_string(&pong).unwrap(); let info_serialized = serde_json::to_string(&pong).unwrap();
@ -288,7 +258,7 @@ impl EndpointHandler for VmmShutdown {
) -> Response { ) -> Response {
match req.method() { match req.method() {
Method::Put => { Method::Put => {
match vmm_shutdown(api_notifier, api_sender).map_err(HttpError::VmmShutdown) { match vmm_shutdown(api_notifier, api_sender).map_err(HttpError::ApiError) {
Ok(_) => Response::new(Version::Http11, StatusCode::OK), Ok(_) => Response::new(Version::Http11, StatusCode::OK),
Err(e) => error_response(e, StatusCode::InternalServerError), Err(e) => error_response(e, StatusCode::InternalServerError),
} }