Driver BDM 数据结构¶
除了 API BDM 数据格式 之外,Nova 内部还有几个数据结构,用于映射块设备到实例的方式。本文档旨在概述两种通用数据结构和 libvirt virt 驱动程序使用的两种特定数据结构。
注意
本文档基于 Matthew Booth 发送给 openstack-dev 邮件列表的一封邮件,如下所示,作为开发人员在使用 virt 驱动程序并与这些数据结构交互时的入门指南。
http://lists.openstack.org/pipermail/openstack-dev/2016-June/097529.html
注意
以下文档中对本地磁盘的引用是指由 nova compute 直接管理的任何磁盘。如果 nova 配置为使用 RBD 或 NFS 作为实例磁盘,那么这些磁盘实际上并非本地磁盘,但它们仍然在本地管理并称为本地磁盘。与 Cinder 提供的 RBD 卷不同,后者不被视为本地磁盘。
通用 BDM 数据结构¶
BlockDeviceMapping¶
“顶层”数据结构是 BlockDeviceMapping (BDM) 对象。它是一个 NovaObject,持久化在数据库中。当前代码为与实例关联的每个磁盘(无论是卷还是其他)创建一个 BDM 对象。
BDM 对象描述了用户指定每个磁盘的属性。最初来自用户请求,有关这些请求的格式的详细信息,请参阅 Nova 中的块设备映射 文档。
Compute API 转换并合并所有 BDM,以确保所有磁盘(显式或隐式)都具有 BDM,然后将其持久化。请查看 nova.objects.block_device 以获取所有 BDM 字段,但本质上它们包含诸如 (source_type=’image’, destination_type=’local’, image_id=’<image uuid’>) 之类的信息,或者描述临时磁盘、交换磁盘或卷的等效信息,以及一些相关数据。
注意
BDM 对象通常存储在名为 bdm 的变量中,列表存储在 bdms 中,尽管这显然并非保证(而且不幸的是并非总是如此:bdm 在 libvirt.block_device 中通常是一个 DriverBlockDevice 对象)。这是一种有用的阅读辅助工具(除非它主动令人困惑),因为还有一些通常称为 block_device_mapping 的东西,它不是 BlockDeviceMapping 对象。
block_device_info¶
版本 24.0.0 中更改: (Xena)
旧版 block_device_info 格式不再受支持。
驱动程序不直接使用 BDM 对象。相反,它们被转换为不同的驱动程序特定表示形式。这种表示形式通常称为 block_device_info,由 virt.driver.get_block_device_info() 生成。其输出基于 BDM 中的数据。block_device_info 是一个包含以下内容的字典:
root_device_name超visor 对根设备的名称
image如果使用基于镜像的磁盘
ephemerals所有临时磁盘的列表
block_device_mapping所有 cinder 卷的列表
swap交换磁盘,如果没有交换磁盘则为 None
注意
磁盘先前以两种方式之一表示,具体取决于所使用的特定驱动程序。旧版纯字典格式或当前使用的 DriverBlockDevice 格式(如下所述)。Xena 中已删除对旧版格式的支持。
磁盘由 nova.block_device.DriverBlockDevice 的子类表示。这些子类保留对底层 BDM 对象的引用。这意味着通过操作 DriverBlockDevice 对象,驱动程序能够将数据持久化到数据库中的 BDM 对象。
注意
常见用法是从此字典中提取 block_device_mapping 到名为 block_device_mapping 的变量中。这不是 BlockDeviceMapping 对象,也不是它们的列表。
注意
如果 block_device_info 由 compute manager 传递给驱动程序,则它可能是由 _get_instance_block_device_info() 生成的。默认情况下,此函数会从 block_device_mapping 中过滤掉所有当前没有 connection_info 的 cinder 卷。在其他上下文中,此过滤不会发生,并且 block_device_mapping 将包含所有卷。
libvirt 驱动程序特定的 BDM 数据结构¶
instance_disk_info¶
virt 驱动程序 API 定义了一个方法 get_instance_disk_info,它返回一个 JSON blob。compute manager 调用此方法并通过 RPC 在调用之间传递数据,而无需查看它。这是特定于驱动程序的、不透明的数据。它也仅由 libvirt 驱动程序使用,尽管它是所有驱动程序的 API 的一部分。其他驱动程序不返回任何数据。instance_disk_info 最有趣的地方在于它是从 libvirt XML 生成的,而不是从 nova 的状态生成的。
注意
instance_disk_info 通常在代码中命名为 disk_info,这很不幸,因为它与下一个结构的常规命名冲突。有时两者在同一代码块中使用。
注意
RBD 磁盘(包括非卷磁盘)和 cinder 卷不包含在 instance_disk_info 中。
instance_disk_info 是一个实例磁盘的字典列表。每个字典包含以下内容:
typelibvirt 对磁盘的类型的概念
路径libvirt 对磁盘路径的概念
virt_disk_size磁盘的虚拟大小(字节),即客户机操作系统看到的大小
backing_filelibvirt 对 backing 文件路径的概念
disk_size路径的文件大小(字节)。
over_committed_disk_size尚未分配的磁盘大小(字节)。
disk_info¶
注意
与 instance_disk_info 相比,后者通常称为 disk_info。
此数据结构实际上在 nova.virt.libvirt.blockinfo 的顶部注释块中描述得很好。它是 libvirt 驱动程序内部的。它包含
disk_bus磁盘使用的默认总线
cdrom_bus光驱使用的默认总线
映射定义如下
mapping 是一个字典,它将磁盘名称映射到描述如何将该磁盘传递给 libvirt 的字典。此映射包含连接到实例的每个磁盘,包括本地磁盘和卷。
首先,关于磁盘命名。libvirt 驱动程序使用的本地磁盘名称定义明确。它们是
disk根磁盘
disk.localflavor 定义的临时磁盘
disk.ephX其中 X 是 BDM 定义的临时磁盘的从零开始的索引
disk.swap交换磁盘
disk.config配置磁盘
这些名称是硬编码的、可靠的,并且在许多地方使用。
在 disk_info 中,卷按设备名称键入,例如 ‘vda’、‘vdb’。不同的总线将以不同的方式命名,大致按照旧版 Linux 设备命名规则。
此外,disk_info 将包含一个名为 ‘root’ 的映射,它是根磁盘。这将重复其他条目之一,即 ‘disk’ 或卷映射。
mapping 字典中的每个字典包含以下 3 个必需字段:bus、dev 和 type,以及两个可选字段:format 和 boot_index
bus:客户机总线类型(‘ide’、‘virtio’、‘scsi’ 等)
dev:设备名称 ‘vda’、‘hdc’、‘sdf’、‘xvde’ 等
type:设备类型,例如 ‘disk’、‘cdrom’、‘floppy’
format如果适用,应用于设备的格式
boot_index设备的启动顺序编号
注意
BlockDeviceMapping 和 DriverBlockDevice 存储从零开始的启动索引。但是,libvirt 的启动索引是从 1 开始的,因此此处存储的值是从 1 开始的。
待办事项
在 libvirt 驱动程序使用实例目录时,为每个磁盘 disk.info 文件添加一个部分。