Rename Mgmt API to Admin API

QubesOS/qubes-issues#853
This commit is contained in:
Marek Marczykowski-Górecki 2017-05-11 22:39:53 +02:00
parent 886c5496b9
commit eb484c383b
No known key found for this signature in database
GPG key ID: F32894BE9684938A
3 changed files with 198 additions and 195 deletions

187
services/admin-api.md Normal file
View file

@ -0,0 +1,187 @@
---
layout: doc-full
title: Admin API
permalink: /doc/admin-api/
redirect_from:
- /doc/mgmt/
- /doc/mgmt1/
---
# Admin API
*(This page is the current draft of the proposal. It is not implemented yet.)*
The API should be implemented as a set of qrexec calls. This is to make it easy
to set the policy using current mechanism.
## The calls
| call | dest | argument | inside | return | note |
| ------------------------------------- | --------- | --------- | ----------------------------------------- | --------------------------------------------------------- | ---- |
| `admin.vmclass.List` | `dom0` | - | - | `<class>\n` |
| `admin.vm.List` | `dom0|<vm>` | - | - | `<name> class=<class> state=<state>\n` |
| `admin.vm.Create.<class>` | `dom0` | template | `name=<name> label=<label>` | - |
| `admin.vm.CreateInPool.<class>` | `dom0` | template | `name=<name> label=<label> `<br/>`pool=<pool> pool:<volume>=<pool>` | - | either use `pool=` to put all volumes there, <br/>or `pool:<volume>=` for individual volumes - both forms are not allowed at the same time
| `admin.vm.CreateTemplate` | `dom0` | name | `root.img` | - |
| `admin.vm.Clone` | vm | - | `name=<name>` | - |
| `admin.vm.CloneInPool` | vm | - | `name=<name> `<br/>`pool=<pool> pool:<volume>=<pool>` | - | same as for `admin.vm.CreateInPool`
| `admin.vm.Remove` | vm | - | - | - |
| `admin.label.List` | `dom0` | - | - | `<property>\n` |
| `admin.label.Create` | `dom0` | label | `0xRRGGBB` | - |
| `admin.label.Get` | `dom0` | label | - | `0xRRGGBB` |
| `admin.label.Index` | `dom0` | label | - | `<label-index>` |
| `admin.label.Remove` | `dom0` | label | - | - |
| `admin.property.List` | `dom0` | - | - | `<property>\n` |
| `admin.property.Get` | `dom0` | property | - | `default={yes|no} `<br/>`type={str|int|bool|vm|label} <value>` |
| `admin.property.Help` | `dom0` | property | - | `help` |
| `admin.property.HelpRst` | `dom0` | property | - | `help.rst` |
| `admin.property.Reset` | `dom0` | property | - | - |
| `admin.property.Set` | `dom0` | property | value | - |
| `admin.vm.property.List` | vm | - | - | `<property>\n` |
| `admin.vm.property.Get` | vm | property | - | `default={yes|no} <value>` |
| `admin.vm.property.Help` | vm | property | - | `help` |
| `admin.vm.property.HelpRst` | vm | property | - | `help.rst` |
| `admin.vm.property.Reset` | vm | property | - | - |
| `admin.vm.property.Set` | vm | property | value | - |
| `admin.vm.feature.List` | vm | - | - | `<feature>\n` |
| `admin.vm.feature.Get` | vm | feature | - | value |
| `admin.vm.feature.CheckWithTemplate` | vm | feature | - | value |
| `admin.vm.feature.Remove` | vm | feature | - | - |
| `admin.vm.feature.Set` | vm | feature | value | - |
| `admin.vm.tag.List` | vm | - | - | `<tag>\n` |
| `admin.vm.tag.Get` | vm | tag | - | `0` or `1` | retcode? |
| `admin.vm.tag.Remove` | vm | tag | - | - |
| `admin.vm.tag.Set` | vm | tag | - | - |
| `admin.vm.firewall.Get` | vm | - | - | `<rule>\n` | rules syntax as in [firewall interface](/doc/vm-interface/#firewall-rules-in-4x) with addition of `expire=` and `comment=` options; `comment=` (if present) must be the last option
| `admin.vm.firewall.Set` | vm | - | `<rule>\n` | - | set firewall rules, see `admin.vm.firewall.Get` for syntax
| `admin.vm.firewall.Flush` | vm | - | - | - |
| `admin.vm.firewall.SetPolicy` | vm | - | `accept|drop` | - |
| `admin.vm.firewall.GetPolicy` | vm | - | - | `accept|drop` |
| `admin.vm.firewall.Reload` | vm | - | - | - | force reload firewall without changing any rule
| `admin.vm.device.<class>.Attach` | vm | device | options | - | `device` is in form `<backend-name>+<device-ident>` <br/>optional options given in `key=value` format, separated with spaces; <br/>options can include `persistent=yes` to "persistently" attach the device (default is temporary)
| `admin.vm.device.<class>.Detach` | vm | device | - | - | `device` is in form `<backend-name>+<device-ident>`
| `admin.vm.device.<class>.List` | vm | - | - | `<device> <options>\n` |
| `admin.vm.device.<class>.Available` | vm | device-ident | - | `<device-ident> <properties> description=<desc>\n` | optional service argument may be used to get info about a single device, <br/>optional (device class specific) properties are in `key=value` form, <br/>`description` must be the last one and is the only one allowed to contain spaces; <br/>options can include `persistent=yes` for "persistently" attached devices (default is temporary)
| `admin.vm.microphone.Attach` | vm | - | - | - |
| `admin.vm.microphone.Detach` | vm | - | - | - |
| `admin.pool.List` | `dom0` | - | - | `<pool>\n` |
| `admin.pool.ListDrivers` | `dom0` | - | - | `<pool-driver> <property> ...\n` | Properties allowed in `admin.pool.Add`
| `admin.pool.Info` | `dom0` | pool | - | `<property>=<value>\n` |
| `admin.pool.Add` | `dom0` | driver | `<property>=<value>\n` | - |
| `admin.pool.Remove` | `dom0` | pool | - | - |
| `admin.pool.volume.List` | `dom0` | pool | - | volume id |
| `admin.pool.volume.Info` | `dom0` | pool | vid | `<property>=<value>\n` |
| `admin.pool.volume.ListSnapshots` | `dom0` | pool | vid | `<snapshot>\n` |
| `admin.pool.volume.Snapshot` | `dom0` | pool | vid | snapshot |
| `admin.pool.volume.Revert` | `dom0` | pool | `<vid> <snapshot>` | - |
| `admin.pool.volume.Resize` | `dom0` | pool | `<vid> <size_in_bytes>` | - |
| `admin.pool.volume.Import` | `dom0` | pool | `<vid>\n<raw volume data>` | - |
| `admin.vm.volume.List` | vm | - | - | `<volume>\n` | `<volume>` is per-VM volume name, `<vid>` is pool-unique volume id
| `admin.vm.volume.Info` | vm | volume | - | `<property>=<value>\n` |
| `admin.vm.volume.ListSnapshots` | vm | volume | - | snapshot | duplicate of `admin.pool.volume.`, but with other call params |
| `admin.vm.volume.Snapshot` | vm | volume | - | snapshot | id. |
| `admin.vm.volume.Revert` | vm | volume | snapshot | - | id. |
| `admin.vm.volume.Resize` | vm | volume | size_in_bytes | - | id. |
| `admin.vm.volume.Import` | vm | volume | raw volume data | - | id. |
| `admin.vm.Start` | vm | - | - | - |
| `admin.vm.Shutdown` | vm | - | - | - |
| `admin.vm.Pause` | vm | - | - | - |
| `admin.vm.Unpause` | vm | - | - | - |
| `admin.vm.Kill` | vm | - | - | - |
| `admin.backup.Execute` | `dom0` | config i | - | - | config in `/etc/qubes/backup/<id>.conf` |
| `admin.backup.Info` | `dom0` | ? | content? | ? |
| `admin.backup.Restore` | `dom0` | ? | content | ? |
| `admin.Events` | `dom0|vm` | - | - | events |
Volume properties:
- `pool`
- `vid`
- `size`
- `usage`
- `rw`
- `internal`
- `source`
- `save_on_stop`
- `snap_on_start`
## Returned messages
First byte of a message is a message type. This is 8 bit non-zero integer.
Values start at 0x30 (48, `'0'`, zero digit in ASCII) for readability in hexdump.
Next byte must be 0x00 (a separator).
This alternatively can be thought of as zero-terminated string containing
single ASCII digit.
### OK (0)
```
30 00 <content>
```
Server will close the connection after delivering single message.
### EVENT (1)
```
31 00 <subject> 00 <event> 00 ( <key> 00 <value> 00 )* 00
```
Events are returned as stream of messages in selected API calls. Normally server
will not close the connection.
A method yielding events will not ever return a `OK` or `EXCEPTION` message.
When calling such method, it will produce an artificial event
`connection-established` just after connection, to help avoiding race
conditions during event handler registration.
### EXCEPTION (2)
```
32 00 <type> 00 ( <traceback> )? 00 <format string> 00 ( <field> 00 )*
```
Server will close the connection.
Traceback may be empty, can be enabled server-side as part of debug mode.
Delimiting zero-byte is always present.
Fields are should substituted into `%`-style format string, possibly after
client-side translation, to form final message to be displayed unto user. Server
does not by itself support translation.
## Tags
- `created-by-<vm>`
- `managed-by-<vm>`
- `backup-<id>`
## General notes
- there is no provision for `qvm-run`, but there already exists `qubes.VMShell` call
- generally actions `*.List` return a list of objects and have "object
identifier" as first word in a row. Such action can be also called with "object
identifier" in argument to get only a single entry (in the same format).
- closing qrexec connection normally does _not_ interrupt running operation; this is important to avoid leaving the system in inconsistent state
- actual operation starts only after caller send all the parameters (including a payload), signaled by sending EOF mark; there is no support for interactive protocols, to keep the protocol reasonable simple
## TODO
- something to configure/update policy
- notifications
- how to constrain the events?
- how to pass the parameters? maybe XML, since this is trusted anyway and
parser may be complicated
- how to constrain the possible values for `admin.vm.property.Set` etc, like
"you can change `netvm`, but you have to pick from this set"; this currently
can be done by writing an extension
- a call for executing `*.desktop` file from `/usr/share/applications`, for use
with appmenus without giving access to `qubes.VMShell`; currently this can be
done by writing custom qrexec calls
- maybe some generator for `.desktop` for appmenus, which would wrap calls in
`qrexec-client-vm`
<!-- vim: set ts=4 sts=4 sw=4 et : -->

View file

@ -1,16 +1,18 @@
--- ---
layout: doc-full layout: doc-full
title: Management API title: Admin API architecture
permalink: /doc/mgmt-architecture/ permalink: /doc/admin-api-architecture/
redirect_from:
- /doc/mgmt-architecture/
--- ---
# Qubes OS Management Architecture # Qubes OS Admin API Architecture
*(This page is the current draft of the proposal. It is not implemented yet.)* *(This page is the current draft of the proposal. It is not implemented yet.)*
## Goals ## Goals
The goals of the management system is to provide a way for the user to manage The goals of the Admin API system is to provide a way for the user to manage
the domains without direct access to dom0. the domains without direct access to dom0.
Foreseen benefits include: Foreseen benefits include:
@ -33,9 +35,9 @@ TBD
## Components ## Components
![Management Architecture][mgmt-architecture] ![Admin API Architecture][admin-api-architecture]
A central entity in the Qubes management system is a `qubesd` daemon, which A central entity in the Qubes Admin API system is a `qubesd` daemon, which
holds information about all domains in the system and mediates all actions (like holds information about all domains in the system and mediates all actions (like
starting and stopping a qube) with `libvirtd`. The `qubesd` daemon also manages starting and stopping a qube) with `libvirtd`. The `qubesd` daemon also manages
the `qubes.xml` file, which stores all persistent state information and the `qubes.xml` file, which stores all persistent state information and
@ -43,13 +45,13 @@ dispatches events to extensions. Last but not least, `qubesd` is responsible for
querying the RPC policy for qrexec daemon. querying the RPC policy for qrexec daemon.
The `qubesd` daemon may be accessed from other domains through a set of qrexec The `qubesd` daemon may be accessed from other domains through a set of qrexec
API calls called the [management API][mgmt1]. This API is the intended API calls called the [Admin API][admin-api]. This API is the intended
management interface supported by the Qubes OS. The API is stable. When called, management interface supported by the Qubes OS. The API is stable. When called,
the RPC handler performs basic validation and forwards the request to the the RPC handler performs basic validation and forwards the request to the
`qubesd` via UNIX domain socket. The socket API is private and unstable. It is `qubesd` via UNIX domain socket. The socket API is private and unstable. It is
documented [FIXME currently it isn't -- woju 20161221] in the developer's documented [FIXME currently it isn't -- woju 20161221] in the developer's
documentation of the source code. documentation of the source code.
[mgmt1]: ../mgmt1/ [admin-api]: ../admin-api/
[mgmt-architecture]: /attachment/wiki/mgmt/mgmt-architecture.svg [admin-api-architecture]: /attachment/wiki/AdminAPI/admin-api-architecture.svg

View file

@ -1,186 +0,0 @@
---
layout: doc-full
title: Management API
permalink: /doc/mgmt1/
redirect_from:
- /doc/mgmt/
---
# Management API
*(This page is the current draft of the proposal. It is not implemented yet.)*
The API should be implemented as a set of qrexec calls. This is to make it easy
to set the policy using current mechanism.
## The calls
| call | dest | argument | inside | return | note |
| ------------------------------------- | --------- | --------- | ----------------------------------------- | --------------------------------------------------------- | ---- |
| `mgmt.vmclass.List` | `dom0` | - | - | `<class>\n` |
| `mgmt.vm.List` | `dom0|<vm>` | - | - | `<name> class=<class> state=<state>\n` |
| `mgmt.vm.Create.<class>` | `dom0` | template | `name=<name> label=<label>` | - |
| `mgmt.vm.CreateInPool.<class>` | `dom0` | template | `name=<name> label=<label> `<br/>`pool=<pool> pool:<volume>=<pool>` | - | either use `pool=` to put all volumes there, <br/>or `pool:<volume>=` for individual volumes - both forms are not allowed at the same time
| `mgmt.vm.CreateTemplate` | `dom0` | name | `root.img` | - |
| `mgmt.vm.Clone` | vm | - | `name=<name>` | - |
| `mgmt.vm.CloneInPool` | vm | - | `name=<name> `<br/>`pool=<pool> pool:<volume>=<pool>` | - | same as for `mgmt.vm.CreateInPool`
| `mgmt.vm.Remove` | vm | - | - | - |
| `mgmt.label.List` | `dom0` | - | - | `<property>\n` |
| `mgmt.label.Create` | `dom0` | label | `0xRRGGBB` | - |
| `mgmt.label.Get` | `dom0` | label | - | `0xRRGGBB` |
| `mgmt.label.Index` | `dom0` | label | - | `<label-index>` |
| `mgmt.label.Remove` | `dom0` | label | - | - |
| `mgmt.property.List` | `dom0` | - | - | `<property>\n` |
| `mgmt.property.Get` | `dom0` | property | - | `default={yes|no} `<br/>`type={str|int|bool|vm|label} <value>` |
| `mgmt.property.Help` | `dom0` | property | - | `help` |
| `mgmt.property.HelpRst` | `dom0` | property | - | `help.rst` |
| `mgmt.property.Reset` | `dom0` | property | - | - |
| `mgmt.property.Set` | `dom0` | property | value | - |
| `mgmt.vm.property.List` | vm | - | - | `<property>\n` |
| `mgmt.vm.property.Get` | vm | property | - | `default={yes|no} <value>` |
| `mgmt.vm.property.Help` | vm | property | - | `help` |
| `mgmt.vm.property.HelpRst` | vm | property | - | `help.rst` |
| `mgmt.vm.property.Reset` | vm | property | - | - |
| `mgmt.vm.property.Set` | vm | property | value | - |
| `mgmt.vm.feature.List` | vm | - | - | `<feature>\n` |
| `mgmt.vm.feature.Get` | vm | feature | - | value |
| `mgmt.vm.feature.CheckWithTemplate` | vm | feature | - | value |
| `mgmt.vm.feature.Remove` | vm | feature | - | - |
| `mgmt.vm.feature.Set` | vm | feature | value | - |
| `mgmt.vm.tag.List` | vm | - | - | `<tag>\n` |
| `mgmt.vm.tag.Get` | vm | tag | - | `0` or `1` | retcode? |
| `mgmt.vm.tag.Remove` | vm | tag | - | - |
| `mgmt.vm.tag.Set` | vm | tag | - | - |
| `mgmt.vm.firewall.Get` | vm | - | - | `<rule>\n` | rules syntax as in [firewall interface](/doc/vm-interface/#firewall-rules-in-4x) with addition of `expire=` and `comment=` options; `comment=` (if present) must be the last option
| `mgmt.vm.firewall.Set` | vm | - | `<rule>\n` | - | set firewall rules, see `mgmt.vm.firewall.Get` for syntax
| `mgmt.vm.firewall.Flush` | vm | - | - | - |
| `mgmt.vm.firewall.SetPolicy` | vm | - | `accept|drop` | - |
| `mgmt.vm.firewall.GetPolicy` | vm | - | - | `accept|drop` |
| `mgmt.vm.firewall.Reload` | vm | - | - | - | force reload firewall without changing any rule
| `mgmt.vm.device.<class>.Attach` | vm | device | options | - | `device` is in form `<backend-name>+<device-ident>` <br/>optional options given in `key=value` format, separated with spaces; <br/>options can include `persistent=yes` to "persistently" attach the device (default is temporary)
| `mgmt.vm.device.<class>.Detach` | vm | device | - | - | `device` is in form `<backend-name>+<device-ident>`
| `mgmt.vm.device.<class>.List` | vm | - | - | `<device> <options>\n` |
| `mgmt.vm.device.<class>.Available` | vm | device-ident | - | `<device-ident> <properties> description=<desc>\n` | optional service argument may be used to get info about a single device, <br/>optional (device class specific) properties are in `key=value` form, <br/>`description` must be the last one and is the only one allowed to contain spaces; <br/>options can include `persistent=yes` for "persistently" attached devices (default is temporary)
| `mgmt.vm.microphone.Attach` | vm | - | - | - |
| `mgmt.vm.microphone.Detach` | vm | - | - | - |
| `mgmt.pool.List` | `dom0` | - | - | `<pool>\n` |
| `mgmt.pool.ListDrivers` | `dom0` | - | - | `<pool-driver> <property> ...\n` | Properties allowed in `mgmt.pool.Add`
| `mgmt.pool.Info` | `dom0` | pool | - | `<property>=<value>\n` |
| `mgmt.pool.Add` | `dom0` | driver | `<property>=<value>\n` | - |
| `mgmt.pool.Remove` | `dom0` | pool | - | - |
| `mgmt.pool.volume.List` | `dom0` | pool | - | volume id |
| `mgmt.pool.volume.Info` | `dom0` | pool | vid | `<property>=<value>\n` |
| `mgmt.pool.volume.ListSnapshots` | `dom0` | pool | vid | `<snapshot>\n` |
| `mgmt.pool.volume.Snapshot` | `dom0` | pool | vid | snapshot |
| `mgmt.pool.volume.Revert` | `dom0` | pool | `<vid> <snapshot>` | - |
| `mgmt.pool.volume.Resize` | `dom0` | pool | `<vid> <size_in_bytes>` | - |
| `mgmt.pool.volume.Import` | `dom0` | pool | `<vid>\n<raw volume data>` | - |
| `mgmt.vm.volume.List` | vm | - | - | `<volume>\n` | `<volume>` is per-VM volume name, `<vid>` is pool-unique volume id
| `mgmt.vm.volume.Info` | vm | volume | - | `<property>=<value>\n` |
| `mgmt.vm.volume.ListSnapshots` | vm | volume | - | snapshot | duplicate of `mgmt.pool.volume.`, but with other call params |
| `mgmt.vm.volume.Snapshot` | vm | volume | - | snapshot | id. |
| `mgmt.vm.volume.Revert` | vm | volume | snapshot | - | id. |
| `mgmt.vm.volume.Resize` | vm | volume | size_in_bytes | - | id. |
| `mgmt.vm.volume.Import` | vm | volume | raw volume data | - | id. |
| `mgmt.vm.Start` | vm | - | - | - |
| `mgmt.vm.Shutdown` | vm | - | - | - |
| `mgmt.vm.Pause` | vm | - | - | - |
| `mgmt.vm.Unpause` | vm | - | - | - |
| `mgmt.vm.Kill` | vm | - | - | - |
| `mgmt.backup.Execute` | `dom0` | config i | - | - | config in `/etc/qubes/backup/<id>.conf` |
| `mgmt.backup.Info` | `dom0` | ? | content? | ? |
| `mgmt.backup.Restore` | `dom0` | ? | content | ? |
| `mgmt.Events` | `dom0|vm` | - | - | events |
Volume properties:
- `pool`
- `vid`
- `size`
- `usage`
- `rw`
- `internal`
- `source`
- `save_on_stop`
- `snap_on_start`
## Returned messages
First byte of a message is a message type. This is 8 bit non-zero integer.
Values start at 0x30 (48, `'0'`, zero digit in ASCII) for readability in hexdump.
Next byte must be 0x00 (a separator).
This alternatively can be thought of as zero-terminated string containing
single ASCII digit.
### OK (0)
```
30 00 <content>
```
Server will close the connection after delivering single message.
### EVENT (1)
```
31 00 <subject> 00 <event> 00 ( <key> 00 <value> 00 )* 00
```
Events are returned as stream of messages in selected API calls. Normally server
will not close the connection.
A method yielding events will not ever return a `OK` or `EXCEPTION` message.
When calling such method, it will produce an artificial event
`connection-established` just after connection, to help avoiding race
conditions during event handler registration.
### EXCEPTION (2)
```
32 00 <type> 00 ( <traceback> )? 00 <format string> 00 ( <field> 00 )*
```
Server will close the connection.
Traceback may be empty, can be enabled server-side as part of debug mode.
Delimiting zero-byte is always present.
Fields are should substituted into `%`-style format string, possibly after
client-side translation, to form final message to be displayed unto user. Server
does not by itself support translation.
## Tags
- `created-by-<vm>`
- `managed-by-<vm>`
- `backup-<id>`
## General notes
- there is no provision for `qvm-run`, but there already exists `qubes.VMShell` call
- generally actions `*.List` return a list of objects and have "object
identifier" as first word in a row. Such action can be also called with "object
identifier" in argument to get only a single entry (in the same format).
- closing qrexec connection normally does _not_ interrupt running operation; this is important to avoid leaving the system in inconsistent state
- actual operation starts only after caller send all the parameters (including a payload), signaled by sending EOF mark; there is no support for interactive protocols, to keep the protocol reasonable simple
## TODO
- something to configure/update policy
- notifications
- how to constrain the events?
- how to pass the parameters? maybe XML, since this is trusted anyway and
parser may be complicated
- how to constrain the possible values for `mgmt.vm.property.Set` etc, like
"you can change `netvm`, but you have to pick from this set"; this currently
can be done by writing an extension
- a call for executing `*.desktop` file from `/usr/share/applications`, for use
with appmenus without giving access to `qubes.VMShell`; currently this can be
done by writing custom qrexec calls
- maybe some generator for `.desktop` for appmenus, which would wrap calls in
`qrexec-client-vm`
<!-- vim: set ts=4 sts=4 sw=4 et : -->