Merge "Apply a list_image_members rule of GET to image client"
diff --git a/.testr.conf b/.testr.conf
index 4f6e0b3..95a4fb4 100644
--- a/.testr.conf
+++ b/.testr.conf
@@ -3,7 +3,7 @@
              OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
              OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-500} \
              OS_TEST_LOCK_PATH=${OS_TEST_LOCK_PATH:-${TMPDIR:-'/tmp'}} \
-             ${PYTHON:-python} -m subunit.run discover -t ./ ${OS_TEST_PATH:-./tempest/test_discover} $LISTOPT $IDOPTION
+             ${PYTHON:-python} -m subunit.run discover -t ${OS_TOP_LEVEL:-./} ${OS_TEST_PATH:-./tempest/test_discover} $LISTOPT $IDOPTION
 test_id_option=--load-list $IDFILE
 test_list_option=--list
 group_regex=([^\.]*\.)*
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index b434fdc..eab7487 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -310,6 +310,12 @@
 will additionally be used as a fallback for server creation. However, unlike
 accounts.yaml this should never be triggered.
 
+However, there is an option *create_isolated_networks* to disable tenant
+isolation's automatic provisioning of network resources. If this option is
+used you will have to either rely on there only being a single/default network
+available for the server creation, or use *fixed_network_name* to inform
+Tempest which network to use.
+
 Configuring Available Services
 ------------------------------
 OpenStack is really a constellation of several different projects which
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 5b15c5e..b3aca42 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -40,13 +40,15 @@
 #log_dir = <None>
 
 # Use syslog for logging. Existing syslog format is DEPRECATED during
-# I, and will change in J to honor RFC5424. (boolean value)
+# I, and changed in J to honor RFC5424. (boolean value)
 #use_syslog = false
 
 # (Optional) Enables or disables syslog rfc5424 format for logging. If
 # enabled, prefixes the MSG part of the syslog message with APP-NAME
 # (RFC5424). The format without the APP-NAME is deprecated in K, and
-# will be removed in L, along with this option. (boolean value)
+# will be removed in M, along with this option. (boolean value)
+# This option is deprecated for removal.
+# Its value may be silently ignored in the future.
 #use_syslog_rfc_format = true
 
 # Syslog facility to receive log lines. (string value)
@@ -67,7 +69,7 @@
 
 # Prefix each line of exception output with this format. (string
 # value)
-#logging_exception_prefix = %(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s
+#logging_exception_prefix = %(asctime)s.%(msecs)03d %(process)d ERROR %(name)s %(instance)s
 
 # List of logger=LEVEL pairs. (list value)
 #default_log_levels = amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN,websocket=WARN,requests.packages.urllib3.util.retry=WARN,urllib3.util.retry=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=WARN
@@ -86,6 +88,9 @@
 # (string value)
 #instance_uuid_format = "[instance: %(uuid)s] "
 
+# Enables or disables fatal status of deprecations. (boolean value)
+#fatal_deprecations = false
+
 
 [auth]
 
@@ -117,6 +122,14 @@
 # the domain from theadmin user is used instead. (string value)
 #tenant_isolation_domain_name = <None>
 
+# If allow_tenant_isolation is set to True and Neutron is enabled
+# Tempest will try to create a useable network, subnet, and router
+# when needed for each tenant it  creates. However in some neutron
+# configurations, like with VLAN provider networks, this doesn't work.
+# So if set to False the isolated networks will not be created
+# (boolean value)
+#create_isolated_networks = true
+
 
 [baremetal]
 
@@ -571,6 +584,9 @@
 # applies to user and project (string value)
 #admin_domain_name = <None>
 
+# ID of the default domain (string value)
+#default_domain_id = default
+
 
 [identity-feature-enabled]
 
@@ -935,6 +951,10 @@
 # Image container format (string value)
 #img_container_format = bare
 
+# Glance image properties. Use for custom images which require them
+# (dict value)
+#img_properties = <None>
+
 # AMI image file name (string value)
 #ami_img_file = cirros-0.3.1-x86_64-blank.img
 
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 16115fb..d7607ab 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -275,8 +275,14 @@
             msg = 'fixed_network_name needs to be configured to run this test'
             raise self.skipException(msg)
         self.s1 = self.client.get_server(self.s1['id'])
-        ip = self.s1['addresses'][self.fixed_network_name][0]['addr']
-        params = {'ip': ip}
+        for addr_spec in self.s1['addresses'][self.fixed_network_name]:
+            ip = addr_spec['addr']
+            if addr_spec['version'] == 4:
+                params = {'ip': ip}
+                break
+        else:
+            msg = "Skipped until bug 1450859 is resolved"
+            raise self.skipException(msg)
         body = self.client.list_servers(params)
         servers = body['servers']
 
@@ -295,8 +301,12 @@
             msg = 'fixed_network_name needs to be configured to run this test'
             raise self.skipException(msg)
         self.s1 = self.client.get_server(self.s1['id'])
-        ip = self.s1['addresses'][self.fixed_network_name][0]['addr'][0:-3]
-        params = {'ip': ip}
+        addr_spec = self.s1['addresses'][self.fixed_network_name][0]
+        ip = addr_spec['addr'][0:-3]
+        if addr_spec['version'] == 4:
+            params = {'ip': ip}
+        else:
+            params = {'ip6': ip}
         body = self.client.list_servers(params)
         servers = body['servers']
 
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index eed3be8..11b457b 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -30,7 +30,9 @@
         This is the right way to create_multiple servers and manage to get the
         created servers into the servers list to be cleaned up after all.
         """
-        kwargs['name'] = kwargs.get('name', self._generate_name())
+        kwargs['name'] = name if name else self._generate_name()
+        if wait_until:
+            kwargs['wait_until'] = wait_until
         body = self.create_test_server(**kwargs)
 
         return body
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index c4cabaa..c2ed0ce 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -47,8 +47,6 @@
             self.__class__.server_id = self.rebuild_server(self.server_id)
 
     def tearDown(self):
-        server = self.client.get_server(self.server_id)
-        self.assertEqual(self.image_ref, server['image']['id'])
         self.server_check_teardown()
         super(ServerActionsTestJSON, self).tearDown()
 
@@ -110,6 +108,14 @@
         # The server should be signaled to reboot gracefully
         self._test_reboot_server('SOFT')
 
+    def _rebuild_server_and_check(self, image_ref):
+        rebuilt_server = self.client.rebuild(self.server_id, image_ref)
+        self.client.wait_for_server_status(self.server_id, 'ACTIVE')
+        msg = ('Server was not rebuilt to the original image. '
+               'The original image: {0}. The current image: {1}'
+               .format(image_ref, rebuilt_server['image']['id']))
+        self.assertEqual(image_ref, rebuilt_server['image']['id'], msg)
+
     @test.idempotent_id('aaa6cdf3-55a7-461a-add9-1c8596b9a07c')
     def test_rebuild_server(self):
         # The server should be rebuilt using the provided image and data
@@ -129,8 +135,7 @@
         # If the server was rebuilt on a different image, restore it to the
         # original image once the test ends
         if self.image_ref_alt != self.image_ref:
-            self.addCleanup(self.client.rebuild,
-                            (self.server_id, self.image_ref))
+            self.addCleanup(self._rebuild_server_and_check, self.image_ref)
 
         # Verify the properties in the initial response are correct
         self.assertEqual(self.server_id, rebuilt_server['id'])
@@ -157,11 +162,15 @@
         # image and remain in SHUTOFF state
         server = self.client.get_server(self.server_id)
         old_image = server['image']['id']
-        new_image = self.image_ref_alt \
-            if old_image == self.image_ref else self.image_ref
+        new_image = (self.image_ref_alt
+                     if old_image == self.image_ref else self.image_ref)
         self.client.stop(self.server_id)
         self.client.wait_for_server_status(self.server_id, 'SHUTOFF')
         rebuilt_server = self.client.rebuild(self.server_id, new_image)
+        # If the server was rebuilt on a different image, restore it to the
+        # original image once the test ends
+        if self.image_ref_alt != self.image_ref:
+            self.addCleanup(self._rebuild_server_and_check, old_image)
 
         # Verify the properties in the initial response are correct
         self.assertEqual(self.server_id, rebuilt_server['id'])
@@ -175,10 +184,6 @@
         rebuilt_image_id = server['image']['id']
         self.assertEqual(new_image, rebuilt_image_id)
 
-        # Restore to the original image (The tearDown will test it again)
-        if self.image_ref_alt != self.image_ref:
-            self.client.rebuild(self.server_id, old_image)
-            self.client.wait_for_server_status(self.server_id, 'SHUTOFF')
         self.client.start(self.server_id)
 
     def _test_resize_server_confirm(self, stop=False):
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index 79943bb..b775e91 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -13,10 +13,13 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest.api.identity import base
+from tempest import config
+from tempest import test
+
 from tempest_lib.common.utils import data_utils
 
-from tempest.api.identity import base
-from tempest import test
+CONF = config.CONF
 
 
 class DomainsTestJSON(base.BaseIdentityV3AdminTest):
@@ -105,3 +108,18 @@
         expected_data = {'name': d_name, 'enabled': True}
         self.assertIsNone(domain['description'])
         self.assertDictContainsSubset(expected_data, domain)
+
+
+class DefaultDomainTestJSON(base.BaseIdentityV3AdminTest):
+
+    @classmethod
+    def resource_setup(cls):
+        cls.domain_id = CONF.identity.default_domain_id
+        super(DefaultDomainTestJSON, cls).resource_setup()
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('17a5de24-e6a0-4e4a-a9ee-d85b6e5612b5')
+    def test_default_domain_exists(self):
+        domain = self.client.get_domain(self.domain_id)
+
+        self.assertTrue(domain['enabled'])
diff --git a/tempest/api/identity/admin/v3/test_domains_negative.py b/tempest/api/identity/admin/v3/test_domains_negative.py
new file mode 100644
index 0000000..e2f3ef5
--- /dev/null
+++ b/tempest/api/identity/admin/v3/test_domains_negative.py
@@ -0,0 +1,38 @@
+# Copyright 2015 Red Hat Inc.
+# All Rights Reserved.
+#
+#    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.
+
+from tempest.api.identity import base
+from tempest import test
+
+from tempest_lib.common.utils import data_utils
+from tempest_lib import exceptions as lib_exc
+
+
+class DomainsNegativeTestJSON(base.BaseIdentityV3AdminTest):
+    _interface = 'json'
+
+    @test.attr(type=['negative', 'gate'])
+    @test.idempotent_id('1f3fbff5-4e44-400d-9ca1-d953f05f609b')
+    def test_delete_active_domain(self):
+        d_name = data_utils.rand_name('domain')
+        d_desc = data_utils.rand_name('domain-desc')
+        domain = self.client.create_domain(d_name, description=d_desc)
+        domain_id = domain['id']
+
+        self.addCleanup(self.delete_domain, domain_id)
+
+        # domain need to be disabled before deleting
+        self.assertRaises(lib_exc.Forbidden, self.client.delete_domain,
+                          domain_id)
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 878ff6d..913e807 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -172,6 +172,12 @@
         if len(role) > 0:
             return role[0]
 
+    def delete_domain(self, domain_id):
+        # NOTE(mpavlase) It is necessary to disable the domain before deleting
+        # otherwise it raises Forbidden exception
+        self.client.update_domain(domain_id, enabled=False)
+        self.client.delete_domain(domain_id)
+
 
 class DataGenerator(object):
 
diff --git a/tempest/api_schema/response/compute/baremetal_nodes.py b/tempest/api_schema/response/compute/v2_1/baremetal_nodes.py
similarity index 100%
rename from tempest/api_schema/response/compute/baremetal_nodes.py
rename to tempest/api_schema/response/compute/v2_1/baremetal_nodes.py
diff --git a/tempest/api_schema/response/compute/v2_1/flavors.py b/tempest/api_schema/response/compute/v2_1/flavors.py
index 725d17a..26760ac 100644
--- a/tempest/api_schema/response/compute/v2_1/flavors.py
+++ b/tempest/api_schema/response/compute/v2_1/flavors.py
@@ -12,7 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.api_schema.response.compute import parameter_types
+from tempest.api_schema.response.compute.v2_1 import parameter_types
 
 list_flavors = {
     'status_code': [200],
diff --git a/tempest/api_schema/response/compute/flavors_access.py b/tempest/api_schema/response/compute/v2_1/flavors_access.py
similarity index 100%
rename from tempest/api_schema/response/compute/flavors_access.py
rename to tempest/api_schema/response/compute/v2_1/flavors_access.py
diff --git a/tempest/api_schema/response/compute/flavors_extra_specs.py b/tempest/api_schema/response/compute/v2_1/flavors_extra_specs.py
similarity index 94%
rename from tempest/api_schema/response/compute/flavors_extra_specs.py
rename to tempest/api_schema/response/compute/v2_1/flavors_extra_specs.py
index 4003d36..faa25d0 100644
--- a/tempest/api_schema/response/compute/flavors_extra_specs.py
+++ b/tempest/api_schema/response/compute/v2_1/flavors_extra_specs.py
@@ -12,7 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-flavor_extra_specs = {
+set_get_flavor_extra_specs = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
@@ -28,7 +28,7 @@
     }
 }
 
-flavor_extra_specs_key = {
+set_get_flavor_extra_specs_key = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
diff --git a/tempest/api_schema/response/compute/v2_1/floating_ips.py b/tempest/api_schema/response/compute/v2_1/floating_ips.py
index 7369bec..ad1c531 100644
--- a/tempest/api_schema/response/compute/v2_1/floating_ips.py
+++ b/tempest/api_schema/response/compute/v2_1/floating_ips.py
@@ -48,7 +48,7 @@
     }
 }
 
-floating_ip = {
+create_get_floating_ip = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
@@ -59,7 +59,7 @@
     }
 }
 
-floating_ip_pools = {
+list_floating_ip_pools = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
diff --git a/tempest/api_schema/response/compute/v2_1/images.py b/tempest/api_schema/response/compute/v2_1/images.py
index 3c0b80e..e6f8db6 100644
--- a/tempest/api_schema/response/compute/v2_1/images.py
+++ b/tempest/api_schema/response/compute/v2_1/images.py
@@ -14,7 +14,7 @@
 
 import copy
 
-from tempest.api_schema.response.compute import parameter_types
+from tempest.api_schema.response.compute.v2_1 import parameter_types
 
 image_links = copy.deepcopy(parameter_types.links)
 image_links['items']['properties'].update({'type': {'type': 'string'}})
diff --git a/tempest/api_schema/response/compute/v2_1/interfaces.py b/tempest/api_schema/response/compute/v2_1/interfaces.py
index 4de3309..033f816 100644
--- a/tempest/api_schema/response/compute/v2_1/interfaces.py
+++ b/tempest/api_schema/response/compute/v2_1/interfaces.py
@@ -12,7 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.api_schema.response.compute import parameter_types
+from tempest.api_schema.response.compute.v2_1 import parameter_types
 
 interface_common_info = {
     'type': 'object',
diff --git a/tempest/api_schema/response/compute/migrations.py b/tempest/api_schema/response/compute/v2_1/migrations.py
similarity index 100%
rename from tempest/api_schema/response/compute/migrations.py
rename to tempest/api_schema/response/compute/v2_1/migrations.py
diff --git a/tempest/api_schema/response/compute/parameter_types.py b/tempest/api_schema/response/compute/v2_1/parameter_types.py
similarity index 100%
rename from tempest/api_schema/response/compute/parameter_types.py
rename to tempest/api_schema/response/compute/v2_1/parameter_types.py
diff --git a/tempest/api_schema/response/compute/v2_1/servers.py b/tempest/api_schema/response/compute/v2_1/servers.py
index 726f9b1..875f607 100644
--- a/tempest/api_schema/response/compute/v2_1/servers.py
+++ b/tempest/api_schema/response/compute/v2_1/servers.py
@@ -14,7 +14,7 @@
 
 import copy
 
-from tempest.api_schema.response.compute import parameter_types
+from tempest.api_schema.response.compute.v2_1 import parameter_types
 
 create_server = {
     'status_code': [202],
diff --git a/tempest/api_schema/response/compute/services.py b/tempest/api_schema/response/compute/v2_1/services.py
similarity index 100%
rename from tempest/api_schema/response/compute/services.py
rename to tempest/api_schema/response/compute/v2_1/services.py
diff --git a/tempest/api_schema/response/compute/v2_1/tenant_usages.py b/tempest/api_schema/response/compute/v2_1/tenant_usages.py
index 0b824a1..d51ef12 100644
--- a/tempest/api_schema/response/compute/v2_1/tenant_usages.py
+++ b/tempest/api_schema/response/compute/v2_1/tenant_usages.py
@@ -66,7 +66,7 @@
                                  'total_hours', 'total_local_gb_usage',
                                  'total_memory_mb_usage', 'total_vcpus_usage']
 
-list_tenant = {
+list_tenant_usage = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
@@ -80,7 +80,7 @@
     }
 }
 
-get_tenant = {
+get_tenant_usage = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
diff --git a/tempest/api_schema/response/compute/version.py b/tempest/api_schema/response/compute/v2_1/version.py
similarity index 100%
rename from tempest/api_schema/response/compute/version.py
rename to tempest/api_schema/response/compute/v2_1/version.py
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index fee1467..5ded3ee 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -311,7 +311,8 @@
             LOG.info("Acquired isolated creds:\n credentials: %s"
                      % credentials)
             if (CONF.service_available.neutron and
-                not CONF.baremetal.driver_enabled):
+                not CONF.baremetal.driver_enabled and
+                CONF.auth.create_isolated_networks):
                 network, subnet, router = self._create_network_resources(
                     credentials.tenant_id)
                 credentials.set_resources(network=network, subnet=subnet,
diff --git a/tempest/config.py b/tempest/config.py
index bdbf942..603ccd2 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -69,7 +69,15 @@
                help="Only applicable when identity.auth_version is v3."
                     "Domain within which isolated credentials are provisioned."
                     "The default \"None\" means that the domain from the"
-                    "admin user is used instead.")
+                    "admin user is used instead."),
+    cfg.BoolOpt('create_isolated_networks',
+                default=True,
+                help="If allow_tenant_isolation is set to True and Neutron is "
+                     "enabled Tempest will try to create a useable network, "
+                     "subnet, and router when needed for each tenant it  "
+                     "creates. However in some neutron configurations, like "
+                     "with VLAN provider networks, this doesn't work. So if "
+                     "set to False the isolated networks will not be created"),
 ]
 
 identity_group = cfg.OptGroup(name='identity',
@@ -142,6 +150,9 @@
     cfg.StrOpt('admin_domain_name',
                help="Admin domain name for authentication (Keystone V3)."
                     "The same domain applies to user and project"),
+    cfg.StrOpt('default_domain_id',
+               default='default',
+               help="ID of the default domain"),
 ]
 
 identity_feature_group = cfg.OptGroup(name='identity-feature-enabled',
@@ -947,6 +958,8 @@
     cfg.StrOpt('img_container_format',
                default='bare',
                help='Image container format'),
+    cfg.DictOpt('img_properties', help='Glance image properties. '
+                'Use for custom images which require them'),
     cfg.StrOpt('ami_img_file',
                default='cirros-0.3.1-x86_64-blank.img',
                help='AMI image file name'),
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index cfd5169..6ccd4d9 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -323,7 +323,8 @@
 
         return linux_client
 
-    def _image_create(self, name, fmt, path, properties=None):
+    def _image_create(self, name, fmt, path,
+                      disk_format=None, properties=None):
         if properties is None:
             properties = {}
         name = data_utils.rand_name('%s-' % name)
@@ -332,10 +333,10 @@
         params = {
             'name': name,
             'container_format': fmt,
-            'disk_format': fmt,
+            'disk_format': disk_format or fmt,
             'is_public': 'False',
         }
-        params.update(properties)
+        params['properties'] = properties
         image = self.image_client.create_image(**params)
         self.addCleanup(self.image_client.delete_image, image['id'])
         self.assertEqual("queued", image['status'])
@@ -349,23 +350,22 @@
         ami_img_path = CONF.scenario.img_dir + "/" + CONF.scenario.ami_img_file
         img_container_format = CONF.scenario.img_container_format
         img_disk_format = CONF.scenario.img_disk_format
+        img_properties = CONF.scenario.img_properties
         LOG.debug("paths: img: %s, container_fomat: %s, disk_format: %s, "
-                  "ami: %s, ari: %s, aki: %s" %
+                  "properties: %s, ami: %s, ari: %s, aki: %s" %
                   (img_path, img_container_format, img_disk_format,
-                   ami_img_path, ari_img_path, aki_img_path))
+                   img_properties, ami_img_path, ari_img_path, aki_img_path))
         try:
             self.image = self._image_create('scenario-img',
                                             img_container_format,
                                             img_path,
-                                            properties={'disk_format':
-                                                        img_disk_format})
+                                            disk_format=img_disk_format,
+                                            properties=img_properties)
         except IOError:
             LOG.debug("A qcow2 image was not found. Try to get a uec image.")
             kernel = self._image_create('scenario-aki', 'aki', aki_img_path)
             ramdisk = self._image_create('scenario-ari', 'ari', ari_img_path)
-            properties = {
-                'properties': {'kernel_id': kernel, 'ramdisk_id': ramdisk}
-            }
+            properties = {'kernel_id': kernel, 'ramdisk_id': ramdisk}
             self.image = self._image_create('scenario-ami', 'ami',
                                             path=ami_img_path,
                                             properties=properties)
@@ -413,9 +413,9 @@
         return snapshot_image
 
     def nova_volume_attach(self):
-        # TODO(andreaf) Device should be here CONF.compute.volume_device_name
         volume = self.servers_client.attach_volume(
-            self.server['id'], self.volume['id'], '/dev/vdb')
+            self.server['id'], self.volume['id'], '/dev/%s'
+            % CONF.compute.volume_device_name)
         self.assertEqual(self.volume['id'], volume['id'])
         self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
         # Refresh the volume after the attachment
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 53b471a..51c4c59 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -103,9 +103,9 @@
         return self.create_volume(snapshot_id=snapshot_id)
 
     def _attach_volume(self, server, volume):
-        # TODO(andreaf) we should use device from config instead if vdb
         attached_volume = self.servers_client.attach_volume(
-            server['id'], volume['id'], device='/dev/vdb')
+            server['id'], volume['id'], device='/dev/%s'
+            % CONF.compute.volume_device_name)
         self.assertEqual(volume['id'], attached_volume['id'])
         self._wait_for_volume_status(attached_volume, 'in-use')
 
@@ -119,7 +119,7 @@
         def _func():
             part = ssh.get_partitions()
             LOG.debug("Partitions:%s" % part)
-            return 'vdb' in part
+            return CONF.compute.volume_device_name in part
 
         if not tempest.test.call_until_true(_func,
                                             CONF.compute.build_timeout,
@@ -128,15 +128,18 @@
 
     def _create_timestamp(self, server_or_ip):
         ssh_client = self._ssh_to_server(server_or_ip)
-        ssh_client.exec_command('sudo /usr/sbin/mkfs.ext4 /dev/vdb')
-        ssh_client.exec_command('sudo mount /dev/vdb /mnt')
+        ssh_client.exec_command('sudo /usr/sbin/mkfs.ext4 /dev/%s'
+                                % CONF.compute.volume_device_name)
+        ssh_client.exec_command('sudo mount /dev/%s /mnt'
+                                % CONF.compute.volume_device_name)
         ssh_client.exec_command('sudo sh -c "date > /mnt/timestamp;sync"')
         self.timestamp = ssh_client.exec_command('sudo cat /mnt/timestamp')
         ssh_client.exec_command('sudo umount /mnt')
 
     def _check_timestamp(self, server_or_ip):
         ssh_client = self._ssh_to_server(server_or_ip)
-        ssh_client.exec_command('sudo mount /dev/vdb /mnt')
+        ssh_client.exec_command('sudo mount /dev/%s /mnt'
+                                % CONF.compute.volume_device_name)
         got_timestamp = ssh_client.exec_command('sudo cat /mnt/timestamp')
         self.assertEqual(self.timestamp, got_timestamp)
 
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 177697b..1731c48 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -41,8 +41,6 @@
         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/services/compute/json/baremetal_nodes_client.py b/tempest/services/compute/json/baremetal_nodes_client.py
index fa2d7f4..d8f13c4 100644
--- a/tempest/services/compute/json/baremetal_nodes_client.py
+++ b/tempest/services/compute/json/baremetal_nodes_client.py
@@ -16,7 +16,8 @@
 
 from six.moves.urllib import parse as urllib
 
-from tempest.api_schema.response.compute import baremetal_nodes as schema
+from tempest.api_schema.response.compute.v2_1 import baremetal_nodes \
+    as schema
 from tempest.common import service_client
 
 
diff --git a/tempest/services/compute/json/flavors_client.py b/tempest/services/compute/json/flavors_client.py
index 80cbe4d..7938d8e 100644
--- a/tempest/services/compute/json/flavors_client.py
+++ b/tempest/services/compute/json/flavors_client.py
@@ -17,10 +17,11 @@
 
 from six.moves.urllib import parse as urllib
 
-from tempest.api_schema.response.compute import flavors_access as schema_access
-from tempest.api_schema.response.compute import flavors_extra_specs \
-    as schema_extra_specs
 from tempest.api_schema.response.compute.v2_1 import flavors as schema
+from tempest.api_schema.response.compute.v2_1 import flavors_access \
+    as schema_access
+from tempest.api_schema.response.compute.v2_1 import flavors_extra_specs \
+    as schema_extra_specs
 from tempest.common import service_client
 
 
@@ -103,7 +104,7 @@
         resp, body = self.post('flavors/%s/os-extra_specs' % flavor_id,
                                post_body)
         body = json.loads(body)
-        self.validate_response(schema_extra_specs.flavor_extra_specs,
+        self.validate_response(schema_extra_specs.set_get_flavor_extra_specs,
                                resp, body)
         return service_client.ResponseBody(resp, body['extra_specs'])
 
@@ -111,7 +112,7 @@
         """Gets extra Specs details of the mentioned flavor."""
         resp, body = self.get('flavors/%s/os-extra_specs' % flavor_id)
         body = json.loads(body)
-        self.validate_response(schema_extra_specs.flavor_extra_specs,
+        self.validate_response(schema_extra_specs.set_get_flavor_extra_specs,
                                resp, body)
         return service_client.ResponseBody(resp, body['extra_specs'])
 
@@ -120,8 +121,9 @@
         resp, body = self.get('flavors/%s/os-extra_specs/%s' % (str(flavor_id),
                               key))
         body = json.loads(body)
-        self.validate_response(schema_extra_specs.flavor_extra_specs_key,
-                               resp, body)
+        self.validate_response(
+            schema_extra_specs.set_get_flavor_extra_specs_key,
+            resp, body)
         return service_client.ResponseBody(resp, body)
 
     def update_flavor_extra_spec(self, flavor_id, key, **kwargs):
@@ -129,8 +131,9 @@
         resp, body = self.put('flavors/%s/os-extra_specs/%s' %
                               (flavor_id, key), json.dumps(kwargs))
         body = json.loads(body)
-        self.validate_response(schema_extra_specs.flavor_extra_specs_key,
-                               resp, body)
+        self.validate_response(
+            schema_extra_specs.set_get_flavor_extra_specs_key,
+            resp, body)
         return service_client.ResponseBody(resp, body)
 
     def unset_flavor_extra_spec(self, flavor_id, key):
diff --git a/tempest/services/compute/json/floating_ips_client.py b/tempest/services/compute/json/floating_ips_client.py
index 9568a5e..f30bfdb 100644
--- a/tempest/services/compute/json/floating_ips_client.py
+++ b/tempest/services/compute/json/floating_ips_client.py
@@ -40,7 +40,7 @@
         url = "os-floating-ips/%s" % str(floating_ip_id)
         resp, body = self.get(url)
         body = json.loads(body)
-        self.validate_response(schema.floating_ip, resp, body)
+        self.validate_response(schema.create_get_floating_ip, resp, body)
         return service_client.ResponseBody(resp, body['floating_ip'])
 
     def create_floating_ip(self, pool_name=None):
@@ -50,7 +50,7 @@
         post_body = json.dumps(post_body)
         resp, body = self.post(url, post_body)
         body = json.loads(body)
-        self.validate_response(schema.floating_ip, resp, body)
+        self.validate_response(schema.create_get_floating_ip, resp, body)
         return service_client.ResponseBody(resp, body['floating_ip'])
 
     def delete_floating_ip(self, floating_ip_id):
@@ -108,7 +108,7 @@
 
         resp, body = self.get(url)
         body = json.loads(body)
-        self.validate_response(schema.floating_ip_pools, resp, body)
+        self.validate_response(schema.list_floating_ip_pools, resp, body)
         return service_client.ResponseBodyList(resp, body['floating_ip_pools'])
 
     def create_floating_ips_bulk(self, ip_range, pool, interface):
diff --git a/tempest/services/compute/json/migrations_client.py b/tempest/services/compute/json/migrations_client.py
index 009992c..f708a07 100644
--- a/tempest/services/compute/json/migrations_client.py
+++ b/tempest/services/compute/json/migrations_client.py
@@ -16,7 +16,7 @@
 
 from six.moves.urllib import parse as urllib
 
-from tempest.api_schema.response.compute import migrations as schema
+from tempest.api_schema.response.compute.v2_1 import migrations as schema
 from tempest.common import service_client
 
 
diff --git a/tempest/services/compute/json/services_client.py b/tempest/services/compute/json/services_client.py
index e2d959b..156ad8d 100644
--- a/tempest/services/compute/json/services_client.py
+++ b/tempest/services/compute/json/services_client.py
@@ -18,7 +18,7 @@
 
 from six.moves.urllib import parse as urllib
 
-from tempest.api_schema.response.compute import services as schema
+from tempest.api_schema.response.compute.v2_1 import services as schema
 from tempest.common import service_client
 
 
diff --git a/tempest/services/compute/json/tenant_usages_client.py b/tempest/services/compute/json/tenant_usages_client.py
index b7e2b2a..52f46e2 100644
--- a/tempest/services/compute/json/tenant_usages_client.py
+++ b/tempest/services/compute/json/tenant_usages_client.py
@@ -30,7 +30,7 @@
 
         resp, body = self.get(url)
         body = json.loads(body)
-        self.validate_response(schema.list_tenant, resp, body)
+        self.validate_response(schema.list_tenant_usage, resp, body)
         return service_client.ResponseBodyList(resp, body['tenant_usages'][0])
 
     def get_tenant_usage(self, tenant_id, params=None):
@@ -40,5 +40,5 @@
 
         resp, body = self.get(url)
         body = json.loads(body)
-        self.validate_response(schema.get_tenant, resp, body)
+        self.validate_response(schema.get_tenant_usage, resp, body)
         return service_client.ResponseBodyList(resp, body['tenant_usage'])
diff --git a/tempest/test.py b/tempest/test.py
index 675071b..0d709f6c 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -324,7 +324,7 @@
         if 'admin' in cls.credentials and not credentials.is_admin_available():
             msg = "Missing Identity Admin API credentials in configuration."
             raise cls.skipException(msg)
-        if 'alt' is cls.credentials and not credentials.is_alt_available():
+        if 'alt' in cls.credentials and not credentials.is_alt_available():
             msg = "Missing a 2nd set of API credentials in configuration."
             raise cls.skipException(msg)
         if hasattr(cls, 'identity_version'):
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py
index 47e6abd..72a63c3 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/test_tenant_isolation.py
@@ -268,6 +268,36 @@
         self.assertEqual(alt_creds.user_id, '1234')
 
     @mock.patch('tempest_lib.common.rest_client.RestClient')
+    def test_no_network_creation_with_config_set(self, MockRestClient):
+        cfg.CONF.set_default('create_isolated_networks', False, group='auth')
+        iso_creds = isolated_creds.IsolatedCreds(name='test class',
+                                                 password='fake_password')
+        self._mock_assign_user_role()
+        self._mock_list_role()
+        self._mock_user_create('1234', 'fake_prim_user')
+        self._mock_tenant_create('1234', 'fake_prim_tenant')
+        net = mock.patch.object(iso_creds.network_admin_client,
+                                'delete_network')
+        net_mock = net.start()
+        subnet = mock.patch.object(iso_creds.network_admin_client,
+                                   'delete_subnet')
+        subnet_mock = subnet.start()
+        router = mock.patch.object(iso_creds.network_admin_client,
+                                   'delete_router')
+        router_mock = router.start()
+
+        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 = primary_creds.network
+        subnet = primary_creds.subnet
+        router = primary_creds.router
+        self.assertIsNone(network)
+        self.assertIsNone(subnet)
+        self.assertIsNone(router)
+
+    @mock.patch('tempest_lib.common.rest_client.RestClient')
     def test_network_creation(self, MockRestClient):
         iso_creds = isolated_creds.IsolatedCreds(name='test class',
                                                  password='fake_password')
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index 19a77dc..b7f0e81 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -283,7 +283,17 @@
                                          CONF.compute.ssh_user,
                                          pkey=self.keypair.material)
         text = data_utils.rand_name("Pattern text for console output")
-        resp = ssh.write_to_console(text)
+        try:
+            resp = ssh.write_to_console(text)
+        except Exception:
+            if not CONF.compute_feature_enabled.console_output:
+                LOG.debug('Console output not supported, cannot log')
+            else:
+                console_output = instance.get_console_output().output
+                LOG.debug('Console output for %s\nbody=\n%s',
+                          instance.id, console_output)
+            raise
+
         self.assertFalse(resp)
 
         def _output():