Merge "Raise orchestration build_timeout to 600 seconds"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index bab2471..31aff61 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -391,6 +391,20 @@
 #endpoint_type=publicURL
 
 
+[database]
+
+#
+# Options defined in tempest.config
+#
+
+# Catalog type of the Database service. (string value)
+#catalog_type=database
+
+# Valid primary flavor to use in database tests. (string
+# value)
+#db_flavor_ref=1
+
+
 [debug]
 
 #
@@ -773,6 +787,10 @@
 # value)
 #ironic=false
 
+# Whether or not Trove is expected to be available (boolean
+# value)
+#trove=false
+
 
 [stress]
 
diff --git a/tempest/api/database/__init__.py b/tempest/api/database/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/database/__init__.py
diff --git a/tempest/api/database/base.py b/tempest/api/database/base.py
new file mode 100644
index 0000000..8add9ba
--- /dev/null
+++ b/tempest/api/database/base.py
@@ -0,0 +1,42 @@
+# Copyright 2014 OpenStack Foundation
+# 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 import config
+from tempest.openstack.common import log as logging
+import tempest.test
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+
+class BaseDatabaseTest(tempest.test.BaseTestCase):
+    """Base test case class for all Database API tests."""
+
+    _interface = 'json'
+    force_tenant_isolation = False
+
+    @classmethod
+    def setUpClass(cls):
+        super(BaseDatabaseTest, cls).setUpClass()
+        if not CONF.service_available.trove:
+            skip_msg = ("%s skipped as trove is not available" % cls.__name__)
+            raise cls.skipException(skip_msg)
+
+        cls.catalog_type = CONF.database.catalog_type
+        cls.db_flavor_ref = CONF.database.db_flavor_ref
+
+        os = cls.get_client_manager()
+        cls.os = os
+        cls.database_flavors_client = cls.os.database_flavors_client
diff --git a/tempest/api/database/flavors/__init__.py b/tempest/api/database/flavors/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/database/flavors/__init__.py
diff --git a/tempest/api/database/flavors/test_flavors.py b/tempest/api/database/flavors/test_flavors.py
new file mode 100644
index 0000000..a591e8e
--- /dev/null
+++ b/tempest/api/database/flavors/test_flavors.py
@@ -0,0 +1,41 @@
+# Copyright 2014 OpenStack Foundation
+# 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.database import base
+from tempest import test
+
+
+class DatabaseFlavorsTest(base.BaseDatabaseTest):
+
+    @classmethod
+    def setUpClass(cls):
+        super(DatabaseFlavorsTest, cls).setUpClass()
+        cls.client = cls.database_flavors_client
+
+    @test.attr(type='smoke')
+    def test_get_db_flavor(self):
+        # The expected flavor details should be returned
+        resp, flavor = self.client.get_db_flavor_details(self.db_flavor_ref)
+        self.assertEqual(self.db_flavor_ref, str(flavor['id']))
+        self.assertIn('ram', flavor)
+        self.assertIn('links', flavor)
+        self.assertIn('name', flavor)
+
+    @test.attr(type='smoke')
+    def test_list_db_flavors(self):
+        resp, flavor = self.client.get_db_flavor_details(self.db_flavor_ref)
+        # List of all flavors should contain the expected flavor
+        resp, flavors = self.client.list_db_flavors()
+        self.assertIn(flavor, flavors)
diff --git a/tempest/api/database/flavors/test_flavors_negative.py b/tempest/api/database/flavors/test_flavors_negative.py
new file mode 100644
index 0000000..202dc48
--- /dev/null
+++ b/tempest/api/database/flavors/test_flavors_negative.py
@@ -0,0 +1,32 @@
+# Copyright 2014 OpenStack Foundation
+# 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.database import base
+from tempest import exceptions
+from tempest import test
+
+
+class DatabaseFlavorsNegativeTest(base.BaseDatabaseTest):
+
+    @classmethod
+    def setUpClass(cls):
+        super(DatabaseFlavorsNegativeTest, cls).setUpClass()
+        cls.client = cls.database_flavors_client
+
+    @test.attr(type=['negative', 'gate'])
+    def test_get_non_existent_db_flavor(self):
+        # flavor details are not returned for non-existent flavors
+        self.assertRaises(exceptions.NotFound,
+                          self.client.get_db_flavor_details, -1)
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 8720985..ba6a617 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -152,8 +152,6 @@
             cidr = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
             mask_bits = CONF.network.tenant_network_v6_mask_bits
         # Find a cidr that is not in use yet and create a subnet with it
-        body = None
-        failure = None
         for subnet_cidr in cidr.subnet(mask_bits):
             try:
                 resp, body = cls.client.create_subnet(
@@ -165,12 +163,9 @@
                 is_overlapping_cidr = 'overlaps with another subnet' in str(e)
                 if not is_overlapping_cidr:
                     raise
-                # save the failure in case all of the CIDRs are overlapping
-                failure = e
-
-        if not body and failure:
-            raise failure
-
+        else:
+            message = 'Available CIDR for subnet creation could not be found'
+            raise exceptions.BuildErrorException(message)
         subnet = body['subnet']
         cls.subnets.append(subnet)
         return subnet
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 654552d..ea802ad 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -18,7 +18,6 @@
 from tempest.api.network import base
 from tempest.common.utils import data_utils
 from tempest import config
-from tempest import exceptions
 from tempest.test import attr
 
 CONF = config.CONF
@@ -85,25 +84,7 @@
         updated_net = body['network']
         self.assertEqual(updated_net['name'], new_name)
         # Find a cidr that is not in use yet and create a subnet with it
-        if self._ip_version == 4:
-            cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
-            mask_bits = CONF.network.tenant_network_mask_bits
-        elif self._ip_version == 6:
-            cidr = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
-            mask_bits = CONF.network.tenant_network_v6_mask_bits
-        for subnet_cidr in cidr.subnet(mask_bits):
-            try:
-                resp, body = self.client.create_subnet(
-                    network_id=net_id,
-                    cidr=str(subnet_cidr),
-                    ip_version=self._ip_version)
-                break
-            except exceptions.BadRequest as e:
-                is_overlapping_cidr = 'overlaps with another subnet' in str(e)
-                if not is_overlapping_cidr:
-                    raise
-        self.assertEqual('201', resp['status'])
-        subnet = body['subnet']
+        subnet = self.create_subnet(network)
         subnet_id = subnet['id']
         # Verification of subnet update
         new_subnet = "New_subnet"
@@ -115,6 +96,8 @@
         # Delete subnet and network
         resp, body = self.client.delete_subnet(subnet_id)
         self.assertEqual('204', resp['status'])
+        # Remove subnet from cleanup list
+        self.subnets.pop()
         resp, body = self.client.delete_network(net_id)
         self.assertEqual('204', resp['status'])
 
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index 291f0d1..18ba37b 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -73,7 +73,7 @@
       subnet_id: {get_resource: Subnet}
   Server:
     type: AWS::EC2::Instance
-    Metadata:
+    metadata:
       Name: SmokeServerNeutron
     properties:
       ImageId: {get_param: ImageId}
@@ -93,7 +93,7 @@
     type: AWS::CloudFormation::WaitConditionHandle
   WaitCondition:
     type: AWS::CloudFormation::WaitCondition
-    DependsOn: Server
+    depends_on: Server
     properties:
       Handle: {get_resource: WaitHandleNeutron}
       Timeout: '600'
diff --git a/tempest/api/orchestration/stacks/test_swift_resources.py b/tempest/api/orchestration/stacks/test_swift_resources.py
index 5921a7a..713cfd4 100644
--- a/tempest/api/orchestration/stacks/test_swift_resources.py
+++ b/tempest/api/orchestration/stacks/test_swift_resources.py
@@ -27,20 +27,20 @@
     _interface = 'json'
     template = """
 heat_template_version: 2013-05-23
-description: Template which creates a Swift container ressource
+description: Template which creates a Swift container resource
 
 resources:
   SwiftContainerWebsite:
-    DeletionPolicy: "Delete"
-    Type: OS::Swift::Container
-    Properties:
+    deletion_policy: "Delete"
+    type: OS::Swift::Container
+    properties:
       X-Container-Read: ".r:*"
       X-Container-Meta:
         web-index: "index.html"
         web-error: "error.html"
 
   SwiftContainer:
-    Type: OS::Swift::Container
+    type: OS::Swift::Container
 
 outputs:
   WebsiteURL:
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index b0c878b..6178a1c 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -14,7 +14,7 @@
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest.openstack.common import log as logging
-from tempest.test import attr
+from tempest import test
 
 CONF = config.CONF
 
@@ -86,7 +86,7 @@
 
         super(VolumeMultiBackendTest, cls).tearDownClass()
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_backend_name_reporting(self):
         # this test checks if os-vol-attr:host is populated correctly after
         # the multi backend feature has been enabled
@@ -100,7 +100,7 @@
                self.volume1['id'])
         self.assertTrue(len(volume1_host.split("@")) > 1, msg)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_backend_name_distinction(self):
         # this test checks that the two volumes created at setUp don't
         # belong to the same backend (if they are, than the
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
index 12fda92..e140ad0 100644
--- a/tempest/api/volume/admin/test_snapshots_actions.py
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -15,7 +15,7 @@
 
 from tempest.api.volume import base
 from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
 
 
 class SnapshotsActionsTest(base.BaseVolumeV1AdminTest):
@@ -80,7 +80,7 @@
     def _get_progress_alias(self):
         return 'os-extended-snapshot-attributes:progress'
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_reset_snapshot_status(self):
         # Reset snapshot status to creating
         status = 'creating'
@@ -92,7 +92,7 @@
         self.assertEqual(200, resp_get.status)
         self.assertEqual(status, snapshot_get['status'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_update_snapshot_status(self):
         # Reset snapshot status to creating
         status = 'creating'
@@ -112,22 +112,22 @@
         self.assertEqual(status, snapshot_get['status'])
         self.assertEqual(progress, snapshot_get[progress_alias])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_snapshot_force_delete_when_snapshot_is_creating(self):
         # test force delete when status of snapshot is creating
         self._create_reset_and_force_delete_temp_snapshot('creating')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_snapshot_force_delete_when_snapshot_is_deleting(self):
         # test force delete when status of snapshot is deleting
         self._create_reset_and_force_delete_temp_snapshot('deleting')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_snapshot_force_delete_when_snapshot_is_error(self):
         # test force delete when status of snapshot is error
         self._create_reset_and_force_delete_temp_snapshot('error')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_snapshot_force_delete_when_snapshot_is_error_deleting(self):
         # test force delete when status of snapshot is error_deleting
         self._create_reset_and_force_delete_temp_snapshot('error_deleting')
diff --git a/tempest/api/volume/admin/test_volume_hosts.py b/tempest/api/volume/admin/test_volume_hosts.py
index 5c311e1..01ba915 100644
--- a/tempest/api/volume/admin/test_volume_hosts.py
+++ b/tempest/api/volume/admin/test_volume_hosts.py
@@ -14,13 +14,13 @@
 #    under the License.
 
 from tempest.api.volume import base
-from tempest.test import attr
+from tempest import test
 
 
 class VolumeHostsAdminTestsJSON(base.BaseVolumeV1AdminTest):
     _interface = "json"
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_hosts(self):
         resp, hosts = self.hosts_client.list_hosts()
         self.assertEqual(200, resp.status)
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index d481251..8183999 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -16,7 +16,7 @@
 from tempest.api.volume import base
 from tempest.common.utils import data_utils
 from tempest import config
-from tempest.test import attr
+from tempest import test
 
 CONF = config.CONF
 
@@ -33,14 +33,14 @@
         resp, _ = self.client.delete_volume_type(volume_type_id)
         self.assertEqual(202, resp.status)
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_volume_type_list(self):
         # List Volume types.
         resp, body = self.client.list_volume_types()
         self.assertEqual(200, resp.status)
         self.assertIsInstance(body, list)
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_create_get_delete_volume_with_volume_type_and_extra_specs(self):
         # Create/get/delete volume with volume_type and extra spec.
         volume = {}
@@ -84,7 +84,7 @@
                          'The fetched Volume is different '
                          'from the created Volume')
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_volume_type_create_get_delete(self):
         # Create/get volume type.
         body = {}
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs.py b/tempest/api/volume/admin/test_volume_types_extra_specs.py
index 99a0826..06a0b34 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs.py
@@ -15,7 +15,7 @@
 
 from tempest.api.volume import base
 from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
 
 
 class VolumeTypesExtraSpecsTest(base.BaseVolumeV1AdminTest):
@@ -32,7 +32,7 @@
         cls.client.delete_volume_type(cls.volume_type['id'])
         super(VolumeTypesExtraSpecsTest, cls).tearDownClass()
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_volume_type_extra_specs_list(self):
         # List Volume types extra specs.
         extra_specs = {"spec1": "val1"}
@@ -47,7 +47,7 @@
         self.assertIsInstance(body, dict)
         self.assertIn('spec1', body)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volume_type_extra_specs_update(self):
         # Update volume type extra specs
         extra_specs = {"spec2": "val1"}
@@ -67,7 +67,7 @@
         self.assertEqual(extra_spec['spec2'], body['spec2'],
                          "Volume type extra spec incorrectly updated")
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_volume_type_extra_spec_create_get_delete(self):
         # Create/Get/Delete volume type extra spec.
         extra_specs = {"spec3": "val1"}
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
index 5a1a2cd..d3a052e 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
@@ -18,7 +18,7 @@
 from tempest.api.volume import base
 from tempest.common.utils import data_utils
 from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 
 class ExtraSpecsNegativeTest(base.BaseVolumeV1AdminTest):
@@ -38,7 +38,7 @@
         cls.client.delete_volume_type(cls.volume_type['id'])
         super(ExtraSpecsNegativeTest, cls).tearDownClass()
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_update_no_body(self):
         # Should not update volume type extra specs with no body
         extra_spec = {"spec1": "val2"}
@@ -46,7 +46,7 @@
                           self.client.update_volume_type_extra_specs,
                           self.volume_type['id'], extra_spec.keys()[0], None)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_update_nonexistent_extra_spec_id(self):
         # Should not update volume type extra specs with nonexistent id.
         extra_spec = {"spec1": "val2"}
@@ -55,7 +55,7 @@
                           self.volume_type['id'], str(uuid.uuid4()),
                           extra_spec)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_update_none_extra_spec_id(self):
         # Should not update volume type extra specs with none id.
         extra_spec = {"spec1": "val2"}
@@ -63,7 +63,7 @@
                           self.client.update_volume_type_extra_specs,
                           self.volume_type['id'], None, extra_spec)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_update_multiple_extra_spec(self):
         # Should not update volume type extra specs with multiple specs as
             # body.
@@ -73,7 +73,7 @@
                           self.volume_type['id'], extra_spec.keys()[0],
                           extra_spec)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_nonexistent_type_id(self):
         # Should not create volume type extra spec for nonexistent volume
             # type id.
@@ -82,21 +82,21 @@
                           self.client.create_volume_type_extra_specs,
                           str(uuid.uuid4()), extra_specs)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_none_body(self):
         # Should not create volume type extra spec for none POST body.
         self.assertRaises(exceptions.BadRequest,
                           self.client.create_volume_type_extra_specs,
                           self.volume_type['id'], None)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_invalid_body(self):
         # Should not create volume type extra spec for invalid POST body.
         self.assertRaises(exceptions.BadRequest,
                           self.client.create_volume_type_extra_specs,
                           self.volume_type['id'], ['invalid'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_delete_nonexistent_volume_type_id(self):
         # Should not delete volume type extra spec for nonexistent
             # type id.
@@ -105,14 +105,14 @@
                           self.client.delete_volume_type_extra_specs,
                           str(uuid.uuid4()), extra_specs.keys()[0])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_nonexistent_volume_type_id(self):
         # Should not list volume type extra spec for nonexistent type id.
         self.assertRaises(exceptions.NotFound,
                           self.client.list_volume_types_extra_specs,
                           str(uuid.uuid4()))
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_get_nonexistent_volume_type_id(self):
         # Should not get volume type extra spec for nonexistent type id.
         extra_specs = {"spec1": "val1"}
@@ -120,7 +120,7 @@
                           self.client.get_volume_type_extra_specs,
                           str(uuid.uuid4()), extra_specs.keys()[0])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_get_nonexistent_extra_spec_id(self):
         # Should not get volume type extra spec for nonexistent extra spec
             # id.
diff --git a/tempest/api/volume/admin/test_volume_types_negative.py b/tempest/api/volume/admin/test_volume_types_negative.py
index 56ad227..c18e15d 100644
--- a/tempest/api/volume/admin/test_volume_types_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_negative.py
@@ -17,13 +17,13 @@
 
 from tempest.api.volume import base
 from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 
 class VolumeTypesNegativeTest(base.BaseVolumeV1AdminTest):
     _interface = 'json'
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_with_nonexistent_volume_type(self):
         # Should not be able to create volume with nonexistent volume_type.
         self.assertRaises(exceptions.NotFound,
@@ -31,19 +31,19 @@
                           display_name=str(uuid.uuid4()),
                           volume_type=str(uuid.uuid4()))
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_with_empty_name(self):
         # Should not be able to create volume type with an empty name.
         self.assertRaises(exceptions.BadRequest,
                           self.client.create_volume_type, '')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_get_nonexistent_type_id(self):
         # Should not be able to get volume type with nonexistent type id.
         self.assertRaises(exceptions.NotFound, self.client.get_volume_type,
                           str(uuid.uuid4()))
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_delete_nonexistent_type_id(self):
         # Should not be able to delete volume type with nonexistent type id.
         self.assertRaises(exceptions.NotFound, self.client.delete_volume_type,
diff --git a/tempest/api/volume/admin/test_volumes_actions.py b/tempest/api/volume/admin/test_volumes_actions.py
index 9274fce..aa00700 100644
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -15,7 +15,7 @@
 
 from tempest.api.volume import base
 from tempest.common.utils import data_utils as utils
-from tempest.test import attr
+from tempest import test
 
 
 class VolumesActionsTest(base.BaseVolumeV1AdminTest):
@@ -75,7 +75,7 @@
         self.assertEqual(202, resp_delete.status)
         self.client.wait_for_resource_deletion(temp_volume['id'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volume_reset_status(self):
         # test volume reset status : available->error->available
         resp, body = self._reset_volume_status(self.volume['id'], 'error')
@@ -84,7 +84,7 @@
             self.volume['id'])
         self.assertEqual('error', volume_get['status'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volume_begin_detaching(self):
         # test volume begin detaching : available -> detaching -> available
         resp, body = self.client.volume_begin_detaching(self.volume['id'])
@@ -92,7 +92,7 @@
         resp_get, volume_get = self.client.get_volume(self.volume['id'])
         self.assertEqual('detaching', volume_get['status'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volume_roll_detaching(self):
         # test volume roll detaching : detaching -> in-use -> available
         resp, body = self.client.volume_begin_detaching(self.volume['id'])
@@ -110,7 +110,7 @@
         # test force delete when status of volume is attaching
         self._create_reset_and_force_delete_temp_volume('attaching')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volume_force_delete_when_volume_is_error(self):
         # test force delete when status of volume is error
         self._create_reset_and_force_delete_temp_volume('error')
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
index 47094f0..9af4011 100644
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -13,7 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest.api.volume.base import BaseVolumeV1AdminTest
+from tempest.api.volume import base
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest.openstack.common import log as logging
@@ -23,7 +23,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class VolumesBackupsTest(BaseVolumeV1AdminTest):
+class VolumesBackupsTest(base.BaseVolumeV1AdminTest):
     _interface = "json"
 
     @classmethod
diff --git a/tempest/api/volume/test_extensions.py b/tempest/api/volume/test_extensions.py
index cceffd6..ce019a2 100644
--- a/tempest/api/volume/test_extensions.py
+++ b/tempest/api/volume/test_extensions.py
@@ -17,7 +17,7 @@
 from tempest.api.volume import base
 from tempest import config
 from tempest.openstack.common import log as logging
-from tempest.test import attr
+from tempest import test
 
 CONF = config.CONF
 
@@ -28,7 +28,7 @@
 class ExtensionsTestJSON(base.BaseVolumeV1Test):
     _interface = 'json'
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_extensions(self):
         # List of all extensions
         resp, extensions = self.volumes_extension_client.list_extensions()
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
index f4b2d4c..55a72c1 100644
--- a/tempest/api/volume/test_volume_transfers.py
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -18,7 +18,7 @@
 from tempest.api.volume import base
 from tempest import clients
 from tempest import config
-from tempest.test import attr
+from tempest import test
 
 CONF = config.CONF
 
@@ -66,7 +66,7 @@
         self.assertEqual(202, resp.status)
         self.adm_client.wait_for_resource_deletion(volume_id)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_get_list_accept_volume_transfer(self):
         # Create a volume first
         volume = self.create_volume()
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index 284c321..82924a5 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -18,7 +18,7 @@
 from tempest.api.volume import base
 from tempest.common.utils import data_utils
 from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 
 class VolumesNegativeTest(base.BaseVolumeV1Test):
@@ -33,19 +33,19 @@
         cls.volume = cls.create_volume()
         cls.mountpoint = "/dev/vdc"
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_volume_get_nonexistent_volume_id(self):
         # Should not be able to get a non-existent volume
         self.assertRaises(exceptions.NotFound, self.client.get_volume,
                           str(uuid.uuid4()))
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_volume_delete_nonexistent_volume_id(self):
         # Should not be able to delete a non-existent Volume
         self.assertRaises(exceptions.NotFound, self.client.delete_volume,
                           str(uuid.uuid4()))
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_create_volume_with_invalid_size(self):
         # Should not be able to create volume with invalid size
         # in request
@@ -54,7 +54,7 @@
         self.assertRaises(exceptions.BadRequest, self.client.create_volume,
                           size='#$%', display_name=v_name, metadata=metadata)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_create_volume_with_out_passing_size(self):
         # Should not be able to create volume without passing size
         # in request
@@ -63,7 +63,7 @@
         self.assertRaises(exceptions.BadRequest, self.client.create_volume,
                           size='', display_name=v_name, metadata=metadata)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_create_volume_with_size_zero(self):
         # Should not be able to create volume with size zero
         v_name = data_utils.rand_name('Volume-')
@@ -71,7 +71,7 @@
         self.assertRaises(exceptions.BadRequest, self.client.create_volume,
                           size='0', display_name=v_name, metadata=metadata)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_create_volume_with_size_negative(self):
         # Should not be able to create volume with size negative
         v_name = data_utils.rand_name('Volume-')
@@ -79,7 +79,7 @@
         self.assertRaises(exceptions.BadRequest, self.client.create_volume,
                           size='-1', display_name=v_name, metadata=metadata)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_create_volume_with_nonexistent_volume_type(self):
         # Should not be able to create volume with non-existent volume type
         v_name = data_utils.rand_name('Volume-')
@@ -88,7 +88,7 @@
                           size='1', volume_type=str(uuid.uuid4()),
                           display_name=v_name, metadata=metadata)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_create_volume_with_nonexistent_snapshot_id(self):
         # Should not be able to create volume with non-existent snapshot
         v_name = data_utils.rand_name('Volume-')
@@ -97,7 +97,7 @@
                           size='1', snapshot_id=str(uuid.uuid4()),
                           display_name=v_name, metadata=metadata)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_create_volume_with_nonexistent_source_volid(self):
         # Should not be able to create volume with non-existent source volume
         v_name = data_utils.rand_name('Volume-')
@@ -106,7 +106,7 @@
                           size='1', source_volid=str(uuid.uuid4()),
                           display_name=v_name, metadata=metadata)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_update_volume_with_nonexistent_volume_id(self):
         v_name = data_utils.rand_name('Volume-')
         metadata = {'Type': 'work'}
@@ -114,7 +114,7 @@
                           volume_id=str(uuid.uuid4()), display_name=v_name,
                           metadata=metadata)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_update_volume_with_invalid_volume_id(self):
         v_name = data_utils.rand_name('Volume-')
         metadata = {'Type': 'work'}
@@ -122,7 +122,7 @@
                           volume_id='#$%%&^&^', display_name=v_name,
                           metadata=metadata)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_update_volume_with_empty_volume_id(self):
         v_name = data_utils.rand_name('Volume-')
         metadata = {'Type': 'work'}
@@ -130,29 +130,29 @@
                           volume_id='', display_name=v_name,
                           metadata=metadata)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_get_invalid_volume_id(self):
         # Should not be able to get volume with invalid id
         self.assertRaises(exceptions.NotFound, self.client.get_volume,
                           '#$%%&^&^')
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_get_volume_without_passing_volume_id(self):
         # Should not be able to get volume when empty ID is passed
         self.assertRaises(exceptions.NotFound, self.client.get_volume, '')
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_delete_invalid_volume_id(self):
         # Should not be able to delete volume when invalid ID is passed
         self.assertRaises(exceptions.NotFound, self.client.delete_volume,
                           '!@#$%^&*()')
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_delete_volume_without_passing_volume_id(self):
         # Should not be able to delete volume when empty ID is passed
         self.assertRaises(exceptions.NotFound, self.client.delete_volume, '')
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_attach_volumes_with_nonexistent_volume_id(self):
         srv_name = data_utils.rand_name('Instance-')
         resp, server = self.servers_client.create_server(srv_name,
@@ -166,60 +166,60 @@
                           server['id'],
                           self.mountpoint)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_detach_volumes_with_invalid_volume_id(self):
         self.assertRaises(exceptions.NotFound,
                           self.client.detach_volume,
                           'xxx')
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_volume_extend_with_size_smaller_than_original_size(self):
         # Extend volume with smaller size than original size.
         extend_size = 0
         self.assertRaises(exceptions.BadRequest, self.client.extend_volume,
                           self.volume['id'], extend_size)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_volume_extend_with_non_number_size(self):
         # Extend volume when size is non number.
         extend_size = 'abc'
         self.assertRaises(exceptions.BadRequest, self.client.extend_volume,
                           self.volume['id'], extend_size)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_volume_extend_with_None_size(self):
         # Extend volume with None size.
         extend_size = None
         self.assertRaises(exceptions.BadRequest, self.client.extend_volume,
                           self.volume['id'], extend_size)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_volume_extend_with_nonexistent_volume_id(self):
         # Extend volume size when volume is nonexistent.
         extend_size = int(self.volume['size']) + 1
         self.assertRaises(exceptions.NotFound, self.client.extend_volume,
                           str(uuid.uuid4()), extend_size)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_volume_extend_without_passing_volume_id(self):
         # Extend volume size when passing volume id is None.
         extend_size = int(self.volume['size']) + 1
         self.assertRaises(exceptions.NotFound, self.client.extend_volume,
                           None, extend_size)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_reserve_volume_with_nonexistent_volume_id(self):
         self.assertRaises(exceptions.NotFound,
                           self.client.reserve_volume,
                           str(uuid.uuid4()))
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_unreserve_volume_with_nonexistent_volume_id(self):
         self.assertRaises(exceptions.NotFound,
                           self.client.unreserve_volume,
                           str(uuid.uuid4()))
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_reserve_volume_with_negative_volume_status(self):
         # Mark volume as reserved.
         resp, body = self.client.reserve_volume(self.volume['id'])
@@ -232,7 +232,7 @@
         resp, body = self.client.unreserve_volume(self.volume['id'])
         self.assertEqual(202, resp.status)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_volumes_with_nonexistent_name(self):
         v_name = data_utils.rand_name('Volume-')
         params = {'display_name': v_name}
@@ -240,7 +240,7 @@
         self.assertEqual(200, resp.status)
         self.assertEqual(0, len(fetched_volume))
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_volumes_detail_with_nonexistent_name(self):
         v_name = data_utils.rand_name('Volume-')
         params = {'display_name': v_name}
@@ -248,14 +248,14 @@
         self.assertEqual(200, resp.status)
         self.assertEqual(0, len(fetched_volume))
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_volumes_with_invalid_status(self):
         params = {'status': 'null'}
         resp, fetched_volume = self.client.list_volumes(params)
         self.assertEqual(200, resp.status)
         self.assertEqual(0, len(fetched_volume))
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_volumes_detail_with_invalid_status(self):
         params = {'status': 'null'}
         resp, fetched_volume = self.client.list_volumes_with_detail(params)
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 56915e6..2701e84 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -14,7 +14,7 @@
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest.openstack.common import log as logging
-from tempest.test import attr
+from tempest import test
 
 LOG = logging.getLogger(__name__)
 CONF = config.CONF
@@ -63,7 +63,7 @@
                       ('details' if with_detail else '', key)
                 self.assertEqual(params[key], snap[key], msg)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_snapshot_create_with_volume_in_use(self):
         # Create a snapshot when volume status is in-use
         # Create a test instance
@@ -89,7 +89,7 @@
         self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
         self.snapshots.remove(snapshot)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_snapshot_create_get_list_update_delete(self):
         # Create a snapshot
         s_name = data_utils.rand_name('snap')
@@ -134,7 +134,7 @@
         self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
         self.snapshots.remove(snapshot)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_snapshots_list_with_params(self):
         """list snapshots with params."""
         # Create a snapshot
@@ -155,7 +155,7 @@
                   'display_name': snapshot['display_name']}
         self._list_by_param_values_and_assert(params)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_snapshots_list_details_with_params(self):
         """list snapshot details with params."""
         # Create a snapshot
@@ -174,7 +174,7 @@
                   'display_name': snapshot['display_name']}
         self._list_by_param_values_and_assert(params, with_detail=True)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volume_from_snapshot(self):
         # Create a temporary snap using wrapper method from base, then
         # create a snap based volume, check resp code and deletes it
diff --git a/tempest/api/volume/test_volumes_snapshots_negative.py b/tempest/api/volume/test_volumes_snapshots_negative.py
index b24b597..9e47c03 100644
--- a/tempest/api/volume/test_volumes_snapshots_negative.py
+++ b/tempest/api/volume/test_volumes_snapshots_negative.py
@@ -15,13 +15,13 @@
 from tempest.api.volume import base
 from tempest.common.utils import data_utils
 from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 
 class VolumesSnapshotNegativeTest(base.BaseVolumeV1Test):
     _interface = "json"
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_create_snapshot_with_nonexistent_volume_id(self):
         # Create a snapshot with nonexistent volume id
         s_name = data_utils.rand_name('snap')
@@ -29,7 +29,7 @@
                           self.snapshots_client.create_snapshot,
                           str(uuid.uuid4()), display_name=s_name)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_create_snapshot_without_passing_volume_id(self):
         # Create a snapshot without passing volume id
         s_name = data_utils.rand_name('snap')
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
index d0e8b99..0e91371 100644
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ b/tempest/api/volume/v2/test_volumes_list.py
@@ -18,8 +18,8 @@
 from tempest.api.volume import base
 from tempest.common.utils import data_utils
 from tempest.openstack.common import log as logging
-from tempest.test import attr
-from testtools.matchers import ContainsAll
+from tempest import test
+from testtools import matchers
 
 LOG = logging.getLogger(__name__)
 
@@ -116,12 +116,12 @@
                           ('details' if with_detail else '', key)
                     if key == 'metadata':
                         self.assertThat(volume[key].items(),
-                                        ContainsAll(params[key].items()),
-                                        msg)
+                                        matchers.ContainsAll(params[key]
+                                        .items()), msg)
                     else:
                         self.assertEqual(params[key], volume[key], msg)
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_volume_list(self):
         # Get a list of Volumes
         # Fetch all volumes
@@ -130,7 +130,7 @@
         self.assertVolumesIn(fetched_list, self.volume_list,
                              fields=VOLUME_FIELDS)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volume_list_with_details(self):
         # Get a list of Volumes with details
         # Fetch all Volumes
@@ -138,7 +138,7 @@
         self.assertEqual(200, resp.status)
         self.assertVolumesIn(fetched_list, self.volume_list)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volume_list_by_name(self):
         volume = self.volume_list[data_utils.rand_int_id(0, 2)]
         params = {'name': volume['name']}
@@ -147,7 +147,7 @@
         self.assertEqual(1, len(fetched_vol), str(fetched_vol))
         self.assertEqual(fetched_vol[0]['name'], volume['name'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volume_list_details_by_name(self):
         volume = self.volume_list[data_utils.rand_int_id(0, 2)]
         params = {'name': volume['name']}
@@ -156,43 +156,43 @@
         self.assertEqual(1, len(fetched_vol), str(fetched_vol))
         self.assertEqual(fetched_vol[0]['name'], volume['name'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volumes_list_by_status(self):
         params = {'status': 'available'}
         self._list_by_param_value_and_assert(params)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volumes_list_details_by_status(self):
         params = {'status': 'available'}
         self._list_by_param_value_and_assert(params, with_detail=True)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volumes_list_by_availability_zone(self):
         volume = self.volume_list[data_utils.rand_int_id(0, 2)]
         zone = volume['availability_zone']
         params = {'availability_zone': zone}
         self._list_by_param_value_and_assert(params)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volumes_list_details_by_availability_zone(self):
         volume = self.volume_list[data_utils.rand_int_id(0, 2)]
         zone = volume['availability_zone']
         params = {'availability_zone': zone}
         self._list_by_param_value_and_assert(params, with_detail=True)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volume_list_with_param_metadata(self):
         # Test to list volumes when metadata param is given
         params = {'metadata': self.metadata}
         self._list_by_param_value_and_assert(params)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volume_list_with_detail_param_metadata(self):
         # Test to list volumes details when metadata param is given
         params = {'metadata': self.metadata}
         self._list_by_param_value_and_assert(params, with_detail=True)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volume_list_param_display_name_and_status(self):
         # Test to list volume when display name and status param is given
         volume = self.volume_list[data_utils.rand_int_id(0, 2)]
@@ -200,7 +200,7 @@
                   'status': 'available'}
         self._list_by_param_value_and_assert(params, expected_list=[volume])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_volume_list_with_detail_param_display_name_and_status(self):
         # Test to list volume when name and status param is given
         volume = self.volume_list[data_utils.rand_int_id(0, 2)]
diff --git a/tempest/auth.py b/tempest/auth.py
index 8cb3b2c..0e45161 100644
--- a/tempest/auth.py
+++ b/tempest/auth.py
@@ -14,11 +14,11 @@
 #    under the License.
 
 import copy
+import datetime
 import exceptions
 import re
 import urlparse
 
-from datetime import datetime
 from tempest import config
 from tempest.services.identity.json import identity_client as json_id
 from tempest.services.identity.v3.json import identity_client as json_v3id
@@ -291,9 +291,9 @@
 
     def is_expired(self, auth_data):
         _, access = auth_data
-        expiry = datetime.strptime(access['token']['expires'],
-                                   self.EXPIRY_DATE_FORMAT)
-        return expiry <= datetime.now()
+        expiry = datetime.datetime.strptime(access['token']['expires'],
+                                            self.EXPIRY_DATE_FORMAT)
+        return expiry <= datetime.datetime.now()
 
 
 class KeystoneV3AuthProvider(KeystoneAuthProvider):
@@ -391,6 +391,6 @@
 
     def is_expired(self, auth_data):
         _, access = auth_data
-        expiry = datetime.strptime(access['expires_at'],
-                                   self.EXPIRY_DATE_FORMAT)
-        return expiry <= datetime.now()
+        expiry = datetime.datetime.strptime(access['expires_at'],
+                                            self.EXPIRY_DATE_FORMAT)
+        return expiry <= datetime.datetime.now()
diff --git a/tempest/clients.py b/tempest/clients.py
index 8db399a..e16d0f4 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -114,6 +114,8 @@
 from tempest.services.compute.xml.volumes_extensions_client import \
     VolumesExtensionsClientXML
 from tempest.services.data_processing.v1_1.client import DataProcessingClient
+from tempest.services.database.json.flavors_client import \
+    DatabaseFlavorsClientJSON
 from tempest.services.identity.json.identity_client import IdentityClientJSON
 from tempest.services.identity.json.identity_client import TokenClientJSON
 from tempest.services.identity.v3.json.credentials_client import \
@@ -330,6 +332,8 @@
             self.volumes_extension_client = VolumeExtensionClientJSON(
                 self.auth_provider)
             self.hosts_v3_client = HostsV3ClientJSON(self.auth_provider)
+            self.database_flavors_client = DatabaseFlavorsClientJSON(
+                self.auth_provider)
             if CONF.service_available.ceilometer:
                 self.telemetry_client = TelemetryClientJSON(
                     self.auth_provider)
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index 03dccd4..66b6fe7 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -25,7 +25,7 @@
 from tempest import config
 from tempest import exceptions
 from tempest.openstack.common import log as logging
-from tempest.services.compute.xml.common import xml_to_json
+from tempest.services.compute.xml import common
 
 CONF = config.CONF
 
@@ -299,11 +299,11 @@
                 # Parse list-like xmls (users, roles, etc)
                 array = []
                 for child in element.getchildren():
-                    array.append(xml_to_json(child))
+                    array.append(common.xml_to_json(child))
                 return array
 
             # Parse one-item-like xmls (user, role, etc)
-            return xml_to_json(element)
+            return common.xml_to_json(element)
 
     def response_checker(self, method, url, headers, body, resp, resp_body):
         if (resp.status in set((204, 205, 304)) or resp.status < 200 or
diff --git a/tempest/config.py b/tempest/config.py
index d7d8079..a82d6d2 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -493,6 +493,17 @@
                      "features are expected to be enabled"),
 ]
 
+database_group = cfg.OptGroup(name='database',
+                              title='Database Service Options')
+
+DatabaseGroup = [
+    cfg.StrOpt('catalog_type',
+               default='database',
+               help="Catalog type of the Database service."),
+    cfg.StrOpt('db_flavor_ref',
+               default="1",
+               help="Valid primary flavor to use in database tests."),
+]
 
 orchestration_group = cfg.OptGroup(name='orchestration',
                                    title='Orchestration Service Options')
@@ -739,6 +750,9 @@
     cfg.BoolOpt('ironic',
                 default=False,
                 help="Whether or not Ironic is expected to be available"),
+    cfg.BoolOpt('trove',
+                default=False,
+                help="Whether or not Trove is expected to be available"),
 ]
 
 debug_group = cfg.OptGroup(name="debug",
@@ -825,6 +839,7 @@
     register_opt_group(cfg.CONF, object_storage_group, ObjectStoreGroup)
     register_opt_group(cfg.CONF, object_storage_feature_group,
                        ObjectStoreFeaturesGroup)
+    register_opt_group(cfg.CONF, database_group, DatabaseGroup)
     register_opt_group(cfg.CONF, orchestration_group, OrchestrationGroup)
     register_opt_group(cfg.CONF, telemetry_group, TelemetryGroup)
     register_opt_group(cfg.CONF, dashboard_group, DashboardGroup)
@@ -866,6 +881,7 @@
         self.object_storage = cfg.CONF['object-storage']
         self.object_storage_feature_enabled = cfg.CONF[
             'object-storage-feature-enabled']
+        self.database = cfg.CONF.database
         self.orchestration = cfg.CONF.orchestration
         self.telemetry = cfg.CONF.telemetry
         self.dashboard = cfg.CONF.dashboard
diff --git a/tempest/services/database/__init__.py b/tempest/services/database/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/services/database/__init__.py
diff --git a/tempest/services/database/json/__init__.py b/tempest/services/database/json/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/services/database/json/__init__.py
diff --git a/tempest/services/database/json/flavors_client.py b/tempest/services/database/json/flavors_client.py
new file mode 100644
index 0000000..1a8a4c1
--- /dev/null
+++ b/tempest/services/database/json/flavors_client.py
@@ -0,0 +1,39 @@
+# Copyright 2014 OpenStack Foundation
+# 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.common import rest_client
+from tempest import config
+import urllib
+
+CONF = config.CONF
+
+
+class DatabaseFlavorsClientJSON(rest_client.RestClient):
+
+    def __init__(self, auth_provider):
+        super(DatabaseFlavorsClientJSON, self).__init__(auth_provider)
+        self.service = CONF.database.catalog_type
+
+    def list_db_flavors(self, params=None):
+        url = 'flavors'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+
+        resp, body = self.get(url)
+        return resp, self._parse_resp(body)
+
+    def get_db_flavor_details(self, db_flavor_id):
+        resp, body = self.get("flavors/%s" % str(db_flavor_id))
+        return resp, self._parse_resp(body)