2013-03-18 01:06:52 +04:00
#
# Base class for all VM devices
#
2013-10-28 00:59:47 +04:00
# Copyright 2008, 2013 Red Hat, Inc.
2013-03-18 01:06:52 +04:00
#
2018-04-04 16:35:41 +03:00
# This work is licensed under the GNU GPLv2 or later.
2018-03-20 22:00:02 +03:00
# See the COPYING file in the top-level directory.
2013-03-18 01:06:52 +04:00
2018-03-20 19:27:37 +03:00
from . . xmlbuilder import XMLBuilder , XMLChildProperty , XMLProperty
2013-09-11 19:47:09 +04:00
2019-05-14 19:45:57 +03:00
class DeviceVirtioDriver ( XMLBuilder ) :
"""
Represents shared virtio < driver > options
"""
XML_NAME = " driver "
ats = XMLProperty ( " ./@ats " , is_onoff = True )
iommu = XMLProperty ( " ./@iommu " , is_onoff = True )
2020-09-10 19:44:36 +03:00
packed = XMLProperty ( " ./@packed " , is_onoff = True )
2022-01-27 01:11:56 +03:00
page_per_vq = XMLProperty ( " ./@page_per_vq " , is_onoff = True )
2019-05-14 19:45:57 +03:00
2019-05-14 03:03:23 +03:00
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 " )
2018-03-20 19:18:35 +03:00
class DeviceAlias ( XMLBuilder ) :
2018-03-21 17:53:34 +03:00
XML_NAME = " alias "
2013-09-19 21:27:30 +04:00
name = XMLProperty ( " ./@name " )
2013-09-11 19:47:09 +04:00
2018-03-20 19:18:35 +03:00
class DeviceBoot ( XMLBuilder ) :
2018-03-21 17:53:34 +03:00
XML_NAME = " boot "
2014-02-09 22:36:12 +04:00
order = XMLProperty ( " ./@order " , is_int = True )
2019-05-14 19:33:07 +03:00
loadparm = XMLProperty ( " ./@loadparm " )
2014-02-09 22:36:12 +04:00
2018-03-20 19:18:35 +03:00
class DeviceAddress ( XMLBuilder ) :
2013-09-11 19:47:09 +04:00
"""
Examples :
< address type = ' pci ' domain = ' 0x0000 ' bus = ' 0x00 ' slot = ' 0x04 ' function = ' 0x0 ' / >
< address type = ' drive ' controller = ' 0 ' bus = ' 0 ' unit = ' 0 ' / >
< address type = ' ccid ' controller = ' 0 ' slot = ' 0 ' / >
< address type = ' virtio-serial ' controller = ' 1 ' bus = ' 0 ' port = ' 4 ' / >
"""
ADDRESS_TYPE_PCI = " pci "
ADDRESS_TYPE_DRIVE = " drive "
ADDRESS_TYPE_VIRTIO_SERIAL = " virtio-serial "
ADDRESS_TYPE_CCID = " ccid "
ADDRESS_TYPE_SPAPR_VIO = " spapr-vio "
2018-03-21 17:53:34 +03:00
XML_NAME = " address "
2013-09-11 19:47:09 +04:00
_XML_PROP_ORDER = [ " type " , " domain " , " controller " , " bus " , " slot " ,
" function " , " target " , " unit " , " multifunction " ]
2017-11-23 12:32:46 +03:00
def pretty_desc ( self ) :
pretty_desc = None
if self . type == self . ADDRESS_TYPE_DRIVE :
2020-07-12 00:31:40 +03:00
pretty_desc = ( " %s : %s : %s : %s " %
2017-11-23 12:32:46 +03:00
( self . controller , self . bus , self . target , self . unit ) )
return pretty_desc
2013-09-11 19:47:09 +04:00
2013-09-19 21:27:30 +04:00
type = XMLProperty ( " ./@type " )
2016-06-11 19:36:45 +03:00
# type=pci
2013-09-19 21:27:30 +04:00
domain = XMLProperty ( " ./@domain " , is_int = True )
bus = XMLProperty ( " ./@bus " , is_int = True )
slot = XMLProperty ( " ./@slot " , is_int = True )
function = XMLProperty ( " ./@function " , is_int = True )
2016-06-11 19:36:45 +03:00
multifunction = XMLProperty ( " ./@multifunction " , is_onoff = True )
2019-05-14 19:20:53 +03:00
zpci_uid = XMLProperty ( " ./zpci/@uid " )
zpci_fid = XMLProperty ( " ./zpci/@fid " )
2016-06-11 19:36:45 +03:00
# type=drive
2013-09-19 21:27:30 +04:00
controller = XMLProperty ( " ./@controller " , is_int = True )
unit = XMLProperty ( " ./@unit " , is_int = True )
port = XMLProperty ( " ./@port " , is_int = True )
target = XMLProperty ( " ./@target " , is_int = True )
2016-06-11 19:36:45 +03:00
# 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 " )
2013-03-18 01:06:52 +04:00
2013-04-13 22:34:52 +04:00
2018-03-20 19:18:35 +03:00
class Device ( XMLBuilder ) :
2013-03-18 01:06:52 +04:00
"""
Base class for all domain xml device objects .
"""
2013-09-11 19:47:09 +04:00
def __init__ ( self , * args , * * kwargs ) :
2013-03-18 01:06:52 +04:00
"""
Initialize device state
2018-02-14 15:17:31 +03:00
: param conn : libvirt connection to validate device against
2013-03-18 01:06:52 +04:00
"""
2013-09-11 19:47:09 +04:00
XMLBuilder . __init__ ( self , * args , * * kwargs )
2019-05-14 19:45:57 +03:00
self . _XML_PROP_ORDER = self . _XML_PROP_ORDER + [
" virtio_driver " , " alias " , " address " ]
2013-03-18 01:06:52 +04:00
2018-03-20 19:18:35 +03:00
alias = XMLChildProperty ( DeviceAlias , is_single = True )
address = XMLChildProperty ( DeviceAddress , is_single = True )
boot = XMLChildProperty ( DeviceBoot , is_single = True )
2019-05-14 19:45:57 +03:00
virtio_driver = XMLChildProperty ( DeviceVirtioDriver , is_single = True )
2013-09-11 19:47:09 +04:00
2018-03-21 01:59:14 +03:00
@property
def DEVICE_TYPE ( self ) :
2018-03-21 17:53:34 +03:00
return self . XML_NAME
2019-02-08 01:42:25 +03:00
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 " ] ,
2024-02-12 12:40:19 +03:00
" audio " : [ " type " , " id " ] ,
2019-02-08 01:42:25 +03:00
" video " : [ " model " , " xmlindex " ] ,
2020-01-27 15:38:53 +03:00
" watchdog " : [ " model " , " xmlindex " ] ,
2019-02-08 01:42:25 +03:00
" 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 " ] ,
2019-05-13 21:42:50 +03:00
" rng " : [ " backend_model " , " xmlindex " ] ,
2020-01-27 15:38:53 +03:00
" panic " : [ " model " , " xmlindex " ] ,
2021-07-26 23:14:30 +03:00
" shmem " : [ " name " , " xmlindex " ] ,
2020-01-27 15:38:53 +03:00
" vsock " : [ " model " , " xmlindex " ] ,
" memballoon " : [ " model " , " xmlindex " ] ,
2020-07-07 10:55:53 +03:00
" iommu " : [ " model " , " xmlindex " ] ,
2019-02-08 01:42:25 +03:00
}
if id ( self ) == id ( newdev ) :
return True
if not isinstance ( self , type ( newdev ) ) :
return False
2020-01-27 15:38:53 +03:00
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 ( ) )
2019-02-08 01:42:25 +03:00
for devprop in devprops [ self . DEVICE_TYPE ] :
if devprop == " xmlindex " :
2020-01-27 15:38:53 +03:00
if not can_check_xml :
continue
2019-02-08 01:42:25 +03:00
origval = self . get_xml_idx ( )
newval = idx
else :
origval = getattr ( self , devprop )
newval = getattr ( newdev , devprop )
if origval != newval :
return False
return True