def test_config_host(self): xmlin = """ <capabilities> <host> <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> <cpu> <arch>x86_64</arch> <model>Opteron_G3</model> <vendor>AMD</vendor> <topology sockets='1' cores='4' threads='1'/> <feature name='ibs'/> <feature name='osvw'/> </cpu> </host> <guest> <os_type>hvm</os_type> <arch name='x86_64'/> </guest> <guest> <os_type>hvm</os_type> <arch name='i686'/> </guest> </capabilities>""" obj = config.LibvirtConfigCaps() obj.parse_str(xmlin) self.assertEqual(type(obj.host), config.LibvirtConfigCapsHost) self.assertEqual(obj.host.uuid, "c7a5fdbd-edaf-9455-926a-d65c16db1809") xmlout = obj.to_xml() self.assertXmlEqual(xmlin, xmlout)
def get_capabilities(self): """Returns the host capabilities information Returns an instance of config.LibvirtConfigCaps representing the capabilities of the host. Note: The result is cached in the member attribute _caps. :returns: a config.LibvirtConfigCaps object """ if not self._caps: xmlstr = self.get_connection().getCapabilities() LOG.info(_LI("Libvirt host capabilities %s"), xmlstr) self._caps = vconfig.LibvirtConfigCaps() self._caps.parse_str(xmlstr) if hasattr(libvirt, 'VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES'): try: features = self.get_connection().baselineCPU( [self._caps.host.cpu.to_xml()], libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) # FIXME(wangpan): the return value of baselineCPU should be # None or xml string, but libvirt has a bug # of it from 1.1.2 which is fixed in 1.2.0, # this -1 checking should be removed later. if features and features != -1: cpu = vconfig.LibvirtConfigCPU() cpu.parse_str(features) self._caps.host.cpu.features = cpu.features except libvirt.libvirtError as ex: error_code = ex.get_error_code() if error_code == libvirt.VIR_ERR_NO_SUPPORT: LOG.warn( _LW("URI %(uri)s does not support full set" " of host capabilities: %(error)s"), { 'uri': self._uri, 'error': ex }) else: raise # PF9: Get sockets, cores and threads from lscpu instead of # libvirt try: (stdout, stderr) = processutils.execute("lscpu") lscpu_cpu_info = Host._parse_cpu_info_pf9(stdout) if set(['cores', 'sockets', 'threads']) == set(lscpu_cpu_info.keys()): LOG.info("Using cpu information from lscpu") self._caps.host.cpu.cores = lscpu_cpu_info["cores"] self._caps.host.cpu.sockets = lscpu_cpu_info["sockets"] self._caps.host.cpu.threads = lscpu_cpu_info["threads"] else: LOG.info("Using cpu information from libvirt") except (OSError, processutils.ProcessExecutionError): # Looks like we can't use lscpu on this hypervisor. We continue # to use libvirt provided cores, socket and thread counts. LOG.info("Using cpu information from libvirt") # PF9 end return self._caps
def get_capabilities(self): """Returns the host capabilities information Returns an instance of config.LibvirtConfigCaps representing the capabilities of the host. Note: The result is cached in the member attribute _caps. :returns: a config.LibvirtConfigCaps object """ if not self._caps: xmlstr = self.get_connection().getCapabilities() LOG.info(_LI("Libvirt host capabilities %s"), xmlstr) self._caps = vconfig.LibvirtConfigCaps() self._caps.parse_str(xmlstr) # NOTE(mriedem): Don't attempt to get baseline CPU features # if libvirt can't determine the host cpu model. if (hasattr(libvirt, 'VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES') and self._caps.host.cpu.model is not None): try: features = self.get_connection().baselineCPU( [self._caps.host.cpu.to_xml()], libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) # FIXME(wangpan): the return value of baselineCPU should be # None or xml string, but libvirt has a bug # of it from 1.1.2 which is fixed in 1.2.0, # this -1 checking should be removed later. if features and features != -1: cpu = vconfig.LibvirtConfigCPU() cpu.parse_str(features) self._caps.host.cpu.features = cpu.features except libvirt.libvirtError as ex: error_code = ex.get_error_code() if error_code == libvirt.VIR_ERR_NO_SUPPORT: LOG.warn( _LW("URI %(uri)s does not support full set" " of host capabilities: " "%(error)s"), { 'uri': self._uri, 'error': ex }) else: raise return self._caps
def get_capabilities(self): """Returns the host capabilities information Returns an instance of config.LibvirtConfigCaps representing the capabilities of the host. Note: The result is cached in the member attribute _caps. :returns: a config.LibvirtConfigCaps object """ if not self._caps: xmlstr = self.get_connection().getCapabilities() LOG.info("Libvirt host capabilities %s", xmlstr) self._caps = vconfig.LibvirtConfigCaps() self._caps.parse_str(xmlstr) # NOTE(mriedem): Don't attempt to get baseline CPU features # if libvirt can't determine the host cpu model. if (hasattr(libvirt, 'VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES') and self._caps.host.cpu.model is not None): try: xml_str = self._caps.host.cpu.to_xml() if six.PY3 and isinstance(xml_str, six.binary_type): xml_str = xml_str.decode('utf-8') features = self.get_connection().baselineCPU( [xml_str], libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) if features: cpu = vconfig.LibvirtConfigCPU() cpu.parse_str(features) self._caps.host.cpu.features = cpu.features except libvirt.libvirtError as ex: error_code = ex.get_error_code() if error_code == libvirt.VIR_ERR_NO_SUPPORT: LOG.warning( "URI %(uri)s does not support full set" " of host capabilities: %(error)s", { 'uri': self._uri, 'error': ex }) else: raise return self._caps
def get_capabilities(self): """Returns the host capabilities information Returns an instance of config.LibvirtConfigCaps representing the capabilities of the host. Note: The result is cached in the member attribute _caps. :returns: a config.LibvirtConfigCaps object """ if not self._caps: xmlstr = self.get_connection().getCapabilities() LOG.info(_LI("Libvirt host capabilities %s"), xmlstr) self._caps = vconfig.LibvirtConfigCaps() self._caps.parse_str(xmlstr) # if False: # try: # features = self.get_connection().baselineCPU( # [self._caps.host.cpu.to_xml()], # libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) # # FIXME(wangpan): the return value of baselineCPU should be # # None or xml string, but libvirt has a bug # # of it from 1.1.2 which is fixed in 1.2.0, # # this -1 checking should be removed later. # if features and features != -1: # cpu = vconfig.LibvirtConfigCPU() # cpu.parse_str(features) # self._caps.host.cpu.features = cpu.features # except libvirt.libvirtError as ex: # error_code = ex.get_error_code() # if error_code == libvirt.VIR_ERR_NO_SUPPORT: # LOG.warn(_LW("URI %(uri)s does not support full set" # " of host capabilities: " "%(error)s"), # {'uri': self._uri, 'error': ex}) # else: # raise return self._caps
def get_capabilities(self): """Returns the host capabilities information Returns an instance of config.LibvirtConfigCaps representing the capabilities of the host. Note: The result is cached in the member attribute _caps. :returns: a config.LibvirtConfigCaps object """ if not self._caps: xmlstr = self.get_connection().getCapabilities() LOG.info("Libvirt host capabilities %s", xmlstr) self._caps = vconfig.LibvirtConfigCaps() self._caps.parse_str(xmlstr) # NOTE(mriedem): Don't attempt to get baseline CPU features # if libvirt can't determine the host cpu model. if (hasattr(libvirt, 'VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES') and self._caps.host.cpu.model is not None): try: xml_str = self._caps.host.cpu.to_xml() if six.PY3 and isinstance(xml_str, six.binary_type): xml_str = xml_str.decode('utf-8') features = self.get_connection().baselineCPU( [xml_str], libvirt.VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) if features: cpu = vconfig.LibvirtConfigCPU() cpu.parse_str(features) self._caps.host.cpu.features = cpu.features except libvirt.libvirtError as ex: error_code = ex.get_error_code() if error_code == libvirt.VIR_ERR_NO_SUPPORT: LOG.warning("URI %(uri)s does not support full set" " of host capabilities: %(error)s", {'uri': self._uri, 'error': ex}) else: raise # WRS - Simplify memory accounting by engineering out of maximum # VM available memory instead of total physical memory. # After this adjustment, cell.mempages[] only represents VM memory # and corresponds exactly match compute-huge. # The following adjustment also removes vswitch hugepages overheads # and 4K pages overheads from accounting. # Important: cell.memory obtained from getCapabilities() is KiB. # The NumaCell.memory field is in MiB as converted by routine # virt/libvirt/driver.py: _get_host_numa_topology(). This is # confusing since both use same variable name. topology = self._caps.host.topology if topology is None or not topology.cells: return self._caps vm_4K_nodes = self._get_configured_pages( csv=CONF.compute_vm_4K_pages) vs_2M_nodes = self._get_configured_pages( csv=CONF.compute_vswitch_2M_pages) vs_1G_nodes = self._get_configured_pages( csv=CONF.compute_vswitch_1G_pages) for cell in topology.cells: msg = [] cell.memory = 0 for k, pages in enumerate(cell.mempages): pg = cell.mempages[k] if pages.size == MEMPAGE_SZ_4K and vm_4K_nodes: vm_4K = vm_4K_nodes[cell.id] oh_4K = pg.total - vm_4K pg.total -= oh_4K cell.memory += (pg.total * pg.size) MiB = oh_4K * MEMPAGE_SZ_4K // units.Ki msg.append('%d MiB 4K overhead' % (MiB)) if pages.size == MEMPAGE_SZ_2M and vs_2M_nodes: vs_2M = vs_2M_nodes[cell.id] pg.total -= vs_2M cell.memory += (pg.total * pg.size) MiB = vs_2M * MEMPAGE_SZ_2M // units.Ki msg.append('%d MiB 2M vswitch' % (MiB)) if pages.size == MEMPAGE_SZ_1G and vs_1G_nodes: vs_1G = vs_1G_nodes[cell.id] pg.total -= vs_1G cell.memory += (pg.total * pg.size) MiB = vs_1G * MEMPAGE_SZ_1G // units.Ki msg.append('%d MiB 1G vswitch' % (MiB)) LOG.info("cell:%(id)s exclude: %(msg)s", {'id': cell.id, 'msg': '; '.join(msg)}) return self._caps