def make_drive(log, dom, irs, index, conf, block_info): cfg = utils.picklecopy(conf) cfg['index'] = index cfg['path'] = '/{iface}/{index}'.format( iface=cfg['iface'], index=cfg['index'] ) add_uuids(index, cfg) if 'diskReplicate' in cfg: add_uuids(index + REPLICA_BASE_INDEX, cfg['diskReplicate']) drive = Drive(log, **cfg) dom.block_info[drive.path] = utils.picklecopy(block_info) if (drive.format == "raw" and block_info["physical"] != block_info["capacity"]): raise RuntimeError( "Invalid test data - " "raw disk capacity != physical: %s" % block_info) irs.set_drive_size(drive, block_info['physical']) return drive
def getGuestInfo(self): # This is rather hacky, but for now we want to prefer information from # oVirt GA over QEMU-GA info = { 'username': '******', 'session': 'Unknown', 'memUsage': 0, 'guestCPUCount': -1, 'appsList': (), 'guestIPs': '', 'guestFQDN': ''} diskMapping = {} qga = self._qgaGuestInfo() if qga is not None: if 'diskMapping' in qga: diskMapping.update(qga['diskMapping']) del qga['diskMapping'] info.update(qga) if self.isResponsive(): info.update(self.guestInfo) diskMapping.update(self.oVirtGuestDiskMapping) else: if len(self.guestInfo['appsList']) > 0: info['appsList'] = self.guestInfo['appsList'] if len(self.guestInfo['guestIPs']) > 0: info['guestIPs'] = self.guestInfo['guestIPs'] if len(self.guestInfo['guestFQDN']) > 0: info['guestFQDN'] = self.guestInfo['guestFQDN'] self.guestDiskMapping = diskMapping return utils.picklecopy(info)
def getGuestInfo(self): # Prefer information from QEMU GA if available. Fall-back to oVirt GA # only for info that is not availble in QEMU GA. info = { 'username': '******', 'session': 'Unknown', 'memUsage': 0, 'guestCPUCount': -1, 'appsList': (), 'guestIPs': '', 'guestFQDN': ''} diskMapping = {} if self.isResponsive(): info.update(self.guestInfo) diskMapping.update(self.oVirtGuestDiskMapping) else: if len(self.guestInfo['appsList']) > 0: info['appsList'] = self.guestInfo['appsList'] if len(self.guestInfo['guestIPs']) > 0: info['guestIPs'] = self.guestInfo['guestIPs'] if len(self.guestInfo['guestFQDN']) > 0: info['guestFQDN'] = self.guestInfo['guestFQDN'] qga = self._qgaGuestInfo() if qga is not None: if 'diskMapping' in qga: diskMapping.update(qga['diskMapping']) del qga['diskMapping'] if len(info['appsList']) > 0 and 'appsList' in qga: # This is an exception since the entry from QEMU GA is faked. # Prefer oVirt GA info if available. Take fake QEMU GA info # only if the other is not available. del qga['appsList'] info.update(qga) self.guestDiskMapping = diskMapping return utils.picklecopy(info)
def io_tune_update_list(tunables, changes): """ This method updates elements in a list of VmDiskDeviceTuneLimits :param tunables: List of VmDiskDeviceTuneLimits to be updated :param changes: List of VmDiskDeviceTuneLimits with changes """ indexByPath = {} indexByName = {} for id, tune in enumerate(tunables): if "path" in tune: indexByPath[tune["path"]] = id if "name" in tune: indexByName[tune["name"]] = id for change in changes: old_id = None if ("name" in change and change["name"] in indexByName): old_id = indexByName[change["name"]] elif ("path" in change and change["path"] in indexByPath): old_id = indexByPath[change["path"]] if old_id is None: new_tune = utils.picklecopy(change) tunables.append(new_tune) else: old_tune = tunables[old_id] new_tune = io_tune_merge(old_tune, change) tunables[old_id] = new_tune
def _dump_device(md_obj, data, node_name=_DEVICE): elems = [] data = utils.picklecopy(data) for key in _IGNORED_KEYS: data.pop(key, None) for key in _DEVICE_SUBKEYS: value = data.pop(key, {}) if not value and key in _NONEMPTY_KEYS: # empty elements make no sense continue if key == _PORT_MIRRORING: elems.append(_dump_port_mirroring(md_obj, value)) elif key == _REPLICA: elems.append(_dump_device(md_obj, value, _REPLICA)) elif key in _LAYERED_KEYS: elems.append( _dump_layered(md_obj, key, _LAYERED_KEYS[key], value) ) elif key == _SPEC_PARAMS: elems.append(_dump_device_spec_params(md_obj, value)) elif key == _PAYLOAD: elems.append(_dump_payload(md_obj, _PAYLOAD, value)) else: elems.append(md_obj.dump(key, **value)) dev_elem = md_obj.dump(node_name, **data) for elem in elems: vmxml.append_child(dev_elem, etree_child=elem) return dev_elem
def io_tune_merge(old, new): """ Merge two VmDiskDeviceTuneLimits structures in their dictionary form and return the new iotune setting. :param old: VmDiskDeviceTuneLimits in dict form :param new: VmDiskDeviceTuneLimits in dict form :return: old + new (in this order) in the dict form """ result = utils.picklecopy(old) if "name" in new: result["name"] = new["name"] if "path" in new: result["path"] = new["path"] result.setdefault("maximum", {}) if "maximum" in new: result["maximum"].update(new["maximum"]) result.setdefault("guaranteed", {}) if "guaranteed" in new: result["guaranteed"].update(new["guaranteed"]) return result
def _collect(self, vm): data = vm.status() data['startTime'] = vm.start_time if vm.lastStatus != vmstatus.DOWN: guestInfo = vm.guestAgent.getGuestInfo() data['username'] = guestInfo['username'] data['guestIPs'] = guestInfo['guestIPs'] data['guestFQDN'] = guestInfo['guestFQDN'] else: data['username'] = "" data['guestIPs'] = "" data['guestFQDN'] = "" if 'sysprepInf' in data: del data['sysprepInf'] if 'floppy' in data: del data['floppy'] for drive in data.get('drives', []): for d in vm.getDiskDevices(): if isVdsmImage(d) and drive.get('volumeID') == d.volumeID: drive['truesize'] = str(d.truesize) drive['apparentsize'] = str(d.apparentsize) data['_blockJobs'] = utils.picklecopy( vm.conf.get('_blockJobs', {})) return data
def _cmd_send(self, dispatcher, frame): destination = frame.headers.get(stomp.Headers.DESTINATION, None) if destination in self.request_queues: # default subscription self._handle_internal(dispatcher, frame.headers.get(stomp.Headers.REPLY_TO), frame.body) return else: try: subs = self._sub_dests[destination] except KeyError: self._send_error("Subscription not available", dispatcher.connection) return if not subs: self._send_error("Subscription not available", dispatcher.connection) return for subscription in subs: headers = utils.picklecopy(frame.headers) headers = {stomp.Headers.SUBSCRIPTION: subscription.id} headers.update(frame.headers) res = stomp.Frame( stomp.Command.MESSAGE, headers, frame.body ) subscription.client.send_raw(res)
def device(self, **kwargs): """ Helper context manager to get and update the metadata of a given device. Any change performed to the device metadata is not committed to the underlying libvirt.Domain until dump() is called. :param dom: domain to access :type dom: libvirt.Domain kwargs: attributes to match to identify the device; values are expected to be strings. Example: let's start with dom.metadata() -> <vm> <device id="dev0"> <foo>bar</foo> </device> <device id="dev1"> <number type="int">42</number> </device> </vm> let's run this code md_desc = Descriptor('vm') md_desc.load(dom) with md_desc.device(id='dev0') as vm: print(vm) will emit { 'foo': 'bar' } """ dev_data = self._find_device(kwargs) if dev_data is None: dev_data = self._add_device(kwargs) self._log.debug('device metadata: %s', dev_data) data = utils.picklecopy(dev_data) yield data dev_data.clear() dev_data.update(utils.picklecopy(data)) self._log.debug('device metadata updated: %s', dev_data)
def config(self): """ Return dictionary of constructor kwargs or None. This is used to make a legacy device configuration for this instance. Return None in case `update_device_info` already adds the legacy configuration. """ return compat.device_config(utils.picklecopy(self._conf))
def _update_meta_params(params, meta): for key in METADATA_KEYS: if key in meta: params[key] = meta[key] for key in METADATA_NESTED_KEYS: if key in meta: params[key] = utils.picklecopy(meta[key]) core.update_device_params_from_meta(params, meta)
def getGuestInfo(self): if self.isResponsive(): return utils.picklecopy(self.guestInfo) else: return { 'username': '******', 'session': 'Unknown', 'memUsage': 0, 'guestCPUCount': -1, 'appsList': self.guestInfo['appsList'], 'guestIPs': self.guestInfo['guestIPs'], 'guestFQDN': self.guestInfo['guestFQDN']}
def test_caps(self): """ Make sure the capabilities are stored properly and the returned capabilities are stable. """ c1 = { "version": "1.0", "commands": ["foo", "bar"], } c2 = utils.picklecopy(c1) c2["commands"].append("baz") self.qga_poller.update_caps(self.vm.id, c1) c3 = self.qga_poller.get_caps(self.vm.id) self.qga_poller.update_caps(self.vm.id, c2) self.assertEqual(c1, c3) self.assertNotEqual(c2, c3)
def all_devices(self, **kwargs): """ Return all the devices which match the given attributes. kwargs: each argument corresponds to a <device> attribute name and the value (string) to the attribute value; only devices having all the given values are returned. :rtype: dict Example: let's start with dom.metadata() -> <vm> <device kind="blah" id="dev0"> <foo>bar</foo> </device> <device kind="blah" id="dev1"> <number type="int">42</number> </device> </vm> let's run this code md_desc = Descriptor('vm') md_desc.load(dom) print [dev for dev in md_desc.all_devices(kind="blah")] will emit [{'foo': 'bar'}, {'number': 42}] """ for data in self._matching_devices(kwargs): # A shallow copy ({}.copy) would have been enough. # We need to support complex storage devices, hence # we use picklecopy. yield utils.picklecopy(data)
def wrapper(*args, **kwargs): try: logLevel = logging.DEBUG suppress_logging = f.__name__ in ('getAllVmStats',) # TODO: This password protection code is fragile and ugly. Password # protection should be done in the wrapped methods, and logging # shold be done in the next layers, similar to storage logs. displayArgs = args if f.__name__ == 'vmDesktopLogin': if 'password' in kwargs: raise TypeError("Got an unexpected keyword argument: " "'password'") if len(args) > 3: displayArgs = args[:3] + ('****',) + args[4:] elif f.__name__ == 'getExternalVMs': if len(args) >= 3: displayArgs = args[:2] + ('****',) + args[3:] elif f.__name__ == 'getExternalVMNames': if len(args) == 3: displayArgs = args[:2] + ('****',) elif f.__name__ == 'convertExternalVm': if len(args) > 3: displayArgs = args[:2] + ('****',) + args[3:] elif f.__name__ == 'registerSecrets': secrets = protect_passwords(utils.picklecopy(args[0])) displayArgs = (secrets,) + args[1:] elif f.__name__ == 'vmUpdateDevice': if len(args) >= 2 and args[1].get( 'deviceType', '') == 'graphics': params = protect_passwords(utils.picklecopy(args[1])) displayArgs = (args[0],) + (params,) + args[2:] # Logging current call logStr = 'client [%s]::call %s with %s %s' % \ (getattr(f.__self__.cif.threadLocal, 'client', ''), f.__name__, displayArgs, kwargs) # if flowID exists if getattr(f.__self__.cif.threadLocal, 'flowID', None) is not None: logStr += " flowID [%s]" % f.__self__.cif.threadLocal.flowID # Ready to show the log into vdsm.log f.__self__.log.log(logLevel, logStr) if f.__self__.cif.ready: res = f(*args, **kwargs) else: res = errCode['recovery'] log_res = "(suppressed)" if suppress_logging else res f.__self__.cif.log.log(logLevel, 'return %s with %s', f.__name__, log_res) return res except libvirt.libvirtError as e: f.__self__.cif.log.error("libvirt error", exc_info=True) if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN: return errCode['noVM'] else: return errCode['unexpected'] except VdsmException as e: f.__self__.cif.log.error("vdsm exception occured", exc_info=True) return e.response() except: f.__self__.cif.log.error("unexpected error", exc_info=True) return errCode['unexpected']
def get_types(self): return utils.picklecopy(self._types)
def get_methods(self): return utils.picklecopy(self._methods)
def get_caps(self, vm_id): with self._capabilities_lock: # Return a copy so the caller has a stable representation return utils.picklecopy(self._capabilities.get(vm_id, None))
def test_picklecopy_exact(self): self.assertEqual(utils.picklecopy(VM_STATUS_DUMP), copy.deepcopy(VM_STATUS_DUMP))
def get_guest_info(self, vm_id): with self._guest_info_lock: # Return a copy so the caller has a stable representation return utils.picklecopy(self._guest_info.get(vm_id, None))
def update_metadata_from_object(data, dev_obj, keys): for key in keys: value = getattr(dev_obj, key, None) if value is not None: data[key] = utils.picklecopy(value)