xref: /cloud-hypervisor/docs/api.md (revision 1bc74e43f83bd3b0645239098c33e44656999151)
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