Francesco Romani has uploaded a new change for review. Change subject: vm: add manufactorer metadata element ......................................................................
vm: add manufactorer metadata element On recovery, VDSM checks the manufactorer/osversion fields on SMBIOS domain xml data, to detect if it should take care of a given VM. This won't work on architectures != x86, like PPC. A cleanest approach is to move this field in the domain XML metadata. This patch does that, but since we cannot have yet an hard dependency on libvirt which makes us sure we have the metadata support, the new identification is added to the existing one. Once we can adjust the dependency, the old path will be removed. Change-Id: If2b7ee8ae46a7a86b942e5f55077c120d42a5206 Relates-To: https://bugzilla.redhat.com/1126887 Signed-off-by: Francesco Romani <[email protected]> --- M tests/vmTests.py M vdsm/clientIF.py M vdsm/virt/utils.py M vdsm/virt/vm.py M vdsm/virt/vmxml.py 5 files changed, 115 insertions(+), 26 deletions(-) git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/11/31211/1 diff --git a/tests/vmTests.py b/tests/vmTests.py index e43af8d..99bf80e 100644 --- a/tests/vmTests.py +++ b/tests/vmTests.py @@ -358,6 +358,10 @@ domxml.appendFeatures() self.assertXML(domxml.dom, featuresXML, 'features') + @MonkeyPatch(caps, 'osversion', lambda: { + 'release': '1', 'version': '17', 'name': 'Fedora'}) + @MonkeyPatch(constants, 'SMBIOS_MANUFACTURER', 'oVirt') + @MonkeyPatch(constants, 'SMBIOS_OSNAME', 'oVirt Node') def testSysinfoXML(self): sysinfoXML = """ <sysinfo type="smbios"> @@ -369,13 +373,13 @@ <entry name="uuid">%s</entry> </system> </sysinfo>""" - product = 'oVirt Node' version = '17-1' serial = 'A5955881-519B-11CB-8352-E78A528C28D8_00:21:cc:68:d7:38' sysinfoXML = sysinfoXML % (constants.SMBIOS_MANUFACTURER, - product, version, serial, self.conf['vmId']) + constants.SMBIOS_OSNAME, + version, serial, self.conf['vmId']) domxml = vmxml.Domain(self.conf, self.log, caps.Architecture.X86_64) - domxml.appendSysinfo(product, version, serial) + domxml.appendSysinfo(serial) self.assertXML(domxml.dom, sysinfoXML, 'sysinfo') def testConsoleXML(self): @@ -1276,6 +1280,29 @@ self.assertEqual(self._xml_sanitizer(drives[0]._deviceXML), self._xml_sanitizer(expected_xml)) + @MonkeyPatch(caps, 'osversion', lambda: { + 'release': '1', 'version': '17', 'name': 'Fedora'}) + @MonkeyPatch(constants, 'SMBIOS_MANUFACTURER', 'oVirt') + @MonkeyPatch(constants, 'SMBIOS_OSNAME', 'oVirt Node') + def testSystemIDXML(self): + templateXML = """ + <system> + <manufacturer>%s</manufacturer> + <product>%s</product> + <version>%s</version> + <serial>%s</serial> + <uuid>%s</uuid> + </system>""" + version = '17-1' + serial = 'A5955881-519B-11CB-8352-E78A528C28D8_00:21:cc:68:d7:38' + expectedXML = self._xml_sanitizer( + templateXML % (constants.SMBIOS_MANUFACTURER, + constants.SMBIOS_OSNAME, + version, serial, self.conf['vmId'])) + sysinfoXML = self._xml_sanitizer( + vmxml.buildSystemID(self.conf['vmId'], serial)) + self.assertEqual(sysinfoXML, expectedXML) + class FakeGuestAgent(object): def getGuestInfo(self): @@ -1419,6 +1446,14 @@ fake._dom = FakeDomain(domState=libvirt.VIR_DOMAIN_RUNNING) self.assertTrue(fake._isDomainRunning()) + def testSetsysinfo(self): + with FakeVM({'serial': '42'}) as fake: + fake._dom = FakeDomain() + fake._setSysinfo() + info = fake.getSysinfo() + self.assertEqual(info.serial, fake.conf['serial']) + self.assertEqual(info.uuid, fake.conf['vmId']) + VM_EXITS = tuple(product((define.NORMAL, define.ERROR), vmexitreason.exitReasons.keys())) diff --git a/vdsm/clientIF.py b/vdsm/clientIF.py index a2df805..d0e5a63 100644 --- a/vdsm/clientIF.py +++ b/vdsm/clientIF.py @@ -482,6 +482,13 @@ """ Return True if vm seems as if it was created by vdsm. """ + sysinfo = vm.getSysinfo() + if sysinfo: + if sysinfo.product in (caps.OSName.RHEL, caps.OSName.OVIRT, + caps.OSName.RHEVH, caps.OSName.FEDORA, + caps.OSName.DEBIAN): + return True + try: vmdom = minidom.parseString(vm.XMLDesc(0)) sysinfo = vmdom.getElementsByTagName("sysinfo")[0] diff --git a/vdsm/virt/utils.py b/vdsm/virt/utils.py index f771606..1f20cd1 100644 --- a/vdsm/virt/utils.py +++ b/vdsm/virt/utils.py @@ -22,6 +22,11 @@ shared utilities and common code for the virt package """ +from collections import namedtuple + + +Sysinfo = namedtuple("Sysinfo", "manufacturer,product,version,serial,uuid") + def isVdsmImage(drive): """ diff --git a/vdsm/virt/vm.py b/vdsm/virt/vm.py index 0405726..c497127 100644 --- a/vdsm/virt/vm.py +++ b/vdsm/virt/vm.py @@ -93,6 +93,7 @@ TPM_DEVICES = 'tpm' METADATA_VM_TUNE_URI = 'http://ovirt.org/vm/tune/1.0' +METADATA_VM_SYSINFO_URI = 'http://ovirt.org/vm/id/1.0' # A libvirt constant for undefined cpu quota _NO_CPU_QUOTA = 0 @@ -2660,15 +2661,7 @@ domxml.appendOs() if self.arch == caps.Architecture.X86_64: - osd = caps.osversion() - - osVersion = osd.get('version', '') + '-' + osd.get('release', '') - serialNumber = self.conf.get('serial', utils.getHostUUID()) - - domxml.appendSysinfo( - osname=constants.SMBIOS_OSNAME, - osversion=osVersion, - serialNumber=serialNumber) + domxml.appendSysinfo(self.conf.get('serial')) domxml.appendClock() @@ -2814,6 +2807,10 @@ self._getUnderlyingVmInfo() self._getUnderlyingVmDevicesInfo() self._updateAgentChannels() + + # we cannot just build the metadata element in the domain XML until + # we have hard dependency on libvirt in place + self._setSystemInfo() # Currently there is no protection agains mirroring a network twice, if not self.recovering: @@ -3423,9 +3420,7 @@ :return: XML DOM object representing the root qos element """ - metadata_xml = self._getVmMetadata( - METADATA_VM_TUNE_URI, - "<qos></qos>") + metadata_xml = self._getVmMetadata(METADATA_VM_TUNE_URI, "<qos></qos>") if metadata_xml is None: return None @@ -5569,6 +5564,25 @@ if dev['type'] == BALLOON_DEVICES: yield dev + def getSysinfo(self): + metadata_xml = self._getVmMetadata(METADATA_VM_SYSINFO_URI, + "<system></system>") + if metadata_xml is None: + return None + else: + return vmxml.parseSystemID(metadata_xml) + + def _setSysinfo(self): + try: + self._dom.setMetadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT, + vmxml.buildSystemID(self.conf['vmId'], + self.conf.get('serial')), + 'ovirt', METADATA_VM_SYSINFO_URI, 0) + except libvirt.libvirtError: + pass + # this can happen on RHEL/CENTOS 6.x, so just go ahead until + # we drop support for them. + class LiveMergeCleanupThread(threading.Thread): def __init__(self, vm, jobId, drive): diff --git a/vdsm/virt/vmxml.py b/vdsm/virt/vmxml.py index b8d87df..3acf554 100644 --- a/vdsm/virt/vmxml.py +++ b/vdsm/virt/vmxml.py @@ -23,6 +23,8 @@ import xml.dom import xml.dom.minidom +from .utils import Sysinfo + from vdsm import constants from vdsm import utils @@ -205,7 +207,7 @@ if utils.tobool(self.conf.get('bootMenuEnable', False)): oselem.appendChildWithArgs('bootmenu', enable='yes') - def appendSysinfo(self, osname, osversion, serialNumber): + def appendSysinfo(self, serialNumber): """ Add <sysinfo> element to domain: @@ -227,17 +229,11 @@ sysinfoelem = Element('sysinfo', type='smbios') self.dom.appendChild(sysinfoelem) - syselem = Element('system') - sysinfoelem.appendChild(syselem) + def appendEntry(e, k, v): + e.appendChildWithArgs('entry', text=v, name=k) - def appendEntry(k, v): - syselem.appendChildWithArgs('entry', text=v, name=k) - - appendEntry('manufacturer', constants.SMBIOS_MANUFACTURER) - appendEntry('product', osname) - appendEntry('version', osversion) - appendEntry('serial', serialNumber) - appendEntry('uuid', self.conf['vmId']) + sysinfoelem.appendChild(_buildSystemElement( + self.conf['vmId'], serialNumber, appendEntry)) def appendFeatures(self): """ @@ -430,6 +426,38 @@ return self.conf.get('maxVCpus', self._getSmp()) +def _buildOsVersion(): + osd = caps.osversion() + return osd.get('version', '') + '-' + osd.get('release', '') + + +def _buildSystemElement(vmId, serial, appendEntry): + syselem = Element('system') + appendEntry(syselem, 'manufacturer', constants.SMBIOS_MANUFACTURER) + appendEntry(syselem, 'product', constants.SMBIOS_OSNAME) + appendEntry(syselem, 'version', _buildOsVersion()) + appendEntry(syselem, + 'serial', utils.getHostUUID() if serial is None else serial) + appendEntry(syselem, 'uuid', vmId) + return syselem + + +def buildSystemID(vmId, serial=None): + def appendEntry(e, k, v): + e.appendChildWithArgs(k, text=v) + return _buildSystemElement(vmId, serial, appendEntry).toprettyxml() + + +def parseSystemID(sysinfoXml): + sysinfo = xml.dom.minidom.parseString(sysinfoXml) + + def getData(name): + return sysinfo.getElementsByTagName(name)[0].firstChild.data + + return Sysinfo(getData('manufacturer'), getData('product'), + getData('version'), getData('serial'), getData('uuid')) + + if sys.version_info[:2] == (2, 6): # A little unrelated hack to make xml.dom.minidom.Document.toprettyxml() # not wrap Text node with whitespace. -- To view, visit http://gerrit.ovirt.org/31211 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: If2b7ee8ae46a7a86b942e5f55077c120d42a5206 Gerrit-PatchSet: 1 Gerrit-Project: vdsm Gerrit-Branch: master Gerrit-Owner: Francesco Romani <[email protected]> _______________________________________________ vdsm-patches mailing list [email protected] https://lists.fedorahosted.org/mailman/listinfo/vdsm-patches
