Merge "Add knowledge of storage network to scenario tests"
diff --git a/manila_tempest_tests/config.py b/manila_tempest_tests/config.py
index c6b9c73..e0e8ea3 100644
--- a/manila_tempest_tests/config.py
+++ b/manila_tempest_tests/config.py
@@ -86,6 +86,15 @@
                help="Forces access rules to be as specified on NFS scenario"
                     " tests. This can used for working around multiple "
                     "NATs between the VMs and the storage controller."),
+    cfg.StrOpt("storage_network",
+               help="Name or UUID of a neutron network that is used to access "
+                    "shared file systems over. If specified, test virtual "
+                    "machines are created with two NICs, the primary NIC is "
+                    "attached to the private project network and the "
+                    "secondary NIC is attached to the specified storage "
+                    "network. If using NFS, access control is done with the "
+                    "help of the IP address assigned to the virtual machine's "
+                    "storage network NIC."),
     cfg.ListOpt("enable_ro_access_level_for_protocols",
                 default=["nfs", ],
                 help="List of protocols to run tests with ro access level."),
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,