Merge "Rearrange hypervisors response schemas into one file"
diff --git a/requirements.txt b/requirements.txt
index 35b5144..bf7471e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -12,7 +12,6 @@
 python-glanceclient>=0.15.0
 python-cinderclient>=1.1.0
 python-heatclient>=0.3.0
-python-saharaclient>=0.8.0
 python-swiftclient>=2.2.0
 testrepository>=0.0.18
 oslo.concurrency>=1.8.0,<1.9.0         # Apache-2.0
diff --git a/tempest/api/network/admin/test_l3_agent_scheduler.py b/tempest/api/network/admin/test_l3_agent_scheduler.py
index cf0b5e3..fca57c6 100644
--- a/tempest/api/network/admin/test_l3_agent_scheduler.py
+++ b/tempest/api/network/admin/test_l3_agent_scheduler.py
@@ -65,6 +65,21 @@
             msg = "L3 Agent Scheduler enabled in conf, but L3 Agent not found"
             raise exceptions.InvalidConfiguration(msg)
         cls.router = cls.create_router(data_utils.rand_name('router'))
+        # NOTE(armax): If DVR is an available extension, and the created router
+        # is indeed a distributed one, more resources need to be provisioned
+        # in order to bind the router to the L3 agent.
+        # That said, let's preserve the existing test logic, where the extra
+        # query and setup steps are only required if the extension is available
+        # and only if the router's default type is distributed.
+        if test.is_extension_enabled('dvr', 'network'):
+            is_dvr_router = cls.admin_client.show_router(
+                cls.router['id'])['router'].get('distributed', False)
+            if is_dvr_router:
+                cls.network = cls.create_network()
+                cls.create_subnet(cls.network)
+                cls.port = cls.create_port(cls.network)
+                cls.client.add_router_interface_with_port_id(
+                    cls.router['id'], cls.port['id'])
 
     @test.attr(type='smoke')
     @test.idempotent_id('b7ce6e89-e837-4ded-9b78-9ed3c9c6a45a')
diff --git a/tempest/cli/simple_read_only/data_processing/__init__.py b/tempest/cli/simple_read_only/data_processing/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/cli/simple_read_only/data_processing/__init__.py
+++ /dev/null
diff --git a/tempest/cli/simple_read_only/data_processing/test_sahara.py b/tempest/cli/simple_read_only/data_processing/test_sahara.py
deleted file mode 100644
index 153dbd2..0000000
--- a/tempest/cli/simple_read_only/data_processing/test_sahara.py
+++ /dev/null
@@ -1,191 +0,0 @@
-# Copyright (c) 2013 Mirantis Inc.
-#
-# 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 logging
-import re
-
-from tempest_lib import exceptions
-import testtools
-
-from tempest import cli
-from tempest import config
-from tempest import test
-
-CONF = config.CONF
-
-LOG = logging.getLogger(__name__)
-
-
-class SimpleReadOnlySaharaClientTest(cli.ClientTestBase):
-    """Basic, read-only tests for Sahara CLI client.
-
-    Checks return values and output of read-only commands.
-    These tests do not presume any content, nor do they create
-    their own. They only verify the structure of output if present.
-    """
-
-    @classmethod
-    def resource_setup(cls):
-        if not CONF.service_available.sahara:
-            msg = "Skipping all Sahara cli tests because it is not available"
-            raise cls.skipException(msg)
-        super(SimpleReadOnlySaharaClientTest, cls).resource_setup()
-
-    def sahara(self, *args, **kwargs):
-        return self.clients.sahara(
-            *args, endpoint_type=CONF.data_processing.endpoint_type, **kwargs)
-
-    @test.attr(type='negative')
-    @test.idempotent_id('c8809259-710f-43f9-b452-54b2be3115a9')
-    def test_sahara_fake_action(self):
-        self.assertRaises(exceptions.CommandFailed,
-                          self.sahara,
-                          'this-does-not-exist')
-
-    @test.idempotent_id('39afe90c-0fd8-456e-89e2-da6de9680fff')
-    def test_sahara_plugins_list(self):
-        plugins = self.parser.listing(self.sahara('plugin-list'))
-        self.assertTableStruct(plugins, [
-            'name',
-            'versions',
-            'title'
-        ])
-
-    @test.idempotent_id('3eb36fd8-bb06-4004-9e90-84ddf4dbcf5b')
-    @testtools.skipUnless(CONF.data_processing_feature_enabled.plugins,
-                          'No plugins defined')
-    def test_sahara_plugins_show(self):
-        name_param = '--name %s' % \
-            (CONF.data_processing_feature_enabled.plugins[0])
-        result = self.sahara('plugin-show', params=name_param)
-        plugin = self.parser.listing(result)
-        self.assertTableStruct(plugin, [
-            'Property',
-            'Value'
-        ])
-
-    @test.idempotent_id('502b684b-3d41-4619-aa6c-4db3465ae79d')
-    def test_sahara_node_group_template_list(self):
-        result = self.sahara('node-group-template-list')
-        node_group_templates = self.parser.listing(result)
-        self.assertTableStruct(node_group_templates, [
-            'name',
-            'id',
-            'plugin_name',
-            'node_processes',
-            'description'
-        ])
-
-    @test.idempotent_id('6c36fe4d-3b88-4b0d-b702-2a051db7dae7')
-    def test_sahara_cluster_template_list(self):
-        result = self.sahara('cluster-template-list')
-        cluster_templates = self.parser.listing(result)
-        self.assertTableStruct(cluster_templates, [
-            'name',
-            'id',
-            'plugin_name',
-            'node_groups',
-            'description'
-        ])
-
-    @test.idempotent_id('b951949d-b9a6-49db-add5-8a18ac533810')
-    def test_sahara_cluster_list(self):
-        result = self.sahara('cluster-list')
-        clusters = self.parser.listing(result)
-        self.assertTableStruct(clusters, [
-            'name',
-            'id',
-            'status',
-            'node_count'
-        ])
-
-    @test.idempotent_id('dbc83a8c-15b6-4aa8-b274-5896577397e1')
-    def test_sahara_data_source_list(self):
-        result = self.sahara('data-source-list')
-        data_sources = self.parser.listing(result)
-        self.assertTableStruct(data_sources, [
-            'name',
-            'id',
-            'type',
-            'description'
-        ])
-
-    @test.idempotent_id('a8f77e05-d4bf-45c3-8245-57835d0de37b')
-    def test_sahara_job_binary_data_list(self):
-        result = self.sahara('job-binary-data-list')
-        job_binary_data_list = self.parser.listing(result)
-        self.assertTableStruct(job_binary_data_list, [
-            'id',
-            'name'
-        ])
-
-    @test.idempotent_id('a8f4d0f3-fa1c-49ce-b73f-d624d89dc381')
-    def test_sahara_job_binary_list(self):
-        result = self.sahara('job-binary-list')
-        job_binaries = self.parser.listing(result)
-        self.assertTableStruct(job_binaries, [
-            'id',
-            'name',
-            'description'
-        ])
-
-    @test.idempotent_id('91164ca4-d049-49e0-a52a-686b408196ff')
-    def test_sahara_job_template_list(self):
-        result = self.sahara('job-template-list')
-        job_templates = self.parser.listing(result)
-        self.assertTableStruct(job_templates, [
-            'id',
-            'name',
-            'description'
-        ])
-
-    @test.idempotent_id('6829c251-a8b6-449d-af86-7dd98b69a7ce')
-    def test_sahara_job_list(self):
-        result = self.sahara('job-list')
-        jobs = self.parser.listing(result)
-        self.assertTableStruct(jobs, [
-            'id',
-            'cluster_id',
-            'status'
-        ])
-
-    @test.idempotent_id('e4bd5d3b-474b-4b7a-82ab-f6bb0bc89faf')
-    def test_sahara_bash_completion(self):
-        self.sahara('bash-completion')
-
-    # Optional arguments
-    @test.idempotent_id('699c14e5-632e-46b8-91e5-6bff8c8307e5')
-    def test_sahara_help(self):
-        help_text = self.sahara('help')
-        lines = help_text.split('\n')
-        self.assertFirstLineStartsWith(lines, 'usage: sahara')
-
-        commands = []
-        cmds_start = lines.index('Positional arguments:')
-        cmds_end = lines.index('Optional arguments:')
-        command_pattern = re.compile('^ {4}([a-z0-9\-\_]+)')
-        for line in lines[cmds_start:cmds_end]:
-            match = command_pattern.match(line)
-            if match:
-                commands.append(match.group(1))
-        commands = set(commands)
-        wanted_commands = set(('cluster-create', 'data-source-create',
-                               'image-unregister', 'job-binary-create',
-                               'plugin-list', 'job-binary-create', 'help'))
-        self.assertFalse(wanted_commands - commands)
-
-    @test.idempotent_id('84a18ea6-6379-4024-af6b-0e938f60dfc2')
-    def test_sahara_version(self):
-        version = self.sahara('', flags='--version')
-        self.assertTrue(re.search('[0-9.]+', version))
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index c945a46..fec3bd4 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -86,6 +86,7 @@
       owner: javelin
       flavor: m1.small
       image: javelin_cirros
+      floating_ip_pool: public
     - name: hoplite
       owner: javelin
       flavor: m1.medium
@@ -859,7 +860,9 @@
         for secgroup in server['secgroups']:
             client.servers.add_security_group(server_id, secgroup)
         if CONF.compute.use_floatingip_for_ssh:
-            floating_ip = client.floating_ips.create_floating_ip()
+            floating_ip_pool = server.get('floating_ip_pool')
+            floating_ip = client.floating_ips.create_floating_ip(
+                pool_name=floating_ip_pool)
             client.floating_ips.associate_floating_ip_to_server(
                 floating_ip['ip'], server_id)
 
diff --git a/tempest/common/cred_provider.py b/tempest/common/cred_provider.py
index 9630d1c..2c6763d 100644
--- a/tempest/common/cred_provider.py
+++ b/tempest/common/cred_provider.py
@@ -147,3 +147,25 @@
     @abc.abstractmethod
     def is_role_available(self, role):
         return
+
+
+class TestResources(object):
+    """Readonly Credentials, with network resources added."""
+
+    def __init__(self, credentials):
+        self._credentials = credentials
+        self.network = None
+        self.subnet = None
+        self.router = None
+
+    def __getattr__(self, item):
+        return getattr(self._credentials, item)
+
+    def set_resources(self, **kwargs):
+        for key in kwargs.keys():
+            if hasattr(self, key):
+                setattr(self, key, kwargs[key])
+
+    @property
+    def credentials(self):
+        return self._credentials
diff --git a/tempest/common/fixed_network.py b/tempest/common/fixed_network.py
index b533898..67fbab1 100644
--- a/tempest/common/fixed_network.py
+++ b/tempest/common/fixed_network.py
@@ -42,7 +42,8 @@
     if (isinstance(creds_provider, isolated_creds.IsolatedCreds) and
         (CONF.service_available.neutron and
          not CONF.service_available.ironic)):
-        network = creds_provider.get_primary_network()
+        # tenant_allow_isolation == True, so network is defined
+        network = creds_provider.get_primary_creds().network
     else:
         if fixed_network_name:
             try:
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 22fc9c3..1f85872 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -142,7 +142,6 @@
                                             network_resources)
         self.network_resources = network_resources
         self.isolated_creds = {}
-        self.isolated_net_resources = {}
         self.ports = []
         self.password = password
         self.default_admin_creds = cred_provider.get_configured_credentials(
@@ -207,7 +206,8 @@
         if roles:
             for role in roles:
                 self.creds_client.assign_user_role(user, project, role)
-        return self.creds_client.get_credentials(user, project, self.password)
+        creds = self.creds_client.get_credentials(user, project, self.password)
+        return cred_provider.TestResources(creds)
 
     def _create_network_resources(self, tenant_id):
         network = None
@@ -297,33 +297,6 @@
         self.network_admin_client.add_router_interface_with_subnet_id(
             router_id, subnet_id)
 
-    def get_primary_network(self):
-        return self.isolated_net_resources.get('primary')[0]
-
-    def get_primary_subnet(self):
-        return self.isolated_net_resources.get('primary')[1]
-
-    def get_primary_router(self):
-        return self.isolated_net_resources.get('primary')[2]
-
-    def get_admin_network(self):
-        return self.isolated_net_resources.get('admin')[0]
-
-    def get_admin_subnet(self):
-        return self.isolated_net_resources.get('admin')[1]
-
-    def get_admin_router(self):
-        return self.isolated_net_resources.get('admin')[2]
-
-    def get_alt_network(self):
-        return self.isolated_net_resources.get('alt')[0]
-
-    def get_alt_subnet(self):
-        return self.isolated_net_resources.get('alt')[1]
-
-    def get_alt_router(self):
-        return self.isolated_net_resources.get('alt')[2]
-
     def get_credentials(self, credential_type):
         if self.isolated_creds.get(str(credential_type)):
             credentials = self.isolated_creds[str(credential_type)]
@@ -341,8 +314,8 @@
                 not CONF.baremetal.driver_enabled):
                 network, subnet, router = self._create_network_resources(
                     credentials.tenant_id)
-                self.isolated_net_resources[str(credential_type)] = (
-                    network, subnet, router,)
+                credentials.set_resources(network=network, subnet=subnet,
+                                          router=router)
                 LOG.info("Created isolated network resources for : \n"
                          + " credentials: %s" % credentials)
         return credentials
@@ -368,12 +341,6 @@
             new_index = str(roles) + '-' + str(len(self.isolated_creds))
             self.isolated_creds[new_index] = exist_creds
             del self.isolated_creds[str(roles)]
-            # Handle isolated neutron resouces if they exist too
-            if CONF.service_available.neutron:
-                exist_net = self.isolated_net_resources.get(str(roles))
-                if exist_net:
-                    self.isolated_net_resources[new_index] = exist_net
-                    del self.isolated_net_resources[str(roles)]
         return self.get_credentials(roles)
 
     def _clear_isolated_router(self, router_id, router_name):
@@ -414,27 +381,33 @@
 
     def _clear_isolated_net_resources(self):
         net_client = self.network_admin_client
-        for cred in self.isolated_net_resources:
-            network, subnet, router = self.isolated_net_resources.get(cred)
+        for cred in self.isolated_creds:
+            creds = self.isolated_creds.get(cred)
+            if (not creds or not any([creds.router, creds.network,
+                                      creds.subnet])):
+                continue
             LOG.debug("Clearing network: %(network)s, "
                       "subnet: %(subnet)s, router: %(router)s",
-                      {'network': network, 'subnet': subnet, 'router': router})
+                      {'network': creds.network, 'subnet': creds.subnet,
+                       'router': creds.router})
             if (not self.network_resources or
-                self.network_resources.get('router')):
+                    (self.network_resources.get('router') and creds.subnet)):
                 try:
                     net_client.remove_router_interface_with_subnet_id(
-                        router['id'], subnet['id'])
+                        creds.router['id'], creds.subnet['id'])
                 except lib_exc.NotFound:
                     LOG.warn('router with name: %s not found for delete' %
-                             router['name'])
-                self._clear_isolated_router(router['id'], router['name'])
+                             creds.router['name'])
+                self._clear_isolated_router(creds.router['id'],
+                                            creds.router['name'])
             if (not self.network_resources or
                 self.network_resources.get('subnet')):
-                self._clear_isolated_subnet(subnet['id'], subnet['name'])
+                self._clear_isolated_subnet(creds.subnet['id'],
+                                            creds.subnet['name'])
             if (not self.network_resources or
                 self.network_resources.get('network')):
-                self._clear_isolated_network(network['id'], network['name'])
-        self.isolated_net_resources = {}
+                self._clear_isolated_network(creds.network['id'],
+                                             creds.network['name'])
 
     def clear_isolated_creds(self):
         if not self.isolated_creds:
diff --git a/tempest/manager.py b/tempest/manager.py
index a256f25..025ce65 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -46,8 +46,14 @@
         # Check if passed or default credentials are valid
         if not self.credentials.is_valid():
             raise exceptions.InvalidCredentials()
+        # Tenant isolation creates TestResources, but Accounts and some tests
+        # creates Credentials
+        if isinstance(credentials, cred_provider.TestResources):
+            creds = self.credentials.credentials
+        else:
+            creds = self.credentials
         # Creates an auth provider for the credentials
-        self.auth_provider = get_auth_provider(self.credentials)
+        self.auth_provider = get_auth_provider(creds)
         # FIXME(andreaf) unused
         self.client_attr_names = []
 
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 4fab38b..1ecc212 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -125,6 +125,10 @@
         if CONF.baremetal.driver_enabled:
             msg = ('Not currently supported by baremetal.')
             raise cls.skipException(msg)
+        if CONF.network.port_vnic_type in ['direct', 'macvtap']:
+            msg = ('Not currently supported when using vnic_type'
+                   ' direct or macvtap')
+            raise cls.skipException(msg)
         if not (CONF.network.tenant_networks_reachable or
                 CONF.network.public_network_id):
             msg = ('Either tenant_networks_reachable must be "true", or '
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 8fa2df5..5bc24ea 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -41,6 +41,8 @@
         super(TestVolumeBootPattern, cls).skip_checks()
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder volume snapshots are disabled")
+        if CONF.volume.storage_protocol == 'ceph':
+            raise cls.skipException('Skip until bug 1439371 is fixed.')
 
     def _create_volume_from_image(self):
         img_uuid = CONF.compute.image_ref
diff --git a/tempest/test.py b/tempest/test.py
index da936b4..2585999 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -445,7 +445,12 @@
         # 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():
+        # In case of nova network, isolated tenants are not able to list the
+        # network configured in fixed_network_name, even if the can use it
+        # for their servers, so using an admin network client to validate
+        # the network name
+        if (not CONF.service_available.neutron and
+                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,
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py
index 82cbde9..fd8718f 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/test_tenant_isolation.py
@@ -278,11 +278,11 @@
         router_interface_mock = self.patch(
             'tempest.services.network.json.network_client.NetworkClientJSON.'
             'add_router_interface_with_subnet_id')
-        iso_creds.get_primary_creds()
+        primary_creds = iso_creds.get_primary_creds()
         router_interface_mock.called_once_with('1234', '1234')
-        network = iso_creds.get_primary_network()
-        subnet = iso_creds.get_primary_subnet()
-        router = iso_creds.get_primary_router()
+        network = primary_creds.network
+        subnet = primary_creds.subnet
+        router = primary_creds.router
         self.assertEqual(network['id'], '1234')
         self.assertEqual(network['name'], 'fake_net')
         self.assertEqual(subnet['id'], '1234')
@@ -427,11 +427,11 @@
         router_interface_mock = self.patch(
             'tempest.services.network.json.network_client.NetworkClientJSON.'
             'add_router_interface_with_subnet_id')
-        iso_creds.get_alt_creds()
+        alt_creds = iso_creds.get_alt_creds()
         router_interface_mock.called_once_with('1234', '1234')
-        network = iso_creds.get_alt_network()
-        subnet = iso_creds.get_alt_subnet()
-        router = iso_creds.get_alt_router()
+        network = alt_creds.network
+        subnet = alt_creds.subnet
+        router = alt_creds.router
         self.assertEqual(network['id'], '1234')
         self.assertEqual(network['name'], 'fake_alt_net')
         self.assertEqual(subnet['id'], '1234')
@@ -453,11 +453,11 @@
             'tempest.services.network.json.network_client.NetworkClientJSON.'
             'add_router_interface_with_subnet_id')
         self._mock_list_roles('123456', 'admin')
-        iso_creds.get_admin_creds()
+        admin_creds = iso_creds.get_admin_creds()
         router_interface_mock.called_once_with('1234', '1234')
-        network = iso_creds.get_admin_network()
-        subnet = iso_creds.get_admin_subnet()
-        router = iso_creds.get_admin_router()
+        network = admin_creds.network
+        subnet = admin_creds.subnet
+        router = admin_creds.router
         self.assertEqual(network['id'], '1234')
         self.assertEqual(network['name'], 'fake_admin_net')
         self.assertEqual(subnet['id'], '1234')
@@ -490,13 +490,13 @@
                                    'delete_router')
         router_mock = router.start()
 
-        iso_creds.get_primary_creds()
+        primary_creds = iso_creds.get_primary_creds()
         self.assertEqual(net_mock.mock_calls, [])
         self.assertEqual(subnet_mock.mock_calls, [])
         self.assertEqual(router_mock.mock_calls, [])
-        network = iso_creds.get_primary_network()
-        subnet = iso_creds.get_primary_subnet()
-        router = iso_creds.get_primary_router()
+        network = primary_creds.network
+        subnet = primary_creds.subnet
+        router = primary_creds.router
         self.assertIsNone(network)
         self.assertIsNone(subnet)
         self.assertIsNone(router)