Merge "Remove hyphen from rand_name calls in thirdparty tests"
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index c872184..ef3a029 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -16,6 +16,7 @@
 from tempest_lib import decorators
 
 from tempest.api.compute import base
+from tempest.common import fixed_network
 from tempest import test
 
 
@@ -112,7 +113,10 @@
         name = data_utils.rand_name('server')
         flavor = self.flavor_ref
         image_id = self.image_ref
-        test_server = self.client.create_server(name, image_id, flavor)
+        network = self.get_tenant_network()
+        network_kwargs = fixed_network.set_networks_kwarg(network)
+        test_server = self.client.create_server(name, image_id, flavor,
+                                                **network_kwargs)
         self.addCleanup(self.client.delete_server, test_server['id'])
         self.client.wait_for_server_status(test_server['id'], 'ACTIVE')
         server = self.client.get_server(test_server['id'])
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index ddfe6de..b794101 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -22,6 +22,7 @@
 
 from tempest import clients
 from tempest.common import credentials
+from tempest.common import fixed_network
 from tempest import config
 from tempest import exceptions
 import tempest.test
@@ -212,6 +213,8 @@
         flavor = kwargs.get('flavor', cls.flavor_ref)
         image_id = kwargs.get('image_id', cls.image_ref)
 
+        kwargs = fixed_network.set_networks_kwarg(
+            cls.get_tenant_network(), kwargs) or {}
         body = cls.servers_client.create_server(
             name, image_id, flavor, **kwargs)
 
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index 0702f3f..42a61da 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -13,13 +13,15 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import time
+
+from tempest_lib import exceptions as lib_exc
+
 from tempest.api.compute import base
 from tempest import config
 from tempest import exceptions
 from tempest import test
 
-import time
-
 CONF = config.CONF
 
 
@@ -125,8 +127,15 @@
         self.assertTrue(interface_count > 0)
         self._check_interface(ifs[0])
 
-        iface = self._test_create_interface(server)
-        ifs.append(iface)
+        try:
+            iface = self._test_create_interface(server)
+        except lib_exc.BadRequest as e:
+            msg = ('Multiple possible networks found, use a Network ID to be '
+                   'more specific.')
+            if not CONF.compute.fixed_network_name and e.message == msg:
+                raise
+        else:
+            ifs.append(iface)
 
         iface = self._test_create_interface_by_network_id(server, ifs)
         ifs.append(iface)
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 5c10f30..70e4dff 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -19,6 +19,7 @@
 
 from tempest.api.compute import base
 from tempest.api import utils
+from tempest.common import fixed_network
 from tempest import config
 from tempest import test
 
@@ -66,9 +67,13 @@
             raise RuntimeError("Image %s (image_ref_alt) was not found!" %
                                cls.image_ref_alt)
 
+        network = cls.get_tenant_network()
+        cls.fixed_network_name = network['name']
+        network_kwargs = fixed_network.set_networks_kwarg(network)
         cls.s1_name = data_utils.rand_name(cls.__name__ + '-instance')
         cls.s1 = cls.create_test_server(name=cls.s1_name,
-                                        wait_until='ACTIVE')
+                                        wait_until='ACTIVE',
+                                        **network_kwargs)
 
         cls.s2_name = data_utils.rand_name(cls.__name__ + '-instance')
         cls.s2 = cls.create_test_server(name=cls.s2_name,
@@ -80,12 +85,6 @@
                                         flavor=cls.flavor_ref_alt,
                                         wait_until='ACTIVE')
 
-        cls.fixed_network_name = CONF.compute.fixed_network_name
-        if CONF.service_available.neutron:
-            if hasattr(cls.isolated_creds, 'get_primary_network'):
-                network = cls.isolated_creds.get_primary_network()
-                cls.fixed_network_name = network['name']
-
     @test.idempotent_id('05e8a8e7-9659-459a-989d-92c2f501f4ba')
     @utils.skip_unless_attr('multiple_images', 'Only one image found')
     @test.attr(type='gate')
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 157bd44..1f76b1c 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -18,6 +18,7 @@
 from tempest_lib import exceptions as lib_exc
 
 from tempest import clients
+from tempest.common import fixed_network
 from tempest import config
 from tempest import exceptions
 import tempest.test
@@ -62,6 +63,7 @@
         super(BaseVolumeTest, cls).setup_clients()
 
         cls.servers_client = cls.os.servers_client
+        cls.networks_client = cls.os.networks_client
 
         if cls._api_version == 1:
             cls.snapshots_client = cls.os.snapshots_client
@@ -159,6 +161,15 @@
             except Exception:
                 pass
 
+    @classmethod
+    def create_server(cls, name, **kwargs):
+        network = cls.get_tenant_network()
+        network_kwargs = fixed_network.set_networks_kwarg(network, kwargs)
+        return cls.servers_client.create_server(name,
+                                                cls.image_ref,
+                                                cls.flavor_ref,
+                                                **network_kwargs)
+
 
 class BaseVolumeAdminTest(BaseVolumeTest):
     """Base test case class for all Volume Admin API tests."""
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index 3de5021..1872ec7 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -36,9 +36,7 @@
 
         # Create a test shared instance
         srv_name = data_utils.rand_name(cls.__name__ + '-Instance')
-        cls.server = cls.servers_client.create_server(srv_name,
-                                                      cls.image_ref,
-                                                      cls.flavor_ref)
+        cls.server = cls.create_server(srv_name)
         cls.servers_client.wait_for_server_status(cls.server['id'], 'ACTIVE')
 
         # Create a test shared volume for attach/detach tests
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index af6e24e..a47e964 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -179,9 +179,7 @@
     @test.services('compute')
     def test_attach_volumes_with_nonexistent_volume_id(self):
         srv_name = data_utils.rand_name('Instance')
-        server = self.servers_client.create_server(srv_name,
-                                                   self.image_ref,
-                                                   self.flavor_ref)
+        server = self.create_server(srv_name)
         self.addCleanup(self.servers_client.delete_server, server['id'])
         self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
         self.assertRaises(lib_exc.NotFound,
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 2b6339a..b277390 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -69,9 +69,7 @@
         # Create a snapshot when volume status is in-use
         # Create a test instance
         server_name = data_utils.rand_name('instance')
-        server = self.servers_client.create_server(server_name,
-                                                   self.image_ref,
-                                                   self.flavor_ref)
+        server = self.create_server(server_name)
         self.addCleanup(self.servers_client.delete_server, server['id'])
         self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
         mountpoint = '/dev/%s' % CONF.compute.volume_device_name
diff --git a/tempest/common/fixed_network.py b/tempest/common/fixed_network.py
new file mode 100644
index 0000000..83822c2
--- /dev/null
+++ b/tempest/common/fixed_network.py
@@ -0,0 +1,83 @@
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import copy
+from oslo_log import log as logging
+
+from tempest_lib import exceptions as lib_exc
+
+from tempest import config
+
+CONF = config.CONF
+
+LOG = logging.getLogger(__name__)
+
+
+def get_tenant_network(creds_provider, compute_networks_client):
+    """Get a network usable by the primary tenant
+
+    :param creds_provider: instance of credential provider
+    :param compute_networks_client: compute network client. We want to have the
+           compute network client so we can have use a common approach for both
+           neutron and nova-network cases. If this is not an admin network
+           client, set_network_kwargs might fail in case fixed_network_name
+           is the network to be used, and it's not visible to the tenant
+    :return a dict with 'id' and 'name' of the network
+    """
+    fixed_network_name = CONF.compute.fixed_network_name
+    # NOTE(andreaf) get_primary_network will always be available once
+    # bp test-accounts-continued is implemented
+    if (CONF.auth.allow_tenant_isolation and
+        (CONF.service_available.neutron and
+         not CONF.service_available.ironic)):
+        network = creds_provider.get_primary_network()
+    else:
+        if fixed_network_name:
+            try:
+                resp = compute_networks_client.list_networks(
+                    name=fixed_network_name)
+                if isinstance(resp, list):
+                    networks = resp
+                elif isinstance(resp, dict):
+                    networks = resp['networks']
+                else:
+                    raise lib_exc.NotFound()
+                network = networks[0]
+                # To be consistent with network isolation, add name is only
+                # label is available
+                network['name'] = network.get('name', network.get('label'))
+            except lib_exc.NotFound:
+                # In case of nova network, if the fixed_network_name is not
+                # owned by the tenant, and the network client is not an admin
+                # one, list_networks will not find it
+                LOG.info('Unable to find network %s. '
+                         'Starting instance without specifying a network.' %
+                         fixed_network_name)
+                network = {'name': fixed_network_name}
+    LOG.info('Found network %s available for tenant' % network)
+    return network
+
+
+def set_networks_kwarg(network, kwargs=None):
+    """Set 'networks' kwargs for a server create if missing
+
+    :param network: dict of network to be used with 'id' and 'name'
+    :param kwargs: server create kwargs to be enhanced
+    :return: new dict of kwargs updated to include networks
+    """
+    params = copy.copy(kwargs) or {}
+    if kwargs and 'networks' in kwargs:
+        return params
+
+    if network:
+        params.update({"networks": [{'uuid': network['id']}]})
+    return params
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index f8cc17c..bae8296 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -24,6 +24,7 @@
 
 from tempest import clients
 from tempest.common import credentials
+from tempest.common import fixed_network
 from tempest.common.utils.linux import remote_client
 from tempest import config
 from tempest import exceptions
@@ -184,6 +185,8 @@
             flavor = CONF.compute.flavor_ref
         if create_kwargs is None:
             create_kwargs = {}
+        network = self.get_tenant_network()
+        fixed_network.set_networks_kwarg(network, create_kwargs)
 
         LOG.debug("Creating a server (name: %s, image: %s, flavor: %s)",
                   name, image, flavor)
diff --git a/tempest/services/compute/json/networks_client.py b/tempest/services/compute/json/networks_client.py
index ef1c058..0ae0920 100644
--- a/tempest/services/compute/json/networks_client.py
+++ b/tempest/services/compute/json/networks_client.py
@@ -20,11 +20,15 @@
 
 class NetworksClientJSON(service_client.ServiceClient):
 
-    def list_networks(self):
+    def list_networks(self, name=None):
         resp, body = self.get("os-networks")
         body = json.loads(body)
         self.expected_success(200, resp.status)
-        return service_client.ResponseBodyList(resp, body['networks'])
+        if name:
+            networks = [n for n in body['networks'] if n['label'] == name]
+        else:
+            networks = body['networks']
+        return service_client.ResponseBodyList(resp, networks)
 
     def get_network(self, network_id):
         resp, body = self.get("os-networks/%s" % str(network_id))
diff --git a/tempest/test.py b/tempest/test.py
index 19bae74..da936b4 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -32,6 +32,7 @@
 
 from tempest import clients
 from tempest.common import credentials
+from tempest.common import fixed_network
 import tempest.common.generator.valid_generator as valid
 from tempest import config
 from tempest import exceptions
@@ -435,6 +436,21 @@
                 'subnet': subnet,
                 'dhcp': dhcp}
 
+    @classmethod
+    def get_tenant_network(cls):
+        """Get the network to be used in testing
+
+        :return: network dict including 'id' and 'name'
+        """
+        # Make sure isolated_creds exists and get a network client
+        networks_client = cls.get_client_manager().networks_client
+        isolated_creds = getattr(cls, 'isolated_creds', None)
+        if credentials.is_admin_available():
+            admin_creds = isolated_creds.get_admin_creds()
+            networks_client = clients.Manager(admin_creds).networks_client
+        return fixed_network.get_tenant_network(isolated_creds,
+                                                networks_client)
+
     def assertEmpty(self, list, msg=None):
         self.assertTrue(len(list) == 0, msg)