Skip to content

Commit bf02f13

Browse files
committed
libvirt: define XML schema for recording nova instance metadata
Define an XML schema to be used in the libvirt guest config as a metadata block to provide information about the instance that is being run. When querying the libvirt guest XML this is visible thus: <domain type='kvm' id='6'> <name>instance-00000004</name> <uuid>a173eb64-f8e6-419b-a2b7-2d3283ecb26c</uuid> <metadata> <nova:instance xmlns:nova="http://openstack.org/xmlns/libvirt/nova/1.0"> <nova:package version="2014.2"/> <nova:name>demo</nova:name> <nova:creationTime>2014-06-27 11:22:25+GMT</nova:creationTime> <nova:flavor name="m1.small"> <nova:memory>2048</nova:memory> <nova:disk>20</nova:disk> <nova:swap>0</nova:swap> <nova:vcpus>1</nova:vcpus> </nova:flavor> <nova:owner> <nova:user uuid="18509018d00743c89518135e476003e0">admin</nova:user> <nova:project uuid="38bd8e984a3e435a87e950a441ee55aa">admin</nova:project> </nova:owner> <nova:root type="image" uuid="f0f0d38c-0a5f-4c54-83e5-d48006b888a7"/> </nova:instance> </metadata> ...snip... </domain> Blueprint: libvirt-driver-domain-metadata Change-Id: I19432cb93bc1471118d9d323c712cdd9756a5926
1 parent c5b4188 commit bf02f13

File tree

2 files changed

+173
-8
lines changed

2 files changed

+173
-8
lines changed

nova/tests/virt/libvirt/test_config.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,3 +1735,55 @@ def test_config_cputune_timeslice(self):
17351735
<quota>50000</quota>
17361736
<period>25000</period>
17371737
</cputune>""")
1738+
1739+
1740+
class LibvirtConfigGuestMetadataNovaTest(LibvirtConfigBaseTest):
1741+
1742+
def test_config_metadata(self):
1743+
meta = config.LibvirtConfigGuestMetaNovaInstance()
1744+
meta.package = "2014.2.3"
1745+
meta.name = "moonbuggy"
1746+
meta.creationTime = 1234567890
1747+
meta.roottype = "image"
1748+
meta.rootid = "fe55c69a-8b2e-4bbc-811a-9ad2023a0426"
1749+
1750+
owner = config.LibvirtConfigGuestMetaNovaOwner()
1751+
owner.userid = "3472c2a6-de91-4fb5-b618-42bc781ef670"
1752+
owner.username = "buzz"
1753+
owner.projectid = "f241e906-010e-4917-ae81-53f4fb8aa021"
1754+
owner.projectname = "moonshot"
1755+
1756+
meta.owner = owner
1757+
1758+
flavor = config.LibvirtConfigGuestMetaNovaFlavor()
1759+
flavor.name = "m1.lowgravity"
1760+
flavor.vcpus = 8
1761+
flavor.memory = 2048
1762+
flavor.swap = 10
1763+
flavor.disk = 50
1764+
flavor.ephemeral = 10
1765+
1766+
meta.flavor = flavor
1767+
1768+
xml = meta.to_xml()
1769+
self.assertXmlEqual(xml, """
1770+
<nova:instance xmlns:nova='http://openstack.org/xmlns/libvirt/nova/1.0'>
1771+
<nova:package version="2014.2.3"/>
1772+
<nova:name>moonbuggy</nova:name>
1773+
<nova:creationTime>2009-02-13 23:31:30</nova:creationTime>
1774+
<nova:flavor name="m1.lowgravity">
1775+
<nova:memory>2048</nova:memory>
1776+
<nova:disk>50</nova:disk>
1777+
<nova:swap>10</nova:swap>
1778+
<nova:ephemeral>10</nova:ephemeral>
1779+
<nova:vcpus>8</nova:vcpus>
1780+
</nova:flavor>
1781+
<nova:owner>
1782+
<nova:user
1783+
uuid="3472c2a6-de91-4fb5-b618-42bc781ef670">buzz</nova:user>
1784+
<nova:project
1785+
uuid="f241e906-010e-4917-ae81-53f4fb8aa021">moonshot</nova:project>
1786+
</nova:owner>
1787+
<nova:root type="image" uuid="fe55c69a-8b2e-4bbc-811a-9ad2023a0426"/>
1788+
</nova:instance>
1789+
""")

nova/virt/libvirt/config.py

Lines changed: 121 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
helpers for populating up config object instances.
2424
"""
2525

26+
import time
27+
2628
from nova import exception
2729
from nova.openstack.common import log as logging
2830
from nova.openstack.common import units
@@ -33,6 +35,9 @@
3335

3436
LOG = logging.getLogger(__name__)
3537

38+
# Namespace to use for Nova specific metadata items in XML
39+
NOVA_NS = "http://openstack.org/xmlns/libvirt/nova/1.0"
40+
3641

3742
class LibvirtConfigObject(object):
3843

@@ -43,18 +48,20 @@ def __init__(self, **kwargs):
4348
self.ns_prefix = kwargs.get('ns_prefix')
4449
self.ns_uri = kwargs.get('ns_uri')
4550

46-
@staticmethod
47-
def _text_node(name, value):
48-
child = etree.Element(name)
51+
def _new_node(self, name):
52+
if self.ns_uri is None:
53+
return etree.Element(name)
54+
else:
55+
return etree.Element("{" + self.ns_uri + "}" + name,
56+
nsmap={self.ns_prefix: self.ns_uri})
57+
58+
def _text_node(self, name, value):
59+
child = self._new_node(name)
4960
child.text = str(value)
5061
return child
5162

5263
def format_dom(self):
53-
if self.ns_uri is None:
54-
return etree.Element(self.root_name)
55-
else:
56-
return etree.Element("{" + self.ns_uri + "}" + self.root_name,
57-
nsmap={self.ns_prefix: self.ns_uri})
64+
return self._new_node(self.root_name)
5865

5966
def parse_str(self, xmlstr):
6067
self.parse_dom(etree.fromstring(xmlstr))
@@ -1186,6 +1193,7 @@ def __init__(self, **kwargs):
11861193
self.os_smbios = None
11871194
self.os_mach_type = None
11881195
self.devices = []
1196+
self.metadata = []
11891197

11901198
def _format_basic_props(self, root):
11911199
root.append(self._text_node("uuid", self.uuid))
@@ -1198,6 +1206,12 @@ def _format_basic_props(self, root):
11981206
else:
11991207
root.append(self._text_node("vcpu", self.vcpus))
12001208

1209+
if len(self.metadata) > 0:
1210+
metadata = etree.Element("metadata")
1211+
for m in self.metadata:
1212+
metadata.append(m.format_dom())
1213+
root.append(metadata)
1214+
12011215
def _format_os(self, root):
12021216
os = etree.Element("os")
12031217
type_node = self._text_node("type", self.os_type)
@@ -1435,3 +1449,102 @@ def format_dom(self):
14351449
dev.append(backend)
14361450

14371451
return dev
1452+
1453+
1454+
class LibvirtConfigGuestMetaNovaInstance(LibvirtConfigObject):
1455+
1456+
def __init__(self):
1457+
super(LibvirtConfigGuestMetaNovaInstance,
1458+
self).__init__(root_name="instance",
1459+
ns_prefix="nova",
1460+
ns_uri=NOVA_NS)
1461+
1462+
self.package = None
1463+
self.flavor = None
1464+
self.name = None
1465+
self.creationTime = None
1466+
self.owner = None
1467+
self.roottype = None
1468+
self.rootid = None
1469+
1470+
def format_dom(self):
1471+
meta = super(LibvirtConfigGuestMetaNovaInstance, self).format_dom()
1472+
1473+
pkg = self._new_node("package")
1474+
pkg.set("version", self.package)
1475+
meta.append(pkg)
1476+
if self.name is not None:
1477+
meta.append(self._text_node("name", self.name))
1478+
if self.creationTime is not None:
1479+
timestr = time.strftime("%Y-%m-%d %H:%M:%S",
1480+
time.gmtime(self.creationTime))
1481+
meta.append(self._text_node("creationTime", timestr))
1482+
if self.flavor is not None:
1483+
meta.append(self.flavor.format_dom())
1484+
if self.owner is not None:
1485+
meta.append(self.owner.format_dom())
1486+
1487+
if self.roottype is not None and self.rootid is not None:
1488+
root = self._new_node("root")
1489+
root.set("type", self.roottype)
1490+
root.set("uuid", str(self.rootid))
1491+
meta.append(root)
1492+
1493+
return meta
1494+
1495+
1496+
class LibvirtConfigGuestMetaNovaFlavor(LibvirtConfigObject):
1497+
1498+
def __init__(self):
1499+
super(LibvirtConfigGuestMetaNovaFlavor,
1500+
self).__init__(root_name="flavor",
1501+
ns_prefix="nova",
1502+
ns_uri=NOVA_NS)
1503+
1504+
self.name = None
1505+
self.memory = None
1506+
self.disk = None
1507+
self.swap = None
1508+
self.ephemeral = None
1509+
self.vcpus = None
1510+
1511+
def format_dom(self):
1512+
meta = super(LibvirtConfigGuestMetaNovaFlavor, self).format_dom()
1513+
meta.set("name", self.name)
1514+
if self.memory is not None:
1515+
meta.append(self._text_node("memory", str(self.memory)))
1516+
if self.disk is not None:
1517+
meta.append(self._text_node("disk", str(self.disk)))
1518+
if self.swap is not None:
1519+
meta.append(self._text_node("swap", str(self.swap)))
1520+
if self.ephemeral is not None:
1521+
meta.append(self._text_node("ephemeral", str(self.ephemeral)))
1522+
if self.vcpus is not None:
1523+
meta.append(self._text_node("vcpus", str(self.vcpus)))
1524+
return meta
1525+
1526+
1527+
class LibvirtConfigGuestMetaNovaOwner(LibvirtConfigObject):
1528+
1529+
def __init__(self):
1530+
super(LibvirtConfigGuestMetaNovaOwner,
1531+
self).__init__(root_name="owner",
1532+
ns_prefix="nova",
1533+
ns_uri=NOVA_NS)
1534+
1535+
self.userid = None
1536+
self.username = None
1537+
self.projectid = None
1538+
self.projectname = None
1539+
1540+
def format_dom(self):
1541+
meta = super(LibvirtConfigGuestMetaNovaOwner, self).format_dom()
1542+
if self.userid is not None and self.username is not None:
1543+
user = self._text_node("user", self.username)
1544+
user.set("uuid", self.userid)
1545+
meta.append(user)
1546+
if self.projectid is not None and self.projectname is not None:
1547+
project = self._text_node("project", self.projectname)
1548+
project.set("uuid", self.projectid)
1549+
meta.append(project)
1550+
return meta

0 commit comments

Comments
 (0)