Browse Source

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)
tags/14.0.3
Nate Johnston 5 months ago
parent
commit
aa60d6e837
7 changed files with 50 additions and 13 deletions
  1. +1
    -1
      neutron/db/db_base_plugin_common.py
  2. +4
    -2
      neutron/db/l3_db.py
  3. +2
    -1
      neutron/db/securitygroups_db.py
  4. +35
    -8
      neutron/plugins/ml2/plugin.py
  5. +3
    -0
      neutron/tests/unit/db/test_db_base_plugin_v2.py
  6. +1
    -0
      neutron/tests/unit/db/test_rbac_db_mixin.py
  7. +4
    -1
      neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py

+ 1
- 1
neutron/db/db_base_plugin_common.py 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"]}

+ 4
- 2
neutron/db/l3_db.py 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,

+ 2
- 1
neutron/db/securitygroups_db.py 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.

+ 35
- 8
neutron/plugins/ml2/plugin.py 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)

+ 3
- 0
neutron/tests/unit/db/test_db_base_plugin_v2.py 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,

+ 1
- 0
neutron/tests/unit/db/test_rbac_db_mixin.py 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)

+ 4
- 1
neutron/tests/unit/plugins/ml2/drivers/l2pop/test_mech_driver.py 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(

Loading…
Cancel
Save