From cd6bf8035d9a63e1803e6c763083d3aef0e9408c Mon Sep 17 00:00:00 2001 From: LIU Yulong Date: Mon, 18 Mar 2019 23:52:18 +0800 Subject: [PATCH] Random IP for concurrent create pf and update_port Port forwarding test port IP should be specified, otherwise IP collision may happen between new port IP and router interface IP. Or sometimes, port new IP and old IP are same. After this patch, the port new IP will be randomly choiced from the subset without [old_port_ips, router_interface_ips]. Partially reverts commit 414bdd4c5997886c97d0e3a0b19c684dafeabb7a. Change-Id: I157e08288765f1716b4cb12bb2e176760db806c0 Closes-Bug: #1818334 --- .../portforwarding/test_port_forwarding.py | 21 +++++++++++++++++-- .../tests/unit/db/test_db_base_plugin_v2.py | 16 ++++++++++---- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/neutron/tests/functional/services/portforwarding/test_port_forwarding.py b/neutron/tests/functional/services/portforwarding/test_port_forwarding.py index f0dd09a1854..7400285958e 100644 --- a/neutron/tests/functional/services/portforwarding/test_port_forwarding.py +++ b/neutron/tests/functional/services/portforwarding/test_port_forwarding.py @@ -57,6 +57,9 @@ class PortForwardingTestCaseBase(ml2_test_base.ML2TestFramework, def _delete_floatingip(self, fip_id): return self.l3_plugin.delete_floatingip(self.context, fip_id) + def _get_ports(self, filters): + return self.core_plugin.get_ports(self.context, filters=filters) + def _update_port(self, port_id, update_info): return self.core_plugin.update_port( self.context, port_id, {'port': update_info}) @@ -86,6 +89,13 @@ class PortForwardingTestCase(PortForwardingTestCaseBase): super(PortForwardingTestCase, self).setUp() self._prepare_env() + def _get_network_port_ips(self): + net_ports = self._get_ports( + filters={"network_id": [self.net['id']]}) + net_port_ips = [ + p['fixed_ips'][0]['ip_address'] for p in net_ports] + return net_port_ips + def _prepare_env(self): self.router = self._create_router(distributed=True) self.ext_net = self._create_network( @@ -101,9 +111,13 @@ class PortForwardingTestCase(PortForwardingTestCaseBase): self._set_router_gw(self.router['id'], self.ext_net['id']) self._add_router_interface(self.router['id'], self.subnet['id']) self.fip = self._create_floatingip(self.ext_net['id']) + + self.port_ip = self._find_ip_address( + self.subnet, exclude=self._get_network_port_ips(), is_random=True) self.port = self._create_port( self.fmt, self.net['id'], - fixed_ips=[{'subnet_id': self.subnet['id']}]).json['port'] + fixed_ips=[{'subnet_id': self.subnet['id'], + 'ip_address': self.port_ip}]).json['port'] self.port_forwarding = { apidef.RESOURCE_NAME: {apidef.EXTERNAL_PORT: 2225, @@ -445,7 +459,10 @@ class PortForwardingTestCase(PortForwardingTestCaseBase): funcs, args_list) def test_concurrent_create_port_forwarding_update_port(self): - new_ip = self._find_ip_address(self.subnet) + new_ip = self._find_ip_address( + self.subnet, + exclude=self._get_network_port_ips(), + is_random=True) funcs = [self.pf_plugin.create_floatingip_port_forwarding, self._update_port] args_list = [(self.context, self.fip['id'], self.port_forwarding), diff --git a/neutron/tests/unit/db/test_db_base_plugin_v2.py b/neutron/tests/unit/db/test_db_base_plugin_v2.py index 4e2b5b81181..c8175cfe6f1 100644 --- a/neutron/tests/unit/db/test_db_base_plugin_v2.py +++ b/neutron/tests/unit/db/test_db_base_plugin_v2.py @@ -17,6 +17,7 @@ import contextlib import copy import functools import itertools +import random import eventlet import mock @@ -288,10 +289,15 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): data = self._deserializers[ctype].deserialize(response.body)['body'] return data - def _find_ip_address(self, subnet): + def _find_ip_address(self, subnet, exclude=None, is_random=False): network_ports = self._list_ports( "json", 200, subnet['network_id']).json['ports'] used_ips = set() + if exclude: + if isinstance(exclude, (list, set, tuple)): + used_ips = set(exclude) + else: + used_ips.add(exclude) for port in network_ports: for ip in port['fixed_ips']: if ip['subnet_id'] == subnet['id']: @@ -299,9 +305,11 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): for pool in subnet['allocation_pools']: ips_range = netaddr.IPRange(pool['start'], pool['end']) - for ip in ips_range: - if ip not in used_ips: - return str(ip) + ip_list = [str(ip) for ip in ips_range if str(ip) not in used_ips] + if ip_list: + if is_random: + return random.choice(ip_list) + return ip_list[0] def _create_bulk_from_list(self, fmt, resource, objects, **kwargs): """Creates a bulk request from a list of objects."""