vmm: introduce nice error messages on exit (CHV and ch-remote)

With the foundations of each error type implementing std::error::Error,
we can now nicely walk the `.source()` chain and print an error trace.

This commit introduces improved user-facing error printing when:
- Cloud Hypervisor fails with an error
- ch-remote fails (client error)
- ch-remote fails (remote error)

The additional context is a clear improvement in UX for both users and
developers. In the following example, the new behaviour is shown for
a direct invocation of Cloud Hypervisor leading to a failure. This
looks similar for ch-remote.

```
Old Style
`target/release/cloud-hypervisor --api-socket /tmp/chv2.sock --kernel /etc/bootitems/linux/kernel_minimal/stable.bzImage --cmdline console=ttyS0 --serial tty --console off --disk path=img.raw --initramfs /etc/bootitems/linux/initrd_minimal/default`

Error booting VM: VmBoot(LockingError(BlockError(LockDiskImage(AlreadyLocked)))
```

```
`target/release/cloud-hypervisor --api-socket /tmp/chv2.sock --kernel /etc/bootitems/linux/kernel_minimal/stable.bzImage --cmdline console=ttyS0 --serial tty --console off --disk path=img.raw --initramfs
/etc/bootitems/linux/initrd_minimal/default`

Error: Cloud Hypervisor exited with the following chain of errors:
  0: Error booting VM
  1: The VM could not boot
  2: Error locking disk images: Another instance likely holds a lock
  3: Cannot lock images of all block devices
  4: Failed to get Write lock for disk image: ./img.raw
  5: The file is already locked

Debug Info: VmBoot(VmBoot(LockingError(DiskLockError(LockDiskImage { error: AlreadyLocked, lock_type: Write, path: "./raw_disk.bin" })))
```

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
This commit is contained in:
Philipp Schuster
2025-05-19 11:23:47 +02:00
committed by Rob Bradford
parent 1433763d40
commit 060c9de07f
4 changed files with 43 additions and 5 deletions

View File

@@ -69,9 +69,20 @@ pub enum HttpError {
const HTTP_ROOT: &str = "/api/v1";
/// Creates the error response's body meant to be sent back to an API client.
/// The error message contained in the response is supposed to be user-facing,
/// thus insightful and helpful while balancing technical accuracy and
/// simplicity.
pub fn error_response(error: HttpError, status: StatusCode) -> Response {
let mut response = Response::new(Version::Http11, status);
response.set_body(Body::new(format!("{error}")));
// We must use debug output here without `#`, as it is currently the only
// feasible option to get all relevant error details to the receiver,
// i.e., ch-remote, in a balanced form. The Display impl is not guaranteed
// to hold all relevant or helpful data.
//
// TODO: We might print a nice error chain here as well and send it to the
// remote, similar to the normal error reporting?
response.set_body(Body::new(format!("{error:?}")));
response
}