Command line options and configuration files
It is possible to configure a VM through command-line options and/or a JSON configuration file.
The names and format of configurations options are consistent between both ways of specifying, however the command-line includes options that are deprecated or unstable, whereas the configuration file only allows stable options. This section reviews how to use both.
Command-line options
Command-line options generally take a set of key-value pairs separated by the comma (,
) character.
The acceptable key-values for each option can be obtained by passing the --help
option to a crosvm
command:
crosvm run --help
...
-b, --block parameters for setting up a block device.
Valid keys:
path=PATH - Path to the disk image. Can be specified
without the key as the first argument.
ro=BOOL - Whether the block should be read-only.
(default: false)
root=BOOL - Whether the block device should be mounted
as the root filesystem. This will add the required
parameters to the kernel command-line. Can only be
specified once. (default: false)
sparse=BOOL - Indicates whether the disk should support
the discard operation. (default: true)
block-size=BYTES - Set the reported block size of the
disk. (default: 512)
id=STRING - Set the block device identifier to an ASCII
string, up to 20 characters. (default: no ID)
direct=BOOL - Use O_DIRECT mode to bypass page cache.
(default: false)
...
From this help message, we see that the --block
or -b
option accepts the path
, ro
, root
,
sparse
, block-size
, id
, and direct
keys. Keys which default value is mentioned are optional,
which means only the path
key must always be specified.
One example invocation of the --block
option could be:
--block path=/path/to/bzImage,root=true,block-size=4096
Keys taking a boolean parameters can be enabled by specifying their name witout any value, so the previous option can also be written as
--block path=/path/to/bzImage,root,block-size=4096
Also, the name of the first key can be entirely omitted, which further simplifies our option as:
--block /path/to/bzImage,root,block-size=4096
Configuration files
Configuration files are specified using the --cfg
argument. Here is an example configuration file
specifying a basic VM with a few devices:
{
"kernel": "/path/to/bzImage",
"cpus": {
"num-cores": 8
},
"mem": {
"size": 2048
},
"block": [
{
"path": "/path/to/root.img",
"root": true
}
],
"serial": [
{
"type": "stdout",
"hardware": "virtio-console",
"console": true,
"stdin": true
}
],
"net": [
{
"tap-name": "crosvm_tap"
}
]
}
The equivalent command-line options corresponding to this configuration file would be:
--kernel path/to/bzImage \
--cpus num-cores=8 --mem size=2048 \
--block path=/path/to/root.img,root \
--serial type=stdout,hardware=virtio-console,console,stdin \
--net tap-name=crosvm_tap
Or, if we apply the simplification rules discussed in the previous section:
--kernel /path/to/bzImage \
--cpus 8 --mem 2048 \
--block /path/to/root.img,root \
--serial stdout,hardware=virtio-console,console,stdin \
--net tap-name=crosvm_tap
Note that so cfg
directive can also be used within configuration files, allowing a form of
configuration inclusion:
{
...
"cfg": [ "net.json", "gpu.json" ],
...
}
Included files are always applied first. So in this example, the net.json
is the base
configuration to which gpu.json
is applied, and finally the parent file that included these two.
This order does not matter if each file specifies different options, but in case of overlap
parameters from the parent will take precedence over included ones, regardless of where the cfg
directive appears in the file.
Combining configuration files and command-line options
One useful use of configuration files is to specify a base configuration that can be augmented or modified by other configuration files or command-line arguments.
All the configuration files specified with --cfg
are merged by order of appearance into a single
configuration. The merge rules are generally that arguments that can only be specified once are
overwritten by the newest configuration, while arguments that can be specified many times (like
devices) are extended.
Finally, the other command-line parameters are merged into the configuration, regardless of their
position relative to a --cfg
argument (i.e. even if they come before it). This means that
command-line arguments take precedence over anything in configuration files.
For instance, considering this configuration file vm.json
:
{
"kernel": "/path/to/bzImage",
"block": [
{
"path": "/path/to/root.img",
"root": true
}
]
}
And the following crosvm invocation:
crosvm run --cfg vm.json --block /path/to/home.img
Then the created VM will have two block devices, the first one pointing to root.img
and the second
one to home.img
.
For options that can be specified only once, like --kernel
, the one specified on the command-line
will take precedence over the one in the configuration file. For instance, with the same vm.json
file and the following command-line:
crosvm run --cfg vm.json --kernel /path/to/another/bzImage
Then the loaded kernel will be /path/to/another/bzImage
, and the kernel
option in the
configuration file will become a no-op.