Merge "[bgpvpn] Bring in L2/L3 VPN endpoints tests" into mcp/caracal
diff --git a/neutron_tempest_plugin/bgpvpn/api/test_bgpvpn.py b/neutron_tempest_plugin/bgpvpn/api/test_bgpvpn.py
index 4610686..14fa320 100644
--- a/neutron_tempest_plugin/bgpvpn/api/test_bgpvpn.py
+++ b/neutron_tempest_plugin/bgpvpn/api/test_bgpvpn.py
@@ -257,6 +257,7 @@
         self.assertRaises(exceptions.BadRequest,
                           self.bgpvpn_admin_client.update_bgpvpn,
                           bgpvpn['bgpvpn']['id'], **updatedata)
+        self.delete_bgpvpn(self.bgpvpn_admin_client, bgpvpn['bgpvpn'])
 
     @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f049ce21-d239-47c0-b13f-fb57a2a558ce')
@@ -279,6 +280,7 @@
                           self.bgpvpn_client.create_network_association,
                           uuidutils.generate_uuid(),
                           network['network']['id'])
+        self.delete_bgpvpn(self.bgpvpn_admin_client, bgpvpn['bgpvpn'])
 
     @decorators.attr(type=['negative'])
     @decorators.idempotent_id('078b2660-4adb-4c4c-abf0-b77bf0bface5')
@@ -306,6 +308,7 @@
                           self.bgpvpn_client.delete_network_association,
                           uuidutils.generate_uuid(),
                           association['network_association']['id'])
+        self.delete_bgpvpn(self.bgpvpn_admin_client, bgpvpn['bgpvpn'])
 
     @decorators.idempotent_id('de8d94b0-0239-4a48-9574-c3a4a4f7cacb')
     def test_associate_disassociate_router(self):
diff --git a/neutron_tempest_plugin/bgpvpn/base.py b/neutron_tempest_plugin/bgpvpn/base.py
index b436a5d..46c2c78 100644
--- a/neutron_tempest_plugin/bgpvpn/base.py
+++ b/neutron_tempest_plugin/bgpvpn/base.py
@@ -17,6 +17,7 @@
 from tempest.common import utils
 from tempest import config
 from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
 
 from neutron_tempest_plugin.bgpvpn.services import bgpvpn_client
 
@@ -34,12 +35,6 @@
     bgpvpn_alt_client = None
 
     @classmethod
-    def resource_cleanup(cls):
-        for bgpvpn in cls.bgpvpns:
-            cls.bgpvpn_admin_client.delete_bgpvpn(bgpvpn['id'])
-        super(BaseBgpvpnTest, cls).resource_cleanup()
-
-    @classmethod
     def resource_setup(cls):
         cls.route_distinguishers = []
         cls.bgpvpns = []
@@ -87,9 +82,9 @@
 
         body = client.create_bgpvpn(**kwargs)
         bgpvpn = body['bgpvpn']
-        self.bgpvpns.append(bgpvpn)
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.bgpvpn_admin_client.delete_bgpvpn, bgpvpn['id'])
         return bgpvpn
 
     def delete_bgpvpn(self, client, bgpvpn):
         client.delete_bgpvpn(bgpvpn['id'])
-        self.bgpvpns.remove(bgpvpn)
diff --git a/neutron_tempest_plugin/bgpvpn/scenario/test_bgpvpn_basic.py b/neutron_tempest_plugin/bgpvpn/scenario/test_bgpvpn_basic.py
index 75ca80c..597bfc8 100644
--- a/neutron_tempest_plugin/bgpvpn/scenario/test_bgpvpn_basic.py
+++ b/neutron_tempest_plugin/bgpvpn/scenario/test_bgpvpn_basic.py
@@ -27,7 +27,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
-import testtools
 
 from neutron_tempest_plugin.bgpvpn import base
 from neutron_tempest_plugin.bgpvpn.scenario import manager
@@ -815,7 +814,6 @@
     @decorators.idempotent_id('8de130c1-778a-4d86-913b-ff41be3c2f0b')
     @utils.services('compute', 'network')
     @utils.requires_ext(extension='bgpvpn-routes-control', service='network')
-    @testtools.skipUnless(False, "Skip unless PRODX-25126 is fixed")
     def test_bgpvpn_port_association_create_and_delete_bgpvpn(self):
         """This test checks port association in BGPVPN.
 
@@ -1352,6 +1350,9 @@
             tenant_id=self.bgpvpn_admin_client.project_id,
             name=name, route_targets=rts, export_targets=export_rts,
             import_targets=import_rts)
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.bgpvpn_admin_client.delete_bgpvpn,
+                        self.bgpvpn['id'])
         return self.bgpvpn
 
     def _update_l3_bgpvpn(self, rts=None, import_rts=None, export_rts=None,
diff --git a/neutron_tempest_plugin/neutron_dynamic_routing/api/test_bgp_speaker_extensions.py b/neutron_tempest_plugin/neutron_dynamic_routing/api/test_bgp_speaker_extensions.py
index 5cdd524..b7e5c9e 100644
--- a/neutron_tempest_plugin/neutron_dynamic_routing/api/test_bgp_speaker_extensions.py
+++ b/neutron_tempest_plugin/neutron_dynamic_routing/api/test_bgp_speaker_extensions.py
@@ -229,6 +229,25 @@
     def test_get_advertised_routes_null_address_scope(self):
         self.useFixture(fixtures.LockFixture('gateway_network_binding'))
         bgp_speaker = self.create_bgp_speaker(**self.default_bgp_speaker_args)
+
+        addr_scope1 = self.create_address_scope(
+                                 'get-advertised-routes-null-address-scope',
+                                 ip_version=4)
+        ext_net = self.create_shared_network(**{'router:external': True})
+        ext_subnetpool = self.create_subnetpool(
+                                 'get-advertised-routes-null-address-pool-ext',
+                                 is_admin=True,
+                                 default_prefixlen=24,
+                                 address_scope_id=addr_scope1['id'],
+                                 prefixes=['8.0.0.0/8'])
+        self.create_subnet({'id': ext_net['id']},
+                   cidr=netaddr.IPNetwork('8.1.0.0/24'),
+                   ip_version=4,
+                   client=self.admin_client,
+                   subnetpool_id=ext_subnetpool['id'])
+        ext_gw_info = {'network_id': ext_net['id']}
+        router = self.create_router(ext_gw_info)
+        self.admin_routers.append(router)
         bgp_speaker_id = bgp_speaker['id']
         self.bgp_adm_client.add_bgp_gateway_network(bgp_speaker_id,
                                                   self.ext_net_id)
@@ -238,6 +257,21 @@
     @decorators.idempotent_id('cae9cdb1-ad65-423c-9604-d4cd0073616e')
     def test_get_advertised_routes_floating_ips(self):
         self.useFixture(fixtures.LockFixture('gateway_network_binding'))
+        addr_scope1 = self.create_address_scope(
+                                 'get-advertised-routes-floating-ip-scope',
+                                 ip_version=4)
+        ext_net = self.create_shared_network(**{'router:external': True})
+        ext_subnetpool = self.create_subnetpool(
+                                 'get-advertised-routes-floating-ip-ext',
+                                 is_admin=True,
+                                 default_prefixlen=24,
+                                 address_scope_id=addr_scope1['id'],
+                                 prefixes=['8.0.0.0/8'])
+        self.create_subnet({'id': ext_net['id']},
+                   cidr=netaddr.IPNetwork('8.2.0.0/24'),
+                   ip_version=4,
+                   client=self.admin_client,
+                   subnetpool_id=ext_subnetpool['id'])
         bgp_speaker = self.create_bgp_speaker(**self.default_bgp_speaker_args)
         bgp_speaker_id = bgp_speaker['id']
         self.bgp_adm_client.add_bgp_gateway_network(bgp_speaker_id,
diff --git a/neutron_tempest_plugin/vpnaas/api/base_vpnaas.py b/neutron_tempest_plugin/vpnaas/api/base_vpnaas.py
index 0e54380..3ccf48b 100644
--- a/neutron_tempest_plugin/vpnaas/api/base_vpnaas.py
+++ b/neutron_tempest_plugin/vpnaas/api/base_vpnaas.py
@@ -14,7 +14,10 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import time
+
 from tempest.lib.common.utils import data_utils
+from tempest.lib import exceptions as lib_exc
 
 from neutron_tempest_plugin.api import base
 from neutron_tempest_plugin import config
@@ -138,6 +141,31 @@
         return ipsec_site_connection
 
     @classmethod
+    def wait_ipsec_site_connection_status(cls, site_id, status, timeout=None,
+                                          interval=None):
+        start_time = int(time.time())
+        timeout = timeout or cls.client.build_timeout
+        interval = interval or cls.client.build_interval
+        current_status = ""
+        while True:
+            if current_status.lower() == status.lower():
+                return
+
+            timed_out = int(time.time()) - start_time >= timeout
+            if timed_out:
+                message = ('IPSec site connection %(site_id)s failed to reach '
+                           'desired status %(desired_status)s, current state '
+                           '%(current_status)s in %(timeout)d' %
+                           {"site_id": site_id,
+                            "desired_status": status,
+                            "current_status": current_status,
+                            "timeout": timeout})
+                raise lib_exc.TimeoutException(message)
+            current_status = cls.client.show_ipsec_site_connection(
+                site_id)['ipsec_site_connection']['status']
+            time.sleep(interval)
+
+    @classmethod
     def create_endpoint_group(cls, name, type, endpoints):
         """Wrapper utility that returns a test ipsec policy."""
         body = cls.client.create_endpoint_group(
diff --git a/neutron_tempest_plugin/vpnaas/scenario/test_vpnaas.py b/neutron_tempest_plugin/vpnaas/scenario/test_vpnaas.py
index 30a8674..32181fe 100644
--- a/neutron_tempest_plugin/vpnaas/scenario/test_vpnaas.py
+++ b/neutron_tempest_plugin/vpnaas/scenario/test_vpnaas.py
@@ -116,6 +116,13 @@
             cls.extra_subnet_attributes['ipv6_address_mode'] = 'slaac'
             cls.extra_subnet_attributes['ipv6_ra_mode'] = 'slaac'
 
+        left_v4_cidr = netaddr.IPNetwork('10.20.0.0/24')
+        left_v6_cidr = netaddr.IPNetwork('2001:db8:0:2::/64')
+        cls.left_cidr = left_v6_cidr if cls.inner_ipv6 else left_v4_cidr
+        right_v4_cidr = netaddr.IPNetwork('10.10.0.0/24')
+        right_v6_cidr = netaddr.IPNetwork('2001:db8:0:1::/64')
+        cls.right_cidr = right_v6_cidr if cls.inner_ipv6 else right_v4_cidr
+
         # LEFT
         cls.router = cls.create_router(
             data_utils.rand_name('left-router'),
@@ -123,14 +130,22 @@
             external_network_id=CONF.network.public_network_id)
         cls.network = cls.create_network(network_name='left-network')
         ip_version = 6 if cls.inner_ipv6 else 4
-        v4_cidr = netaddr.IPNetwork('10.20.0.0/24')
-        v6_cidr = netaddr.IPNetwork('2001:db8:0:2::/64')
-        cidr = v6_cidr if cls.inner_ipv6 else v4_cidr
-        cls.subnet = cls.create_subnet(
-            cls.network, ip_version=ip_version, cidr=cidr, name='left-subnet',
-            **cls.extra_subnet_attributes)
-        cls.create_router_interface(cls.router['id'], cls.subnet['id'])
+        is_distributed = cls.os_admin.network_client.show_router(
+            cls.router['id'])['router'].get('distributed')
 
+        cls.subnet = cls.create_subnet(
+            cls.network, ip_version=ip_version, cidr=cls.left_cidr,
+            name='left-subnet', **cls.extra_subnet_attributes)
+        cls.create_router_interface(cls.router['id'], cls.subnet['id'])
+        if is_distributed:
+            snat_port = cls.os_admin.network_client.list_ports(
+                device_id=cls.router['id'],
+                device_owner='network:router_centralized_snat')
+            snat_ip = cls._get_ip_on_subnet_for_port(
+                cls, snat_port['ports'][0], cls.subnet['id'])
+            cls.os_admin.network_client.update_subnet(
+                cls.subnet['id'], host_routes=[{"destination": cls.right_cidr,
+                                                "nexthop": snat_ip}])
         # Gives an internal IPv4 subnet for floating IP to the left server,
         # we use it to ssh into the left server.
         if cls.inner_ipv6:
@@ -164,15 +179,23 @@
             data_utils.rand_name('right-router'),
             admin_state_up=True,
             external_network_id=CONF.network.public_network_id)
+        is_distributed = cls.os_admin.network_client.show_router(
+            router['id'])['router'].get('distributed')
         network = cls.create_network(network_name='right-network')
-        v4_cidr = netaddr.IPNetwork('10.10.0.0/24')
-        v6_cidr = netaddr.IPNetwork('2001:db8:0:1::/64')
-        cidr = v6_cidr if cls.inner_ipv6 else v4_cidr
         ip_version = 6 if cls.inner_ipv6 else 4
         subnet = cls.create_subnet(
-            network, ip_version=ip_version, cidr=cidr, name='right-subnet',
-            **cls.extra_subnet_attributes)
+            network, ip_version=ip_version, cidr=cls.right_cidr,
+            name='right-subnet', **cls.extra_subnet_attributes)
         cls.create_router_interface(router['id'], subnet['id'])
+        if is_distributed:
+            snat_port = cls.os_admin.network_client.list_ports(
+                device_id=router['id'],
+                device_owner='network:router_centralized_snat')
+            snat_ip = cls._get_ip_on_subnet_for_port(
+                cls, snat_port['ports'][0], subnet['id'])
+            cls.os_admin.network_client.update_subnet(
+                subnet['id'], host_routes=[{"destination": cls.left_cidr,
+                                            "nexthop": snat_ip}])
 
         return network, subnet, router
 
@@ -207,6 +230,7 @@
             site['vpnservice'] = self.create_vpnservice(
                 site['subnet']['id'], site['router']['id'],
                 name=data_utils.rand_name('%s-vpnservice' % site['name']))
+        site_connections = []
         for i in range(0, 2):
             site = sites[i]
             vpnservice = site['vpnservice']
@@ -218,7 +242,7 @@
                     raise self.skipException(msg)
             else:
                 peer_address = peer['vpnservice']['external_v4_ip']
-            self.create_ipsec_site_connection(
+            site_connection = self.create_ipsec_site_connection(
                 self.ikepolicy['id'],
                 self.ipsecpolicy['id'],
                 vpnservice['id'],
@@ -228,6 +252,10 @@
                 psk=psk,
                 name=data_utils.rand_name(
                     '%s-ipsec-site-connection' % site['name']))
+            site_connections.append(site_connection)
+        for site_connection in site_connections:
+            self.wait_ipsec_site_connection_status(site_connection['id'],
+                                                   status="ACTIVE")
 
     def _get_ip_on_subnet_for_port(self, port, subnet_id):
         for fixed_ip in port['fixed_ips']: