Merge "neutron: Update the port with a MAC address for PFs"
This commit is contained in:
@@ -37,8 +37,10 @@ from nova.network import base_api
|
||||
from nova.network import model as network_model
|
||||
from nova.network.neutronv2 import constants
|
||||
from nova import objects
|
||||
from nova.objects import fields as obj_fields
|
||||
from nova.pci import manager as pci_manager
|
||||
from nova.pci import request as pci_request
|
||||
from nova.pci import utils as pci_utils
|
||||
from nova.pci import whitelist as pci_whitelist
|
||||
|
||||
neutron_opts = [
|
||||
@@ -643,6 +645,8 @@ class API(base_api.NetworkAPI):
|
||||
context, instance, request.pci_request_id, port_req_body,
|
||||
network=network, neutron=neutron,
|
||||
bind_host_id=bind_host_id)
|
||||
self._populate_mac_address(instance, request.pci_request_id,
|
||||
port_req_body)
|
||||
if request.port_id:
|
||||
port = ports[request.port_id]
|
||||
port_client.update_port(port['id'], port_req_body)
|
||||
@@ -716,6 +720,38 @@ class API(base_api.NetworkAPI):
|
||||
}
|
||||
port_req_body['port']['binding:profile'] = profile
|
||||
|
||||
@staticmethod
|
||||
def _populate_mac_address(instance, pci_request_id, port_req_body):
|
||||
"""Add the updated MAC address value to the update_port request body.
|
||||
|
||||
Currently this is done only for PF passthrough.
|
||||
"""
|
||||
if pci_request_id is not None:
|
||||
pci_devs = pci_manager.get_instance_pci_devs(
|
||||
instance, pci_request_id)
|
||||
if len(pci_devs) != 1:
|
||||
# NOTE(ndipanov): We shouldn't ever get here since
|
||||
# InstancePCIRequest instances built from network requests
|
||||
# only ever index a single device, which needs to be
|
||||
# successfully claimed for this to be called as part of
|
||||
# allocate_networks method
|
||||
LOG.error(_LE("PCI request %s does not have a "
|
||||
"unique device associated with it. Unable to "
|
||||
"determine MAC address"),
|
||||
pci_request, instance=instance)
|
||||
return
|
||||
pci_dev = pci_devs[0]
|
||||
if pci_dev.dev_type == obj_fields.PciDeviceType.SRIOV_PF:
|
||||
try:
|
||||
mac = pci_utils.get_mac_by_pci_address(pci_dev.address)
|
||||
except exception.PciDeviceNotFoundById as e:
|
||||
LOG.error(
|
||||
_LE("Could not determine MAC address for %(addr)s, "
|
||||
"error: %(e)s"),
|
||||
{"addr": pci_dev.address, "e": e}, instance=instance)
|
||||
else:
|
||||
port_req_body['port']['mac_address'] = mac
|
||||
|
||||
def _populate_neutron_extension_values(self, context, instance,
|
||||
pci_request_id, port_req_body,
|
||||
network=None, neutron=None,
|
||||
|
||||
@@ -41,6 +41,7 @@ from nova.network.neutronv2 import api as neutronapi
|
||||
from nova.network.neutronv2 import constants
|
||||
from nova import objects
|
||||
from nova.pci import manager as pci_manager
|
||||
from nova.pci import utils as pci_utils
|
||||
from nova.pci import whitelist as pci_whitelist
|
||||
from nova import policy
|
||||
from nova import test
|
||||
@@ -3907,6 +3908,74 @@ class TestNeutronv2Portbinding(TestNeutronv2Base):
|
||||
|
||||
self.assertEqual(profile, port_req_body['port']['binding:profile'])
|
||||
|
||||
def _populate_mac_address_fakes(self):
|
||||
instance = fake_instance.fake_instance_obj(self.context)
|
||||
pci_dev = {'vendor_id': '1377',
|
||||
'product_id': '0047',
|
||||
'address': '0000:0a:00.1',
|
||||
'dev_type': 'type-PF'}
|
||||
pf = objects.PciDevice()
|
||||
vf = objects.PciDevice()
|
||||
pf.update_device(pci_dev)
|
||||
|
||||
pci_dev['dev_type'] = 'type-VF'
|
||||
vf.update_device(pci_dev)
|
||||
return instance, pf, vf
|
||||
|
||||
@mock.patch.object(pci_manager, 'get_instance_pci_devs')
|
||||
@mock.patch.object(pci_utils, 'get_mac_by_pci_address')
|
||||
def test_populate_mac_address_pf(self, mock_get_mac_by_pci_address,
|
||||
mock_get_instance_pci_devs):
|
||||
api = neutronapi.API()
|
||||
instance, pf, vf = self._populate_mac_address_fakes()
|
||||
|
||||
port_req_body = {'port': {}}
|
||||
mock_get_instance_pci_devs.return_value = [pf]
|
||||
mock_get_mac_by_pci_address.return_value = 'fake-mac-address'
|
||||
expected_port_req_body = {'port': {'mac_address': 'fake-mac-address'}}
|
||||
req = port_req_body.copy()
|
||||
api._populate_mac_address(instance, 0, req)
|
||||
self.assertEqual(expected_port_req_body, req)
|
||||
|
||||
@mock.patch.object(pci_manager, 'get_instance_pci_devs')
|
||||
@mock.patch.object(pci_utils, 'get_mac_by_pci_address')
|
||||
def test_populate_mac_address_vf(self, mock_get_mac_by_pci_address,
|
||||
mock_get_instance_pci_devs):
|
||||
api = neutronapi.API()
|
||||
instance, pf, vf = self._populate_mac_address_fakes()
|
||||
|
||||
port_req_body = {'port': {}}
|
||||
mock_get_instance_pci_devs.return_value = [vf]
|
||||
req = port_req_body.copy()
|
||||
api._populate_mac_address(instance, 42, port_req_body)
|
||||
self.assertEqual(port_req_body, req)
|
||||
|
||||
@mock.patch.object(pci_manager, 'get_instance_pci_devs')
|
||||
@mock.patch.object(pci_utils, 'get_mac_by_pci_address')
|
||||
def test_populate_mac_address_vf_fail(self, mock_get_mac_by_pci_address,
|
||||
mock_get_instance_pci_devs):
|
||||
api = neutronapi.API()
|
||||
instance, pf, vf = self._populate_mac_address_fakes()
|
||||
|
||||
port_req_body = {'port': {}}
|
||||
mock_get_instance_pci_devs.return_value = [vf]
|
||||
mock_get_mac_by_pci_address.side_effect = (
|
||||
exception.PciDeviceNotFoundById)
|
||||
req = port_req_body.copy()
|
||||
api._populate_mac_address(instance, 42, port_req_body)
|
||||
self.assertEqual(port_req_body, req)
|
||||
|
||||
@mock.patch.object(pci_manager, 'get_instance_pci_devs')
|
||||
def test_populate_mac_address_no_device(self, mock_get_instance_pci_devs):
|
||||
api = neutronapi.API()
|
||||
instance, pf, vf = self._populate_mac_address_fakes()
|
||||
|
||||
port_req_body = {'port': {}}
|
||||
mock_get_instance_pci_devs.return_value = []
|
||||
req = port_req_body.copy()
|
||||
api._populate_mac_address(instance, 42, port_req_body)
|
||||
self.assertEqual(port_req_body, req)
|
||||
|
||||
def _test_update_port_binding_false(self, func_name, *args):
|
||||
api = neutronapi.API()
|
||||
func = getattr(api, func_name)
|
||||
|
||||
Reference in New Issue
Block a user