libvirt: report pci Type-PF type even when VFs are disabled
libvirt < 1.3 reports virt_functions capability only when pf has VFs enabled. This workaround patch updates the is_physical_function function to read the sriov_totalvfs if exists and check it is greater than 0. The sriov_totalvfs is the number for the maximum possible VF for this PF. _get_pcidev_info in libvirt driver is updated to get the correct pci device type using this function. Closes-Bug: #1499204 Change-Id: I8990c36fb1d6c66093a465930ff3f0948dd64986
This commit is contained in:
parent
996c2f6f05
commit
2ba4644f91
@ -67,7 +67,8 @@ class PciAddress(object):
|
||||
def _check_physical_function(self):
|
||||
if ANY in (self.domain, self.bus, self.slot, self.func):
|
||||
return
|
||||
self.is_physical_function = utils.is_physical_function(self)
|
||||
self.is_physical_function = utils.is_physical_function(
|
||||
self.domain, self.bus, self.slot, self.func)
|
||||
|
||||
def _init_address_fields(self, pci_addr):
|
||||
if self.is_physical_function:
|
||||
|
@ -23,7 +23,6 @@ from oslo_log import log as logging
|
||||
import six
|
||||
|
||||
from nova import exception
|
||||
from nova.i18n import _LE
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
@ -33,7 +32,7 @@ _PCI_ADDRESS_PATTERN = ("^(hex{4}):(hex{2}):(hex{2}).(oct{1})$".
|
||||
replace("oct", "[0-7]"))
|
||||
_PCI_ADDRESS_REGEX = re.compile(_PCI_ADDRESS_PATTERN)
|
||||
|
||||
_VIRTFN_RE = re.compile("virtfn\d+")
|
||||
_SRIOV_TOTALVFS = "sriov_totalvfs"
|
||||
|
||||
|
||||
def pci_device_prop_match(pci_dev, specs):
|
||||
@ -74,33 +73,32 @@ def get_function_by_ifname(ifname):
|
||||
"""Given the device name, returns the PCI address of a an device
|
||||
and returns True if the address in a physical function.
|
||||
"""
|
||||
try:
|
||||
dev_path = "/sys/class/net/%s/device" % ifname
|
||||
dev_info = os.listdir(dev_path)
|
||||
for dev_file in dev_info:
|
||||
if _VIRTFN_RE.match(dev_file):
|
||||
return os.readlink(dev_path).strip("./"), True
|
||||
else:
|
||||
dev_path = "/sys/class/net/%s/device" % ifname
|
||||
sriov_totalvfs = 0
|
||||
if os.path.isdir(dev_path):
|
||||
try:
|
||||
# sriov_totalvfs contains the maximum possible VFs for this PF
|
||||
with open(dev_path + _SRIOV_TOTALVFS) as fd:
|
||||
sriov_totalvfs = int(fd.read())
|
||||
return (os.readlink(dev_path).strip("./"),
|
||||
sriov_totalvfs > 0)
|
||||
except (IOError, ValueError):
|
||||
return os.readlink(dev_path).strip("./"), False
|
||||
except Exception:
|
||||
LOG.error(_LE("PCI device %s not found") % ifname)
|
||||
return None, False
|
||||
return None, False
|
||||
|
||||
|
||||
def is_physical_function(pci_addr):
|
||||
def is_physical_function(domain, bus, slot, function):
|
||||
dev_path = "/sys/bus/pci/devices/%(d)s:%(b)s:%(s)s.%(f)s/" % {
|
||||
"d": pci_addr.domain, "b": pci_addr.bus,
|
||||
"s": pci_addr.slot, "f": pci_addr.func}
|
||||
try:
|
||||
dev_info = os.listdir(dev_path)
|
||||
for dev_file in dev_info:
|
||||
if _VIRTFN_RE.match(dev_file):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
except Exception:
|
||||
LOG.error(_LE("PCI device %s not found") % dev_path)
|
||||
return False
|
||||
"d": domain, "b": bus, "s": slot, "f": function}
|
||||
if os.path.isdir(dev_path):
|
||||
sriov_totalvfs = 0
|
||||
try:
|
||||
with open(dev_path + _SRIOV_TOTALVFS) as fd:
|
||||
sriov_totalvfs = int(fd.read())
|
||||
return sriov_totalvfs > 0
|
||||
except (IOError, ValueError):
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def get_ifname_by_pci_address(pci_addr, pf_interface=False):
|
||||
|
@ -18,6 +18,7 @@ import glob
|
||||
import os
|
||||
|
||||
import mock
|
||||
from six.moves import builtins
|
||||
|
||||
from nova import exception
|
||||
from nova.pci import utils
|
||||
@ -68,27 +69,28 @@ class PciDeviceAddressParserTestCase(test.NoDBTestCase):
|
||||
|
||||
class GetFunctionByIfnameTestCase(test.NoDBTestCase):
|
||||
|
||||
@mock.patch('os.path.isdir', return_value=True)
|
||||
@mock.patch.object(os, 'readlink')
|
||||
@mock.patch.object(os, 'listdir')
|
||||
def test_virtual_function(self, mock_listdir, mock_readlink):
|
||||
mock_listdir.return_value = ['foo', 'bar']
|
||||
def test_virtual_function(self, mock_readlink, *args):
|
||||
mock_readlink.return_value = '../../../0000.00.00.1'
|
||||
address, physical_function = utils.get_function_by_ifname('eth0')
|
||||
self.assertEqual(address, '0000.00.00.1')
|
||||
self.assertFalse(physical_function)
|
||||
with mock.patch.object(
|
||||
builtins, 'open', side_effect=IOError()):
|
||||
address, physical_function = utils.get_function_by_ifname('eth0')
|
||||
self.assertEqual(address, '0000.00.00.1')
|
||||
self.assertFalse(physical_function)
|
||||
|
||||
@mock.patch('os.path.isdir', return_value=True)
|
||||
@mock.patch.object(os, 'readlink')
|
||||
@mock.patch.object(os, 'listdir')
|
||||
def test_physical_function(self, mock_listdir, mock_readlink):
|
||||
mock_listdir.return_value = ['foo', 'virtfn1', 'bar']
|
||||
def test_physical_function(self, mock_readlink, *args):
|
||||
mock_readlink.return_value = '../../../0000:00:00.1'
|
||||
address, physical_function = utils.get_function_by_ifname('eth0')
|
||||
self.assertEqual(address, '0000:00:00.1')
|
||||
self.assertTrue(physical_function)
|
||||
with mock.patch.object(
|
||||
builtins, 'open', mock.mock_open(read_data='4')):
|
||||
address, physical_function = utils.get_function_by_ifname('eth0')
|
||||
self.assertEqual(address, '0000:00:00.1')
|
||||
self.assertTrue(physical_function)
|
||||
|
||||
@mock.patch.object(os, 'listdir')
|
||||
def test_exception(self, mock_listdir):
|
||||
mock_listdir.side_effect = OSError('No such file or directory')
|
||||
@mock.patch('os.path.isdir', return_value=False)
|
||||
def test_exception(self, *args):
|
||||
address, physical_function = utils.get_function_by_ifname('lo')
|
||||
self.assertIsNone(address)
|
||||
self.assertFalse(physical_function)
|
||||
@ -96,31 +98,25 @@ class GetFunctionByIfnameTestCase(test.NoDBTestCase):
|
||||
|
||||
class IsPhysicalFunctionTestCase(test.NoDBTestCase):
|
||||
|
||||
class FakePciAddress(object):
|
||||
def __init__(self):
|
||||
self.domain = 0
|
||||
self.bus = 0
|
||||
self.slot = 0
|
||||
self.func = 0
|
||||
|
||||
def setUp(self):
|
||||
super(IsPhysicalFunctionTestCase, self).setUp()
|
||||
self.pci_address = self.FakePciAddress()
|
||||
self.pci_args = utils.get_pci_address_fields('0000:00:00.1')
|
||||
|
||||
@mock.patch.object(os, 'listdir')
|
||||
def test_virtual_function(self, mock_listdir):
|
||||
mock_listdir.return_value = ['foo', 'bar']
|
||||
self.assertFalse(utils.is_physical_function(self.pci_address))
|
||||
@mock.patch('os.path.isdir', return_value=True)
|
||||
def test_virtual_function(self, *args):
|
||||
with mock.patch.object(
|
||||
builtins, 'open', side_effect=IOError()):
|
||||
self.assertFalse(utils.is_physical_function(*self.pci_args))
|
||||
|
||||
@mock.patch.object(os, 'listdir')
|
||||
def test_physical_function(self, mock_listdir):
|
||||
mock_listdir.return_value = ['foo', 'virtfn1', 'bar']
|
||||
self.assertTrue(utils.is_physical_function(self.pci_address))
|
||||
@mock.patch('os.path.isdir', return_value=True)
|
||||
def test_physical_function(self, *args):
|
||||
with mock.patch.object(
|
||||
builtins, 'open', mock.mock_open(read_data='4')):
|
||||
self.assertTrue(utils.is_physical_function(*self.pci_args))
|
||||
|
||||
@mock.patch.object(os, 'listdir')
|
||||
def test_exception(self, mock_listdir):
|
||||
mock_listdir.side_effect = OSError('No such file or directory')
|
||||
self.assertFalse(utils.is_physical_function(self.pci_address))
|
||||
@mock.patch('os.path.isdir', return_value=False)
|
||||
def test_exception(self, *args):
|
||||
self.assertFalse(utils.is_physical_function(*self.pci_args))
|
||||
|
||||
|
||||
class GetIfnameByPciAddressTestCase(test.NoDBTestCase):
|
||||
|
@ -65,6 +65,7 @@ from nova.network import model as network_model
|
||||
from nova import objects
|
||||
from nova.objects import fields
|
||||
from nova.pci import manager as pci_manager
|
||||
from nova.pci import utils as pci_utils
|
||||
from nova import test
|
||||
from nova.tests.unit import fake_block_device
|
||||
from nova.tests.unit import fake_instance
|
||||
@ -180,7 +181,94 @@ _fake_NodeDevXml = \
|
||||
<capability type='virt_functions'>
|
||||
</capability>
|
||||
</capability>
|
||||
</device>"""}
|
||||
</device>""",
|
||||
"pci_0000_04_00_1": """
|
||||
<device>
|
||||
<name>pci_0000_04_00_1</name>
|
||||
<path>/sys/devices/pci0000:00/0000:00:02.0/0000:04:00.1</path>
|
||||
<parent>pci_0000_00_02_0</parent>
|
||||
<driver>
|
||||
<name>mlx5_core</name>
|
||||
</driver>
|
||||
<capability type='pci'>
|
||||
<domain>0</domain>
|
||||
<bus>4</bus>
|
||||
<slot>0</slot>
|
||||
<function>1</function>
|
||||
<product id='0x1013'>MT27700 Family [ConnectX-4]</product>
|
||||
<vendor id='0x15b3'>Mellanox Technologies</vendor>
|
||||
<iommuGroup number='15'>
|
||||
<address domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
|
||||
<address domain='0x0000' bus='0x03' slot='0x00' function='0x1'/>
|
||||
</iommuGroup>
|
||||
<numa node='0'/>
|
||||
<pci-express>
|
||||
<link validity='cap' port='0' speed='8' width='16'/>
|
||||
<link validity='sta' speed='8' width='16'/>
|
||||
</pci-express>
|
||||
</capability>
|
||||
</device>""",
|
||||
# libvirt >= 1.3.0 nodedev-dumpxml
|
||||
"pci_0000_03_00_0": """
|
||||
<device>
|
||||
<name>pci_0000_03_00_0</name>
|
||||
<path>/sys/devices/pci0000:00/0000:00:02.0/0000:03:00.0</path>
|
||||
<parent>pci_0000_00_02_0</parent>
|
||||
<driver>
|
||||
<name>mlx5_core</name>
|
||||
</driver>
|
||||
<capability type='pci'>
|
||||
<domain>0</domain>
|
||||
<bus>3</bus>
|
||||
<slot>0</slot>
|
||||
<function>0</function>
|
||||
<product id='0x1013'>MT27700 Family [ConnectX-4]</product>
|
||||
<vendor id='0x15b3'>Mellanox Technologies</vendor>
|
||||
<capability type='virt_functions' maxCount='16'>
|
||||
<address domain='0x0000' bus='0x03' slot='0x00' function='0x2'/>
|
||||
<address domain='0x0000' bus='0x03' slot='0x00' function='0x3'/>
|
||||
<address domain='0x0000' bus='0x03' slot='0x00' function='0x4'/>
|
||||
<address domain='0x0000' bus='0x03' slot='0x00' function='0x5'/>
|
||||
</capability>
|
||||
<iommuGroup number='15'>
|
||||
<address domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
|
||||
<address domain='0x0000' bus='0x03' slot='0x00' function='0x1'/>
|
||||
</iommuGroup>
|
||||
<numa node='0'/>
|
||||
<pci-express>
|
||||
<link validity='cap' port='0' speed='8' width='16'/>
|
||||
<link validity='sta' speed='8' width='16'/>
|
||||
</pci-express>
|
||||
</capability>
|
||||
</device>""",
|
||||
"pci_0000_03_00_1": """
|
||||
<device>
|
||||
<name>pci_0000_03_00_1</name>
|
||||
<path>/sys/devices/pci0000:00/0000:00:02.0/0000:03:00.1</path>
|
||||
<parent>pci_0000_00_02_0</parent>
|
||||
<driver>
|
||||
<name>mlx5_core</name>
|
||||
</driver>
|
||||
<capability type='pci'>
|
||||
<domain>0</domain>
|
||||
<bus>3</bus>
|
||||
<slot>0</slot>
|
||||
<function>1</function>
|
||||
<product id='0x1013'>MT27700 Family [ConnectX-4]</product>
|
||||
<vendor id='0x15b3'>Mellanox Technologies</vendor>
|
||||
<capability type='virt_functions' maxCount='16'/>
|
||||
<iommuGroup number='15'>
|
||||
<address domain='0x0000' bus='0x03' slot='0x00' function='0x0'/>
|
||||
<address domain='0x0000' bus='0x03' slot='0x00' function='0x1'/>
|
||||
</iommuGroup>
|
||||
<numa node='0'/>
|
||||
<pci-express>
|
||||
<link validity='cap' port='0' speed='8' width='16'/>
|
||||
<link validity='sta' speed='8' width='16'/>
|
||||
</pci-express>
|
||||
</capability>
|
||||
</device>""",
|
||||
}
|
||||
|
||||
_fake_cpu_info = {
|
||||
"arch": "test_arch",
|
||||
@ -9770,43 +9858,108 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
||||
host.Host.device_lookup_by_name = fake_nodeDeviceLookupByName
|
||||
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
actualvf = drvr._get_pcidev_info("pci_0000_04_00_3")
|
||||
expect_vf = {
|
||||
"dev_id": "pci_0000_04_00_3",
|
||||
"address": "0000:04:00.3",
|
||||
"product_id": '1521',
|
||||
"numa_node": None,
|
||||
"vendor_id": '8086',
|
||||
"label": 'label_8086_1521',
|
||||
"dev_type": fields.PciDeviceType.SRIOV_PF,
|
||||
}
|
||||
with mock.patch.object(
|
||||
fakelibvirt.Connection, 'getLibVersion') as mock_lib_version:
|
||||
mock_lib_version.return_value = (
|
||||
versionutils.convert_version_to_int(
|
||||
libvirt_driver.MIN_LIBVIRT_PF_WITH_NO_VFS_CAP_VERSION) - 1)
|
||||
|
||||
self.assertEqual(expect_vf, actualvf)
|
||||
actualvf = drvr._get_pcidev_info("pci_0000_04_10_7")
|
||||
expect_vf = {
|
||||
"dev_id": "pci_0000_04_10_7",
|
||||
"address": "0000:04:10.7",
|
||||
"product_id": '1520',
|
||||
"numa_node": None,
|
||||
"vendor_id": '8086',
|
||||
"label": 'label_8086_1520',
|
||||
"dev_type": fields.PciDeviceType.SRIOV_VF,
|
||||
"phys_function": '0000:04:00.3',
|
||||
}
|
||||
self.assertEqual(expect_vf, actualvf)
|
||||
actualvf = drvr._get_pcidev_info("pci_0000_04_11_7")
|
||||
expect_vf = {
|
||||
"dev_id": "pci_0000_04_11_7",
|
||||
"address": "0000:04:11.7",
|
||||
"product_id": '1520',
|
||||
"vendor_id": '8086',
|
||||
"numa_node": 0,
|
||||
"label": 'label_8086_1520',
|
||||
"dev_type": fields.PciDeviceType.SRIOV_VF,
|
||||
"phys_function": '0000:04:00.3',
|
||||
}
|
||||
actualvf = drvr._get_pcidev_info("pci_0000_04_00_3")
|
||||
expect_vf = {
|
||||
"dev_id": "pci_0000_04_00_3",
|
||||
"address": "0000:04:00.3",
|
||||
"product_id": '1521',
|
||||
"numa_node": None,
|
||||
"vendor_id": '8086',
|
||||
"label": 'label_8086_1521',
|
||||
"dev_type": fields.PciDeviceType.SRIOV_PF,
|
||||
}
|
||||
|
||||
self.assertEqual(expect_vf, actualvf)
|
||||
self.assertEqual(expect_vf, actualvf)
|
||||
actualvf = drvr._get_pcidev_info("pci_0000_04_10_7")
|
||||
expect_vf = {
|
||||
"dev_id": "pci_0000_04_10_7",
|
||||
"address": "0000:04:10.7",
|
||||
"product_id": '1520',
|
||||
"numa_node": None,
|
||||
"vendor_id": '8086',
|
||||
"label": 'label_8086_1520',
|
||||
"dev_type": fields.PciDeviceType.SRIOV_VF,
|
||||
"phys_function": '0000:04:00.3',
|
||||
}
|
||||
self.assertEqual(expect_vf, actualvf)
|
||||
|
||||
actualvf = drvr._get_pcidev_info("pci_0000_04_11_7")
|
||||
expect_vf = {
|
||||
"dev_id": "pci_0000_04_11_7",
|
||||
"address": "0000:04:11.7",
|
||||
"product_id": '1520',
|
||||
"vendor_id": '8086',
|
||||
"numa_node": 0,
|
||||
"label": 'label_8086_1520',
|
||||
"dev_type": fields.PciDeviceType.SRIOV_VF,
|
||||
"phys_function": '0000:04:00.3',
|
||||
}
|
||||
|
||||
self.assertEqual(expect_vf, actualvf)
|
||||
|
||||
with mock.patch.object(
|
||||
pci_utils, 'is_physical_function', return_value=True):
|
||||
actualvf = drvr._get_pcidev_info("pci_0000_04_00_1")
|
||||
expect_vf = {
|
||||
"dev_id": "pci_0000_04_00_1",
|
||||
"address": "0000:04:00.1",
|
||||
"product_id": '1013',
|
||||
"numa_node": 0,
|
||||
"vendor_id": '15b3',
|
||||
"label": 'label_15b3_1013',
|
||||
"dev_type": fields.PciDeviceType.SRIOV_PF,
|
||||
}
|
||||
self.assertEqual(expect_vf, actualvf)
|
||||
|
||||
with mock.patch.object(
|
||||
pci_utils, 'is_physical_function', return_value=False):
|
||||
actualvf = drvr._get_pcidev_info("pci_0000_04_00_1")
|
||||
expect_vf = {
|
||||
"dev_id": "pci_0000_04_00_1",
|
||||
"address": "0000:04:00.1",
|
||||
"product_id": '1013',
|
||||
"numa_node": 0,
|
||||
"vendor_id": '15b3',
|
||||
"label": 'label_15b3_1013',
|
||||
"dev_type": fields.PciDeviceType.STANDARD,
|
||||
}
|
||||
self.assertEqual(expect_vf, actualvf)
|
||||
|
||||
with mock.patch.object(
|
||||
fakelibvirt.Connection, 'getLibVersion') as mock_lib_version:
|
||||
mock_lib_version.return_value = (
|
||||
versionutils.convert_version_to_int(
|
||||
libvirt_driver.MIN_LIBVIRT_PF_WITH_NO_VFS_CAP_VERSION))
|
||||
actualvf = drvr._get_pcidev_info("pci_0000_03_00_0")
|
||||
expect_vf = {
|
||||
"dev_id": "pci_0000_03_00_0",
|
||||
"address": "0000:03:00.0",
|
||||
"product_id": '1013',
|
||||
"numa_node": 0,
|
||||
"vendor_id": '15b3',
|
||||
"label": 'label_15b3_1013',
|
||||
"dev_type": fields.PciDeviceType.SRIOV_PF,
|
||||
}
|
||||
self.assertEqual(expect_vf, actualvf)
|
||||
|
||||
actualvf = drvr._get_pcidev_info("pci_0000_03_00_1")
|
||||
expect_vf = {
|
||||
"dev_id": "pci_0000_03_00_1",
|
||||
"address": "0000:03:00.1",
|
||||
"product_id": '1013',
|
||||
"numa_node": 0,
|
||||
"vendor_id": '15b3',
|
||||
"label": 'label_15b3_1013',
|
||||
"dev_type": fields.PciDeviceType.SRIOV_PF,
|
||||
}
|
||||
|
||||
self.assertEqual(expect_vf, actualvf)
|
||||
|
||||
def test_list_devices_not_supported(self):
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
|
@ -420,6 +420,12 @@ MIN_LIBVIRT_SET_ADMIN_PASSWD = (1, 2, 16)
|
||||
MIN_LIBVIRT_KVM_S390_VERSION = (1, 2, 13)
|
||||
MIN_QEMU_S390_VERSION = (2, 3, 0)
|
||||
|
||||
# libvirt < 1.3 reported virt_functions capability
|
||||
# only when VFs are enabled.
|
||||
# libvirt 1.3 fix f391889f4e942e22b9ef8ecca492de05106ce41e
|
||||
MIN_LIBVIRT_PF_WITH_NO_VFS_CAP_VERSION = (1, 3, 0)
|
||||
|
||||
|
||||
# Names of the types that do not get compressed during migration
|
||||
NO_COMPRESSION_TYPES = ('qcow2',)
|
||||
|
||||
@ -4805,7 +4811,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
def _get_pcidev_info(self, devname):
|
||||
"""Returns a dict of PCI device."""
|
||||
|
||||
def _get_device_type(cfgdev):
|
||||
def _get_device_type(cfgdev, pci_address):
|
||||
"""Get a PCI device's device type.
|
||||
|
||||
An assignable PCI device can be a normal PCI device,
|
||||
@ -4813,26 +4819,35 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
Function (VF). Only normal PCI devices or SR-IOV VFs
|
||||
are assignable, while SR-IOV PFs are always owned by
|
||||
hypervisor.
|
||||
|
||||
Please notice that a PCI device with SR-IOV
|
||||
capability but not enabled is reported as normal PCI device.
|
||||
"""
|
||||
for fun_cap in cfgdev.pci_capability.fun_capability:
|
||||
if len(fun_cap.device_addrs) != 0:
|
||||
if fun_cap.type == 'virt_functions':
|
||||
return {
|
||||
'dev_type': fields.PciDeviceType.SRIOV_PF,
|
||||
}
|
||||
if fun_cap.type == 'phys_function':
|
||||
phys_address = "%04x:%02x:%02x.%01x" % (
|
||||
fun_cap.device_addrs[0][0],
|
||||
fun_cap.device_addrs[0][1],
|
||||
fun_cap.device_addrs[0][2],
|
||||
fun_cap.device_addrs[0][3])
|
||||
return {
|
||||
'dev_type': fields.PciDeviceType.SRIOV_VF,
|
||||
'phys_function': phys_address,
|
||||
}
|
||||
if fun_cap.type == 'virt_functions':
|
||||
return {
|
||||
'dev_type': fields.PciDeviceType.SRIOV_PF,
|
||||
}
|
||||
if (fun_cap.type == 'phys_function' and
|
||||
len(fun_cap.device_addrs) != 0):
|
||||
phys_address = "%04x:%02x:%02x.%01x" % (
|
||||
fun_cap.device_addrs[0][0],
|
||||
fun_cap.device_addrs[0][1],
|
||||
fun_cap.device_addrs[0][2],
|
||||
fun_cap.device_addrs[0][3])
|
||||
return {
|
||||
'dev_type': fields.PciDeviceType.SRIOV_VF,
|
||||
'phys_function': phys_address,
|
||||
}
|
||||
|
||||
# Note(moshele): libvirt < 1.3 reported virt_functions capability
|
||||
# only when VFs are enabled. The check below is a workaround
|
||||
# to get the correct report regardless of whether or not any
|
||||
# VFs are enabled for the device.
|
||||
if not self._host.has_min_version(
|
||||
MIN_LIBVIRT_PF_WITH_NO_VFS_CAP_VERSION):
|
||||
is_physical_function = pci_utils.is_physical_function(
|
||||
*pci_utils.get_pci_address_fields(pci_address))
|
||||
if is_physical_function:
|
||||
return {'dev_type': fields.PciDeviceType.SRIOV_PF}
|
||||
|
||||
return {'dev_type': fields.PciDeviceType.STANDARD}
|
||||
|
||||
virtdev = self._host.device_lookup_by_name(devname)
|
||||
@ -4857,7 +4872,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
|
||||
# requirement by DataBase Model
|
||||
device['label'] = 'label_%(vendor_id)s_%(product_id)s' % device
|
||||
device.update(_get_device_type(cfgdev))
|
||||
device.update(_get_device_type(cfgdev, address))
|
||||
return device
|
||||
|
||||
def _get_pci_passthrough_devices(self):
|
||||
|
Loading…
Reference in New Issue
Block a user