Merge "Unskip test_rescope_token()"
diff --git a/tempest/api/orchestration/stacks/test_update.py b/tempest/api/orchestration/stacks/test_update.py
index 791a19b..98761ac 100644
--- a/tempest/api/orchestration/stacks/test_update.py
+++ b/tempest/api/orchestration/stacks/test_update.py
@@ -61,7 +61,6 @@
                          self.list_resources(stack_identifier))
 
     @test.attr(type='gate')
-    @test.skip_because(bug='1308682')
     def test_stack_update_add_remove(self):
         stack_name = data_utils.rand_name('heat')
         stack_identifier = self.create_stack(stack_name, self.template)
diff --git a/tempest/cli/simple_read_only/orchestration/test_heat.py b/tempest/cli/simple_read_only/orchestration/test_heat.py
index 8e413a9..019818b 100644
--- a/tempest/cli/simple_read_only/orchestration/test_heat.py
+++ b/tempest/cli/simple_read_only/orchestration/test_heat.py
@@ -56,7 +56,7 @@
 
     def test_heat_resource_template_fmt_arg_long_json(self):
         ret = self.heat('resource-template --format json OS::Nova::Server')
-        self.assertIn('"Type": "OS::Nova::Server",', ret)
+        self.assertIn('"Type": "OS::Nova::Server"', ret)
         self.assertIsInstance(json.loads(ret), dict)
 
     def test_heat_resource_type_list(self):
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 87b7cd7..3f8db3d 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -21,7 +21,6 @@
 
 import argparse
 import datetime
-import logging
 import os
 import sys
 import unittest
@@ -31,6 +30,7 @@
 import tempest.auth
 from tempest import config
 from tempest import exceptions
+from tempest.openstack.common import log as logging
 from tempest.openstack.common import timeutils
 from tempest.services.compute.json import flavors_client
 from tempest.services.compute.json import servers_client
@@ -616,21 +616,10 @@
         config.CONF.set_config_path(OPTS.config_file)
 
 
-def setup_logging(debug=True):
+def setup_logging():
     global LOG
+    logging.setup(__name__)
     LOG = logging.getLogger(__name__)
-    if debug:
-        LOG.setLevel(logging.DEBUG)
-    else:
-        LOG.setLevel(logging.INFO)
-
-    ch = logging.StreamHandler(sys.stdout)
-    ch.setLevel(logging.DEBUG)
-    formatter = logging.Formatter(
-        datefmt='%Y-%m-%d %H:%M:%S',
-        fmt='%(asctime)s.%(msecs).03d - %(levelname)s - %(message)s')
-    ch.setFormatter(formatter)
-    LOG.addHandler(ch)
 
 
 def main():
diff --git a/tempest/manager.py b/tempest/manager.py
index fb2842f..75aee96 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -51,17 +51,17 @@
         self.client_attr_names = []
 
     @classmethod
-    def get_auth_provider_class(cls, auth_version):
-        if auth_version == 'v2':
-            return auth.KeystoneV2AuthProvider
-        else:
+    def get_auth_provider_class(cls, credentials):
+        if isinstance(credentials, auth.KeystoneV3Credentials):
             return auth.KeystoneV3AuthProvider
+        else:
+            return auth.KeystoneV2AuthProvider
 
     def get_auth_provider(self, credentials):
         if credentials is None:
             raise exceptions.InvalidCredentials(
                 'Credentials must be specified')
-        auth_provider_class = self.get_auth_provider_class(self.auth_version)
+        auth_provider_class = self.get_auth_provider_class(credentials)
         return auth_provider_class(
             client_type=getattr(self, 'client_type', None),
             interface=getattr(self, 'interface', None),
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index cabefc8..66043d3 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -271,14 +271,18 @@
         _, volume = self.volumes_client.create_volume(
             size=size, display_name=name, snapshot_id=snapshot_id,
             imageRef=imageRef, volume_type=volume_type)
+
         if wait_on_delete:
             self.addCleanup(self.volumes_client.wait_for_resource_deletion,
                             volume['id'])
-        self.addCleanup_with_wait(
-            waiter_callable=self.volumes_client.wait_for_resource_deletion,
-            thing_id=volume['id'], thing_id_param='id',
-            cleanup_callable=self.delete_wrapper,
-            cleanup_args=[self.volumes_client.delete_volume, volume['id']])
+            self.addCleanup(self.delete_wrapper,
+                            self.volumes_client.delete_volume, volume['id'])
+        else:
+            self.addCleanup_with_wait(
+                waiter_callable=self.volumes_client.wait_for_resource_deletion,
+                thing_id=volume['id'], thing_id_param='id',
+                cleanup_callable=self.delete_wrapper,
+                cleanup_args=[self.volumes_client.delete_volume, volume['id']])
 
         self.assertEqual(name, volume['display_name'])
         self.volumes_client.wait_for_volume_status(volume['id'], 'available')
@@ -446,6 +450,24 @@
                   image_name, server['name'])
         return snapshot_image
 
+    def nova_volume_attach(self):
+        # TODO(andreaf) Device should be here CONF.compute.volume_device_name
+        _, volume_attachment = self.servers_client.attach_volume(
+            self.server['id'], self.volume['id'], '/dev/vdb')
+        volume = volume_attachment['volumeAttachment']
+        self.assertEqual(self.volume['id'], volume['id'])
+        self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
+        # Refresh the volume after the attachment
+        _, self.volume = self.volumes_client.get_volume(volume['id'])
+
+    def nova_volume_detach(self):
+        self.servers_client.detach_volume(self.server['id'], self.volume['id'])
+        self.volumes_client.wait_for_volume_status(self.volume['id'],
+                                                   'available')
+
+        _, volume = self.volumes_client.get_volume(self.volume['id'])
+        self.assertEqual('available', volume['status'])
+
 
 # TODO(yfried): change this class name to NetworkScenarioTest once client
 # migration is complete
@@ -1620,7 +1642,7 @@
             timeout=CONF.baremetal.unprovision_timeout)
 
 
-class EncryptionScenarioTest(OfficialClientTest):
+class EncryptionScenarioTest(ScenarioTest):
     """
     Base class for encryption scenario tests
     """
@@ -1628,11 +1650,7 @@
     @classmethod
     def setUpClass(cls):
         super(EncryptionScenarioTest, cls).setUpClass()
-
-        # use admin credentials to create encrypted volume types
-        admin_creds = cls.admin_credentials()
-        manager = clients.OfficialClientManager(credentials=admin_creds)
-        cls.admin_volume_client = manager.volume_client
+        cls.admin_volume_types_client = cls.admin_manager.volume_types_client
 
     def _wait_for_volume_status(self, status):
         self.status_timeout(
@@ -1640,53 +1658,35 @@
 
     def nova_boot(self):
         self.keypair = self.create_keypair()
-        create_kwargs = {'key_name': self.keypair.name}
-        self.server = self.create_server(self.compute_client,
-                                         image=self.image,
+        create_kwargs = {'key_name': self.keypair['name']}
+        self.server = self.create_server(image=self.image,
                                          create_kwargs=create_kwargs)
 
     def create_volume_type(self, client=None, name=None):
         if not client:
-            client = self.admin_volume_client
+            client = self.admin_volume_types_client
         if not name:
             name = 'generic'
         randomized_name = data_utils.rand_name('scenario-type-' + name + '-')
         LOG.debug("Creating a volume type: %s", randomized_name)
-        volume_type = client.volume_types.create(randomized_name)
-        self.addCleanup(client.volume_types.delete, volume_type.id)
-        return volume_type
+        _, body = client.create_volume_type(
+            randomized_name)
+        self.assertIn('id', body)
+        self.addCleanup(client.delete_volume_type, body['id'])
+        return body
 
     def create_encryption_type(self, client=None, type_id=None, provider=None,
                                key_size=None, cipher=None,
                                control_location=None):
         if not client:
-            client = self.admin_volume_client
+            client = self.admin_volume_types_client
         if not type_id:
             volume_type = self.create_volume_type()
-            type_id = volume_type.id
+            type_id = volume_type['id']
         LOG.debug("Creating an encryption type for volume type: %s", type_id)
-        client.volume_encryption_types.create(type_id,
-                                              {'provider': provider,
-                                               'key_size': key_size,
-                                               'cipher': cipher,
-                                               'control_location':
-                                               control_location})
-
-    def nova_volume_attach(self):
-        attach_volume_client = self.compute_client.volumes.create_server_volume
-        volume = attach_volume_client(self.server.id,
-                                      self.volume.id,
-                                      '/dev/vdb')
-        self.assertEqual(self.volume.id, volume.id)
-        self._wait_for_volume_status('in-use')
-
-    def nova_volume_detach(self):
-        detach_volume_client = self.compute_client.volumes.delete_server_volume
-        detach_volume_client(self.server.id, self.volume.id)
-        self._wait_for_volume_status('available')
-
-        volume = self.volume_client.volumes.get(self.volume.id)
-        self.assertEqual('available', volume.status)
+        client.create_encryption_type(
+            type_id, provider=provider, key_size=key_size, cipher=cipher,
+            control_location=control_location)
 
 
 class NetworkScenarioTest(OfficialClientTest):
diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py
index 9ad6bc4..efbf4ce 100644
--- a/tempest/scenario/test_baremetal_basic_ops.py
+++ b/tempest/scenario/test_baremetal_basic_ops.py
@@ -133,18 +133,23 @@
         # the same size as our flavor definition.
         eph_size = self.get_flavor_ephemeral_size()
         self.assertIsNotNone(eph_size)
-        self.verify_partition(vm_client, 'ephemeral0', '/mnt', eph_size)
+        if eph_size > 0:
+            preserve_ephemeral = True
 
-        # Create the test file
-        self.create_remote_file(vm_client, test_filename)
+            self.verify_partition(vm_client, 'ephemeral0', '/mnt', eph_size)
+            # Create the test file
+            self.create_remote_file(vm_client, test_filename)
+        else:
+            preserve_ephemeral = False
 
-        # Rebuild and preserve the ephemeral partition
-        self.rebuild_instance(True)
+        # Rebuild and preserve the ephemeral partition if it exists
+        self.rebuild_instance(preserve_ephemeral)
         self.verify_connectivity()
 
         # Check that we maintained our data
-        vm_client = self.get_remote_client(self.instance)
-        self.verify_partition(vm_client, 'ephemeral0', '/mnt', eph_size)
-        vm_client.exec_command('ls ' + test_filename)
+        if eph_size > 0:
+            vm_client = self.get_remote_client(self.instance)
+            self.verify_partition(vm_client, 'ephemeral0', '/mnt', eph_size)
+            vm_client.exec_command('ls ' + test_filename)
 
         self.terminate_instance()
diff --git a/tempest/scenario/test_encrypted_cinder_volumes.py b/tempest/scenario/test_encrypted_cinder_volumes.py
index 366cd93..ac2ef8a 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -37,12 +37,12 @@
 
     def create_encrypted_volume(self, encryption_provider):
         volume_type = self.create_volume_type(name='luks')
-        self.create_encryption_type(type_id=volume_type.id,
+        self.create_encryption_type(type_id=volume_type['id'],
                                     provider=encryption_provider,
                                     key_size=512,
                                     cipher='aes-xts-plain64',
                                     control_location='front-end')
-        self.volume = self.create_volume(volume_type=volume_type.name)
+        self.volume = self.create_volume(volume_type=volume_type['name'])
 
     def attach_detach_volume(self):
         self.nova_volume_attach()
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
index 15cf13b..a7ea70f 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -25,7 +25,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class TestLargeOpsScenario(manager.NetworkScenarioTest):
+class TestLargeOpsScenario(manager.ScenarioTest):
 
     """
     Test large operations.
@@ -44,29 +44,34 @@
 
     def _wait_for_server_status(self, status):
         for server in self.servers:
-            self.status_timeout(
-                self.compute_client.servers, server.id, status)
+            self.servers_client.wait_for_server_status(server['id'], status)
 
     def nova_boot(self):
         name = data_utils.rand_name('scenario-server-')
-        client = self.compute_client
         flavor_id = CONF.compute.flavor_ref
-        secgroup = self._create_security_group_nova()
-        self.servers = client.servers.create(
-            name=name, image=self.image,
-            flavor=flavor_id,
+        secgroup = self._create_security_group()
+        self.servers_client.create_server(
+            name,
+            self.image,
+            flavor_id,
             min_count=CONF.scenario.large_ops_number,
-            security_groups=[secgroup.name])
+            security_groups=[secgroup])
         # needed because of bug 1199788
-        self.servers = [x for x in client.servers.list() if name in x.name]
+        params = {'name': name}
+        _, server_list = self.servers_client.list_servers(params)
+        self.servers = server_list['servers']
         for server in self.servers:
             # after deleting all servers - wait for all servers to clear
             # before cleanup continues
-            self.addCleanup(self.delete_timeout,
-                            self.compute_client.servers,
-                            server.id)
+            self.addCleanup(self.servers_client.wait_for_server_termination,
+                            server['id'])
         for server in self.servers:
-            self.addCleanup_with_wait(self.compute_client.servers, server.id)
+            self.addCleanup_with_wait(
+                waiter_callable=(self.servers_client.
+                                 wait_for_server_termination),
+                thing_id=server['id'], thing_id_param='server_id',
+                cleanup_callable=self.delete_wrapper,
+                cleanup_args=[self.servers_client.delete_server, server['id']])
         self._wait_for_server_status('ACTIVE')
 
     def _large_ops_scenario(self):
diff --git a/tempest/tests/test_wrappers.py b/tempest/tests/test_wrappers.py
index bba4012..3f4ac7d 100644
--- a/tempest/tests/test_wrappers.py
+++ b/tempest/tests/test_wrappers.py
@@ -69,14 +69,14 @@
 
         self.assertEqual(
             p.returncode, expected,
-            "Stdout: %s; Stderr: %s" % (p.stdout, p.stderr))
+            "Stdout: %s; Stderr: %s" % (p.stdout.read(), p.stderr.read()))
 
     def test_pretty_tox(self):
         # Git init is required for the pbr testr command. pbr requires a git
         # version or an sdist to work. so make the test directory a git repo
         # too.
         subprocess.call(['git', 'init'], stderr=DEVNULL)
-        self.assertRunExit('pretty_tox.sh tests.passing', 0)
+        self.assertRunExit('pretty_tox.sh passing', 0)
 
     def test_pretty_tox_fails(self):
         # Git init is required for the pbr testr command. pbr requires a git
@@ -86,7 +86,7 @@
         self.assertRunExit('pretty_tox.sh', 1)
 
     def test_pretty_tox_serial(self):
-        self.assertRunExit('pretty_tox_serial.sh tests.passing', 0)
+        self.assertRunExit('pretty_tox_serial.sh passing', 0)
 
     def test_pretty_tox_serial_fails(self):
         self.assertRunExit('pretty_tox_serial.sh', 1)
diff --git a/tools/subunit-trace.py b/tools/subunit-trace.py
index 8ad59bb..57e58f2 100755
--- a/tools/subunit-trace.py
+++ b/tools/subunit-trace.py
@@ -23,7 +23,6 @@
 import re
 import sys
 
-import mimeparse
 import subunit
 import testtools
 
@@ -32,55 +31,6 @@
 RESULTS = {}
 
 
-class Starts(testtools.StreamResult):
-
-    def __init__(self, output):
-        super(Starts, self).__init__()
-        self._output = output
-
-    def startTestRun(self):
-        self._neednewline = False
-        self._emitted = set()
-
-    def status(self, test_id=None, test_status=None, test_tags=None,
-               runnable=True, file_name=None, file_bytes=None, eof=False,
-               mime_type=None, route_code=None, timestamp=None):
-        super(Starts, self).status(
-            test_id, test_status,
-            test_tags=test_tags, runnable=runnable, file_name=file_name,
-            file_bytes=file_bytes, eof=eof, mime_type=mime_type,
-            route_code=route_code, timestamp=timestamp)
-        if not test_id:
-            if not file_bytes:
-                return
-            if not mime_type or mime_type == 'test/plain;charset=utf8':
-                mime_type = 'text/plain; charset=utf-8'
-            primary, sub, parameters = mimeparse.parse_mime_type(mime_type)
-            content_type = testtools.content_type.ContentType(
-                primary, sub, parameters)
-            content = testtools.content.Content(
-                content_type, lambda: [file_bytes])
-            text = content.as_text()
-            if text and text[-1] not in '\r\n':
-                self._neednewline = True
-            self._output.write(text)
-        elif test_status == 'inprogress' and test_id not in self._emitted:
-            if self._neednewline:
-                self._neednewline = False
-                self._output.write('\n')
-            worker = ''
-            for tag in test_tags or ():
-                if tag.startswith('worker-'):
-                    worker = '(' + tag[7:] + ') '
-            if timestamp:
-                timestr = timestamp.isoformat()
-            else:
-                timestr = ''
-                self._output.write('%s: %s%s [start]\n' %
-                                   (timestr, worker, test_id))
-            self._emitted.add(test_id)
-
-
 def cleanup_test_name(name, strip_tags=True, strip_scenarios=False):
     """Clean up the test name for display.
 
@@ -274,17 +224,19 @@
     args = parse_args()
     stream = subunit.ByteStreamToStreamResult(
         sys.stdin, non_subunit_name='stdout')
-    starts = Starts(sys.stdout)
     outcomes = testtools.StreamToDict(
         functools.partial(show_outcome, sys.stdout,
                           print_failures=args.print_failures))
     summary = testtools.StreamSummary()
-    result = testtools.CopyStreamResult([starts, outcomes, summary])
+    result = testtools.CopyStreamResult([outcomes, summary])
     result.startTestRun()
     try:
         stream.run(result)
     finally:
         result.stopTestRun()
+    if count_tests('status', '.*') == 0:
+        print("The test run didn't actually run any tests")
+        return 1
     if args.post_fails:
         print_fails(sys.stdout)
     print_summary(sys.stdout)