Add image meta to libvirt XML metadata
This patch adds the image_meta used to launch an instance to its libvirt domain metadata. Nova exposes the image_meta structure when publishing instance notifications. Downstream services that consume these notifications such as Ceilometer use this to provide metadata about the image originally used to create an ephemeral instance or instance boot volume. Ceilometer also polls the running instances using the Compute Agent by reading the metadata of active instances from the libvirt socket. Adding the data stored in image_meta to the libvirt metadata allows Ceilometer to discover and expose the actual image metadata used to launch instances using its compute pollsters, without performing additional API queries to Nova, Cinder and Glance to get this information (and even if that was done, it could be different to what is actually running if images are updated after the fact). To match the existing image_meta definition from Nova notifications, depending on the type of instance, the behaviour of the metadata is: * Instance built from image => UUID set for image, image metadata added to the XML * Instance launched from volume built from image => UUID empty, volume image metadata added to the XML * Instance launched from volume NOT built from image => UUID empty, no attributes from image meta defined Signed-off-by: Callum Dickinson <callum.dickinson@catalystcloud.nz> Implements: blueprint xml-image-meta Change-Id: I09f4f76fff30f9cccf35f4832b9c870095c380ad
This commit is contained in:
@@ -224,6 +224,10 @@ def get_test_instance_driver_metadata(**kw):
|
||||
projectname='testproject')
|
||||
default_image_meta = driver.ImageMeta(id=TEST_IMAGE_UUID,
|
||||
name=TEST_IMAGE_NAME,
|
||||
container_format=None,
|
||||
disk_format=None,
|
||||
min_disk=None,
|
||||
min_ram=None,
|
||||
properties={})
|
||||
default_flavor_meta = driver.FlavorMeta(
|
||||
name=kw.get('flavor_name', TEST_FLAVOR_NAME),
|
||||
|
||||
@@ -23,6 +23,7 @@ from nova import exception
|
||||
from nova.objects import fields as obj_fields
|
||||
from nova import test
|
||||
from nova.tests.fixtures import libvirt_data as fake_libvirt_data
|
||||
from nova.virt import driver
|
||||
from nova.virt import hardware
|
||||
from nova.virt.libvirt import config
|
||||
|
||||
@@ -4099,91 +4100,6 @@ class LibvirtConfigGuestNUMATuneTest(LibvirtConfigBaseTest):
|
||||
|
||||
class LibvirtConfigGuestMetadataNovaTest(LibvirtConfigBaseTest):
|
||||
|
||||
def test_config_metadata(self):
|
||||
meta = config.LibvirtConfigGuestMetaNovaInstance()
|
||||
meta.package = "2014.2.3"
|
||||
meta.name = "moonbuggy"
|
||||
meta.creationTime = 1234567890
|
||||
meta.roottype = "image"
|
||||
meta.rootid = "fe55c69a-8b2e-4bbc-811a-9ad2023a0426"
|
||||
|
||||
owner = config.LibvirtConfigGuestMetaNovaOwner()
|
||||
owner.userid = "3472c2a6-de91-4fb5-b618-42bc781ef670"
|
||||
owner.username = "buzz"
|
||||
owner.projectid = "f241e906-010e-4917-ae81-53f4fb8aa021"
|
||||
owner.projectname = "moonshot"
|
||||
|
||||
meta.owner = owner
|
||||
|
||||
flavor = config.LibvirtConfigGuestMetaNovaFlavor()
|
||||
flavor.name = "m1.lowgravity"
|
||||
flavor.id = "f719a0dd-4b43-4efe-8336-48ef74099ad4"
|
||||
flavor.vcpus = 8
|
||||
flavor.memory = 2048
|
||||
flavor.swap = 10
|
||||
flavor.disk = 50
|
||||
flavor.ephemeral = 10
|
||||
|
||||
meta.flavor = flavor
|
||||
|
||||
meta.ports = config.LibvirtConfigGuestMetaNovaPorts(
|
||||
ports=[
|
||||
config.LibvirtConfigGuestMetaNovaPort(
|
||||
'567a4527-b0e4-4d0a-bcc2-71fda37897f7',
|
||||
ips=[
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', '192.168.1.1', '4'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', 'fe80::f95c:b030:7094', '6'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'floating', '11.22.33.44', '4')]),
|
||||
config.LibvirtConfigGuestMetaNovaPort(
|
||||
'a3ca97e2-0cf9-4159-9bfc-afd55bc13ead',
|
||||
ips=[
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', '10.0.0.1', '4'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', 'fdf8:f53b:82e4::52', '6'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'floating', '1.2.3.4', '4')])])
|
||||
|
||||
xml = meta.to_xml()
|
||||
self.assertXmlEqual(xml, """
|
||||
<nova:instance xmlns:nova='http://openstack.org/xmlns/libvirt/nova/1.1'>
|
||||
<nova:package version="2014.2.3"/>
|
||||
<nova:name>moonbuggy</nova:name>
|
||||
<nova:creationTime>2009-02-13 23:31:30</nova:creationTime>
|
||||
<nova:flavor name="m1.lowgravity"
|
||||
id="f719a0dd-4b43-4efe-8336-48ef74099ad4">
|
||||
<nova:memory>2048</nova:memory>
|
||||
<nova:disk>50</nova:disk>
|
||||
<nova:swap>10</nova:swap>
|
||||
<nova:ephemeral>10</nova:ephemeral>
|
||||
<nova:vcpus>8</nova:vcpus>
|
||||
<nova:extraSpecs></nova:extraSpecs>
|
||||
</nova:flavor>
|
||||
<nova:owner>
|
||||
<nova:user
|
||||
uuid="3472c2a6-de91-4fb5-b618-42bc781ef670">buzz</nova:user>
|
||||
<nova:project
|
||||
uuid="f241e906-010e-4917-ae81-53f4fb8aa021">moonshot</nova:project>
|
||||
</nova:owner>
|
||||
<nova:root type="image" uuid="fe55c69a-8b2e-4bbc-811a-9ad2023a0426"/>
|
||||
<nova:ports>
|
||||
<nova:port uuid="567a4527-b0e4-4d0a-bcc2-71fda37897f7">
|
||||
<nova:ip type="fixed" address="192.168.1.1" ipVersion="4"/>
|
||||
<nova:ip type="fixed" address="fe80::f95c:b030:7094" ipVersion="6"/>
|
||||
<nova:ip type="floating" address="11.22.33.44" ipVersion="4"/>
|
||||
</nova:port>
|
||||
<nova:port uuid="a3ca97e2-0cf9-4159-9bfc-afd55bc13ead">
|
||||
<nova:ip type="fixed" address="10.0.0.1" ipVersion="4"/>
|
||||
<nova:ip type="fixed" address="fdf8:f53b:82e4::52" ipVersion="6"/>
|
||||
<nova:ip type="floating" address="1.2.3.4" ipVersion="4"/>
|
||||
</nova:port>
|
||||
</nova:ports>
|
||||
</nova:instance>
|
||||
""")
|
||||
|
||||
def test_config_metadata_flavor_extra_specs(self):
|
||||
meta = config.LibvirtConfigGuestMetaNovaInstance()
|
||||
meta.package = "2014.2.3"
|
||||
@@ -4272,6 +4188,317 @@ class LibvirtConfigGuestMetadataNovaTest(LibvirtConfigBaseTest):
|
||||
</nova:instance>
|
||||
""")
|
||||
|
||||
def test_config_metadata_from_image(self):
|
||||
meta = config.LibvirtConfigGuestMetaNovaInstance()
|
||||
meta.package = "2014.2.3"
|
||||
meta.name = "moonbuggy"
|
||||
meta.creationTime = 1234567890
|
||||
meta.roottype = "image"
|
||||
meta.rootid = "fe55c69a-8b2e-4bbc-811a-9ad2023a0426"
|
||||
|
||||
imeta = config.LibvirtConfigGuestMetaImage()
|
||||
imeta.uuid = meta.rootid
|
||||
imeta.image_meta = driver.ImageMeta(
|
||||
id=meta.rootid,
|
||||
name="ubuntu-24.04-x86_64",
|
||||
container_format="bare",
|
||||
disk_format="raw",
|
||||
min_disk=10,
|
||||
min_ram=0,
|
||||
properties={"os_distro": "ubuntu",
|
||||
"os_type": "linux",
|
||||
"img_version": 1,
|
||||
"img_use_agent": True})
|
||||
|
||||
meta.image = imeta
|
||||
|
||||
owner = config.LibvirtConfigGuestMetaNovaOwner()
|
||||
owner.userid = "3472c2a6-de91-4fb5-b618-42bc781ef670"
|
||||
owner.username = "buzz"
|
||||
owner.projectid = "f241e906-010e-4917-ae81-53f4fb8aa021"
|
||||
owner.projectname = "moonshot"
|
||||
|
||||
meta.owner = owner
|
||||
|
||||
flavor = config.LibvirtConfigGuestMetaNovaFlavor()
|
||||
flavor.name = "m1.lowgravity"
|
||||
flavor.id = "f719a0dd-4b43-4efe-8336-48ef74099ad4"
|
||||
flavor.vcpus = 8
|
||||
flavor.memory = 2048
|
||||
flavor.swap = 10
|
||||
flavor.disk = 50
|
||||
flavor.ephemeral = 10
|
||||
|
||||
meta.flavor = flavor
|
||||
|
||||
meta.ports = config.LibvirtConfigGuestMetaNovaPorts(
|
||||
ports=[
|
||||
config.LibvirtConfigGuestMetaNovaPort(
|
||||
'567a4527-b0e4-4d0a-bcc2-71fda37897f7',
|
||||
ips=[
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', '192.168.1.1', '4'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', 'fe80::f95c:b030:7094', '6'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'floating', '11.22.33.44', '4')]),
|
||||
config.LibvirtConfigGuestMetaNovaPort(
|
||||
'a3ca97e2-0cf9-4159-9bfc-afd55bc13ead',
|
||||
ips=[
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', '10.0.0.1', '4'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', 'fdf8:f53b:82e4::52', '6'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'floating', '1.2.3.4', '4')])])
|
||||
|
||||
xml = meta.to_xml()
|
||||
self.assertXmlEqual(xml, """
|
||||
<nova:instance xmlns:nova='http://openstack.org/xmlns/libvirt/nova/1.1'>
|
||||
<nova:package version="2014.2.3"/>
|
||||
<nova:name>moonbuggy</nova:name>
|
||||
<nova:creationTime>2009-02-13 23:31:30</nova:creationTime>
|
||||
<nova:flavor name="m1.lowgravity"
|
||||
id="f719a0dd-4b43-4efe-8336-48ef74099ad4">
|
||||
<nova:memory>2048</nova:memory>
|
||||
<nova:disk>50</nova:disk>
|
||||
<nova:swap>10</nova:swap>
|
||||
<nova:ephemeral>10</nova:ephemeral>
|
||||
<nova:vcpus>8</nova:vcpus>
|
||||
<nova:extraSpecs></nova:extraSpecs>
|
||||
</nova:flavor>
|
||||
<nova:image uuid="fe55c69a-8b2e-4bbc-811a-9ad2023a0426">
|
||||
<nova:containerFormat>bare</nova:containerFormat>
|
||||
<nova:diskFormat>raw</nova:diskFormat>
|
||||
<nova:minDisk>10</nova:minDisk>
|
||||
<nova:minRam>0</nova:minRam>
|
||||
<nova:properties>
|
||||
<nova:property name="os_distro">ubuntu</nova:property>
|
||||
<nova:property name="os_type">linux</nova:property>
|
||||
<nova:property name="img_version">1</nova:property>
|
||||
<nova:property name="img_use_agent">True</nova:property>
|
||||
</nova:properties>
|
||||
</nova:image>
|
||||
<nova:owner>
|
||||
<nova:user
|
||||
uuid="3472c2a6-de91-4fb5-b618-42bc781ef670">buzz</nova:user>
|
||||
<nova:project
|
||||
uuid="f241e906-010e-4917-ae81-53f4fb8aa021">moonshot</nova:project>
|
||||
</nova:owner>
|
||||
<nova:root type="image" uuid="fe55c69a-8b2e-4bbc-811a-9ad2023a0426"/>
|
||||
<nova:ports>
|
||||
<nova:port uuid="567a4527-b0e4-4d0a-bcc2-71fda37897f7">
|
||||
<nova:ip type="fixed" address="192.168.1.1" ipVersion="4"/>
|
||||
<nova:ip type="fixed" address="fe80::f95c:b030:7094" ipVersion="6"/>
|
||||
<nova:ip type="floating" address="11.22.33.44" ipVersion="4"/>
|
||||
</nova:port>
|
||||
<nova:port uuid="a3ca97e2-0cf9-4159-9bfc-afd55bc13ead">
|
||||
<nova:ip type="fixed" address="10.0.0.1" ipVersion="4"/>
|
||||
<nova:ip type="fixed" address="fdf8:f53b:82e4::52" ipVersion="6"/>
|
||||
<nova:ip type="floating" address="1.2.3.4" ipVersion="4"/>
|
||||
</nova:port>
|
||||
</nova:ports>
|
||||
</nova:instance>
|
||||
""")
|
||||
|
||||
def test_config_metadata_from_volume_image(self):
|
||||
meta = config.LibvirtConfigGuestMetaNovaInstance()
|
||||
meta.package = "2014.2.3"
|
||||
meta.name = "moonbuggy"
|
||||
meta.creationTime = 1234567890
|
||||
|
||||
imeta = config.LibvirtConfigGuestMetaImage()
|
||||
imeta.image_meta = driver.ImageMeta(
|
||||
id="",
|
||||
name="",
|
||||
container_format="bare",
|
||||
disk_format="raw",
|
||||
min_disk=10,
|
||||
min_ram=0,
|
||||
properties={"os_distro": "ubuntu",
|
||||
"os_type": "linux",
|
||||
"img_version": 1,
|
||||
"img_use_agent": True})
|
||||
|
||||
meta.image = imeta
|
||||
|
||||
owner = config.LibvirtConfigGuestMetaNovaOwner()
|
||||
owner.userid = "3472c2a6-de91-4fb5-b618-42bc781ef670"
|
||||
owner.username = "buzz"
|
||||
owner.projectid = "f241e906-010e-4917-ae81-53f4fb8aa021"
|
||||
owner.projectname = "moonshot"
|
||||
|
||||
meta.owner = owner
|
||||
|
||||
flavor = config.LibvirtConfigGuestMetaNovaFlavor()
|
||||
flavor.name = "m1.lowgravity"
|
||||
flavor.id = "f719a0dd-4b43-4efe-8336-48ef74099ad4"
|
||||
flavor.vcpus = 8
|
||||
flavor.memory = 2048
|
||||
flavor.swap = 10
|
||||
flavor.disk = 50
|
||||
flavor.ephemeral = 10
|
||||
|
||||
meta.flavor = flavor
|
||||
|
||||
meta.ports = config.LibvirtConfigGuestMetaNovaPorts(
|
||||
ports=[
|
||||
config.LibvirtConfigGuestMetaNovaPort(
|
||||
'567a4527-b0e4-4d0a-bcc2-71fda37897f7',
|
||||
ips=[
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', '192.168.1.1', '4'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', 'fe80::f95c:b030:7094', '6'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'floating', '11.22.33.44', '4')]),
|
||||
config.LibvirtConfigGuestMetaNovaPort(
|
||||
'a3ca97e2-0cf9-4159-9bfc-afd55bc13ead',
|
||||
ips=[
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', '10.0.0.1', '4'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', 'fdf8:f53b:82e4::52', '6'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'floating', '1.2.3.4', '4')])])
|
||||
|
||||
xml = meta.to_xml()
|
||||
self.assertXmlEqual(xml, """
|
||||
<nova:instance xmlns:nova='http://openstack.org/xmlns/libvirt/nova/1.1'>
|
||||
<nova:package version="2014.2.3"/>
|
||||
<nova:name>moonbuggy</nova:name>
|
||||
<nova:creationTime>2009-02-13 23:31:30</nova:creationTime>
|
||||
<nova:flavor name="m1.lowgravity"
|
||||
id="f719a0dd-4b43-4efe-8336-48ef74099ad4">
|
||||
<nova:memory>2048</nova:memory>
|
||||
<nova:disk>50</nova:disk>
|
||||
<nova:swap>10</nova:swap>
|
||||
<nova:ephemeral>10</nova:ephemeral>
|
||||
<nova:vcpus>8</nova:vcpus>
|
||||
<nova:extraSpecs></nova:extraSpecs>
|
||||
</nova:flavor>
|
||||
<nova:image uuid="">
|
||||
<nova:containerFormat>bare</nova:containerFormat>
|
||||
<nova:diskFormat>raw</nova:diskFormat>
|
||||
<nova:minDisk>10</nova:minDisk>
|
||||
<nova:minRam>0</nova:minRam>
|
||||
<nova:properties>
|
||||
<nova:property name="os_distro">ubuntu</nova:property>
|
||||
<nova:property name="os_type">linux</nova:property>
|
||||
<nova:property name="img_version">1</nova:property>
|
||||
<nova:property name="img_use_agent">True</nova:property>
|
||||
</nova:properties>
|
||||
</nova:image>
|
||||
<nova:owner>
|
||||
<nova:user
|
||||
uuid="3472c2a6-de91-4fb5-b618-42bc781ef670">buzz</nova:user>
|
||||
<nova:project
|
||||
uuid="f241e906-010e-4917-ae81-53f4fb8aa021">moonshot</nova:project>
|
||||
</nova:owner>
|
||||
<nova:ports>
|
||||
<nova:port uuid="567a4527-b0e4-4d0a-bcc2-71fda37897f7">
|
||||
<nova:ip type="fixed" address="192.168.1.1" ipVersion="4"/>
|
||||
<nova:ip type="fixed" address="fe80::f95c:b030:7094" ipVersion="6"/>
|
||||
<nova:ip type="floating" address="11.22.33.44" ipVersion="4"/>
|
||||
</nova:port>
|
||||
<nova:port uuid="a3ca97e2-0cf9-4159-9bfc-afd55bc13ead">
|
||||
<nova:ip type="fixed" address="10.0.0.1" ipVersion="4"/>
|
||||
<nova:ip type="fixed" address="fdf8:f53b:82e4::52" ipVersion="6"/>
|
||||
<nova:ip type="floating" address="1.2.3.4" ipVersion="4"/>
|
||||
</nova:port>
|
||||
</nova:ports>
|
||||
</nova:instance>
|
||||
""")
|
||||
|
||||
def test_config_metadata_from_volume_no_image(self):
|
||||
meta = config.LibvirtConfigGuestMetaNovaInstance()
|
||||
meta.package = "2014.2.3"
|
||||
meta.name = "moonbuggy"
|
||||
meta.creationTime = 1234567890
|
||||
|
||||
imeta = config.LibvirtConfigGuestMetaImage()
|
||||
|
||||
meta.image = imeta
|
||||
|
||||
owner = config.LibvirtConfigGuestMetaNovaOwner()
|
||||
owner.userid = "3472c2a6-de91-4fb5-b618-42bc781ef670"
|
||||
owner.username = "buzz"
|
||||
owner.projectid = "f241e906-010e-4917-ae81-53f4fb8aa021"
|
||||
owner.projectname = "moonshot"
|
||||
|
||||
meta.owner = owner
|
||||
|
||||
flavor = config.LibvirtConfigGuestMetaNovaFlavor()
|
||||
flavor.name = "m1.lowgravity"
|
||||
flavor.id = "f719a0dd-4b43-4efe-8336-48ef74099ad4"
|
||||
flavor.vcpus = 8
|
||||
flavor.memory = 2048
|
||||
flavor.swap = 10
|
||||
flavor.disk = 50
|
||||
flavor.ephemeral = 10
|
||||
|
||||
meta.flavor = flavor
|
||||
|
||||
meta.ports = config.LibvirtConfigGuestMetaNovaPorts(
|
||||
ports=[
|
||||
config.LibvirtConfigGuestMetaNovaPort(
|
||||
'567a4527-b0e4-4d0a-bcc2-71fda37897f7',
|
||||
ips=[
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', '192.168.1.1', '4'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', 'fe80::f95c:b030:7094', '6'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'floating', '11.22.33.44', '4')]),
|
||||
config.LibvirtConfigGuestMetaNovaPort(
|
||||
'a3ca97e2-0cf9-4159-9bfc-afd55bc13ead',
|
||||
ips=[
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', '10.0.0.1', '4'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'fixed', 'fdf8:f53b:82e4::52', '6'),
|
||||
config.LibvirtConfigGuestMetaNovaIp(
|
||||
'floating', '1.2.3.4', '4')])])
|
||||
|
||||
xml = meta.to_xml()
|
||||
self.assertXmlEqual(xml, """
|
||||
<nova:instance xmlns:nova='http://openstack.org/xmlns/libvirt/nova/1.1'>
|
||||
<nova:package version="2014.2.3"/>
|
||||
<nova:name>moonbuggy</nova:name>
|
||||
<nova:creationTime>2009-02-13 23:31:30</nova:creationTime>
|
||||
<nova:flavor name="m1.lowgravity"
|
||||
id="f719a0dd-4b43-4efe-8336-48ef74099ad4">
|
||||
<nova:memory>2048</nova:memory>
|
||||
<nova:disk>50</nova:disk>
|
||||
<nova:swap>10</nova:swap>
|
||||
<nova:ephemeral>10</nova:ephemeral>
|
||||
<nova:vcpus>8</nova:vcpus>
|
||||
<nova:extraSpecs></nova:extraSpecs>
|
||||
</nova:flavor>
|
||||
<nova:image uuid="">
|
||||
<nova:properties></nova:properties>
|
||||
</nova:image>
|
||||
<nova:owner>
|
||||
<nova:user
|
||||
uuid="3472c2a6-de91-4fb5-b618-42bc781ef670">buzz</nova:user>
|
||||
<nova:project
|
||||
uuid="f241e906-010e-4917-ae81-53f4fb8aa021">moonshot</nova:project>
|
||||
</nova:owner>
|
||||
<nova:ports>
|
||||
<nova:port uuid="567a4527-b0e4-4d0a-bcc2-71fda37897f7">
|
||||
<nova:ip type="fixed" address="192.168.1.1" ipVersion="4"/>
|
||||
<nova:ip type="fixed" address="fe80::f95c:b030:7094" ipVersion="6"/>
|
||||
<nova:ip type="floating" address="11.22.33.44" ipVersion="4"/>
|
||||
</nova:port>
|
||||
<nova:port uuid="a3ca97e2-0cf9-4159-9bfc-afd55bc13ead">
|
||||
<nova:ip type="fixed" address="10.0.0.1" ipVersion="4"/>
|
||||
<nova:ip type="fixed" address="fdf8:f53b:82e4::52" ipVersion="6"/>
|
||||
<nova:ip type="floating" address="1.2.3.4" ipVersion="4"/>
|
||||
</nova:port>
|
||||
</nova:ports>
|
||||
</nova:instance>
|
||||
""")
|
||||
|
||||
|
||||
class LibvirtConfigGuestIDMap(LibvirtConfigBaseTest):
|
||||
def test_config_id_map_parse_start_not_int(self):
|
||||
|
||||
@@ -665,7 +665,8 @@ class FakeNodeDevice(object):
|
||||
return self.xml
|
||||
|
||||
|
||||
def _create_test_instance():
|
||||
def _create_test_instance(image_ref='155d900f-4e14-4e4c-a73d-069cbf4541e6',
|
||||
system_metadata=None):
|
||||
flavor = objects.Flavor(memory_mb=2048,
|
||||
swap=0,
|
||||
vcpu_weight=None,
|
||||
@@ -677,6 +678,9 @@ def _create_test_instance():
|
||||
flavorid=u'1',
|
||||
vcpus=2,
|
||||
extra_specs={})
|
||||
if system_metadata is None:
|
||||
system_metadata = {'image_base_image_ref': image_ref,
|
||||
'image_disk_format': 'raw'}
|
||||
return {
|
||||
'id': 1,
|
||||
'uuid': uuids.instance,
|
||||
@@ -687,13 +691,10 @@ def _create_test_instance():
|
||||
'vcpus': 2,
|
||||
'project_id': 'fake',
|
||||
'bridge': 'br101',
|
||||
'image_ref': '155d900f-4e14-4e4c-a73d-069cbf4541e6',
|
||||
'image_ref': image_ref,
|
||||
'root_gb': 10,
|
||||
'ephemeral_gb': 20,
|
||||
'system_metadata': {
|
||||
'image_base_image_ref': '155d900f-4e14-4e4c-a73d-069cbf4541e6',
|
||||
'image_disk_format': 'raw'
|
||||
},
|
||||
'system_metadata': system_metadata,
|
||||
'instance_type_id': flavor.id,
|
||||
'flavor': flavor,
|
||||
'new_flavor': None,
|
||||
@@ -2945,6 +2946,104 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
"image_base_image_ref"],
|
||||
meta.rootid)
|
||||
|
||||
def test_get_guest_config_meta_from_image(self):
|
||||
image_id = '85daefce-4e20-4d2b-a4f3-11d3765f2a8f'
|
||||
instance = _create_test_instance(
|
||||
image_ref=image_id,
|
||||
system_metadata={
|
||||
'image_base_image_ref': image_id,
|
||||
'image_container_format': 'bare',
|
||||
'image_disk_format': 'raw',
|
||||
'image_min_disk': 10,
|
||||
'image_min_ram': 0,
|
||||
'image_os_type': 'linux'})
|
||||
instance['info_cache'] = self.test_instance['info_cache']
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
idm = drvr.get_instance_driver_metadata(
|
||||
objects.Instance(**instance),
|
||||
_fake_network_info(self, num_networks=0))
|
||||
meta = drvr._get_guest_config_meta(idm)
|
||||
|
||||
self.assertEqual(meta.image.uuid, image_id)
|
||||
image_meta = meta.image.image_meta
|
||||
self.assertEqual(image_meta.container_format, 'bare')
|
||||
self.assertEqual(image_meta.disk_format, 'raw')
|
||||
self.assertEqual(image_meta.min_disk, 10)
|
||||
self.assertEqual(image_meta.min_ram, 0)
|
||||
self.assertEqual(dict(image_meta.properties), {'os_type': 'linux'})
|
||||
|
||||
def test_get_guest_config_meta_from_image_unshelved(self):
|
||||
instance = _create_test_instance(
|
||||
image_ref='e3e66d4e-43ba-4e3b-8a1d-46cb78a0b527',
|
||||
system_metadata={
|
||||
'image_base_image_ref': (
|
||||
'155d900f-4e14-4e4c-a73d-069cbf4541e6'),
|
||||
'container_format': 'bare',
|
||||
'disk_format': 'raw',
|
||||
'min_disk': 1,
|
||||
'min_ram': 0,
|
||||
'image_os_type': 'linux'})
|
||||
instance['vm_state'] = 'shelved_offloaded'
|
||||
instance['info_cache'] = self.test_instance['info_cache']
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
idm = drvr.get_instance_driver_metadata(
|
||||
objects.Instance(**instance),
|
||||
_fake_network_info(self, num_networks=0))
|
||||
meta = drvr._get_guest_config_meta(idm)
|
||||
|
||||
self.assertEqual(meta.image.uuid,
|
||||
'155d900f-4e14-4e4c-a73d-069cbf4541e6')
|
||||
image_meta = meta.image.image_meta
|
||||
self.assertEqual(image_meta.container_format, 'bare')
|
||||
self.assertEqual(image_meta.disk_format, 'raw')
|
||||
self.assertEqual(image_meta.min_disk, 1)
|
||||
self.assertEqual(image_meta.min_ram, 0)
|
||||
self.assertEqual(dict(image_meta.properties), {'os_type': 'linux'})
|
||||
|
||||
def test_get_guest_config_meta_from_volume_image(self):
|
||||
instance = _create_test_instance(
|
||||
image_ref='',
|
||||
system_metadata={
|
||||
'image_base_image_ref': '',
|
||||
'image_container_format': 'bare',
|
||||
'image_disk_format': 'raw',
|
||||
'image_min_disk': 10,
|
||||
'image_min_ram': 0,
|
||||
'image_os_type': 'linux'})
|
||||
instance['info_cache'] = self.test_instance['info_cache']
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
idm = drvr.get_instance_driver_metadata(
|
||||
objects.Instance(**instance),
|
||||
_fake_network_info(self, num_networks=0))
|
||||
meta = drvr._get_guest_config_meta(idm)
|
||||
|
||||
self.assertEqual(meta.image.uuid, '')
|
||||
image_meta = meta.image.image_meta
|
||||
self.assertEqual(image_meta.container_format, 'bare')
|
||||
self.assertEqual(image_meta.disk_format, 'raw')
|
||||
self.assertEqual(image_meta.min_disk, 10)
|
||||
self.assertEqual(image_meta.min_ram, 0)
|
||||
self.assertEqual(dict(image_meta.properties), {'os_type': 'linux'})
|
||||
|
||||
def test_get_guest_config_meta_from_volume_no_image(self):
|
||||
instance = _create_test_instance(
|
||||
image_ref='',
|
||||
system_metadata={'image_base_image_ref': ''})
|
||||
instance['info_cache'] = self.test_instance['info_cache']
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
idm = drvr.get_instance_driver_metadata(
|
||||
objects.Instance(**instance),
|
||||
_fake_network_info(self, num_networks=0))
|
||||
meta = drvr._get_guest_config_meta(idm)
|
||||
|
||||
self.assertEqual(meta.image.uuid, '')
|
||||
image_meta = meta.image.image_meta
|
||||
self.assertIsNone(image_meta.container_format)
|
||||
self.assertIsNone(image_meta.disk_format)
|
||||
self.assertIsNone(image_meta.min_disk)
|
||||
self.assertIsNone(image_meta.min_ram)
|
||||
self.assertEqual(dict(image_meta.properties), {})
|
||||
|
||||
@mock.patch.object(time, "time")
|
||||
def test_get_guest_config(self, time_mock):
|
||||
"""Generate a "standard" guest with minimal configuration.
|
||||
|
||||
@@ -62,8 +62,39 @@ class FlavorMeta:
|
||||
class ImageMeta:
|
||||
id: str
|
||||
name: str
|
||||
container_format: str | None
|
||||
disk_format: str | None
|
||||
min_disk: int | None
|
||||
min_ram: int | None
|
||||
properties: dict
|
||||
|
||||
@staticmethod
|
||||
def from_instance(
|
||||
instance: 'nova.objects.instance.Instance',
|
||||
) -> 'ImageMeta':
|
||||
image_meta = instance.image_meta
|
||||
return ImageMeta(
|
||||
id=instance.image_ref,
|
||||
name=instance.system_metadata.get('image_name'),
|
||||
container_format=(
|
||||
image_meta.container_format
|
||||
if image_meta.obj_attr_is_set('container_format')
|
||||
else None),
|
||||
disk_format=(
|
||||
image_meta.disk_format
|
||||
if image_meta.obj_attr_is_set('disk_format')
|
||||
else None),
|
||||
min_disk=(
|
||||
image_meta.min_disk
|
||||
if image_meta.obj_attr_is_set('min_disk')
|
||||
else None),
|
||||
min_ram=(
|
||||
image_meta.min_ram
|
||||
if image_meta.obj_attr_is_set('min_ram')
|
||||
else None),
|
||||
properties=image_meta.properties.to_dict(),
|
||||
)
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class NovaInstanceMeta:
|
||||
@@ -385,11 +416,7 @@ class ComputeDriver(object):
|
||||
swap=instance.flavor.swap,
|
||||
extra_specs=instance.flavor.extra_specs,
|
||||
)
|
||||
image = ImageMeta(
|
||||
id=instance.image_ref,
|
||||
name=system_meta.get('image_name'),
|
||||
properties=instance.image_meta.properties
|
||||
)
|
||||
image = ImageMeta.from_instance(instance)
|
||||
meta = InstanceDriverMetadata(
|
||||
instance_meta=instance_meta,
|
||||
owner=owner,
|
||||
|
||||
@@ -3760,6 +3760,7 @@ class LibvirtConfigGuestMetaNovaInstance(LibvirtConfigObject):
|
||||
|
||||
self.package = None
|
||||
self.flavor = None
|
||||
self.image = None
|
||||
self.name = None
|
||||
self.creationTime = None
|
||||
self.owner = None
|
||||
@@ -3781,6 +3782,8 @@ class LibvirtConfigGuestMetaNovaInstance(LibvirtConfigObject):
|
||||
meta.append(self._text_node("creationTime", timestr))
|
||||
if self.flavor is not None:
|
||||
meta.append(self.flavor.format_dom())
|
||||
if self.image is not None:
|
||||
meta.append(self.image.format_dom())
|
||||
if self.owner is not None:
|
||||
meta.append(self.owner.format_dom())
|
||||
|
||||
@@ -3851,6 +3854,56 @@ class LibvirtConfigGuestMetaNovaFlavorExtraSpecs(LibvirtConfigObject):
|
||||
return meta
|
||||
|
||||
|
||||
class LibvirtConfigGuestMetaImage(LibvirtConfigObject):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(root_name="image",
|
||||
ns_prefix="nova",
|
||||
ns_uri=NOVA_NS)
|
||||
self.uuid = None
|
||||
self.image_meta = None
|
||||
# NOTE(callumdickinson): Based on the values of SM_INHERITABLE_KEYS.
|
||||
self.attrs = [
|
||||
("container_format", "containerFormat"),
|
||||
("disk_format", "diskFormat"),
|
||||
("min_disk", "minDisk"),
|
||||
("min_ram", "minRam")]
|
||||
|
||||
def format_dom(self):
|
||||
meta = super().format_dom()
|
||||
# uuid can be empty for instances booted from volume.
|
||||
meta.set("uuid", self.uuid or "")
|
||||
if self.image_meta is not None:
|
||||
for attr, node_key in self.attrs:
|
||||
value = getattr(self.image_meta, attr)
|
||||
if value is not None:
|
||||
node = self._text_node(node_key, value)
|
||||
meta.append(node)
|
||||
properties_meta = LibvirtConfigGuestMetaImageProperties()
|
||||
if self.image_meta is not None:
|
||||
properties_meta.properties = self.image_meta.properties
|
||||
meta.append(properties_meta.format_dom())
|
||||
return meta
|
||||
|
||||
|
||||
class LibvirtConfigGuestMetaImageProperties(LibvirtConfigObject):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(root_name="properties",
|
||||
ns_prefix="nova",
|
||||
ns_uri=NOVA_NS)
|
||||
self.properties = None
|
||||
|
||||
def format_dom(self):
|
||||
meta = super().format_dom()
|
||||
if self.properties is not None:
|
||||
for attr, value in self.properties.items():
|
||||
node = self._text_node("property", value)
|
||||
node.set("name", attr)
|
||||
meta.append(node)
|
||||
return meta
|
||||
|
||||
|
||||
class LibvirtConfigGuestMetaNovaOwner(LibvirtConfigObject):
|
||||
|
||||
def __init__(self):
|
||||
|
||||
@@ -6241,6 +6241,13 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
meta.roottype = dmeta.root_type
|
||||
meta.rootid = dmeta.root_id
|
||||
|
||||
# Always set the image meta, even when booting from volume
|
||||
# as volumes can contain image meta as well.
|
||||
imeta = vconfig.LibvirtConfigGuestMetaImage()
|
||||
imeta.uuid = meta.rootid
|
||||
imeta.image_meta = dmeta.image
|
||||
meta.image = imeta
|
||||
|
||||
ometa = vconfig.LibvirtConfigGuestMetaNovaOwner()
|
||||
ometa.userid = dmeta.owner.userid
|
||||
ometa.username = dmeta.owner.username
|
||||
|
||||
@@ -7,6 +7,14 @@ features:
|
||||
This allows downstream clients that queries libvirt domain metadata,
|
||||
such as Ceilometer, to avoid performing additional Nova API queries
|
||||
to get this information.
|
||||
- |
|
||||
Additional attributes relating to the image metadata an instance is
|
||||
configured with have been added to the libvirt domain metadata under
|
||||
the ``<nova:image>`` element. This allows downstream services that
|
||||
read libvirt domain metadata, such as Ceilometer, to use and expose
|
||||
more information about an instance without needing to perform
|
||||
additional API queries (potentially to multiple services) to get that
|
||||
information.
|
||||
|
||||
upgrades:
|
||||
- |
|
||||
|
||||
Reference in New Issue
Block a user