2013-03-17 17:06:52 -04:00
#
2013-10-27 21:59:46 +01:00
# Copyright 2009, 2013 Red Hat, Inc.
2013-03-17 17:06:52 -04:00
#
2018-04-04 14:35:41 +01:00
# This work is licensed under the GNU GPLv2 or later.
2018-03-20 15:00:02 -04:00
# See the COPYING file in the top-level directory.
2013-03-17 17:06:52 -04:00
2017-02-21 17:00:53 +04:00
import os
2021-05-31 21:54:26 +02:00
import uuid
2013-03-17 17:06:52 -04:00
2017-02-21 17:00:53 +04:00
from . xmlbuilder import XMLBuilder , XMLProperty , XMLChildProperty
2013-03-17 17:06:52 -04:00
2013-04-13 14:34:52 -04:00
2014-09-20 13:52:52 -04:00
def _compare_int ( nodedev_val , hostdev_val ) :
def _intify ( val ) :
try :
if " 0x " in str ( val ) :
return int ( val or ' 0x00 ' , 16 )
else :
return int ( val )
2017-07-24 09:26:48 +01:00
except Exception :
2014-09-20 13:52:52 -04:00
return - 1
2014-09-16 23:44:21 +08:00
2014-09-20 13:52:52 -04:00
nodedev_val = _intify ( nodedev_val )
hostdev_val = _intify ( hostdev_val )
return ( nodedev_val == hostdev_val or hostdev_val == - 1 )
2014-09-16 23:44:21 +08:00
2021-05-31 21:54:26 +02:00
def _compare_uuid ( nodedev_val , hostdev_val ) :
try :
nodedev_val = uuid . UUID ( nodedev_val )
hostdev_val = uuid . UUID ( hostdev_val )
except Exception : # pragma: no cover
return - 1
return ( nodedev_val == hostdev_val )
2017-02-21 17:00:53 +04:00
class DevNode ( XMLBuilder ) :
2018-03-21 10:53:34 -04:00
XML_NAME = " devnode "
2017-02-21 17:00:53 +04:00
node_type = XMLProperty ( " ./@type " )
path = XMLProperty ( " . " )
2013-09-22 18:13:24 -04:00
class NodeDevice ( XMLBuilder ) :
CAPABILITY_TYPE_NET = " net "
CAPABILITY_TYPE_PCI = " pci "
CAPABILITY_TYPE_USBDEV = " usb_device "
CAPABILITY_TYPE_STORAGE = " storage "
CAPABILITY_TYPE_SCSIBUS = " scsi_host "
CAPABILITY_TYPE_SCSIDEV = " scsi "
2017-02-21 17:00:54 +04:00
CAPABILITY_TYPE_DRM = " drm "
2021-04-14 17:18:55 +02:00
CAPABILITY_TYPE_MDEV = " mdev "
2013-09-22 18:13:24 -04:00
2022-01-21 12:39:26 -05:00
@staticmethod
def lookupNodedevByName ( conn , name ) :
"""
Search the nodedev list cache for a matching name , and return the
result .
: param conn : libvirt . virConnect instance to perform the lookup on
: param conn : nodedev name
: returns : NodeDevice instance
"""
for nodedev in conn . fetch_all_nodedevs ( ) :
if nodedev . name == name :
return nodedev
2018-03-21 10:53:34 -04:00
XML_NAME = " device "
2013-09-22 18:13:24 -04:00
2015-03-26 18:04:23 -04:00
# Libvirt can generate bogus 'system' XML:
# https://bugzilla.redhat.com/show_bug.cgi?id=1184131
_XML_SANITIZE = True
2013-09-22 18:13:24 -04:00
name = XMLProperty ( " ./name " )
parent = XMLProperty ( " ./parent " )
device_type = XMLProperty ( " ./capability/@type " )
2013-03-17 17:06:52 -04:00
2021-05-31 21:54:26 +02:00
def get_mdev_uuid ( self ) :
2021-10-26 14:18:40 -05:00
# libvirt 7.3.0 added a <uuid> element to the nodedev xml for mdev
# types. For older versions, we unfortunately have to parse the nodedev
# name, which uses the format "mdev_$UUID_WITH_UNDERSCORES"
if self . uuid is not None :
return self . uuid
2021-05-31 21:54:26 +02:00
return self . name [ 5 : ] . replace ( ' _ ' , ' - ' )
2019-06-05 15:11:31 -04:00
def compare_to_hostdev ( self , hostdev ) :
2019-06-05 15:29:10 -04:00
if self . device_type == " pci " :
2019-06-05 15:39:09 -04:00
if hostdev . type != " pci " :
2019-06-05 15:29:10 -04:00
return False
return ( _compare_int ( self . domain , hostdev . domain ) and
_compare_int ( self . bus , hostdev . bus ) and
_compare_int ( self . slot , hostdev . slot ) and
_compare_int ( self . function , hostdev . function ) )
2019-06-05 15:39:09 -04:00
if self . device_type == " usb_device " :
if hostdev . type != " usb " :
return False
return ( _compare_int ( self . product_id , hostdev . product ) and
_compare_int ( self . vendor_id , hostdev . vendor ) and
_compare_int ( self . bus , hostdev . bus ) and
_compare_int ( self . device , hostdev . device ) )
2021-05-31 21:54:26 +02:00
if self . device_type == " mdev " :
if hostdev . type != " mdev " :
return False
return _compare_uuid ( self . get_mdev_uuid ( ) , hostdev . uuid )
2019-06-05 15:11:31 -04:00
return False
2014-09-16 23:44:21 +08:00
2019-06-05 15:29:10 -04:00
########################
# XML helper functions #
########################
def is_pci_sriov ( self ) :
return self . _capability_type == " virt_functions "
def is_pci_bridge ( self ) :
return self . _capability_type == " pci-bridge "
2019-06-05 15:39:09 -04:00
def is_usb_linux_root_hub ( self ) :
return ( self . vendor_id == " 0x1d6b " and
self . product_id in [ " 0x0001 " , " 0x0002 " , " 0x0003 " ] )
2019-06-05 16:13:44 -04:00
def is_drm_render ( self ) :
2019-06-09 15:29:44 -04:00
return self . device_type == " drm " and self . drm_type == " render "
2019-06-05 16:13:44 -04:00
2019-06-05 15:29:10 -04:00
2019-06-05 15:11:31 -04:00
##################
# XML properties #
##################
2013-04-13 14:34:52 -04:00
2019-06-05 15:11:31 -04:00
# type='net' options
2013-09-22 18:13:24 -04:00
interface = XMLProperty ( " ./capability/interface " )
2013-03-17 17:06:52 -04:00
2019-06-05 15:29:10 -04:00
# type='pci' options
2013-09-22 18:13:24 -04:00
domain = XMLProperty ( " ./capability/domain " )
bus = XMLProperty ( " ./capability/bus " )
slot = XMLProperty ( " ./capability/slot " )
function = XMLProperty ( " ./capability/function " )
2019-06-09 15:29:44 -04:00
product_name = XMLProperty ( " ./capability/product " )
vendor_name = XMLProperty ( " ./capability/vendor " )
2019-06-05 15:29:10 -04:00
_capability_type = XMLProperty ( " ./capability/capability/@type " )
2013-03-17 17:06:52 -04:00
2019-06-05 15:39:09 -04:00
# type='usb' options
2013-09-22 18:13:24 -04:00
device = XMLProperty ( " ./capability/device " )
product_id = XMLProperty ( " ./capability/product/@id " )
vendor_id = XMLProperty ( " ./capability/vendor/@id " )
2013-03-17 17:06:52 -04:00
2019-06-05 15:46:26 -04:00
# type='scsi' options
host = XMLProperty ( " ./capability/host " )
target = XMLProperty ( " ./capability/target " )
lun = XMLProperty ( " ./capability/lun " )
2019-06-05 16:00:25 -04:00
# type='storage' options
2013-09-22 18:13:24 -04:00
block = XMLProperty ( " ./capability/block " )
drive_type = XMLProperty ( " ./capability/drive_type " )
media_label = XMLProperty (
" ./capability/capability[@type= ' removable ' ]/media_label " )
2019-06-05 16:00:25 -04:00
media_available = XMLProperty (
2013-09-22 18:13:24 -04:00
" ./capability/capability[@type= ' removable ' ]/media_available " ,
is_int = True )
2013-03-17 17:06:52 -04:00
2019-06-05 16:13:44 -04:00
# type='drm' options
2019-06-09 15:29:44 -04:00
drm_type = XMLProperty ( " ./capability/type " )
2019-06-05 16:13:44 -04:00
devnodes = XMLChildProperty ( DevNode )
2013-04-13 14:34:52 -04:00
2019-06-05 16:13:44 -04:00
def get_devnode ( self , parent = " by-path " ) :
for d in self . devnodes :
paths = d . path . split ( os . sep )
if len ( paths ) > 2 and paths [ - 2 ] == parent :
return d
if len ( self . devnodes ) > 0 :
return self . devnodes [ 0 ]
2017-02-21 17:00:54 +04:00
2021-04-14 17:18:55 +02:00
# type='mdev' options
type_id = XMLProperty ( " ./capability/type/@id " )
2021-10-26 14:18:40 -05:00
uuid = XMLProperty ( " ./capability/uuid " )