Add Trove (database) Flavor API Tests
Added Trove (database) service and flavor API tests.
Partially implements blueprint: trove-tempest
Change-Id: Ic4c43bd42fba96950b26232a37bcf300e1e742d1
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index ee2da40..ce867e6 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/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/config.py b/tempest/config.py
index 0f5e23c..dd5cc58 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)