Fix bulk port binding

Bulk ports were not binding correctly when they were created.  This is
due to a few inconsistencies between the create_port code and the
create_port_bulk code, mostly a result of the use of the Port object in
the bulk code.

Change-Id: I3bcd3cec12b1b6f6a568cda4bfeb569f636efb98
Closes-Bug: #1835209
(cherry picked from commit d0c172afa6)
This commit is contained in:
Nate Johnston 2019-06-15 10:14:58 -04:00
parent 1229be91d9
commit aa60d6e837
7 changed files with 50 additions and 13 deletions

View File

@ -215,7 +215,7 @@ class DbBasePluginCommon(common_db_mixin.CommonDbMixin):
"admin_state_up": port["admin_state_up"],
"status": port["status"],
"fixed_ips": [{'subnet_id': ip["subnet_id"],
'ip_address': ip["ip_address"]}
'ip_address': str(ip["ip_address"])}
for ip in port["fixed_ips"]],
"device_id": port["device_id"],
"device_owner": port["device_owner"]}

View File

@ -1418,8 +1418,10 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
floatingip_id=fip_id,
floatingip_db=floatingip_db)
self._core_plugin.update_port(context.elevated(), external_port['id'],
{'port': {'device_id': fip_id}})
self._core_plugin.update_port(
context.elevated(), external_port['id'],
{'port': {'device_id': fip_id,
'project_id': fip['tenant_id']}})
registry.notify(resources.FLOATING_IP,
events.AFTER_UPDATE,
self._update_fip_assoc,

View File

@ -771,7 +771,8 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase,
tenant_id = kwargs['original_' + resource]['tenant_id']
else:
tenant_id = kwargs[resource]['tenant_id']
self._ensure_default_security_group(context, tenant_id)
if tenant_id:
self._ensure_default_security_group(context, tenant_id)
def _ensure_default_security_group(self, context, tenant_id):
"""Create a default security group if one doesn't exist.

View File

@ -1401,11 +1401,18 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
for port in port_list:
# Set up the port request dict
pdata = port.get('port')
project_id = pdata.get('project_id') or pdata.get('tenant_id')
security_group_ids = pdata.get('security_groups')
if security_group_ids is const.ATTR_NOT_SPECIFIED:
security_group_ids = None
else:
security_group_ids = set(security_group_ids)
if pdata.get('device_owner'):
self._enforce_device_owner_not_router_intf_or_device_id(
context, pdata.get('device_owner'),
pdata.get('device_id'), pdata.get('tenant_id'))
bulk_port_data = dict(project_id=pdata.get('project_id'),
pdata.get('device_id'), project_id)
bulk_port_data = dict(
project_id=project_id,
name=pdata.get('name'),
network_id=pdata.get('network_id'),
admin_state_up=pdata.get('admin_state_up'),
@ -1413,7 +1420,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
const.PORT_STATUS_ACTIVE),
device_id=pdata.get('device_id'),
device_owner=pdata.get('device_owner'),
security_groups=pdata.get('security_groups'),
security_group_ids=security_group_ids,
description=pdata.get('description'))
# Ensure that the networks exist.
@ -1434,6 +1441,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
mac=raw_mac_address)
eui_mac_address = netaddr.EUI(raw_mac_address,
dialect=eui48.mac_unix_expanded)
port['port']['mac_address'] = str(eui_mac_address)
# Create the Port object
db_port_obj = ports_obj.Port(context,
@ -1441,27 +1449,42 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
id=uuidutils.generate_uuid(),
**bulk_port_data)
db_port_obj.create()
port_dict = self._make_port_dict(db_port_obj,
process_extensions=False)
port_compat = {'port': port_dict}
# Call IPAM to allocate IP addresses
try:
# TODO(njohnston): IPAM allocation needs to be revamped to
# be bulk-friendly.
self.ipam.allocate_ips_for_port_and_store(
context, db_port_obj, db_port_obj['id'])
ips = self.ipam.allocate_ips_for_port_and_store(
context, port, db_port_obj['id'])
ipam_fixed_ips = []
for ip in ips:
fixed_ip = ports_obj.IPAllocation(
port_id=db_port_obj['id'],
subnet_id=ip['subnet_id'],
network_id=network_id,
ip_address=ip['ip_address'])
ipam_fixed_ips.append(fixed_ip)
db_port_obj['fixed_ips'] = ipam_fixed_ips
db_port_obj['ip_allocation'] = (ipalloc_apidef.
IP_ALLOCATION_IMMEDIATE)
except ipam_exc.DeferIpam:
db_port_obj['ip_allocation'] = (ipalloc_apidef.
IP_ALLOCATION_DEFERRED)
fixed_ips = pdata.get('fixed_ips')
if validators.is_attr_set(fixed_ips) and not fixed_ips:
# [] was passed explicitly as fixed_ips: unaddressed port.
db_port_obj['ip_allocation'] = (ipalloc_apidef.
IP_ALLOCATION_NONE)
# Make port dict
port_dict = self._make_port_dict(db_port_obj,
process_extensions=False)
port_dict[portbindings.HOST_ID] = pdata.get(
portbindings.HOST_ID)
port_compat = {'port': port_dict}
# Activities immediately post-port-creation
self.extension_manager.process_create_port(context, port_dict,
db_port_obj)
@ -1475,6 +1498,10 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
# process port binding
binding = db.add_port_binding(context, port_dict['id'])
binding_host = pdata.get(
portbindings.HOST_ID, const.ATTR_NOT_SPECIFIED)
if binding_host != const.ATTR_NOT_SPECIFIED:
binding["host"] = binding_host
mech_context = driver_context.PortContext(self, context,
port_dict, network,
binding, None)

View File

@ -586,6 +586,9 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase):
if neutron_context:
# create a specific auth context for this request
req.environ['neutron.context'] = neutron_context
elif hasattr(self, 'tenant_id'):
req.environ['neutron.context'] = context.Context('',
self.tenant_id)
return req.get_response(self._api_for_resource(resource))
def _show(self, resource, id,

View File

@ -54,6 +54,7 @@ class NetworkRbacTestcase(test_plugin.NeutronDbPluginV2TestCase):
'admin_state_up': True,
'device_id': 'device_id',
'device_owner': 'device_owner',
'project_id': target_tenant,
'tenant_id': target_tenant}}
port = self.plugin.create_port(self.context, test_port)

View File

@ -69,6 +69,7 @@ class FakeL3PluginWithAgents(common_db_mixin.CommonDbMixin,
class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase):
_mechanism_drivers = ['openvswitch', 'fake_agent', 'l2population']
tenant = 'tenant'
def setUp(self):
super(TestL2PopulationRpcTestCase, self).setUp()
@ -366,13 +367,15 @@ class TestL2PopulationRpcTestCase(test_plugin.Ml2PluginV2TestCase):
enable_dhcp=False) as snet:
with self.port(
subnet=snet,
project_id=self.tenant,
device_owner=constants.DEVICE_OWNER_DVR_INTERFACE)\
as port:
port_id = port['port']['id']
plugin.update_distributed_port_binding(self.adminContext,
port_id, {'port': {portbindings.HOST_ID: HOST_4,
'device_id': router['id']}})
port = self._show('ports', port_id)
port = self._show('ports', port_id,
neutron_context=self.adminContext)
self.assertEqual(portbindings.VIF_TYPE_DISTRIBUTED,
port['port'][portbindings.VIF_TYPE])
self.callbacks.update_device_up(