10cd3325aSSamuel Ortiz- [Cloud Hypervisor API](#cloud-hypervisor-api) 2072af956SRob Bradford - [External API](#external-api) 3072af956SRob Bradford - [REST API](#rest-api) 483914d80SOmer Faruk Bayram - [REST API Location and availability](#rest-api-location-and-availability) 583914d80SOmer Faruk Bayram - [REST API Endpoints](#rest-api-endpoints) 6072af956SRob Bradford - [Virtual Machine Manager (VMM) Actions](#virtual-machine-manager-vmm-actions) 7072af956SRob Bradford - [Virtual Machine (VM) Actions](#virtual-machine-vm-actions) 80cd3325aSSamuel Ortiz - [REST API Examples](#rest-api-examples) 9072af956SRob Bradford - [Create a Virtual Machine](#create-a-virtual-machine) 10072af956SRob Bradford - [Boot a Virtual Machine](#boot-a-virtual-machine) 11072af956SRob Bradford - [Dump a Virtual Machine Information](#dump-a-virtual-machine-information) 12072af956SRob Bradford - [Reboot a Virtual Machine](#reboot-a-virtual-machine) 13072af956SRob Bradford - [Shut a Virtual Machine Down](#shut-a-virtual-machine-down) 1483914d80SOmer Faruk Bayram - [D-Bus API](#d-bus-api) 1583914d80SOmer Faruk Bayram - [D-Bus API Location and availability](#d-bus-api-location-and-availability) 1683914d80SOmer Faruk Bayram - [D-Bus API Interface](#d-bus-api-interface) 17072af956SRob Bradford - [Command Line Interface](#command-line-interface) 1883914d80SOmer Faruk Bayram - [REST API, D-Bus API and CLI Architectural Relationship](#rest-api-and-cli-architectural-relationship) 19072af956SRob Bradford - [Internal API](#internal-api) 20072af956SRob Bradford - [Goals and Design](#goals-and-design) 21072af956SRob Bradford - [End to End Example](#end-to-end-example) 220cd3325aSSamuel Ortiz 230cd3325aSSamuel Ortiz# Cloud Hypervisor API 240cd3325aSSamuel Ortiz 250cd3325aSSamuel OrtizThe Cloud Hypervisor API is made of 2 distinct interfaces: 260cd3325aSSamuel Ortiz 2783914d80SOmer Faruk Bayram1. **The External API** This is the user facing API. Users and operators 2883914d80SOmer Faruk Bayram can control and manage the Cloud Hypervisor through various options 2983914d80SOmer Faruk Bayram including a REST API, a Command Line Interface (CLI) or a D-Bus based API, 3083914d80SOmer Faruk Bayram which is not compiled into Cloud Hypervisor by default. 3183914d80SOmer Faruk Bayram 320cd3325aSSamuel Ortiz1. **The internal API**, based on [rust's Multi-Producer, Single-Consumer (MPSC)](https://doc.rust-lang.org/std/sync/mpsc/) 330cd3325aSSamuel Ortiz module. This API is used internally by the Cloud Hypervisor threads to 340cd3325aSSamuel Ortiz communicate between each others. 350cd3325aSSamuel Ortiz 360cd3325aSSamuel OrtizThe goal of this document is to describe the Cloud Hypervisor API as a whole, 370cd3325aSSamuel Ortizand to outline how the internal and external APIs are architecturally related. 380cd3325aSSamuel Ortiz 390cd3325aSSamuel Ortiz## External API 400cd3325aSSamuel Ortiz 410cd3325aSSamuel Ortiz### REST API 420cd3325aSSamuel Ortiz 430cd3325aSSamuel OrtizThe Cloud Hypervisor [REST](https://en.wikipedia.org/wiki/Representational_state_transfer) 440cd3325aSSamuel OrtizAPI triggers VM and VMM specific actions, and as such it is designed as a 450cd3325aSSamuel Ortizcollection of RPC-style, static methods. 460cd3325aSSamuel Ortiz 470cd3325aSSamuel OrtizThe API is [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md) 4883914d80SOmer Faruk Bayramcompliant. Please consult the [Cloud Hypervisor OpenAPI Document](https://raw.githubusercontent.com/cloud-hypervisor/cloud-hypervisor/master/vmm/src/api/openapi/cloud-hypervisor.yaml) 4983914d80SOmer Faruk Bayramfor more details about the API payloads and responses. 500cd3325aSSamuel Ortiz 5183914d80SOmer Faruk Bayram#### REST API Location and availability 520cd3325aSSamuel Ortiz 53*1bc74e43SAndrew ConsroeThe REST API, if enabled, is available as soon as the Cloud Hypervisor binary is started, 54*1bc74e43SAndrew Consroethrough either a local UNIX socket as given in the Cloud Hypervisor option `--api-socket path=...` 55*1bc74e43SAndrew Consroeor a fd with `--api-socket fd=...`. 560cd3325aSSamuel Ortiz 570cd3325aSSamuel Ortiz``` 58*1bc74e43SAndrew Consroe$ ./target/debug/cloud-hypervisor --api-socket path=/tmp/cloud-hypervisor.sock 590cd3325aSSamuel OrtizCloud Hypervisor Guest 600cd3325aSSamuel Ortiz API server: /tmp/cloud-hypervisor.sock 610cd3325aSSamuel Ortiz vCPUs: 1 620cd3325aSSamuel Ortiz Memory: 512 MB 630cd3325aSSamuel Ortiz Kernel: None 640cd3325aSSamuel Ortiz Kernel cmdline: 650cd3325aSSamuel Ortiz Disk(s): None 660cd3325aSSamuel Ortiz``` 670cd3325aSSamuel Ortiz 6883914d80SOmer Faruk Bayram#### REST API Endpoints 690cd3325aSSamuel Ortiz 700cd3325aSSamuel OrtizThe Cloud Hypervisor API exposes the following actions through its endpoints: 710cd3325aSSamuel Ortiz 7283914d80SOmer Faruk Bayram##### Virtual Machine Manager (VMM) Actions 730cd3325aSSamuel Ortiz 74072af956SRob Bradford| Action | Endpoint | Request Body | Response Body | Prerequisites | 75072af956SRob Bradford| ----------------------------------- | --------------- | ------------ | -------------------------- | ------------------ | 76072af956SRob Bradford| Check for the REST API availability | `/vmm.ping` | N/A | `/schemas/VmmPingResponse` | N/A | 77072af956SRob Bradford| Shut the VMM down | `/vmm.shutdown` | N/A | N/A | The VMM is running | 780cd3325aSSamuel Ortiz 7983914d80SOmer Faruk Bayram##### Virtual Machine (VM) Actions 800cd3325aSSamuel Ortiz 81072af956SRob Bradford| Action | Endpoint | Request Body | Response Body | Prerequisites | 82e7d52fc7SOmer Faruk Bayram| ---------------------------------- | ----------------------- | ------------------------------- | ------------------------ | ------------------------------------------------------ | 83072af956SRob Bradford| Create the VM | `/vm.create` | `/schemas/VmConfig` | N/A | The VM is not created yet | 84072af956SRob Bradford| Delete the VM | `/vm.delete` | N/A | N/A | N/A | 85072af956SRob Bradford| Boot the VM | `/vm.boot` | N/A | N/A | The VM is created but not booted | 86072af956SRob Bradford| Shut the VM down | `/vm.shutdown` | N/A | N/A | The VM is booted | 87072af956SRob Bradford| Reboot the VM | `/vm.reboot` | N/A | N/A | The VM is booted | 88072af956SRob Bradford| Trigger power button of the VM | `/vm.power-button` | N/A | N/A | The VM is booted | 89072af956SRob Bradford| Pause the VM | `/vm.pause` | N/A | N/A | The VM is booted | 90072af956SRob Bradford| Resume the VM | `/vm.resume` | N/A | N/A | The VM is paused | 91072af956SRob Bradford| Task a snapshot of the VM | `/vm.snapshot` | `/schemas/VmSnapshotConfig` | N/A | The VM is paused | 9236cf46e3SOmer Faruk Bayram| Perform a coredump of the VM* | `/vm.coredump` | `/schemas/VmCoredumpData` | N/A | The VM is paused | 93072af956SRob Bradford| Restore the VM from a snapshot | `/vm.restore` | `/schemas/RestoreConfig` | N/A | The VM is created but not booted | 94072af956SRob Bradford| Add/remove CPUs to/from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted | 95072af956SRob Bradford| Add/remove memory from the VM | `/vm.resize` | `/schemas/VmResize` | N/A | The VM is booted | 96072af956SRob Bradford| Add/remove memory from a zone | `/vm.resize-zone` | `/schemas/VmResizeZone` | N/A | The VM is booted | 97072af956SRob Bradford| Dump the VM information | `/vm.info` | N/A | `/schemas/VmInfo` | The VM is created | 98072af956SRob Bradford| Add VFIO PCI device to the VM | `/vm.add-device` | `/schemas/VmAddDevice` | `/schemas/PciDeviceInfo` | The VM is booted | 99072af956SRob Bradford| Add disk device to the VM | `/vm.add-disk` | `/schemas/DiskConfig` | `/schemas/PciDeviceInfo` | The VM is booted | 100072af956SRob Bradford| Add fs device to the VM | `/vm.add-fs` | `/schemas/FsConfig` | `/schemas/PciDeviceInfo` | The VM is booted | 101072af956SRob Bradford| Add pmem device to the VM | `/vm.add-pmem` | `/schemas/PmemConfig` | `/schemas/PciDeviceInfo` | The VM is booted | 102072af956SRob Bradford| Add network device to the VM | `/vm.add-net` | `/schemas/NetConfig` | `/schemas/PciDeviceInfo` | The VM is booted | 103072af956SRob Bradford| Add userspace PCI device to the VM | `/vm.add-user-device` | `/schemas/VmAddUserDevice` | `/schemas/PciDeviceInfo` | The VM is booted | 104072af956SRob Bradford| Add vdpa device to the VM | `/vm.add-vdpa` | `/schemas/VdpaConfig` | `/schemas/PciDeviceInfo` | The VM is booted | 105072af956SRob Bradford| Add vsock device to the VM | `/vm.add-vsock` | `/schemas/VsockConfig` | `/schemas/PciDeviceInfo` | The VM is booted | 106072af956SRob Bradford| Remove device from the VM | `/vm.remove-device` | `/schemas/VmRemoveDevice` | N/A | The VM is booted | 107072af956SRob Bradford| Dump the VM counters | `/vm.counters` | N/A | `/schemas/VmCounters` | The VM is booted | 1085466e873SYi Wang| Inject an NMI | `/vm.nmi` | N/A | N/A | The VM is booted | 109e7d52fc7SOmer Faruk Bayram| Prepare to receive a migration | `/vm.receive-migration` | `/schemas/ReceiveMigrationData` | N/A | N/A | 110e7d52fc7SOmer Faruk Bayram| Start to send migration to target | `/vm.send-migration` | `/schemas/SendMigrationData` | N/A | The VM is booted and (shared mem or hugepages enabled) | 1110cd3325aSSamuel Ortiz 11236cf46e3SOmer Faruk Bayram* The `vmcoredump` action is available exclusively for the `x86_64` 11336cf46e3SOmer Faruk Bayramarchitecture and can be executed only when the `guest_debug` feature is 11483914d80SOmer Faruk Bayramenabled. Without this feature, the corresponding [REST API](#rest-api) or 11583914d80SOmer Faruk Bayram[D-Bus API](#d-bus-api) endpoints are not available. 11636cf46e3SOmer Faruk Bayram 11783914d80SOmer Faruk Bayram#### REST API Examples 1180cd3325aSSamuel Ortiz 1190cd3325aSSamuel OrtizFor the following set of examples, we assume Cloud Hypervisor is started with 1200cd3325aSSamuel Ortizthe REST API available at `/tmp/cloud-hypervisor.sock`: 1210cd3325aSSamuel Ortiz 1220cd3325aSSamuel Ortiz``` 1230cd3325aSSamuel Ortiz$ ./target/debug/cloud-hypervisor --api-socket /tmp/cloud-hypervisor.sock 1240cd3325aSSamuel OrtizCloud Hypervisor Guest 1250cd3325aSSamuel Ortiz API server: /tmp/cloud-hypervisor.sock 1260cd3325aSSamuel Ortiz vCPUs: 1 1270cd3325aSSamuel Ortiz Memory: 512 MB 1280cd3325aSSamuel Ortiz Kernel: None 1290cd3325aSSamuel Ortiz Kernel cmdline: 1300cd3325aSSamuel Ortiz Disk(s): None 1310cd3325aSSamuel Ortiz``` 1320cd3325aSSamuel Ortiz 13383914d80SOmer Faruk Bayram##### Create a Virtual Machine 1340cd3325aSSamuel Ortiz 1350cd3325aSSamuel OrtizWe want to create a virtual machine with the following characteristics: 1360cd3325aSSamuel Ortiz 1370cd3325aSSamuel Ortiz* 4 vCPUs 1380cd3325aSSamuel Ortiz* 1 GB of RAM 1390cd3325aSSamuel Ortiz* 1 virtio based networking interface 140a3342bdbSSebastien Boeuf* Direct kernel boot from a custom 5.6.0-rc4 Linux kernel located at 1410cd3325aSSamuel Ortiz `/opt/clh/kernel/vmlinux-virtio-fs-virtio-iommu` 142a3342bdbSSebastien Boeuf* Using a Ubuntu image as its root filesystem, located at 143a3342bdbSSebastien Boeuf `/opt/clh/images/focal-server-cloudimg-amd64.raw` 1440cd3325aSSamuel Ortiz 1450cd3325aSSamuel Ortiz```shell 14691fe48d5SPhilipp Schuster#!/usr/bin/env bash 1470cd3325aSSamuel Ortiz 1480cd3325aSSamuel Ortizcurl --unix-socket /tmp/cloud-hypervisor.sock -i \ 1490cd3325aSSamuel Ortiz -X PUT 'http://localhost/api/v1/vm.create' \ 1500cd3325aSSamuel Ortiz -H 'Accept: application/json' \ 1510cd3325aSSamuel Ortiz -H 'Content-Type: application/json' \ 1520cd3325aSSamuel Ortiz -d '{ 1530cd3325aSSamuel Ortiz "cpus":{"boot_vcpus": 4, "max_vcpus": 4}, 1546fda567aSRob Bradford "payload":{"kernel":"/opt/clh/kernel/vmlinux-virtio-fs-virtio-iommu", "cmdline":"console=ttyS0 console=hvc0 root=/dev/vda1 rw"}, 155a3342bdbSSebastien Boeuf "disks":[{"path":"/opt/clh/images/focal-server-cloudimg-amd64.raw"}], 1560cd3325aSSamuel Ortiz "rng":{"src":"/dev/urandom"}, 1570cd3325aSSamuel Ortiz "net":[{"ip":"192.168.10.10", "mask":"255.255.255.0", "mac":"12:34:56:78:90:01"}] 1580cd3325aSSamuel Ortiz }' 1590cd3325aSSamuel Ortiz``` 1600cd3325aSSamuel Ortiz 16183914d80SOmer Faruk Bayram##### Boot a Virtual Machine 1620cd3325aSSamuel Ortiz 1630cd3325aSSamuel OrtizOnce the VM is created, we can boot it: 1640cd3325aSSamuel Ortiz 1650cd3325aSSamuel Ortiz```shell 16691fe48d5SPhilipp Schuster#!/usr/bin/env bash 1670cd3325aSSamuel Ortiz 1680cd3325aSSamuel Ortizcurl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1/vm.boot' 1690cd3325aSSamuel Ortiz``` 1700cd3325aSSamuel Ortiz 17183914d80SOmer Faruk Bayram##### Dump a Virtual Machine Information 1720cd3325aSSamuel Ortiz 1730cd3325aSSamuel OrtizWe can fetch information about any VM, as soon as it's created: 1740cd3325aSSamuel Ortiz 1750cd3325aSSamuel Ortiz```shell 17691fe48d5SPhilipp Schuster#!/usr/bin/env bash 1770cd3325aSSamuel Ortiz 1780cd3325aSSamuel Ortizcurl --unix-socket /tmp/cloud-hypervisor.sock -i \ 1790cd3325aSSamuel Ortiz -X GET 'http://localhost/api/v1/vm.info' \ 1800cd3325aSSamuel Ortiz -H 'Accept: application/json' 1810cd3325aSSamuel Ortiz``` 1820cd3325aSSamuel Ortiz 18383914d80SOmer Faruk Bayram##### Reboot a Virtual Machine 1840cd3325aSSamuel Ortiz 1850cd3325aSSamuel OrtizWe can reboot a VM that's already booted: 1860cd3325aSSamuel Ortiz 1870cd3325aSSamuel Ortiz```shell 18891fe48d5SPhilipp Schuster#!/usr/bin/env bash 1890cd3325aSSamuel Ortiz 1900cd3325aSSamuel Ortizcurl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1/vm.reboot' 1910cd3325aSSamuel Ortiz``` 1920cd3325aSSamuel Ortiz 19383914d80SOmer Faruk Bayram##### Shut a Virtual Machine Down 1940cd3325aSSamuel Ortiz 1950cd3325aSSamuel OrtizOnce booted, we can shut a VM down from the REST API: 1960cd3325aSSamuel Ortiz 1970cd3325aSSamuel Ortiz```shell 19891fe48d5SPhilipp Schuster#!/usr/bin/env bash 1990cd3325aSSamuel Ortiz 2000cd3325aSSamuel Ortizcurl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1/vm.shutdown' 2010cd3325aSSamuel Ortiz``` 2020cd3325aSSamuel Ortiz 20383914d80SOmer Faruk Bayram### D-Bus API 20483914d80SOmer Faruk Bayram 205cc5dd8c2SOmer Faruk BayramCloud Hypervisor offers a D-Bus API as an alternative to its REST API. This 206cc5dd8c2SOmer Faruk BayramD-Bus API fully reflects the functionality of the REST API, exposing the 207cc5dd8c2SOmer Faruk Bayramsame group of endpoints. It can be a drop-in replacement since it also 208cc5dd8c2SOmer Faruk Bayramconsumes/produces JSON. 209cc5dd8c2SOmer Faruk Bayram 210cc5dd8c2SOmer Faruk BayramIn addition, the D-Bus API also exposes events from `event-monitor` in the 211cc5dd8c2SOmer Faruk Bayramform of a D-Bus signal to which users can subscribe. For more information, 212cc5dd8c2SOmer Faruk Bayramsee [D-Bus API Interface](#d-bus-api-interface). 21383914d80SOmer Faruk Bayram 21483914d80SOmer Faruk Bayram#### D-Bus API Location and availability 21583914d80SOmer Faruk Bayram 21683914d80SOmer Faruk BayramThis feature is not compiled into Cloud Hypervisor by default. Users who 21783914d80SOmer Faruk Bayramwish to use the D-Bus API, must explicitly enable it with the `dbus_api` 21883914d80SOmer Faruk Bayramfeature flag when compiling Cloud Hypervisor. 21983914d80SOmer Faruk Bayram 22083914d80SOmer Faruk Bayram```sh 22183914d80SOmer Faruk Bayram$ ./scripts/dev_cli.sh build --release --libc musl -- --features dbus_api 22283914d80SOmer Faruk Bayram``` 22383914d80SOmer Faruk Bayram 22483914d80SOmer Faruk BayramOnce this feature is enabled, it can be configured with the following 22583914d80SOmer Faruk BayramCLI options: 22683914d80SOmer Faruk Bayram 22783914d80SOmer Faruk Bayram``` 22883914d80SOmer Faruk Bayram --dbus-service-name 22983914d80SOmer Faruk Bayram well known name of the service 23083914d80SOmer Faruk Bayram --dbus-object-path 23183914d80SOmer Faruk Bayram object path to serve the dbus interface 23283914d80SOmer Faruk Bayram --dbus-system-bus use the system bus instead of a session bus 23383914d80SOmer Faruk Bayram``` 23483914d80SOmer Faruk Bayram 23583914d80SOmer Faruk BayramExample invocation: 23683914d80SOmer Faruk Bayram 23783914d80SOmer Faruk Bayram```sh 23883914d80SOmer Faruk Bayram$ ./cloud-hypervisor --dbus-service-name "org.cloudhypervisor.DBusApi" \ 23983914d80SOmer Faruk Bayram --dbus-object-path "/org/cloudhypervisor/DBusApi" 24083914d80SOmer Faruk Bayram``` 24183914d80SOmer Faruk Bayram 24283914d80SOmer Faruk BayramThis will start serving a service with the name `org.cloudhypervisor.DBusApi1` 24383914d80SOmer Faruk Bayramwhich in turn can be used to control and manage Cloud Hypervisor. 24483914d80SOmer Faruk Bayram 24583914d80SOmer Faruk Bayram#### D-Bus API Interface 24683914d80SOmer Faruk Bayram 247cc5dd8c2SOmer Faruk BayramPlease refer to the [REST API](#rest-api) documentation for everything that 248cc5dd8c2SOmer Faruk Bayramis in common with the REST API. As previously mentioned, the D-Bus API can 249cc5dd8c2SOmer Faruk Bayrambe used as a drop-in replacement for the [REST API](#rest-api). 250cc5dd8c2SOmer Faruk Bayram 251cc5dd8c2SOmer Faruk BayramThe D-Bus interface also exposes a signal, named `Event`, which is emitted 252cc5dd8c2SOmer Faruk Bayramwhenever a new event is published from the `event-monitor` crate. Here is its 253cc5dd8c2SOmer Faruk Bayramdefinition in XML format: 254cc5dd8c2SOmer Faruk Bayram 255cc5dd8c2SOmer Faruk Bayram```xml 256cc5dd8c2SOmer Faruk Bayram<node> 257cc5dd8c2SOmer Faruk Bayram <interface name="org.cloudhypervisor.DBusApi1"> 258cc5dd8c2SOmer Faruk Bayram <signal name="Event"> 259cc5dd8c2SOmer Faruk Bayram <arg name="event" type="s"/> 260cc5dd8c2SOmer Faruk Bayram </signal> 261cc5dd8c2SOmer Faruk Bayram </interface> 262cc5dd8c2SOmer Faruk Bayram</node> 263cc5dd8c2SOmer Faruk Bayram``` 26483914d80SOmer Faruk Bayram 2650cd3325aSSamuel Ortiz### Command Line Interface 2660cd3325aSSamuel Ortiz 2670cd3325aSSamuel OrtizThe Cloud Hypervisor Command Line Interface (CLI) can only be used for launching 2680cd3325aSSamuel Ortizthe Cloud Hypervisor binary, i.e. it cannot be used for controlling the VMM or 2690cd3325aSSamuel Ortizthe launched VM once they're up and running. 2700cd3325aSSamuel Ortiz 2710cd3325aSSamuel OrtizIf you want to inspect the VMM, or control the VM after launching Cloud 27283914d80SOmer Faruk BayramHypervisor from the CLI, you must use either the [REST API](#rest-api) 27383914d80SOmer Faruk Bayramor the [D-Bus API](#d-bus-api). 2740cd3325aSSamuel Ortiz 27583914d80SOmer Faruk BayramFrom the CLI, one can: 2760cd3325aSSamuel Ortiz 2770cd3325aSSamuel Ortiz1. Create and boot a complete virtual machine by using the CLI options to build 2780cd3325aSSamuel Ortiz the VM config. Run `cloud-hypervisor --help` for a complete list of CLI 27983914d80SOmer Faruk Bayram options. As soon as the `cloud-hypervisor` binary is launched, contrary 28083914d80SOmer Faruk Bayram to the [D-Bus API](#d-bus-api), the [REST API](#rest-api) is available 28183914d80SOmer Faruk Bayram for controlling and managing the VM. The [D-Bus API](#d-bus-api) doesn't start 28283914d80SOmer Faruk Bayram automatically and needs to be explicitly configured in order to be run. 28383914d80SOmer Faruk Bayram1. Start either the REST API, D-Bus API or both simultaneously without passing 28483914d80SOmer Faruk Bayram any VM configuration options. The VM can then be asynchronously created and 28583914d80SOmer Faruk Bayram booted by calling API methods of choice. It should be noted that one external 28683914d80SOmer Faruk Bayram API does not exclude another; it is possible to have both the REST and D-Bus 28783914d80SOmer Faruk Bayram APIs running simultaneously. 2880cd3325aSSamuel Ortiz 28983914d80SOmer Faruk Bayram### REST API, D-Bus API and CLI Architectural Relationship 2900cd3325aSSamuel Ortiz 29183914d80SOmer Faruk BayramThe REST API, D-Bus API and the CLI all rely on a common, [internal API](#internal-api). 2920cd3325aSSamuel Ortiz 2930cd3325aSSamuel OrtizThe CLI options are parsed by the 294fa22cb0bSRavi kumar Veeramally[clap crate](https://docs.rs/clap/4.3.11/clap/) and then translated into 2950cd3325aSSamuel Ortiz[internal API](#internal-api) commands. 2960cd3325aSSamuel Ortiz 2970cd3325aSSamuel OrtizThe REST API is processed by an HTTP thread using the 29844452cbeSRavi kumar Veeramally[Firecracker's `micro_http`](https://github.com/firecracker-microvm/micro-http) 2990cd3325aSSamuel Ortizcrate. As with the CLI, the HTTP requests eventually get translated into 3000cd3325aSSamuel Ortiz[internal API](#internal-api) commands. 3010cd3325aSSamuel Ortiz 30283914d80SOmer Faruk BayramThe D-Bus API is implemented using the [zbus](https://github.com/dbus2/zbus) 30383914d80SOmer Faruk Bayramcrate and runs in its own thread. Whenever it needs to call the [internal API](#internal-api), 30483914d80SOmer Faruk Bayramthe [blocking](https://github.com/smol-rs/blocking) crate is used perform the call in zbus' async context. 30583914d80SOmer Faruk Bayram 30683914d80SOmer Faruk BayramAs a summary, the REST API, the D-Bus API and the CLI are essentially frontends for the 3070cd3325aSSamuel Ortiz[internal API](#internal-api): 3080cd3325aSSamuel Ortiz 3090cd3325aSSamuel Ortiz``` 3100cd3325aSSamuel Ortiz +------------------+ 3110cd3325aSSamuel Ortiz REST API | | 3120cd3325aSSamuel Ortiz +--------->+ micro_http +--------+ 3130cd3325aSSamuel Ortiz | | | | 3140cd3325aSSamuel Ortiz | +------------------+ | 3150cd3325aSSamuel Ortiz | | +------------------------+ 3160cd3325aSSamuel Ortiz | | | | 31783914d80SOmer Faruk Bayram+------------+ | +----------+ | | | 31883914d80SOmer Faruk Bayram| | | D-Bus API | | | | +--------------+ | 31983914d80SOmer Faruk Bayram| User +---------+----------->+ zbus +--------------+------> | Internal API | | 32083914d80SOmer Faruk Bayram| | | | | | | +--------------+ | 32183914d80SOmer Faruk Bayram+------------+ | +----------+ | | | 3220cd3325aSSamuel Ortiz | | | | 3230cd3325aSSamuel Ortiz | | +------------------------+ 3240cd3325aSSamuel Ortiz | +----------+ | VMM 3250cd3325aSSamuel Ortiz | CLI | | | 326fa22cb0bSRavi kumar Veeramally +----------->+ clap +--------------+ 3270cd3325aSSamuel Ortiz | | 3280cd3325aSSamuel Ortiz +----------+ 3290cd3325aSSamuel Ortiz 3300cd3325aSSamuel Ortiz 3310cd3325aSSamuel Ortiz``` 3320cd3325aSSamuel Ortiz 3330cd3325aSSamuel Ortiz## Internal API 3340cd3325aSSamuel Ortiz 3350cd3325aSSamuel OrtizThe Cloud Hypervisor internal API, as its name suggests, is used internally 33683914d80SOmer Faruk Bayramby the different Cloud Hypervisor threads (VMM, HTTP, D-Bus, control loop, 33783914d80SOmer Faruk Bayrametc) to send commands and responses to each others. 3380cd3325aSSamuel Ortiz 3390cd3325aSSamuel OrtizIt is based on [rust's Multi-Producer, Single-Consumer (MPSC)](https://doc.rust-lang.org/std/sync/mpsc/), 3400cd3325aSSamuel Ortizand the single consumer (a.k.a. the API receiver) is the Cloud Hypervisor 3410cd3325aSSamuel Ortizcontrol loop. 3420cd3325aSSamuel Ortiz 34383914d80SOmer Faruk BayramAPI producers are the HTTP thread handling the [REST API](#rest-api), the 34483914d80SOmer Faruk BayramD-Bus thread handling the [D-Bus API](#d-bus-api) and the main thread that 34583914d80SOmer Faruk Bayraminitially parses the [CLI](#command-line-interface). 3460cd3325aSSamuel Ortiz 3470cd3325aSSamuel Ortiz### Goals and Design 3480cd3325aSSamuel Ortiz 3490cd3325aSSamuel OrtizThe internal API is designed for controlling, managing and inspecting a Cloud 3500cd3325aSSamuel OrtizHypervisor VMM and its guest. It is a backend for handling external, user 35183914d80SOmer Faruk Bayramvisible requests through the [REST API](#rest-api), the [D-Bus API](#d-bus-api) 35283914d80SOmer Faruk Bayramor the [CLI](#command-line-interface) interfaces. 3530cd3325aSSamuel Ortiz 3540cd3325aSSamuel OrtizThe API follows a command-response scheme that closely maps the [REST API](#rest-api). 3550cd3325aSSamuel OrtizAny command must be replied to with a response. 3560cd3325aSSamuel Ortiz 3570cd3325aSSamuel OrtizCommands are [MPSC](https://doc.rust-lang.org/std/sync/mpsc/) based messages and 3580cd3325aSSamuel Ortizare received and processed by the VMM control loop. 3590cd3325aSSamuel Ortiz 3600cd3325aSSamuel OrtizIn order for the VMM control loop to respond to any internal API command, it 3610cd3325aSSamuel Ortizmust be able to send a response back to the MPSC sender. For that purpose, all 3620cd3325aSSamuel Ortizinternal API command payload carry the [Sender](https://doc.rust-lang.org/std/sync/mpsc/struct.Sender.html) 3630cd3325aSSamuel Ortizend of an [MPSC](https://doc.rust-lang.org/std/sync/mpsc/) channel. 3640cd3325aSSamuel Ortiz 3650cd3325aSSamuel OrtizThe sender of any internal API command is therefore responsible for: 3660cd3325aSSamuel Ortiz 3670cd3325aSSamuel Ortiz1. Creating an [MPSC](https://doc.rust-lang.org/std/sync/mpsc/) response 3680cd3325aSSamuel Ortiz channel. 3690cd3325aSSamuel Ortiz1. Passing the [Sender](https://doc.rust-lang.org/std/sync/mpsc/struct.Sender.html) 3700cd3325aSSamuel Ortiz end of the response channel as part of the internal API command payload. 3710cd3325aSSamuel Ortiz1. Waiting for the internal API command's response on the [Receiver](https://doc.rust-lang.org/std/sync/mpsc/struct.Receiver.html) 3720cd3325aSSamuel Ortiz end of the response channel. 3730cd3325aSSamuel Ortiz 3740cd3325aSSamuel Ortiz## End to End Example 3750cd3325aSSamuel Ortiz 3760cd3325aSSamuel OrtizIn order to further understand how the external and internal Cloud Hypervisor 3770cd3325aSSamuel OrtizAPIs work together, let's look at a complete VM creation flow, from the 3780cd3325aSSamuel Ortiz[REST API](#rest-api) call, to the reply the external user will receive: 3790cd3325aSSamuel Ortiz 3800cd3325aSSamuel Ortiz1. A user or operator sends an HTTP request to the Cloud Hypervisor 3810cd3325aSSamuel Ortiz [REST API](#rest-api) in order to creates a virtual machine: 3820cd3325aSSamuel Ortiz ``` 3830cd3325aSSamuel Ortiz shell 38491fe48d5SPhilipp Schuster #!/usr/bin/env bash 3850cd3325aSSamuel Ortiz 3860cd3325aSSamuel Ortiz curl --unix-socket /tmp/cloud-hypervisor.sock -i \ 3870cd3325aSSamuel Ortiz -X PUT 'http://localhost/api/v1/vm.create' \ 3880cd3325aSSamuel Ortiz -H 'Accept: application/json' \ 3890cd3325aSSamuel Ortiz -H 'Content-Type: application/json' \ 3900cd3325aSSamuel Ortiz -d '{ 3910cd3325aSSamuel Ortiz "cpus":{"boot_vcpus": 4, "max_vcpus": 4}, 3926fda567aSRob Bradford "payload":{"kernel":"/opt/clh/kernel/vmlinux-virtio-fs-virtio-iommu", "cmdline":"console=ttyS0 console=hvc0 root=/dev/vda1 rw"}, 393a3342bdbSSebastien Boeuf "disks":[{"path":"/opt/clh/images/focal-server-cloudimg-amd64.raw"}], 3940cd3325aSSamuel Ortiz "rng":{"src":"/dev/urandom"}, 3950cd3325aSSamuel Ortiz "net":[{"ip":"192.168.10.10", "mask":"255.255.255.0", "mac":"12:34:56:78:90:01"}] 3960cd3325aSSamuel Ortiz }' 3970cd3325aSSamuel Ortiz ``` 3980cd3325aSSamuel Ortiz1. The Cloud Hypervisor HTTP thread processes the request and de-serializes the 3990cd3325aSSamuel Ortiz HTTP request JSON body into an internal `VmConfig` structure. 4000cd3325aSSamuel Ortiz1. The Cloud Hypervisor HTTP thread creates an 4010cd3325aSSamuel Ortiz [MPSC](https://doc.rust-lang.org/std/sync/mpsc/) channel for the internal API 4020cd3325aSSamuel Ortiz server to send its response back. 4030cd3325aSSamuel Ortiz1. The Cloud Hypervisor HTTP thread prepares an internal API command for creating a 4040cd3325aSSamuel Ortiz virtual machine. The command's payload is made of the de-serialized 4050cd3325aSSamuel Ortiz `VmConfig` structure and the response channel: 4060cd3325aSSamuel Ortiz ```Rust 4070cd3325aSSamuel Ortiz VmCreate(Arc<Mutex<VmConfig>>, Sender<ApiResponse>) 4080cd3325aSSamuel Ortiz ``` 4090cd3325aSSamuel Ortiz1. The Cloud Hypervisor HTTP thread sends the internal API command, and waits 4100cd3325aSSamuel Ortiz for the response: 4110cd3325aSSamuel Ortiz ```Rust 4120cd3325aSSamuel Ortiz // Send the VM creation request. 4130cd3325aSSamuel Ortiz api_sender 4140cd3325aSSamuel Ortiz .send(ApiRequest::VmCreate(config, response_sender)) 4150cd3325aSSamuel Ortiz .map_err(ApiError::RequestSend)?; 4160cd3325aSSamuel Ortiz api_evt.write(1).map_err(ApiError::EventFdWrite)?; 4170cd3325aSSamuel Ortiz 4180cd3325aSSamuel Ortiz response_receiver.recv().map_err(ApiError::ResponseRecv)??; 4190cd3325aSSamuel Ortiz ``` 4200cd3325aSSamuel Ortiz1. The Cloud Hypervisor control loop receives the command, as it listens on the 4210cd3325aSSamuel Ortiz internal API [MPSC](https://doc.rust-lang.org/std/sync/mpsc/) channel: 4220cd3325aSSamuel Ortiz ```Rust 4230cd3325aSSamuel Ortiz // Read from the API receiver channel 4240cd3325aSSamuel Ortiz let api_request = api_receiver.recv().map_err(Error::ApiRequestRecv)?; 4250cd3325aSSamuel Ortiz ``` 4260cd3325aSSamuel Ortiz1. The Cloud Hypervisor control loop matches the received internal API against 4270cd3325aSSamuel Ortiz the `VmCreate` payload, and extracts both the `VmConfig` structure and the 4280cd3325aSSamuel Ortiz [Sender](https://doc.rust-lang.org/std/sync/mpsc/struct.Sender.html) from the 4290cd3325aSSamuel Ortiz command payload. It stores the `VmConfig` structure and replies back to the 4300cd3325aSSamuel Ortiz sender ((The HTTP thread): 4310cd3325aSSamuel Ortiz ```Rust 4320cd3325aSSamuel Ortiz match api_request { 4330cd3325aSSamuel Ortiz ApiRequest::VmCreate(config, sender) => { 4340cd3325aSSamuel Ortiz // We only store the passed VM config. 4350cd3325aSSamuel Ortiz // The VM will be created when being asked to boot it. 4360cd3325aSSamuel Ortiz let response = if self.vm_config.is_none() { 4370cd3325aSSamuel Ortiz self.vm_config = Some(config); 4380cd3325aSSamuel Ortiz Ok(ApiResponsePayload::Empty) 4390cd3325aSSamuel Ortiz } else { 4400cd3325aSSamuel Ortiz Err(ApiError::VmAlreadyCreated) 4410cd3325aSSamuel Ortiz }; 4420cd3325aSSamuel Ortiz 4430cd3325aSSamuel Ortiz sender.send(response).map_err(Error::ApiResponseSend)?; 4440cd3325aSSamuel Ortiz } 4450cd3325aSSamuel Ortiz ``` 4460cd3325aSSamuel Ortiz1. The Cloud Hypervisor HTTP thread receives the internal API command response 4470cd3325aSSamuel Ortiz as the return value from its `VmCreate` HTTP handler. Depending on the 4480cd3325aSSamuel Ortiz control loop internal API response, it generates the appropriate HTTP 4490cd3325aSSamuel Ortiz response: 4500cd3325aSSamuel Ortiz ```Rust 4510cd3325aSSamuel Ortiz // Call vm_create() 4520cd3325aSSamuel Ortiz match vm_create(api_notifier, api_sender, Arc::new(Mutex::new(vm_config))) 4530cd3325aSSamuel Ortiz .map_err(HttpError::VmCreate) 4540cd3325aSSamuel Ortiz { 4550cd3325aSSamuel Ortiz Ok(_) => Response::new(Version::Http11, StatusCode::NoContent), 4560cd3325aSSamuel Ortiz Err(e) => error_response(e, StatusCode::InternalServerError), 4570cd3325aSSamuel Ortiz } 4580cd3325aSSamuel Ortiz ``` 4590cd3325aSSamuel Ortiz1. The Cloud Hypervisor HTTP thread sends the formed HTTP response back to the 4600cd3325aSSamuel Ortiz user. This is abstracted by the 46144452cbeSRavi kumar Veeramally [micro_http](https://github.com/firecracker-microvm/micro-http) 4620cd3325aSSamuel Ortiz crate. 463