Fix testing IPv6 VIP network connectivity

The IPv6 VIP subnet used in the tests is created using devstack's
default IPv6 subnetpool.
Devstack ensures that any CIDR from this subnetpool is routable from the
devstack node if the subnet is plugged into devstack's router1.

Change-Id: Iaf3113087a344787add3405208fb229838a56d0b
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 f44bf96..7af7a1f 100644
--- a/octavia_tempest_plugin/config.py
+++ b/octavia_tempest_plugin/config.py
@@ -179,6 +179,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/test_base.py b/octavia_tempest_plugin/tests/test_base.py
index 669a33c..ace6502 100644
--- a/octavia_tempest_plugin/tests/test_base.py
+++ b/octavia_tempest_plugin/tests/test_base.py
@@ -128,6 +128,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 = (
@@ -324,33 +326,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))
@@ -737,6 +744,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'],