def testProcessMdevDeviceParams(self): deviceXML = hostdev._process_device_params( libvirtconnection.get().nodeDeviceLookupByName( hostdevlib.MDEV_DEVICE).XMLDesc() ) self.assertEqual(hostdevlib.MDEV_DEVICE_PROCESSED, deviceXML)
def compatible_cpu_models(): """ Compare qemu's CPU models to models the host is capable of emulating. Returns: A list of strings indicating compatible CPU models prefixed with 'model_'. Example: ['model_Haswell-noTSX', 'model_Nehalem', 'model_Conroe', 'model_coreduo', 'model_core2duo', 'model_Penryn', 'model_IvyBridge', 'model_Westmere', 'model_n270', 'model_SandyBridge'] """ c = libvirtconnection.get() arch = cpuarch.real() cpu_mode = _CpuMode.HOST_MODEL if cpuarch.is_ppc(arch) else _CpuMode.CUSTOM all_models = domain_cpu_models(c, arch, cpu_mode) compatible_models = [model for (model, usable) in six.iteritems(all_models) if usable == 'yes'] # Current QEMU doesn't report POWER compatibility modes, so we # must add them ourselves. if cpuarch.is_ppc(arch) and \ 'POWER9' in compatible_models and \ 'POWER8' not in compatible_models: compatible_models.append('POWER8') return list(set(["model_" + model for model in compatible_models]))
def _get_devices_from_libvirt(flags=0): """ Returns all available host devices from libvirt processd to dict """ libvirt_devices = libvirtconnection.get().listAllDevices(flags) global _last_alldevices_hash global _device_tree_cache global _device_address_to_name_cache if (flags == 0 and __device_tree_hash(libvirt_devices) == _last_alldevices_hash): return _device_tree_cache, _device_address_to_name_cache devices = _process_all_devices(libvirt_devices) address_to_name = {} with _DeviceTreeCache(devices) as cache: for device_name, device_params in devices.items(): if device_params['capability'] == 'scsi': device_params.update( _process_scsi_device_params(device_name, cache)) _update_address_to_name_map( address_to_name, device_name, device_params ) if flags == 0: _device_tree_cache = devices _device_address_to_name_cache = address_to_name _last_alldevices_hash = __device_tree_hash(libvirt_devices) return devices, address_to_name
def networks(): """ Get dict of networks from libvirt :returns: dict of networkname={properties} :rtype: dict of dict { 'ovirtmgmt': { 'bridge': 'ovirtmgmt', 'bridged': True} 'red': { 'iface': 'red', 'bridged': False}} """ nets = {} conn = libvirtconnection.get() allNets = ((net, net.name()) for net in conn.listAllNetworks(0)) for net, netname in allNets: if netname.startswith(LIBVIRT_NET_PREFIX): netname = netname[len(LIBVIRT_NET_PREFIX):] nets[netname] = {} xml = etree.fromstring(net.XMLDesc(0)) interface = xml.find('.//interface') if interface is not None: nets[netname]['iface'] = interface.get('dev') nets[netname]['bridged'] = False else: nets[netname]['bridge'] = xml.find('.//bridge').get('name') nets[netname]['bridged'] = True return nets
def testProcessSRIOV_VFDeviceParams(self): deviceXML = hostdev._process_device_params( libvirtconnection.get().nodeDeviceLookupByName( hostdevlib.SRIOV_VF).XMLDesc() ) self.assertEqual(hostdevlib.SRIOV_VF_PROCESSED, deviceXML)
def start(cif, scheduler): global _operations global _executor _executor = executor.Executor(name="periodic", workers_count=_WORKERS, max_tasks=_TASKS, scheduler=scheduler, max_workers=_MAX_WORKERS) _executor.start() def per_vm_operation(func, period): disp = VmDispatcher(cif.getVMs, _executor, func, _timeout_from(period)) return Operation(disp, period, scheduler) _operations = [ # Needs dispatching because updating the volume stats needs # access to the storage, thus can block. per_vm_operation(UpdateVolumes, config.getint('irs', 'vol_size_sample_interval')), # Job monitoring need QEMU monitor access. per_vm_operation(BlockjobMonitor, config.getint('vars', 'vm_sample_jobs_interval')), # We do this only until we get high water mark notifications # from QEMU. It accesses storage and/or QEMU monitor, so can block, # thus we need dispatching. per_vm_operation(DriveWatermarkMonitor, config.getint('vars', 'vm_watermark_interval')), Operation(lambda: recovery.lookup_external_vms(cif), config.getint('sampling', 'external_vm_lookup_interval'), scheduler, exclusive=True, discard=False), Operation(containersconnection.monitor, config.getint('vars', 'vm_sample_interval'), scheduler), ] if config.getboolean('sampling', 'enable'): _operations.extend([ # libvirt sampling using bulk stats can block, but unresponsive # domains are handled inside VMBulkstatsMonitor for performance # reasons; thus, does not need dispatching. Operation( sampling.VMBulkstatsMonitor(libvirtconnection.get(cif), cif.getVMs, sampling.stats_cache), config.getint('vars', 'vm_sample_interval'), scheduler), Operation(sampling.HostMonitor(cif=cif), config.getint('vars', 'host_sample_stats_interval'), scheduler, timeout=config.getint('vars', 'host_sample_stats_interval'), exclusive=True, discard=False), ]) host.stats.start() for op in _operations: op.start()
def cpu_features(): """ Read CPU features from dom capabilities. Returns: A list of strings indicating CPU features. """ c = libvirtconnection.get() arch = cpuarch.real() xmldomcaps = _get_domain_capabilities(c, arch) if xmldomcaps is None: logging.error('Error while getting CPU features: ' 'no domain capabilities found') return [] cpucaps = xmldomcaps.find('cpu') if cpucaps is None: logging.error('Error while getting CPU features: ' 'no domain CPU capabilities found') return [] features = [] for mode in cpucaps.findall('mode'): if mode.get('name') == _CpuMode.HOST_MODEL: for feature in mode.findall('feature'): if feature.get('policy') == 'require': features.append(feature.get('name')) logging.debug('CPU features: %s', features) return features
def unregister(uuids): try: uuids = [str(uuid.UUID(s)) for s in uuids] except ValueError as e: logging.warning("Attempt to unregister invalid uuid %s: %s" % (uuids, e)) return response.error("secretBadRequestErr") con = libvirtconnection.get() try: for sec_uuid in uuids: logging.info("Unregistering secret %r", sec_uuid) try: virsecret = con.secretLookupByUUIDString(sec_uuid) except libvirt.libvirtError as e: if e.get_error_code() != libvirt.VIR_ERR_NO_SECRET: raise logging.debug("No such secret %r", sec_uuid) else: virsecret.undefine() except libvirt.libvirtError as e: logging.error("Could not unregister secrets: %s", e) return response.error("secretUnregisterErr") return response.success()
def testCallSucceeded(self): """Positive test - libvirtMock does not raise any errors""" with run_libvirt_event_loop(): LibvirtMock.virConnect.failGetLibVersion = False LibvirtMock.virConnect.failNodeDeviceLookupByName = False connection = libvirtconnection.get() connection.nodeDeviceLookupByName()
def _getLibvirtNetworkByName(networkName): conn = libvirtconnection.get(killOnFailure=False) try: return conn.networkLookupByName(networkName) except libvirtError as e: if e.get_error_code() == VIR_ERR_NO_NETWORK: return None raise
def _create(cif, scheduler): def per_vm_operation(func, period): disp = VmDispatcher(cif.getVMs, _executor, func, _timeout_from(period)) return Operation(disp, period, scheduler) ops = [ # Needs dispatching because updating the volume stats needs # access to the storage, thus can block. per_vm_operation(UpdateVolumes, config.getint('irs', 'vol_size_sample_interval')), # Job monitoring need QEMU monitor access. per_vm_operation(BlockjobMonitor, config.getint('vars', 'vm_sample_jobs_interval')), # We do this only until we get high water mark notifications # from QEMU. It accesses storage and/or QEMU monitor, so can block, # thus we need dispatching. per_vm_operation(DriveWatermarkMonitor, config.getint('vars', 'vm_watermark_interval')), per_vm_operation( NvramDataMonitor, config.getint('sampling', 'nvram_data_update_interval')), per_vm_operation(TpmDataMonitor, config.getint('sampling', 'tpm_data_update_interval')), Operation(lambda: recovery.lookup_external_vms(cif), config.getint('sampling', 'external_vm_lookup_interval'), scheduler, exclusive=True, discard=False), Operation(lambda: _kill_long_paused_vms(cif), config.getint('vars', 'vm_kill_paused_time') // 2, scheduler, exclusive=True, discard=False), ] if config.getboolean('sampling', 'enable'): ops.extend([ # libvirt sampling using bulk stats can block, but unresponsive # domains are handled inside VMBulkstatsMonitor for performance # reasons; thus, does not need dispatching. Operation( sampling.VMBulkstatsMonitor(libvirtconnection.get(cif), cif.getVMs, sampling.stats_cache), config.getint('vars', 'vm_sample_interval'), scheduler), Operation(sampling.HostMonitor(cif=cif), config.getint('vars', 'host_sample_stats_interval'), scheduler, timeout=config.getint('vars', 'host_sample_stats_interval'), exclusive=True, discard=False), ]) return ops
def compatible_cpu_models(): """ Compare qemu's CPU models to models the host is capable of emulating. Due to historic reasons, this comparison takes into account the CPU vendor. Returns: A list of strings indicating compatible CPU models prefixed with 'model_'. Example: ['model_Haswell-noTSX', 'model_Nehalem', 'model_Conroe', 'model_coreduo', 'model_core2duo', 'model_Penryn', 'model_IvyBridge', 'model_Westmere', 'model_n270', 'model_SandyBridge'] """ def compatible(model, vendor): if not vendor: return False mode_xml = '' # POWER CPUs are special case because we run them using versioned # compat mode (aka host-model). Libvirt's compareCPU call uses the # selected mode - we have to be sure to tell it to compare CPU # capabilities based on the compat features, not the CPU itself. if cpuarch.is_ppc(cpuarch.real()): mode_xml = " mode='host-model'" model = model.lower() xml = '<cpu match="minimum"%s><model>%s</model>' \ '<vendor>%s</vendor></cpu>' % (mode_xml, model, vendor) try: return c.compareCPU(xml, 0) in (libvirt.VIR_CPU_COMPARE_SUPERSET, libvirt.VIR_CPU_COMPARE_IDENTICAL) except libvirt.libvirtError as e: # hack around libvirt BZ#795836 if e.get_error_code() == libvirt.VIR_ERR_OPERATION_INVALID: return False raise compatible_models = [] c = libvirtconnection.get() arch = cpuarch.real() if arch == cpuarch.S390X: # s390x uses libvirt domain caps for CPU model reporting all_models = domain_cpu_models(c, arch) compatible_models = [ model for (model, usable) in six.iteritems(all_models) if usable == 'yes' ] else: all_models = cpu_models() compatible_models = [ model for (model, vendor) in six.iteritems(all_models) if compatible(model, vendor) ] return list(set(["model_" + model for model in compatible_models]))
def main(*args): """ nwfilter Defines network filters on libvirt """ if len(args) > 1: raise ExtraArgsError() conn = libvirtconnection.get(None, False) NoMacSpoofingFilter().defineNwFilter(conn)
def main(): portProfile = os.environ.get('vmfex') if portProfile is not None: handleDirectPool(libvirtconnection.get()) if not _migration_script(): doc = hooking.read_domxml() interface, = doc.getElementsByTagName('interface') attachProfileToInterfaceXml(interface, portProfile) removeFilter(interface) hooking.write_domxml(doc)
def testProcessDeviceParamsInvalidEncoding(self): deviceXML = hostdev._process_device_params( libvirtconnection.get().nodeDeviceLookupByName( hostdevlib.COMPUTER_DEVICE).XMLDesc() ) self.assertEqual( hostdevlib.COMPUTER_DEVICE_PROCESSED, deviceXML )
def free_pages_by_cell(page_sizes, numa_index): free_pages = {} if page_sizes: conn = libvirtconnection.get() libvirt_freepages = conn.getFreePages(page_sizes, numa_index, 1) free_pages = \ {int(page_size): {'freePages': free_pages} for page_size, free_pages in libvirt_freepages[numa_index].items()} return free_pages
def removeNetwork(network): netName = LIBVIRT_NET_PREFIX + network conn = libvirtconnection.get() net = _netlookup_by_name(conn, netName) if net: if net.isActive(): net.destroy() if net.isPersistent(): net.undefine()
def _getTscScaling(): """ Read TSC Scaling from libvirt. This is only available in libvirt >= 5.5.0 (and 4.5.0-21 for RHEL7) """ conn = libvirtconnection.get() caps = xmlutils.fromstring(conn.getCapabilities()) counter = caps.findall("./host/cpu/counter[@name='tsc']") if len(counter) > 0: return counter[0].get('scaling') == 'yes' logging.debug('No TSC counter returned by Libvirt') return False
def memory_by_cell(index): ''' Get the memory stats of a specified numa node, the unit is MiB. :param cell: the index of numa node :type cell: int :return: dict like {'total': '49141', 'free': '46783'} ''' conn = libvirtconnection.get() meminfo = conn.getMemoryStats(index, 0) meminfo['total'] = str(meminfo['total'] // 1024) meminfo['free'] = str(meminfo['free'] // 1024) return meminfo
def _get_device_ref_and_params(device_name): libvirt_device = libvirtconnection.get().\ nodeDeviceLookupByName(device_name) params = _process_device_params(libvirt_device.XMLDesc(0)) if params['capability'] != 'scsi': return libvirt_device, params devices, _ = _get_devices_from_libvirt() with _DeviceTreeCache(devices) as cache: params.update(_process_scsi_device_params(device_name, cache)) return libvirt_device, params
def memory_by_cell(index): ''' Get the memory stats of a specified numa node, the unit is MiB. :param cell: the index of numa node :type cell: int :return: dict like {'total': '49141', 'free': '46783'} ''' conn = libvirtconnection.get() meminfo = conn.getMemoryStats(index, 0) meminfo['total'] = str(meminfo['total'] / 1024) meminfo['free'] = str(meminfo['free'] / 1024) return meminfo
def _getTscFrequencyLibvirt(): """ Read TSC Frequency from libvirt. This is only available in libvirt >= 5.5.0 (and 4.5.0-21 for RHEL7) """ conn = libvirtconnection.get() caps = xmlutils.fromstring(conn.getCapabilities()) counter = caps.findall("./host/cpu/counter[@name='tsc']") if len(counter) > 0: # Libvirt reports frequency in Hz, cut off last six digits to get MHz return counter[0].get('frequency')[:-6] logging.debug('No TSC counter returned by Libvirt') return None
def testCallFailedConnectionUp(self): """ libvirtMock will raise an error when nodeDeviceLookupByName is called. When getLibVersion is called (used by libvirtconnection to recognize disconnections) it will not raise an error -> in that case an error should be raised ('Unknown libvirterror'). """ with run_libvirt_event_loop(): connection = libvirtconnection.get(killOnFailure=True) LibvirtMock.virConnect.failNodeDeviceLookupByName = True LibvirtMock.virConnect.failGetLibVersion = False self.assertRaises(LibvirtMock.libvirtError, connection.nodeDeviceLookupByName)
def testCallFailedConnectionDown(self): """ libvirtMock will raise an error when nodeDeviceLookupByName is called. When getLibVersion is called (used by libvirtconnection to recognize disconnections) it will also raise an error -> in that case os.kill should be called ('connection to libvirt broken.'). """ with run_libvirt_event_loop(): connection = libvirtconnection.get(killOnFailure=True) LibvirtMock.virConnect.failNodeDeviceLookupByName = True LibvirtMock.virConnect.failGetLibVersion = True self.assertRaises(TerminationException, connection.nodeDeviceLookupByName)
def clear(): """ Clear all regsistered ovirt secrets. Should be called during startup and shutdown to ensure that we don't leave around stale or unneeded secrets. """ logging.info("Unregistering all secrets") con = libvirtconnection.get() for virsecret in con.listAllSecrets(): try: if _is_ovirt_secret(virsecret): virsecret.undefine() except libvirt.libvirtError as e: logging.error("Could not unregister %s: %s", virsecret, e)
def compatible_cpu_models(): """ Compare qemu's CPU models to models the host is capable of emulating. Due to historic reasons, this comparison takes into account the CPU vendor. Returns: A list of strings indicating compatible CPU models prefixed with 'model_'. Example: ['model_Haswell-noTSX', 'model_Nehalem', 'model_Conroe', 'model_coreduo', 'model_core2duo', 'model_Penryn', 'model_IvyBridge', 'model_Westmere', 'model_n270', 'model_SandyBridge'] """ def compatible(model, vendor): if not vendor: return False xml = '<cpu match="minimum"><model>%s</model>' \ '<vendor>%s</vendor></cpu>' % (model, vendor) try: return c.compareCPU(xml, 0) in (libvirt.VIR_CPU_COMPARE_SUPERSET, libvirt.VIR_CPU_COMPARE_IDENTICAL) except libvirt.libvirtError as e: # hack around libvirt BZ#795836 if e.get_error_code() == libvirt.VIR_ERR_OPERATION_INVALID: return False raise compatible_models = [] c = libvirtconnection.get() arch = cpuarch.real() if arch == cpuarch.S390X: # s390x uses libvirt domain caps for CPU model reporting all_models = domain_cpu_models(c, arch) compatible_models = [model for (model, usable) in six.iteritems(all_models) if usable == 'yes'] else: all_models = cpu_models() compatible_models = [model for (model, vendor) in six.iteritems(all_models) if compatible(model, vendor)] return ["model_" + model for model in compatible_models]
def lookup_external_vms(cif): conn = libvirtconnection.get() for vm_id in cif.get_unknown_vm_ids(): try: dom_obj = conn.lookupByUUIDString(vm_id) dom_xml = dom_obj.XMLDesc(0) except libvirt.libvirtError as e: if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN: logging.debug("External domain %s not found", vm_id) continue else: raise if _is_ignored_vm(vm_id, dom_obj, dom_xml): continue logging.debug("Recovering external domain: %s", vm_id) if _recover_domain(cif, vm_id, dom_xml, True): cif.log.info("Recovered new external domain: %s", vm_id) else: cif.log.info("Failed to recover new external domain: %s", vm_id)
def cpu_features(): """ Read CPU features from dom capabilities. Returns: A list of strings indicating CPU features. """ c = libvirtconnection.get() arch = cpuarch.real() xmldomcaps = _get_domain_capabilities(c, arch) if xmldomcaps is None: logging.error('Error while getting CPU features: ' 'no domain capabilities found') return [] cpucaps = xmldomcaps.find('cpu') if cpucaps is None: logging.error('Error while getting CPU features: ' 'no domain CPU capabilities found') return [] features = [] for mode in cpucaps.findall('mode'): if mode.get('name') == _CpuMode.HOST_MODEL: for feature in mode.findall('feature'): if feature.get('policy') == 'require': features.append(feature.get('name')) # Easier to add here than in Engine: # If -IBRS suffix is present in the CPU model, we can assume # spec_ctrl feature. model = mode.find('model') if model is not None and model.text.endswith('-IBRS'): spec_ctrl = 'spec_ctrl' if spec_ctrl not in features: features.append(spec_ctrl) logging.debug('CPU features: %s', features) return features
def register(secrets, clear=False): try: secrets = [Secret(params) for params in secrets] except ValueError as e: logging.warning("Attempt to register invalid secret: %s", e) return response.error("secretBadRequestErr") con = libvirtconnection.get() try: for secret in secrets: logging.info("Registering secret %s", secret) secret.register(con) if clear: uuids = frozenset(sec.uuid for sec in secrets) for virsecret in con.listAllSecrets(): if (virsecret.UUIDString() not in uuids and _is_ovirt_secret(virsecret)): virsecret.undefine() except libvirt.libvirtError as e: logging.error("Could not register secret %s: %s", secret, e) return response.error("secretRegisterErr") return response.success()
def _list_domains(): conn = libvirtconnection.get() domains = [] for dom_obj in conn.listAllDomains(): dom_uuid = 'unknown' try: dom_uuid = dom_obj.UUIDString() logging.debug("Found domain %s", dom_uuid) dom_xml = dom_obj.XMLDesc() except libvirt.libvirtError as e: if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN: logging.exception("domain %s is dead", dom_uuid) else: raise else: if _is_ignored_vm(dom_uuid, dom_obj, dom_xml): continue domains.append(( dom_obj, dom_xml, _is_external_vm(dom_xml), )) return domains
def contEIOVms(self, sdUUID, isDomainStateValid): # This method is called everytime the onDomainStateChange # event is emitted, this event is emitted even when a domain goes # INVALID if this happens there is nothing to do if not isDomainStateValid: return libvirtCon = libvirtconnection.get() libvirtVms = libvirtCon.listAllDomains( libvirt.VIR_CONNECT_LIST_DOMAINS_PAUSED) with self.vmContainerLock: self.log.info("vmContainerLock acquired") for libvirtVm in libvirtVms: state = libvirtVm.state(0) if state[1] == libvirt.VIR_DOMAIN_PAUSED_IOERROR: vmId = libvirtVm.UUIDString() vmObj = self.vmContainer[vmId] if sdUUID in vmObj.sdIds: self.log.info("Trying to resume VM %s after EIO", vmId) try: vmObj.maybe_resume() except DestroyedOnResumeError: pass
def is_libvirt_network(netname): conn = libvirtconnection.get() libvirt_nets = conn.listAllNetworks() netname = LIBVIRT_NET_PREFIX + netname return any(n.name() == netname for n in libvirt_nets)
def addBridgeToLibvirt(bridgeName): conn = libvirtconnection.get(None, False) if bridgeName not in conn.listNetworks(): conn.networkCreateXML( '''<network><name>%s</name><forward mode='bridge'/><bridge ''' '''name='%s'/></network>''' % (bridgeName, bridgeName))
def _create(cif, scheduler): def per_vm_operation(func, period): disp = VmDispatcher( cif.getVMs, _executor, func, _timeout_from(period)) return Operation(disp, period, scheduler) ops = [ # Needs dispatching because updating the volume stats needs # access to the storage, thus can block. per_vm_operation( UpdateVolumes, config.getint('irs', 'vol_size_sample_interval')), # Job monitoring need QEMU monitor access. per_vm_operation( BlockjobMonitor, config.getint('vars', 'vm_sample_jobs_interval')), # We do this only until we get high water mark notifications # from QEMU. It accesses storage and/or QEMU monitor, so can block, # thus we need dispatching. per_vm_operation( DriveWatermarkMonitor, config.getint('vars', 'vm_watermark_interval')), Operation( lambda: recovery.lookup_external_vms(cif), config.getint('sampling', 'external_vm_lookup_interval'), scheduler, exclusive=True, discard=False), Operation( lambda: _kill_long_paused_vms(cif), config.getint('vars', 'vm_kill_paused_time') // 2, scheduler, exclusive=True, discard=False), ] if config.getboolean('sampling', 'enable'): ops.extend([ # libvirt sampling using bulk stats can block, but unresponsive # domains are handled inside VMBulkstatsMonitor for performance # reasons; thus, does not need dispatching. Operation( sampling.VMBulkstatsMonitor( libvirtconnection.get(cif), cif.getVMs, sampling.stats_cache), config.getint('vars', 'vm_sample_interval'), scheduler), Operation( sampling.HostMonitor(cif=cif), config.getint('vars', 'host_sample_stats_interval'), scheduler, timeout=config.getint('vars', 'host_sample_stats_interval'), exclusive=True, discard=False), ]) return ops
def _createNetwork(netXml): conn = libvirtconnection.get() net = conn.networkDefineXML(netXml) net.create() net.setAutostart(1)
def test_3k_storage_devices(self): with hostdevlib.Connection.use_hostdev_tree(): self.assertEqual( len(hostdev.list_by_caps()), len(libvirtconnection.get().listAllDevices()) )
def _get_libvirt_caps(): conn = libvirtconnection.get() return conn.getCapabilities()