Driver BDM Data Structures¶
In addition to the API BDM data format there are also several internal data structures within Nova that map out how block devices are attached to instances. This document aims to outline the two general data structures and two additional specific data structures used by the libvirt virt driver.
This document is based on an email to the openstack-dev mailing list by Matthew Booth below provided as a primer for developers working on virt drivers and interacting with these data structures.
References to local disks in the following document refer to any disk directly managed by nova compute. If nova is configured to use RBD or NFS for instance disks then these disks won’t actually be local, but they are still managed locally and referred to as local disks. As opposed to RBD volumes provided by Cinder that are not considered local.
Generic BDM data structures¶
The ‘top level’ data structure is the
BlockDeviceMapping (BDM) object. It
NovaObject, persisted in the DB. Current code creates a BDM object for
every disk associated with an instance, whether it is a volume or not.
The BDM object describes properties of each disk as specified by the user. It is initially from a user request, for more details on the format of these requests please see the Block Device Mapping in Nova document.
The Compute API transforms and consolidates all BDMs to ensure that all disks,
explicit or implicit, have a BDM, and then persists them. Look in
nova.objects.block_device for all BDM fields, but in essence they contain
information like (source_type=’image’, destination_type=’local’,
image_id=’<image uuid’>), or equivalents describing ephemeral disks, swap disks
or volumes, and some associated data.
BDM objects are typically stored in variables called
bdm with lists
bdms, although this is obviously not guaranteed (and unfortunately
not always true:
libvirt.block_device is usually a
DriverBlockDevice object). This is a useful reading aid (except when
it’s proactively confounding), as there is also something else typically
block_device_mapping which is not a
Drivers do not directly use BDM objects. Instead, they are transformed into a
different driver-specific representation. This representation is normally
block_device_info, and is generated by
virt.driver.get_block_device_info(). Its output is based on data in BDMs.
block_device_info is a dict containing:
Hypervisor’s notion of the root device’s name
A list of all ephemeral disks
A list of all cinder volumes
A swap disk, or None if there is no swap disk
The disks are represented in one of two ways, depending on the specific driver currently in use. There’s the ‘new’ representation, used by the libvirt and vmwareAPI drivers, and the ‘legacy’ representation used by all other drivers. The legacy representation is a plain dict. It does not contain the same information as the new representation.
The new representation involves subclasses of
nova.block_device.DriverBlockDevice. As well as containing different
fields, the new representation significantly also retains a reference to the
underlying BDM object. This means that by manipulating the
DriverBlockDevice object, the driver is able to persist data to the BDM
object in the DB.
Common usage is to pull
block_device_mapping out of this
dict into a variable called
block_device_mapping. This is not a
BlockDeviceMapping object, or list of them.
block_device_info was passed to the driver by compute manager, it
was probably generated by
By default, this function filters out all cinder volumes from
block_device_mapping which don’t currently have
In other contexts this filtering will not have happened, and
block_device_mapping will contain all volumes.
block_device_info does not currently represent all
disks that an instance might have. Significantly, it will not contain any
representation of an image-backed local disk, i.e. the root disk of a
typical instance which isn’t boot-from-volume. Other representations used
by the libvirt driver explicitly reconstruct this missing disk.
libvirt driver specific BDM data structures¶
The virt driver API defines a method
get_instance_disk_info, which returns
a JSON blob. The compute manager calls this and passes the data over RPC
between calls without ever looking at it. This is driver-specific opaque data.
It is also only used by the libvirt driver, despite being part of the API for
all drivers. Other drivers do not return any data. The most interesting aspect
instance_disk_info is that it is generated from the libvirt XML, not
from nova’s state.
instance_disk_info is often named
disk_info in code, which
is unfortunate as this clashes with the normal naming of the next
structure. Occasionally the two are used in the same block of code.
RBD disks (including non-volume disks) and cinder volumes
are not included in
instance_disk_info is a list of dicts for some of an instance’s disks. Each
dict contains the following:
libvirt’s notion of the disk’s type
libvirt’s notion of the disk’s path
The disk’s virtual size in bytes (the size the guest OS sees)
libvirt’s notion of the backing file path
The file size of path, in bytes.
As-yet-unallocated disk size, in bytes.
As opposed to
instance_disk_info, which is frequently called
This data structure is actually described pretty well in the comment block at
the top of
nova.virt.libvirt.blockinfo. It is internal to the libvirt
driver. It contains:
The default bus used by disks
The default bus used by cdrom drives
mapping is a dict which maps disk names to a dict describing how that disk
should be passed to libvirt. This mapping contains every disk connected to the
instance, both local and volumes.
First, a note on disk naming. Local disk names used by the libvirt driver are well defined. They are:
The root disk
The flavor-defined ephemeral disk
Where X is a zero-based index for BDM defined ephemeral disks
The swap disk
The config disk
These names are hardcoded, reliable, and used in lots of places.
disk_info, volumes are keyed by device name, eg ‘vda’, ‘vdb’. Different
buses will be named differently, approximately according to legacy Linux
disk_info will contain a mapping for ‘root’, which is the
root disk. This will duplicate one of the other entries, either ‘disk’ or a
Each dict within the
mapping dict contains the following 3 required fields
of bus, dev and type with two optional fields of format and
The guest bus type (‘ide’, ‘virtio’, ‘scsi’, etc)
The device name ‘vda’, ‘hdc’, ‘sdf’, ‘xvde’ etc
Type of device eg ‘disk’, ‘cdrom’, ‘floppy’
Which format to apply to the device if applicable
Number designating the boot order of the device
DriverBlockDevice store boot index
zero-based. However, libvirt’s boot index is 1-based, so the value stored
here is 1-based.
Add a section for the per disk
disk.info file within instance
directory when using the libvirt driver.