Merge "Adds certificate tests for keystone v3"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 3cccf98..28a4d1c 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -454,6 +454,10 @@
# value)
#db_flavor_ref=1
+# Current database version to use in database tests. (string
+# value)
+#db_current_version=v1.0
+
[debug]
diff --git a/tempest/api/compute/admin/test_flavors_access.py b/tempest/api/compute/admin/test_flavors_access.py
index 193d415..3ba7314 100644
--- a/tempest/api/compute/admin/test_flavors_access.py
+++ b/tempest/api/compute/admin/test_flavors_access.py
@@ -32,15 +32,12 @@
msg = "FlavorExtraData extension not enabled."
raise cls.skipException(msg)
+ # Compute admin flavor client
cls.client = cls.os_adm.flavors_client
- admin_client = cls._get_identity_admin_client()
- cls.tenant = admin_client.get_tenant_by_name(cls.flavors_client.
- tenant_name)
- cls.tenant_id = cls.tenant['id']
- cls.adm_tenant = admin_client.get_tenant_by_name(cls.os_adm.
- flavors_client.
- tenant_name)
- cls.adm_tenant_id = cls.adm_tenant['id']
+ # Non admin tenant ID
+ cls.tenant_id = cls.flavors_client.tenant_id
+ # Compute admin tenant ID
+ cls.adm_tenant_id = cls.client.tenant_id
cls.flavor_name_prefix = 'test_flavor_access_'
cls.ram = 512
cls.vcpus = 1
diff --git a/tempest/api/compute/admin/test_flavors_access_negative.py b/tempest/api/compute/admin/test_flavors_access_negative.py
index 8fe3331..73834e9 100644
--- a/tempest/api/compute/admin/test_flavors_access_negative.py
+++ b/tempest/api/compute/admin/test_flavors_access_negative.py
@@ -36,14 +36,7 @@
raise cls.skipException(msg)
cls.client = cls.os_adm.flavors_client
- admin_client = cls._get_identity_admin_client()
- cls.tenant = admin_client.get_tenant_by_name(cls.flavors_client.
- tenant_name)
- cls.tenant_id = cls.tenant['id']
- cls.adm_tenant = admin_client.get_tenant_by_name(cls.os_adm.
- flavors_client.
- tenant_name)
- cls.adm_tenant_id = cls.adm_tenant['id']
+ cls.tenant_id = cls.flavors_client.tenant_id
cls.flavor_name_prefix = 'test_flavor_access_'
cls.ram = 512
cls.vcpus = 1
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index d6d5592..348666d 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -28,7 +28,7 @@
# NOTE(afazekas): these test cases should always create and use a new
# tenant most of them should be skipped if we can't do that
- cls.demo_tenant_id = cls.isolated_creds.get_primary_creds().tenant_id
+ cls.demo_tenant_id = cls.quotas_client.tenant_id
cls.default_quota_set = set(('injected_file_content_bytes',
'metadata_items', 'injected_files',
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index 10c3243..e1dc685 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -33,7 +33,7 @@
# NOTE(afazekas): these test cases should always create and use a new
# tenant most of them should be skipped if we can't do that
- cls.demo_tenant_id = cls.isolated_creds.get_primary_creds().tenant_id
+ cls.demo_tenant_id = cls.client.tenant_id
@test.attr(type=['negative', 'gate'])
def test_update_quota_normal_user(self):
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index 9fa07f6..8b3a0b5 100644
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -37,10 +37,7 @@
cls.client = cls.os_adm.servers_client
cls.non_adm_client = cls.servers_client
cls.flavors_client = cls.os_adm.flavors_client
- cls.identity_client = cls._get_identity_admin_client()
- tenant = cls.identity_client.get_tenant_by_name(
- cls.client.tenant_name)
- cls.tenant_id = tenant['id']
+ cls.tenant_id = cls.client.tenant_id
cls.s1_name = data_utils.rand_name('server')
resp, server = cls.create_test_server(name=cls.s1_name,
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage.py b/tempest/api/compute/admin/test_simple_tenant_usage.py
index 33cd6f3..f3a81d1 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage.py
@@ -27,11 +27,7 @@
super(TenantUsagesTestJSON, cls).setUpClass()
cls.adm_client = cls.os_adm.tenant_usages_client
cls.client = cls.os.tenant_usages_client
- cls.identity_client = cls._get_identity_admin_client()
-
- resp, tenants = cls.identity_client.list_tenants()
- cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
- cls.client.tenant_name][0]
+ cls.tenant_id = cls.client.tenant_id
# Create a server in the demo tenant
resp, server = cls.create_test_server(wait_until='ACTIVE')
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage_negative.py b/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
index a080f2e..d69c43c 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
@@ -52,11 +52,9 @@
params = {'start': self.end,
'end': self.start}
resp, tenants = self.identity_client.list_tenants()
- tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
- self.client.tenant_name][0]
self.assertRaises(exceptions.BadRequest,
self.adm_client.get_tenant_usage,
- tenant_id, params)
+ self.client.tenant_id, params)
@test.attr(type=['negative', 'gate'])
def test_list_usage_all_tenants_with_non_admin_user(self):
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 44340c3..7c70aec 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -56,6 +56,7 @@
cls.images = []
cls.multi_user = cls.get_multi_user()
cls.security_groups = []
+ cls.server_groups = []
if cls._api_version == 2:
cls.servers_client = cls.os.servers_client
@@ -191,11 +192,24 @@
LOG.exception(exc)
@classmethod
+ def clear_server_groups(cls):
+ for server_group_id in cls.server_groups:
+ try:
+ cls.client.delete_server_group(server_group_id)
+ except exceptions.NotFound:
+ # The server-group may have already been deleted which is OK.
+ pass
+ except Exception:
+ LOG.exception('Exception raised deleting server-group %s',
+ server_group_id)
+
+ @classmethod
def tearDownClass(cls):
cls.clear_images()
cls.clear_servers()
cls.clear_security_groups()
cls.clear_isolated_creds()
+ cls.clear_server_groups()
super(BaseComputeTest, cls).tearDownClass()
@classmethod
@@ -249,6 +263,16 @@
return resp, body
+ @classmethod
+ def create_test_server_group(cls, name="", policy=[]):
+ if not name:
+ name = data_utils.rand_name(cls.__name__ + "-Server-Group")
+ if not policy:
+ policy = ['affinity']
+ resp, body = cls.servers_client.create_server_group(name, policy)
+ cls.server_groups.append(body)
+ return resp, body
+
def wait_for(self, condition):
"""Repeatedly calls condition() until a timeout."""
start_time = int(time.time())
diff --git a/tempest/api/compute/certificates/test_certificates.py b/tempest/api/compute/certificates/test_certificates.py
index f6cadf7..0f921c5 100644
--- a/tempest/api/compute/certificates/test_certificates.py
+++ b/tempest/api/compute/certificates/test_certificates.py
@@ -17,13 +17,14 @@
from tempest import test
-class CertificatesTestJSON(base.BaseV2ComputeTest):
+class CertificatesV3Test(base.BaseComputeTest):
+
+ _api_version = 3
@test.attr(type='gate')
def test_create_root_certificate(self):
# create certificates
resp, body = self.certificates_client.create_certificate()
- self.assertEqual(200, resp.status)
self.assertIn('data', body)
self.assertIn('private_key', body)
@@ -36,5 +37,9 @@
self.assertIn('private_key', body)
-class CertificatesTestXML(CertificatesTestJSON):
+class CertificatesV2TestJSON(CertificatesV3Test):
+ _api_version = 2
+
+
+class CertificatesV2TestXML(CertificatesV2TestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index 3736f28..85ad29d 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -120,9 +120,9 @@
self.servers_client.delete_server(server_id)
self.servers_client.wait_for_server_termination(server_id)
- self.client.delete_security_group(sg['id'])
+ resp, _ = self.client.delete_security_group(sg['id'])
self.assertEqual(202, resp.status)
- self.client.delete_security_group(sg2['id'])
+ resp, _ = self.client.delete_security_group(sg2['id'])
self.assertEqual(202, resp.status)
@test.attr(type='smoke')
diff --git a/tempest/api/compute/servers/test_server_group.py b/tempest/api/compute/servers/test_server_group.py
new file mode 100644
index 0000000..0cd23fd
--- /dev/null
+++ b/tempest/api/compute/servers/test_server_group.py
@@ -0,0 +1,112 @@
+# Copyright 2014 NEC Technologies India Ltd.
+# 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.compute import base
+from tempest.common.utils import data_utils
+from tempest import test
+
+
+class ServerGroupTestJSON(base.BaseV2ComputeTest):
+ """
+ These tests check for the server-group APIs
+ They create/delete server-groups with different policies.
+ policies = affinity/anti-affinity
+ It also adds the tests for list and get details of server-groups
+ """
+ @classmethod
+ @test.safe_setup
+ def setUpClass(cls):
+ super(ServerGroupTestJSON, cls).setUpClass()
+ if not test.is_extension_enabled('os-server-groups', 'compute'):
+ msg = "os-server-groups extension is not enabled."
+ raise cls.skipException(msg)
+ cls.client = cls.servers_client
+ server_group_name = data_utils.rand_name('server-group')
+ cls.policy = ['affinity']
+
+ _, cls.created_server_group = cls.create_test_server_group(
+ server_group_name,
+ cls.policy)
+
+ def _create_server_group(self, name, policy):
+ # create the test server-group with given policy
+ server_group = {'name': name, 'policies': policy}
+ resp, body = self.create_test_server_group(name, policy)
+ self.assertEqual(200, resp.status)
+ for key in ['name', 'policies']:
+ self.assertEqual(server_group[key], body[key])
+ return body
+
+ def _delete_server_group(self, server_group):
+ # delete the test server-group
+ resp, _ = self.client.delete_server_group(server_group['id'])
+ self.assertEqual(204, resp.status)
+ # validation of server-group deletion
+ resp, server_group_list = self.client.list_server_groups()
+ self.assertEqual(200, resp.status)
+ self.assertNotIn(server_group, server_group_list)
+
+ def _create_delete_server_group(self, policy):
+ # Create and Delete the server-group with given policy
+ name = data_utils.rand_name('server-group')
+ server_group = self._create_server_group(name, policy)
+ self._delete_server_group(server_group)
+
+ @test.attr(type='gate')
+ def test_create_delete_server_group_with_affinity_policy(self):
+ # Create and Delete the server-group with affinity policy
+ self._create_delete_server_group(self.policy)
+
+ @test.attr(type='gate')
+ def test_create_delete_server_group_with_anti_affinity_policy(self):
+ # Create and Delete the server-group with anti-affinity policy
+ policy = ['anti-affinity']
+ self._create_delete_server_group(policy)
+
+ @test.attr(type='gate')
+ def test_create_delete_server_group_with_multiple_policies(self):
+ # Create and Delete the server-group with multiple policies
+ policies = ['affinity', 'affinity']
+ self._create_delete_server_group(policies)
+
+ @test.attr(type='gate')
+ def test_create_delete_multiple_server_groups_with_same_name_policy(self):
+ # Create and Delete the server-groups with same name and same policy
+ server_groups = []
+ server_group_name = data_utils.rand_name('server-group')
+ for i in range(0, 2):
+ server_groups.append(self._create_server_group(server_group_name,
+ self.policy))
+ for key in ['name', 'policies']:
+ self.assertEqual(server_groups[0][key], server_groups[1][key])
+ self.assertNotEqual(server_groups[0]['id'], server_groups[1]['id'])
+
+ for i in range(0, 2):
+ self._delete_server_group(server_groups[i])
+
+ @test.attr(type='gate')
+ def test_get_server_group(self):
+ # Get the server-group
+ resp, body = self.client.get_server_group(
+ self.created_server_group['id'])
+ self.assertEqual(200, resp.status)
+ self.assertEqual(self.created_server_group, body)
+
+ @test.attr(type='gate')
+ def test_list_server_groups(self):
+ # List the server-group
+ resp, body = self.client.list_server_groups()
+ self.assertEqual(200, resp.status)
+ self.assertIn(self.created_server_group, body)
diff --git a/tempest/api/compute/servers/test_server_metadata_negative.py b/tempest/api/compute/servers/test_server_metadata_negative.py
index 8b69c78..b55833c 100644
--- a/tempest/api/compute/servers/test_server_metadata_negative.py
+++ b/tempest/api/compute/servers/test_server_metadata_negative.py
@@ -26,10 +26,7 @@
super(ServerMetadataNegativeTestJSON, cls).setUpClass()
cls.client = cls.servers_client
cls.quotas = cls.quotas_client
- cls.admin_client = cls._get_identity_admin_client()
- resp, tenants = cls.admin_client.list_tenants()
- cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
- cls.client.tenant_name][0]
+ cls.tenant_id = cls.client.tenant_id
resp, server = cls.create_test_server(meta={}, wait_until='ACTIVE')
cls.server_id = server['id']
diff --git a/tempest/api/compute/test_quotas.py b/tempest/api/compute/test_quotas.py
index 4db8c56..dc85e76 100644
--- a/tempest/api/compute/test_quotas.py
+++ b/tempest/api/compute/test_quotas.py
@@ -23,13 +23,8 @@
def setUpClass(cls):
super(QuotasTestJSON, cls).setUpClass()
cls.client = cls.quotas_client
- cls.admin_client = cls._get_identity_admin_client()
- resp, tenants = cls.admin_client.list_tenants()
- cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
- cls.client.tenant_name][0]
- resp, users = cls.admin_client.list_users_for_tenant(cls.tenant_id)
- cls.user_id = [user['id'] for user in users if user['name'] ==
- cls.client.user][0]
+ cls.tenant_id = cls.client.tenant_id
+ cls.user_id = cls.client.user_id
cls.default_quota_set = set(('injected_file_content_bytes',
'metadata_items', 'injected_files',
'ram', 'floating_ips',
diff --git a/tempest/api/compute/v3/admin/test_flavors_access.py b/tempest/api/compute/v3/admin/test_flavors_access.py
index 03305ff..c641bf6 100644
--- a/tempest/api/compute/v3/admin/test_flavors_access.py
+++ b/tempest/api/compute/v3/admin/test_flavors_access.py
@@ -31,12 +31,8 @@
cls.client = cls.flavors_admin_client
admin_client = cls._get_identity_admin_client()
- cls.tenant = admin_client.get_tenant_by_name(cls.flavors_client.
- tenant_name)
- cls.tenant_id = cls.tenant['id']
- cls.adm_tenant = admin_client.get_tenant_by_name(
- cls.flavors_admin_client.tenant_name)
- cls.adm_tenant_id = cls.adm_tenant['id']
+ cls.tenant_id = cls.client.tenant_id
+ cls.adm_tenant_id = admin_client.tenant_id
cls.flavor_name_prefix = 'test_flavor_access_'
cls.ram = 512
cls.vcpus = 1
diff --git a/tempest/api/compute/v3/admin/test_flavors_access_negative.py b/tempest/api/compute/v3/admin/test_flavors_access_negative.py
index 334d124..02ecb24 100644
--- a/tempest/api/compute/v3/admin/test_flavors_access_negative.py
+++ b/tempest/api/compute/v3/admin/test_flavors_access_negative.py
@@ -33,13 +33,7 @@
super(FlavorsAccessNegativeV3Test, cls).setUpClass()
cls.client = cls.flavors_admin_client
- admin_client = cls._get_identity_admin_client()
- cls.tenant = admin_client.get_tenant_by_name(cls.flavors_client.
- tenant_name)
- cls.tenant_id = cls.tenant['id']
- cls.adm_tenant = admin_client.get_tenant_by_name(
- cls.flavors_admin_client.tenant_name)
- cls.adm_tenant_id = cls.adm_tenant['id']
+ cls.tenant_id = cls.client.tenant_id
cls.flavor_name_prefix = 'test_flavor_access_'
cls.ram = 512
cls.vcpus = 1
diff --git a/tempest/api/compute/v3/admin/test_quotas.py b/tempest/api/compute/v3/admin/test_quotas.py
index 27836fb..19c31fe 100644
--- a/tempest/api/compute/v3/admin/test_quotas.py
+++ b/tempest/api/compute/v3/admin/test_quotas.py
@@ -32,7 +32,7 @@
# NOTE(afazekas): these test cases should always create and use a new
# tenant most of them should be skipped if we can't do that
- cls.demo_tenant_id = cls.isolated_creds.get_primary_creds().tenant_id
+ cls.demo_tenant_id = cls.client.tenant_id
cls.default_quota_set = set(('metadata_items',
'ram', 'floating_ips',
diff --git a/tempest/api/compute/v3/admin/test_servers_negative.py b/tempest/api/compute/v3/admin/test_servers_negative.py
index fba4cd1..a46da47 100644
--- a/tempest/api/compute/v3/admin/test_servers_negative.py
+++ b/tempest/api/compute/v3/admin/test_servers_negative.py
@@ -37,10 +37,7 @@
cls.client = cls.servers_admin_client
cls.non_adm_client = cls.servers_client
cls.flavors_client = cls.flavors_admin_client
- cls.identity_client = cls._get_identity_admin_client()
- tenant = cls.identity_client.get_tenant_by_name(
- cls.client.tenant_name)
- cls.tenant_id = tenant['id']
+ cls.tenant_id = cls.client.tenant_id
cls.s1_name = data_utils.rand_name('server')
resp, server = cls.create_test_server(name=cls.s1_name,
diff --git a/tempest/api/compute/v3/certificates/test_certificates.py b/tempest/api/compute/v3/certificates/test_certificates.py
deleted file mode 100644
index 0ba44cb..0000000
--- a/tempest/api/compute/v3/certificates/test_certificates.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright 2012 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.compute import base
-from tempest.test import attr
-
-
-class CertificatesV3Test(base.BaseV3ComputeTest):
-
- @attr(type='gate')
- def test_create_root_certificate(self):
- # create certificates
- resp, body = self.certificates_client.create_certificate()
- self.assertEqual(201, resp.status)
- self.assertIn('data', body)
- self.assertIn('private_key', body)
-
- @attr(type='gate')
- def test_get_root_certificate(self):
- # get the root certificate
- resp, body = self.certificates_client.get_certificate('root')
- self.assertEqual(200, resp.status)
- self.assertIn('data', body)
- self.assertIn('private_key', body)
diff --git a/tempest/api/compute/v3/servers/test_server_metadata.py b/tempest/api/compute/v3/servers/test_server_metadata.py
index 0e4ef07..298cd3c 100644
--- a/tempest/api/compute/v3/servers/test_server_metadata.py
+++ b/tempest/api/compute/v3/servers/test_server_metadata.py
@@ -24,10 +24,7 @@
super(ServerMetadataV3Test, cls).setUpClass()
cls.client = cls.servers_client
cls.quotas = cls.quotas_client
- cls.admin_client = cls._get_identity_admin_client()
- resp, tenants = cls.admin_client.list_tenants()
- cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
- cls.client.tenant_name][0]
+ cls.tenant_id = cls.client.tenant_id
resp, server = cls.create_test_server(meta={}, wait_until='ACTIVE')
cls.server_id = server['id']
diff --git a/tempest/api/compute/v3/servers/test_server_metadata_negative.py b/tempest/api/compute/v3/servers/test_server_metadata_negative.py
index ec2bc8c..f746be3 100644
--- a/tempest/api/compute/v3/servers/test_server_metadata_negative.py
+++ b/tempest/api/compute/v3/servers/test_server_metadata_negative.py
@@ -25,10 +25,7 @@
super(ServerMetadataV3NegativeTest, cls).setUpClass()
cls.client = cls.servers_client
cls.quotas = cls.quotas_client
- cls.admin_client = cls._get_identity_admin_client()
- resp, tenants = cls.admin_client.list_tenants()
- cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
- cls.client.tenant_name][0]
+ cls.tenant_id = cls.client.tenant_id
resp, server = cls.create_test_server(meta={}, wait_until='ACTIVE')
cls.server_id = server['id']
diff --git a/tempest/api/compute/v3/test_quotas.py b/tempest/api/compute/v3/test_quotas.py
index 3fe62e9..62a7556 100644
--- a/tempest/api/compute/v3/test_quotas.py
+++ b/tempest/api/compute/v3/test_quotas.py
@@ -23,13 +23,8 @@
def setUpClass(cls):
super(QuotasV3Test, cls).setUpClass()
cls.client = cls.quotas_client
- cls.admin_client = cls._get_identity_admin_client()
- resp, tenants = cls.admin_client.list_tenants()
- cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
- cls.client.tenant_name][0]
- resp, users = cls.admin_client.list_users_for_tenant(cls.tenant_id)
- cls.user_id = [user['id'] for user in users if user['name'] ==
- cls.client.user][0]
+ cls.tenant_id = cls.client.tenant_id
+ cls.user_id = cls.client.user_id
cls.default_quota_set = set(('metadata_items',
'ram', 'floating_ips',
'fixed_ips', 'key_pairs',
diff --git a/tempest/api/database/base.py b/tempest/api/database/base.py
index 8add9ba..cf70d11 100644
--- a/tempest/api/database/base.py
+++ b/tempest/api/database/base.py
@@ -36,7 +36,9 @@
cls.catalog_type = CONF.database.catalog_type
cls.db_flavor_ref = CONF.database.db_flavor_ref
+ cls.db_current_version = CONF.database.db_current_version
os = cls.get_client_manager()
cls.os = os
cls.database_flavors_client = cls.os.database_flavors_client
+ cls.database_versions_client = cls.os.database_versions_client
diff --git a/tempest/api/compute/v3/certificates/__init__.py b/tempest/api/database/versions/__init__.py
similarity index 100%
rename from tempest/api/compute/v3/certificates/__init__.py
rename to tempest/api/database/versions/__init__.py
diff --git a/tempest/api/database/versions/test_versions.py b/tempest/api/database/versions/test_versions.py
new file mode 100644
index 0000000..6101f47
--- /dev/null
+++ b/tempest/api/database/versions/test_versions.py
@@ -0,0 +1,40 @@
+# 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 DatabaseVersionsTest(base.BaseDatabaseTest):
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(DatabaseVersionsTest, cls).setUpClass()
+ cls.client = cls.database_versions_client
+
+ @test.attr(type='smoke')
+ def test_list_db_versions(self):
+ resp, versions = self.client.list_db_versions()
+ self.assertEqual(200, resp.status)
+ self.assertTrue(len(versions) > 0, "No database versions found")
+ # List of all versions should contain the current version, and there
+ # should only be one 'current' version
+ current_versions = list()
+ for version in versions:
+ if 'CURRENT' == version['status']:
+ current_versions.append(version['id'])
+ self.assertEqual(1, len(current_versions))
+ self.assertIn(self.db_current_version, current_versions)
diff --git a/tempest/api/identity/admin/test_users.py b/tempest/api/identity/admin/test_users.py
index a4e6c17..e2c1066 100644
--- a/tempest/api/identity/admin/test_users.py
+++ b/tempest/api/identity/admin/test_users.py
@@ -206,6 +206,25 @@
"Failed to find user %s in fetched list" %
', '.join(m_user for m_user in missing_users))
+ @test.attr(type='smoke')
+ def test_update_user_password(self):
+ # Test case to check if updating of user password is successful.
+ self.data.setup_test_user()
+ # Updating the user with new password
+ new_pass = data_utils.rand_name('pass-')
+ resp, update_user = self.client.update_user_password(
+ self.data.user['id'], new_pass)
+ # Assert response body of update user.
+ self.assertEqual(200, resp.status)
+ self.assertEqual(update_user['id'], self.data.user['id'])
+
+ # Validate the updated password
+ # Get a token
+ resp, body = self.token_client.auth(self.data.test_user, new_pass,
+ self.data.test_tenant)
+ self.assertEqual('200', resp['status'])
+ self.assertTrue('id' in body['token'])
+
class UsersTestXML(UsersTestJSON):
_interface = 'xml'
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 31ffd14..e31e635 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -93,14 +93,11 @@
super(BaseV1ImageMembersTest, cls).setUpClass()
if CONF.compute.allow_tenant_isolation:
cls.os_alt = clients.Manager(cls.isolated_creds.get_alt_creds())
- cls.alt_tenant_id = cls.isolated_creds.get_alt_tenant()['id']
else:
cls.os_alt = clients.AltManager()
- identity_client = cls._get_identity_admin_client()
- cls.alt_tenant_id = identity_client.get_tenant_by_name(
- cls.os_alt.credentials['tenant_name'])['id']
cls.alt_img_cli = cls.os_alt.image_client
+ cls.alt_tenant_id = cls.alt_img_cli.tenant_id
def _create_image(self):
image_file = StringIO.StringIO('*' * 1024)
diff --git a/tempest/api/network/admin/test_floating_ips_admin_actions.py b/tempest/api/network/admin/test_floating_ips_admin_actions.py
new file mode 100644
index 0000000..5728432
--- /dev/null
+++ b/tempest/api/network/admin/test_floating_ips_admin_actions.py
@@ -0,0 +1,72 @@
+# 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.network import base
+from tempest import clients
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+
+class FloatingIPAdminTestJSON(base.BaseAdminNetworkTest):
+ _interface = 'json'
+ force_tenant_isolation = True
+
+ @classmethod
+ def setUpClass(cls):
+ super(FloatingIPAdminTestJSON, cls).setUpClass()
+ cls.ext_net_id = CONF.network.public_network_id
+ cls.floating_ip = cls.create_floatingip(cls.ext_net_id)
+ cls.alt_manager = clients.Manager(cls.isolated_creds.get_alt_creds())
+ cls.alt_client = cls.alt_manager.network_client
+
+ @test.attr(type='smoke')
+ def test_list_floating_ips_from_admin_and_nonadmin(self):
+ # Create floating ip from admin user
+ resp, floating_ip_admin = self.admin_client.create_floatingip(
+ floating_network_id=self.ext_net_id)
+ self.assertEqual('201', resp['status'])
+ self.addCleanup(self.admin_client.delete_floatingip,
+ floating_ip_admin['floatingip']['id'])
+ # Create floating ip from alt user
+ resp, body = self.alt_client.create_floatingip(
+ floating_network_id=self.ext_net_id)
+ self.assertEqual('201', resp['status'])
+ floating_ip_alt = body['floatingip']
+ self.addCleanup(self.alt_client.delete_floatingip,
+ floating_ip_alt['id'])
+ # List floating ips from admin
+ resp, body = self.admin_client.list_floatingips()
+ self.assertEqual('200', resp['status'])
+ floating_ip_ids_admin = [f['id'] for f in body['floatingips']]
+ # Check that admin sees all floating ips
+ self.assertIn(self.floating_ip['id'], floating_ip_ids_admin)
+ self.assertIn(floating_ip_admin['floatingip']['id'],
+ floating_ip_ids_admin)
+ self.assertIn(floating_ip_alt['id'], floating_ip_ids_admin)
+ # List floating ips from nonadmin
+ resp, body = self.client.list_floatingips()
+ floating_ip_ids = [f['id'] for f in body['floatingips']]
+ # Check that nonadmin user doesn't see floating ip created from admin
+ # and floating ip that is created in another tenant (alt user)
+ self.assertIn(self.floating_ip['id'], floating_ip_ids)
+ self.assertNotIn(floating_ip_admin['floatingip']['id'],
+ floating_ip_ids)
+ self.assertNotIn(floating_ip_alt['id'], floating_ip_ids)
+
+
+class FloatingIPAdminTestXML(FloatingIPAdminTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index 7191940..d0d25ec 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -78,6 +78,8 @@
self.assertEqual(created_floating_ip['port_id'], self.ports[0]['id'])
self.assertEqual(created_floating_ip['floating_network_id'],
self.ext_net_id)
+ self.assertIn(created_floating_ip['fixed_ip_address'],
+ [ip['ip_address'] for ip in self.ports[0]['fixed_ips']])
# Verifies the details of a floating_ip
resp, floating_ip = self.client.show_floatingip(
created_floating_ip['id'])
@@ -172,6 +174,24 @@
port_other_router['id'])
self.assertIsNotNone(updated_floating_ip['fixed_ip_address'])
+ @test.attr(type='smoke')
+ def test_create_floating_ip_specifying_a_fixed_ip_address(self):
+ resp, body = self.client.create_floatingip(
+ floating_network_id=self.ext_net_id,
+ port_id=self.ports[1]['id'],
+ fixed_ip_address=self.ports[1]['fixed_ips'][0]['ip_address'])
+ self.assertEqual('201', resp['status'])
+ created_floating_ip = body['floatingip']
+ self.addCleanup(self.client.delete_floatingip,
+ created_floating_ip['id'])
+ self.assertIsNotNone(created_floating_ip['id'])
+ self.assertEqual(created_floating_ip['fixed_ip_address'],
+ self.ports[1]['fixed_ips'][0]['ip_address'])
+ resp, floating_ip = self.client.update_floatingip(
+ created_floating_ip['id'], port_id=None)
+ self.assertEqual('200', resp['status'])
+ self.assertIsNone(floating_ip['floatingip']['port_id'])
+
class FloatingIPTestXML(FloatingIPTestJSON):
_interface = 'xml'
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 660b376..ac0fd11 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -234,6 +234,8 @@
@test.attr(type='smoke')
def test_create_delete_subnet_without_gw(self):
+ net = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
+ gateway_ip = str(netaddr.IPAddress(net.first + 1))
name = data_utils.rand_name('network-')
resp, body = self.client.create_network(name=name)
self.assertEqual('201', resp['status'])
@@ -241,7 +243,7 @@
net_id = network['id']
subnet = self.create_subnet(network)
# Verifies Subnet GW in IPv4
- self.assertEqual(subnet['gateway_ip'], '10.100.0.1')
+ self.assertEqual(subnet['gateway_ip'], gateway_ip)
# Delete network and subnet
resp, body = self.client.delete_network(net_id)
self.assertEqual('204', resp['status'])
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index 021555c..19e3068 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -47,15 +47,11 @@
msg = "No ResellerAdmin role found"
raise exceptions.NotFound(msg)
- # Retrieve the ResellerAdmin tenant id
- _, users = cls.os_admin.identity_client.get_users()
- reseller_user_id = next(usr['id'] for usr in users if usr['name']
- == cls.data.test_user)
+ # Retrieve the ResellerAdmin user id
+ reseller_user_id = cls.data.test_credentials.user_id
# Retrieve the ResellerAdmin tenant id
- _, tenants = cls.os_admin.identity_client.list_tenants()
- reseller_tenant_id = next(tnt['id'] for tnt in tenants if tnt['name']
- == cls.data.test_tenant)
+ reseller_tenant_id = cls.data.test_credentials.tenant_id
# Assign the newly created user the appropriate ResellerAdmin role
cls.os_admin.identity_client.assign_user_role(
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index f1355db..6afd381 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -48,14 +48,10 @@
raise exceptions.NotFound(msg)
# Retrieve the ResellerAdmin tenant id
- _, users = cls.os_admin.identity_client.get_users()
- reseller_user_id = next(usr['id'] for usr in users if usr['name']
- == cls.data.test_user)
+ reseller_user_id = cls.data.test_credentials.user_id
# Retrieve the ResellerAdmin tenant id
- _, tenants = cls.os_admin.identity_client.list_tenants()
- reseller_tenant_id = next(tnt['id'] for tnt in tenants if tnt['name']
- == cls.data.test_tenant)
+ reseller_tenant_id = cls.data.test_credentials.tenant_id
# Assign the newly created user the appropriate ResellerAdmin role
cls.os_admin.identity_client.assign_user_role(
diff --git a/tempest/api/volume/admin/test_volume_quotas_negative.py b/tempest/api/volume/admin/test_volume_quotas_negative.py
index 292f8ed..ab88b90 100644
--- a/tempest/api/volume/admin/test_volume_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_quotas_negative.py
@@ -26,8 +26,8 @@
@test.safe_setup
def setUpClass(cls):
super(VolumeQuotasNegativeTestJSON, cls).setUpClass()
- demo_user = cls.isolated_creds.get_primary_user()
- cls.demo_tenant_id = demo_user.get('tenantId')
+ demo_user = cls.isolated_creds.get_primary_creds()
+ cls.demo_tenant_id = demo_user.tenant_id
cls.shared_quota_set = {'gigabytes': 3, 'volumes': 1, 'snapshots': 1}
# NOTE(gfidente): no need to restore original quota set
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
index 1ef93b9..82d1364 100644
--- a/tempest/api/volume/test_volume_transfers.py
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -34,22 +34,16 @@
if CONF.compute.allow_tenant_isolation:
cls.os_alt = clients.Manager(cls.isolated_creds.get_alt_creds(),
interface=cls._interface)
- cls.alt_tenant_id = cls.isolated_creds.get_alt_tenant()['id']
# Add admin tenant to cleanup resources
cls.os_adm = clients.Manager(cls.isolated_creds.get_admin_creds(),
interface=cls._interface)
-
else:
cls.os_alt = clients.AltManager()
- alt_tenant_name = cls.os_alt.credentials['tenant_name']
- identity_client = cls._get_identity_admin_client()
- _, tenants = identity_client.list_tenants()
- cls.alt_tenant_id = [tnt['id'] for tnt in tenants
- if tnt['name'] == alt_tenant_name][0]
cls.os_adm = clients.ComputeAdminManager(interface=cls._interface)
cls.client = cls.volumes_client
cls.alt_client = cls.os_alt.volumes_client
+ cls.alt_tenant_id = cls.alt_client.tenant_id
cls.adm_client = cls.os_adm.volumes_client
def _delete_volume(self, volume_id):
diff --git a/tempest/api_schema/compute/v2/servers.py b/tempest/api_schema/compute/v2/servers.py
index 05d37af..e90f436 100644
--- a/tempest/api_schema/compute/v2/servers.py
+++ b/tempest/api_schema/compute/v2/servers.py
@@ -123,3 +123,8 @@
'required': ['meta']
}
}
+
+list_addresses_by_network = {
+ 'status_code': [200],
+ 'response_body': parameter_types.addresses
+}
diff --git a/tempest/api_schema/compute/v3/servers.py b/tempest/api_schema/compute/v3/servers.py
index 6926dbd..956b5ad 100644
--- a/tempest/api_schema/compute/v3/servers.py
+++ b/tempest/api_schema/compute/v3/servers.py
@@ -76,3 +76,8 @@
}
set_get_server_metadata_item = copy.deepcopy(servers.set_server_metadata)
+
+list_addresses_by_network = {
+ 'status_code': [200],
+ 'response_body': addresses_v3
+}
diff --git a/tempest/clients.py b/tempest/clients.py
index b9550fd..e50a0c3 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -117,6 +117,8 @@
from tempest.services.data_processing.v1_1.client import DataProcessingClient
from tempest.services.database.json.flavors_client import \
DatabaseFlavorsClientJSON
+from tempest.services.database.json.versions_client import \
+ DatabaseVersionsClientJSON
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 \
@@ -345,6 +347,8 @@
self.hosts_v3_client = HostsV3ClientJSON(self.auth_provider)
self.database_flavors_client = DatabaseFlavorsClientJSON(
self.auth_provider)
+ self.database_versions_client = DatabaseVersionsClientJSON(
+ self.auth_provider)
self.queuing_client = QueuingClientJSON(self.auth_provider)
if CONF.service_available.ceilometer:
self.telemetry_client = TelemetryClientJSON(
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 5059a5b..b4618ed 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -31,7 +31,6 @@
password='pass', network_resources=None):
self.network_resources = network_resources
self.isolated_creds = {}
- self.isolated_creds_old_style = {}
self.isolated_net_resources = {}
self.ports = []
self.name = name
@@ -166,7 +165,7 @@
self._assign_user_role(tenant['id'], user['id'], role['id'])
else:
self._assign_user_role(tenant.id, user.id, role.id)
- return self._get_credentials(user, tenant), user, tenant
+ return self._get_credentials(user, tenant)
def _get_credentials(self, user, tenant):
if self.tempest_client:
@@ -292,30 +291,6 @@
body = {'subnet_id': subnet_id}
self.network_admin_client.add_interface_router(router_id, body)
- def get_primary_tenant(self):
- # Deprecated. Maintained until all tests are ported
- return self.isolated_creds_old_style.get('primary')[1]
-
- def get_primary_user(self):
- # Deprecated. Maintained until all tests are ported
- return self.isolated_creds_old_style.get('primary')[0]
-
- def get_alt_tenant(self):
- # Deprecated. Maintained until all tests are ported
- return self.isolated_creds_old_style.get('alt')[1]
-
- def get_alt_user(self):
- # Deprecated. Maintained until all tests are ported
- return self.isolated_creds_old_style.get('alt')[0]
-
- def get_admin_tenant(self):
- # Deprecated. Maintained until all tests are ported
- return self.isolated_creds_old_style.get('admin')[1]
-
- def get_admin_user(self):
- # Deprecated. Maintained until all tests are ported
- return self.isolated_creds_old_style.get('admin')[0]
-
def get_primary_network(self):
return self.isolated_net_resources.get('primary')[0]
@@ -343,15 +318,14 @@
def get_alt_router(self):
return self.isolated_net_resources.get('alt')[2]
- def get_credentials(self, credential_type, old_style):
+ def get_credentials(self, credential_type):
if self.isolated_creds.get(credential_type):
credentials = self.isolated_creds[credential_type]
else:
is_admin = (credential_type == 'admin')
- credentials, user, tenant = self._create_creds(admin=is_admin)
+ credentials = self._create_creds(admin=is_admin)
self.isolated_creds[credential_type] = credentials
# Maintained until tests are ported
- self.isolated_creds_old_style[credential_type] = (user, tenant)
LOG.info("Acquired isolated creds:\n credentials: %s"
% credentials)
if CONF.service_available.neutron:
@@ -361,20 +335,16 @@
network, subnet, router,)
LOG.info("Created isolated network resources for : \n"
+ " credentials: %s" % credentials)
- if old_style:
- return (credentials.username, credentials.tenant_name,
- credentials.password)
- else:
- return credentials
+ return credentials
- def get_primary_creds(self, old_style=False):
- return self.get_credentials('primary', old_style)
+ def get_primary_creds(self):
+ return self.get_credentials('primary')
- def get_admin_creds(self, old_style=False):
- return self.get_credentials('admin', old_style)
+ def get_admin_creds(self):
+ return self.get_credentials('admin')
- def get_alt_creds(self, old_style=False):
- return self.get_credentials('alt', old_style)
+ def get_alt_creds(self):
+ return self.get_credentials('alt')
def _clear_isolated_router(self, router_id, router_name):
net_client = self.network_admin_client
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index 02a8c65..10223a0 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -143,6 +143,10 @@
return self.auth_provider.credentials.username
@property
+ def user_id(self):
+ return self.auth_provider.credentials.user_id
+
+ @property
def tenant_name(self):
return self.auth_provider.credentials.tenant_name
diff --git a/tempest/config.py b/tempest/config.py
index 9bb77af..f9be90d 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -566,6 +566,9 @@
cfg.StrOpt('db_flavor_ref',
default="1",
help="Valid primary flavor to use in database tests."),
+ cfg.StrOpt('db_current_version',
+ default="v1.0",
+ help="Current database version to use in database tests."),
]
orchestration_group = cfg.OptGroup(name='orchestration',
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 0ef34c6..e057c74 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -114,8 +114,10 @@
resource.delete()
except Exception as e:
# If the resource is already missing, mission accomplished.
- # add status code as workaround for bug 1247568
- if (e.__class__.__name__ == 'NotFound' or
+ # - Status code tolerated as a workaround for bug 1247568
+ # - HTTPNotFound tolerated as this is currently raised when
+ # attempting to delete an already-deleted heat stack.
+ if (e.__class__.__name__ in ('NotFound', 'HTTPNotFound') or
(hasattr(e, 'status_code') and e.status_code == 404)):
return
raise
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index 831ceb8..5204cd0 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -200,6 +200,7 @@
resp, body = self.get("servers/%s/ips/%s" %
(str(server_id), network_id))
body = json.loads(body)
+ self.validate_response(schema.list_addresses_by_network, resp, body)
return resp, body
def action(self, server_id, action_name, response_key,
@@ -477,3 +478,36 @@
return self.action(server_id, "os-getVNCConsole",
"console", common_schema.get_vnc_console,
type=console_type)
+
+ def create_server_group(self, name, policies):
+ """
+ Create the server group
+ name : Name of the server-group
+ policies : List of the policies - affinity/anti-affinity)
+ """
+ post_body = {
+ 'name': name,
+ 'policies': policies,
+ }
+
+ post_body = json.dumps({'server_group': post_body})
+ resp, body = self.post('os-server-groups', post_body)
+
+ body = json.loads(body)
+ return resp, body['server_group']
+
+ def delete_server_group(self, server_group_id):
+ """Delete the given server-group."""
+ return self.delete("os-server-groups/%s" % str(server_group_id))
+
+ def list_server_groups(self):
+ """List the server-groups."""
+ resp, body = self.get("os-server-groups")
+ body = json.loads(body)
+ return resp, body['server_groups']
+
+ def get_server_group(self, server_group_id):
+ """Get the details of given server_group."""
+ resp, body = self.get("os-server-groups/%s" % str(server_group_id))
+ body = json.loads(body)
+ return resp, body['server_group']
diff --git a/tempest/services/compute/v3/json/servers_client.py b/tempest/services/compute/v3/json/servers_client.py
index ecfaffa..1990d39 100644
--- a/tempest/services/compute/v3/json/servers_client.py
+++ b/tempest/services/compute/v3/json/servers_client.py
@@ -200,6 +200,7 @@
resp, body = self.get("servers/%s/ips/%s" %
(str(server_id), network_id))
body = json.loads(body)
+ self.validate_response(schema.list_addresses_by_network, resp, body)
return resp, body
def action(self, server_id, action_name, response_key, **kwargs):
diff --git a/tempest/services/database/json/versions_client.py b/tempest/services/database/json/versions_client.py
new file mode 100644
index 0000000..0269c43
--- /dev/null
+++ b/tempest/services/database/json/versions_client.py
@@ -0,0 +1,38 @@
+# 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.
+
+import urllib
+
+from tempest.common import rest_client
+from tempest import config
+
+CONF = config.CONF
+
+
+class DatabaseVersionsClientJSON(rest_client.RestClient):
+
+ def __init__(self, auth_provider):
+ super(DatabaseVersionsClientJSON, self).__init__(auth_provider)
+ self.skip_path()
+ self.service = CONF.database.catalog_type
+
+ def list_db_versions(self, params=None):
+ """List all versions."""
+ url = ''
+ if params:
+ url += '?%s' % urllib.urlencode(params)
+
+ resp, body = self.get(url)
+ return resp, self._parse_resp(body)
diff --git a/tempest/services/identity/json/identity_client.py b/tempest/services/identity/json/identity_client.py
index 55239f7..479a289 100644
--- a/tempest/services/identity/json/identity_client.py
+++ b/tempest/services/identity/json/identity_client.py
@@ -227,6 +227,16 @@
url = '/OS-KSADM/services/%s' % service_id
return self.delete(url)
+ def update_user_password(self, user_id, new_pass):
+ """Update User Password."""
+ put_body = {
+ 'password': new_pass,
+ 'id': user_id
+ }
+ put_body = json.dumps({'user': put_body})
+ resp, body = self.put('users/%s/OS-KSADM/password' % user_id, put_body)
+ return resp, self._parse_resp(body)
+
class TokenClientJSON(IdentityClientJSON):
diff --git a/tempest/services/identity/xml/identity_client.py b/tempest/services/identity/xml/identity_client.py
index c48bc90..b213c1a 100644
--- a/tempest/services/identity/xml/identity_client.py
+++ b/tempest/services/identity/xml/identity_client.py
@@ -118,6 +118,15 @@
str(xml.Document(create_service)))
return resp, self._parse_resp(body)
+ def update_user_password(self, user_id, new_pass):
+ """Update User Password."""
+ put_body = xml.Element("user",
+ id=user_id,
+ password=new_pass)
+ resp, body = self.put('users/%s/OS-KSADM/password' % user_id,
+ str(xml.Document(put_body)))
+ return resp, self._parse_resp(body)
+
class TokenClientXML(identity_client.TokenClientJSON):
TYPE = "xml"
diff --git a/tempest/services/volume/xml/volumes_client.py b/tempest/services/volume/xml/volumes_client.py
index 65bc321..9799e55 100644
--- a/tempest/services/volume/xml/volumes_client.py
+++ b/tempest/services/volume/xml/volumes_client.py
@@ -26,6 +26,11 @@
CONF = config.CONF
+VOLUME_NS_BASE = 'http://docs.openstack.org/volume/ext/'
+VOLUME_HOST_NS = VOLUME_NS_BASE + 'volume_host_attribute/api/v1'
+VOLUME_MIG_STATUS_NS = VOLUME_NS_BASE + 'volume_mig_status_attribute/api/v1'
+VOLUMES_TENANT_NS = VOLUME_NS_BASE + 'volume_tenant_attribute/api/v1'
+
class VolumesClientXML(rest_client.RestClient):
"""
@@ -39,6 +44,23 @@
self.build_interval = CONF.compute.build_interval
self.build_timeout = CONF.compute.build_timeout
+ def _translate_attributes_to_json(self, volume):
+ volume_host_attr = '{' + VOLUME_HOST_NS + '}host'
+ volume_mig_stat_attr = '{' + VOLUME_MIG_STATUS_NS + '}migstat'
+ volume_mig_name_attr = '{' + VOLUME_MIG_STATUS_NS + '}name_id'
+ volume_tenant_id_attr = '{' + VOLUMES_TENANT_NS + '}tenant_id'
+ if volume_host_attr in volume:
+ volume['os-vol-host-attr:host'] = volume.pop(volume_host_attr)
+ if volume_mig_stat_attr in volume:
+ volume['os-vol-mig-status-attr:migstat'] = volume.pop(
+ volume_mig_stat_attr)
+ if volume_mig_name_attr in volume:
+ volume['os-vol-mig-status-attr:name_id'] = volume.pop(
+ volume_mig_name_attr)
+ if volume_tenant_id_attr in volume:
+ volume['os-vol-tenant-attr:tenant_id'] = volume.pop(
+ volume_tenant_id_attr)
+
def _parse_volume(self, body):
vol = dict((attr, body.get(attr)) for attr in body.keys())
@@ -52,6 +74,8 @@
child.getchildren())
else:
vol[tag] = common.xml_to_json(child)
+ self._translate_attributes_to_json(vol)
+ self._check_if_bootable(vol)
return vol
def get_attachment_from_volume(self, volume):
@@ -90,8 +114,6 @@
volumes = []
if body is not None:
volumes += [self._parse_volume(vol) for vol in list(body)]
- for v in volumes:
- v = self._check_if_bootable(v)
return resp, volumes
def list_volumes_with_detail(self, params=None):
@@ -106,8 +128,6 @@
volumes = []
if body is not None:
volumes += [self._parse_volume(vol) for vol in list(body)]
- for v in volumes:
- v = self._check_if_bootable(v)
return resp, volumes
def get_volume(self, volume_id):
@@ -115,7 +135,6 @@
url = "volumes/%s" % str(volume_id)
resp, body = self.get(url)
body = self._parse_volume(etree.fromstring(body))
- body = self._check_if_bootable(body)
return resp, body
def create_volume(self, size=None, **kwargs):
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py
index 98a896f..9292dcb 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/test_tenant_isolation.py
@@ -121,14 +121,12 @@
password='fake_password')
self._mock_tenant_create('1234', 'fake_prim_tenant')
self._mock_user_create('1234', 'fake_prim_user')
- primary_creds = iso_creds.get_primary_creds(old_style=False)
+ primary_creds = iso_creds.get_primary_creds()
self.assertEqual(primary_creds.username, 'fake_prim_user')
self.assertEqual(primary_creds.tenant_name, 'fake_prim_tenant')
- # Verify helper methods
- tenant = iso_creds.get_primary_tenant()
- user = iso_creds.get_primary_user()
- self.assertEqual(tenant['id'], '1234')
- self.assertEqual(user['id'], '1234')
+ # Verify IDs
+ self.assertEqual(primary_creds.tenant_id, '1234')
+ self.assertEqual(primary_creds.user_id, '1234')
@patch('tempest.common.rest_client.RestClient')
def test_admin_creds(self, MockRestClient):
@@ -153,11 +151,9 @@
user_mock.assert_called_once_with('1234', '1234', '1234')
self.assertEqual(admin_creds.username, 'fake_admin_user')
self.assertEqual(admin_creds.tenant_name, 'fake_admin_tenant')
- # Verify helper methods
- tenant = iso_creds.get_admin_tenant()
- user = iso_creds.get_admin_user()
- self.assertEqual(tenant['id'], '1234')
- self.assertEqual(user['id'], '1234')
+ # Verify IDs
+ self.assertEqual(admin_creds.tenant_id, '1234')
+ self.assertEqual(admin_creds.user_id, '1234')
@patch('tempest.common.rest_client.RestClient')
def test_all_cred_cleanup(self, MockRestClient):
@@ -166,12 +162,12 @@
password='fake_password')
tenant_fix = self._mock_tenant_create('1234', 'fake_prim_tenant')
user_fix = self._mock_user_create('1234', 'fake_prim_user')
- iso_creds.get_primary_creds(old_style=False)
+ iso_creds.get_primary_creds()
tenant_fix.cleanUp()
user_fix.cleanUp()
tenant_fix = self._mock_tenant_create('12345', 'fake_alt_tenant')
user_fix = self._mock_user_create('12345', 'fake_alt_user')
- iso_creds.get_alt_creds(old_style=False)
+ iso_creds.get_alt_creds()
tenant_fix.cleanUp()
user_fix.cleanUp()
tenant_fix = self._mock_tenant_create('123456', 'fake_admin_tenant')
@@ -213,14 +209,12 @@
password='fake_password')
self._mock_user_create('1234', 'fake_alt_user')
self._mock_tenant_create('1234', 'fake_alt_tenant')
- alt_creds = iso_creds.get_alt_creds(old_style=False)
+ alt_creds = iso_creds.get_alt_creds()
self.assertEqual(alt_creds.username, 'fake_alt_user')
self.assertEqual(alt_creds.tenant_name, 'fake_alt_tenant')
- # Verify helper methods
- tenant = iso_creds.get_alt_tenant()
- user = iso_creds.get_alt_user()
- self.assertEqual(tenant['id'], '1234')
- self.assertEqual(user['id'], '1234')
+ # Verify IDs
+ self.assertEqual(alt_creds.tenant_id, '1234')
+ self.assertEqual(alt_creds.user_id, '1234')
@patch('tempest.common.rest_client.RestClient')
def test_network_creation(self, MockRestClient):
@@ -234,7 +228,7 @@
router_interface_mock = self.patch(
'tempest.services.network.json.network_client.NetworkClientJSON.'
'add_router_interface_with_subnet_id')
- iso_creds.get_primary_creds(old_style=False)
+ iso_creds.get_primary_creds()
router_interface_mock.called_once_with('1234', '1234')
network = iso_creds.get_primary_network()
subnet = iso_creds.get_primary_subnet()
@@ -259,7 +253,7 @@
router_interface_mock = self.patch(
'tempest.services.network.json.network_client.NetworkClientJSON.'
'add_router_interface_with_subnet_id')
- iso_creds.get_primary_creds(old_style=False)
+ iso_creds.get_primary_creds()
router_interface_mock.called_once_with('1234', '1234')
router_interface_mock.reset_mock()
tenant_fix.cleanUp()
@@ -274,7 +268,7 @@
subnet_fix = self._mock_subnet_create(iso_creds, '12345',
'fake_alt_subnet')
router_fix = self._mock_router_create('12345', 'fake_alt_router')
- iso_creds.get_alt_creds(old_style=False)
+ iso_creds.get_alt_creds()
router_interface_mock.called_once_with('12345', '12345')
router_interface_mock.reset_mock()
tenant_fix.cleanUp()
diff --git a/tools/tempest_auto_config.py b/tools/tempest_auto_config.py
deleted file mode 100644
index 5b8d05b..0000000
--- a/tools/tempest_auto_config.py
+++ /dev/null
@@ -1,395 +0,0 @@
-# Copyright 2012 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.
-#
-# This script aims to configure an initial OpenStack environment with all the
-# necessary configurations for tempest's run using nothing but OpenStack's
-# native API.
-# That includes, creating users, tenants, registering images (cirros),
-# configuring neutron and so on.
-#
-# ASSUMPTION: this script is run by an admin user as it is meant to configure
-# the OpenStack environment prior to actual use.
-
-# Config
-import ConfigParser
-import os
-import tarfile
-import urllib2
-
-# Default client libs
-import glanceclient as glance_client
-import keystoneclient.v2_0.client as keystone_client
-
-# Import OpenStack exceptions
-import glanceclient.exc as glance_exception
-import keystoneclient.exceptions as keystone_exception
-
-
-TEMPEST_TEMP_DIR = os.getenv("TEMPEST_TEMP_DIR", "/tmp").rstrip('/')
-TEMPEST_ROOT_DIR = os.getenv("TEMPEST_ROOT_DIR", os.getenv("HOME")).rstrip('/')
-
-# Environment variables override defaults
-TEMPEST_CONFIG_DIR = os.getenv("TEMPEST_CONFIG_DIR",
- "%s%s" % (TEMPEST_ROOT_DIR, "/etc")).rstrip('/')
-TEMPEST_CONFIG_FILE = os.getenv("TEMPEST_CONFIG_FILE",
- "%s%s" % (TEMPEST_CONFIG_DIR, "/tempest.conf"))
-TEMPEST_CONFIG_SAMPLE = os.getenv("TEMPEST_CONFIG_SAMPLE",
- "%s%s" % (TEMPEST_CONFIG_DIR,
- "/tempest.conf.sample"))
-# Image references
-IMAGE_DOWNLOAD_CHUNK_SIZE = 8 * 1024
-IMAGE_UEC_SOURCE_URL = os.getenv("IMAGE_UEC_SOURCE_URL",
- "http://download.cirros-cloud.net/0.3.1/"
- "cirros-0.3.1-x86_64-uec.tar.gz")
-TEMPEST_IMAGE_ID = os.getenv('IMAGE_ID')
-TEMPEST_IMAGE_ID_ALT = os.getenv('IMAGE_ID_ALT')
-IMAGE_STATUS_ACTIVE = 'active'
-
-
-class ClientManager(object):
- """
- Manager that provides access to the official python clients for
- calling various OpenStack APIs.
- """
- def __init__(self):
- self.identity_client = None
- self.image_client = None
- self.network_client = None
- self.compute_client = None
- self.volume_client = None
-
- def get_identity_client(self, **kwargs):
- """
- Returns the openstack identity python client
- :param username: a string representing the username
- :param password: a string representing the user's password
- :param tenant_name: a string representing the tenant name of the user
- :param auth_url: a string representing the auth url of the identity
- :param insecure: True if we wish to disable ssl certificate validation,
- False otherwise
- :returns an instance of openstack identity python client
- """
- if not self.identity_client:
- self.identity_client = keystone_client.Client(**kwargs)
-
- return self.identity_client
-
- def get_image_client(self, version="1", *args, **kwargs):
- """
- This method returns OpenStack glance python client
- :param version: a string representing the version of the glance client
- to use.
- :param string endpoint: A user-supplied endpoint URL for the glance
- service.
- :param string token: Token for authentication.
- :param integer timeout: Allows customization of the timeout for client
- http requests. (optional)
- :return: a Client object representing the glance client
- """
- if not self.image_client:
- self.image_client = glance_client.Client(version, *args, **kwargs)
-
- return self.image_client
-
-
-def get_tempest_config(path_to_config):
- """
- Gets the tempest configuration file as a ConfigParser object
- :param path_to_config: path to the config file
- :return: a ConfigParser object representing the tempest configuration file
- """
- # get the sample config file from the sample
- config = ConfigParser.ConfigParser()
- config.readfp(open(path_to_config))
-
- return config
-
-
-def update_config_admin_credentials(config, config_section):
- """
- Updates the tempest config with the admin credentials
- :param config: a ConfigParser object representing the tempest config file
- :param config_section: the section name where the admin credentials are
- """
- # Check if credentials are present, default uses the config credentials
- OS_USERNAME = os.getenv('OS_USERNAME',
- config.get(config_section, "admin_username"))
- OS_PASSWORD = os.getenv('OS_PASSWORD',
- config.get(config_section, "admin_password"))
- OS_TENANT_NAME = os.getenv('OS_TENANT_NAME',
- config.get(config_section, "admin_tenant_name"))
- OS_AUTH_URL = os.getenv('OS_AUTH_URL', config.get(config_section, "uri"))
-
- if not (OS_AUTH_URL and
- OS_USERNAME and
- OS_PASSWORD and
- OS_TENANT_NAME):
- raise Exception("Admin environment variables not found.")
-
- # TODO(tkammer): Add support for uri_v3
- config_identity_params = {'uri': OS_AUTH_URL,
- 'admin_username': OS_USERNAME,
- 'admin_password': OS_PASSWORD,
- 'admin_tenant_name': OS_TENANT_NAME}
-
- update_config_section_with_params(config,
- config_section,
- config_identity_params)
-
-
-def update_config_section_with_params(config, config_section, params):
- """
- Updates a given config object with given params
- :param config: a ConfigParser object representing the tempest config file
- :param config_section: the section we would like to update
- :param params: the parameters we wish to update for that section
- """
- for option, value in params.items():
- config.set(config_section, option, value)
-
-
-def get_identity_client_kwargs(config, config_section):
- """
- Get the required arguments for the identity python client
- :param config: a ConfigParser object representing the tempest config file
- :param config_section: the section name in the configuration where the
- arguments can be found
- :return: a dictionary representing the needed arguments for the identity
- client
- """
- username = config.get(config_section, 'admin_username')
- password = config.get(config_section, 'admin_password')
- tenant_name = config.get(config_section, 'admin_tenant_name')
- auth_url = config.get(config_section, 'uri')
- dscv = config.get(config_section, 'disable_ssl_certificate_validation')
- kwargs = {'username': username,
- 'password': password,
- 'tenant_name': tenant_name,
- 'auth_url': auth_url,
- 'insecure': dscv}
-
- return kwargs
-
-
-def create_user_with_tenant(identity_client, username, password, tenant_name):
- """
- Creates a user using a given identity client
- :param identity_client: openstack identity python client
- :param username: a string representing the username
- :param password: a string representing the user's password
- :param tenant_name: a string representing the tenant name of the user
- """
- # Try to create the necessary tenant
- tenant_id = None
- try:
- tenant_description = "Tenant for Tempest %s user" % username
- tenant = identity_client.tenants.create(tenant_name,
- tenant_description)
- tenant_id = tenant.id
- except keystone_exception.Conflict:
-
- # if already exist, use existing tenant
- tenant_list = identity_client.tenants.list()
- for tenant in tenant_list:
- if tenant.name == tenant_name:
- tenant_id = tenant.id
-
- # Try to create the user
- try:
- email = "%s@test.com" % username
- identity_client.users.create(name=username,
- password=password,
- email=email,
- tenant_id=tenant_id)
- except keystone_exception.Conflict:
-
- # if already exist, use existing user
- pass
-
-
-def create_users_and_tenants(identity_client,
- config,
- config_section):
- """
- Creates the two non admin users and tenants for tempest
- :param identity_client: openstack identity python client
- :param config: a ConfigParser object representing the tempest config file
- :param config_section: the section name of identity in the config
- """
- # Get the necessary params from the config file
- tenant_name = config.get(config_section, 'tenant_name')
- username = config.get(config_section, 'username')
- password = config.get(config_section, 'password')
-
- alt_tenant_name = config.get(config_section, 'alt_tenant_name')
- alt_username = config.get(config_section, 'alt_username')
- alt_password = config.get(config_section, 'alt_password')
-
- # Create the necessary users for the test runs
- create_user_with_tenant(identity_client, username, password, tenant_name)
- create_user_with_tenant(identity_client, alt_username, alt_password,
- alt_tenant_name)
-
-
-def get_image_client_kwargs(identity_client, config, config_section):
- """
- Get the required arguments for the image python client
- :param identity_client: openstack identity python client
- :param config: a ConfigParser object representing the tempest config file
- :param config_section: the section name of identity in the config
- :return: a dictionary representing the needed arguments for the image
- client
- """
-
- token = identity_client.auth_token
- endpoint = identity_client.\
- service_catalog.url_for(service_type='image', endpoint_type='publicURL'
- )
- dscv = config.get(config_section, 'disable_ssl_certificate_validation')
- kwargs = {'endpoint': endpoint,
- 'token': token,
- 'insecure': dscv}
-
- return kwargs
-
-
-def images_exist(image_client):
- """
- Checks whether the images ID's located in the environment variable are
- indeed registered
- :param image_client: the openstack python client representing the image
- client
- """
- exist = True
- if not TEMPEST_IMAGE_ID or not TEMPEST_IMAGE_ID_ALT:
- exist = False
- else:
- try:
- image_client.images.get(TEMPEST_IMAGE_ID)
- image_client.images.get(TEMPEST_IMAGE_ID_ALT)
- except glance_exception.HTTPNotFound:
- exist = False
-
- return exist
-
-
-def download_and_register_uec_images(image_client, download_url,
- download_folder):
- """
- Downloads and registered the UEC AKI/AMI/ARI images
- :param image_client:
- :param download_url: the url of the uec tar file
- :param download_folder: the destination folder we wish to save the file to
- """
- basename = os.path.basename(download_url)
- path = os.path.join(download_folder, basename)
-
- request = urllib2.urlopen(download_url)
-
- # First, download the file
- with open(path, "wb") as fp:
- while True:
- chunk = request.read(IMAGE_DOWNLOAD_CHUNK_SIZE)
- if not chunk:
- break
-
- fp.write(chunk)
-
- # Then extract and register images
- tar = tarfile.open(path, "r")
- for name in tar.getnames():
- file_obj = tar.extractfile(name)
- format = "aki"
-
- if file_obj.name.endswith(".img"):
- format = "ami"
-
- if file_obj.name.endswith("initrd"):
- format = "ari"
-
- # Register images in image client
- image_client.images.create(name=file_obj.name, disk_format=format,
- container_format=format, data=file_obj,
- is_public="true")
-
- tar.close()
-
-
-def create_images(image_client, config, config_section,
- download_url=IMAGE_UEC_SOURCE_URL,
- download_folder=TEMPEST_TEMP_DIR):
- """
- Creates images for tempest's use and registers the environment variables
- IMAGE_ID and IMAGE_ID_ALT with registered images
- :param image_client: OpenStack python image client
- :param config: a ConfigParser object representing the tempest config file
- :param config_section: the section name where the IMAGE ids are set
- :param download_url: the URL from which we should download the UEC tar
- :param download_folder: the place where we want to save the download file
- """
- if not images_exist(image_client):
- # Falls down to the default uec images
- download_and_register_uec_images(image_client, download_url,
- download_folder)
- image_ids = []
- for image in image_client.images.list():
- image_ids.append(image.id)
-
- os.environ["IMAGE_ID"] = image_ids[0]
- os.environ["IMAGE_ID_ALT"] = image_ids[1]
-
- params = {'image_ref': os.getenv("IMAGE_ID"),
- 'image_ref_alt': os.getenv("IMAGE_ID_ALT")}
-
- update_config_section_with_params(config, config_section, params)
-
-
-def main():
- """
- Main module to control the script
- """
- # Check if config file exists or fall to the default sample otherwise
- path_to_config = TEMPEST_CONFIG_SAMPLE
-
- if os.path.isfile(TEMPEST_CONFIG_FILE):
- path_to_config = TEMPEST_CONFIG_FILE
-
- config = get_tempest_config(path_to_config)
- update_config_admin_credentials(config, 'identity')
-
- client_manager = ClientManager()
-
- # Set the identity related info for tempest
- identity_client_kwargs = get_identity_client_kwargs(config,
- 'identity')
- identity_client = client_manager.get_identity_client(
- **identity_client_kwargs)
-
- # Create the necessary users and tenants for tempest run
- create_users_and_tenants(identity_client, config, 'identity')
-
- # Set the image related info for tempest
- image_client_kwargs = get_image_client_kwargs(identity_client,
- config,
- 'identity')
- image_client = client_manager.get_image_client(**image_client_kwargs)
-
- # Create the necessary users and tenants for tempest run
- create_images(image_client, config, 'compute')
-
- # TODO(tkammer): add network implementation
-
-if __name__ == "__main__":
- main()