Merge "Add get_instance_pci_request_from_vif"
This commit is contained in:
commit
51e3787bf8
nova
@ -1804,6 +1804,11 @@ class PciConfigInvalidWhitelist(Invalid):
|
||||
msg_fmt = _("Invalid PCI devices Whitelist config: %(reason)s")
|
||||
|
||||
|
||||
class PciRequestFromVIFNotFound(NotFound):
|
||||
msg_fmt = _("Failed to locate PCI request associated with the given VIF "
|
||||
"PCI address: %(pci_slot)s on compute node: %(node_id)s")
|
||||
|
||||
|
||||
# Cannot be templated, msg needs to be constructed when raised.
|
||||
class InternalError(NovaException):
|
||||
"""Generic hypervisor errors.
|
||||
|
@ -39,6 +39,7 @@
|
||||
"""
|
||||
|
||||
import jsonschema
|
||||
from oslo_log import log as logging
|
||||
from oslo_serialization import jsonutils
|
||||
import six
|
||||
|
||||
@ -50,6 +51,7 @@ from nova import objects
|
||||
from nova.objects import fields as obj_fields
|
||||
from nova.pci import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
PCI_NET_TAG = 'physical_network'
|
||||
PCI_TRUSTED_TAG = 'trusted'
|
||||
PCI_DEVICE_TYPE_TAG = 'dev_type'
|
||||
@ -171,6 +173,60 @@ def _translate_alias_to_requests(alias_spec):
|
||||
return pci_requests
|
||||
|
||||
|
||||
def get_instance_pci_request_from_vif(context, instance, vif):
|
||||
"""Given an Instance, return the PCI request associated
|
||||
to the PCI device related to the given VIF (if any) on the
|
||||
compute node the instance is currently running.
|
||||
|
||||
In this method we assume a VIF is associated with a PCI device
|
||||
if 'pci_slot' attribute exists in the vif 'profile' dict.
|
||||
|
||||
:param context: security context
|
||||
:param instance: instance object
|
||||
:param vif: network VIF model object
|
||||
:raises: raises PciRequestFromVIFNotFound if a pci device is requested
|
||||
but not found on current host
|
||||
:return: instance's PCIRequest object associated with the given VIF
|
||||
or None if no PCI device is requested
|
||||
"""
|
||||
|
||||
# Get PCI device address for VIF if exists
|
||||
vif_pci_dev_addr = vif['profile'].get('pci_slot') \
|
||||
if vif['profile'] else None
|
||||
|
||||
if not vif_pci_dev_addr:
|
||||
return None
|
||||
|
||||
try:
|
||||
cn_id = objects.ComputeNode.get_by_host_and_nodename(
|
||||
context,
|
||||
instance.host,
|
||||
instance.node).id
|
||||
except exception.NotFound:
|
||||
LOG.warning("expected to find compute node with host %s "
|
||||
"and node %s when getting instance PCI request "
|
||||
"from VIF", instance.host, instance.node)
|
||||
return None
|
||||
# Find PCIDevice associated with vif_pci_dev_addr on the compute node
|
||||
# the instance is running on.
|
||||
found_pci_dev = None
|
||||
for pci_dev in instance.pci_devices:
|
||||
if (pci_dev.compute_node_id == cn_id and
|
||||
pci_dev.address == vif_pci_dev_addr):
|
||||
found_pci_dev = pci_dev
|
||||
break
|
||||
if not found_pci_dev:
|
||||
return None
|
||||
# Find PCIRequest associated with the given PCIDevice in instance
|
||||
for pci_req in instance.pci_requests.requests:
|
||||
if pci_req.request_id == found_pci_dev.request_id:
|
||||
return pci_req
|
||||
|
||||
raise exception.PciRequestFromVIFNotFound(
|
||||
pci_slot=vif_pci_dev_addr,
|
||||
node_id=cn_id)
|
||||
|
||||
|
||||
def get_pci_requests_from_flavor(flavor):
|
||||
"""Validate and return PCI requests.
|
||||
|
||||
|
@ -15,9 +15,17 @@
|
||||
|
||||
"""Tests for PCI request."""
|
||||
|
||||
import mock
|
||||
|
||||
from oslo_utils.fixture import uuidsentinel
|
||||
|
||||
from nova import context
|
||||
from nova import exception
|
||||
from nova.network import model
|
||||
from nova import objects
|
||||
from nova.pci import request
|
||||
from nova import test
|
||||
from nova.tests.unit.api.openstack import fakes
|
||||
|
||||
|
||||
_fake_alias1 = """{
|
||||
@ -62,7 +70,35 @@ _fake_alias4 = """{
|
||||
}"""
|
||||
|
||||
|
||||
class AliasTestCase(test.NoDBTestCase):
|
||||
class PciRequestTestCase(test.NoDBTestCase):
|
||||
|
||||
@staticmethod
|
||||
def _create_fake_inst_with_pci_devs(pci_req_list, pci_dev_list):
|
||||
"""Create a fake Instance object with the provided InstancePciRequests
|
||||
and PciDevices.
|
||||
|
||||
:param pci_req_list: a list of InstancePCIRequest objects.
|
||||
:param pci_dev_list: a list of PciDevice objects, each element
|
||||
associated (via request_id attribute)with a corresponding
|
||||
element from pci_req_list.
|
||||
:return: A fake Instance object associated with the provided
|
||||
PciRequests and PciDevices.
|
||||
"""
|
||||
|
||||
inst = objects.Instance()
|
||||
inst.uuid = uuidsentinel.instance1
|
||||
inst.pci_requests = objects.InstancePCIRequests(
|
||||
requests=pci_req_list)
|
||||
inst.pci_devices = objects.PciDeviceList(objects=pci_dev_list)
|
||||
inst.host = 'fake-host'
|
||||
inst.node = 'fake-node'
|
||||
return inst
|
||||
|
||||
def setUp(self):
|
||||
super(PciRequestTestCase, self).setUp()
|
||||
self.context = context.RequestContext(fakes.FAKE_USER_ID,
|
||||
fakes.FAKE_PROJECT_ID)
|
||||
self.mock_inst_cn = mock.Mock()
|
||||
|
||||
def test_valid_alias(self):
|
||||
self.flags(alias=[_fake_alias1], group='pci')
|
||||
@ -232,6 +268,99 @@ class AliasTestCase(test.NoDBTestCase):
|
||||
request._translate_alias_to_requests,
|
||||
"QuicAssistX : 3")
|
||||
|
||||
@mock.patch.object(objects.compute_node.ComputeNode,
|
||||
'get_by_host_and_nodename')
|
||||
def test_get_instance_pci_request_from_vif_invalid(
|
||||
self,
|
||||
cn_get_by_host_and_node):
|
||||
# Basically make sure we raise an exception if an instance
|
||||
# has an allocated PCI device without having the its corresponding
|
||||
# PCIRequest object in instance.pci_requests
|
||||
self.mock_inst_cn.id = 1
|
||||
cn_get_by_host_and_node.return_value = self.mock_inst_cn
|
||||
|
||||
# Create a fake instance with PCI request and allocated PCI devices
|
||||
pci_dev1 = objects.PciDevice(request_id=uuidsentinel.pci_req_id1,
|
||||
address='0000:04:00.0',
|
||||
compute_node_id=1)
|
||||
|
||||
pci_req2 = objects.InstancePCIRequest(
|
||||
request_id=uuidsentinel.pci_req_id2)
|
||||
pci_dev2 = objects.PciDevice(request_id=uuidsentinel.pci_req_id2,
|
||||
address='0000:05:00.0',
|
||||
compute_node_id=1)
|
||||
pci_request_list = [pci_req2]
|
||||
pci_device_list = [pci_dev1, pci_dev2]
|
||||
inst = PciRequestTestCase._create_fake_inst_with_pci_devs(
|
||||
pci_request_list,
|
||||
pci_device_list)
|
||||
# Create a VIF with pci_dev1 that has no corresponding PCI request
|
||||
pci_vif = model.VIF(vnic_type=model.VNIC_TYPE_DIRECT,
|
||||
profile={'pci_slot': '0000:04:00.0'})
|
||||
|
||||
self.assertRaises(exception.PciRequestFromVIFNotFound,
|
||||
request.get_instance_pci_request_from_vif,
|
||||
self.context,
|
||||
inst,
|
||||
pci_vif)
|
||||
|
||||
@mock.patch.object(objects.compute_node.ComputeNode,
|
||||
'get_by_host_and_nodename')
|
||||
def test_get_instance_pci_request_from_vif(self, cn_get_by_host_and_node):
|
||||
self.mock_inst_cn.id = 1
|
||||
cn_get_by_host_and_node.return_value = self.mock_inst_cn
|
||||
|
||||
# Create a fake instance with PCI request and allocated PCI devices
|
||||
pci_req1 = objects.InstancePCIRequest(
|
||||
request_id=uuidsentinel.pci_req_id1)
|
||||
pci_dev1 = objects.PciDevice(request_id=uuidsentinel.pci_req_id1,
|
||||
address='0000:04:00.0',
|
||||
compute_node_id = 1)
|
||||
pci_req2 = objects.InstancePCIRequest(
|
||||
request_id=uuidsentinel.pci_req_id2)
|
||||
pci_dev2 = objects.PciDevice(request_id=uuidsentinel.pci_req_id2,
|
||||
address='0000:05:00.0',
|
||||
compute_node_id=1)
|
||||
pci_request_list = [pci_req1, pci_req2]
|
||||
pci_device_list = [pci_dev1, pci_dev2]
|
||||
inst = PciRequestTestCase._create_fake_inst_with_pci_devs(
|
||||
pci_request_list,
|
||||
pci_device_list)
|
||||
|
||||
# Create a vif with normal port and make sure no PCI request returned
|
||||
normal_vif = model.VIF(vnic_type=model.VNIC_TYPE_NORMAL)
|
||||
self.assertIsNone(request.get_instance_pci_request_from_vif(
|
||||
self.context,
|
||||
inst,
|
||||
normal_vif))
|
||||
|
||||
# Create a vif with PCI address under profile, make sure the correct
|
||||
# PCI request is returned
|
||||
pci_vif = model.VIF(vnic_type=model.VNIC_TYPE_DIRECT,
|
||||
profile={'pci_slot': '0000:05:00.0'})
|
||||
self.assertEqual(uuidsentinel.pci_req_id2,
|
||||
request.get_instance_pci_request_from_vif(
|
||||
self.context,
|
||||
inst,
|
||||
pci_vif).request_id)
|
||||
|
||||
# Create a vif with PCI under profile which is not claimed
|
||||
# for the instance, i.e no matching pci device in instance.pci_devices
|
||||
nonclaimed_pci_vif = model.VIF(vnic_type=model.VNIC_TYPE_DIRECT,
|
||||
profile={'pci_slot': '0000:08:00.0'})
|
||||
self.assertIsNone(request.get_instance_pci_request_from_vif(
|
||||
self.context,
|
||||
inst,
|
||||
nonclaimed_pci_vif))
|
||||
|
||||
# "Move" the instance to another compute node, make sure that no
|
||||
# matching PCI request against the new compute.
|
||||
self.mock_inst_cn.id = 2
|
||||
self.assertIsNone(request.get_instance_pci_request_from_vif(
|
||||
self.context,
|
||||
inst,
|
||||
pci_vif))
|
||||
|
||||
def test_get_pci_requests_from_flavor(self):
|
||||
self.flags(alias=[_fake_alias1, _fake_alias3], group='pci')
|
||||
expect_request = [
|
||||
|
Loading…
x
Reference in New Issue
Block a user