Merge "Update tests for scoped tokens and default roles"
diff --git a/devstack/plugin.sh b/devstack/plugin.sh
index 5eac133..fb4e932 100644
--- a/devstack/plugin.sh
+++ b/devstack/plugin.sh
@@ -24,6 +24,15 @@
         ${DEST}/octavia-tempest-plugin/octavia_tempest_plugin/contrib/test_server/test_server.go
 }
 
+function _configure_tempest {
+    if [ -n "$Q_ROUTER_NAME" ]; then
+        iniset $TEMPEST_CONFIG load_balancer default_router "$Q_ROUTER_NAME"
+    fi
+    if [ -n "$SUBNETPOOL_NAME_V6" ]; then
+        iniset $TEMPEST_CONFIG load_balancer default_ipv6_subnetpool "$SUBNETPOOL_NAME_V6"
+    fi
+}
+
 if [[ "$1" == "stack" ]]; then
     case "$2" in
         install)
@@ -40,6 +49,7 @@
         test-config)
             echo_summary "Building backend test server"
             build_backend_test_server
+            _configure_tempest
             ;;
     esac
 fi
diff --git a/octavia_tempest_plugin/config.py b/octavia_tempest_plugin/config.py
index fb4cb36..4d1543b 100644
--- a/octavia_tempest_plugin/config.py
+++ b/octavia_tempest_plugin/config.py
@@ -188,6 +188,13 @@
     cfg.StrOpt('member_2_ipv6_subnet_cidr',
                default='fd77:1457:4cf0:26a8::/64',
                help='CIDR format subnet to use for the member 1 ipv6 subnet.'),
+    cfg.StrOpt('default_router',
+               default='router1',
+               help='The default router connected to the public network.'),
+    cfg.StrOpt('default_ipv6_subnetpool',
+               default='shared-default-subnetpool-v6',
+               help='The default IPv6 subnetpool to use when creating the '
+                    'IPv6 VIP subnet.'),
     # Amphora specific options
     cfg.StrOpt('amphora_ssh_user',
                default='ubuntu',
diff --git a/octavia_tempest_plugin/tests/scenario/v2/test_ipv6_traffic_ops.py b/octavia_tempest_plugin/tests/scenario/v2/test_ipv6_traffic_ops.py
index 1495b82..717ddf9 100644
--- a/octavia_tempest_plugin/tests/scenario/v2/test_ipv6_traffic_ops.py
+++ b/octavia_tempest_plugin/tests/scenario/v2/test_ipv6_traffic_ops.py
@@ -297,7 +297,7 @@
     @decorators.idempotent_id('843a13f7-e00f-4151-8817-b5395eb69b52')
     def test_ipv6_tcp_LC_listener_with_allowed_cidrs(self):
         self._test_listener_with_allowed_cidrs(
-            const.TCP, 91, const.LB_ALGORITHM_LEAST_CONNECTIONS)
+            const.TCP, 91, const.LB_ALGORITHM_LEAST_CONNECTIONS, delay=0.2)
 
     @decorators.idempotent_id('cc0d55b1-87e8-4a87-bf50-66299947a469')
     def test_ipv6_udp_LC_listener_with_allowed_cidrs(self):
@@ -350,7 +350,7 @@
             const.UDP, 101, const.LB_ALGORITHM_SOURCE_IP_PORT)
 
     def _test_listener_with_allowed_cidrs(self, protocol, protocol_port,
-                                          algorithm):
+                                          algorithm, delay=None):
         """Tests traffic through a loadbalancer with allowed CIDRs set.
 
         * Set up listener with allowed CIDRS (allow all) on a loadbalancer.
@@ -476,7 +476,7 @@
         self.check_members_balanced(
             self.lb_vip_address, protocol=protocol,
             protocol_port=protocol_port, persistent=False,
-            traffic_member_count=members)
+            traffic_member_count=members, delay=delay)
 
         listener_kwargs = {
             const.LISTENER_ID: listener_id,
diff --git a/octavia_tempest_plugin/tests/test_base.py b/octavia_tempest_plugin/tests/test_base.py
index 26e44ee..e182d58 100644
--- a/octavia_tempest_plugin/tests/test_base.py
+++ b/octavia_tempest_plugin/tests/test_base.py
@@ -185,6 +185,8 @@
         cls.mem_flavor_client = cls.os_roles_lb_member.flavor_client
         cls.mem_provider_client = cls.os_roles_lb_member.provider_client
         cls.os_admin_servers_client = cls.os_admin.servers_client
+        cls.os_admin_routers_client = cls.os_admin.routers_client
+        cls.os_admin_subnetpools_client = cls.os_admin.subnetpools_client
         cls.lb_admin_flavor_capabilities_client = (
             cls.os_roles_lb_admin.flavor_capabilities_client)
         cls.lb_admin_availability_zone_capabilities_client = (
@@ -381,33 +383,38 @@
 
         # Create tenant VIP IPv6 subnet
         if CONF.load_balancer.test_with_ipv6:
-            # See if ipv6-private-subnet exists and use it if so.
-            priv_ipv6_subnet = cls.os_admin.subnets_client.list_subnets(
-                name='ipv6-private-subnet')['subnets']
-
             cls.lb_member_vip_ipv6_subnet_stateful = False
-            if len(priv_ipv6_subnet) == 1:
-                if (priv_ipv6_subnet[0]['ipv6_address_mode'] ==
-                        'dhcpv6-stateful'):
-                    cls.lb_member_vip_ipv6_subnet_stateful = True
-                cls.lb_member_vip_ipv6_subnet = priv_ipv6_subnet[0]
-                cls.lb_member_vip_ipv6_net = {
-                    'id': priv_ipv6_subnet[0]['network_id']}
-            else:
-                subnet_kwargs = {
-                    'name': data_utils.rand_name("lb_member_vip_ipv6_subnet"),
-                    'network_id': cls.lb_member_vip_net['id'],
-                    'cidr': CONF.load_balancer.vip_ipv6_subnet_cidr,
-                    'ip_version': 6}
-                result = cls.lb_mem_subnet_client.create_subnet(
-                    **subnet_kwargs)
-                cls.lb_member_vip_ipv6_net = cls.lb_member_vip_net
-                cls.lb_member_vip_ipv6_subnet = result['subnet']
-                cls.addClassResourceCleanup(
-                    waiters.wait_for_not_found,
-                    cls._logging_delete_subnet,
-                    cls.lb_mem_subnet_client.show_subnet,
-                    cls.lb_member_vip_ipv6_subnet['id'])
+            cls.lb_member_vip_ipv6_subnet_use_subnetpool = False
+            subnet_kwargs = {
+                'name': data_utils.rand_name("lb_member_vip_ipv6_subnet"),
+                'network_id': cls.lb_member_vip_net['id'],
+                'ip_version': 6}
+
+            # Use a CIDR from devstack's default IPv6 subnetpool if it exists,
+            # the subnetpool's cidr is routable from the devstack node
+            # through the default router
+            subnetpool_name = CONF.load_balancer.default_ipv6_subnetpool
+            if subnetpool_name:
+                subnetpool = cls.os_admin_subnetpools_client.list_subnetpools(
+                    name=subnetpool_name)['subnetpools']
+                if len(subnetpool) == 1:
+                    subnetpool = subnetpool[0]
+                    subnet_kwargs['subnetpool_id'] = subnetpool['id']
+                    cls.lb_member_vip_ipv6_subnet_use_subnetpool = True
+
+            if 'subnetpool_id' not in subnet_kwargs:
+                subnet_kwargs['cidr'] = (
+                    CONF.load_balancer.vip_ipv6_subnet_cidr)
+
+            result = cls.lb_mem_subnet_client.create_subnet(
+                **subnet_kwargs)
+            cls.lb_member_vip_ipv6_net = cls.lb_member_vip_net
+            cls.lb_member_vip_ipv6_subnet = result['subnet']
+            cls.addClassResourceCleanup(
+                waiters.wait_for_not_found,
+                cls._logging_delete_subnet,
+                cls.lb_mem_subnet_client.show_subnet,
+                cls.lb_member_vip_ipv6_subnet['id'])
 
             LOG.info('lb_member_vip_ipv6_subnet: {}'.format(
                 cls.lb_member_vip_ipv6_subnet))
@@ -797,6 +804,30 @@
             cls.lb_member_router['id'],
             subnet_id=cls.lb_member_vip_subnet['id'])
 
+        if (CONF.load_balancer.test_with_ipv6 and
+                CONF.load_balancer.default_router and
+                cls.lb_member_vip_ipv6_subnet_use_subnetpool):
+
+            router_name = CONF.load_balancer.default_router
+            # if lb_member_vip_ipv6_subnet uses devstack's subnetpool,
+            # plug the subnet into the default router
+            router = cls.os_admin.routers_client.list_routers(
+                name=router_name)['routers']
+
+            if len(router) == 1:
+                router = router[0]
+
+                # Add IPv6 VIP subnet to router1
+                cls.os_admin_routers_client.add_router_interface(
+                    router['id'],
+                    subnet_id=cls.lb_member_vip_ipv6_subnet['id'])
+                cls.addClassResourceCleanup(
+                    waiters.wait_for_not_found,
+                    cls.os_admin_routers_client.remove_router_interface,
+                    cls.os_admin_routers_client.remove_router_interface,
+                    router['id'],
+                    subnet_id=cls.lb_member_vip_ipv6_subnet['id'])
+
         # Add member subnet 1 to router
         cls.lb_mem_routers_client.add_router_interface(
             cls.lb_member_router['id'],