[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] RFC v2: blockdev_add & friends, brief rationale, QMP docs
From: |
Markus Armbruster |
Subject: |
[Qemu-devel] RFC v2: blockdev_add & friends, brief rationale, QMP docs |
Date: |
Thu, 10 Jun 2010 19:45:38 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) |
v2: Cover protocols
Split blockdev_change into media_insert and media_remove
Option syntax
list TODOs
Rationale: Why new commands for block devices?
==============================================
We want a clean separation between host part and guest part. Existing
-drive and drive_add don't provide that; they were designed to specify
both parts together. Moreover, drive_add is limited to adding virtio
drives (with pci_add's help) and SCSI drives.
We already have commands to specify the guest part: -device and
device_add.
Support for defining just a host part for use with -device and
device_add was grafted onto -drive and drive_add (if=none), but it's a
mess. Some parts are redundant, other parts are broken.
For instance, unit, bus, index, addr are redundant: -device/device_add
don't use them. They provide their own parameters to specify bus and
bus-specific address.
The checks whether rerror, werror, readonly, cyls, heads, secs are sane
for a particular guest device model are broken. The checks are in the
-drive code, which used to know what the guest device model supports,
but can't with if=none.
Moreover, -drive/drive_add have several flaws:
* Many parameters set with -drive/drive_add silently revert to defaults
on media change.
* There are two ways to specify protocol, and both are flawed: you
either use parameter format (then you can neither specify a
non-default format, nor supply protocol options), or encode it in
parameter file (yet another ad hoc mini-language, breaks filenames
with ':').
* Behavior when format= is missing is insecure.
My proposed solution is a new option -blockdev and monitor command
blockdev_add. These specify only the host drive. Guest drive
properties are left to -device/device_add. We keep -drive for backwards
compatibility and command line convenience. Except we get rid of
if=none (may need a grace period).
New monitor command blockdev_del works regardless of how the host block
device was created.
New monitor commands media_insert, media_remove provide full control
over the host part, unlike the existing change command.
Summary of the host / guest split:
-drive options host or guest?
bus, unit, if, index, addr guest, already covered by qdev
cyls, heads, secs, trans guest, new qdev properties
(but defaults depend on image)
media guest FIXME
snapshot, cache, aio host, blockdev_add options
file, format host, blockdev_add options
separate option for protocol
format is just that, not protocol
file is just a filename, no protocol
rerror, werror host, guest device models will
reject values they don't support
serial guest, new qdev properties
readonly both host & guest, qdev will refuse to
connect readonly host to read/write
guest
QMP command docs
================
blockdev_add
------------
Add host block device.
Arguments:
- "id": the host block device's ID, must be unique (json-string)
- "format": image format (json-string, optional)
- Possible values: "raw", "qcow2", ...
- "protocol": image access protocol (json-object, optional)
- Has a member "type" (json-string), and depending on its value
additional members
- For "type" = "file", [...]
- "file": name of image file (json-string)
- For "type" = "nbd":
- "domain": address family (json-string, optional)
- Possible values: "inet" (default), "unix"
- "file": name of socket file (json-string), only with "domain" =
"unix"
- "host": host name (json-string), only with "domain" = "inet"
- "port": port (json-int), only with "domain" = "inet"
- For "type" = "blkdebug":
- "config": name of config file (json-string)
- "protocol": image access protocol (json-object), as above
[...]
- "aio": host AIO (json-string, optional)
- Possible values: "threads" (default), "native"
- "cache": host cache usage (json-string, optional)
- Possible values: "writethrough" (default), "writeback", "unsafe",
"none"
- "readonly": open image read-only (json-bool, optional, default false)
- "rerror": what to do on read error (json-string, optional)
- Possible values: "report" (default), "ignore", "stop"
- "werror": what to do on write error (json-string, optional)
- Possible values: "enospc" (default), "report", "ignore", "stop"
- "snapshot": enable snapshot (json-bool, optional, default false)
Example:
-> { "execute": "blockdev_add",
"arguments": { "id": "blk1", "format": "raw",
"protocol": { "type": "file", "file": "fedora.img" } } }
<- { "return": {} }
-> { "execute": "blockdev_add",
"arguments": {
"id": "blk2", "format": "qcow2",
"protocol": {
"type": "blkdebug", "config": "test.blkdebug",
"protocol": { "type": "file", "file": "test.qcow2" }
}
}
}
<- { "return": {} }
Notes:
(1) If argument "protocol" is missing, all other optional arguments must
be missing as well. This defines a block device with no media
inserted.
(2) In theory, the protocols form a tree. In practice, all protocols
but blkdebug have no children, and blkdebug has just one.
(3) It's possible to list supported disk formats by running QEMU with
arguments "-blockdev_add \?".
blockdev_del
------------
Remove a host block device.
Arguments:
- "id": the host block device's ID (json-string)
Example:
-> { "execute": "blockdev_del", "arguments": { "id": "blk1" } }
<- { "return": {} }
media_insert
------------
Insert media into an empty host block device.
Arguments are exactly like blockdev_add, except "protocol" is mandatory.
media_remove
------------
Remove media from a host block device.
Arguments:
- "id": the host block device's ID (json-string)
Example:
-> { "execute": "media_remove", "arguments": { "id": "blk1" } }
<- { "return": {} }
Command line syntax
===================
We want common setups to be simple, and fancy setups to be possible.
"Simple" means use of common QemuOpts syntax, and reasonable defaults.
The trouble are protocols. QemuOpts provides a list of options.
Protocols stack, so in the general case, we need a tree of lists of
options.
I can see a couple of ways to do this, and each of them sucks in its own
way.
Let me start with QMP snippets for the examples I'm going to use:
* The common case: a single protocol
{
"id": "blk1", "format": "raw",
"protocol": { "type": "file", "file": "fedora.img" }
}
* blkdebug
{
"id": "blk2", "format": "qcow2",
"protocol": {
"type": "blkdebug", "config": "test.blkdebug",
"protocol": { "type": "file", "file": "test.qcow2" }
}
}
* Avi's hypothetical mirror protocol
{
"id": "blk3", "format": "raw",
"protocol": {
"type": "mirror",
"protocols": [
{ "type": "file", "file": "local.img" }
{ "type": "nbd", "domain": "unix", "socket": "nbd-sock" }
]
}
}
I think we can all agree that the common case should look as simple as
this:
-blockdev id=blk1,file=fedora.img (*)
Here, file=fedora.img has the intuitive meaning "use fedora.img with the
appropriate protocol and a default format". Since fedora.img is not a
special file, the appropriate protocol is "file". The default format is
"raw". Maybe we want to pick default format based on filename,
say. "qcow2" when the file name ends with ".qcow2".
Now let's examine what we can do to provide for the general case.
1. Make QemuOpts recursive, add brackets to its syntax
This has several serious drawbacks:
* No matter what kind of bracket we choose, the shell will be unhappy
with it, unless we quote them. Angle brackets fail destructively
(redirection). Curly braces suffer brace expansion. Parenthesis
fail reliably. Square brackets suffer filename expansion.
However, since actual match is unlikely, they're likely to just
work. Except with shopt failglob they fail reliably. I guess
they're the least bad choice.
* We need a way to escape the brackets, or else we can't do filenames
containing brackets.
We better choose an escape syntax that doesn't interfere with the
shell's.
If we make brackets special characters in all option values, then
no matter what escape syntax we choose, we'll break existing usage.
In particular, brackets in filenames would need escaping.
The one exception is to use ',' as escape character, but that's
just too ugly.
If we make brackets special characters only in values of structured
options like protocol, our syntax becomes context-sensitive. Ugh.
* Our config file format is in INI syntax. QemuOpts correspond to
INI sections. Sections can't be nested, so recursive QemuOpts
don't translate.
Examples:
* Single protocol:
-blockdev id=blk1,format=raw,protocol=[file,file=fedora.img]
Requires suitable syntactic sugar to get the simple form (*).
* blkdebug
-blockdev id=blk2,format=qcow2,\
protocol=[blkdebug,config=test.blkdebug,\
protocol=[file,file=test.qcow2]]
* Avi's mirror:
-blockdev id=blk3,format=raw,\
protocol=[mirror,\
[file,file=local.img],\
[nbd,domain=unix,sockert=nbd-sock]]
2. We already have a syntax to specify trees, namely JSON, so use it
If -blockdev's argument starts with '{', it's a JSON object suitable
as argument of blockdev_add in QMP.
We still provide ordinary QemuOpts syntax for the cases that can be
expressed with it, i.e. single protocol.
I figure we'd want syntactic sugar for blkdebug, to permit its use
from the command line without having to resort to JSON.
3. Stack protocols through named references
The first protocol is "inlined" into -blockdev. Any further
protocols need to be referenced by name.
Best explained by example:
* Single protocol:
-blockdev id=blk1,format=raw,protocol=file,file=fedora.img
To get the simple form (*), make protocol optional with a suitable
default.
* blkdebug
-blockdev id=blk2,format=qcow2,protocol=blkdebug,config=test.blkdebug,\
base=blk2-base
-blockproto id=blk2-base,protocol=file,file=test.qcow2
* Avi's mirror:
-blockdev id=blk3,format=raw,protocol=mirror,\
base=blk3-base1,base=blk3=base2
-blockproto id=blk3-base1,protocol=file,file=local.img
-blockproto id=blk3-base2,protocol=nbd,domain=unix,sockert=nbd-sock
Anything but a single protocol becomes pretty verbose. Syntactic
sugar for the blkdebug case would be possible; not sure it's worth
it.
No QemuOpts syntax changes. INI can handle this just fine.
TODO
====
* Pick a command line syntax
* Human monitor syntax
- [Qemu-devel] RFC v2: blockdev_add & friends, brief rationale, QMP docs,
Markus Armbruster <=
- Re: [Qemu-devel] RFC v2: blockdev_add & friends, brief rationale, QMP docs, Avi Kivity, 2010/06/15
- Re: [Qemu-devel] RFC v2: blockdev_add & friends, brief rationale, QMP docs, Markus Armbruster, 2010/06/15
- Re: [Qemu-devel] RFC v2: blockdev_add & friends, brief rationale, QMP docs, Avi Kivity, 2010/06/15
- Re: [Qemu-devel] RFC v2: blockdev_add & friends, brief rationale, QMP docs, Markus Armbruster, 2010/06/15
- Re: [Qemu-devel] RFC v2: blockdev_add & friends, brief rationale, QMP docs, Avi Kivity, 2010/06/15
- Re: [Qemu-devel] RFC v2: blockdev_add & friends, brief rationale, QMP docs, Markus Armbruster, 2010/06/15
- Re: [Qemu-devel] RFC v2: blockdev_add & friends, brief rationale, QMP docs, Avi Kivity, 2010/06/16
- Re: [Qemu-devel] RFC v2: blockdev_add & friends, brief rationale, QMP docs, Markus Armbruster, 2010/06/16
- Re: [Qemu-devel] RFC v2: blockdev_add & friends, brief rationale, QMP docs, Avi Kivity, 2010/06/16
[Qemu-devel] Re: RFC v2: blockdev_add & friends, brief rationale, QMP docs, Avi Kivity, 2010/06/15