# # Base class for all VM devices # # Copyright 2008, 2013 Red Hat, Inc. # # This work is licensed under the GNU GPLv2 or later. # See the COPYING file in the top-level directory. from ..xmlbuilder import XMLBuilder, XMLChildProperty, XMLProperty class DeviceVirtioDriver(XMLBuilder): """ Represents shared virtio options """ XML_NAME = "driver" ats = XMLProperty("./@ats", is_onoff=True) iommu = XMLProperty("./@iommu", is_onoff=True) packed = XMLProperty("./@packed", is_onoff=True) page_per_vq = XMLProperty("./@page_per_vq", is_onoff=True) class DeviceSeclabel(XMLBuilder): """ Minimal seclabel that's used for device sources. """ XML_NAME = "seclabel" model = XMLProperty("./@model") relabel = XMLProperty("./@relabel", is_yesno=True) label = XMLProperty("./label") class DeviceAlias(XMLBuilder): XML_NAME = "alias" name = XMLProperty("./@name") class DeviceBoot(XMLBuilder): XML_NAME = "boot" order = XMLProperty("./@order", is_int=True) loadparm = XMLProperty("./@loadparm") class DeviceAddress(XMLBuilder): """ Examples:
""" ADDRESS_TYPE_PCI = "pci" ADDRESS_TYPE_DRIVE = "drive" ADDRESS_TYPE_VIRTIO_SERIAL = "virtio-serial" ADDRESS_TYPE_CCID = "ccid" ADDRESS_TYPE_SPAPR_VIO = "spapr-vio" XML_NAME = "address" _XML_PROP_ORDER = ["type", "domain", "controller", "bus", "slot", "function", "target", "unit", "multifunction"] def pretty_desc(self): pretty_desc = None if self.type == self.ADDRESS_TYPE_DRIVE: pretty_desc = ("%s:%s:%s:%s" % (self.controller, self.bus, self.target, self.unit)) return pretty_desc type = XMLProperty("./@type") # type=pci domain = XMLProperty("./@domain", is_int=True) bus = XMLProperty("./@bus", is_int=True) slot = XMLProperty("./@slot", is_int=True) function = XMLProperty("./@function", is_int=True) multifunction = XMLProperty("./@multifunction", is_onoff=True) zpci_uid = XMLProperty("./zpci/@uid") zpci_fid = XMLProperty("./zpci/@fid") # type=drive controller = XMLProperty("./@controller", is_int=True) unit = XMLProperty("./@unit", is_int=True) port = XMLProperty("./@port", is_int=True) target = XMLProperty("./@target", is_int=True) # type=spapr-vio reg = XMLProperty("./@reg") # type=ccw cssid = XMLProperty("./@cssid") ssid = XMLProperty("./@ssid") devno = XMLProperty("./@devno") # type=isa iobase = XMLProperty("./@iobase") irq = XMLProperty("./@irq") # type=dimm base = XMLProperty("./@base") class Device(XMLBuilder): """ Base class for all domain xml device objects. """ def __init__(self, *args, **kwargs): """ Initialize device state :param conn: libvirt connection to validate device against """ XMLBuilder.__init__(self, *args, **kwargs) self._XML_PROP_ORDER = self._XML_PROP_ORDER + [ "virtio_driver", "alias", "address"] alias = XMLChildProperty(DeviceAlias, is_single=True) address = XMLChildProperty(DeviceAddress, is_single=True) boot = XMLChildProperty(DeviceBoot, is_single=True) virtio_driver = XMLChildProperty(DeviceVirtioDriver, is_single=True) @property def DEVICE_TYPE(self): return self.XML_NAME def compare_device(self, newdev, idx): """ Attempt to compare this device against the passed @newdev, using various heuristics. For example, when removing a device from both active and inactive XML, the device XML my be very different or the devices may appear in different orders, so we have to do some fuzzy matching to determine if the devices are a 'match' """ devprops = { "disk": ["target", "bus"], "interface": ["macaddr", "xmlindex"], "input": ["bus", "type", "xmlindex"], "sound": ["model", "xmlindex"], "video": ["model", "xmlindex"], "watchdog": ["model", "xmlindex"], "hostdev": ["type", "managed", "xmlindex", "product", "vendor", "function", "domain", "slot"], "serial": ["type", "target_port"], "parallel": ["type", "target_port"], "console": ["type", "target_type", "target_port"], "graphics": ["type", "xmlindex"], "controller": ["type", "index"], "channel": ["type", "target_name"], "filesystem": ["target", "xmlindex"], "smartcard": ["mode", "xmlindex"], "redirdev": ["bus", "type", "xmlindex"], "tpm": ["type", "xmlindex"], "rng": ["backend_model", "xmlindex"], "panic": ["model", "xmlindex"], "shmem": ["name", "xmlindex"], "vsock": ["model", "xmlindex"], "memballoon": ["model", "xmlindex"], "iommu": ["model", "xmlindex"], } if id(self) == id(newdev): return True if not isinstance(self, type(newdev)): return False if self.DEVICE_TYPE not in devprops: # pragma: no cover return False # Only compare against XML ID values, if both devices were # taken from inside a complete guest hierarchy, otherwise # things won't line up. can_check_xml = ("devices" in newdev.get_xml_id() and "devices" in self.get_xml_id()) for devprop in devprops[self.DEVICE_TYPE]: if devprop == "xmlindex": if not can_check_xml: continue origval = self.get_xml_idx() newval = idx else: origval = getattr(self, devprop) newval = getattr(newdev, devprop) if origval != newval: return False return True