Merge "Split large-ops into three tests so each has its own timeout"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 70950b7..28a4d1c 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -405,6 +405,14 @@
# as [nova.vnc]->vnc_enabled in nova.conf (boolean value)
#vnc_console=false
+# Enable Spice console. This configuration value should be
+# same as [nova.spice]->enabled in nova.conf (boolean value)
+#spice_console=false
+
+# Enable RDP console. This configuration value should be same
+# as [nova.rdp]->enabled in nova.conf (boolean value)
+#rdp_console=false
+
[dashboard]
@@ -446,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_availability_zone_negative.py b/tempest/api/compute/v3/admin/test_availability_zone_negative.py
index f3af6df..b012e65 100644
--- a/tempest/api/compute/v3/admin/test_availability_zone_negative.py
+++ b/tempest/api/compute/v3/admin/test_availability_zone_negative.py
@@ -15,7 +15,7 @@
from tempest.api.compute import base
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class AZAdminNegativeV3Test(base.BaseV3ComputeAdminTest):
@@ -30,7 +30,7 @@
cls.client = cls.availability_zone_admin_client
cls.non_adm_client = cls.availability_zone_client
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_get_availability_zone_list_detail_with_non_admin_user(self):
# List of availability zones and available services with
# non-administrator user
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_hypervisor.py b/tempest/api/compute/v3/admin/test_hypervisor.py
index 93d4441..f3397a8 100644
--- a/tempest/api/compute/v3/admin/test_hypervisor.py
+++ b/tempest/api/compute/v3/admin/test_hypervisor.py
@@ -14,7 +14,7 @@
# under the License.
from tempest.api.compute import base
-from tempest.test import attr
+from tempest import test
class HypervisorAdminV3Test(base.BaseV3ComputeAdminTest):
@@ -34,20 +34,20 @@
self.assertEqual(200, resp.status)
return hypers
- @attr(type='gate')
+ @test.attr(type='gate')
def test_get_hypervisor_list(self):
# List of hypervisor and available hypervisors hostname
hypers = self._list_hypervisors()
self.assertTrue(len(hypers) > 0)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_get_hypervisor_list_details(self):
# Display the details of the all hypervisor
resp, hypers = self.client.get_hypervisor_list_details()
self.assertEqual(200, resp.status)
self.assertTrue(len(hypers) > 0)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_get_hypervisor_show_details(self):
# Display the details of the specified hypervisor
hypers = self._list_hypervisors()
@@ -60,7 +60,7 @@
self.assertEqual(details['hypervisor_hostname'],
hypers[0]['hypervisor_hostname'])
- @attr(type='gate')
+ @test.attr(type='gate')
def test_get_hypervisor_show_servers(self):
# Show instances about the specific hypervisors
hypers = self._list_hypervisors()
@@ -71,14 +71,14 @@
self.assertEqual(200, resp.status)
self.assertTrue(len(hypervisors) > 0)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_get_hypervisor_stats(self):
# Verify the stats of the all hypervisor
resp, stats = self.client.get_hypervisor_stats()
self.assertEqual(200, resp.status)
self.assertTrue(len(stats) > 0)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_get_hypervisor_uptime(self):
# Verify that GET shows the specified hypervisor uptime
hypers = self._list_hypervisors()
@@ -87,7 +87,7 @@
self.assertEqual(200, resp.status)
self.assertTrue(len(uptime) > 0)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_search_hypervisor(self):
hypers = self._list_hypervisors()
self.assertTrue(len(hypers) > 0)
diff --git a/tempest/api/compute/v3/admin/test_hypervisor_negative.py b/tempest/api/compute/v3/admin/test_hypervisor_negative.py
index 45642b7..ae4df15 100644
--- a/tempest/api/compute/v3/admin/test_hypervisor_negative.py
+++ b/tempest/api/compute/v3/admin/test_hypervisor_negative.py
@@ -18,7 +18,7 @@
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class HypervisorAdminNegativeV3Test(base.BaseV3ComputeAdminTest):
@@ -39,7 +39,7 @@
self.assertEqual(200, resp.status)
return hypers
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_show_nonexistent_hypervisor(self):
nonexistent_hypervisor_id = str(uuid.uuid4())
@@ -48,7 +48,7 @@
self.client.get_hypervisor_show_details,
nonexistent_hypervisor_id)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_show_hypervisor_with_non_admin_user(self):
hypers = self._list_hypervisors()
self.assertTrue(len(hypers) > 0)
@@ -58,7 +58,7 @@
self.non_adm_client.get_hypervisor_show_details,
hypers[0]['id'])
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_show_servers_with_non_admin_user(self):
hypers = self._list_hypervisors()
self.assertTrue(len(hypers) > 0)
@@ -68,7 +68,7 @@
self.non_adm_client.get_hypervisor_servers,
hypers[0]['id'])
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_show_servers_with_nonexistent_hypervisor(self):
nonexistent_hypervisor_id = str(uuid.uuid4())
@@ -77,13 +77,13 @@
self.client.get_hypervisor_servers,
nonexistent_hypervisor_id)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_get_hypervisor_stats_with_non_admin_user(self):
self.assertRaises(
exceptions.Unauthorized,
self.non_adm_client.get_hypervisor_stats)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_get_nonexistent_hypervisor_uptime(self):
nonexistent_hypervisor_id = str(uuid.uuid4())
@@ -92,7 +92,7 @@
self.client.get_hypervisor_uptime,
nonexistent_hypervisor_id)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_get_hypervisor_uptime_with_non_admin_user(self):
hypers = self._list_hypervisors()
self.assertTrue(len(hypers) > 0)
@@ -102,21 +102,21 @@
self.non_adm_client.get_hypervisor_uptime,
hypers[0]['id'])
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_get_hypervisor_list_with_non_admin_user(self):
# List of hypervisor and available services with non admin user
self.assertRaises(
exceptions.Unauthorized,
self.non_adm_client.get_hypervisor_list)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_get_hypervisor_list_details_with_non_admin_user(self):
# List of hypervisor details and available services with non admin user
self.assertRaises(
exceptions.Unauthorized,
self.non_adm_client.get_hypervisor_list_details)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_search_nonexistent_hypervisor(self):
nonexistent_hypervisor_name = data_utils.rand_name('test_hypervisor')
@@ -125,7 +125,7 @@
self.assertEqual(200, resp.status)
self.assertEqual(0, len(hypers))
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_search_hypervisor_with_non_admin_user(self):
hypers = self._list_hypervisors()
self.assertTrue(len(hypers) > 0)
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..a971463 100644
--- a/tempest/api/compute/v3/admin/test_servers_negative.py
+++ b/tempest/api/compute/v3/admin/test_servers_negative.py
@@ -20,7 +20,7 @@
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
CONF = config.CONF
@@ -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,
@@ -57,7 +54,7 @@
flavor_id = data_utils.rand_int_id(start=1000)
return flavor_id
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_resize_server_using_overlimit_ram(self):
flavor_name = data_utils.rand_name("flavor-")
flavor_id = self._get_unused_flavor_id()
@@ -75,7 +72,7 @@
self.servers[0]['id'],
flavor_ref['id'])
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_resize_server_using_overlimit_vcpus(self):
flavor_name = data_utils.rand_name("flavor-")
flavor_id = self._get_unused_flavor_id()
@@ -93,31 +90,31 @@
self.servers[0]['id'],
flavor_ref['id'])
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_reset_state_server_invalid_state(self):
self.assertRaises(exceptions.BadRequest,
self.client.reset_state, self.s1_id,
state='invalid')
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_reset_state_server_invalid_type(self):
self.assertRaises(exceptions.BadRequest,
self.client.reset_state, self.s1_id,
state=1)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_reset_state_server_nonexistent_server(self):
self.assertRaises(exceptions.NotFound,
self.client.reset_state, '999')
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_get_server_diagnostics_by_non_admin(self):
# Non-admin user can not view server diagnostics according to policy
self.assertRaises(exceptions.Unauthorized,
self.non_adm_client.get_server_diagnostics,
self.s1_id)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_migrate_non_existent_server(self):
# migrate a non existent server
self.assertRaises(exceptions.NotFound,
@@ -126,7 +123,7 @@
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
'Suspend is not available.')
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_migrate_server_invalid_state(self):
# create server.
resp, server = self.create_test_server(wait_until='ACTIVE')
diff --git a/tempest/api/compute/v3/admin/test_services.py b/tempest/api/compute/v3/admin/test_services.py
index b367dad..e6efb70 100644
--- a/tempest/api/compute/v3/admin/test_services.py
+++ b/tempest/api/compute/v3/admin/test_services.py
@@ -15,7 +15,7 @@
# under the License.
from tempest.api.compute import base
-from tempest.test import attr
+from tempest import test
class ServicesAdminV3Test(base.BaseV3ComputeAdminTest):
@@ -29,13 +29,13 @@
super(ServicesAdminV3Test, cls).setUpClass()
cls.client = cls.services_admin_client
- @attr(type='gate')
+ @test.attr(type='gate')
def test_list_services(self):
resp, services = self.client.list_services()
self.assertEqual(200, resp.status)
self.assertNotEqual(0, len(services))
- @attr(type='gate')
+ @test.attr(type='gate')
def test_get_service_by_service_binary_name(self):
binary_name = 'nova-compute'
params = {'binary': binary_name}
@@ -45,7 +45,7 @@
for service in services:
self.assertEqual(binary_name, service['binary'])
- @attr(type='gate')
+ @test.attr(type='gate')
def test_get_service_by_host_name(self):
resp, services = self.client.list_services()
self.assertEqual(200, resp.status)
@@ -65,7 +65,7 @@
# on order.
self.assertEqual(sorted(s1), sorted(s2))
- @attr(type='gate')
+ @test.attr(type='gate')
def test_get_service_by_service_and_host_name(self):
resp, services = self.client.list_services()
host_name = services[0]['host']
diff --git a/tempest/api/compute/v3/admin/test_services_negative.py b/tempest/api/compute/v3/admin/test_services_negative.py
index 3168af2..6ac78d4 100644
--- a/tempest/api/compute/v3/admin/test_services_negative.py
+++ b/tempest/api/compute/v3/admin/test_services_negative.py
@@ -16,7 +16,7 @@
from tempest.api.compute import base
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class ServicesAdminNegativeV3Test(base.BaseV3ComputeAdminTest):
@@ -31,12 +31,12 @@
cls.client = cls.services_admin_client
cls.non_admin_client = cls.services_client
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_list_services_with_non_admin_user(self):
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.list_services)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_get_service_by_invalid_params(self):
# return all services if send the request with invalid parameter
resp, services = self.client.list_services()
@@ -45,7 +45,7 @@
self.assertEqual(200, resp.status)
self.assertEqual(len(services), len(services_xxx))
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_get_service_by_invalid_service_and_valid_host(self):
resp, services = self.client.list_services()
host_name = services[0]['host']
@@ -54,7 +54,7 @@
self.assertEqual(200, resp.status)
self.assertEqual(0, len(services))
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_get_service_with_valid_service_and_invalid_host(self):
resp, services = self.client.list_services()
binary_name = services[0]['binary']
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_attach_interfaces.py b/tempest/api/compute/v3/servers/test_attach_interfaces.py
index c848f8c..43440c1 100644
--- a/tempest/api/compute/v3/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/v3/servers/test_attach_interfaces.py
@@ -16,7 +16,7 @@
from tempest.api.compute import base
from tempest import config
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
import time
@@ -106,7 +106,7 @@
self.assertEqual(sorted(list1), sorted(list2))
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_create_list_show_delete_interfaces(self):
server, ifs = self._create_server_get_interfaces()
interface_count = len(ifs)
@@ -127,7 +127,7 @@
_ifs = self._test_delete_interface(server, ifs)
self.assertEqual(len(ifs) - 1, len(_ifs))
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_add_remove_fixed_ip(self):
# Add and Remove the fixed IP to server.
server, ifs = self._create_server_get_interfaces()
diff --git a/tempest/api/compute/v3/servers/test_server_actions.py b/tempest/api/compute/v3/servers/test_server_actions.py
index 5b35e2a..721fe42 100644
--- a/tempest/api/compute/v3/servers/test_server_actions.py
+++ b/tempest/api/compute/v3/servers/test_server_actions.py
@@ -14,6 +14,7 @@
# under the License.
import testtools
+import urlparse
from tempest.api.compute import base
from tempest.common.utils import data_utils
@@ -420,6 +421,12 @@
self.assertEqual(202, resp.status)
self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
+ def _validate_url(self, url):
+ valid_scheme = ['http', 'https']
+ parsed_url = urlparse.urlparse(url)
+ self.assertNotEqual('None', parsed_url.hostname)
+ self.assertIn(parsed_url.scheme, valid_scheme)
+
@testtools.skipUnless(CONF.compute_feature_enabled.vnc_console,
'VNC Console feature is disabled')
@test.attr(type='gate')
@@ -429,6 +436,35 @@
for console_type in console_types:
resp, body = self.servers_client.get_vnc_console(self.server_id,
console_type)
- self.assertEqual(200, resp.status)
+ self.assertEqual(
+ 200, resp.status,
+ "Failed to get Console Type: %s" % (console_type))
self.assertEqual(console_type, body['type'])
self.assertNotEqual('', body['url'])
+ self._validate_url(body['url'])
+
+ @testtools.skipUnless(CONF.compute_feature_enabled.spice_console,
+ 'Spice Console feature is disabled.')
+ @test.attr(type='gate')
+ def test_get_spice_console(self):
+ # Get the Spice console of type "spice-html5"
+ console_type = 'spice-html5'
+ resp, body = self.servers_client.get_spice_console(self.server_id,
+ console_type)
+ self.assertEqual(200, resp.status)
+ self.assertEqual(console_type, body['type'])
+ self.assertNotEqual('', body['url'])
+ self._validate_url(body['url'])
+
+ @testtools.skipUnless(CONF.compute_feature_enabled.rdp_console,
+ 'RDP Console feature is disabled.')
+ @test.attr(type='gate')
+ def test_get_rdp_console(self):
+ # Get the RDP console of type "rdp-html5"
+ console_type = 'rdp-html5'
+ resp, body = self.servers_client.get_rdp_console(self.server_id,
+ console_type)
+ self.assertEqual(200, resp.status)
+ self.assertEqual(console_type, body['type'])
+ self.assertNotEqual('', body['url'])
+ self._validate_url(body['url'])
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_live_block_migration.py b/tempest/api/compute/v3/test_live_block_migration.py
index 33d2bd9..6ca37e6 100644
--- a/tempest/api/compute/v3/test_live_block_migration.py
+++ b/tempest/api/compute/v3/test_live_block_migration.py
@@ -17,7 +17,7 @@
from tempest.api.compute import base
from tempest import config
-from tempest.test import attr
+from tempest import test
CONF = config.CONF
@@ -85,7 +85,7 @@
@testtools.skipIf(not CONF.compute_feature_enabled.live_migration,
'Live migration not available')
- @attr(type='gate')
+ @test.attr(type='gate')
def test_live_block_migration(self):
# Live block migrate an instance to another host
if len(self._get_compute_hostnames()) < 2:
@@ -105,7 +105,7 @@
@testtools.skipIf(not CONF.compute_feature_enabled.
block_migrate_cinder_iscsi,
'Block Live migration not configured for iSCSI')
- @attr(type='gate')
+ @test.attr(type='gate')
def test_iscsi_volume(self):
# Live block migrate an instance to another host
if len(self._get_compute_hostnames()) < 2:
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/compute/volumes/test_volumes_list.py b/tempest/api/compute/volumes/test_volumes_list.py
index 9867c64..25a8547 100644
--- a/tempest/api/compute/volumes/test_volumes_list.py
+++ b/tempest/api/compute/volumes/test_volumes_list.py
@@ -16,7 +16,7 @@
from tempest.api.compute 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
@@ -75,7 +75,7 @@
cls.delete_volume(volume['id'])
super(VolumesTestJSON, cls).tearDownClass()
- @attr(type='gate')
+ @test.attr(type='gate')
def test_volume_list(self):
# Should return the list of Volumes
# Fetch all Volumes
@@ -91,7 +91,7 @@
', '.join(m_vol['displayName']
for m_vol in missing_volumes))
- @attr(type='gate')
+ @test.attr(type='gate')
def test_volume_list_with_details(self):
# Should return the list of Volumes with details
# Fetch all Volumes
@@ -107,7 +107,7 @@
', '.join(m_vol['displayName']
for m_vol in missing_volumes))
- @attr(type='gate')
+ @test.attr(type='gate')
def test_volume_list_param_limit(self):
# Return the list of volumes based on limit set
params = {'limit': 2}
@@ -117,7 +117,7 @@
self.assertEqual(len(fetched_vol_list), params['limit'],
"Failed to list volumes by limit set")
- @attr(type='gate')
+ @test.attr(type='gate')
def test_volume_list_with_detail_param_limit(self):
# Return the list of volumes with details based on limit set.
params = {'limit': 2}
@@ -128,7 +128,7 @@
self.assertEqual(len(fetched_vol_list), params['limit'],
"Failed to list volume details by limit set")
- @attr(type='gate')
+ @test.attr(type='gate')
def test_volume_list_param_offset_and_limit(self):
# Return the list of volumes based on offset and limit set.
# get all volumes list
@@ -146,7 +146,7 @@
all_vol_list[index + params['offset']]['id'],
"Failed to list volumes by offset and limit")
- @attr(type='gate')
+ @test.attr(type='gate')
def test_volume_list_with_detail_param_offset_and_limit(self):
# Return the list of volumes details based on offset and limit set.
# get all volumes list
diff --git a/tempest/api/compute/volumes/test_volumes_negative.py b/tempest/api/compute/volumes/test_volumes_negative.py
index cecaf62..5dfbad7 100644
--- a/tempest/api/compute/volumes/test_volumes_negative.py
+++ b/tempest/api/compute/volumes/test_volumes_negative.py
@@ -19,7 +19,7 @@
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
CONF = config.CONF
@@ -34,7 +34,7 @@
skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
raise cls.skipException(skip_msg)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_volume_get_nonexistent_volume_id(self):
# Negative: Should not be able to get details of nonexistent volume
# Creating a nonexistent volume id
@@ -42,7 +42,7 @@
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):
# Negative: Should not be able to delete nonexistent Volume
# Creating nonexistent volume id
@@ -50,7 +50,7 @@
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):
# Negative: Should not be able to create volume with invalid size
# in request
@@ -59,7 +59,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):
# Negative: Should not be able to create volume without passing size
# in request
@@ -68,7 +68,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):
# Negative: Should not be able to create volume with size zero
v_name = data_utils.rand_name('Volume-')
@@ -76,25 +76,25 @@
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_get_invalid_volume_id(self):
# Negative: 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):
# Negative: 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):
# Negative: 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):
# Negative: Should not be able to delete volume when empty ID is passed
self.assertRaises(exceptions.NotFound, self.client.delete_volume, '')
diff --git a/tempest/api/data_processing/base.py b/tempest/api/data_processing/base.py
index 74444d7..8d5e223 100644
--- a/tempest/api/data_processing/base.py
+++ b/tempest/api/data_processing/base.py
@@ -1,17 +1,16 @@
-# Copyright (c) 2013 Mirantis Inc.
+# Copyright (c) 2014 Mirantis Inc.
#
-# 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
+# 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
+# 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.
+# 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 import exceptions
diff --git a/tempest/api/data_processing/test_node_group_templates.py b/tempest/api/data_processing/test_node_group_templates.py
index ed4cf1f..f3af4e8 100644
--- a/tempest/api/data_processing/test_node_group_templates.py
+++ b/tempest/api/data_processing/test_node_group_templates.py
@@ -1,21 +1,20 @@
-# Copyright (c) 2013 Mirantis Inc.
+# Copyright (c) 2014 Mirantis Inc.
#
-# 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
+# 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
+# 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.
+# 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.data_processing import base as dp_base
from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
class NodeGroupTemplateTest(dp_base.BaseDataProcessingTest):
@@ -61,7 +60,7 @@
return body['id'], template_name
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_node_group_template_create(self):
template_name = data_utils.rand_name('sahara-ng-template')
resp, body = self.create_node_group_template(
@@ -72,7 +71,7 @@
self.assertEqual(template_name, body['name'])
self.assertDictContainsSubset(self.node_group_template, body)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_node_group_template_list(self):
template_info = self._create_node_group_template()
@@ -84,7 +83,7 @@
for template in templates]
self.assertIn(template_info, templates_info)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_node_group_template_get(self):
template_id, template_name = self._create_node_group_template()
@@ -95,7 +94,7 @@
self.assertEqual(template_name, template['name'])
self.assertDictContainsSubset(self.node_group_template, template)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_node_group_template_delete(self):
template_id = self._create_node_group_template()[0]
diff --git a/tempest/api/data_processing/test_plugins.py b/tempest/api/data_processing/test_plugins.py
index 3b941d8..c6832a2 100644
--- a/tempest/api/data_processing/test_plugins.py
+++ b/tempest/api/data_processing/test_plugins.py
@@ -1,20 +1,19 @@
-# Copyright (c) 2013 Mirantis Inc.
+# Copyright (c) 2014 Mirantis Inc.
#
-# 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
+# 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
+# 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.
+# 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.data_processing import base as dp_base
-from tempest.test import attr
+from tempest import test
class PluginsTest(dp_base.BaseDataProcessingTest):
@@ -33,11 +32,11 @@
return plugins_names
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_plugin_list(self):
self._list_all_plugin_names()
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_plugin_get(self):
for plugin_name in self._list_all_plugin_names():
resp, plugin = self.client.get_plugin(plugin_name)
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_roles_negative.py b/tempest/api/identity/admin/test_roles_negative.py
index d311143..6f8f9b5 100644
--- a/tempest/api/identity/admin/test_roles_negative.py
+++ b/tempest/api/identity/admin/test_roles_negative.py
@@ -18,7 +18,7 @@
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class RolesNegativeTestJSON(base.BaseIdentityV2AdminTest):
@@ -32,13 +32,13 @@
role = self.get_role_by_name(self.data.test_role)
return (user, tenant, role)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_list_roles_by_unauthorized_user(self):
# Non-administrator user should not be able to list roles
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.list_roles)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_list_roles_request_without_token(self):
# Request to list roles without a valid token should fail
token = self.client.auth_provider.get_token()
@@ -46,19 +46,19 @@
self.assertRaises(exceptions.Unauthorized, self.client.list_roles)
self.client.auth_provider.clear_auth()
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_role_create_blank_name(self):
# Should not be able to create a role with a blank name
self.assertRaises(exceptions.BadRequest, self.client.create_role, '')
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_role_by_unauthorized_user(self):
# Non-administrator user should not be able to create role
role_name = data_utils.rand_name(name='role-')
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.create_role, role_name)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_role_request_without_token(self):
# Request to create role without a valid token should fail
token = self.client.auth_provider.get_token()
@@ -68,7 +68,7 @@
self.client.create_role, role_name)
self.client.auth_provider.clear_auth()
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_role_create_duplicate(self):
# Role names should be unique
role_name = data_utils.rand_name(name='role-dup-')
@@ -79,7 +79,7 @@
self.assertRaises(exceptions.Conflict, self.client.create_role,
role_name)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_delete_role_by_unauthorized_user(self):
# Non-administrator user should not be able to delete role
role_name = data_utils.rand_name(name='role-')
@@ -90,7 +90,7 @@
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.delete_role, role_id)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_delete_role_request_without_token(self):
# Request to delete role without a valid token should fail
role_name = data_utils.rand_name(name='role-')
@@ -105,14 +105,14 @@
role_id)
self.client.auth_provider.clear_auth()
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_delete_role_non_existent(self):
# Attempt to delete a non existent role should fail
non_existent_role = str(uuid.uuid4().hex)
self.assertRaises(exceptions.NotFound, self.client.delete_role,
non_existent_role)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_assign_user_role_by_unauthorized_user(self):
# Non-administrator user should not be authorized to
# assign a role to user
@@ -121,7 +121,7 @@
self.non_admin_client.assign_user_role,
tenant['id'], user['id'], role['id'])
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_assign_user_role_request_without_token(self):
# Request to assign a role to a user without a valid token
(user, tenant, role) = self._get_role_params()
@@ -132,7 +132,7 @@
user['id'], role['id'])
self.client.auth_provider.clear_auth()
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_assign_user_role_for_non_existent_role(self):
# Attempt to assign a non existent role to user should fail
(user, tenant, role) = self._get_role_params()
@@ -140,7 +140,7 @@
self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
tenant['id'], user['id'], non_existent_role)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_assign_user_role_for_non_existent_tenant(self):
# Attempt to assign a role on a non existent tenant should fail
(user, tenant, role) = self._get_role_params()
@@ -148,7 +148,7 @@
self.assertRaises(exceptions.NotFound, self.client.assign_user_role,
non_existent_tenant, user['id'], role['id'])
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_assign_duplicate_user_role(self):
# Duplicate user role should not get assigned
(user, tenant, role) = self._get_role_params()
@@ -156,7 +156,7 @@
self.assertRaises(exceptions.Conflict, self.client.assign_user_role,
tenant['id'], user['id'], role['id'])
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_remove_user_role_by_unauthorized_user(self):
# Non-administrator user should not be authorized to
# remove a user's role
@@ -168,7 +168,7 @@
self.non_admin_client.remove_user_role,
tenant['id'], user['id'], role['id'])
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_remove_user_role_request_without_token(self):
# Request to remove a user's role without a valid token
(user, tenant, role) = self._get_role_params()
@@ -182,7 +182,7 @@
user['id'], role['id'])
self.client.auth_provider.clear_auth()
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_remove_user_role_non_existent_role(self):
# Attempt to delete a non existent role from a user should fail
(user, tenant, role) = self._get_role_params()
@@ -193,7 +193,7 @@
self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
tenant['id'], user['id'], non_existent_role)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_remove_user_role_non_existent_tenant(self):
# Attempt to remove a role from a non existent tenant should fail
(user, tenant, role) = self._get_role_params()
@@ -204,7 +204,7 @@
self.assertRaises(exceptions.NotFound, self.client.remove_user_role,
non_existent_tenant, user['id'], role['id'])
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_list_user_roles_by_unauthorized_user(self):
# Non-administrator user should not be authorized to list
# a user's roles
@@ -214,7 +214,7 @@
self.non_admin_client.list_user_roles, tenant['id'],
user['id'])
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_list_user_roles_request_without_token(self):
# Request to list user's roles without a valid token should fail
(user, tenant, role) = self._get_role_params()
diff --git a/tempest/api/identity/admin/test_services.py b/tempest/api/identity/admin/test_services.py
index e5cb348..0472e07 100644
--- a/tempest/api/identity/admin/test_services.py
+++ b/tempest/api/identity/admin/test_services.py
@@ -18,7 +18,7 @@
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class ServicesTestJSON(base.BaseIdentityV2AdminTest):
@@ -32,7 +32,7 @@
self.assertRaises(exceptions.NotFound, self.client.get_service,
service_id)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_create_get_delete_service(self):
# GET Service
# Creating a Service
@@ -66,7 +66,7 @@
self.assertEqual(fetched_service['description'],
service_data['description'])
- @attr(type='gate')
+ @test.attr(type='gate')
def test_create_service_without_description(self):
# Create a service only with name and type
name = data_utils.rand_name('service-')
@@ -80,7 +80,7 @@
self.assertIn('type', service)
self.assertEqual(type, service['type'])
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_list_services(self):
# Create, List, Verify and Delete Services
services = []
diff --git a/tempest/api/identity/admin/test_tenant_negative.py b/tempest/api/identity/admin/test_tenant_negative.py
index 44b54b8..622ad81 100644
--- a/tempest/api/identity/admin/test_tenant_negative.py
+++ b/tempest/api/identity/admin/test_tenant_negative.py
@@ -18,19 +18,19 @@
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class TenantsNegativeTestJSON(base.BaseIdentityV2AdminTest):
_interface = 'json'
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_list_tenants_by_unauthorized_user(self):
# Non-administrator user should not be able to list tenants
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.list_tenants)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_list_tenant_request_without_token(self):
# Request to list tenants without a valid token should fail
token = self.client.auth_provider.get_token()
@@ -38,7 +38,7 @@
self.assertRaises(exceptions.Unauthorized, self.client.list_tenants)
self.client.auth_provider.clear_auth()
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_tenant_delete_by_unauthorized_user(self):
# Non-administrator user should not be able to delete a tenant
tenant_name = data_utils.rand_name(name='tenant-')
@@ -48,7 +48,7 @@
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.delete_tenant, tenant['id'])
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_tenant_delete_request_without_token(self):
# Request to delete a tenant without a valid token should fail
tenant_name = data_utils.rand_name(name='tenant-')
@@ -61,13 +61,13 @@
tenant['id'])
self.client.auth_provider.clear_auth()
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_delete_non_existent_tenant(self):
# Attempt to delete a non existent tenant should fail
self.assertRaises(exceptions.NotFound, self.client.delete_tenant,
str(uuid.uuid4().hex))
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_tenant_create_duplicate(self):
# Tenant names should be unique
tenant_name = data_utils.rand_name(name='tenant-')
@@ -82,14 +82,14 @@
self.assertRaises(exceptions.Conflict, self.client.create_tenant,
tenant_name)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_tenant_by_unauthorized_user(self):
# Non-administrator user should not be authorized to create a tenant
tenant_name = data_utils.rand_name(name='tenant-')
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.create_tenant, tenant_name)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_tenant_request_without_token(self):
# Create tenant request without a token should not be authorized
tenant_name = data_utils.rand_name(name='tenant-')
@@ -99,26 +99,26 @@
tenant_name)
self.client.auth_provider.clear_auth()
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_tenant_with_empty_name(self):
# Tenant name should not be empty
self.assertRaises(exceptions.BadRequest, self.client.create_tenant,
name='')
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_tenants_name_length_over_64(self):
# Tenant name length should not be greater than 64 characters
tenant_name = 'a' * 65
self.assertRaises(exceptions.BadRequest, self.client.create_tenant,
tenant_name)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_update_non_existent_tenant(self):
# Attempt to update a non existent tenant should fail
self.assertRaises(exceptions.NotFound, self.client.update_tenant,
str(uuid.uuid4().hex))
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_tenant_update_by_unauthorized_user(self):
# Non-administrator user should not be able to update a tenant
tenant_name = data_utils.rand_name(name='tenant-')
@@ -128,7 +128,7 @@
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.update_tenant, tenant['id'])
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_tenant_update_request_without_token(self):
# Request to update a tenant without a valid token should fail
tenant_name = data_utils.rand_name(name='tenant-')
diff --git a/tempest/api/identity/admin/test_tenants.py b/tempest/api/identity/admin/test_tenants.py
index 7ba46bb..b989664 100644
--- a/tempest/api/identity/admin/test_tenants.py
+++ b/tempest/api/identity/admin/test_tenants.py
@@ -17,13 +17,13 @@
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
class TenantsTestJSON(base.BaseIdentityV2AdminTest):
_interface = 'json'
- @attr(type='gate')
+ @test.attr(type='gate')
def test_tenant_list_delete(self):
# Create several tenants and delete them
tenants = []
@@ -48,7 +48,7 @@
found = [tenant for tenant in body if tenant['id'] in tenant_ids]
self.assertFalse(any(found), 'Tenants failed to delete')
- @attr(type='gate')
+ @test.attr(type='gate')
def test_tenant_create_with_description(self):
# Create tenant with a description
tenant_name = data_utils.rand_name(name='tenant-')
@@ -69,7 +69,7 @@
self.client.delete_tenant(tenant_id)
self.data.tenants.remove(tenant)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_tenant_create_enabled(self):
# Create a tenant that is enabled
tenant_name = data_utils.rand_name(name='tenant-')
@@ -86,7 +86,7 @@
self.client.delete_tenant(tenant_id)
self.data.tenants.remove(tenant)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_tenant_create_not_enabled(self):
# Create a tenant that is not enabled
tenant_name = data_utils.rand_name(name='tenant-')
@@ -105,7 +105,7 @@
self.client.delete_tenant(tenant_id)
self.data.tenants.remove(tenant)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_tenant_update_name(self):
# Update name attribute of a tenant
t_name1 = data_utils.rand_name(name='tenant-')
@@ -133,7 +133,7 @@
self.client.delete_tenant(t_id)
self.data.tenants.remove(tenant)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_tenant_update_desc(self):
# Update description attribute of a tenant
t_name = data_utils.rand_name(name='tenant-')
@@ -162,7 +162,7 @@
self.client.delete_tenant(t_id)
self.data.tenants.remove(tenant)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_tenant_update_enable(self):
# Update the enabled attribute of a tenant
t_name = data_utils.rand_name(name='tenant-')
diff --git a/tempest/api/identity/admin/test_tokens.py b/tempest/api/identity/admin/test_tokens.py
index 7fec28d..08e12f0 100644
--- a/tempest/api/identity/admin/test_tokens.py
+++ b/tempest/api/identity/admin/test_tokens.py
@@ -15,13 +15,13 @@
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
class TokensTestJSON(base.BaseIdentityV2AdminTest):
_interface = 'json'
- @attr(type='gate')
+ @test.attr(type='gate')
def test_create_get_delete_token(self):
# get a token by username and password
user_name = data_utils.rand_name(name='user-')
@@ -56,7 +56,7 @@
resp, body = self.client.delete_token(token_id)
self.assertEqual(resp['status'], '204')
- @attr(type='gate')
+ @test.attr(type='gate')
def test_rescope_token(self):
"""An unscoped token can be requested, that token can be used to
request a scoped token.
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/identity/admin/test_users_negative.py b/tempest/api/identity/admin/test_users_negative.py
index 4e8ebe5..a584a7b 100644
--- a/tempest/api/identity/admin/test_users_negative.py
+++ b/tempest/api/identity/admin/test_users_negative.py
@@ -18,7 +18,7 @@
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class UsersNegativeTestJSON(base.BaseIdentityV2AdminTest):
@@ -31,7 +31,7 @@
cls.alt_password = data_utils.rand_name('pass_')
cls.alt_email = cls.alt_user + '@testmail.tm'
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_user_by_unauthorized_user(self):
# Non-administrator should not be authorized to create a user
self.data.setup_test_tenant()
@@ -40,7 +40,7 @@
self.alt_password, self.data.tenant['id'],
self.alt_email)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_user_with_empty_name(self):
# User with an empty name should not be created
self.data.setup_test_tenant()
@@ -48,7 +48,7 @@
self.alt_password, self.data.tenant['id'],
self.alt_email)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_user_with_name_length_over_255(self):
# Length of user name filed should be restricted to 255 characters
self.data.setup_test_tenant()
@@ -56,7 +56,7 @@
'a' * 256, self.alt_password,
self.data.tenant['id'], self.alt_email)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_user_with_duplicate_name(self):
# Duplicate user should not be created
self.data.setup_test_user()
@@ -64,14 +64,14 @@
self.data.test_user, self.data.test_password,
self.data.tenant['id'], self.data.test_email)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_user_for_non_existent_tenant(self):
# Attempt to create a user in a non-existent tenant should fail
self.assertRaises(exceptions.NotFound, self.client.create_user,
self.alt_user, self.alt_password, '49ffgg99999',
self.alt_email)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_user_request_without_a_token(self):
# Request to create a user without a valid token should fail
self.data.setup_test_tenant()
@@ -86,7 +86,7 @@
# Unset the token to allow further tests to generate a new token
self.client.auth_provider.clear_auth()
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_user_with_enabled_non_bool(self):
# Attempt to create a user with valid enabled para should fail
self.data.setup_test_tenant()
@@ -96,7 +96,7 @@
self.data.tenant['id'],
self.alt_email, enabled=3)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_update_user_for_non_existent_user(self):
# Attempt to update a user non-existent user should fail
user_name = data_utils.rand_name('user-')
@@ -104,7 +104,7 @@
self.assertRaises(exceptions.NotFound, self.client.update_user,
non_existent_id, name=user_name)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_update_user_request_without_a_token(self):
# Request to update a user without a valid token should fail
@@ -118,14 +118,14 @@
# Unset the token to allow further tests to generate a new token
self.client.auth_provider.clear_auth()
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_update_user_by_unauthorized_user(self):
# Non-administrator should not be authorized to update user
self.data.setup_test_tenant()
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.update_user, self.alt_user)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_delete_users_by_unauthorized_user(self):
# Non-administrator user should not be authorized to delete a user
self.data.setup_test_user()
@@ -133,13 +133,13 @@
self.non_admin_client.delete_user,
self.data.user['id'])
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_delete_non_existent_user(self):
# Attempt to delete a non-existent user should fail
self.assertRaises(exceptions.NotFound, self.client.delete_user,
'junk12345123')
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_delete_user_request_without_a_token(self):
# Request to delete a user without a valid token should fail
@@ -153,7 +153,7 @@
# Unset the token to allow further tests to generate a new token
self.client.auth_provider.clear_auth()
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_authentication_for_disabled_user(self):
# Disabled user's token should not get authenticated
self.data.setup_test_user()
@@ -163,7 +163,7 @@
self.data.test_password,
self.data.test_tenant)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_authentication_when_tenant_is_disabled(self):
# User's token for a disabled tenant should not be authenticated
self.data.setup_test_user()
@@ -173,7 +173,7 @@
self.data.test_password,
self.data.test_tenant)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_authentication_with_invalid_tenant(self):
# User's token for an invalid tenant should not be authenticated
self.data.setup_test_user()
@@ -182,7 +182,7 @@
self.data.test_password,
'junktenant1234')
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_authentication_with_invalid_username(self):
# Non-existent user's token should not get authenticated
self.data.setup_test_user()
@@ -190,7 +190,7 @@
'junkuser123', self.data.test_password,
self.data.test_tenant)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_authentication_with_invalid_password(self):
# User's token with invalid password should not be authenticated
self.data.setup_test_user()
@@ -198,14 +198,14 @@
self.data.test_user, 'junkpass1234',
self.data.test_tenant)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_get_users_by_unauthorized_user(self):
# Non-administrator user should not be authorized to get user list
self.data.setup_test_user()
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.get_users)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_get_users_request_without_token(self):
# Request to get list of users without a valid token should fail
token = self.client.auth_provider.get_token()
@@ -213,7 +213,7 @@
self.assertRaises(exceptions.Unauthorized, self.client.get_users)
self.client.auth_provider.clear_auth()
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_list_users_with_invalid_tenant(self):
# Should not be able to return a list of all
# users for a non-existent tenant
diff --git a/tempest/api/identity/admin/v3/test_certificates.py b/tempest/api/identity/admin/v3/test_certificates.py
new file mode 100644
index 0000000..a53ee0a
--- /dev/null
+++ b/tempest/api/identity/admin/v3/test_certificates.py
@@ -0,0 +1,43 @@
+# 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.identity import base
+from tempest import test
+
+
+class CertificatesV3TestJSON(base.BaseIdentityV3AdminTest):
+ _interface = 'json'
+
+ def _verify_response(self, expected, actual):
+ missing_tags = [t for t in expected if t not in actual]
+ self.assertEqual(0, len(missing_tags),
+ "Failed to fetch expected tag"
+ "in the certificate: %s" % ','.join(missing_tags))
+
+ @test.attr(type='smoke')
+ def test_get_ca_certificate(self):
+ # Verify ca certificate chain
+ expected_tags = ['BEGIN CERTIFICATE', 'END CERTIFICATE']
+ resp, certificate = self.client.get_ca_certificate()
+ self.assertEqual(200, resp.status)
+ self._verify_response(expected_tags, certificate)
+
+ @test.attr(type='smoke')
+ def test_get_certificates(self):
+ # Verify signing certificates
+ expected_tags = ['Certificate', 'BEGIN CERTIFICATE', 'END CERTIFICATE']
+ resp, certificates = self.client.get_certificates()
+ self.assertEqual(200, resp.status)
+ self._verify_response(expected_tags, certificates)
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index 086d235..a1e6cde 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -16,7 +16,7 @@
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
class DomainsTestJSON(base.BaseIdentityV3AdminTest):
@@ -29,7 +29,7 @@
resp, _ = self.client.delete_domain(domain_id)
self.assertEqual(204, resp.status)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_list_domains(self):
# Test to list domains
domain_ids = list()
@@ -49,7 +49,7 @@
missing_doms = [d for d in domain_ids if d not in fetched_ids]
self.assertEqual(0, len(missing_doms))
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_create_update_delete_domain(self):
d_name = data_utils.rand_name('domain-')
d_desc = data_utils.rand_name('domain-desc-')
diff --git a/tempest/api/identity/admin/v3/test_endpoints_negative.py b/tempest/api/identity/admin/v3/test_endpoints_negative.py
index 28615a4..5b46f89 100644
--- a/tempest/api/identity/admin/v3/test_endpoints_negative.py
+++ b/tempest/api/identity/admin/v3/test_endpoints_negative.py
@@ -18,7 +18,7 @@
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class EndpointsNegativeTestJSON(base.BaseIdentityV3AdminTest):
@@ -45,7 +45,7 @@
cls.service_client.delete_service(s)
super(EndpointsNegativeTestJSON, cls).tearDownClass()
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_with_enabled_False(self):
# Enabled should be a boolean, not a string like 'False'
interface = 'public'
@@ -55,7 +55,7 @@
self.service_id, interface, url, region=region,
force_enabled='False')
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_with_enabled_True(self):
# Enabled should be a boolean, not a string like 'True'
interface = 'public'
@@ -79,12 +79,12 @@
self.assertRaises(exceptions.BadRequest, self.client.update_endpoint,
endpoint_for_update['id'], force_enabled=enabled)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_update_with_enabled_False(self):
# Enabled should be a boolean, not a string like 'False'
self._assert_update_raises_bad_request('False')
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_update_with_enabled_True(self):
# Enabled should be a boolean, not a string like 'True'
self._assert_update_raises_bad_request('True')
diff --git a/tempest/api/identity/admin/v3/test_policies.py b/tempest/api/identity/admin/v3/test_policies.py
index 3e04b5f..0e79440 100644
--- a/tempest/api/identity/admin/v3/test_policies.py
+++ b/tempest/api/identity/admin/v3/test_policies.py
@@ -15,7 +15,7 @@
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
class PoliciesTestJSON(base.BaseIdentityV3AdminTest):
@@ -25,7 +25,7 @@
resp, _ = self.policy_client.delete_policy(policy_id)
self.assertEqual(204, resp.status)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_list_policies(self):
# Test to list policies
policy_ids = list()
@@ -46,7 +46,7 @@
missing_pols = [p for p in policy_ids if p not in fetched_ids]
self.assertEqual(0, len(missing_pols))
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_create_update_delete_policy(self):
# Test to update policy
blob = data_utils.rand_name('BlobName-')
diff --git a/tempest/api/identity/admin/v3/test_services.py b/tempest/api/identity/admin/v3/test_services.py
index c5d4ddf..36e5327 100644
--- a/tempest/api/identity/admin/v3/test_services.py
+++ b/tempest/api/identity/admin/v3/test_services.py
@@ -16,13 +16,13 @@
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
class ServicesTestJSON(base.BaseIdentityV3AdminTest):
_interface = 'json'
- @attr(type='gate')
+ @test.attr(type='gate')
def test_update_service(self):
# Update description attribute of service
name = data_utils.rand_name('service-')
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index ebc1cac..fe3eb03 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -16,13 +16,13 @@
from tempest.api.identity import base
from tempest.common.utils import data_utils
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class TokensV3TestJSON(base.BaseIdentityV3AdminTest):
_interface = 'json'
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_tokens(self):
# Valid user's token is authenticated
# Create a User
@@ -50,7 +50,7 @@
self.assertRaises(exceptions.NotFound, self.client.get_token,
subject_token)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_rescope_token(self):
"""Rescope a token.
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index e1d1543..7316c7f 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -15,13 +15,13 @@
from tempest.api.identity import base
from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
class UsersV3TestJSON(base.BaseIdentityV3AdminTest):
_interface = 'json'
- @attr(type='gate')
+ @test.attr(type='gate')
def test_user_update(self):
# Test case to check if updating of user attributes is successful.
# Creating first user
@@ -66,7 +66,7 @@
self.assertEqual(u_email2, new_user_get['email'])
self.assertEqual('false', str(new_user_get['enabled']).lower())
- @attr(type='gate')
+ @test.attr(type='gate')
def test_list_user_projects(self):
# List the projects that a user has access upon
assigned_project_ids = list()
@@ -120,7 +120,7 @@
', '.join(m_project for m_project
in missing_projects))
- @attr(type='gate')
+ @test.attr(type='gate')
def test_get_user(self):
# Get a user detail
self.data.setup_test_v3_user()
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 31ffd14..9981292 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)
@@ -132,15 +129,11 @@
if CONF.compute.allow_tenant_isolation:
creds = cls.isolated_creds.get_alt_creds()
cls.os_alt = clients.Manager(creds)
- cls.alt_tenant_id = cls.isolated_creds.get_alt_creds().tenant_id
else:
cls.os_alt = clients.AltManager()
- alt_tenant_name = cls.os_alt.credentials['tenant_name']
- identity_client = cls._get_identity_admin_client()
- cls.alt_tenant_id = identity_client.get_tenant_by_name(
- alt_tenant_name)['id']
cls.os_img_client = cls.os.image_client_v2
cls.alt_img_client = cls.os_alt.image_client_v2
+ cls.alt_tenant_id = cls.alt_img_client.tenant_id
def _list_image_ids_as_alt(self):
_, image_list = self.alt_img_client.image_list()
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/network/test_networks_negative.py b/tempest/api/network/test_networks_negative.py
index 89c8a9f..53dfc52 100644
--- a/tempest/api/network/test_networks_negative.py
+++ b/tempest/api/network/test_networks_negative.py
@@ -17,37 +17,37 @@
from tempest.api.network import base
from tempest.common.utils import data_utils
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class NetworksNegativeTestJSON(base.BaseNetworkTest):
_interface = 'json'
- @attr(type=['negative', 'smoke'])
+ @test.attr(type=['negative', 'smoke'])
def test_show_non_existent_network(self):
non_exist_id = data_utils.rand_name('network')
self.assertRaises(exceptions.NotFound, self.client.show_network,
non_exist_id)
- @attr(type=['negative', 'smoke'])
+ @test.attr(type=['negative', 'smoke'])
def test_show_non_existent_subnet(self):
non_exist_id = data_utils.rand_name('subnet')
self.assertRaises(exceptions.NotFound, self.client.show_subnet,
non_exist_id)
- @attr(type=['negative', 'smoke'])
+ @test.attr(type=['negative', 'smoke'])
def test_show_non_existent_port(self):
non_exist_id = data_utils.rand_name('port')
self.assertRaises(exceptions.NotFound, self.client.show_port,
non_exist_id)
- @attr(type=['negative', 'smoke'])
+ @test.attr(type=['negative', 'smoke'])
def test_update_non_existent_network(self):
non_exist_id = data_utils.rand_name('network')
self.assertRaises(exceptions.NotFound, self.client.update_network,
non_exist_id, name="new_name")
- @attr(type=['negative', 'smoke'])
+ @test.attr(type=['negative', 'smoke'])
def test_delete_non_existent_network(self):
non_exist_id = data_utils.rand_name('network')
self.assertRaises(exceptions.NotFound, self.client.delete_network,
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index 3e26f46..97b3c4b 100644
--- a/tempest/api/network/test_security_groups.py
+++ b/tempest/api/network/test_security_groups.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import six
+
from tempest.api.network import base_security_groups as base
from tempest.common.utils import data_utils
from tempest import test
@@ -88,18 +90,24 @@
rule_create_body['security_group_rule']['id']
)
- # Show details of the created security rule
- resp, show_rule_body = self.client.show_security_group_rule(
- rule_create_body['security_group_rule']['id']
- )
- self.assertEqual('200', resp['status'])
+ # Show details of the created security rule
+ resp, show_rule_body = self.client.show_security_group_rule(
+ rule_create_body['security_group_rule']['id']
+ )
+ self.assertEqual('200', resp['status'])
+ create_dict = rule_create_body['security_group_rule']
+ for key, value in six.iteritems(create_dict):
+ self.assertEqual(value,
+ show_rule_body['security_group_rule'][key],
+ "%s does not match." % key)
- # List rules and verify created rule is in response
- resp, rule_list_body = self.client.list_security_group_rules()
- self.assertEqual('200', resp['status'])
- rule_list = [rule['id']
- for rule in rule_list_body['security_group_rules']]
- self.assertIn(rule_create_body['security_group_rule']['id'], rule_list)
+ # List rules and verify created rule is in response
+ resp, rule_list_body = self.client.list_security_group_rules()
+ self.assertEqual('200', resp['status'])
+ rule_list = [rule['id']
+ for rule in rule_list_body['security_group_rules']]
+ self.assertIn(rule_create_body['security_group_rule']['id'],
+ rule_list)
@test.attr(type='smoke')
def test_create_security_group_rule_with_additional_args(self):
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/object_storage/test_account_services_negative.py b/tempest/api/object_storage/test_account_services_negative.py
index d5f8649..490672d 100644
--- a/tempest/api/object_storage/test_account_services_negative.py
+++ b/tempest/api/object_storage/test_account_services_negative.py
@@ -17,12 +17,12 @@
from tempest.api.object_storage import base
from tempest import clients
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class AccountNegativeTest(base.BaseObjectTest):
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_list_containers_with_non_authorized_user(self):
# list containers using non-authorized user
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index 4e40de9..d4bda19 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -60,11 +60,14 @@
return admin_client
@classmethod
- def create_stack(cls, stack_name, template_data, parameters={}):
+ def create_stack(cls, stack_name, template_data, parameters={},
+ environment=None, files=None):
resp, body = cls.client.create_stack(
stack_name,
template=template_data,
- parameters=parameters)
+ parameters=parameters,
+ environment=environment,
+ files=files)
stack_id = resp['location'].split('/')[-1]
stack_identifier = '%s/%s' % (stack_name, stack_id)
cls.stacks.append(stack_identifier)
diff --git a/tempest/api/orchestration/stacks/templates/random_string.yaml b/tempest/api/orchestration/stacks/templates/random_string.yaml
new file mode 100644
index 0000000..dfd2342
--- /dev/null
+++ b/tempest/api/orchestration/stacks/templates/random_string.yaml
@@ -0,0 +1,18 @@
+heat_template_version: 2013-05-23
+
+parameters:
+ random_length:
+ type: number
+ default: 10
+
+resources:
+ random:
+ type: OS::Heat::RandomString
+ properties:
+ length: {get_param: random_length}
+
+outputs:
+ random_length:
+ value: {get_param: random_length}
+ random_value:
+ value: {get_attr: [random, value]}
diff --git a/tempest/api/orchestration/stacks/test_environment.py b/tempest/api/orchestration/stacks/test_environment.py
new file mode 100644
index 0000000..3911e72
--- /dev/null
+++ b/tempest/api/orchestration/stacks/test_environment.py
@@ -0,0 +1,93 @@
+# 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 logging
+
+from tempest.api.orchestration import base
+from tempest.common.utils import data_utils
+from tempest import config
+from tempest import test
+
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+
+class StackEnvironmentTest(base.BaseOrchestrationTest):
+
+ @test.attr(type='gate')
+ def test_environment_parameter(self):
+ """Test passing a stack parameter via the environment."""
+ stack_name = data_utils.rand_name('heat')
+ template = self.load_template('random_string')
+ environment = {'parameters': {'random_length': 20}}
+
+ stack_identifier = self.create_stack(stack_name, template,
+ environment=environment)
+ self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
+
+ random_len = self.get_stack_output(stack_identifier, 'random_length')
+ self.assertEqual(20, random_len)
+
+ random_value = self.get_stack_output(stack_identifier, 'random_value')
+ self.assertEqual(20, len(random_value))
+
+ @test.attr(type='gate')
+ def test_environment_provider_resource(self):
+ """Test passing resource_registry defining a provider resource."""
+ stack_name = data_utils.rand_name('heat')
+ template = '''
+heat_template_version: 2013-05-23
+resources:
+ random:
+ type: My:Random::String
+outputs:
+ random_value:
+ value: {get_attr: [random, random_value]}
+'''
+ environment = {'resource_registry':
+ {'My:Random::String': 'my_random.yaml'}}
+ files = {'my_random.yaml': self.load_template('random_string')}
+
+ stack_identifier = self.create_stack(stack_name, template,
+ environment=environment,
+ files=files)
+ self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
+
+ # random_string.yaml specifies a length of 10
+ random_value = self.get_stack_output(stack_identifier, 'random_value')
+ self.assertEqual(10, len(random_value))
+
+ @test.attr(type='gate')
+ def test_files_provider_resource(self):
+ """Test untyped defining of a provider resource via "files"."""
+ # It's also possible to specify the filename directly in the template.
+ # without adding the type alias to resource_registry
+ stack_name = data_utils.rand_name('heat')
+ template = '''
+heat_template_version: 2013-05-23
+resources:
+ random:
+ type: my_random.yaml
+outputs:
+ random_value:
+ value: {get_attr: [random, random_value]}
+'''
+ files = {'my_random.yaml': self.load_template('random_string')}
+
+ stack_identifier = self.create_stack(stack_name, template,
+ files=files)
+ self.client.wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
+
+ # random_string.yaml specifies a length of 10
+ random_value = self.get_stack_output(stack_identifier, 'random_value')
+ self.assertEqual(10, len(random_value))
diff --git a/tempest/api/orchestration/stacks/test_limits.py b/tempest/api/orchestration/stacks/test_limits.py
index 283ab2b..8ee62ab 100644
--- a/tempest/api/orchestration/stacks/test_limits.py
+++ b/tempest/api/orchestration/stacks/test_limits.py
@@ -16,7 +16,7 @@
from tempest.common.utils import data_utils
from tempest import config
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
CONF = config.CONF
@@ -25,7 +25,7 @@
class TestServerStackLimits(base.BaseOrchestrationTest):
- @attr(type='gate')
+ @test.attr(type='gate')
def test_exceed_max_template_size_fails(self):
stack_name = data_utils.rand_name('heat')
fill = 'A' * CONF.orchestration.max_template_size
@@ -38,7 +38,7 @@
stack_name, template)
self.assertIn('Template exceeds maximum allowed size', str(ex))
- @attr(type='gate')
+ @test.attr(type='gate')
def test_exceed_max_resources_per_stack(self):
stack_name = data_utils.rand_name('heat')
# Create a big template, one resource more than the limit
diff --git a/tempest/api/orchestration/stacks/test_non_empty_stack.py b/tempest/api/orchestration/stacks/test_non_empty_stack.py
index 9ef95a1..9cf59a5 100644
--- a/tempest/api/orchestration/stacks/test_non_empty_stack.py
+++ b/tempest/api/orchestration/stacks/test_non_empty_stack.py
@@ -14,7 +14,7 @@
from tempest.api.orchestration import base
from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
LOG = logging.getLogger(__name__)
@@ -48,14 +48,14 @@
self.assertEqual(expected_num, len(stacks))
return stacks
- @attr(type='gate')
+ @test.attr(type='gate')
def test_stack_list(self):
"""Created stack should be in the list of existing stacks."""
stacks = self._list_stacks()
stacks_names = map(lambda stack: stack['stack_name'], stacks)
self.assertIn(self.stack_name, stacks_names)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_stack_show(self):
"""Getting details about created stack should be possible."""
resp, stack = self.client.get_stack(self.stack_name)
@@ -75,7 +75,7 @@
self.assertEqual(self.stack_id, stack['id'])
self.assertEqual('fluffy', stack['outputs'][0]['output_key'])
- @attr(type='gate')
+ @test.attr(type='gate')
def test_suspend_resume_stack(self):
"""Suspend and resume a stack."""
resp, suspend_stack = self.client.suspend_stack(self.stack_identifier)
@@ -87,14 +87,14 @@
self.client.wait_for_stack_status(self.stack_identifier,
'RESUME_COMPLETE')
- @attr(type='gate')
+ @test.attr(type='gate')
def test_list_resources(self):
"""Getting list of created resources for the stack should be possible.
"""
resources = self.list_resources(self.stack_identifier)
self.assertEqual({self.resource_name: self.resource_type}, resources)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_show_resource(self):
"""Getting details about created resource should be possible."""
resp, resource = self.client.get_resource(self.stack_identifier,
@@ -108,7 +108,7 @@
self.assertEqual(self.resource_name, resource['logical_resource_id'])
self.assertEqual(self.resource_type, resource['resource_type'])
- @attr(type='gate')
+ @test.attr(type='gate')
def test_resource_metadata(self):
"""Getting metadata for created resources should be possible."""
resp, metadata = self.client.show_resource_metadata(
@@ -118,7 +118,7 @@
self.assertIsInstance(metadata, dict)
self.assertEqual(['Tom', 'Stinky'], metadata.get('kittens', None))
- @attr(type='gate')
+ @test.attr(type='gate')
def test_list_events(self):
"""Getting list of created events for the stack should be possible."""
resp, events = self.client.list_events(self.stack_identifier)
@@ -134,7 +134,7 @@
self.assertIn('CREATE_IN_PROGRESS', resource_statuses)
self.assertIn('CREATE_COMPLETE', resource_statuses)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_show_event(self):
"""Getting details about an event should be possible."""
resp, events = self.client.list_resource_events(self.stack_identifier,
diff --git a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
index 7f088de..cb70d07 100644
--- a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
+++ b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
@@ -15,7 +15,7 @@
from tempest.api.orchestration import base
from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
LOG = logging.getLogger(__name__)
@@ -46,7 +46,7 @@
for resource in resources:
cls.test_resources[resource['logical_resource_id']] = resource
- @attr(type='slow')
+ @test.attr(type='slow')
def test_created_resources(self):
"""Verifies created keypair resource."""
resources = [('KeyPairSavePrivate', 'OS::Nova::KeyPair'),
@@ -59,7 +59,7 @@
self.assertEqual(resource_type, resource['resource_type'])
self.assertEqual('CREATE_COMPLETE', resource['resource_status'])
- @attr(type='slow')
+ @test.attr(type='slow')
def test_stack_keypairs_output(self):
resp, stack = self.client.get_stack(self.stack_name)
self.assertEqual('200', resp['status'])
diff --git a/tempest/api/orchestration/stacks/test_stacks.py b/tempest/api/orchestration/stacks/test_stacks.py
index 867995c..5b45d82 100644
--- a/tempest/api/orchestration/stacks/test_stacks.py
+++ b/tempest/api/orchestration/stacks/test_stacks.py
@@ -13,7 +13,7 @@
from tempest.api.orchestration import base
from tempest.common.utils import data_utils
from tempest.openstack.common import log as logging
-from tempest.test import attr
+from tempest import test
LOG = logging.getLogger(__name__)
@@ -26,13 +26,13 @@
def setUpClass(cls):
super(StacksTestJSON, cls).setUpClass()
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_stack_list_responds(self):
resp, stacks = self.client.list_stacks()
self.assertEqual('200', resp['status'])
self.assertIsInstance(stacks, list)
- @attr(type='smoke')
+ @test.attr(type='smoke')
def test_stack_crud_no_resources(self):
stack_name = data_utils.rand_name('heat')
diff --git a/tempest/api/telemetry/test_telemetry_alarming_api.py b/tempest/api/telemetry/test_telemetry_alarming_api.py
index 3472b31..95758e8 100644
--- a/tempest/api/telemetry/test_telemetry_alarming_api.py
+++ b/tempest/api/telemetry/test_telemetry_alarming_api.py
@@ -13,7 +13,7 @@
from tempest.api.telemetry import base
from tempest.common.utils import data_utils
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class TelemetryAlarmingAPITestJSON(base.BaseTelemetryTest):
@@ -29,7 +29,7 @@
for i in range(2):
cls.create_alarm(threshold_rule=cls.rule)
- @attr(type="gate")
+ @test.attr(type="gate")
def test_alarm_list(self):
# List alarms
resp, alarm_list = self.telemetry_client.list_alarms()
@@ -43,7 +43,7 @@
" in a fetched list: %s" %
', '.join(str(a) for a in missing_alarms))
- @attr(type="gate")
+ @test.attr(type="gate")
def test_create_update_get_delete_alarm(self):
# Create an alarm
alarm_name = data_utils.rand_name('telemetry_alarm')
@@ -78,7 +78,7 @@
self.assertRaises(exceptions.NotFound,
self.telemetry_client.get_alarm, alarm_id)
- @attr(type="gate")
+ @test.attr(type="gate")
def test_set_get_alarm_state(self):
alarm_states = ['ok', 'alarm', 'insufficient data']
_, alarm = self.create_alarm(threshold_rule=self.rule)
@@ -94,7 +94,7 @@
self.assertEqual(200, resp.status)
self.assertEqual(new_state, state)
- @attr(type="gate")
+ @test.attr(type="gate")
def test_create_delete_alarm_with_combination_rule(self):
rule = {"alarm_ids": self.alarm_ids,
"operator": "or"}
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/interfaces.py b/tempest/api_schema/compute/interfaces.py
index 1e15c18..79a8f42 100644
--- a/tempest/api_schema/compute/interfaces.py
+++ b/tempest/api_schema/compute/interfaces.py
@@ -12,6 +12,36 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.api_schema.compute import parameter_types
+
delete_interface = {
'status_code': [202]
}
+
+interface_common_info = {
+ 'type': 'object',
+ 'properties': {
+ 'port_state': {'type': 'string'},
+ 'fixed_ips': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'subnet_id': {
+ 'type': 'string',
+ 'format': 'uuid'
+ },
+ 'ip_address': {
+ 'type': 'string',
+ 'format': 'ipv4'
+ }
+ },
+ 'required': ['subnet_id', 'ip_address']
+ }
+ },
+ 'port_id': {'type': 'string', 'format': 'uuid'},
+ 'net_id': {'type': 'string', 'format': 'uuid'},
+ 'mac_addr': parameter_types.mac_address
+ },
+ 'required': ['port_state', 'fixed_ips', 'port_id', 'net_id', 'mac_addr']
+}
diff --git a/tempest/api_schema/compute/servers.py b/tempest/api_schema/compute/servers.py
index aefb8f5..e11f047 100644
--- a/tempest/api_schema/compute/servers.py
+++ b/tempest/api_schema/compute/servers.py
@@ -117,3 +117,25 @@
delete_server_metadata_item = {
'status_code': [204]
}
+
+list_servers = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'servers': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'id': {'type': 'string'},
+ 'links': parameter_types.links,
+ 'name': {'type': 'string'}
+ },
+ 'required': ['id', 'links', 'name']
+ }
+ }
+ },
+ 'required': ['servers']
+ }
+}
diff --git a/tempest/api_schema/compute/v2/interfaces.py b/tempest/api_schema/compute/v2/interfaces.py
new file mode 100644
index 0000000..7fca791
--- /dev/null
+++ b/tempest/api_schema/compute/v2/interfaces.py
@@ -0,0 +1,29 @@
+# Copyright 2014 NEC Corporation. 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_schema.compute import interfaces as common_schema
+
+list_interfaces = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'interfaceAttachments': {
+ 'type': 'array',
+ 'items': common_schema.interface_common_info
+ }
+ },
+ 'required': ['interfaceAttachments']
+ }
+}
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/interfaces.py b/tempest/api_schema/compute/v3/interfaces.py
new file mode 100644
index 0000000..5e1cee2
--- /dev/null
+++ b/tempest/api_schema/compute/v3/interfaces.py
@@ -0,0 +1,29 @@
+# Copyright 2014 NEC Corporation. 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_schema.compute import interfaces as common_schema
+
+list_interfaces = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'interface_attachments': {
+ 'type': 'array',
+ 'items': common_schema.interface_common_info
+ }
+ },
+ 'required': ['interface_attachments']
+ }
+}
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..37049d6 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -17,7 +17,7 @@
import keystoneclient.v2_0.client
from tempest import auth
-from tempest.common.rest_client import NegativeRestClient
+from tempest.common import rest_client
from tempest import config
from tempest import exceptions
from tempest import manager
@@ -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,13 +347,16 @@
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(
self.auth_provider)
self.token_client = TokenClientJSON()
self.token_v3_client = V3TokenClientJSON()
- self.negative_client = NegativeRestClient(self.auth_provider)
+ self.negative_client = rest_client.NegativeRestClient(
+ self.auth_provider)
self.negative_client.service = service
else:
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 634634d..f9be90d 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -295,7 +295,15 @@
cfg.BoolOpt('vnc_console',
default=False,
help='Enable VNC console. This configuration value should '
- 'be same as [nova.vnc]->vnc_enabled in nova.conf')
+ 'be same as [nova.vnc]->vnc_enabled in nova.conf'),
+ cfg.BoolOpt('spice_console',
+ default=False,
+ help='Enable Spice console. This configuration value should '
+ 'be same as [nova.spice]->enabled in nova.conf'),
+ cfg.BoolOpt('rdp_console',
+ default=False,
+ help='Enable RDP console. This configuration value should '
+ 'be same as [nova.rdp]->enabled in nova.conf')
]
@@ -558,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 c745f4e..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
@@ -452,8 +454,8 @@
raise cls.skipException(msg)
# use an admin client manager for baremetal client
- username, password, tenant = cls.admin_credentials()
- manager = clients.OfficialClientManager(username, password, tenant)
+ admin_creds = cls.admin_credentials()
+ manager = clients.OfficialClientManager(credentials=admin_creds)
cls.baremetal_client = manager.baremetal_client
# allow any issues obtaining the node list to raise early
diff --git a/tempest/scenario/test_load_balancer_basic.py b/tempest/scenario/test_load_balancer_basic.py
index d771aed..9152220 100644
--- a/tempest/scenario/test_load_balancer_basic.py
+++ b/tempest/scenario/test_load_balancer_basic.py
@@ -68,6 +68,7 @@
def setUp(self):
super(TestLoadBalancerBasic, self).setUp()
self.server_ips = {}
+ self.server_fixed_ips = {}
self._create_security_group()
def cleanup_wrapper(self, resource):
@@ -119,6 +120,7 @@
self.server_ips[server.id] = floating_ip.floating_ip_address
else:
self.server_ips[server.id] = server.networks[net['name']][0]
+ self.server_fixed_ips[server.id] = server.networks[net['name']][0]
self.assertTrue(self.servers_keypairs)
return server
@@ -231,8 +233,8 @@
but with different ports to listen on.
"""
- for server_id, ip in self.server_ips.iteritems():
- if len(self.server_ips) == 1:
+ for server_id, ip in self.server_fixed_ips.iteritems():
+ if len(self.server_fixed_ips) == 1:
member1 = self._create_member(address=ip,
protocol_port=self.port1,
pool_id=self.pool.id)
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index 0ba65cf..e0d5779 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -20,7 +20,7 @@
from tempest import config
from tempest.openstack.common import log as logging
from tempest.scenario import manager
-from tempest.test import services
+from tempest import test
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -140,7 +140,7 @@
'ACTIVE')
self._check_network_connectivity()
- @services('compute', 'network')
+ @test.services('compute', 'network')
def test_server_connectivity_stop_start(self):
self.server.stop()
self.status_timeout(self.compute_client.servers, self.server.id,
@@ -149,12 +149,12 @@
self.server.start()
self._wait_server_status_and_check_network_connectivity()
- @services('compute', 'network')
+ @test.services('compute', 'network')
def test_server_connectivity_reboot(self):
self.server.reboot()
self._wait_server_status_and_check_network_connectivity()
- @services('compute', 'network')
+ @test.services('compute', 'network')
def test_server_connectivity_rebuild(self):
image_ref_alt = CONF.compute.image_ref_alt
self.server.rebuild(image_ref_alt)
@@ -162,7 +162,7 @@
@testtools.skipUnless(CONF.compute_feature_enabled.pause,
'Pause is not available.')
- @services('compute', 'network')
+ @test.services('compute', 'network')
def test_server_connectivity_pause_unpause(self):
self.server.pause()
self.status_timeout(self.compute_client.servers, self.server.id,
@@ -173,7 +173,7 @@
@testtools.skipUnless(CONF.compute_feature_enabled.suspend,
'Suspend is not available.')
- @services('compute', 'network')
+ @test.services('compute', 'network')
def test_server_connectivity_suspend_resume(self):
self.server.suspend()
self.status_timeout(self.compute_client.servers, self.server.id,
@@ -184,7 +184,7 @@
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
'Resize is not available.')
- @services('compute', 'network')
+ @test.services('compute', 'network')
def test_server_connectivity_resize(self):
resize_flavor = CONF.compute.flavor_ref_alt
if resize_flavor == CONF.compute.flavor_ref:
diff --git a/tempest/services/compute/json/interfaces_client.py b/tempest/services/compute/json/interfaces_client.py
index 2f165a2..8d51123 100644
--- a/tempest/services/compute/json/interfaces_client.py
+++ b/tempest/services/compute/json/interfaces_client.py
@@ -17,6 +17,7 @@
import time
from tempest.api_schema.compute import interfaces as common_schema
+from tempest.api_schema.compute.v2 import interfaces as schema
from tempest.common import rest_client
from tempest import config
from tempest import exceptions
@@ -33,6 +34,7 @@
def list_interfaces(self, server):
resp, body = self.get('servers/%s/os-interface' % server)
body = json.loads(body)
+ self.validate_response(schema.list_interfaces, resp, body)
return resp, body['interfaceAttachments']
def create_interface(self, server, port_id=None, network_id=None,
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index f6b76e9..5204cd0 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -150,6 +150,7 @@
resp, body = self.get(url)
body = json.loads(body)
+ self.validate_response(common_schema.list_servers, resp, body)
return resp, body
def list_servers_with_detail(self, params=None):
@@ -199,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,
@@ -476,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/interfaces_client.py b/tempest/services/compute/v3/json/interfaces_client.py
index 25c8db7..77b3179 100644
--- a/tempest/services/compute/v3/json/interfaces_client.py
+++ b/tempest/services/compute/v3/json/interfaces_client.py
@@ -17,6 +17,7 @@
import time
from tempest.api_schema.compute import interfaces as common_schema
+from tempest.api_schema.compute.v3 import interfaces as schema
from tempest.common import rest_client
from tempest import config
from tempest import exceptions
@@ -33,6 +34,7 @@
def list_interfaces(self, server):
resp, body = self.get('servers/%s/os-attach-interfaces' % server)
body = json.loads(body)
+ self.validate_response(schema.list_interfaces, resp, body)
return resp, body['interface_attachments']
def create_interface(self, server, port_id=None, network_id=None,
diff --git a/tempest/services/compute/v3/json/servers_client.py b/tempest/services/compute/v3/json/servers_client.py
index a6d49f1..1990d39 100644
--- a/tempest/services/compute/v3/json/servers_client.py
+++ b/tempest/services/compute/v3/json/servers_client.py
@@ -150,6 +150,7 @@
resp, body = self.get(url)
body = json.loads(body)
+ self.validate_response(common_schema.list_servers, resp, body)
return resp, body
def list_servers_with_detail(self, params=None):
@@ -199,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):
@@ -468,3 +470,13 @@
def inject_network_info(self, server_id, **kwargs):
"""Inject the Network Info into server"""
return self.action(server_id, 'inject_network_info', None, **kwargs)
+
+ def get_spice_console(self, server_id, console_type):
+ """Get URL of Spice console."""
+ return self.action(server_id, "get_spice_console"
+ "console", type=console_type)
+
+ def get_rdp_console(self, server_id, console_type):
+ """Get URL of RDP console."""
+ return self.action(server_id, "get_rdp_console"
+ "console", type=console_type)
diff --git a/tempest/services/data_processing/v1_1/client.py b/tempest/services/data_processing/v1_1/client.py
index 194e300..b07e663 100644
--- a/tempest/services/data_processing/v1_1/client.py
+++ b/tempest/services/data_processing/v1_1/client.py
@@ -1,17 +1,16 @@
# Copyright (c) 2013 Mirantis Inc.
#
-# 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
+# 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
+# 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.
+# 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 json
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/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index 6829333..73e52a0 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -450,6 +450,16 @@
% (trust_id, role_id))
return resp, body
+ def get_ca_certificate(self):
+ """GET ca certificate chain."""
+ resp, body = self.get("OS-SIMPLE-CERT/ca")
+ return resp, body
+
+ def get_certificates(self):
+ """GET signing certificates used to sign tokens."""
+ resp, body = self.get("OS-SIMPLE-CERT/certificates")
+ return resp, body
+
class V3TokenClientJSON(rest_client.RestClient):
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/orchestration/json/orchestration_client.py b/tempest/services/orchestration/json/orchestration_client.py
index 2311bdd..c459f28 100644
--- a/tempest/services/orchestration/json/orchestration_client.py
+++ b/tempest/services/orchestration/json/orchestration_client.py
@@ -45,28 +45,32 @@
return resp, body['stacks']
def create_stack(self, name, disable_rollback=True, parameters={},
- timeout_mins=60, template=None, template_url=None):
+ timeout_mins=60, template=None, template_url=None,
+ environment=None, files=None):
headers, body = self._prepare_update_create(
name,
disable_rollback,
parameters,
timeout_mins,
template,
- template_url)
+ template_url,
+ environment,
+ files)
uri = 'stacks'
resp, body = self.post(uri, headers=headers, body=body)
return resp, body
def update_stack(self, stack_identifier, name, disable_rollback=True,
parameters={}, timeout_mins=60, template=None,
- template_url=None):
+ template_url=None, environment=None, files=None):
headers, body = self._prepare_update_create(
name,
disable_rollback,
parameters,
timeout_mins,
template,
- template_url)
+ template_url,
+ environment)
uri = "stacks/%s" % stack_identifier
resp, body = self.put(uri, headers=headers, body=body)
@@ -74,13 +78,16 @@
def _prepare_update_create(self, name, disable_rollback=True,
parameters={}, timeout_mins=60,
- template=None, template_url=None):
+ template=None, template_url=None,
+ environment=None, files=None):
post_body = {
"stack_name": name,
"disable_rollback": disable_rollback,
"parameters": parameters,
"timeout_mins": timeout_mins,
- "template": "HeatTemplateFormatVersion: '2012-12-12'\n"
+ "template": "HeatTemplateFormatVersion: '2012-12-12'\n",
+ "environment": environment,
+ "files": files
}
if template:
post_body['template'] = template
diff --git a/tempest/services/volume/xml/admin/volume_quotas_client.py b/tempest/services/volume/xml/admin/volume_quotas_client.py
index 710fb3a..dd1423f 100644
--- a/tempest/services/volume/xml/admin/volume_quotas_client.py
+++ b/tempest/services/volume/xml/admin/volume_quotas_client.py
@@ -14,7 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-from ast import literal_eval
+import ast
from lxml import etree
from tempest.common import xml_utils as xml
@@ -35,7 +35,7 @@
quota = {}
for k, v in q.items():
try:
- v = literal_eval(v)
+ v = ast.literal_eval(v)
except (ValueError, SyntaxError):
pass
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/common/utils/test_file_utils.py b/tempest/tests/common/utils/test_file_utils.py
index 99ae033..605e82a 100644
--- a/tempest/tests/common/utils/test_file_utils.py
+++ b/tempest/tests/common/utils/test_file_utils.py
@@ -14,7 +14,6 @@
# under the License.
import mock
-from mock import patch
from tempest.common.utils import file_utils
from tempest.tests import base
@@ -23,7 +22,7 @@
class TestFileUtils(base.TestCase):
def test_have_effective_read_path(self):
- with patch('__builtin__.open', mock.mock_open(), create=True):
+ with mock.patch('__builtin__.open', mock.mock_open(), create=True):
result = file_utils.have_effective_read_access('fake_path')
self.assertTrue(result)
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py
index 98a896f..7a9b6be 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/test_tenant_isolation.py
@@ -13,7 +13,7 @@
# under the License.
import keystoneclient.v2_0.client as keystoneclient
-from mock import patch
+import mock
import neutronclient.v2_0.client as neutronclient
from oslo.config import cfg
@@ -114,23 +114,21 @@
{'router': {'id': id, 'name': name}})))
return router_fix
- @patch('tempest.common.rest_client.RestClient')
+ @mock.patch('tempest.common.rest_client.RestClient')
def test_primary_creds(self, MockRestClient):
cfg.CONF.set_default('neutron', False, 'service_available')
iso_creds = isolated_creds.IsolatedCreds('test class',
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')
+ @mock.patch('tempest.common.rest_client.RestClient')
def test_admin_creds(self, MockRestClient):
cfg.CONF.set_default('neutron', False, 'service_available')
iso_creds = isolated_creds.IsolatedCreds('test class',
@@ -143,35 +141,33 @@
return_value=({'status': 200},
[{'id': '1234', 'name': 'admin'}])))
- user_mock = patch.object(json_iden_client.IdentityClientJSON,
- 'assign_user_role')
+ user_mock = mock.patch.object(json_iden_client.IdentityClientJSON,
+ 'assign_user_role')
user_mock.start()
self.addCleanup(user_mock.stop)
- with patch.object(json_iden_client.IdentityClientJSON,
- 'assign_user_role') as user_mock:
+ with mock.patch.object(json_iden_client.IdentityClientJSON,
+ 'assign_user_role') as user_mock:
admin_creds = iso_creds.get_admin_creds()
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')
+ @mock.patch('tempest.common.rest_client.RestClient')
def test_all_cred_cleanup(self, MockRestClient):
cfg.CONF.set_default('neutron', False, 'service_available')
iso_creds = isolated_creds.IsolatedCreds('test class',
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')
@@ -181,8 +177,8 @@
'list_roles',
return_value=({'status': 200},
[{'id': '123456', 'name': 'admin'}])))
- with patch.object(json_iden_client.IdentityClientJSON,
- 'assign_user_role'):
+ with mock.patch.object(json_iden_client.IdentityClientJSON,
+ 'assign_user_role'):
iso_creds.get_admin_creds()
user_mock = self.patch(
'tempest.services.identity.json.identity_client.'
@@ -206,23 +202,21 @@
self.assertIn('12345', args)
self.assertIn('123456', args)
- @patch('tempest.common.rest_client.RestClient')
+ @mock.patch('tempest.common.rest_client.RestClient')
def test_alt_creds(self, MockRestClient):
cfg.CONF.set_default('neutron', False, 'service_available')
iso_creds = isolated_creds.IsolatedCreds('test class',
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')
+ @mock.patch('tempest.common.rest_client.RestClient')
def test_network_creation(self, MockRestClient):
iso_creds = isolated_creds.IsolatedCreds('test class',
password='fake_password')
@@ -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()
@@ -246,7 +240,7 @@
self.assertEqual(router['id'], '1234')
self.assertEqual(router['name'], 'fake_router')
- @patch('tempest.common.rest_client.RestClient')
+ @mock.patch('tempest.common.rest_client.RestClient')
def test_network_cleanup(self, MockRestClient):
iso_creds = isolated_creds.IsolatedCreds('test class',
password='fake_password')
@@ -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()
@@ -295,28 +289,28 @@
'list_roles',
return_value=({'status': 200},
[{'id': '123456', 'name': 'admin'}])))
- with patch.object(json_iden_client.IdentityClientJSON,
- 'assign_user_role'):
+ with mock.patch.object(json_iden_client.IdentityClientJSON,
+ 'assign_user_role'):
iso_creds.get_admin_creds()
self.patch('tempest.services.identity.json.identity_client.'
'IdentityClientJSON.delete_user')
self.patch('tempest.services.identity.json.identity_client.'
'IdentityClientJSON.delete_tenant')
- net = patch.object(iso_creds.network_admin_client,
- 'delete_network')
+ net = mock.patch.object(iso_creds.network_admin_client,
+ 'delete_network')
net_mock = net.start()
- subnet = patch.object(iso_creds.network_admin_client,
- 'delete_subnet')
+ subnet = mock.patch.object(iso_creds.network_admin_client,
+ 'delete_subnet')
subnet_mock = subnet.start()
- router = patch.object(iso_creds.network_admin_client,
- 'delete_router')
+ router = mock.patch.object(iso_creds.network_admin_client,
+ 'delete_router')
router_mock = router.start()
remove_router_interface_mock = self.patch(
'tempest.services.network.json.network_client.NetworkClientJSON.'
'remove_router_interface_with_subnet_id')
- port_list_mock = patch.object(iso_creds.network_admin_client,
- 'list_ports', return_value=(
- {'status': 200}, {'ports': []}))
+ port_list_mock = mock.patch.object(iso_creds.network_admin_client,
+ 'list_ports', return_value=(
+ {'status': 200}, {'ports': []}))
port_list_mock.start()
iso_creds.clear_isolated_creds()
# Verify remove router interface calls
@@ -348,7 +342,7 @@
self.assertIn('12345', args)
self.assertIn('123456', args)
- @patch('tempest.common.rest_client.RestClient')
+ @mock.patch('tempest.common.rest_client.RestClient')
def test_network_alt_creation(self, MockRestClient):
iso_creds = isolated_creds.IsolatedCreds('test class',
password='fake_password')
@@ -372,7 +366,7 @@
self.assertEqual(router['id'], '1234')
self.assertEqual(router['name'], 'fake_alt_router')
- @patch('tempest.common.rest_client.RestClient')
+ @mock.patch('tempest.common.rest_client.RestClient')
def test_network_admin_creation(self, MockRestClient):
iso_creds = isolated_creds.IsolatedCreds('test class',
password='fake_password')
@@ -389,8 +383,8 @@
'list_roles',
return_value=({'status': 200},
[{'id': '123456', 'name': 'admin'}])))
- with patch.object(json_iden_client.IdentityClientJSON,
- 'assign_user_role'):
+ with mock.patch.object(json_iden_client.IdentityClientJSON,
+ 'assign_user_role'):
iso_creds.get_admin_creds()
router_interface_mock.called_once_with('1234', '1234')
network = iso_creds.get_admin_network()
@@ -403,7 +397,7 @@
self.assertEqual(router['id'], '1234')
self.assertEqual(router['name'], 'fake_admin_router')
- @patch('tempest.common.rest_client.RestClient')
+ @mock.patch('tempest.common.rest_client.RestClient')
def test_no_network_resources(self, MockRestClient):
net_dict = {
'network': False,
@@ -416,14 +410,14 @@
network_resources=net_dict)
self._mock_user_create('1234', 'fake_prim_user')
self._mock_tenant_create('1234', 'fake_prim_tenant')
- net = patch.object(iso_creds.network_admin_client,
- 'delete_network')
+ net = mock.patch.object(iso_creds.network_admin_client,
+ 'delete_network')
net_mock = net.start()
- subnet = patch.object(iso_creds.network_admin_client,
- 'delete_subnet')
+ subnet = mock.patch.object(iso_creds.network_admin_client,
+ 'delete_subnet')
subnet_mock = subnet.start()
- router = patch.object(iso_creds.network_admin_client,
- 'delete_router')
+ router = mock.patch.object(iso_creds.network_admin_client,
+ 'delete_router')
router_mock = router.start()
iso_creds.get_primary_creds()
@@ -437,7 +431,7 @@
self.assertIsNone(subnet)
self.assertIsNone(router)
- @patch('tempest.common.rest_client.RestClient')
+ @mock.patch('tempest.common.rest_client.RestClient')
def test_router_without_network(self, MockRestClient):
net_dict = {
'network': False,
@@ -453,7 +447,7 @@
self.assertRaises(exceptions.InvalidConfiguration,
iso_creds.get_primary_creds)
- @patch('tempest.common.rest_client.RestClient')
+ @mock.patch('tempest.common.rest_client.RestClient')
def test_subnet_without_network(self, MockRestClient):
net_dict = {
'network': False,
@@ -469,7 +463,7 @@
self.assertRaises(exceptions.InvalidConfiguration,
iso_creds.get_primary_creds)
- @patch('tempest.common.rest_client.RestClient')
+ @mock.patch('tempest.common.rest_client.RestClient')
def test_dhcp_without_subnet(self, MockRestClient):
net_dict = {
'network': False,
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()
diff --git a/tox.ini b/tox.ini
index 5e8d283..2110362 100644
--- a/tox.ini
+++ b/tox.ini
@@ -95,9 +95,10 @@
[hacking]
local-check-factory = tempest.hacking.checks.factory
+import_exceptions = tempest.services
[flake8]
# E125 is a won't fix until https://github.com/jcrocholl/pep8/issues/126 is resolved. For further detail see https://review.openstack.org/#/c/36788/
-ignore = E125,H302,H404
+ignore = E125,H404
show-source = True
exclude = .git,.venv,.tox,dist,doc,openstack,*egg