Add knowledge of storage network to scenario tests

In many deployments, shared file systems are exported
over a shared storage network. Typically, this shared
storage network is not reachable from within
private tenant networks. Our tests currently
have no cognizance of this topology, and expect that
shares are always exported on a network routable or
directly reachable through private tenant networks.

Add a configuration option to allow configuring the
name or UUID of a shared storage network. If specified
this network will be plugged into VMs created by the
scenario tests and access control will be on the
storage network IP, if NFS.

Change-Id: I8d8063d46284076499d868a5f9b3d13a2a78b5b0
Signed-off-by: Goutham Pacha Ravi <gouthampravi@gmail.com>
diff --git a/manila_tempest_tests/tests/scenario/manager.py b/manila_tempest_tests/tests/scenario/manager.py
index 0aa1b9e..e767b02 100644
--- a/manila_tempest_tests/tests/scenario/manager.py
+++ b/manila_tempest_tests/tests/scenario/manager.py
@@ -19,6 +19,7 @@
 import netaddr
 from oslo_log import log
 from oslo_utils import netutils
+from oslo_utils import uuidutils
 import six
 
 from tempest.common import compute
@@ -721,12 +722,20 @@
                          % port_map)
         return port_map[0]
 
-    def _get_network_by_name(self, network_name):
-        net = self.os_admin.networks_client.list_networks(
-            name=network_name)['networks']
-        self.assertNotEqual(len(net), 0,
-                            "Unable to get network by name: %s" % network_name)
-        return net[0]
+    def _get_network_by_name_or_id(self, identifier):
+
+        if uuidutils.is_uuid_like(identifier):
+            return self.os_admin.networks_client.show_network(
+                identifier)['network']
+
+        networks = self.os_admin.networks_client.list_networks(
+            name=identifier)['networks']
+        self.assertNotEqual(len(networks), 0,
+                            "Unable to get network by name: %s" % identifier)
+        return networks[0]
+
+    def get_networks(self):
+        return self.os_admin.networks_client.list_networks()['networks']
 
     def create_floating_ip(self, thing, external_network_id=None,
                            port_id=None, client=None):
@@ -1111,7 +1120,7 @@
             if not CONF.compute.fixed_network_name:
                 m = 'fixed_network_name must be specified in config'
                 raise lib_exc.InvalidConfiguration(m)
-            network = self._get_network_by_name(
+            network = self._get_network_by_name_or_id(
                 CONF.compute.fixed_network_name)
             router = None
             subnet = None
diff --git a/manila_tempest_tests/tests/scenario/manager_share.py b/manila_tempest_tests/tests/scenario/manager_share.py
index 4e0c1b7..c4cf027 100644
--- a/manila_tempest_tests/tests/scenario/manager_share.py
+++ b/manila_tempest_tests/tests/scenario/manager_share.py
@@ -79,6 +79,7 @@
         # Setup image and flavor the test instance
         # Support both configured and injected values
         self.floating_ips = {}
+        self.storage_network_nic_ips = {}
 
         if not hasattr(self, 'flavor_ref'):
             self.flavor_ref = CONF.share.client_vm_flavor_ref
@@ -113,6 +114,14 @@
         self._create_router_interface(subnet_id=self.subnet['id'],
                                       router_id=router['id'])
 
+        self.storage_network = (
+            self._get_network_by_name_or_id(CONF.share.storage_network)
+            if CONF.share.storage_network else None
+        )
+        self.storage_network_name = (
+            self.storage_network['name'] if self.storage_network else None
+        )
+
         if CONF.share.multitenancy_enabled:
             # Skip if DHSS=False
             self.share_network = self.create_share_network()
@@ -137,25 +146,39 @@
         if not hasattr(self, 'keypair'):
             self.keypair = self.create_keypair()
         security_groups = [{'name': self.security_group['name']}]
+        networks = [{'uuid': self.network['id']}]
+        if self.storage_network:
+            networks.append({'uuid': self.storage_network['id']})
+
         create_kwargs = {
             'key_name': self.keypair['name'],
             'security_groups': security_groups,
             'wait_until': wait_until,
-            'networks': [{'uuid': self.network['id']}, ],
+            'networks': networks,
         }
         instance = self.create_server(
             image_id=self.image_id, flavor=self.flavor_ref, **create_kwargs)
         return instance
 
     def init_remote_client(self, instance):
+        server_ip = None
         if self.ipv6_enabled:
             server_ip = self._get_ipv6_server_ip(instance)
-        else:
+        if not server_ip:
             # Obtain a floating IP
             floating_ip = (
                 self.compute_floating_ips_client.create_floating_ip()
                 ['floating_ip'])
             self.floating_ips[instance['id']] = floating_ip
+
+            if self.storage_network:
+                storage_net_nic = instance['addresses'].get(
+                    self.storage_network_name)
+                if storage_net_nic:
+                    self.storage_network_nic_ips[instance['id']] = (
+                        storage_net_nic[0]['addr']
+                    )
+
             self.addCleanup(
                 test_utils.call_and_ignore_notfound_exc,
                 self.compute_floating_ips_client.delete_floating_ip,
@@ -286,7 +309,7 @@
                 LOG.exception("Instance has no valid IP address. "
                               "Falling back to default")
         if not ip:
-            ip = '0.0.0.0/0'
+            ip = '::/0' if self.ipv6_enabled else '0.0.0.0/0'
 
         if snapshot:
             self._allow_access_snapshot(snapshot['id'], access_type='ip',
@@ -315,10 +338,12 @@
         share = share or self.share
         client = client or self.shares_v2_client
         if not CONF.share.multitenancy_enabled:
-            if self.ipv6_enabled:
+            if self.ipv6_enabled and not self.storage_network:
                 server_ip = self._get_ipv6_server_ip(instance)
             else:
                 server_ip = (CONF.share.override_ip_for_nfs_access or
+                             self.storage_network_nic_ips.get(
+                                 instance['id']) or
                              self.floating_ips[instance['id']]['ip'])
             self.assertIsNotNone(server_ip)
             return self.allow_access_ip(
@@ -357,10 +382,14 @@
         return locations
 
     def _get_ipv6_server_ip(self, instance):
-        for net_list in instance['addresses'].values():
-            for net_data in net_list:
-                if net_data['version'] == 6:
-                    return net_data['addr']
+        ipv6_addrs = []
+        for network_name, nic_list in instance['addresses'].items():
+            if network_name == self.storage_network_name:
+                continue
+            for nic_data in nic_list:
+                if nic_data['version'] == 6:
+                    ipv6_addrs.append(nic_data['addr'])
+        return ipv6_addrs[0] if ipv6_addrs else None
 
     def _create_share(self, share_protocol=None, size=None, name=None,
                       snapshot_id=None, description=None, metadata=None,