Merge "Validate server detail list attribute of Nova APIs"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 858fce9..8a7ad9c 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -23,47 +23,48 @@
# of default WARNING level). (boolean value)
#verbose=false
-# Log output to standard error (boolean value)
+# Log output to standard error. (boolean value)
#use_stderr=true
-# format string to use for log messages with context (string
+# Format string to use for log messages with context. (string
# value)
#logging_context_format_string=%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user_identity)s] %(instance)s%(message)s
-# format string to use for log messages without context
+# Format string to use for log messages without context.
# (string value)
#logging_default_format_string=%(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s
-# data to append to log format when level is DEBUG (string
+# Data to append to log format when level is DEBUG. (string
# value)
#logging_debug_format_suffix=%(funcName)s %(pathname)s:%(lineno)d
-# prefix each line of exception output with this format
+# Prefix each line of exception output with this format.
# (string value)
#logging_exception_prefix=%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s
-# list of logger=LEVEL pairs (list value)
-#default_log_levels=amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,iso8601=WARN
+# List of logger=LEVEL pairs. (list value)
+#default_log_levels=amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN
-# publish error events (boolean value)
+# Enables or disables publication of error events. (boolean
+# value)
#publish_errors=false
-# make deprecations fatal (boolean value)
+# Enables or disables fatal status of deprecations. (boolean
+# value)
#fatal_deprecations=false
-# If an instance is passed with the log message, format it
-# like this (string value)
+# The format for an instance that is passed with the log
+# message. (string value)
#instance_format="[instance: %(uuid)s] "
-# If an instance UUID is passed with the log message, format
-# it like this (string value)
+# The format for an instance UUID that is passed with the log
+# message. (string value)
#instance_uuid_format="[instance: %(uuid)s] "
-# The name of logging configuration file. It does not disable
-# existing loggers, but just appends specified logging
-# configuration to any other existing logging options. Please
-# see the Python logging module documentation for details on
-# logging configuration files. (string value)
+# The name of a logging configuration file. This file is
+# appended to any existing logging configuration files. For
+# details about logging configuration files, see the Python
+# logging module documentation. (string value)
# Deprecated group/name - [DEFAULT]/log_config
#log_config_append=<None>
@@ -75,7 +76,7 @@
#log_format=<None>
# Format string for %%(asctime)s in log records. Default:
-# %(default)s (string value)
+# %(default)s . (string value)
#log_date_format=%Y-%m-%d %H:%M:%S
# (Optional) Name of log file to output to. If no default is
@@ -84,14 +85,23 @@
#log_file=<None>
# (Optional) The base directory used for relative --log-file
-# paths (string value)
+# paths. (string value)
# Deprecated group/name - [DEFAULT]/logdir
#log_dir=<None>
-# Use syslog for logging. (boolean value)
+# Use syslog for logging. Existing syslog format is DEPRECATED
+# during I, and will change in J to honor RFC5424. (boolean
+# value)
#use_syslog=false
-# syslog facility to receive log lines (string value)
+# (Optional) Enables or disables syslog rfc5424 format for
+# logging. If enabled, prefixes the MSG part of the syslog
+# message with APP-NAME (RFC5424). The format without the APP-
+# NAME is deprecated in I, and will be removed in J. (boolean
+# value)
+#use_syslog_rfc_format=false
+
+# Syslog facility to receive log lines. (string value)
#syslog_log_facility=LOG_USER
diff --git a/tempest/api/baremetal/test_drivers.py b/tempest/api/baremetal/test_drivers.py
index 5e1e310..852b6ab 100644
--- a/tempest/api/baremetal/test_drivers.py
+++ b/tempest/api/baremetal/test_drivers.py
@@ -33,3 +33,9 @@
self.assertEqual('200', resp['status'])
self.assertIn(self.driver_name,
[d['name'] for d in drivers['drivers']])
+
+ @test.attr(type="smoke")
+ def test_show_driver(self):
+ resp, driver = self.client.show_driver(self.driver_name)
+ self.assertEqual('200', resp['status'])
+ self.assertEqual(self.driver_name, driver['name'])
diff --git a/tempest/api/compute/admin/test_availability_zone.py b/tempest/api/compute/admin/test_availability_zone.py
index 9555367..3a6de36 100644
--- a/tempest/api/compute/admin/test_availability_zone.py
+++ b/tempest/api/compute/admin/test_availability_zone.py
@@ -26,7 +26,7 @@
@classmethod
def setUpClass(cls):
super(AZAdminV3Test, cls).setUpClass()
- cls.client = cls.os_adm.availability_zone_client
+ cls.client = cls.availability_zone_admin_client
@test.attr(type='gate')
def test_get_availability_zone_list(self):
diff --git a/tempest/api/compute/admin/test_fixed_ips.py b/tempest/api/compute/admin/test_fixed_ips.py
index b0692b1..939f1a1 100644
--- a/tempest/api/compute/admin/test_fixed_ips.py
+++ b/tempest/api/compute/admin/test_fixed_ips.py
@@ -40,17 +40,20 @@
break
@test.attr(type='gate')
+ @test.services('network')
def test_list_fixed_ip_details(self):
resp, fixed_ip = self.client.get_fixed_ip_details(self.ip)
self.assertEqual(fixed_ip['address'], self.ip)
@test.attr(type='gate')
+ @test.services('network')
def test_set_reserve(self):
body = {"reserve": "None"}
resp, body = self.client.reserve_fixed_ip(self.ip, body)
self.assertEqual(resp.status, 202)
@test.attr(type='gate')
+ @test.services('network')
def test_set_unreserve(self):
body = {"unreserve": "None"}
resp, body = self.client.reserve_fixed_ip(self.ip, body)
diff --git a/tempest/api/compute/admin/test_fixed_ips_negative.py b/tempest/api/compute/admin/test_fixed_ips_negative.py
index 3fb3829..1caa246 100644
--- a/tempest/api/compute/admin/test_fixed_ips_negative.py
+++ b/tempest/api/compute/admin/test_fixed_ips_negative.py
@@ -41,11 +41,13 @@
break
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_list_fixed_ip_details_with_non_admin_user(self):
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.get_fixed_ip_details, self.ip)
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_set_reserve_with_non_admin_user(self):
body = {"reserve": "None"}
self.assertRaises(exceptions.Unauthorized,
@@ -53,6 +55,7 @@
self.ip, body)
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_set_unreserve_with_non_admin_user(self):
body = {"unreserve": "None"}
self.assertRaises(exceptions.Unauthorized,
@@ -60,6 +63,7 @@
self.ip, body)
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_set_reserve_with_invalid_ip(self):
# NOTE(maurosr): since this exercises the same code snippet, we do it
# only for reserve action
@@ -69,6 +73,7 @@
"my.invalid.ip", body)
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_fixed_ip_with_invalid_action(self):
body = {"invalid_action": "None"}
self.assertRaises(exceptions.BadRequest,
diff --git a/tempest/api/compute/admin/test_floating_ips_bulk.py b/tempest/api/compute/admin/test_floating_ips_bulk.py
index 208b032..16c2810 100644
--- a/tempest/api/compute/admin/test_floating_ips_bulk.py
+++ b/tempest/api/compute/admin/test_floating_ips_bulk.py
@@ -58,6 +58,7 @@
pass
@test.attr(type='gate')
+ @test.services('network')
def test_create_list_delete_floating_ips_bulk(self):
# Create, List and delete the Floating IPs Bulk
pool = 'test_pool'
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index 348666d..d27d78b 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -13,14 +13,26 @@
# License for the specific language governing permissions and limitations
# under the License.
+import six
+from testtools import matchers
+
from tempest.api.compute import base
+from tempest.common import tempest_fixtures as fixtures
from tempest.common.utils import data_utils
+from tempest.openstack.common import log as logging
from tempest import test
+LOG = logging.getLogger(__name__)
+
class QuotasAdminTestJSON(base.BaseV2ComputeAdminTest):
force_tenant_isolation = True
+ def setUp(self):
+ # NOTE(mriedem): Avoid conflicts with os-quota-class-sets tests.
+ self.useFixture(fixtures.LockFixture('compute_quotas'))
+ super(QuotasAdminTestJSON, self).setUp()
+
@classmethod
def setUpClass(cls):
super(QuotasAdminTestJSON, cls).setUpClass()
@@ -134,3 +146,55 @@
class QuotasAdminTestXML(QuotasAdminTestJSON):
_interface = 'xml'
+
+
+class QuotaClassesAdminTestJSON(base.BaseV2ComputeAdminTest):
+ """Tests the os-quota-class-sets API to update default quotas.
+ """
+
+ def setUp(self):
+ # All test cases in this class need to externally lock on doing
+ # anything with default quota values.
+ self.useFixture(fixtures.LockFixture('compute_quotas'))
+ super(QuotaClassesAdminTestJSON, self).setUp()
+
+ @classmethod
+ def setUpClass(cls):
+ super(QuotaClassesAdminTestJSON, cls).setUpClass()
+ cls.adm_client = cls.os_adm.quota_classes_client
+
+ def _restore_default_quotas(self, original_defaults):
+ LOG.debug("restoring quota class defaults")
+ resp, body = self.adm_client.update_quota_class_set(
+ 'default', **original_defaults)
+ self.assertEqual(200, resp.status)
+
+ # NOTE(sdague): this test is problematic as it changes
+ # global state, and possibly needs to be part of a set of
+ # tests that get run all by themselves at the end under a
+ # 'danger' flag.
+ def test_update_default_quotas(self):
+ LOG.debug("get the current 'default' quota class values")
+ resp, body = self.adm_client.get_quota_class_set('default')
+ self.assertEqual(200, resp.status)
+ self.assertIn('id', body)
+ self.assertEqual('default', body.pop('id'))
+ # restore the defaults when the test is done
+ self.addCleanup(self._restore_default_quotas, body.copy())
+ # increment all of the values for updating the default quota class
+ for quota, default in six.iteritems(body):
+ # NOTE(sdague): we need to increment a lot, otherwise
+ # there is a real chance that we go from -1 (unlimitted)
+ # to a very small number which causes issues.
+ body[quota] = default + 100
+ LOG.debug("update limits for the default quota class set")
+ resp, update_body = self.adm_client.update_quota_class_set('default',
+ **body)
+ self.assertEqual(200, resp.status)
+ LOG.debug("assert that the response has all of the changed values")
+ self.assertThat(update_body.items(),
+ matchers.ContainsAll(body.items()))
+
+
+class QuotaClassesAdminTestXML(QuotaClassesAdminTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py
index f728d68..004ce8f 100644
--- a/tempest/api/compute/admin/test_security_groups.py
+++ b/tempest/api/compute/admin/test_security_groups.py
@@ -43,6 +43,7 @@
"Skipped because neutron do not support all_tenants"
"search filter.")
@test.attr(type='smoke')
+ @test.services('network')
def test_list_security_groups_list_all_tenants_filter(self):
# Admin can list security groups of all tenants
# List of all security groups created
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 d69c43c..1031b24 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
@@ -51,7 +51,6 @@
# Get usage for tenant with invalid date
params = {'start': self.end,
'end': self.start}
- resp, tenants = self.identity_client.list_tenants()
self.assertRaises(exceptions.BadRequest,
self.adm_client.get_tenant_usage,
self.client.tenant_id, params)
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index a1aaa95..70a9604 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -67,6 +67,8 @@
cls.keypairs_client = cls.os.keypairs_client
cls.security_groups_client = cls.os.security_groups_client
cls.quotas_client = cls.os.quotas_client
+ # NOTE(mriedem): os-quota-class-sets is v2 API only
+ cls.quota_classes_client = cls.os.quota_classes_client
cls.limits_client = cls.os.limits_client
cls.volumes_extensions_client = cls.os.volumes_extensions_client
cls.volumes_client = cls.os.volumes_client
@@ -390,8 +392,11 @@
msg = ("Missing Compute Admin API credentials "
"in configuration.")
raise cls.skipException(msg)
+ if cls._api_version == 2:
+ cls.availability_zone_admin_client = (
+ cls.os_adm.availability_zone_client)
- if cls._api_version == 3:
+ else:
cls.servers_admin_client = cls.os_adm.servers_v3_client
cls.services_admin_client = cls.os_adm.services_v3_client
cls.availability_zone_admin_client = \
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions.py b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
index b3789f8..1eae66f 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -54,6 +54,7 @@
pass
@test.attr(type='gate')
+ @test.services('network')
def test_allocate_floating_ip(self):
# Positive test:Allocation of a new floating IP to a project
# should be successful
@@ -69,6 +70,7 @@
self.assertIn(floating_ip_details, body)
@test.attr(type='gate')
+ @test.services('network')
def test_delete_floating_ip(self):
# Positive test:Deletion of valid floating IP from project
# should be successful
@@ -85,6 +87,7 @@
self.client.wait_for_resource_deletion(floating_ip_body['id'])
@test.attr(type='gate')
+ @test.services('network')
def test_associate_disassociate_floating_ip(self):
# Positive test:Associate and disassociate the provided floating IP
# to a specific server should be successful
@@ -101,6 +104,7 @@
self.assertEqual(202, resp.status)
@test.attr(type='gate')
+ @test.services('network')
def test_associate_already_associated_floating_ip(self):
# positive test:Association of an already associated floating IP
# to specific server should change the association of the Floating IP
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
index 9fc43e2..042a19a 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
@@ -48,6 +48,7 @@
break
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_allocate_floating_ip_from_nonexistent_pool(self):
# Negative test:Allocation of a new floating IP from a nonexistent_pool
# to a project should fail
@@ -56,6 +57,7 @@
"non_exist_pool")
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_delete_nonexistent_floating_ip(self):
# Negative test:Deletion of a nonexistent floating IP
# from project should fail
@@ -65,6 +67,7 @@
self.non_exist_id)
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_associate_nonexistent_floating_ip(self):
# Negative test:Association of a non existent floating IP
# to specific server should fail
@@ -74,6 +77,7 @@
"0.0.0.0", self.server_id)
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_dissociate_nonexistent_floating_ip(self):
# Negative test:Dissociation of a non existent floating IP should fail
# Dissociating non existent floating IP
@@ -82,6 +86,7 @@
"0.0.0.0", self.server_id)
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_associate_ip_to_server_without_passing_floating_ip(self):
# Negative test:Association of empty floating IP to specific server
# should raise NotFound exception
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips.py b/tempest/api/compute/floating_ips/test_list_floating_ips.py
index 94dcf61..a6878d9 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips.py
@@ -37,6 +37,7 @@
super(FloatingIPDetailsTestJSON, cls).tearDownClass()
@test.attr(type='gate')
+ @test.services('network')
def test_list_floating_ips(self):
# Positive test:Should return the list of floating IPs
resp, body = self.client.list_floating_ips()
@@ -48,6 +49,7 @@
self.assertIn(self.floating_ip[i], floating_ips)
@test.attr(type='gate')
+ @test.services('network')
def test_get_floating_ip_details(self):
# Positive test:Should be able to GET the details of floatingIP
# Creating a floating IP for which details are to be checked
@@ -70,6 +72,7 @@
self.assertEqual(floating_ip_id, body['id'])
@test.attr(type='gate')
+ @test.services('network')
def test_list_floating_ip_pools(self):
# Positive test:Should return the list of floating IP Pools
resp, floating_ip_pools = self.client.list_floating_ip_pools()
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
index 8cb2f08..b11ef5b 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
@@ -32,6 +32,7 @@
cls.client = cls.floating_ips_client
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_get_nonexistent_floating_ip_details(self):
# Negative test:Should not be able to GET the details
# of non-existent floating IP
diff --git a/tempest/api/compute/security_groups/test_security_group_rules.py b/tempest/api/compute/security_groups/test_security_group_rules.py
index 35f6fc2..a1808dc 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules.py
@@ -29,6 +29,7 @@
cls.neutron_available = CONF.service_available.neutron
@test.attr(type='smoke')
+ @test.services('network')
def test_security_group_rules_create(self):
# Positive test: Creation of Security Group rule
# should be successful
@@ -48,6 +49,7 @@
self.assertEqual(200, resp.status)
@test.attr(type='smoke')
+ @test.services('network')
def test_security_group_rules_create_with_optional_arguments(self):
# Positive test: Creation of Security Group rule
# with optional arguments
@@ -78,6 +80,7 @@
self.assertEqual(200, resp.status)
@test.attr(type='smoke')
+ @test.services('network')
def test_security_group_rules_list(self):
# Positive test: Created Security Group rules should be
# in the list of all rules
@@ -114,6 +117,7 @@
self.assertTrue(any([i for i in rules if i['id'] == rule2_id]))
@test.attr(type='smoke')
+ @test.services('network')
def test_security_group_rules_delete_when_peer_group_deleted(self):
# Positive test:rule will delete when peer group deleting
# Creating a Security Group to add rules to it
diff --git a/tempest/api/compute/security_groups/test_security_group_rules_negative.py b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
index 0b53037..cfa839a 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules_negative.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
@@ -37,6 +37,7 @@
cls.client = cls.security_groups_client
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_create_security_group_rule_with_non_existent_id(self):
# Negative test: Creation of Security Group rule should FAIL
# with non existent Parent group id
@@ -50,6 +51,7 @@
parent_group_id, ip_protocol, from_port, to_port)
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_create_security_group_rule_with_invalid_id(self):
# Negative test: Creation of Security Group rule should FAIL
# with Parent group id which is not integer
@@ -63,6 +65,7 @@
parent_group_id, ip_protocol, from_port, to_port)
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_create_security_group_rule_duplicate(self):
# Negative test: Create Security Group rule duplicate should fail
# Creating a Security Group to add rule to it
@@ -86,6 +89,7 @@
parent_group_id, ip_protocol, from_port, to_port)
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_create_security_group_rule_with_invalid_ip_protocol(self):
# Negative test: Creation of Security Group rule should FAIL
# with invalid ip_protocol
@@ -102,6 +106,7 @@
parent_group_id, ip_protocol, from_port, to_port)
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_create_security_group_rule_with_invalid_from_port(self):
# Negative test: Creation of Security Group rule should FAIL
# with invalid from_port
@@ -117,6 +122,7 @@
parent_group_id, ip_protocol, from_port, to_port)
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_create_security_group_rule_with_invalid_to_port(self):
# Negative test: Creation of Security Group rule should FAIL
# with invalid to_port
@@ -132,6 +138,7 @@
parent_group_id, ip_protocol, from_port, to_port)
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_create_security_group_rule_with_invalid_port_range(self):
# Negative test: Creation of Security Group rule should FAIL
# with invalid port range.
@@ -147,6 +154,7 @@
secgroup_id, ip_protocol, from_port, to_port)
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_delete_security_group_rule_with_non_existent_id(self):
# Negative test: Deletion of Security Group rule should be FAIL
# with non existent id
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index a077943..860aebc 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -27,6 +27,7 @@
cls.client = cls.security_groups_client
@test.attr(type='smoke')
+ @test.services('network')
def test_security_groups_create_list_delete(self):
# Positive test:Should return the list of Security Groups
# Create 3 Security Groups
@@ -61,6 +62,7 @@
for m_group in deleted_sgs))
@test.attr(type='smoke')
+ @test.services('network')
def test_security_group_create_get_delete(self):
# Security Group should be created, fetched and deleted
# with char space between name along with
@@ -85,6 +87,7 @@
self.client.wait_for_resource_deletion(securitygroup['id'])
@test.attr(type='smoke')
+ @test.services('network')
def test_server_security_groups(self):
# Checks that security groups may be added and linked to a server
# and not deleted if the server is active.
@@ -131,6 +134,7 @@
self.assertEqual(202, resp.status)
@test.attr(type='smoke')
+ @test.services('network')
def test_update_security_groups(self):
# Update security group name and description
# Create a security group
diff --git a/tempest/api/compute/security_groups/test_security_groups_negative.py b/tempest/api/compute/security_groups/test_security_groups_negative.py
index aa2d32e..a9cca55 100644
--- a/tempest/api/compute/security_groups/test_security_groups_negative.py
+++ b/tempest/api/compute/security_groups/test_security_groups_negative.py
@@ -47,6 +47,7 @@
return non_exist_id
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_security_group_get_nonexistent_group(self):
# Negative test:Should not be able to GET the details
# of non-existent Security Group
@@ -57,6 +58,7 @@
@test.skip_because(bug="1161411",
condition=CONF.service_available.neutron)
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_security_group_create_with_invalid_group_name(self):
# Negative test: Security Group should not be created with group name
# as an empty string/with white spaces/chars more than 255
@@ -77,6 +79,7 @@
@test.skip_because(bug="1161411",
condition=CONF.service_available.neutron)
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_security_group_create_with_invalid_group_description(self):
# Negative test:Security Group should not be created with description
# as an empty string/with white spaces/chars more than 255
@@ -96,6 +99,7 @@
@testtools.skipIf(CONF.service_available.neutron,
"Neutron allows duplicate names for security groups")
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_security_group_create_with_duplicate_name(self):
# Negative test:Security Group with duplicate name should not
# be created
@@ -110,6 +114,7 @@
s_description)
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_delete_the_default_security_group(self):
# Negative test:Deletion of the "default" Security Group should Fail
default_security_group_id = None
@@ -124,6 +129,7 @@
default_security_group_id)
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_delete_nonexistent_security_group(self):
# Negative test:Deletion of a non-existent Security Group should fail
non_exist_id = self._generate_a_non_existent_security_group_id()
@@ -131,6 +137,7 @@
self.client.delete_security_group, non_exist_id)
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_delete_security_group_without_passing_id(self):
# Negative test:Deletion of a Security Group with out passing ID
# should Fail
@@ -140,6 +147,7 @@
@testtools.skipIf(CONF.service_available.neutron,
"Neutron not check the security_group_id")
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_update_security_group_with_invalid_sg_id(self):
# Update security_group with invalid sg_id should fail
s_name = data_utils.rand_name('sg-')
@@ -153,6 +161,7 @@
@testtools.skipIf(CONF.service_available.neutron,
"Neutron not check the security_group_name")
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_update_security_group_with_invalid_sg_name(self):
# Update security_group with invalid sg_name should fail
resp, securitygroup = self.create_security_group()
@@ -168,6 +177,7 @@
@testtools.skipIf(CONF.service_available.neutron,
"Neutron not check the security_group_description")
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_update_security_group_with_invalid_sg_des(self):
# Update security_group with invalid sg_des should fail
resp, securitygroup = self.create_security_group()
@@ -181,6 +191,7 @@
securitygroup_id, description=s_new_des)
@test.attr(type=['negative', 'smoke'])
+ @test.services('network')
def test_update_non_existent_security_group(self):
# Update a non-existent Security Group should Fail
non_exist_id = self._generate_a_non_existent_security_group_id()
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index 297b300..067d721 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -107,6 +107,7 @@
self.assertEqual(sorted(list1), sorted(list2))
@test.attr(type='smoke')
+ @test.services('network')
def test_create_list_show_delete_interfaces(self):
server, ifs = self._create_server_get_interfaces()
interface_count = len(ifs)
@@ -128,6 +129,7 @@
self.assertEqual(len(ifs) - 1, len(_ifs))
@test.attr(type='smoke')
+ @test.services('network')
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/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index 0c14dc2..846bf3e 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -34,6 +34,7 @@
@test.skip_because(bug="1210483",
condition=CONF.service_available.neutron)
@test.attr(type='smoke')
+ @test.services('network')
def test_list_server_addresses(self):
# All public and private addresses for
# a server should be returned
@@ -51,6 +52,7 @@
self.assertTrue(address['version'])
@test.attr(type='smoke')
+ @test.services('network')
def test_list_server_addresses_by_network(self):
# Providing a network type should filter
# the addresses return by that type
diff --git a/tempest/api/compute/servers/test_server_addresses_negative.py b/tempest/api/compute/servers/test_server_addresses_negative.py
index d37f7fa..e190161 100644
--- a/tempest/api/compute/servers/test_server_addresses_negative.py
+++ b/tempest/api/compute/servers/test_server_addresses_negative.py
@@ -29,12 +29,14 @@
resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_list_server_addresses_invalid_server_id(self):
# List addresses request should fail if server id not in system
self.assertRaises(exceptions.NotFound, self.client.list_addresses,
'999')
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_list_server_addresses_by_network_neg(self):
# List addresses by network should fail if network name not valid
self.assertRaises(exceptions.NotFound,
diff --git a/tempest/api/compute/servers/test_virtual_interfaces.py b/tempest/api/compute/servers/test_virtual_interfaces.py
index 6354996..421ba8b 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces.py
@@ -36,6 +36,7 @@
@test.skip_because(bug="1183436",
condition=CONF.service_available.neutron)
@test.attr(type='gate')
+ @test.services('network')
def test_list_virtual_interfaces(self):
# Positive test:Should be able to GET the virtual interfaces list
# for a given server_id
diff --git a/tempest/api/compute/servers/test_virtual_interfaces_negative.py b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
index 87289d8..bcb2686 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces_negative.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
@@ -30,6 +30,7 @@
cls.client = cls.servers_client
@test.attr(type=['negative', 'gate'])
+ @test.services('network')
def test_list_virtual_interfaces_invalid_server_id(self):
# Negative test: Should not be able to GET virtual interfaces
# for an invalid server_id
diff --git a/tempest/api/compute/test_quotas.py b/tempest/api/compute/test_quotas.py
index dc85e76..eeff3ce 100644
--- a/tempest/api/compute/test_quotas.py
+++ b/tempest/api/compute/test_quotas.py
@@ -14,11 +14,17 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import tempest_fixtures as fixtures
from tempest import test
class QuotasTestJSON(base.BaseV2ComputeTest):
+ def setUp(self):
+ # NOTE(mriedem): Avoid conflicts with os-quota-class-sets tests.
+ self.useFixture(fixtures.LockFixture('compute_quotas'))
+ super(QuotasTestJSON, self).setUp()
+
@classmethod
def setUpClass(cls):
super(QuotasTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/v3/test_quotas.py b/tempest/api/compute/v3/test_quotas.py
index 62a7556..ecf70cf 100644
--- a/tempest/api/compute/v3/test_quotas.py
+++ b/tempest/api/compute/v3/test_quotas.py
@@ -14,11 +14,17 @@
# under the License.
from tempest.api.compute import base
+from tempest.common import tempest_fixtures as fixtures
from tempest import test
class QuotasV3Test(base.BaseV3ComputeTest):
+ def setUp(self):
+ # NOTE(mriedem): Avoid conflicts with os-quota-class-sets tests.
+ self.useFixture(fixtures.LockFixture('compute_quotas'))
+ super(QuotasV3Test, self).setUp()
+
@classmethod
def setUpClass(cls):
super(QuotasV3Test, cls).setUpClass()
diff --git a/tempest/api/data_processing/test_cluster_templates.py b/tempest/api/data_processing/test_cluster_templates.py
index e5c6303..ad9ed2a 100644
--- a/tempest/api/data_processing/test_cluster_templates.py
+++ b/tempest/api/data_processing/test_cluster_templates.py
@@ -22,6 +22,7 @@
sahara/restapi/rest_api_v1.0.html#cluster-templates
"""
@classmethod
+ @test.safe_setup
def setUpClass(cls):
super(ClusterTemplateTest, cls).setUpClass()
# create node group template
@@ -39,6 +40,7 @@
}
}
resp_body = cls.create_node_group_template(**node_group_template)[1]
+ node_group_template_id = resp_body['id']
cls.full_cluster_template = {
'description': 'Test cluster template',
@@ -65,7 +67,7 @@
},
{
'name': 'worker-node',
- 'node_group_template_id': resp_body['id'],
+ 'node_group_template_id': node_group_template_id,
'count': 3
}
]
diff --git a/tempest/api/data_processing/test_data_sources.py b/tempest/api/data_processing/test_data_sources.py
index c72e828..345153b 100644
--- a/tempest/api/data_processing/test_data_sources.py
+++ b/tempest/api/data_processing/test_data_sources.py
@@ -14,11 +14,8 @@
from tempest.api.data_processing import base as dp_base
from tempest.common.utils import data_utils
-from tempest import config
from tempest import test
-CONF = config.CONF
-
class DataSourceTest(dp_base.BaseDataProcessingTest):
@classmethod
@@ -28,8 +25,8 @@
'url': 'swift://sahara-container.sahara/input-source',
'description': 'Test data source',
'credentials': {
- 'user': CONF.identity.username,
- 'password': CONF.identity.password
+ 'user': cls.os.credentials.username,
+ 'password': cls.os.credentials.password
},
'type': 'swift'
}
diff --git a/tempest/api/identity/admin/test_roles.py b/tempest/api/identity/admin/test_roles.py
index a29f27e..7a6d07f 100644
--- a/tempest/api/identity/admin/test_roles.py
+++ b/tempest/api/identity/admin/test_roles.py
@@ -29,7 +29,7 @@
super(RolesTestJSON, cls).setUpClass()
for _ in moves.xrange(5):
role_name = data_utils.rand_name(name='role-')
- resp, role = cls.client.create_role(role_name)
+ _, role = cls.client.create_role(role_name)
cls.data.roles.append(role)
def _get_role_params(self):
@@ -50,7 +50,7 @@
@test.attr(type='gate')
def test_list_roles(self):
# Return a list of all roles
- resp, body = self.client.list_roles()
+ _, body = self.client.list_roles()
found = [role for role in body if role in self.data.roles]
self.assertTrue(any(found))
self.assertEqual(len(found), len(self.data.roles))
@@ -59,18 +59,16 @@
def test_role_create_delete(self):
# Role should be created, verified, and deleted
role_name = data_utils.rand_name(name='role-test-')
- resp, body = self.client.create_role(role_name)
- self.assertEqual(200, resp.status)
+ _, body = self.client.create_role(role_name)
self.assertEqual(role_name, body['name'])
- resp, body = self.client.list_roles()
+ _, body = self.client.list_roles()
found = [role for role in body if role['name'] == role_name]
self.assertTrue(any(found))
- resp, body = self.client.delete_role(found[0]['id'])
- self.assertEqual(204, resp.status)
+ _, body = self.client.delete_role(found[0]['id'])
- resp, body = self.client.list_roles()
+ _, body = self.client.list_roles()
found = [role for role in body if role['name'] == role_name]
self.assertFalse(any(found))
@@ -80,9 +78,7 @@
self.data.setup_test_role()
role_id = self.data.role['id']
role_name = self.data.role['name']
- resp, body = self.client.get_role(role_id)
- self.assertIn('status', resp)
- self.assertTrue('200', resp['status'])
+ _, body = self.client.get_role(role_id)
self.assertEqual(role_id, body['id'])
self.assertEqual(role_name, body['name'])
@@ -91,25 +87,24 @@
# Assign a role to a user on a tenant
(user, tenant, role) = self._get_role_params()
self.client.assign_user_role(tenant['id'], user['id'], role['id'])
- resp, roles = self.client.list_user_roles(tenant['id'], user['id'])
+ _, roles = self.client.list_user_roles(tenant['id'], user['id'])
self.assert_role_in_role_list(role, roles)
@test.attr(type='gate')
def test_remove_user_role(self):
# Remove a role assigned to a user on a tenant
(user, tenant, role) = self._get_role_params()
- resp, user_role = self.client.assign_user_role(tenant['id'],
- user['id'], role['id'])
- resp, body = self.client.remove_user_role(tenant['id'], user['id'],
- user_role['id'])
- self.assertEqual(204, resp.status)
+ _, user_role = self.client.assign_user_role(tenant['id'],
+ user['id'], role['id'])
+ self.client.remove_user_role(tenant['id'], user['id'],
+ user_role['id'])
@test.attr(type='gate')
def test_list_user_roles(self):
# List roles assigned to a user on tenant
(user, tenant, role) = self._get_role_params()
self.client.assign_user_role(tenant['id'], user['id'], role['id'])
- resp, roles = self.client.list_user_roles(tenant['id'], user['id'])
+ _, roles = self.client.list_user_roles(tenant['id'], user['id'])
self.assert_role_in_role_list(role, roles)
diff --git a/tempest/api/identity/admin/test_roles_negative.py b/tempest/api/identity/admin/test_roles_negative.py
index 6f8f9b5..37a981e 100644
--- a/tempest/api/identity/admin/test_roles_negative.py
+++ b/tempest/api/identity/admin/test_roles_negative.py
@@ -72,9 +72,8 @@
def test_role_create_duplicate(self):
# Role names should be unique
role_name = data_utils.rand_name(name='role-dup-')
- resp, body = self.client.create_role(role_name)
+ _, body = self.client.create_role(role_name)
role1_id = body.get('id')
- self.assertEqual(200, resp.status)
self.addCleanup(self.client.delete_role, role1_id)
self.assertRaises(exceptions.Conflict, self.client.create_role,
role_name)
@@ -83,8 +82,7 @@
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-')
- resp, body = self.client.create_role(role_name)
- self.assertEqual(200, resp.status)
+ _, body = self.client.create_role(role_name)
self.data.roles.append(body)
role_id = body.get('id')
self.assertRaises(exceptions.Unauthorized,
@@ -94,8 +92,7 @@
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-')
- resp, body = self.client.create_role(role_name)
- self.assertEqual(200, resp.status)
+ _, body = self.client.create_role(role_name)
self.data.roles.append(body)
role_id = body.get('id')
token = self.client.auth_provider.get_token()
diff --git a/tempest/api/identity/admin/test_services.py b/tempest/api/identity/admin/test_services.py
index 5926488..a9782a9 100644
--- a/tempest/api/identity/admin/test_services.py
+++ b/tempest/api/identity/admin/test_services.py
@@ -26,8 +26,7 @@
def _del_service(self, service_id):
# Deleting the service created in this method
- resp, _ = self.client.delete_service(service_id)
- self.assertEqual(204, resp.status)
+ self.client.delete_service(service_id)
# Checking whether service is deleted successfully
self.assertRaises(exceptions.NotFound, self.client.get_service,
service_id)
@@ -39,11 +38,10 @@
name = data_utils.rand_name('service-')
type = data_utils.rand_name('type--')
description = data_utils.rand_name('description-')
- resp, service_data = self.client.create_service(
+ _, service_data = self.client.create_service(
name, type, description=description)
self.assertFalse(service_data['id'] is None)
self.addCleanup(self._del_service, service_data['id'])
- self.assertEqual(200, resp.status)
# Verifying response body of create service
self.assertIn('id', service_data)
self.assertIn('name', service_data)
@@ -53,8 +51,7 @@
self.assertIn('description', service_data)
self.assertEqual(description, service_data['description'])
# Get service
- resp, fetched_service = self.client.get_service(service_data['id'])
- self.assertEqual(200, resp.status)
+ _, fetched_service = self.client.get_service(service_data['id'])
# verifying the existence of service created
self.assertIn('id', fetched_service)
self.assertEqual(fetched_service['id'], service_data['id'])
@@ -71,9 +68,8 @@
# Create a service only with name and type
name = data_utils.rand_name('service-')
type = data_utils.rand_name('type--')
- resp, service = self.client.create_service(name, type)
+ _, service = self.client.create_service(name, type)
self.assertIn('id', service)
- self.assertTrue('200', resp['status'])
self.addCleanup(self._del_service, service['id'])
self.assertIn('name', service)
self.assertEqual(name, service['name'])
@@ -88,7 +84,7 @@
name = data_utils.rand_name('service-')
type = data_utils.rand_name('type--')
description = data_utils.rand_name('description-')
- resp, service = self.client.create_service(
+ _, service = self.client.create_service(
name, type, description=description)
services.append(service)
service_ids = map(lambda x: x['id'], services)
@@ -99,8 +95,7 @@
self.addCleanup(delete_services)
# List and Verify Services
- resp, body = self.client.list_services()
- self.assertEqual(200, resp.status)
+ _, body = self.client.list_services()
found = [serv for serv in body if serv['id'] in service_ids]
self.assertEqual(len(found), len(services), 'Services not found')
diff --git a/tempest/api/identity/admin/test_tenant_negative.py b/tempest/api/identity/admin/test_tenant_negative.py
index 622ad81..dcfacee 100644
--- a/tempest/api/identity/admin/test_tenant_negative.py
+++ b/tempest/api/identity/admin/test_tenant_negative.py
@@ -42,8 +42,7 @@
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-')
- resp, tenant = self.client.create_tenant(tenant_name)
- self.assertEqual(200, resp.status)
+ _, tenant = self.client.create_tenant(tenant_name)
self.data.tenants.append(tenant)
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.delete_tenant, tenant['id'])
@@ -52,8 +51,7 @@
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-')
- resp, tenant = self.client.create_tenant(tenant_name)
- self.assertEqual(200, resp.status)
+ _, tenant = self.client.create_tenant(tenant_name)
self.data.tenants.append(tenant)
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
@@ -71,8 +69,7 @@
def test_tenant_create_duplicate(self):
# Tenant names should be unique
tenant_name = data_utils.rand_name(name='tenant-')
- resp, body = self.client.create_tenant(tenant_name)
- self.assertEqual(200, resp.status)
+ _, body = self.client.create_tenant(tenant_name)
tenant = body
self.data.tenants.append(tenant)
tenant1_id = body.get('id')
@@ -122,8 +119,7 @@
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-')
- resp, tenant = self.client.create_tenant(tenant_name)
- self.assertEqual(200, resp.status)
+ _, tenant = self.client.create_tenant(tenant_name)
self.data.tenants.append(tenant)
self.assertRaises(exceptions.Unauthorized,
self.non_admin_client.update_tenant, tenant['id'])
@@ -132,8 +128,7 @@
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-')
- resp, tenant = self.client.create_tenant(tenant_name)
- self.assertEqual(200, resp.status)
+ _, tenant = self.client.create_tenant(tenant_name)
self.data.tenants.append(tenant)
token = self.client.auth_provider.get_token()
self.client.delete_token(token)
diff --git a/tempest/api/identity/admin/test_tenants.py b/tempest/api/identity/admin/test_tenants.py
index 93734d2..8d3b402 100644
--- a/tempest/api/identity/admin/test_tenants.py
+++ b/tempest/api/identity/admin/test_tenants.py
@@ -29,22 +29,19 @@
tenants = []
for _ in moves.xrange(3):
tenant_name = data_utils.rand_name(name='tenant-new')
- resp, tenant = self.client.create_tenant(tenant_name)
- self.assertEqual(200, resp.status)
+ _, tenant = self.client.create_tenant(tenant_name)
self.data.tenants.append(tenant)
tenants.append(tenant)
tenant_ids = map(lambda x: x['id'], tenants)
- resp, body = self.client.list_tenants()
- self.assertEqual(200, resp.status)
+ _, body = self.client.list_tenants()
found = [t for t in body if t['id'] in tenant_ids]
self.assertEqual(len(found), len(tenants), 'Tenants not created')
for tenant in tenants:
- resp, body = self.client.delete_tenant(tenant['id'])
- self.assertEqual(204, resp.status)
+ self.client.delete_tenant(tenant['id'])
self.data.tenants.remove(tenant)
- resp, body = self.client.list_tenants()
+ _, body = self.client.list_tenants()
found = [tenant for tenant in body if tenant['id'] in tenant_ids]
self.assertFalse(any(found), 'Tenants failed to delete')
@@ -53,16 +50,15 @@
# Create tenant with a description
tenant_name = data_utils.rand_name(name='tenant-')
tenant_desc = data_utils.rand_name(name='desc-')
- resp, body = self.client.create_tenant(tenant_name,
- description=tenant_desc)
+ _, body = self.client.create_tenant(tenant_name,
+ description=tenant_desc)
tenant = body
self.data.tenants.append(tenant)
tenant_id = body['id']
desc1 = body['description']
- self.assertEqual(200, resp.status)
self.assertEqual(desc1, tenant_desc, 'Description should have '
'been sent in response for create')
- resp, body = self.client.get_tenant(tenant_id)
+ _, body = self.client.get_tenant(tenant_id)
desc2 = body['description']
self.assertEqual(desc2, tenant_desc, 'Description does not appear'
'to be set')
@@ -73,14 +69,13 @@
def test_tenant_create_enabled(self):
# Create a tenant that is enabled
tenant_name = data_utils.rand_name(name='tenant-')
- resp, body = self.client.create_tenant(tenant_name, enabled=True)
+ _, body = self.client.create_tenant(tenant_name, enabled=True)
tenant = body
self.data.tenants.append(tenant)
tenant_id = body['id']
en1 = body['enabled']
- self.assertEqual(200, resp.status)
self.assertTrue(en1, 'Enable should be True in response')
- resp, body = self.client.get_tenant(tenant_id)
+ _, body = self.client.get_tenant(tenant_id)
en2 = body['enabled']
self.assertTrue(en2, 'Enable should be True in lookup')
self.client.delete_tenant(tenant_id)
@@ -90,15 +85,14 @@
def test_tenant_create_not_enabled(self):
# Create a tenant that is not enabled
tenant_name = data_utils.rand_name(name='tenant-')
- resp, body = self.client.create_tenant(tenant_name, enabled=False)
+ _, body = self.client.create_tenant(tenant_name, enabled=False)
tenant = body
self.data.tenants.append(tenant)
tenant_id = body['id']
en1 = body['enabled']
- self.assertEqual(200, resp.status)
self.assertEqual('false', str(en1).lower(),
'Enable should be False in response')
- resp, body = self.client.get_tenant(tenant_id)
+ _, body = self.client.get_tenant(tenant_id)
en2 = body['enabled']
self.assertEqual('false', str(en2).lower(),
'Enable should be False in lookup')
@@ -109,8 +103,7 @@
def test_tenant_update_name(self):
# Update name attribute of a tenant
t_name1 = data_utils.rand_name(name='tenant-')
- resp, body = self.client.create_tenant(t_name1)
- self.assertEqual(200, resp.status)
+ _, body = self.client.create_tenant(t_name1)
tenant = body
self.data.tenants.append(tenant)
@@ -118,12 +111,11 @@
resp1_name = body['name']
t_name2 = data_utils.rand_name(name='tenant2-')
- resp, body = self.client.update_tenant(t_id, name=t_name2)
+ _, body = self.client.update_tenant(t_id, name=t_name2)
resp2_name = body['name']
- self.assertEqual(200, resp.status)
self.assertNotEqual(resp1_name, resp2_name)
- resp, body = self.client.get_tenant(t_id)
+ _, body = self.client.get_tenant(t_id)
resp3_name = body['name']
self.assertNotEqual(resp1_name, resp3_name)
@@ -138,8 +130,7 @@
# Update description attribute of a tenant
t_name = data_utils.rand_name(name='tenant-')
t_desc = data_utils.rand_name(name='desc-')
- resp, body = self.client.create_tenant(t_name, description=t_desc)
- self.assertEqual(200, resp.status)
+ _, body = self.client.create_tenant(t_name, description=t_desc)
tenant = body
self.data.tenants.append(tenant)
@@ -147,12 +138,11 @@
resp1_desc = body['description']
t_desc2 = data_utils.rand_name(name='desc2-')
- resp, body = self.client.update_tenant(t_id, description=t_desc2)
+ _, body = self.client.update_tenant(t_id, description=t_desc2)
resp2_desc = body['description']
- self.assertEqual(200, resp.status)
self.assertNotEqual(resp1_desc, resp2_desc)
- resp, body = self.client.get_tenant(t_id)
+ _, body = self.client.get_tenant(t_id)
resp3_desc = body['description']
self.assertNotEqual(resp1_desc, resp3_desc)
@@ -167,8 +157,7 @@
# Update the enabled attribute of a tenant
t_name = data_utils.rand_name(name='tenant-')
t_en = False
- resp, body = self.client.create_tenant(t_name, enabled=t_en)
- self.assertEqual(200, resp.status)
+ _, body = self.client.create_tenant(t_name, enabled=t_en)
tenant = body
self.data.tenants.append(tenant)
@@ -176,12 +165,11 @@
resp1_en = body['enabled']
t_en2 = True
- resp, body = self.client.update_tenant(t_id, enabled=t_en2)
+ _, body = self.client.update_tenant(t_id, enabled=t_en2)
resp2_en = body['enabled']
- self.assertEqual(200, resp.status)
self.assertNotEqual(resp1_en, resp2_en)
- resp, body = self.client.get_tenant(t_id)
+ _, body = self.client.get_tenant(t_id)
resp3_en = body['enabled']
self.assertNotEqual(resp1_en, resp3_en)
diff --git a/tempest/api/identity/admin/test_tokens.py b/tempest/api/identity/admin/test_tokens.py
index 08e12f0..e1db008 100644
--- a/tempest/api/identity/admin/test_tokens.py
+++ b/tempest/api/identity/admin/test_tokens.py
@@ -28,13 +28,11 @@
user_password = data_utils.rand_name(name='pass-')
# first:create a tenant
tenant_name = data_utils.rand_name(name='tenant-')
- resp, tenant = self.client.create_tenant(tenant_name)
- self.assertEqual(200, resp.status)
+ _, tenant = self.client.create_tenant(tenant_name)
self.data.tenants.append(tenant)
# second:create a user
- resp, user = self.client.create_user(user_name, user_password,
- tenant['id'], '')
- self.assertEqual(200, resp.status)
+ _, user = self.client.create_user(user_name, user_password,
+ tenant['id'], '')
self.data.users.append(user)
# then get a token for the user
rsp, body = self.token_client.auth(user_name,
@@ -45,16 +43,14 @@
tenant['name'])
# Perform GET Token
token_id = body['token']['id']
- resp, token_details = self.client.get_token(token_id)
- self.assertEqual(resp['status'], '200')
+ _, token_details = self.client.get_token(token_id)
self.assertEqual(token_id, token_details['token']['id'])
self.assertEqual(user['id'], token_details['user']['id'])
self.assertEqual(user_name, token_details['user']['name'])
self.assertEqual(tenant['name'],
token_details['token']['tenant']['name'])
# then delete the token
- resp, body = self.client.delete_token(token_id)
- self.assertEqual(resp['status'], '204')
+ self.client.delete_token(token_id)
@test.attr(type='gate')
def test_rescope_token(self):
@@ -67,56 +63,51 @@
user_password = data_utils.rand_name(name='pass-')
tenant_id = None # No default tenant so will get unscoped token.
email = ''
- resp, user = self.client.create_user(user_name, user_password,
- tenant_id, email)
- self.assertEqual(200, resp.status)
+ _, user = self.client.create_user(user_name, user_password,
+ tenant_id, email)
self.data.users.append(user)
# Create a couple tenants.
tenant1_name = data_utils.rand_name(name='tenant-')
- resp, tenant1 = self.client.create_tenant(tenant1_name)
- self.assertEqual(200, resp.status)
+ _, tenant1 = self.client.create_tenant(tenant1_name)
self.data.tenants.append(tenant1)
tenant2_name = data_utils.rand_name(name='tenant-')
- resp, tenant2 = self.client.create_tenant(tenant2_name)
- self.assertEqual(200, resp.status)
+ _, tenant2 = self.client.create_tenant(tenant2_name)
self.data.tenants.append(tenant2)
# Create a role
role_name = data_utils.rand_name(name='role-')
- resp, role = self.client.create_role(role_name)
- self.assertEqual(200, resp.status)
+ _, role = self.client.create_role(role_name)
self.data.roles.append(role)
# Grant the user the role on the tenants.
- resp, _ = self.client.assign_user_role(tenant1['id'], user['id'],
- role['id'])
- self.assertEqual(200, resp.status)
+ self.client.assign_user_role(tenant1['id'], user['id'],
+ role['id'])
- resp, _ = self.client.assign_user_role(tenant2['id'], user['id'],
- role['id'])
- self.assertEqual(200, resp.status)
+ self.client.assign_user_role(tenant2['id'], user['id'],
+ role['id'])
# Get an unscoped token.
- rsp, body = self.token_client.auth(user_name, user_password)
+ resp, body = self.token_client.auth(user_name, user_password)
self.assertEqual(200, resp.status)
token_id = body['token']['id']
# Use the unscoped token to get a token scoped to tenant1
- rsp, body = self.token_client.auth_token(token_id, tenant=tenant1_name)
+ resp, body = self.token_client.auth_token(token_id,
+ tenant=tenant1_name)
self.assertEqual(200, resp.status)
scoped_token_id = body['token']['id']
# Revoke the scoped token
- resp, body = self.client.delete_token(scoped_token_id)
- self.assertEqual(204, resp.status)
+ self.client.delete_token(scoped_token_id)
# Use the unscoped token to get a token scoped to tenant2
- rsp, body = self.token_client.auth_token(token_id, tenant=tenant2_name)
- self.assertEqual(204, resp.status)
+ resp, body = self.token_client.auth_token(token_id,
+ tenant=tenant2_name)
+ self.assertEqual(200, resp.status)
class TokensTestXML(TokensTestJSON):
diff --git a/tempest/api/identity/admin/test_users.py b/tempest/api/identity/admin/test_users.py
index e2c1066..5838da3 100644
--- a/tempest/api/identity/admin/test_users.py
+++ b/tempest/api/identity/admin/test_users.py
@@ -34,11 +34,10 @@
def test_create_user(self):
# Create a user
self.data.setup_test_tenant()
- resp, user = self.client.create_user(self.alt_user, self.alt_password,
- self.data.tenant['id'],
- self.alt_email)
+ _, user = self.client.create_user(self.alt_user, self.alt_password,
+ self.data.tenant['id'],
+ self.alt_email)
self.data.users.append(user)
- self.assertEqual('200', resp['status'])
self.assertEqual(self.alt_user, user['name'])
@test.attr(type='smoke')
@@ -46,11 +45,10 @@
# Create a user with enabled : False
self.data.setup_test_tenant()
name = data_utils.rand_name('test_user_')
- resp, user = self.client.create_user(name, self.alt_password,
- self.data.tenant['id'],
- self.alt_email, enabled=False)
+ _, user = self.client.create_user(name, self.alt_password,
+ self.data.tenant['id'],
+ self.alt_email, enabled=False)
self.data.users.append(user)
- self.assertEqual('200', resp['status'])
self.assertEqual(name, user['name'])
self.assertEqual('false', str(user['enabled']).lower())
self.assertEqual(self.alt_email, user['email'])
@@ -60,24 +58,22 @@
# Test case to check if updating of user attributes is successful.
test_user = data_utils.rand_name('test_user_')
self.data.setup_test_tenant()
- resp, user = self.client.create_user(test_user, self.alt_password,
- self.data.tenant['id'],
- self.alt_email)
+ _, user = self.client.create_user(test_user, self.alt_password,
+ self.data.tenant['id'],
+ self.alt_email)
# Delete the User at the end of this method
self.addCleanup(self.client.delete_user, user['id'])
# Updating user details with new values
u_name2 = data_utils.rand_name('user2-')
u_email2 = u_name2 + '@testmail.tm'
- resp, update_user = self.client.update_user(user['id'], name=u_name2,
- email=u_email2,
- enabled=False)
- # Assert response body of update user.
- self.assertEqual(200, resp.status)
+ _, update_user = self.client.update_user(user['id'], name=u_name2,
+ email=u_email2,
+ enabled=False)
self.assertEqual(u_name2, update_user['name'])
self.assertEqual(u_email2, update_user['email'])
self.assertEqual('false', str(update_user['enabled']).lower())
# GET by id after updating
- resp, updated_user = self.client.get_user(user['id'])
+ _, updated_user = self.client.get_user(user['id'])
# Assert response body of GET after updating
self.assertEqual(u_name2, updated_user['name'])
self.assertEqual(u_email2, updated_user['email'])
@@ -88,12 +84,10 @@
# Delete a user
test_user = data_utils.rand_name('test_user_')
self.data.setup_test_tenant()
- resp, user = self.client.create_user(test_user, self.alt_password,
- self.data.tenant['id'],
- self.alt_email)
- self.assertEqual('200', resp['status'])
- resp, body = self.client.delete_user(user['id'])
- self.assertEqual('204', resp['status'])
+ _, user = self.client.create_user(test_user, self.alt_password,
+ self.data.tenant['id'],
+ self.alt_email)
+ self.client.delete_user(user['id'])
@test.attr(type='smoke')
def test_user_authentication(self):
@@ -129,7 +123,7 @@
def test_get_users(self):
# Get a list of users and find the test user
self.data.setup_test_user()
- resp, users = self.client.get_users()
+ _, users = self.client.get_users()
self.assertThat([u['name'] for u in users],
matchers.Contains(self.data.test_user),
"Could not find %s" % self.data.test_user)
@@ -141,23 +135,20 @@
user_ids = list()
fetched_user_ids = list()
alt_tenant_user1 = data_utils.rand_name('tenant_user1_')
- resp, user1 = self.client.create_user(alt_tenant_user1, 'password1',
- self.data.tenant['id'],
- 'user1@123')
- self.assertEqual('200', resp['status'])
+ _, user1 = self.client.create_user(alt_tenant_user1, 'password1',
+ self.data.tenant['id'],
+ 'user1@123')
user_ids.append(user1['id'])
self.data.users.append(user1)
alt_tenant_user2 = data_utils.rand_name('tenant_user2_')
- resp, user2 = self.client.create_user(alt_tenant_user2, 'password2',
- self.data.tenant['id'],
- 'user2@123')
- self.assertEqual('200', resp['status'])
+ _, user2 = self.client.create_user(alt_tenant_user2, 'password2',
+ self.data.tenant['id'],
+ 'user2@123')
user_ids.append(user2['id'])
self.data.users.append(user2)
# List of users for the respective tenant ID
- resp, body = self.client.list_users_for_tenant(self.data.tenant['id'])
- self.assertIn(resp['status'], ('200', '203'))
+ _, body = self.client.list_users_for_tenant(self.data.tenant['id'])
for i in body:
fetched_user_ids.append(i['id'])
# verifying the user Id in the list
@@ -179,24 +170,20 @@
user_ids = list()
fetched_user_ids = list()
user_ids.append(user['id'])
- resp, role = self.client.assign_user_role(tenant['id'], user['id'],
- role['id'])
- self.assertEqual('200', resp['status'])
+ _, role = self.client.assign_user_role(tenant['id'], user['id'],
+ role['id'])
alt_user2 = data_utils.rand_name('second_user_')
- resp, second_user = self.client.create_user(alt_user2, 'password1',
- self.data.tenant['id'],
- 'user2@123')
- self.assertEqual('200', resp['status'])
+ _, second_user = self.client.create_user(alt_user2, 'password1',
+ self.data.tenant['id'],
+ 'user2@123')
user_ids.append(second_user['id'])
self.data.users.append(second_user)
- resp, role = self.client.assign_user_role(tenant['id'],
- second_user['id'],
- role['id'])
- self.assertEqual('200', resp['status'])
+ _, role = self.client.assign_user_role(tenant['id'],
+ second_user['id'],
+ role['id'])
# List of users with roles for the respective tenant ID
- resp, body = self.client.list_users_for_tenant(self.data.tenant['id'])
- self.assertEqual('200', resp['status'])
+ _, body = self.client.list_users_for_tenant(self.data.tenant['id'])
for i in body:
fetched_user_ids.append(i['id'])
# verifying the user Id in the list
@@ -212,10 +199,8 @@
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(
+ _, 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
diff --git a/tempest/api/identity/admin/v3/test_credentials.py b/tempest/api/identity/admin/v3/test_credentials.py
index 6bb0ebe..d40e0f3 100644
--- a/tempest/api/identity/admin/v3/test_credentials.py
+++ b/tempest/api/identity/admin/v3/test_credentials.py
@@ -33,28 +33,20 @@
u_email = '%s@testmail.tm' % u_name
u_password = data_utils.rand_name('pass-')
for i in range(2):
- resp, cls.project = cls.client.create_project(
+ _, cls.project = cls.client.create_project(
data_utils.rand_name('project-'),
description=data_utils.rand_name('project-desc-'))
- assert resp['status'] == '201', (
- "Expected 201, but got: %s" % resp['status'])
cls.projects.append(cls.project['id'])
- resp, cls.user_body = cls.client.create_user(
+ _, cls.user_body = cls.client.create_user(
u_name, description=u_desc, password=u_password,
email=u_email, project_id=cls.projects[0])
- assert resp['status'] == '201', (
- "Expected 201, but got: %s" % resp['status'])
@classmethod
def tearDownClass(cls):
- resp, _ = cls.client.delete_user(cls.user_body['id'])
- assert resp['status'] == '204', (
- "Expected 204, but got: %s" % resp['status'])
+ cls.client.delete_user(cls.user_body['id'])
for p in cls.projects:
- resp, _ = cls.client.delete_project(p)
- assert resp['status'] == '204', (
- "Expected 204, but got: %s" % resp['status'])
+ cls.client.delete_project(p)
super(CredentialsTestJSON, cls).tearDownClass()
def _delete_credential(self, cred_id):
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index a1e6cde..5b73df1 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -25,9 +25,8 @@
def _delete_domain(self, domain_id):
# It is necessary to disable the domain before deleting,
# or else it would result in unauthorized error
- _, body = self.client.update_domain(domain_id, enabled=False)
- resp, _ = self.client.delete_domain(domain_id)
- self.assertEqual(204, resp.status)
+ self.client.update_domain(domain_id, enabled=False)
+ self.client.delete_domain(domain_id)
@test.attr(type='smoke')
def test_list_domains(self):
@@ -42,8 +41,7 @@
self.addCleanup(self._delete_domain, domain['id'])
domain_ids.append(domain['id'])
# List and Verify Domains
- resp, body = self.client.list_domains()
- self.assertEqual(resp['status'], '200')
+ _, body = self.client.list_domains()
for d in body:
fetched_ids.append(d['id'])
missing_doms = [d for d in domain_ids if d not in fetched_ids]
@@ -53,9 +51,8 @@
def test_create_update_delete_domain(self):
d_name = data_utils.rand_name('domain-')
d_desc = data_utils.rand_name('domain-desc-')
- resp_1, domain = self.client.create_domain(
+ _, domain = self.client.create_domain(
d_name, description=d_desc)
- self.assertEqual(resp_1['status'], '201')
self.addCleanup(self._delete_domain, domain['id'])
self.assertIn('id', domain)
self.assertIn('description', domain)
@@ -72,9 +69,8 @@
new_desc = data_utils.rand_name('new-desc-')
new_name = data_utils.rand_name('new-name-')
- resp_2, updated_domain = self.client.update_domain(
+ _, updated_domain = self.client.update_domain(
domain['id'], name=new_name, description=new_desc)
- self.assertEqual(resp_2['status'], '200')
self.assertIn('id', updated_domain)
self.assertIn('description', updated_domain)
self.assertIn('name', updated_domain)
@@ -85,8 +81,7 @@
self.assertEqual(new_desc, updated_domain['description'])
self.assertEqual('true', str(updated_domain['enabled']).lower())
- resp_3, fetched_domain = self.client.get_domain(domain['id'])
- self.assertEqual(resp_3['status'], '200')
+ _, fetched_domain = self.client.get_domain(domain['id'])
self.assertEqual(new_name, fetched_domain['name'])
self.assertEqual(new_desc, fetched_domain['description'])
self.assertEqual('true', str(fetched_domain['enabled']).lower())
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 881f69e..1548f89 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -31,7 +31,7 @@
s_name = data_utils.rand_name('service-')
s_type = data_utils.rand_name('type--')
s_description = data_utils.rand_name('description-')
- resp, cls.service_data =\
+ _, cls.service_data =\
cls.service_client.create_service(s_name, s_type,
description=s_description)
cls.service_id = cls.service_data['id']
@@ -108,7 +108,7 @@
s_name = data_utils.rand_name('service-')
s_type = data_utils.rand_name('type--')
s_description = data_utils.rand_name('description-')
- resp, service2 =\
+ _, service2 =\
self.service_client.create_service(s_name, s_type,
description=s_description)
self.service_ids.append(service2['id'])
diff --git a/tempest/api/identity/admin/v3/test_endpoints_negative.py b/tempest/api/identity/admin/v3/test_endpoints_negative.py
index 5b46f89..1d63cce 100644
--- a/tempest/api/identity/admin/v3/test_endpoints_negative.py
+++ b/tempest/api/identity/admin/v3/test_endpoints_negative.py
@@ -33,7 +33,7 @@
s_name = data_utils.rand_name('service-')
s_type = data_utils.rand_name('type--')
s_description = data_utils.rand_name('description-')
- resp, cls.service_data = (
+ _, cls.service_data = (
cls.service_client.create_service(s_name, s_type,
description=s_description))
cls.service_id = cls.service_data['id']
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index 056f713..4d2cc46 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -29,24 +29,21 @@
def test_group_create_update_get(self):
name = data_utils.rand_name('Group')
description = data_utils.rand_name('Description')
- resp, group = self.client.create_group(name,
- description=description)
+ _, group = self.client.create_group(name,
+ description=description)
self.addCleanup(self.client.delete_group, group['id'])
- self.assertEqual(resp['status'], '201')
self.assertEqual(group['name'], name)
self.assertEqual(group['description'], description)
new_name = data_utils.rand_name('UpdateGroup')
new_desc = data_utils.rand_name('UpdateDescription')
- resp, updated_group = self.client.update_group(group['id'],
- name=new_name,
- description=new_desc)
- self.assertEqual(resp['status'], '200')
+ _, updated_group = self.client.update_group(group['id'],
+ name=new_name,
+ description=new_desc)
self.assertEqual(updated_group['name'], new_name)
self.assertEqual(updated_group['description'], new_desc)
- resp, new_group = self.client.get_group(group['id'])
- self.assertEqual(resp['status'], '200')
+ _, new_group = self.client.get_group(group['id'])
self.assertEqual(group['id'], new_group['id'])
self.assertEqual(new_name, new_group['name'])
self.assertEqual(new_desc, new_group['description'])
@@ -54,33 +51,31 @@
@test.attr(type='smoke')
def test_group_users_add_list_delete(self):
name = data_utils.rand_name('Group')
- resp, group = self.client.create_group(name)
+ _, group = self.client.create_group(name)
self.addCleanup(self.client.delete_group, group['id'])
# add user into group
users = []
for i in range(3):
name = data_utils.rand_name('User')
- resp, user = self.client.create_user(name)
+ _, user = self.client.create_user(name)
users.append(user)
self.addCleanup(self.client.delete_user, user['id'])
self.client.add_group_user(group['id'], user['id'])
# list users in group
- resp, group_users = self.client.list_group_users(group['id'])
- self.assertEqual(resp['status'], '200')
+ _, group_users = self.client.list_group_users(group['id'])
self.assertEqual(sorted(users), sorted(group_users))
# delete user in group
for user in users:
- resp, body = self.client.delete_group_user(group['id'],
- user['id'])
- self.assertEqual(resp['status'], '204')
- resp, group_users = self.client.list_group_users(group['id'])
+ self.client.delete_group_user(group['id'],
+ user['id'])
+ _, group_users = self.client.list_group_users(group['id'])
self.assertEqual(len(group_users), 0)
@test.attr(type='smoke')
def test_list_user_groups(self):
# create a user
- resp, user = self.client.create_user(
+ _, user = self.client.create_user(
data_utils.rand_name('User-'),
password=data_utils.rand_name('Pass-'))
self.addCleanup(self.client.delete_user, user['id'])
@@ -88,13 +83,12 @@
groups = []
for i in range(2):
name = data_utils.rand_name('Group-')
- resp, group = self.client.create_group(name)
+ _, group = self.client.create_group(name)
groups.append(group)
self.addCleanup(self.client.delete_group, group['id'])
self.client.add_group_user(group['id'], user['id'])
# list groups which user belongs to
- resp, user_groups = self.client.list_user_groups(user['id'])
- self.assertEqual('200', resp['status'])
+ _, user_groups = self.client.list_user_groups(user['id'])
self.assertEqual(sorted(groups), sorted(user_groups))
self.assertEqual(2, len(user_groups))
diff --git a/tempest/api/identity/admin/v3/test_projects.py b/tempest/api/identity/admin/v3/test_projects.py
index 79717b1..77acd57 100644
--- a/tempest/api/identity/admin/v3/test_projects.py
+++ b/tempest/api/identity/admin/v3/test_projects.py
@@ -25,8 +25,7 @@
_interface = 'json'
def _delete_project(self, project_id):
- resp, _ = self.client.delete_project(project_id)
- self.assertEqual(resp['status'], '204')
+ self.client.delete_project(project_id)
self.assertRaises(
exceptions.NotFound, self.client.get_project, project_id)
@@ -34,14 +33,13 @@
def test_project_list_delete(self):
# Create several projects and delete them
for _ in moves.xrange(3):
- resp, project = self.client.create_project(
+ _, project = self.client.create_project(
data_utils.rand_name('project-new'))
self.addCleanup(self._delete_project, project['id'])
- resp, list_projects = self.client.list_projects()
- self.assertEqual(resp['status'], '200')
+ _, list_projects = self.client.list_projects()
- resp, get_project = self.client.get_project(project['id'])
+ _, get_project = self.client.get_project(project['id'])
self.assertIn(get_project, list_projects)
@test.attr(type='gate')
@@ -49,16 +47,14 @@
# Create project with a description
project_name = data_utils.rand_name('project-')
project_desc = data_utils.rand_name('desc-')
- resp, project = self.client.create_project(
+ _, project = self.client.create_project(
project_name, description=project_desc)
self.data.projects.append(project)
- st1 = resp['status']
project_id = project['id']
desc1 = project['description']
- self.assertEqual(st1, '201')
self.assertEqual(desc1, project_desc, 'Description should have '
'been sent in response for create')
- resp, body = self.client.get_project(project_id)
+ _, body = self.client.get_project(project_id)
desc2 = body['description']
self.assertEqual(desc2, project_desc, 'Description does not appear'
'to be set')
@@ -67,15 +63,13 @@
def test_project_create_enabled(self):
# Create a project that is enabled
project_name = data_utils.rand_name('project-')
- resp, project = self.client.create_project(
+ _, project = self.client.create_project(
project_name, enabled=True)
self.data.projects.append(project)
project_id = project['id']
- st1 = resp['status']
en1 = project['enabled']
- self.assertEqual(st1, '201')
self.assertTrue(en1, 'Enable should be True in response')
- resp, body = self.client.get_project(project_id)
+ _, body = self.client.get_project(project_id)
en2 = body['enabled']
self.assertTrue(en2, 'Enable should be True in lookup')
@@ -83,15 +77,13 @@
def test_project_create_not_enabled(self):
# Create a project that is not enabled
project_name = data_utils.rand_name('project-')
- resp, project = self.client.create_project(
+ _, project = self.client.create_project(
project_name, enabled=False)
self.data.projects.append(project)
- st1 = resp['status']
en1 = project['enabled']
- self.assertEqual(st1, '201')
self.assertEqual('false', str(en1).lower(),
'Enable should be False in response')
- resp, body = self.client.get_project(project['id'])
+ _, body = self.client.get_project(project['id'])
en2 = body['enabled']
self.assertEqual('false', str(en2).lower(),
'Enable should be False in lookup')
@@ -100,19 +92,17 @@
def test_project_update_name(self):
# Update name attribute of a project
p_name1 = data_utils.rand_name('project-')
- resp, project = self.client.create_project(p_name1)
+ _, project = self.client.create_project(p_name1)
self.data.projects.append(project)
resp1_name = project['name']
p_name2 = data_utils.rand_name('project2-')
- resp, body = self.client.update_project(project['id'], name=p_name2)
- st2 = resp['status']
+ _, body = self.client.update_project(project['id'], name=p_name2)
resp2_name = body['name']
- self.assertEqual(st2, '200')
self.assertNotEqual(resp1_name, resp2_name)
- resp, body = self.client.get_project(project['id'])
+ _, body = self.client.get_project(project['id'])
resp3_name = body['name']
self.assertNotEqual(resp1_name, resp3_name)
@@ -124,20 +114,18 @@
# Update description attribute of a project
p_name = data_utils.rand_name('project-')
p_desc = data_utils.rand_name('desc-')
- resp, project = self.client.create_project(
+ _, project = self.client.create_project(
p_name, description=p_desc)
self.data.projects.append(project)
resp1_desc = project['description']
p_desc2 = data_utils.rand_name('desc2-')
- resp, body = self.client.update_project(
+ _, body = self.client.update_project(
project['id'], description=p_desc2)
- st2 = resp['status']
resp2_desc = body['description']
- self.assertEqual(st2, '200')
self.assertNotEqual(resp1_desc, resp2_desc)
- resp, body = self.client.get_project(project['id'])
+ _, body = self.client.get_project(project['id'])
resp3_desc = body['description']
self.assertNotEqual(resp1_desc, resp3_desc)
@@ -149,20 +137,18 @@
# Update the enabled attribute of a project
p_name = data_utils.rand_name('project-')
p_en = False
- resp, project = self.client.create_project(p_name, enabled=p_en)
+ _, project = self.client.create_project(p_name, enabled=p_en)
self.data.projects.append(project)
resp1_en = project['enabled']
p_en2 = True
- resp, body = self.client.update_project(
+ _, body = self.client.update_project(
project['id'], enabled=p_en2)
- st2 = resp['status']
resp2_en = body['enabled']
- self.assertEqual(st2, '200')
self.assertNotEqual(resp1_en, resp2_en)
- resp, body = self.client.get_project(project['id'])
+ _, body = self.client.get_project(project['id'])
resp3_en = body['enabled']
self.assertNotEqual(resp1_en, resp3_en)
@@ -174,7 +160,7 @@
# Associate a user to a project
# Create a Project
p_name = data_utils.rand_name('project-')
- resp, project = self.client.create_project(p_name)
+ _, project = self.client.create_project(p_name)
self.data.projects.append(project)
# Create a User
@@ -182,15 +168,14 @@
u_desc = u_name + 'description'
u_email = u_name + '@testmail.tm'
u_password = data_utils.rand_name('pass-')
- resp, user = self.client.create_user(
+ _, user = self.client.create_user(
u_name, description=u_desc, password=u_password,
email=u_email, project_id=project['id'])
- self.assertEqual(resp['status'], '201')
# Delete the User at the end of this method
self.addCleanup(self.client.delete_user, user['id'])
# Get User To validate the user details
- resp, new_user_get = self.client.get_user(user['id'])
+ _, new_user_get = self.client.get_user(user['id'])
# Assert response body of GET
self.assertEqual(u_name, new_user_get['name'])
self.assertEqual(u_desc, new_user_get['description'])
diff --git a/tempest/api/identity/admin/v3/test_projects_negative.py b/tempest/api/identity/admin/v3/test_projects_negative.py
index 6b60d04..9e8f613 100644
--- a/tempest/api/identity/admin/v3/test_projects_negative.py
+++ b/tempest/api/identity/admin/v3/test_projects_negative.py
@@ -32,7 +32,7 @@
def test_project_create_duplicate(self):
# Project names should be unique
project_name = data_utils.rand_name('project-dup-')
- resp, project = self.client.create_project(project_name)
+ _, project = self.client.create_project(project_name)
self.data.projects.append(project)
self.assertRaises(
@@ -63,7 +63,7 @@
def test_project_delete_by_unauthorized_user(self):
# Non-admin user should not be able to delete a project
project_name = data_utils.rand_name('project-')
- resp, project = self.client.create_project(project_name)
+ _, project = self.client.create_project(project_name)
self.data.projects.append(project)
self.assertRaises(
exceptions.Unauthorized, self.non_admin_client.delete_project,
diff --git a/tempest/api/identity/admin/v3/test_regions.py b/tempest/api/identity/admin/v3/test_regions.py
index 03974e4..c8b034f 100644
--- a/tempest/api/identity/admin/v3/test_regions.py
+++ b/tempest/api/identity/admin/v3/test_regions.py
@@ -1,4 +1,4 @@
-# Copyright 2014 OpenStack Foundation
+# Copyright 2014 Hewlett-Packard Development Company, L.P
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index 90dccca..2e732fe 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -25,131 +25,117 @@
@test.safe_setup
def setUpClass(cls):
super(RolesV3TestJSON, cls).setUpClass()
+ for _ in range(3):
+ role_name = data_utils.rand_name(name='role-')
+ _, role = cls.client.create_role(role_name)
+ cls.data.v3_roles.append(role)
cls.fetched_role_ids = list()
u_name = data_utils.rand_name('user-')
u_desc = '%s description' % u_name
u_email = '%s@testmail.tm' % u_name
cls.u_password = data_utils.rand_name('pass-')
- resp = [None] * 5
- resp[0], cls.domain = cls.client.create_domain(
+ _, cls.domain = cls.client.create_domain(
data_utils.rand_name('domain-'),
description=data_utils.rand_name('domain-desc-'))
- resp[1], cls.project = cls.client.create_project(
+ _, cls.project = cls.client.create_project(
data_utils.rand_name('project-'),
description=data_utils.rand_name('project-desc-'),
domain_id=cls.domain['id'])
- resp[2], cls.group_body = cls.client.create_group(
+ _, cls.group_body = cls.client.create_group(
data_utils.rand_name('Group-'), project_id=cls.project['id'],
domain_id=cls.domain['id'])
- resp[3], cls.user_body = cls.client.create_user(
+ _, cls.user_body = cls.client.create_user(
u_name, description=u_desc, password=cls.u_password,
email=u_email, project_id=cls.project['id'],
domain_id=cls.domain['id'])
- resp[4], cls.role = cls.client.create_role(
+ _, cls.role = cls.client.create_role(
data_utils.rand_name('Role-'))
- for r in resp:
- assert r['status'] == '201', (
- "Expected 201, but got: %s" % r['status'])
@classmethod
def tearDownClass(cls):
- resp = [None] * 5
- resp[0], _ = cls.client.delete_role(cls.role['id'])
- resp[1], _ = cls.client.delete_group(cls.group_body['id'])
- resp[2], _ = cls.client.delete_user(cls.user_body['id'])
- resp[3], _ = cls.client.delete_project(cls.project['id'])
+ cls.client.delete_role(cls.role['id'])
+ cls.client.delete_group(cls.group_body['id'])
+ cls.client.delete_user(cls.user_body['id'])
+ cls.client.delete_project(cls.project['id'])
# NOTE(harika-vakadi): It is necessary to disable the domain
# before deleting,or else it would result in unauthorized error
cls.client.update_domain(cls.domain['id'], enabled=False)
- resp[4], _ = cls.client.delete_domain(cls.domain['id'])
- for r in resp:
- assert r['status'] == '204', (
- "Expected 204, but got: %s" % r['status'])
+ cls.client.delete_domain(cls.domain['id'])
super(RolesV3TestJSON, cls).tearDownClass()
- def _list_assertions(self, resp, body, fetched_role_ids, role_id):
- self.assertEqual(resp['status'], '200')
+ def _list_assertions(self, body, fetched_role_ids, role_id):
self.assertEqual(len(body), 1)
self.assertIn(role_id, fetched_role_ids)
@test.attr(type='smoke')
def test_role_create_update_get_list(self):
r_name = data_utils.rand_name('Role-')
- resp, role = self.client.create_role(r_name)
+ _, role = self.client.create_role(r_name)
self.addCleanup(self.client.delete_role, role['id'])
- self.assertEqual(resp['status'], '201')
self.assertIn('name', role)
self.assertEqual(role['name'], r_name)
new_name = data_utils.rand_name('NewRole-')
- resp, updated_role = self.client.update_role(new_name, role['id'])
- self.assertEqual(resp['status'], '200')
+ _, updated_role = self.client.update_role(new_name, role['id'])
self.assertIn('name', updated_role)
self.assertIn('id', updated_role)
self.assertIn('links', updated_role)
self.assertNotEqual(r_name, updated_role['name'])
- resp, new_role = self.client.get_role(role['id'])
- self.assertEqual(resp['status'], '200')
+ _, new_role = self.client.get_role(role['id'])
self.assertEqual(new_name, new_role['name'])
self.assertEqual(updated_role['id'], new_role['id'])
- resp, roles = self.client.list_roles()
- self.assertEqual(resp['status'], '200')
+ _, roles = self.client.list_roles()
self.assertIn(role['id'], [r['id'] for r in roles])
@test.attr(type='smoke')
def test_grant_list_revoke_role_to_user_on_project(self):
- resp, _ = self.client.assign_user_role_on_project(
+ self.client.assign_user_role_on_project(
self.project['id'], self.user_body['id'], self.role['id'])
- self.assertEqual(resp['status'], '204')
- resp, roles = self.client.list_user_roles_on_project(
+ _, roles = self.client.list_user_roles_on_project(
self.project['id'], self.user_body['id'])
for i in roles:
self.fetched_role_ids.append(i['id'])
- self._list_assertions(resp, roles, self.fetched_role_ids,
+ self._list_assertions(roles, self.fetched_role_ids,
self.role['id'])
- resp, _ = self.client.revoke_role_from_user_on_project(
+ self.client.revoke_role_from_user_on_project(
self.project['id'], self.user_body['id'], self.role['id'])
- self.assertEqual(resp['status'], '204')
@test.attr(type='smoke')
def test_grant_list_revoke_role_to_user_on_domain(self):
- resp, _ = self.client.assign_user_role_on_domain(
+ self.client.assign_user_role_on_domain(
self.domain['id'], self.user_body['id'], self.role['id'])
- self.assertEqual(resp['status'], '204')
- resp, roles = self.client.list_user_roles_on_domain(
+ _, roles = self.client.list_user_roles_on_domain(
self.domain['id'], self.user_body['id'])
for i in roles:
self.fetched_role_ids.append(i['id'])
- self._list_assertions(resp, roles, self.fetched_role_ids,
+ self._list_assertions(roles, self.fetched_role_ids,
self.role['id'])
- resp, _ = self.client.revoke_role_from_user_on_domain(
+ self.client.revoke_role_from_user_on_domain(
self.domain['id'], self.user_body['id'], self.role['id'])
- self.assertEqual(resp['status'], '204')
@test.attr(type='smoke')
def test_grant_list_revoke_role_to_group_on_project(self):
# Grant role to group on project
- resp, _ = self.client.assign_group_role_on_project(
+ self.client.assign_group_role_on_project(
self.project['id'], self.group_body['id'], self.role['id'])
- self.assertEqual(resp['status'], '204')
# List group roles on project
- resp, roles = self.client.list_group_roles_on_project(
+ _, roles = self.client.list_group_roles_on_project(
self.project['id'], self.group_body['id'])
for i in roles:
self.fetched_role_ids.append(i['id'])
- self._list_assertions(resp, roles, self.fetched_role_ids,
+ self._list_assertions(roles, self.fetched_role_ids,
self.role['id'])
# Add user to group, and insure user has role on project
self.client.add_group_user(self.group_body['id'], self.user_body['id'])
@@ -163,28 +149,32 @@
self.assertEqual(len(roles), 1)
self.assertEqual(roles[0]['id'], self.role['id'])
# Revoke role to group on project
- resp, _ = self.client.revoke_role_from_group_on_project(
+ self.client.revoke_role_from_group_on_project(
self.project['id'], self.group_body['id'], self.role['id'])
- self.assertEqual(resp['status'], '204')
@test.attr(type='smoke')
def test_grant_list_revoke_role_to_group_on_domain(self):
- resp, _ = self.client.assign_group_role_on_domain(
+ self.client.assign_group_role_on_domain(
self.domain['id'], self.group_body['id'], self.role['id'])
- self.assertEqual(resp['status'], '204')
- resp, roles = self.client.list_group_roles_on_domain(
+ _, roles = self.client.list_group_roles_on_domain(
self.domain['id'], self.group_body['id'])
for i in roles:
self.fetched_role_ids.append(i['id'])
- self._list_assertions(resp, roles, self.fetched_role_ids,
+ self._list_assertions(roles, self.fetched_role_ids,
self.role['id'])
- resp, _ = self.client.revoke_role_from_group_on_domain(
+ self.client.revoke_role_from_group_on_domain(
self.domain['id'], self.group_body['id'], self.role['id'])
- self.assertEqual(resp['status'], '204')
+
+ @test.attr(type='gate')
+ def test_list_roles(self):
+ # Return a list of all roles
+ _, body = self.client.list_roles()
+ found = [role for role in body if role in self.data.v3_roles]
+ self.assertEqual(len(found), len(self.data.v3_roles))
class RolesV3TestXML(RolesV3TestJSON):
diff --git a/tempest/api/identity/admin/v3/test_services.py b/tempest/api/identity/admin/v3/test_services.py
index 36e5327..f6078da 100644
--- a/tempest/api/identity/admin/v3/test_services.py
+++ b/tempest/api/identity/admin/v3/test_services.py
@@ -28,9 +28,8 @@
name = data_utils.rand_name('service-')
serv_type = data_utils.rand_name('type--')
desc = data_utils.rand_name('description-')
- resp, body = self.service_client.create_service(name, serv_type,
- description=desc)
- self.assertEqual('201', resp['status'])
+ _, body = self.service_client.create_service(name, serv_type,
+ description=desc)
# Deleting the service created in this method
self.addCleanup(self.service_client.delete_service, body['id'])
@@ -38,14 +37,13 @@
resp1_desc = body['description']
s_desc2 = data_utils.rand_name('desc2-')
- resp, body = self.service_client.update_service(
+ _, body = self.service_client.update_service(
s_id, description=s_desc2)
resp2_desc = body['description']
- self.assertEqual('200', resp['status'])
self.assertNotEqual(resp1_desc, resp2_desc)
# Get service
- resp, body = self.service_client.get_service(s_id)
+ _, body = self.service_client.get_service(s_id)
resp3_desc = body['description']
self.assertNotEqual(resp1_desc, resp3_desc)
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index fe3eb03..e61b738 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -30,23 +30,21 @@
u_desc = '%s-description' % u_name
u_email = '%s@testmail.tm' % u_name
u_password = data_utils.rand_name('pass-')
- resp, user = self.client.create_user(
+ _, user = self.client.create_user(
u_name, description=u_desc, password=u_password,
email=u_email)
- self.assertEqual(201, resp.status)
self.addCleanup(self.client.delete_user, user['id'])
# Perform Authentication
resp, body = self.token.auth(user['id'], u_password)
self.assertEqual(201, resp.status)
subject_token = resp['x-subject-token']
# Perform GET Token
- resp, token_details = self.client.get_token(subject_token)
- self.assertEqual(200, resp.status)
+ _, token_details = self.client.get_token(subject_token)
self.assertEqual(resp['x-subject-token'], subject_token)
self.assertEqual(token_details['user']['id'], user['id'])
self.assertEqual(token_details['user']['name'], u_name)
# Perform Delete Token
- resp, _ = self.client.delete_token(subject_token)
+ self.client.delete_token(subject_token)
self.assertRaises(exceptions.NotFound, self.client.get_token,
subject_token)
@@ -63,35 +61,29 @@
# Create a user.
user_name = data_utils.rand_name(name='user-')
user_password = data_utils.rand_name(name='pass-')
- resp, user = self.client.create_user(user_name, password=user_password)
- self.assertEqual(201, resp.status)
+ _, user = self.client.create_user(user_name, password=user_password)
self.addCleanup(self.client.delete_user, user['id'])
# Create a couple projects
project1_name = data_utils.rand_name(name='project-')
- resp, project1 = self.client.create_project(project1_name)
- self.assertEqual(201, resp.status)
+ _, project1 = self.client.create_project(project1_name)
self.addCleanup(self.client.delete_project, project1['id'])
project2_name = data_utils.rand_name(name='project-')
- resp, project2 = self.client.create_project(project2_name)
- self.assertEqual(201, resp.status)
+ _, project2 = self.client.create_project(project2_name)
self.addCleanup(self.client.delete_project, project2['id'])
# Create a role
role_name = data_utils.rand_name(name='role-')
- resp, role = self.client.create_role(role_name)
- self.assertEqual(201, resp.status)
+ _, role = self.client.create_role(role_name)
self.addCleanup(self.client.delete_role, role['id'])
# Grant the user the role on both projects.
- resp, _ = self.client.assign_user_role(project1['id'], user['id'],
- role['id'])
- self.assertEqual(204, resp.status)
+ self.client.assign_user_role(project1['id'], user['id'],
+ role['id'])
- resp, _ = self.client.assign_user_role(project2['id'], user['id'],
- role['id'])
- self.assertEqual(204, resp.status)
+ self.client.assign_user_role(project2['id'], user['id'],
+ role['id'])
# Get an unscoped token.
resp, token_auth = self.token.auth(user=user['id'],
@@ -145,8 +137,7 @@
self.assertEqual(role['name'], token_auth['token']['roles'][0]['name'])
# Revoke the unscoped token.
- resp, _ = self.client.delete_token(token1_id)
- self.assertEqual(204, resp.status)
+ self.client.delete_token(token1_id)
# Now get another scoped token using the unscoped token.
resp, token_auth = self.token.auth(token=token_id,
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 8e3a7d1..fed5171 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -54,25 +54,22 @@
u_desc = self.trustor_username + 'description'
u_email = self.trustor_username + '@testmail.xx'
self.trustor_password = data_utils.rand_name('pass-')
- resp, user = self.client.create_user(
+ _, user = self.client.create_user(
self.trustor_username,
description=u_desc,
password=self.trustor_password,
email=u_email,
project_id=self.trustor_project_id)
- self.assertEqual(resp['status'], '201')
self.trustor_user_id = user['id']
# And two roles, one we'll delegate and one we won't
self.delegated_role = data_utils.rand_name('DelegatedRole-')
self.not_delegated_role = data_utils.rand_name('NotDelegatedRole-')
- resp, role = self.client.create_role(self.delegated_role)
- self.assertEqual(resp['status'], '201')
+ _, role = self.client.create_role(self.delegated_role)
self.delegated_role_id = role['id']
- resp, role = self.client.create_role(self.not_delegated_role)
- self.assertEqual(resp['status'], '201')
+ _, role = self.client.create_role(self.not_delegated_role)
self.not_delegated_role_id = role['id']
# Assign roles to trustor
@@ -108,14 +105,13 @@
def create_trust(self, impersonate=True, expires=None):
- resp, trust_create = self.trustor_client.create_trust(
+ _, trust_create = self.trustor_client.create_trust(
trustor_user_id=self.trustor_user_id,
trustee_user_id=self.trustee_user_id,
project_id=self.trustor_project_id,
role_names=[self.delegated_role],
impersonation=impersonate,
expires_at=expires)
- self.assertEqual('201', resp['status'])
self.trust_id = trust_create['id']
return trust_create
@@ -141,8 +137,7 @@
self.assertEqual(1, len(trust['roles']))
def get_trust(self):
- resp, trust_get = self.trustor_client.get_trust(self.trust_id)
- self.assertEqual('200', resp['status'])
+ _, trust_get = self.trustor_client.get_trust(self.trust_id)
return trust_get
def validate_role(self, role):
@@ -155,22 +150,26 @@
self.assertNotIn('v3/roles/%s' % self.not_delegated_role_id,
role['links']['self'])
+ @test.skip_because(bug='1334368')
def check_trust_roles(self):
# Check we find the delegated role
- resp, roles_get = self.trustor_client.get_trust_roles(
+ _, roles_get = self.trustor_client.get_trust_roles(
self.trust_id)
- self.assertEqual('200', resp['status'])
self.assertEqual(1, len(roles_get))
self.validate_role(roles_get[0])
- resp, role_get = self.trustor_client.get_trust_role(
+ _, role_get = self.trustor_client.get_trust_role(
self.trust_id, self.delegated_role_id)
- self.assertEqual('200', resp['status'])
self.validate_role(role_get)
- resp, role_get = self.trustor_client.check_trust_role(
+ _, role_get = self.trustor_client.check_trust_role(
self.trust_id, self.delegated_role_id)
- self.assertEqual('204', resp['status'])
+ # This tempest two-step change conflicted with the change
+ # moving response checking to the client. This test should be
+ # re-enabled by removing the following assert and changing
+ # the response code in tempest/services/identity/v3/json/
+ # identity_client.py in the check_trust_role_method.
+ # self.assertEqual('200', resp['status'])
# And that we don't find not_delegated_role
self.assertRaises(exceptions.NotFound,
@@ -184,8 +183,7 @@
self.not_delegated_role_id)
def delete_trust(self):
- resp, trust_delete = self.trustor_client.delete_trust(self.trust_id)
- self.assertEqual('204', resp['status'])
+ self.trustor_client.delete_trust(self.trust_id)
self.assertRaises(exceptions.NotFound,
self.trustor_client.get_trust,
self.trust_id)
@@ -253,17 +251,15 @@
@test.attr(type='smoke')
def test_get_trusts_query(self):
self.create_trust()
- resp, trusts_get = self.trustor_client.get_trusts(
+ _, trusts_get = self.trustor_client.get_trusts(
trustor_user_id=self.trustor_user_id)
- self.assertEqual('200', resp['status'])
self.assertEqual(1, len(trusts_get))
self.validate_trust(trusts_get[0], summary=True)
@test.attr(type='smoke')
def test_get_trusts_all(self):
self.create_trust()
- resp, trusts_get = self.client.get_trusts()
- self.assertEqual('200', resp['status'])
+ _, trusts_get = self.client.get_trusts()
trusts = [t for t in trusts_get
if t['id'] == self.trust_id]
self.assertEqual(1, len(trusts))
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index 7316c7f..558575e 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -29,13 +29,13 @@
u_desc = u_name + 'description'
u_email = u_name + '@testmail.tm'
u_password = data_utils.rand_name('pass-')
- resp, user = self.client.create_user(
+ _, user = self.client.create_user(
u_name, description=u_desc, password=u_password,
email=u_email, enabled=False)
# Delete the User at the end of this method
self.addCleanup(self.client.delete_user, user['id'])
# Creating second project for updation
- resp, project = self.client.create_project(
+ _, project = self.client.create_project(
data_utils.rand_name('project-'),
description=data_utils.rand_name('project-desc-'))
# Delete the Project at the end of this method
@@ -44,12 +44,10 @@
u_name2 = data_utils.rand_name('user2-')
u_email2 = u_name2 + '@testmail.tm'
u_description2 = u_name2 + ' description'
- resp, update_user = self.client.update_user(
+ _, update_user = self.client.update_user(
user['id'], name=u_name2, description=u_description2,
project_id=project['id'],
email=u_email2, enabled=False)
- # Assert response body of update user.
- self.assertEqual(200, resp.status)
self.assertEqual(u_name2, update_user['name'])
self.assertEqual(u_description2, update_user['description'])
self.assertEqual(project['id'],
@@ -57,7 +55,7 @@
self.assertEqual(u_email2, update_user['email'])
self.assertEqual('false', str(update_user['enabled']).lower())
# GET by id after updation
- resp, new_user_get = self.client.get_user(user['id'])
+ _, new_user_get = self.client.get_user(user['id'])
# Assert response body of GET after updation
self.assertEqual(u_name2, new_user_get['name'])
self.assertEqual(u_description2, new_user_get['description'])
@@ -107,8 +105,7 @@
user['id'],
role['id'])
assigned_project_ids.append(project['id'])
- resp, body = self.client.list_user_projects(user['id'])
- self.assertEqual(200, resp.status)
+ _, body = self.client.list_user_projects(user['id'])
for i in body:
fetched_project_ids.append(i['id'])
# verifying the project ids in list
@@ -124,7 +121,7 @@
def test_get_user(self):
# Get a user detail
self.data.setup_test_v3_user()
- resp, user = self.client.get_user(self.data.v3_user['id'])
+ _, user = self.client.get_user(self.data.v3_user['id'])
self.assertEqual(self.data.v3_user['id'], user['id'])
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 697057f..0991576 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -136,17 +136,17 @@
self.test_user = data_utils.rand_name('test_user_')
self.test_password = data_utils.rand_name('pass_')
self.test_email = self.test_user + '@testmail.tm'
- resp, self.user = self.client.create_user(self.test_user,
- self.test_password,
- self.tenant['id'],
- self.test_email)
+ _, self.user = self.client.create_user(self.test_user,
+ self.test_password,
+ self.tenant['id'],
+ self.test_email)
self.users.append(self.user)
def setup_test_tenant(self):
"""Set up a test tenant."""
self.test_tenant = data_utils.rand_name('test_tenant_')
self.test_description = data_utils.rand_name('desc_')
- resp, self.tenant = self.client.create_tenant(
+ _, self.tenant = self.client.create_tenant(
name=self.test_tenant,
description=self.test_description)
self.tenants.append(self.tenant)
@@ -154,7 +154,7 @@
def setup_test_role(self):
"""Set up a test role."""
self.test_role = data_utils.rand_name('role')
- resp, self.role = self.client.create_role(self.test_role)
+ _, self.role = self.client.create_role(self.test_role)
self.roles.append(self.role)
def setup_test_v3_user(self):
@@ -163,7 +163,7 @@
self.test_user = data_utils.rand_name('test_user_')
self.test_password = data_utils.rand_name('pass_')
self.test_email = self.test_user + '@testmail.tm'
- resp, self.v3_user = self.client.create_user(
+ _, self.v3_user = self.client.create_user(
self.test_user,
password=self.test_password,
project_id=self.project['id'],
@@ -174,7 +174,7 @@
"""Set up a test project."""
self.test_project = data_utils.rand_name('test_project_')
self.test_description = data_utils.rand_name('desc_')
- resp, self.project = self.client.create_project(
+ _, self.project = self.client.create_project(
name=self.test_project,
description=self.test_description)
self.projects.append(self.project)
@@ -182,7 +182,7 @@
def setup_test_v3_role(self):
"""Set up a test v3 role."""
self.test_role = data_utils.rand_name('role')
- resp, self.v3_role = self.client.create_role(self.test_role)
+ _, self.v3_role = self.client.create_role(self.test_role)
self.v3_roles.append(self.v3_role)
def teardown_all(self):
diff --git a/tempest/api/identity/test_extension.py b/tempest/api/identity/test_extension.py
index 67f20f4..a06ee53 100644
--- a/tempest/api/identity/test_extension.py
+++ b/tempest/api/identity/test_extension.py
@@ -23,8 +23,7 @@
@test.attr(type='gate')
def test_list_extensions(self):
# List all the extensions
- resp, body = self.non_admin_client.list_extensions()
- self.assertEqual(200, resp.status)
+ _, body = self.non_admin_client.list_extensions()
self.assertNotEmpty(body)
keys = ['name', 'updated', 'alias', 'links',
'namespace', 'description']
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 78cb221..ac3a072 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -277,13 +277,6 @@
block defined by tenant-network_cidr
"""
- @classmethod
- @test.safe_setup
- def setUpClass(cls):
- super(BulkNetworkOpsTestJSON, cls).setUpClass()
- cls.network1 = cls.create_network()
- cls.network2 = cls.create_network()
-
def _delete_networks(self, created_networks):
for n in created_networks:
resp, body = self.client.delete_network(n['id'])
@@ -332,11 +325,11 @@
@test.attr(type='smoke')
def test_bulk_create_delete_subnet(self):
+ networks = [self.create_network(), self.create_network()]
# Creates 2 subnets in one request
cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
mask_bits = CONF.network.tenant_network_mask_bits
cidrs = [subnet_cidr for subnet_cidr in cidr.subnet(mask_bits)]
- networks = [self.network1['id'], self.network2['id']]
names = [data_utils.rand_name('subnet-') for i in range(len(networks))]
subnets_list = []
# TODO(raies): "for IPv6, version list [4, 6] will be used.
@@ -344,7 +337,7 @@
ip_version = [4, 4]
for i in range(len(names)):
p1 = {
- 'network_id': networks[i],
+ 'network_id': networks[i]['id'],
'cidr': str(cidrs[(i)]),
'name': names[i],
'ip_version': ip_version[i]
@@ -364,14 +357,14 @@
@test.attr(type='smoke')
def test_bulk_create_delete_port(self):
+ networks = [self.create_network(), self.create_network()]
# Creates 2 ports in one request
- networks = [self.network1['id'], self.network2['id']]
names = [data_utils.rand_name('port-') for i in range(len(networks))]
port_list = []
state = [True, False]
for i in range(len(names)):
p1 = {
- 'network_id': networks[i],
+ 'network_id': networks[i]['id'],
'name': names[i],
'admin_state_up': state[i],
}
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 2a9b407..c5be1f3 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -142,10 +142,6 @@
_api_version = 1
-class BaseVolumeV2Test(BaseVolumeTest):
- _api_version = 2
-
-
class BaseVolumeV1AdminTest(BaseVolumeV1Test):
"""Base test case class for all Volume Admin API tests."""
@classmethod
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index e2f7a38..b8a2faa 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -23,10 +23,8 @@
LOG = logging.getLogger(__name__)
-VOLUME_FIELDS = ('id', 'display_name')
-
-class VolumesListTest(base.BaseVolumeV1Test):
+class VolumesV2ListTestJSON(base.BaseVolumeTest):
"""
This test creates a number of 1G volumes. To run successfully,
@@ -36,7 +34,7 @@
VOLUME_BACKING_FILE_SIZE is at least 4G in your localrc
"""
- _interface = 'json'
+ VOLUME_FIELDS = ('id', 'name')
def assertVolumesIn(self, fetched_list, expected_list, fields=None):
if fields:
@@ -48,7 +46,7 @@
return
def str_vol(vol):
- return "%s:%s" % (vol['id'], vol['display_name'])
+ return "%s:%s" % (vol['id'], vol[self.name])
raw_msg = "Could not find volumes %s in expected list %s; fetched %s"
self.fail(raw_msg % ([str_vol(v) for v in missing_vols],
@@ -58,8 +56,9 @@
@classmethod
@test.safe_setup
def setUpClass(cls):
- super(VolumesListTest, cls).setUpClass()
+ super(VolumesV2ListTestJSON, cls).setUpClass()
cls.client = cls.volumes_client
+ cls.name = cls.VOLUME_FIELDS[1]
# Create 3 test volumes
cls.volume_list = []
@@ -77,7 +76,7 @@
for volid in cls.volume_id_list:
resp, _ = cls.client.delete_volume(volid)
cls.client.wait_for_resource_deletion(volid)
- super(VolumesListTest, cls).tearDownClass()
+ super(VolumesV2ListTestJSON, cls).tearDownClass()
def _list_by_param_value_and_assert(self, params, with_detail=False):
"""
@@ -92,16 +91,22 @@
self.assertEqual(200, resp.status)
# Validating params of fetched volumes
- for volume in fetched_vol_list:
- for key in params:
- msg = "Failed to list volumes %s by %s" % \
- ('details' if with_detail else '', key)
- if key == 'metadata':
- self.assertThat(volume[key].items(),
- matchers.ContainsAll(params[key].items()),
- msg)
- else:
- self.assertEqual(params[key], volume[key], msg)
+ # In v2, only list detail view includes items in params.
+ # In v1, list view and list detail view are same. So the
+ # following check should be run when 'with_detail' is True
+ # or v1 tests.
+ if with_detail or self._api_version == 1:
+ for volume in fetched_vol_list:
+ for key in params:
+ msg = "Failed to list volumes %s by %s" % \
+ ('details' if with_detail else '', key)
+ if key == 'metadata':
+ self.assertThat(
+ volume[key].items(),
+ matchers.ContainsAll(params[key].items()),
+ msg)
+ else:
+ self.assertEqual(params[key], volume[key], msg)
@test.attr(type='smoke')
def test_volume_list(self):
@@ -110,7 +115,7 @@
resp, fetched_list = self.client.list_volumes()
self.assertEqual(200, resp.status)
self.assertVolumesIn(fetched_list, self.volume_list,
- fields=VOLUME_FIELDS)
+ fields=self.VOLUME_FIELDS)
@test.attr(type='gate')
def test_volume_list_with_details(self):
@@ -123,32 +128,31 @@
@test.attr(type='gate')
def test_volume_list_by_name(self):
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
- params = {'display_name': volume['display_name']}
+ params = {self.name: volume[self.name]}
resp, fetched_vol = self.client.list_volumes(params)
self.assertEqual(200, resp.status)
self.assertEqual(1, len(fetched_vol), str(fetched_vol))
- self.assertEqual(fetched_vol[0]['display_name'],
- volume['display_name'])
+ self.assertEqual(fetched_vol[0][self.name],
+ volume[self.name])
@test.attr(type='gate')
def test_volume_list_details_by_name(self):
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
- params = {'display_name': volume['display_name']}
+ params = {self.name: volume[self.name]}
resp, fetched_vol = self.client.list_volumes_with_detail(params)
self.assertEqual(200, resp.status)
self.assertEqual(1, len(fetched_vol), str(fetched_vol))
- self.assertEqual(fetched_vol[0]['display_name'],
- volume['display_name'])
+ self.assertEqual(fetched_vol[0][self.name],
+ volume[self.name])
@test.attr(type='gate')
def test_volumes_list_by_status(self):
params = {'status': 'available'}
resp, fetched_list = self.client.list_volumes(params)
self.assertEqual(200, resp.status)
- for volume in fetched_list:
- self.assertEqual('available', volume['status'])
+ self._list_by_param_value_and_assert(params)
self.assertVolumesIn(fetched_list, self.volume_list,
- fields=VOLUME_FIELDS)
+ fields=self.VOLUME_FIELDS)
@test.attr(type='gate')
def test_volumes_list_details_by_status(self):
@@ -166,10 +170,9 @@
params = {'availability_zone': zone}
resp, fetched_list = self.client.list_volumes(params)
self.assertEqual(200, resp.status)
- for volume in fetched_list:
- self.assertEqual(zone, volume['availability_zone'])
+ self._list_by_param_value_and_assert(params)
self.assertVolumesIn(fetched_list, self.volume_list,
- fields=VOLUME_FIELDS)
+ fields=self.VOLUME_FIELDS)
@test.attr(type='gate')
def test_volumes_list_details_by_availability_zone(self):
@@ -198,7 +201,7 @@
def test_volume_list_param_display_name_and_status(self):
# Test to list volume when display name and status param is given
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
- params = {'display_name': volume['display_name'],
+ params = {self.name: volume[self.name],
'status': 'available'}
self._list_by_param_value_and_assert(params)
@@ -206,10 +209,19 @@
def test_volume_list_with_detail_param_display_name_and_status(self):
# Test to list volume when name and status param is given
volume = self.volume_list[data_utils.rand_int_id(0, 2)]
- params = {'display_name': volume['display_name'],
+ params = {self.name: volume[self.name],
'status': 'available'}
self._list_by_param_value_and_assert(params, with_detail=True)
-class VolumeListTestXML(VolumesListTest):
+class VolumesV2ListTestXML(VolumesV2ListTestJSON):
+ _interface = 'xml'
+
+
+class VolumesV1ListTestJSON(VolumesV2ListTestJSON):
+ _api_version = 1
+ VOLUME_FIELDS = ('id', 'display_name')
+
+
+class VolumesV1ListTestXML(VolumesV1ListTestJSON):
_interface = 'xml'
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
index e90c957..7ca8599 100644
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ b/tempest/api/volume/v2/test_volumes_list.py
@@ -13,22 +13,16 @@
# 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 operator
from tempest.api.volume import base
-from tempest.common.utils import data_utils
-from tempest.openstack.common import log as logging
from tempest import test
-from testtools import matchers
-
-LOG = logging.getLogger(__name__)
-
-VOLUME_FIELDS = ('id', 'name')
-class VolumesV2ListTestJSON(base.BaseVolumeV2Test):
+class VolumesV2ListTestJSON(base.BaseVolumeTest):
"""
+ volumes v2 specific tests.
+
This test creates a number of 1G volumes. To run successfully,
ensure that the backing file for the volume group that Nova uses
has space for at least 3 1G volumes!
@@ -36,25 +30,6 @@
VOLUME_BACKING_FILE_SIZE is at least 4G in your localrc
"""
- _interface = 'json'
-
- def assertVolumesIn(self, fetched_list, expected_list, fields=None):
- if fields:
- expected_list = map(operator.itemgetter(*fields), expected_list)
- fetched_list = map(operator.itemgetter(*fields), fetched_list)
-
- missing_vols = [v for v in expected_list if v not in fetched_list]
- if len(missing_vols) == 0:
- return
-
- def str_vol(vol):
- return "%s:%s" % (vol['id'], vol['name'])
-
- raw_msg = "Could not find volumes %s in expected list %s; fetched %s"
- self.fail(raw_msg % ([str_vol(v) for v in missing_vols],
- [str_vol(v) for v in expected_list],
- [str_vol(v) for v in fetched_list]))
-
@classmethod
@test.safe_setup
def setUpClass(cls):
@@ -79,124 +54,6 @@
cls.client.wait_for_resource_deletion(volid)
super(VolumesV2ListTestJSON, cls).tearDownClass()
- def _list_by_param_value_and_assert(self, params, expected_list=None,
- with_detail=False):
- """
- Perform list or list_details action with given params
- and validates result.
- """
- if with_detail:
- resp, fetched_vol_list = \
- self.client.list_volumes_with_detail(params=params)
- else:
- resp, fetched_vol_list = self.client.list_volumes(params=params)
-
- self.assertEqual(200, resp.status)
- if expected_list is None:
- expected_list = self.volume_list
- self.assertVolumesIn(fetched_vol_list, expected_list,
- fields=VOLUME_FIELDS)
- # Validating params of fetched volumes
- if with_detail:
- for volume in fetched_vol_list:
- for key in params:
- msg = "Failed to list volumes %s by %s" % \
- ('details' if with_detail else '', key)
- if key == 'metadata':
- self.assertThat(volume[key].items(),
- matchers.ContainsAll(
- params[key].items()), msg)
- else:
- self.assertEqual(params[key], volume[key], msg)
-
- @test.attr(type='smoke')
- def test_volume_list(self):
- # Get a list of Volumes
- # Fetch all volumes
- resp, fetched_list = self.client.list_volumes()
- self.assertEqual(200, resp.status)
- self.assertVolumesIn(fetched_list, self.volume_list,
- fields=VOLUME_FIELDS)
-
- @test.attr(type='gate')
- def test_volume_list_with_details(self):
- # Get a list of Volumes with details
- # Fetch all Volumes
- resp, fetched_list = self.client.list_volumes_with_detail()
- self.assertEqual(200, resp.status)
- self.assertVolumesIn(fetched_list, self.volume_list)
-
- @test.attr(type='gate')
- def test_volume_list_by_name(self):
- volume = self.volume_list[data_utils.rand_int_id(0, 2)]
- params = {'name': volume['name']}
- resp, fetched_vol = self.client.list_volumes(params)
- self.assertEqual(200, resp.status)
- self.assertEqual(1, len(fetched_vol), str(fetched_vol))
- self.assertEqual(fetched_vol[0]['name'], volume['name'])
-
- @test.attr(type='gate')
- def test_volume_list_details_by_name(self):
- volume = self.volume_list[data_utils.rand_int_id(0, 2)]
- params = {'name': volume['name']}
- resp, fetched_vol = self.client.list_volumes_with_detail(params)
- self.assertEqual(200, resp.status)
- self.assertEqual(1, len(fetched_vol), str(fetched_vol))
- self.assertEqual(fetched_vol[0]['name'], volume['name'])
-
- @test.attr(type='gate')
- def test_volumes_list_by_status(self):
- params = {'status': 'available'}
- self._list_by_param_value_and_assert(params)
-
- @test.attr(type='gate')
- def test_volumes_list_details_by_status(self):
- params = {'status': 'available'}
- self._list_by_param_value_and_assert(params, with_detail=True)
-
- @test.attr(type='gate')
- def test_volumes_list_by_availability_zone(self):
- volume = self.volume_list[data_utils.rand_int_id(0, 2)]
- zone = volume['availability_zone']
- params = {'availability_zone': zone}
- self._list_by_param_value_and_assert(params)
-
- @test.attr(type='gate')
- def test_volumes_list_details_by_availability_zone(self):
- volume = self.volume_list[data_utils.rand_int_id(0, 2)]
- zone = volume['availability_zone']
- params = {'availability_zone': zone}
- self._list_by_param_value_and_assert(params, with_detail=True)
-
- @test.attr(type='gate')
- def test_volume_list_with_param_metadata(self):
- # Test to list volumes when metadata param is given
- params = {'metadata': self.metadata}
- self._list_by_param_value_and_assert(params)
-
- @test.attr(type='gate')
- def test_volume_list_with_details_param_metadata(self):
- # Test to list volumes details when metadata param is given
- params = {'metadata': self.metadata}
- self._list_by_param_value_and_assert(params, with_detail=True)
-
- @test.attr(type='gate')
- def test_volume_list_param_display_name_and_status(self):
- # Test to list volume when display name and status param is given
- volume = self.volume_list[data_utils.rand_int_id(0, 2)]
- params = {'name': volume['name'],
- 'status': 'available'}
- self._list_by_param_value_and_assert(params, expected_list=[volume])
-
- @test.attr(type='gate')
- def test_volume_list_with_details_param_display_name_and_status(self):
- # Test to list volume when name and status param is given
- volume = self.volume_list[data_utils.rand_int_id(0, 2)]
- params = {'name': volume['name'],
- 'status': 'available'}
- self._list_by_param_value_and_assert(params, expected_list=[volume],
- with_detail=True)
-
@test.attr(type='gate')
def test_volume_list_details_with_multiple_params(self):
# List volumes detail using combined condition
diff --git a/tempest/api_schema/compute/hypervisors.py b/tempest/api_schema/compute/hypervisors.py
index 630901e..e9e1bc9 100644
--- a/tempest/api_schema/compute/hypervisors.py
+++ b/tempest/api_schema/compute/hypervisors.py
@@ -24,7 +24,7 @@
'properties': {
'count': {'type': 'integer'},
'current_workload': {'type': 'integer'},
- 'disk_available_least': {'type': 'integer'},
+ 'disk_available_least': {'type': ['integer', 'null']},
'free_disk_gb': {'type': 'integer'},
'free_ram_mb': {'type': 'integer'},
'local_gb': {'type': 'integer'},
@@ -110,7 +110,7 @@
'properties': {
'cpu_info': {'type': 'string'},
'current_workload': {'type': 'integer'},
- 'disk_available_least': {'type': 'integer'},
+ 'disk_available_least': {'type': ['integer', 'null']},
'host_ip': {
'type': 'string',
'format': 'ip-address'
diff --git a/tempest/api_schema/compute/v2/floating_ips.py b/tempest/api_schema/compute/v2/floating_ips.py
index fb3667b..def0a78 100644
--- a/tempest/api_schema/compute/v2/floating_ips.py
+++ b/tempest/api_schema/compute/v2/floating_ips.py
@@ -128,3 +128,31 @@
'required': ['floating_ips_bulk_delete']
}
}
+
+list_floating_ips_bulk = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'floating_ip_info': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'address': {
+ 'type': 'string',
+ 'format': 'ip-address'
+ },
+ 'instance_uuid': {'type': ['string', 'null']},
+ 'interface': {'type': ['string', 'null']},
+ 'pool': {'type': ['string', 'null']},
+ 'project_id': {'type': ['string', 'null']}
+ },
+ 'required': ['address', 'instance_uuid', 'interface',
+ 'pool', 'project_id']
+ }
+ }
+ },
+ 'required': ['floating_ip_info']
+ }
+}
diff --git a/tempest/api_schema/compute/v2/quota_classes.py b/tempest/api_schema/compute/v2/quota_classes.py
new file mode 100644
index 0000000..3464fb4
--- /dev/null
+++ b/tempest/api_schema/compute/v2/quota_classes.py
@@ -0,0 +1,31 @@
+# Copyright 2014 IBM 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.
+
+import copy
+
+from tempest.api_schema.compute.v2 import quotas
+
+# NOTE(mriedem): os-quota-class-sets responses are the same as os-quota-sets
+# except for the key in the response body is quota_class_set instead of
+# quota_set, so update this copy of the schema from os-quota-sets.
+quota_set = copy.deepcopy(quotas.quota_set)
+quota_set['response_body']['properties']['quota_class_set'] = (
+ quota_set['response_body']['properties'].pop('quota_set'))
+quota_set['response_body']['required'] = ['quota_class_set']
+
+quota_set_update = copy.deepcopy(quotas.quota_set_update)
+quota_set_update['response_body']['properties']['quota_class_set'] = (
+ quota_set_update['response_body']['properties'].pop('quota_set'))
+quota_set_update['response_body']['required'] = ['quota_class_set']
diff --git a/tempest/cli/__init__.py b/tempest/cli/__init__.py
index 0571f4f..ba94c82 100644
--- a/tempest/cli/__init__.py
+++ b/tempest/cli/__init__.py
@@ -95,14 +95,15 @@
return self.cmd_with_auth(
'neutron', action, flags, params, admin, fail_ok)
- def sahara(self, action, flags='', params='', admin=True, fail_ok=False):
+ def sahara(self, action, flags='', params='', admin=True,
+ fail_ok=False, merge_stderr=True):
"""Executes sahara command for the given action."""
flags += ' --endpoint-type %s' % CONF.data_processing.endpoint_type
return self.cmd_with_auth(
- 'sahara', action, flags, params, admin, fail_ok)
+ 'sahara', action, flags, params, admin, fail_ok, merge_stderr)
def cmd_with_auth(self, cmd, action, flags='', params='',
- admin=True, fail_ok=False):
+ admin=True, fail_ok=False, merge_stderr=False):
"""Executes given command with auth attributes appended."""
# TODO(jogo) make admin=False work
creds = ('--os-username %s --os-tenant-name %s --os-password %s '
@@ -112,7 +113,7 @@
CONF.identity.admin_password,
CONF.identity.uri))
flags = creds + ' ' + flags
- return self.cmd(cmd, action, flags, params, fail_ok)
+ return self.cmd(cmd, action, flags, params, fail_ok, merge_stderr)
def cmd(self, cmd, action, flags='', params='', fail_ok=False,
merge_stderr=False):
@@ -120,7 +121,7 @@
cmd = ' '.join([os.path.join(CONF.cli.cli_dir, cmd),
flags, action, params])
LOG.info("running: '%s'" % cmd)
- cmd = shlex.split(cmd)
+ cmd = shlex.split(cmd.encode('utf-8'))
result = ''
result_err = ''
stdout = subprocess.PIPE
diff --git a/tempest/cli/simple_read_only/test_sahara.py b/tempest/cli/simple_read_only/test_sahara.py
index 36cc324..f00dcae 100644
--- a/tempest/cli/simple_read_only/test_sahara.py
+++ b/tempest/cli/simple_read_only/test_sahara.py
@@ -12,8 +12,8 @@
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-
import logging
+import re
import subprocess
from tempest import cli
@@ -138,3 +138,30 @@
'cluster_id',
'status'
])
+
+ def test_sahara_bash_completion(self):
+ self.sahara('bash-completion')
+
+ # Optional arguments
+ def test_sahara_help(self):
+ help_text = self.sahara('help')
+ lines = help_text.split('\n')
+ self.assertFirstLineStartsWith(lines, 'usage: sahara')
+
+ commands = []
+ cmds_start = lines.index('Positional arguments:')
+ cmds_end = lines.index('Optional arguments:')
+ command_pattern = re.compile('^ {4}([a-z0-9\-\_]+)')
+ for line in lines[cmds_start:cmds_end]:
+ match = command_pattern.match(line)
+ if match:
+ commands.append(match.group(1))
+ commands = set(commands)
+ wanted_commands = set(('cluster-create', 'data-source-create',
+ 'image-unregister', 'job-binary-create',
+ 'plugin-list', 'job-binary-create', 'help'))
+ self.assertFalse(wanted_commands - commands)
+
+ def test_sahara_version(self):
+ version = self.sahara('', flags='--version')
+ self.assertTrue(re.search('[0-9.]+', version))
diff --git a/tempest/clients.py b/tempest/clients.py
index 4050a20..4e2205e 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -50,6 +50,7 @@
from tempest.services.compute.json.limits_client import LimitsClientJSON
from tempest.services.compute.json.migrations_client import \
MigrationsClientJSON
+from tempest.services.compute.json.quotas_client import QuotaClassesClientJSON
from tempest.services.compute.json.quotas_client import QuotasClientJSON
from tempest.services.compute.json.security_groups_client import \
SecurityGroupsClientJSON
@@ -105,6 +106,7 @@
InterfacesClientXML
from tempest.services.compute.xml.keypairs_client import KeyPairsClientXML
from tempest.services.compute.xml.limits_client import LimitsClientXML
+from tempest.services.compute.xml.quotas_client import QuotaClassesClientXML
from tempest.services.compute.xml.quotas_client import QuotasClientXML
from tempest.services.compute.xml.security_groups_client \
import SecurityGroupsClientXML
@@ -220,6 +222,8 @@
self.images_client = ImagesClientXML(self.auth_provider)
self.keypairs_client = KeyPairsClientXML(self.auth_provider)
self.quotas_client = QuotasClientXML(self.auth_provider)
+ self.quota_classes_client = QuotaClassesClientXML(
+ self.auth_provider)
self.flavors_client = FlavorsClientXML(self.auth_provider)
self.extensions_client = ExtensionsClientXML(self.auth_provider)
self.volumes_extensions_client = VolumesExtensionsClientXML(
@@ -288,6 +292,8 @@
self.keypairs_v3_client = KeyPairsV3ClientJSON(
self.auth_provider)
self.quotas_client = QuotasClientJSON(self.auth_provider)
+ self.quota_classes_client = QuotaClassesClientJSON(
+ self.auth_provider)
self.quotas_v3_client = QuotasV3ClientJSON(self.auth_provider)
self.flavors_client = FlavorsClientJSON(self.auth_provider)
self.flavors_v3_client = FlavorsV3ClientJSON(self.auth_provider)
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 1d46028..19e816b 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -192,7 +192,9 @@
self.check_users()
self.check_objects()
self.check_servers()
- self.check_volumes()
+ # TODO(sdague): Volumes not yet working, bring it back once the
+ # code is self testing.
+ # self.check_volumes()
def check_users(self):
"""Check that the users we expect to exist, do.
@@ -284,6 +286,12 @@
#######################
+def _resolve_image(image, imgtype):
+ name = image[imgtype]
+ fname = os.path.join(OPTS.devstack_base, image['imgdir'], name)
+ return name, fname
+
+
def create_images(images):
for image in images:
client = client_for_user(image['owner'])
@@ -297,20 +305,23 @@
# special handling for 3 part image
extras = {}
if image['format'] == 'ami':
+ name, fname = _resolve_image(image, 'aki')
r, aki = client.images.create_image(
- 'javelin_' + image['aki'], 'aki', 'aki')
- client.images.store_image(aki.get('id'), open(image['aki'], 'r'))
+ 'javelin_' + name, 'aki', 'aki')
+ client.images.store_image(aki.get('id'), open(fname, 'r'))
extras['kernel_id'] = aki.get('id')
+ name, fname = _resolve_image(image, 'ari')
r, ari = client.images.create_image(
- 'javelin_' + image['ari'], 'ari', 'ari')
- client.images.store_image(ari.get('id'), open(image['ari'], 'r'))
+ 'javelin_' + name, 'ari', 'ari')
+ client.images.store_image(ari.get('id'), open(fname, 'r'))
extras['ramdisk_id'] = ari.get('id')
+ _, fname = _resolve_image(image, 'file')
r, body = client.images.create_image(
image['name'], image['format'], image['format'], **extras)
image_id = body.get('id')
- client.images.store_image(image_id, open(image['file'], 'r'))
+ client.images.store_image(image_id, open(fname, 'r'))
#######################
@@ -407,8 +418,10 @@
create_objects(RES['objects'])
create_images(RES['images'])
create_servers(RES['servers'])
- create_volumes(RES['volumes'])
- attach_volumes(RES['volumes'])
+ # TODO(sdague): volumes definition doesn't work yet, bring it
+ # back once we're actually executing the code
+ # create_volumes(RES['volumes'])
+ # attach_volumes(RES['volumes'])
def get_options():
@@ -423,6 +436,11 @@
required=True,
metavar='resourcefile.yaml',
help='Resources definition yaml file')
+ parser.add_argument(
+ '-d', '--devstack-base',
+ required=True,
+ metavar='/opt/stack/old',
+ help='Devstack base directory for retrieving artifacts')
# auth bits, letting us also just source the devstack openrc
parser.add_argument('--os-username',
metavar='<auth-user-name>',
diff --git a/tempest/cmd/resources.yaml b/tempest/cmd/resources.yaml
index a1f567b..3450e1f 100644
--- a/tempest/cmd/resources.yaml
+++ b/tempest/cmd/resources.yaml
@@ -27,6 +27,7 @@
images:
- name: javelin_cirros
owner: javelin
+ imgdir: files/images/cirros-0.3.2-x86_64-uec
file: cirros-0.3.2-x86_64-blank.img
format: ami
aki: cirros-0.3.2-x86_64-vmlinuz
diff --git a/tempest/common/commands.py b/tempest/common/commands.py
index 2ab008d..6583475 100644
--- a/tempest/common/commands.py
+++ b/tempest/common/commands.py
@@ -25,7 +25,7 @@
def sudo_cmd_call(cmd):
- args = shlex.split(cmd)
+ args = shlex.split(cmd.encode('utf-8'))
subprocess_args = {'stdout': subprocess.PIPE,
'stderr': subprocess.STDOUT}
proc = subprocess.Popen(['/usr/bin/sudo', '-n'] + args,
@@ -84,7 +84,7 @@
"-i %(pkey)s %(file1)s %(dest)s" % {'pkey': pkey,
'file1': file_from,
'dest': dest}
- args = shlex.split(cmd)
+ args = shlex.split(cmd.encode('utf-8'))
subprocess_args = {'stdout': subprocess.PIPE,
'stderr': subprocess.STDOUT}
proc = subprocess.Popen(args, **subprocess_args)
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 8166de5..208f42f 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -57,7 +57,7 @@
def _create_tenant(self, name, description):
if self.tempest_client:
- resp, tenant = self.identity_admin_client.create_tenant(
+ _, tenant = self.identity_admin_client.create_tenant(
name=name, description=description)
else:
tenant = self.identity_admin_client.tenants.create(
@@ -67,7 +67,7 @@
def _get_tenant_by_name(self, name):
if self.tempest_client:
- resp, tenant = self.identity_admin_client.get_tenant_by_name(name)
+ _, tenant = self.identity_admin_client.get_tenant_by_name(name)
else:
tenants = self.identity_admin_client.tenants.list()
for ten in tenants:
@@ -80,10 +80,10 @@
def _create_user(self, username, password, tenant, email):
if self.tempest_client:
- resp, user = self.identity_admin_client.create_user(username,
- password,
- tenant['id'],
- email)
+ _, user = self.identity_admin_client.create_user(username,
+ password,
+ tenant['id'],
+ email)
else:
user = self.identity_admin_client.users.create(username, password,
email,
@@ -92,7 +92,7 @@
def _get_user(self, tenant, username):
if self.tempest_client:
- resp, user = self.identity_admin_client.get_user_by_username(
+ _, user = self.identity_admin_client.get_user_by_username(
tenant['id'],
username)
else:
@@ -101,7 +101,7 @@
def _list_roles(self):
if self.tempest_client:
- resp, roles = self.identity_admin_client.list_roles()
+ _, roles = self.identity_admin_client.list_roles()
else:
roles = self.identity_admin_client.roles.list()
return roles
diff --git a/tempest/openstack/common/gettextutils.py b/tempest/openstack/common/gettextutils.py
index 6102e67..872d58e 100644
--- a/tempest/openstack/common/gettextutils.py
+++ b/tempest/openstack/common/gettextutils.py
@@ -23,7 +23,6 @@
"""
import copy
-import functools
import gettext
import locale
from logging import handlers
@@ -42,7 +41,7 @@
"""Create translator functions
"""
- def __init__(self, domain, lazy=False, localedir=None):
+ def __init__(self, domain, localedir=None):
"""Establish a set of translation functions for the domain.
:param domain: Name of translation domain,
@@ -55,7 +54,6 @@
:type localedir: str
"""
self.domain = domain
- self.lazy = lazy
if localedir is None:
localedir = os.environ.get(domain.upper() + '_LOCALEDIR')
self.localedir = localedir
@@ -75,16 +73,19 @@
"""
if domain is None:
domain = self.domain
- if self.lazy:
- return functools.partial(Message, domain=domain)
- t = gettext.translation(
- domain,
- localedir=self.localedir,
- fallback=True,
- )
- if six.PY3:
- return t.gettext
- return t.ugettext
+ t = gettext.translation(domain,
+ localedir=self.localedir,
+ fallback=True)
+ # Use the appropriate method of the translation object based
+ # on the python version.
+ m = t.gettext if six.PY3 else t.ugettext
+
+ def f(msg):
+ """oslo.i18n.gettextutils translation function."""
+ if USE_LAZY:
+ return Message(msg, domain=domain)
+ return m(msg)
+ return f
@property
def primary(self):
@@ -147,19 +148,11 @@
your project is importing _ directly instead of using the
gettextutils.install() way of importing the _ function.
"""
- # FIXME(dhellmann): This function will be removed in oslo.i18n,
- # because the TranslatorFactory makes it superfluous.
- global _, _LI, _LW, _LE, _LC, USE_LAZY
- tf = TranslatorFactory('tempest', lazy=True)
- _ = tf.primary
- _LI = tf.log_info
- _LW = tf.log_warning
- _LE = tf.log_error
- _LC = tf.log_critical
+ global USE_LAZY
USE_LAZY = True
-def install(domain, lazy=False):
+def install(domain):
"""Install a _() function using the given translation domain.
Given a translation domain, install a _() function using gettext's
@@ -170,26 +163,14 @@
a translation-domain-specific environment variable (e.g.
NOVA_LOCALEDIR).
+ Note that to enable lazy translation, enable_lazy must be
+ called.
+
:param domain: the translation domain
- :param lazy: indicates whether or not to install the lazy _() function.
- The lazy _() introduces a way to do deferred translation
- of messages by installing a _ that builds Message objects,
- instead of strings, which can then be lazily translated into
- any available locale.
"""
- if lazy:
- from six import moves
- tf = TranslatorFactory(domain, lazy=True)
- moves.builtins.__dict__['_'] = tf.primary
- else:
- localedir = '%s_LOCALEDIR' % domain.upper()
- if six.PY3:
- gettext.install(domain,
- localedir=os.environ.get(localedir))
- else:
- gettext.install(domain,
- localedir=os.environ.get(localedir),
- unicode=True)
+ from six import moves
+ tf = TranslatorFactory(domain)
+ moves.builtins.__dict__['_'] = tf.primary
class Message(six.text_type):
@@ -373,8 +354,8 @@
'zh_Hant_HK': 'zh_HK',
'zh_Hant': 'zh_TW',
'fil': 'tl_PH'}
- for (locale, alias) in six.iteritems(aliases):
- if locale in language_list and alias not in language_list:
+ for (locale_, alias) in six.iteritems(aliases):
+ if locale_ in language_list and alias not in language_list:
language_list.append(alias)
_AVAILABLE_LANGUAGES[domain] = language_list
diff --git a/tempest/openstack/common/jsonutils.py b/tempest/openstack/common/jsonutils.py
index 53c0ad4..cb83557 100644
--- a/tempest/openstack/common/jsonutils.py
+++ b/tempest/openstack/common/jsonutils.py
@@ -31,25 +31,29 @@
'''
+import codecs
import datetime
import functools
import inspect
import itertools
-import json
-try:
- import xmlrpclib
-except ImportError:
- # NOTE(jaypipes): xmlrpclib was renamed to xmlrpc.client in Python3
- # however the function and object call signatures
- # remained the same. This whole try/except block should
- # be removed and replaced with a call to six.moves once
- # six 1.4.2 is released. See http://bit.ly/1bqrVzu
- import xmlrpc.client as xmlrpclib
+import sys
+
+if sys.version_info < (2, 7):
+ # On Python <= 2.6, json module is not C boosted, so try to use
+ # simplejson module if available
+ try:
+ import simplejson as json
+ except ImportError:
+ import json
+else:
+ import json
import six
+import six.moves.xmlrpc_client as xmlrpclib
from tempest.openstack.common import gettextutils
from tempest.openstack.common import importutils
+from tempest.openstack.common import strutils
from tempest.openstack.common import timeutils
netaddr = importutils.try_import("netaddr")
@@ -164,12 +168,16 @@
return json.dumps(value, default=default, **kwargs)
-def loads(s):
- return json.loads(s)
+def dump(obj, fp, *args, **kwargs):
+ return json.dump(obj, fp, *args, **kwargs)
-def load(s):
- return json.load(s)
+def loads(s, encoding='utf-8', **kwargs):
+ return json.loads(strutils.safe_decode(s, encoding), **kwargs)
+
+
+def load(fp, encoding='utf-8', **kwargs):
+ return json.load(codecs.getreader(encoding)(fp), **kwargs)
try:
diff --git a/tempest/openstack/common/log.py b/tempest/openstack/common/log.py
index 7bebfdb..44102c0 100644
--- a/tempest/openstack/common/log.py
+++ b/tempest/openstack/common/log.py
@@ -15,7 +15,7 @@
# License for the specific language governing permissions and limitations
# under the License.
-"""Openstack logging handler.
+"""OpenStack logging handler.
This module adds to logging functionality by adding the option to specify
a context object when calling the various log methods. If the context object
@@ -33,7 +33,6 @@
import logging.config
import logging.handlers
import os
-import re
import sys
import traceback
@@ -45,27 +44,13 @@
from tempest.openstack.common import importutils
from tempest.openstack.common import jsonutils
from tempest.openstack.common import local
+# NOTE(flaper87): Pls, remove when graduating this module
+# from the incubator.
+from tempest.openstack.common.strutils import mask_password # noqa
_DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
-_SANITIZE_KEYS = ['adminPass', 'admin_pass', 'password', 'admin_password']
-
-# NOTE(ldbragst): Let's build a list of regex objects using the list of
-# _SANITIZE_KEYS we already have. This way, we only have to add the new key
-# to the list of _SANITIZE_KEYS and we can generate regular expressions
-# for XML and JSON automatically.
-_SANITIZE_PATTERNS = []
-_FORMAT_PATTERNS = [r'(%(key)s\s*[=]\s*[\"\']).*?([\"\'])',
- r'(<%(key)s>).*?(</%(key)s>)',
- r'([\"\']%(key)s[\"\']\s*:\s*[\"\']).*?([\"\'])',
- r'([\'"].*?%(key)s[\'"]\s*:\s*u?[\'"]).*?([\'"])']
-
-for key in _SANITIZE_KEYS:
- for pattern in _FORMAT_PATTERNS:
- reg_ex = re.compile(pattern % {'key': key}, re.DOTALL)
- _SANITIZE_PATTERNS.append(reg_ex)
-
common_cli_opts = [
cfg.BoolOpt('debug',
@@ -84,14 +69,11 @@
cfg.StrOpt('log-config-append',
metavar='PATH',
deprecated_name='log-config',
- help='The name of logging configuration file. It does not '
- 'disable existing loggers, but just appends specified '
- 'logging configuration to any other existing logging '
- 'options. Please see the Python logging module '
- 'documentation for details on logging configuration '
- 'files.'),
+ help='The name of a logging configuration file. This file '
+ 'is appended to any existing logging configuration '
+ 'files. For details about logging configuration files, '
+ 'see the Python logging module documentation.'),
cfg.StrOpt('log-format',
- default=None,
metavar='FORMAT',
help='DEPRECATED. '
'A logging.Formatter log message format string which may '
@@ -103,7 +85,7 @@
default=_DEFAULT_LOG_DATE_FORMAT,
metavar='DATE_FORMAT',
help='Format string for %%(asctime)s in log records. '
- 'Default: %(default)s'),
+ 'Default: %(default)s .'),
cfg.StrOpt('log-file',
metavar='PATH',
deprecated_name='logfile',
@@ -112,67 +94,76 @@
cfg.StrOpt('log-dir',
deprecated_name='logdir',
help='(Optional) The base directory used for relative '
- '--log-file paths'),
+ '--log-file paths.'),
cfg.BoolOpt('use-syslog',
default=False,
- help='Use syslog for logging.'),
+ help='Use syslog for logging. '
+ 'Existing syslog format is DEPRECATED during I, '
+ 'and will change in J to honor RFC5424.'),
+ cfg.BoolOpt('use-syslog-rfc-format',
+ # TODO(bogdando) remove or use True after existing
+ # syslog format deprecation in J
+ default=False,
+ help='(Optional) Enables or disables syslog rfc5424 format '
+ 'for logging. If enabled, prefixes the MSG part of the '
+ 'syslog message with APP-NAME (RFC5424). The '
+ 'format without the APP-NAME is deprecated in I, '
+ 'and will be removed in J.'),
cfg.StrOpt('syslog-log-facility',
default='LOG_USER',
- help='syslog facility to receive log lines')
+ help='Syslog facility to receive log lines.')
]
generic_log_opts = [
cfg.BoolOpt('use_stderr',
default=True,
- help='Log output to standard error')
+ help='Log output to standard error.')
]
+DEFAULT_LOG_LEVELS = ['amqp=WARN', 'amqplib=WARN', 'boto=WARN',
+ 'qpid=WARN', 'sqlalchemy=WARN', 'suds=INFO',
+ 'oslo.messaging=INFO', 'iso8601=WARN',
+ 'requests.packages.urllib3.connectionpool=WARN',
+ 'urllib3.connectionpool=WARN']
+
log_opts = [
cfg.StrOpt('logging_context_format_string',
default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s '
'%(name)s [%(request_id)s %(user_identity)s] '
'%(instance)s%(message)s',
- help='format string to use for log messages with context'),
+ help='Format string to use for log messages with context.'),
cfg.StrOpt('logging_default_format_string',
default='%(asctime)s.%(msecs)03d %(process)d %(levelname)s '
'%(name)s [-] %(instance)s%(message)s',
- help='format string to use for log messages without context'),
+ help='Format string to use for log messages without context.'),
cfg.StrOpt('logging_debug_format_suffix',
default='%(funcName)s %(pathname)s:%(lineno)d',
- help='data to append to log format when level is DEBUG'),
+ help='Data to append to log format when level is DEBUG.'),
cfg.StrOpt('logging_exception_prefix',
default='%(asctime)s.%(msecs)03d %(process)d TRACE %(name)s '
'%(instance)s',
- help='prefix each line of exception output with this format'),
+ help='Prefix each line of exception output with this format.'),
cfg.ListOpt('default_log_levels',
- default=[
- 'amqp=WARN',
- 'amqplib=WARN',
- 'boto=WARN',
- 'qpid=WARN',
- 'sqlalchemy=WARN',
- 'suds=INFO',
- 'iso8601=WARN',
- ],
- help='list of logger=LEVEL pairs'),
+ default=DEFAULT_LOG_LEVELS,
+ help='List of logger=LEVEL pairs.'),
cfg.BoolOpt('publish_errors',
default=False,
- help='publish error events'),
+ help='Enables or disables publication of error events.'),
cfg.BoolOpt('fatal_deprecations',
default=False,
- help='make deprecations fatal'),
+ help='Enables or disables fatal status of deprecations.'),
# NOTE(mikal): there are two options here because sometimes we are handed
# a full instance (and could include more information), and other times we
# are just handed a UUID for the instance.
cfg.StrOpt('instance_format',
default='[instance: %(uuid)s] ',
- help='If an instance is passed with the log message, format '
- 'it like this'),
+ help='The format for an instance that is passed with the log '
+ 'message.'),
cfg.StrOpt('instance_uuid_format',
default='[instance: %(uuid)s] ',
- help='If an instance UUID is passed with the log message, '
- 'format it like this'),
+ help='The format for an instance UUID that is passed with the '
+ 'log message.'),
]
CONF = cfg.CONF
@@ -231,40 +222,6 @@
return None
-def mask_password(message, secret="***"):
- """Replace password with 'secret' in message.
-
- :param message: The string which includes security information.
- :param secret: value with which to replace passwords.
- :returns: The unicode value of message with the password fields masked.
-
- For example:
-
- >>> mask_password("'adminPass' : 'aaaaa'")
- "'adminPass' : '***'"
- >>> mask_password("'admin_pass' : 'aaaaa'")
- "'admin_pass' : '***'"
- >>> mask_password('"password" : "aaaaa"')
- '"password" : "***"'
- >>> mask_password("'original_password' : 'aaaaa'")
- "'original_password' : '***'"
- >>> mask_password("u'original_password' : u'aaaaa'")
- "u'original_password' : u'***'"
- """
- message = six.text_type(message)
-
- # NOTE(ldbragst): Check to see if anything in message contains any key
- # specified in _SANITIZE_KEYS, if not then just return the message since
- # we don't have to mask any passwords.
- if not any(key in message for key in _SANITIZE_KEYS):
- return message
-
- secret = r'\g<1>' + secret + r'\g<2>'
- for pattern in _SANITIZE_PATTERNS:
- message = re.sub(pattern, secret, message)
- return message
-
-
class BaseLoggerAdapter(logging.LoggerAdapter):
def audit(self, msg, *args, **kwargs):
@@ -282,6 +239,11 @@
def logger(self):
if not self._logger:
self._logger = getLogger(self.name, self.version)
+ if six.PY3:
+ # In Python 3, the code fails because the 'manager' attribute
+ # cannot be found when using a LoggerAdapter as the
+ # underlying logger. Work around this issue.
+ self._logger.manager = self._logger.logger.manager
return self._logger
@@ -292,18 +254,39 @@
self.logger = logger
self.project = project_name
self.version = version_string
+ self._deprecated_messages_sent = dict()
@property
def handlers(self):
return self.logger.handlers
def deprecated(self, msg, *args, **kwargs):
+ """Call this method when a deprecated feature is used.
+
+ If the system is configured for fatal deprecations then the message
+ is logged at the 'critical' level and :class:`DeprecatedConfig` will
+ be raised.
+
+ Otherwise, the message will be logged (once) at the 'warn' level.
+
+ :raises: :class:`DeprecatedConfig` if the system is configured for
+ fatal deprecations.
+
+ """
stdmsg = _("Deprecated: %s") % msg
if CONF.fatal_deprecations:
self.critical(stdmsg, *args, **kwargs)
raise DeprecatedConfig(msg=stdmsg)
- else:
- self.warn(stdmsg, *args, **kwargs)
+
+ # Using a list because a tuple with dict can't be stored in a set.
+ sent_args = self._deprecated_messages_sent.setdefault(msg, list())
+
+ if args in sent_args:
+ # Already logged this message, so don't log it again.
+ return
+
+ sent_args.append(args)
+ self.warn(stdmsg, *args, **kwargs)
def process(self, msg, kwargs):
# NOTE(mrodden): catch any Message/other object and
@@ -324,7 +307,7 @@
extra.update(_dictify_context(context))
instance = kwargs.pop('instance', None)
- instance_uuid = (extra.get('instance_uuid', None) or
+ instance_uuid = (extra.get('instance_uuid') or
kwargs.pop('instance_uuid', None))
instance_extra = ''
if instance:
@@ -390,10 +373,10 @@
def _create_logging_excepthook(product_name):
def logging_excepthook(exc_type, value, tb):
- extra = {}
- if CONF.verbose:
- extra['exc_info'] = (exc_type, value, tb)
- getLogger(product_name).critical(str(value), **extra)
+ extra = {'exc_info': (exc_type, value, tb)}
+ getLogger(product_name).critical(
+ "".join(traceback.format_exception_only(exc_type, value)),
+ **extra)
return logging_excepthook
@@ -414,23 +397,31 @@
try:
logging.config.fileConfig(log_config_append,
disable_existing_loggers=False)
- except moves.configparser.Error as exc:
- raise LogConfigError(log_config_append, str(exc))
+ except (moves.configparser.Error, KeyError) as exc:
+ raise LogConfigError(log_config_append, six.text_type(exc))
-def setup(product_name):
+def setup(product_name, version='unknown'):
"""Setup logging."""
if CONF.log_config_append:
_load_log_config(CONF.log_config_append)
else:
- _setup_logging_from_conf()
+ _setup_logging_from_conf(product_name, version)
sys.excepthook = _create_logging_excepthook(product_name)
-def set_defaults(logging_context_format_string):
- cfg.set_defaults(log_opts,
- logging_context_format_string=
- logging_context_format_string)
+def set_defaults(logging_context_format_string,
+ default_log_levels=None):
+ # Just in case the caller is not setting the
+ # default_log_level. This is insurance because
+ # we introduced the default_log_level parameter
+ # later in a backwards in-compatible change
+ if default_log_levels is None:
+ default_log_levels = DEFAULT_LOG_LEVELS
+ cfg.set_defaults(
+ log_opts,
+ logging_context_format_string=logging_context_format_string,
+ default_log_levels=default_log_levels)
def _find_facility_from_conf():
@@ -457,15 +448,38 @@
return facility
-def _setup_logging_from_conf():
+class RFCSysLogHandler(logging.handlers.SysLogHandler):
+ def __init__(self, *args, **kwargs):
+ self.binary_name = _get_binary_name()
+ # Do not use super() unless type(logging.handlers.SysLogHandler)
+ # is 'type' (Python 2.7).
+ # Use old style calls, if the type is 'classobj' (Python 2.6)
+ logging.handlers.SysLogHandler.__init__(self, *args, **kwargs)
+
+ def format(self, record):
+ # Do not use super() unless type(logging.handlers.SysLogHandler)
+ # is 'type' (Python 2.7).
+ # Use old style calls, if the type is 'classobj' (Python 2.6)
+ msg = logging.handlers.SysLogHandler.format(self, record)
+ msg = self.binary_name + ' ' + msg
+ return msg
+
+
+def _setup_logging_from_conf(project, version):
log_root = getLogger(None).logger
for handler in log_root.handlers:
log_root.removeHandler(handler)
if CONF.use_syslog:
facility = _find_facility_from_conf()
- syslog = logging.handlers.SysLogHandler(address='/dev/log',
- facility=facility)
+ # TODO(bogdando) use the format provided by RFCSysLogHandler
+ # after existing syslog format deprecation in J
+ if CONF.use_syslog_rfc_format:
+ syslog = RFCSysLogHandler(address='/dev/log',
+ facility=facility)
+ else:
+ syslog = logging.handlers.SysLogHandler(address='/dev/log',
+ facility=facility)
log_root.addHandler(syslog)
logpath = _get_log_file_path()
@@ -484,9 +498,14 @@
log_root.addHandler(streamlog)
if CONF.publish_errors:
- handler = importutils.import_object(
- "tempest.openstack.common.log_handler.PublishErrorsHandler",
- logging.ERROR)
+ try:
+ handler = importutils.import_object(
+ "tempest.openstack.common.log_handler.PublishErrorsHandler",
+ logging.ERROR)
+ except ImportError:
+ handler = importutils.import_object(
+ "oslo.messaging.notify.log_handler.PublishErrorsHandler",
+ logging.ERROR)
log_root.addHandler(handler)
datefmt = CONF.log_date_format
@@ -499,7 +518,9 @@
log_root.info('Deprecated: log_format is now deprecated and will '
'be removed in the next release')
else:
- handler.setFormatter(ContextFormatter(datefmt=datefmt))
+ handler.setFormatter(ContextFormatter(project=project,
+ version=version,
+ datefmt=datefmt))
if CONF.debug:
log_root.setLevel(logging.DEBUG)
@@ -510,9 +531,15 @@
for pair in CONF.default_log_levels:
mod, _sep, level_name = pair.partition('=')
- level = logging.getLevelName(level_name)
logger = logging.getLogger(mod)
- logger.setLevel(level)
+ # NOTE(AAzza) in python2.6 Logger.setLevel doesn't convert string name
+ # to integer code.
+ if sys.version_info < (2, 7):
+ level = logging.getLevelName(level_name)
+ logger.setLevel(level)
+ else:
+ logger.setLevel(level_name)
+
_loggers = {}
@@ -543,7 +570,7 @@
self.level = level
def write(self, msg):
- self.logger.log(self.level, msg)
+ self.logger.log(self.level, msg.rstrip())
class ContextFormatter(logging.Formatter):
@@ -557,27 +584,64 @@
For information about what variables are available for the formatter see:
http://docs.python.org/library/logging.html#formatter
+ If available, uses the context value stored in TLS - local.store.context
+
"""
+ def __init__(self, *args, **kwargs):
+ """Initialize ContextFormatter instance
+
+ Takes additional keyword arguments which can be used in the message
+ format string.
+
+ :keyword project: project name
+ :type project: string
+ :keyword version: project version
+ :type version: string
+
+ """
+
+ self.project = kwargs.pop('project', 'unknown')
+ self.version = kwargs.pop('version', 'unknown')
+
+ logging.Formatter.__init__(self, *args, **kwargs)
+
def format(self, record):
"""Uses contextstring if request_id is set, otherwise default."""
- # NOTE(sdague): default the fancier formating params
+
+ # store project info
+ record.project = self.project
+ record.version = self.version
+
+ # store request info
+ context = getattr(local.store, 'context', None)
+ if context:
+ d = _dictify_context(context)
+ for k, v in d.items():
+ setattr(record, k, v)
+
+ # NOTE(sdague): default the fancier formatting params
# to an empty string so we don't throw an exception if
# they get used
- for key in ('instance', 'color'):
+ for key in ('instance', 'color', 'user_identity'):
if key not in record.__dict__:
record.__dict__[key] = ''
- if record.__dict__.get('request_id', None):
- self._fmt = CONF.logging_context_format_string
+ if record.__dict__.get('request_id'):
+ fmt = CONF.logging_context_format_string
else:
- self._fmt = CONF.logging_default_format_string
+ fmt = CONF.logging_default_format_string
if (record.levelno == logging.DEBUG and
CONF.logging_debug_format_suffix):
- self._fmt += " " + CONF.logging_debug_format_suffix
+ fmt += " " + CONF.logging_debug_format_suffix
- # Cache this on the record, Logger will respect our formated copy
+ if sys.version_info < (3, 2):
+ self._fmt = fmt
+ else:
+ self._style = logging.PercentStyle(fmt)
+ self._fmt = self._style._fmt
+ # Cache this on the record, Logger will respect our formatted copy
if record.exc_info:
record.exc_text = self.formatException(record.exc_info, record)
return logging.Formatter.format(self, record)
diff --git a/tempest/openstack/common/strutils.py b/tempest/openstack/common/strutils.py
new file mode 100644
index 0000000..605cc02
--- /dev/null
+++ b/tempest/openstack/common/strutils.py
@@ -0,0 +1,295 @@
+# Copyright 2011 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.
+
+"""
+System-level utilities and helper functions.
+"""
+
+import math
+import re
+import sys
+import unicodedata
+
+import six
+
+from tempest.openstack.common.gettextutils import _
+
+
+UNIT_PREFIX_EXPONENT = {
+ 'k': 1,
+ 'K': 1,
+ 'Ki': 1,
+ 'M': 2,
+ 'Mi': 2,
+ 'G': 3,
+ 'Gi': 3,
+ 'T': 4,
+ 'Ti': 4,
+}
+UNIT_SYSTEM_INFO = {
+ 'IEC': (1024, re.compile(r'(^[-+]?\d*\.?\d+)([KMGT]i?)?(b|bit|B)$')),
+ 'SI': (1000, re.compile(r'(^[-+]?\d*\.?\d+)([kMGT])?(b|bit|B)$')),
+}
+
+TRUE_STRINGS = ('1', 't', 'true', 'on', 'y', 'yes')
+FALSE_STRINGS = ('0', 'f', 'false', 'off', 'n', 'no')
+
+SLUGIFY_STRIP_RE = re.compile(r"[^\w\s-]")
+SLUGIFY_HYPHENATE_RE = re.compile(r"[-\s]+")
+
+
+# NOTE(flaper87): The following 3 globals are used by `mask_password`
+_SANITIZE_KEYS = ['adminPass', 'admin_pass', 'password', 'admin_password']
+
+# NOTE(ldbragst): Let's build a list of regex objects using the list of
+# _SANITIZE_KEYS we already have. This way, we only have to add the new key
+# to the list of _SANITIZE_KEYS and we can generate regular expressions
+# for XML and JSON automatically.
+_SANITIZE_PATTERNS = []
+_FORMAT_PATTERNS = [r'(%(key)s\s*[=]\s*[\"\']).*?([\"\'])',
+ r'(<%(key)s>).*?(</%(key)s>)',
+ r'([\"\']%(key)s[\"\']\s*:\s*[\"\']).*?([\"\'])',
+ r'([\'"].*?%(key)s[\'"]\s*:\s*u?[\'"]).*?([\'"])',
+ r'([\'"].*?%(key)s[\'"]\s*,\s*\'--?[A-z]+\'\s*,\s*u?[\'"])'
+ '.*?([\'"])',
+ r'(%(key)s\s*--?[A-z]+\s*)\S+(\s*)']
+
+for key in _SANITIZE_KEYS:
+ for pattern in _FORMAT_PATTERNS:
+ reg_ex = re.compile(pattern % {'key': key}, re.DOTALL)
+ _SANITIZE_PATTERNS.append(reg_ex)
+
+
+def int_from_bool_as_string(subject):
+ """Interpret a string as a boolean and return either 1 or 0.
+
+ Any string value in:
+
+ ('True', 'true', 'On', 'on', '1')
+
+ is interpreted as a boolean True.
+
+ Useful for JSON-decoded stuff and config file parsing
+ """
+ return bool_from_string(subject) and 1 or 0
+
+
+def bool_from_string(subject, strict=False, default=False):
+ """Interpret a string as a boolean.
+
+ A case-insensitive match is performed such that strings matching 't',
+ 'true', 'on', 'y', 'yes', or '1' are considered True and, when
+ `strict=False`, anything else returns the value specified by 'default'.
+
+ Useful for JSON-decoded stuff and config file parsing.
+
+ If `strict=True`, unrecognized values, including None, will raise a
+ ValueError which is useful when parsing values passed in from an API call.
+ Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'.
+ """
+ if not isinstance(subject, six.string_types):
+ subject = six.text_type(subject)
+
+ lowered = subject.strip().lower()
+
+ if lowered in TRUE_STRINGS:
+ return True
+ elif lowered in FALSE_STRINGS:
+ return False
+ elif strict:
+ acceptable = ', '.join(
+ "'%s'" % s for s in sorted(TRUE_STRINGS + FALSE_STRINGS))
+ msg = _("Unrecognized value '%(val)s', acceptable values are:"
+ " %(acceptable)s") % {'val': subject,
+ 'acceptable': acceptable}
+ raise ValueError(msg)
+ else:
+ return default
+
+
+def safe_decode(text, incoming=None, errors='strict'):
+ """Decodes incoming text/bytes string using `incoming` if they're not
+ already unicode.
+
+ :param incoming: Text's current encoding
+ :param errors: Errors handling policy. See here for valid
+ values http://docs.python.org/2/library/codecs.html
+ :returns: text or a unicode `incoming` encoded
+ representation of it.
+ :raises TypeError: If text is not an instance of str
+ """
+ if not isinstance(text, (six.string_types, six.binary_type)):
+ raise TypeError("%s can't be decoded" % type(text))
+
+ if isinstance(text, six.text_type):
+ return text
+
+ if not incoming:
+ incoming = (sys.stdin.encoding or
+ sys.getdefaultencoding())
+
+ try:
+ return text.decode(incoming, errors)
+ except UnicodeDecodeError:
+ # Note(flaper87) If we get here, it means that
+ # sys.stdin.encoding / sys.getdefaultencoding
+ # didn't return a suitable encoding to decode
+ # text. This happens mostly when global LANG
+ # var is not set correctly and there's no
+ # default encoding. In this case, most likely
+ # python will use ASCII or ANSI encoders as
+ # default encodings but they won't be capable
+ # of decoding non-ASCII characters.
+ #
+ # Also, UTF-8 is being used since it's an ASCII
+ # extension.
+ return text.decode('utf-8', errors)
+
+
+def safe_encode(text, incoming=None,
+ encoding='utf-8', errors='strict'):
+ """Encodes incoming text/bytes string using `encoding`.
+
+ If incoming is not specified, text is expected to be encoded with
+ current python's default encoding. (`sys.getdefaultencoding`)
+
+ :param incoming: Text's current encoding
+ :param encoding: Expected encoding for text (Default UTF-8)
+ :param errors: Errors handling policy. See here for valid
+ values http://docs.python.org/2/library/codecs.html
+ :returns: text or a bytestring `encoding` encoded
+ representation of it.
+ :raises TypeError: If text is not an instance of str
+ """
+ if not isinstance(text, (six.string_types, six.binary_type)):
+ raise TypeError("%s can't be encoded" % type(text))
+
+ if not incoming:
+ incoming = (sys.stdin.encoding or
+ sys.getdefaultencoding())
+
+ if isinstance(text, six.text_type):
+ return text.encode(encoding, errors)
+ elif text and encoding != incoming:
+ # Decode text before encoding it with `encoding`
+ text = safe_decode(text, incoming, errors)
+ return text.encode(encoding, errors)
+ else:
+ return text
+
+
+def string_to_bytes(text, unit_system='IEC', return_int=False):
+ """Converts a string into an float representation of bytes.
+
+ The units supported for IEC ::
+
+ Kb(it), Kib(it), Mb(it), Mib(it), Gb(it), Gib(it), Tb(it), Tib(it)
+ KB, KiB, MB, MiB, GB, GiB, TB, TiB
+
+ The units supported for SI ::
+
+ kb(it), Mb(it), Gb(it), Tb(it)
+ kB, MB, GB, TB
+
+ Note that the SI unit system does not support capital letter 'K'
+
+ :param text: String input for bytes size conversion.
+ :param unit_system: Unit system for byte size conversion.
+ :param return_int: If True, returns integer representation of text
+ in bytes. (default: decimal)
+ :returns: Numerical representation of text in bytes.
+ :raises ValueError: If text has an invalid value.
+
+ """
+ try:
+ base, reg_ex = UNIT_SYSTEM_INFO[unit_system]
+ except KeyError:
+ msg = _('Invalid unit system: "%s"') % unit_system
+ raise ValueError(msg)
+ match = reg_ex.match(text)
+ if match:
+ magnitude = float(match.group(1))
+ unit_prefix = match.group(2)
+ if match.group(3) in ['b', 'bit']:
+ magnitude /= 8
+ else:
+ msg = _('Invalid string format: %s') % text
+ raise ValueError(msg)
+ if not unit_prefix:
+ res = magnitude
+ else:
+ res = magnitude * pow(base, UNIT_PREFIX_EXPONENT[unit_prefix])
+ if return_int:
+ return int(math.ceil(res))
+ return res
+
+
+def to_slug(value, incoming=None, errors="strict"):
+ """Normalize string.
+
+ Convert to lowercase, remove non-word characters, and convert spaces
+ to hyphens.
+
+ Inspired by Django's `slugify` filter.
+
+ :param value: Text to slugify
+ :param incoming: Text's current encoding
+ :param errors: Errors handling policy. See here for valid
+ values http://docs.python.org/2/library/codecs.html
+ :returns: slugified unicode representation of `value`
+ :raises TypeError: If text is not an instance of str
+ """
+ value = safe_decode(value, incoming, errors)
+ # NOTE(aababilov): no need to use safe_(encode|decode) here:
+ # encodings are always "ascii", error handling is always "ignore"
+ # and types are always known (first: unicode; second: str)
+ value = unicodedata.normalize("NFKD", value).encode(
+ "ascii", "ignore").decode("ascii")
+ value = SLUGIFY_STRIP_RE.sub("", value).strip().lower()
+ return SLUGIFY_HYPHENATE_RE.sub("-", value)
+
+
+def mask_password(message, secret="***"):
+ """Replace password with 'secret' in message.
+
+ :param message: The string which includes security information.
+ :param secret: value with which to replace passwords.
+ :returns: The unicode value of message with the password fields masked.
+
+ For example:
+
+ >>> mask_password("'adminPass' : 'aaaaa'")
+ "'adminPass' : '***'"
+ >>> mask_password("'admin_pass' : 'aaaaa'")
+ "'admin_pass' : '***'"
+ >>> mask_password('"password" : "aaaaa"')
+ '"password" : "***"'
+ >>> mask_password("'original_password' : 'aaaaa'")
+ "'original_password' : '***'"
+ >>> mask_password("u'original_password' : u'aaaaa'")
+ "u'original_password' : u'***'"
+ """
+ message = six.text_type(message)
+
+ # NOTE(ldbragst): Check to see if anything in message contains any key
+ # specified in _SANITIZE_KEYS, if not then just return the message since
+ # we don't have to mask any passwords.
+ if not any(key in message for key in _SANITIZE_KEYS):
+ return message
+
+ secret = r'\g<1>' + secret + r'\g<2>'
+ for pattern in _SANITIZE_PATTERNS:
+ message = re.sub(pattern, secret, message)
+ return message
diff --git a/tempest/openstack/common/timeutils.py b/tempest/openstack/common/timeutils.py
index d5ed81d..c48da95 100644
--- a/tempest/openstack/common/timeutils.py
+++ b/tempest/openstack/common/timeutils.py
@@ -114,7 +114,7 @@
def iso8601_from_timestamp(timestamp):
- """Returns a iso8601 formated date from timestamp."""
+ """Returns an iso8601 formatted date from timestamp."""
return isotime(datetime.datetime.utcfromtimestamp(timestamp))
@@ -134,7 +134,7 @@
def advance_time_delta(timedelta):
"""Advance overridden time using a datetime.timedelta."""
- assert(not utcnow.override_time is None)
+ assert utcnow.override_time is not None
try:
for dt in utcnow.override_time:
dt += timedelta
diff --git a/tempest/scenario/test_load_balancer_basic.py b/tempest/scenario/test_load_balancer_basic.py
index e041fd2..800b3b0 100644
--- a/tempest/scenario/test_load_balancer_basic.py
+++ b/tempest/scenario/test_load_balancer_basic.py
@@ -258,6 +258,13 @@
else:
self.vip_ip = self.vip.address
+ # Currently the ovs-agent is not enforcing security groups on the
+ # vip port - see https://bugs.launchpad.net/neutron/+bug/1163569
+ # However the linuxbridge-agent does, and it is necessary to add a
+ # security group with a rule that allows tcp port 80 to the vip port.
+ body = {'port': {'security_groups': [self.security_group.id]}}
+ self.network_client.update_port(self.vip.port_id, body)
+
def _check_load_balancing(self):
"""
1. Send 10 requests on the floating ip associated with the VIP
diff --git a/tempest/services/baremetal/v1/base_v1.py b/tempest/services/baremetal/v1/base_v1.py
index 61342eb..9c753c2 100644
--- a/tempest/services/baremetal/v1/base_v1.py
+++ b/tempest/services/baremetal/v1/base_v1.py
@@ -89,6 +89,15 @@
"""
return self._show_request('ports', uuid)
+ def show_driver(self, driver_name):
+ """
+ Gets a specific driver.
+
+ :param driver_name: Name of driver.
+ :return: Serialized driver as a dictionary.
+ """
+ return self._show_request('drivers', driver_name)
+
@base.handle_errors
def create_node(self, chassis_id, **kwargs):
"""
diff --git a/tempest/services/compute/json/floating_ips_client.py b/tempest/services/compute/json/floating_ips_client.py
index 0028eea..cd195f4 100644
--- a/tempest/services/compute/json/floating_ips_client.py
+++ b/tempest/services/compute/json/floating_ips_client.py
@@ -130,6 +130,7 @@
"""Returns a list of all floating IPs bulk."""
resp, body = self.get('os-floating-ips-bulk')
body = json.loads(body)
+ self.validate_response(schema.list_floating_ips_bulk, resp, body)
return resp, body['floating_ip_info']
def delete_floating_ips_bulk(self, ip_range):
diff --git a/tempest/services/compute/json/quotas_client.py b/tempest/services/compute/json/quotas_client.py
index 7e828d8..14b7100 100644
--- a/tempest/services/compute/json/quotas_client.py
+++ b/tempest/services/compute/json/quotas_client.py
@@ -15,6 +15,7 @@
import json
+from tempest.api_schema.compute.v2 import quota_classes as classes_schema
from tempest.api_schema.compute.v2 import quotas as schema
from tempest.common import rest_client
from tempest import config
@@ -118,3 +119,32 @@
resp, body = self.delete('os-quota-sets/%s' % str(tenant_id))
self.validate_response(schema.delete_quota, resp, body)
return resp, body
+
+
+class QuotaClassesClientJSON(rest_client.RestClient):
+
+ def __init__(self, auth_provider):
+ super(QuotaClassesClientJSON, self).__init__(auth_provider)
+ self.service = CONF.compute.catalog_type
+
+ def get_quota_class_set(self, quota_class_id):
+ """List the quota class set for a quota class."""
+
+ url = 'os-quota-class-sets/%s' % str(quota_class_id)
+ resp, body = self.get(url)
+ body = json.loads(body)
+ self.validate_response(classes_schema.quota_set, resp, body)
+ return resp, body['quota_class_set']
+
+ def update_quota_class_set(self, quota_class_id, **kwargs):
+ """
+ Updates the quota class's limits for one or more resources.
+ """
+ post_body = json.dumps({'quota_class_set': kwargs})
+
+ resp, body = self.put('os-quota-class-sets/%s' % str(quota_class_id),
+ post_body)
+
+ body = json.loads(body)
+ self.validate_response(classes_schema.quota_set_update, resp, body)
+ return resp, body['quota_class_set']
diff --git a/tempest/services/compute/xml/quotas_client.py b/tempest/services/compute/xml/quotas_client.py
index 5502fcc..7f87248 100644
--- a/tempest/services/compute/xml/quotas_client.py
+++ b/tempest/services/compute/xml/quotas_client.py
@@ -22,6 +22,19 @@
CONF = config.CONF
+def format_quota(q):
+ quota = {}
+ for k, v in q.items():
+ try:
+ v = int(v)
+ except ValueError:
+ pass
+
+ quota[k] = v
+
+ return quota
+
+
class QuotasClientXML(rest_client.RestClient):
TYPE = "xml"
@@ -29,18 +42,6 @@
super(QuotasClientXML, self).__init__(auth_provider)
self.service = CONF.compute.catalog_type
- def _format_quota(self, q):
- quota = {}
- for k, v in q.items():
- try:
- v = int(v)
- except ValueError:
- pass
-
- quota[k] = v
-
- return quota
-
def get_quota_set(self, tenant_id, user_id=None):
"""List the quota set for a tenant."""
@@ -49,7 +50,7 @@
url += '?user_id=%s' % str(user_id)
resp, body = self.get(url)
body = xml_utils.xml_to_json(etree.fromstring(body))
- body = self._format_quota(body)
+ body = format_quota(body)
return resp, body
def get_default_quota_set(self, tenant_id):
@@ -58,7 +59,7 @@
url = 'os-quota-sets/%s/defaults' % str(tenant_id)
resp, body = self.get(url)
body = xml_utils.xml_to_json(etree.fromstring(body))
- body = self._format_quota(body)
+ body = format_quota(body)
return resp, body
def update_quota_set(self, tenant_id, user_id=None,
@@ -124,9 +125,41 @@
str(xml_utils.Document(post_body)))
body = xml_utils.xml_to_json(etree.fromstring(body))
- body = self._format_quota(body)
+ body = format_quota(body)
return resp, body
def delete_quota_set(self, tenant_id):
"""Delete the tenant's quota set."""
return self.delete('os-quota-sets/%s' % str(tenant_id))
+
+
+class QuotaClassesClientXML(rest_client.RestClient):
+ TYPE = "xml"
+
+ def __init__(self, auth_provider):
+ super(QuotaClassesClientXML, self).__init__(auth_provider)
+ self.service = CONF.compute.catalog_type
+
+ def get_quota_class_set(self, quota_class_id):
+ """List the quota class set for a quota class."""
+
+ url = 'os-quota-class-sets/%s' % str(quota_class_id)
+ resp, body = self.get(url)
+ body = xml_utils.xml_to_json(etree.fromstring(body))
+ body = format_quota(body)
+ return resp, body
+
+ def update_quota_class_set(self, quota_class_id, **kwargs):
+ """
+ Updates the quota class's limits for one or more resources.
+ """
+ post_body = xml_utils.Element("quota_class_set",
+ xmlns=xml_utils.XMLNS_11,
+ **kwargs)
+
+ resp, body = self.put('os-quota-class-sets/%s' % str(quota_class_id),
+ str(xml_utils.Document(post_body)))
+
+ body = xml_utils.xml_to_json(etree.fromstring(body))
+ body = format_quota(body)
+ return resp, body
diff --git a/tempest/services/identity/json/identity_client.py b/tempest/services/identity/json/identity_client.py
index b0cab8e..ac65f81 100644
--- a/tempest/services/identity/json/identity_client.py
+++ b/tempest/services/identity/json/identity_client.py
@@ -37,8 +37,12 @@
"""
if hasattr(self, '_has_admin_extensions'):
return self._has_admin_extensions
- resp, body = self.list_roles()
- self._has_admin_extensions = ('status' in resp and resp.status != 503)
+ # Try something that requires admin
+ try:
+ self.list_roles()
+ self._has_admin_extensions = True
+ except Exception:
+ self._has_admin_extensions = False
return self._has_admin_extensions
def create_role(self, name):
@@ -48,11 +52,13 @@
}
post_body = json.dumps({'role': post_body})
resp, body = self.post('OS-KSADM/roles', post_body)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def get_role(self, role_id):
"""Get a role by its id."""
resp, body = self.get('OS-KSADM/roles/%s' % role_id)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['role']
@@ -70,51 +76,63 @@
}
post_body = json.dumps({'tenant': post_body})
resp, body = self.post('tenants', post_body)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def delete_role(self, role_id):
"""Delete a role."""
- return self.delete('OS-KSADM/roles/%s' % str(role_id))
+ resp, body = self.delete('OS-KSADM/roles/%s' % str(role_id))
+ self.expected_success(204, resp.status)
+ return resp, body
def list_user_roles(self, tenant_id, user_id):
"""Returns a list of roles assigned to a user for a tenant."""
url = '/tenants/%s/users/%s/roles' % (tenant_id, user_id)
resp, body = self.get(url)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def assign_user_role(self, tenant_id, user_id, role_id):
"""Add roles to a user on a tenant."""
resp, body = self.put('/tenants/%s/users/%s/roles/OS-KSADM/%s' %
(tenant_id, user_id, role_id), "")
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def remove_user_role(self, tenant_id, user_id, role_id):
"""Removes a role assignment for a user on a tenant."""
- return self.delete('/tenants/%s/users/%s/roles/OS-KSADM/%s' %
- (tenant_id, user_id, role_id))
+ resp, body = self.delete('/tenants/%s/users/%s/roles/OS-KSADM/%s' %
+ (tenant_id, user_id, role_id))
+ self.expected_success(204, resp.status)
+ return resp, body
def delete_tenant(self, tenant_id):
"""Delete a tenant."""
- return self.delete('tenants/%s' % str(tenant_id))
+ resp, body = self.delete('tenants/%s' % str(tenant_id))
+ self.expected_success(204, resp.status)
+ return resp, body
def get_tenant(self, tenant_id):
"""Get tenant details."""
resp, body = self.get('tenants/%s' % str(tenant_id))
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def list_roles(self):
"""Returns roles."""
resp, body = self.get('OS-KSADM/roles')
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def list_tenants(self):
"""Returns tenants."""
resp, body = self.get('tenants')
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['tenants']
def get_tenant_by_name(self, tenant_name):
- resp, tenants = self.list_tenants()
+ _, tenants = self.list_tenants()
for tenant in tenants:
if tenant['name'] == tenant_name:
return tenant
@@ -122,7 +140,7 @@
def update_tenant(self, tenant_id, **kwargs):
"""Updates a tenant."""
- resp, body = self.get_tenant(tenant_id)
+ _, body = self.get_tenant(tenant_id)
name = kwargs.get('name', body['name'])
desc = kwargs.get('description', body['description'])
en = kwargs.get('enabled', body['enabled'])
@@ -134,6 +152,7 @@
}
post_body = json.dumps({'tenant': post_body})
resp, body = self.post('tenants/%s' % tenant_id, post_body)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def create_user(self, name, password, tenant_id, email, **kwargs):
@@ -149,26 +168,32 @@
post_body['enabled'] = kwargs.get('enabled')
post_body = json.dumps({'user': post_body})
resp, body = self.post('users', post_body)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def update_user(self, user_id, **kwargs):
"""Updates a user."""
put_body = json.dumps({'user': kwargs})
resp, body = self.put('users/%s' % user_id, put_body)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def get_user(self, user_id):
"""GET a user."""
resp, body = self.get("users/%s" % user_id)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def delete_user(self, user_id):
"""Delete a user."""
- return self.delete("users/%s" % user_id)
+ resp, body = self.delete("users/%s" % user_id)
+ self.expected_success(204, resp.status)
+ return resp, body
def get_users(self):
"""Get the list of users."""
resp, body = self.get("users")
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def enable_disable_user(self, user_id, enabled):
@@ -178,24 +203,29 @@
}
put_body = json.dumps({'user': put_body})
resp, body = self.put('users/%s/enabled' % user_id, put_body)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def get_token(self, token_id):
"""Get token details."""
resp, body = self.get("tokens/%s" % token_id)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def delete_token(self, token_id):
"""Delete a token."""
- return self.delete("tokens/%s" % token_id)
+ resp, body = self.delete("tokens/%s" % token_id)
+ self.expected_success(204, resp.status)
+ return resp, body
def list_users_for_tenant(self, tenant_id):
"""List users for a Tenant."""
resp, body = self.get('/tenants/%s/users' % tenant_id)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def get_user_by_username(self, tenant_id, username):
- resp, users = self.list_users_for_tenant(tenant_id)
+ _, users = self.list_users_for_tenant(tenant_id)
for user in users:
if user['name'] == username:
return user
@@ -210,23 +240,28 @@
}
post_body = json.dumps({'OS-KSADM:service': post_body})
resp, body = self.post('/OS-KSADM/services', post_body)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def get_service(self, service_id):
"""Get Service."""
url = '/OS-KSADM/services/%s' % service_id
resp, body = self.get(url)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def list_services(self):
"""List Service - Returns Services."""
resp, body = self.get('/OS-KSADM/services')
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def delete_service(self, service_id):
"""Delete Service."""
url = '/OS-KSADM/services/%s' % service_id
- return self.delete(url)
+ resp, body = self.delete(url)
+ self.expected_success(204, resp.status)
+ return resp, body
def update_user_password(self, user_id, new_pass):
"""Update User Password."""
@@ -236,11 +271,13 @@
}
put_body = json.dumps({'user': put_body})
resp, body = self.put('users/%s/OS-KSADM/password' % user_id, put_body)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def list_extensions(self):
"""List all the extensions."""
resp, body = self.get('/extensions')
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['extensions']['values']
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index 6829333..8c72dfa 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -49,12 +49,13 @@
}
post_body = json.dumps({'user': post_body})
resp, body = self.post('users', post_body)
+ self.expected_success(201, resp.status)
body = json.loads(body)
return resp, body['user']
def update_user(self, user_id, name, **kwargs):
"""Updates a user."""
- resp, body = self.get_user(user_id)
+ _, body = self.get_user(user_id)
email = kwargs.get('email', body['email'])
en = kwargs.get('enabled', body['enabled'])
project_id = kwargs.get('project_id', body['project_id'])
@@ -71,30 +72,35 @@
}
post_body = json.dumps({'user': post_body})
resp, body = self.patch('users/%s' % user_id, post_body)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['user']
def list_user_projects(self, user_id):
"""Lists the projects on which a user has roles assigned."""
resp, body = self.get('users/%s/projects' % user_id)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['projects']
def get_users(self):
"""Get the list of users."""
resp, body = self.get("users")
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['users']
def get_user(self, user_id):
"""GET a user."""
resp, body = self.get("users/%s" % user_id)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['user']
def delete_user(self, user_id):
"""Deletes a User."""
resp, body = self.delete("users/%s" % user_id)
+ self.expected_success(204, resp.status)
return resp, body
def create_project(self, name, **kwargs):
@@ -110,16 +116,18 @@
}
post_body = json.dumps({'project': post_body})
resp, body = self.post('projects', post_body)
+ self.expected_success(201, resp.status)
body = json.loads(body)
return resp, body['project']
def list_projects(self):
resp, body = self.get("projects")
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['projects']
def update_project(self, project_id, **kwargs):
- resp, body = self.get_project(project_id)
+ _, body = self.get_project(project_id)
name = kwargs.get('name', body['name'])
desc = kwargs.get('description', body['description'])
en = kwargs.get('enabled', body['enabled'])
@@ -133,18 +141,21 @@
}
post_body = json.dumps({'project': post_body})
resp, body = self.patch('projects/%s' % project_id, post_body)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['project']
def get_project(self, project_id):
"""GET a Project."""
resp, body = self.get("projects/%s" % project_id)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['project']
def delete_project(self, project_id):
"""Delete a project."""
resp, body = self.delete('projects/%s' % str(project_id))
+ self.expected_success(204, resp.status)
return resp, body
def create_role(self, name):
@@ -154,18 +165,21 @@
}
post_body = json.dumps({'role': post_body})
resp, body = self.post('roles', post_body)
+ self.expected_success(201, resp.status)
body = json.loads(body)
return resp, body['role']
def get_role(self, role_id):
"""GET a Role."""
resp, body = self.get('roles/%s' % str(role_id))
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['role']
def list_roles(self):
"""Get the list of Roles."""
resp, body = self.get("roles")
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['roles']
@@ -176,18 +190,21 @@
}
post_body = json.dumps({'role': post_body})
resp, body = self.patch('roles/%s' % str(role_id), post_body)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['role']
def delete_role(self, role_id):
"""Delete a role."""
resp, body = self.delete('roles/%s' % str(role_id))
+ self.expected_success(204, resp.status)
return resp, body
def assign_user_role(self, project_id, user_id, role_id):
"""Add roles to a user on a project."""
resp, body = self.put('projects/%s/users/%s/roles/%s' %
(project_id, user_id, role_id), None)
+ self.expected_success(204, resp.status)
return resp, body
def create_domain(self, name, **kwargs):
@@ -201,23 +218,26 @@
}
post_body = json.dumps({'domain': post_body})
resp, body = self.post('domains', post_body)
+ self.expected_success(201, resp.status)
body = json.loads(body)
return resp, body['domain']
def delete_domain(self, domain_id):
"""Delete a domain."""
resp, body = self.delete('domains/%s' % str(domain_id))
+ self.expected_success(204, resp.status)
return resp, body
def list_domains(self):
"""List Domains."""
resp, body = self.get('domains')
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['domains']
def update_domain(self, domain_id, **kwargs):
"""Updates a domain."""
- resp, body = self.get_domain(domain_id)
+ _, body = self.get_domain(domain_id)
description = kwargs.get('description', body['description'])
en = kwargs.get('enabled', body['enabled'])
name = kwargs.get('name', body['name'])
@@ -228,12 +248,14 @@
}
post_body = json.dumps({'domain': post_body})
resp, body = self.patch('domains/%s' % domain_id, post_body)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['domain']
def get_domain(self, domain_id):
"""Get Domain details."""
resp, body = self.get('domains/%s' % domain_id)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['domain']
@@ -241,6 +263,7 @@
"""Get token details."""
headers = {'X-Subject-Token': resp_token}
resp, body = self.get("auth/tokens", headers=headers)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['token']
@@ -248,6 +271,7 @@
"""Deletes token."""
headers = {'X-Subject-Token': resp_token}
resp, body = self.delete("auth/tokens", headers=headers)
+ self.expected_success(204, resp.status)
return resp, body
def create_group(self, name, **kwargs):
@@ -263,18 +287,20 @@
}
post_body = json.dumps({'group': post_body})
resp, body = self.post('groups', post_body)
+ self.expected_success(201, resp.status)
body = json.loads(body)
return resp, body['group']
def get_group(self, group_id):
"""Get group details."""
resp, body = self.get('groups/%s' % group_id)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['group']
def update_group(self, group_id, **kwargs):
"""Updates a group."""
- resp, body = self.get_group(group_id)
+ _, body = self.get_group(group_id)
name = kwargs.get('name', body['name'])
description = kwargs.get('description', body['description'])
post_body = {
@@ -283,53 +309,62 @@
}
post_body = json.dumps({'group': post_body})
resp, body = self.patch('groups/%s' % group_id, post_body)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['group']
def delete_group(self, group_id):
"""Delete a group."""
resp, body = self.delete('groups/%s' % str(group_id))
+ self.expected_success(204, resp.status)
return resp, body
def add_group_user(self, group_id, user_id):
"""Add user into group."""
resp, body = self.put('groups/%s/users/%s' % (group_id, user_id),
None)
+ self.expected_success(204, resp.status)
return resp, body
def list_group_users(self, group_id):
"""List users in group."""
resp, body = self.get('groups/%s/users' % group_id)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['users']
def list_user_groups(self, user_id):
"""Lists groups which a user belongs to."""
resp, body = self.get('users/%s/groups' % user_id)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['groups']
def delete_group_user(self, group_id, user_id):
"""Delete user in group."""
resp, body = self.delete('groups/%s/users/%s' % (group_id, user_id))
+ self.expected_success(204, resp.status)
return resp, body
def assign_user_role_on_project(self, project_id, user_id, role_id):
"""Add roles to a user on a project."""
resp, body = self.put('projects/%s/users/%s/roles/%s' %
(project_id, user_id, role_id), None)
+ self.expected_success(204, resp.status)
return resp, body
def assign_user_role_on_domain(self, domain_id, user_id, role_id):
"""Add roles to a user on a domain."""
resp, body = self.put('domains/%s/users/%s/roles/%s' %
(domain_id, user_id, role_id), None)
+ self.expected_success(204, resp.status)
return resp, body
def list_user_roles_on_project(self, project_id, user_id):
"""list roles of a user on a project."""
resp, body = self.get('projects/%s/users/%s/roles' %
(project_id, user_id))
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['roles']
@@ -337,6 +372,7 @@
"""list roles of a user on a domain."""
resp, body = self.get('domains/%s/users/%s/roles' %
(domain_id, user_id))
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['roles']
@@ -344,30 +380,35 @@
"""Delete role of a user on a project."""
resp, body = self.delete('projects/%s/users/%s/roles/%s' %
(project_id, user_id, role_id))
+ self.expected_success(204, resp.status)
return resp, body
def revoke_role_from_user_on_domain(self, domain_id, user_id, role_id):
"""Delete role of a user on a domain."""
resp, body = self.delete('domains/%s/users/%s/roles/%s' %
(domain_id, user_id, role_id))
+ self.expected_success(204, resp.status)
return resp, body
def assign_group_role_on_project(self, project_id, group_id, role_id):
"""Add roles to a user on a project."""
resp, body = self.put('projects/%s/groups/%s/roles/%s' %
(project_id, group_id, role_id), None)
+ self.expected_success(204, resp.status)
return resp, body
def assign_group_role_on_domain(self, domain_id, group_id, role_id):
"""Add roles to a user on a domain."""
resp, body = self.put('domains/%s/groups/%s/roles/%s' %
(domain_id, group_id, role_id), None)
+ self.expected_success(204, resp.status)
return resp, body
def list_group_roles_on_project(self, project_id, group_id):
"""list roles of a user on a project."""
resp, body = self.get('projects/%s/groups/%s/roles' %
(project_id, group_id))
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['roles']
@@ -375,6 +416,7 @@
"""list roles of a user on a domain."""
resp, body = self.get('domains/%s/groups/%s/roles' %
(domain_id, group_id))
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['roles']
@@ -382,12 +424,14 @@
"""Delete role of a user on a project."""
resp, body = self.delete('projects/%s/groups/%s/roles/%s' %
(project_id, group_id, role_id))
+ self.expected_success(204, resp.status)
return resp, body
def revoke_role_from_group_on_domain(self, domain_id, group_id, role_id):
"""Delete role of a user on a domain."""
resp, body = self.delete('domains/%s/groups/%s/roles/%s' %
(domain_id, group_id, role_id))
+ self.expected_success(204, resp.status)
return resp, body
def create_trust(self, trustor_user_id, trustee_user_id, project_id,
@@ -404,12 +448,14 @@
}
post_body = json.dumps({'trust': post_body})
resp, body = self.post('OS-TRUST/trusts', post_body)
+ self.expected_success(201, resp.status)
body = json.loads(body)
return resp, body['trust']
def delete_trust(self, trust_id):
"""Deletes a trust."""
resp, body = self.delete("OS-TRUST/trusts/%s" % trust_id)
+ self.expected_success(204, resp.status)
return resp, body
def get_trusts(self, trustor_user_id=None, trustee_user_id=None):
@@ -422,18 +468,21 @@
% trustee_user_id)
else:
resp, body = self.get("OS-TRUST/trusts")
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['trusts']
def get_trust(self, trust_id):
"""GET trust."""
resp, body = self.get("OS-TRUST/trusts/%s" % trust_id)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['trust']
def get_trust_roles(self, trust_id):
"""GET roles delegated by a trust."""
resp, body = self.get("OS-TRUST/trusts/%s/roles" % trust_id)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['roles']
@@ -441,6 +490,7 @@
"""GET role delegated by a trust."""
resp, body = self.get("OS-TRUST/trusts/%s/roles/%s"
% (trust_id, role_id))
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['role']
@@ -448,6 +498,10 @@
"""HEAD Check if role is delegated by a trust."""
resp, body = self.head("OS-TRUST/trusts/%s/roles/%s"
% (trust_id, role_id))
+ # This code needs to change to 200 when the keystone changes
+ # for bug 1334368 merge and check_trust_roles test is
+ # unskipped
+ self.expected_success(204, resp.status)
return resp, body
diff --git a/tempest/services/identity/v3/json/region_client.py b/tempest/services/identity/v3/json/region_client.py
index f95d00f..c078765 100644
--- a/tempest/services/identity/v3/json/region_client.py
+++ b/tempest/services/identity/v3/json/region_client.py
@@ -1,4 +1,4 @@
-# Copyright 2014 OpenStack Foundation
+# Copyright 2014 Hewlett-Packard Development Company, L.P
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
diff --git a/tempest/services/identity/v3/json/service_client.py b/tempest/services/identity/v3/json/service_client.py
index b66fb4a..82e8aad 100644
--- a/tempest/services/identity/v3/json/service_client.py
+++ b/tempest/services/identity/v3/json/service_client.py
@@ -42,6 +42,7 @@
}
patch_body = json.dumps({'service': patch_body})
resp, body = self.patch('services/%s' % service_id, patch_body)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['service']
@@ -49,6 +50,7 @@
"""Get Service."""
url = 'services/%s' % service_id
resp, body = self.get(url)
+ self.expected_success(200, resp.status)
body = json.loads(body)
return resp, body['service']
@@ -62,10 +64,12 @@
}
body = json.dumps({'service': body_dict})
resp, body = self.post("services", body)
+ self.expected_success(201, resp.status)
body = json.loads(body)
return resp, body["service"]
def delete_service(self, serv_id):
url = "services/" + serv_id
resp, body = self.delete(url)
+ self.expected_success(204, resp.status)
return resp, body
diff --git a/tempest/services/identity/v3/xml/identity_client.py b/tempest/services/identity/v3/xml/identity_client.py
index 35295d7..242b032 100644
--- a/tempest/services/identity/v3/xml/identity_client.py
+++ b/tempest/services/identity/v3/xml/identity_client.py
@@ -104,12 +104,13 @@
project_id=project_id,
domain_id=domain_id)
resp, body = self.post('users', str(common.Document(post_body)))
+ self.expected_success(201, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def update_user(self, user_id, name, **kwargs):
"""Updates a user."""
- resp, body = self.get_user(user_id)
+ _, body = self.get_user(user_id)
email = kwargs.get('email', body['email'])
en = kwargs.get('enabled', body['enabled'])
project_id = kwargs.get('project_id', body['project_id'])
@@ -125,30 +126,35 @@
enabled=str(en).lower())
resp, body = self.patch('users/%s' % user_id,
str(common.Document(update_user)))
+ self.expected_success(200, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def list_user_projects(self, user_id):
"""Lists the projects on which a user has roles assigned."""
resp, body = self.get('users/%s/projects' % user_id)
+ self.expected_success(200, resp.status)
body = self._parse_projects(etree.fromstring(body))
return resp, body
def get_users(self):
"""Get the list of users."""
resp, body = self.get("users")
+ self.expected_success(200, resp.status)
body = self._parse_array(etree.fromstring(body))
return resp, body
def get_user(self, user_id):
"""GET a user."""
resp, body = self.get("users/%s" % user_id)
+ self.expected_success(200, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def delete_user(self, user_id):
"""Deletes a User."""
resp, body = self.delete("users/%s" % user_id)
+ self.expected_success(204, resp.status)
return resp, body
def create_project(self, name, **kwargs):
@@ -164,12 +170,14 @@
name=name)
resp, body = self.post('projects',
str(common.Document(post_body)))
+ self.expected_success(201, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def list_projects(self):
"""Get the list of projects."""
resp, body = self.get("projects")
+ self.expected_success(200, resp.status)
body = self._parse_projects(etree.fromstring(body))
return resp, body
@@ -188,18 +196,21 @@
domain_id=domain_id)
resp, body = self.patch('projects/%s' % project_id,
str(common.Document(post_body)))
+ self.expected_success(200, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def get_project(self, project_id):
"""GET a Project."""
resp, body = self.get("projects/%s" % project_id)
+ self.expected_success(200, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def delete_project(self, project_id):
"""Delete a project."""
resp, body = self.delete('projects/%s' % str(project_id))
+ self.expected_success(204, resp.status)
return resp, body
def create_role(self, name):
@@ -208,18 +219,21 @@
xmlns=XMLNS,
name=name)
resp, body = self.post('roles', str(common.Document(post_body)))
+ self.expected_success(201, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def get_role(self, role_id):
"""GET a Role."""
resp, body = self.get('roles/%s' % str(role_id))
+ self.expected_success(200, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def list_roles(self):
"""Get the list of Roles."""
resp, body = self.get("roles")
+ self.expected_success(200, resp.status)
body = self._parse_roles(etree.fromstring(body))
return resp, body
@@ -230,18 +244,21 @@
name=name)
resp, body = self.patch('roles/%s' % str(role_id),
str(common.Document(post_body)))
+ self.expected_success(200, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def delete_role(self, role_id):
"""Delete a role."""
resp, body = self.delete('roles/%s' % str(role_id))
+ self.expected_success(204, resp.status)
return resp, body
def assign_user_role(self, project_id, user_id, role_id):
"""Add roles to a user on a tenant."""
resp, body = self.put('projects/%s/users/%s/roles/%s' %
(project_id, user_id, role_id), '')
+ self.expected_success(204, resp.status)
return resp, body
def create_domain(self, name, **kwargs):
@@ -254,23 +271,26 @@
description=description,
enabled=str(en).lower())
resp, body = self.post('domains', str(common.Document(post_body)))
+ self.expected_success(201, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def list_domains(self):
"""Get the list of domains."""
resp, body = self.get("domains")
+ self.expected_success(200, resp.status)
body = self._parse_domains(etree.fromstring(body))
return resp, body
def delete_domain(self, domain_id):
"""Delete a domain."""
resp, body = self.delete('domains/%s' % domain_id)
+ self.expected_success(204, resp.status)
return resp, body
def update_domain(self, domain_id, **kwargs):
"""Updates a domain."""
- resp, body = self.get_domain(domain_id)
+ _, body = self.get_domain(domain_id)
description = kwargs.get('description', body['description'])
en = kwargs.get('enabled', body['enabled'])
name = kwargs.get('name', body['name'])
@@ -281,12 +301,14 @@
enabled=str(en).lower())
resp, body = self.patch('domains/%s' % domain_id,
str(common.Document(post_body)))
+ self.expected_success(200, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def get_domain(self, domain_id):
"""Get Domain details."""
resp, body = self.get('domains/%s' % domain_id)
+ self.expected_success(200, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -296,6 +318,7 @@
'Accept': 'application/xml',
'X-Subject-Token': resp_token}
resp, body = self.get("auth/tokens", headers=headers)
+ self.expected_success(200, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -303,6 +326,7 @@
"""Delete a Given Token."""
headers = {'X-Subject-Token': resp_token}
resp, body = self.delete("auth/tokens", headers=headers)
+ self.expected_success(204, resp.status)
return resp, body
def create_group(self, name, **kwargs):
@@ -317,18 +341,20 @@
domain_id=domain_id,
project_id=project_id)
resp, body = self.post('groups', str(common.Document(post_body)))
+ self.expected_success(201, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def get_group(self, group_id):
"""Get group details."""
resp, body = self.get('groups/%s' % group_id)
+ self.expected_success(200, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def update_group(self, group_id, **kwargs):
"""Updates a group."""
- resp, body = self.get_group(group_id)
+ _, body = self.get_group(group_id)
name = kwargs.get('name', body['name'])
description = kwargs.get('description', body['description'])
post_body = common.Element("group",
@@ -337,52 +363,61 @@
description=description)
resp, body = self.patch('groups/%s' % group_id,
str(common.Document(post_body)))
+ self.expected_success(200, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def delete_group(self, group_id):
"""Delete a group."""
resp, body = self.delete('groups/%s' % group_id)
+ self.expected_success(204, resp.status)
return resp, body
def add_group_user(self, group_id, user_id):
"""Add user into group."""
resp, body = self.put('groups/%s/users/%s' % (group_id, user_id), '')
+ self.expected_success(204, resp.status)
return resp, body
def list_group_users(self, group_id):
"""List users in group."""
resp, body = self.get('groups/%s/users' % group_id)
+ self.expected_success(200, resp.status)
body = self._parse_group_users(etree.fromstring(body))
return resp, body
def list_user_groups(self, user_id):
"""Lists the groups which a user belongs to."""
resp, body = self.get('users/%s/groups' % user_id)
+ self.expected_success(200, resp.status)
body = self._parse_groups(etree.fromstring(body))
return resp, body
def delete_group_user(self, group_id, user_id):
"""Delete user in group."""
resp, body = self.delete('groups/%s/users/%s' % (group_id, user_id))
+ self.expected_success(204, resp.status)
return resp, body
def assign_user_role_on_project(self, project_id, user_id, role_id):
"""Add roles to a user on a project."""
resp, body = self.put('projects/%s/users/%s/roles/%s' %
(project_id, user_id, role_id), '')
+ self.expected_success(204, resp.status)
return resp, body
def assign_user_role_on_domain(self, domain_id, user_id, role_id):
"""Add roles to a user on a domain."""
resp, body = self.put('domains/%s/users/%s/roles/%s' %
(domain_id, user_id, role_id), '')
+ self.expected_success(204, resp.status)
return resp, body
def list_user_roles_on_project(self, project_id, user_id):
"""list roles of a user on a project."""
resp, body = self.get('projects/%s/users/%s/roles' %
(project_id, user_id))
+ self.expected_success(200, resp.status)
body = self._parse_roles(etree.fromstring(body))
return resp, body
@@ -390,6 +425,7 @@
"""list roles of a user on a domain."""
resp, body = self.get('domains/%s/users/%s/roles' %
(domain_id, user_id))
+ self.expected_success(200, resp.status)
body = self._parse_roles(etree.fromstring(body))
return resp, body
@@ -397,30 +433,35 @@
"""Delete role of a user on a project."""
resp, body = self.delete('projects/%s/users/%s/roles/%s' %
(project_id, user_id, role_id))
+ self.expected_success(204, resp.status)
return resp, body
def revoke_role_from_user_on_domain(self, domain_id, user_id, role_id):
"""Delete role of a user on a domain."""
resp, body = self.delete('domains/%s/users/%s/roles/%s' %
(domain_id, user_id, role_id))
+ self.expected_success(204, resp.status)
return resp, body
def assign_group_role_on_project(self, project_id, group_id, role_id):
"""Add roles to a user on a project."""
resp, body = self.put('projects/%s/groups/%s/roles/%s' %
(project_id, group_id, role_id), '')
+ self.expected_success(204, resp.status)
return resp, body
def assign_group_role_on_domain(self, domain_id, group_id, role_id):
"""Add roles to a user on a domain."""
resp, body = self.put('domains/%s/groups/%s/roles/%s' %
(domain_id, group_id, role_id), '')
+ self.expected_success(204, resp.status)
return resp, body
def list_group_roles_on_project(self, project_id, group_id):
"""list roles of a user on a project."""
resp, body = self.get('projects/%s/groups/%s/roles' %
(project_id, group_id))
+ self.expected_success(200, resp.status)
body = self._parse_roles(etree.fromstring(body))
return resp, body
@@ -428,6 +469,7 @@
"""list roles of a user on a domain."""
resp, body = self.get('domains/%s/groups/%s/roles' %
(domain_id, group_id))
+ self.expected_success(200, resp.status)
body = self._parse_roles(etree.fromstring(body))
return resp, body
@@ -435,12 +477,14 @@
"""Delete role of a user on a project."""
resp, body = self.delete('projects/%s/groups/%s/roles/%s' %
(project_id, group_id, role_id))
+ self.expected_success(204, resp.status)
return resp, body
def revoke_role_from_group_on_domain(self, domain_id, group_id, role_id):
"""Delete role of a user on a domain."""
resp, body = self.delete('domains/%s/groups/%s/roles/%s' %
(domain_id, group_id, role_id))
+ self.expected_success(204, resp.status)
return resp, body
diff --git a/tempest/services/identity/v3/xml/region_client.py b/tempest/services/identity/v3/xml/region_client.py
index 9f9161d..f854138 100644
--- a/tempest/services/identity/v3/xml/region_client.py
+++ b/tempest/services/identity/v3/xml/region_client.py
@@ -1,4 +1,4 @@
-# Copyright 2014 OpenStack Foundation
+# Copyright 2014 Hewlett-Packard Development Company, L.P
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
diff --git a/tempest/services/identity/v3/xml/service_client.py b/tempest/services/identity/v3/xml/service_client.py
index 37ed892..3beeb89 100644
--- a/tempest/services/identity/v3/xml/service_client.py
+++ b/tempest/services/identity/v3/xml/service_client.py
@@ -51,6 +51,7 @@
type=type)
resp, body = self.patch('services/%s' % service_id,
str(common.Document(update_service)))
+ self.expected_success(200, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -58,6 +59,7 @@
"""Get Service."""
url = 'services/%s' % service_id
resp, body = self.get(url)
+ self.expected_success(200, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
@@ -68,10 +70,12 @@
description=description,
type=serv_type)
resp, body = self.post("services", str(common.Document(post_body)))
+ self.expected_success(201, resp.status)
body = self._parse_body(etree.fromstring(body))
return resp, body
def delete_service(self, serv_id):
url = "services/" + serv_id
resp, body = self.delete(url)
+ self.expected_success(204, resp.status)
return resp, body
diff --git a/tempest/services/identity/xml/identity_client.py b/tempest/services/identity/xml/identity_client.py
index 886ce7b..4ada46c 100644
--- a/tempest/services/identity/xml/identity_client.py
+++ b/tempest/services/identity/xml/identity_client.py
@@ -29,11 +29,13 @@
create_role = xml.Element("role", xmlns=XMLNS, name=name)
resp, body = self.post('OS-KSADM/roles',
str(xml.Document(create_role)))
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def get_role(self, role_id):
"""Get a role by its id."""
resp, body = self.get('OS-KSADM/roles/%s' % role_id)
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def create_tenant(self, name, **kwargs):
@@ -50,16 +52,18 @@
description=kwargs.get('description', ''),
enabled=str(en).lower())
resp, body = self.post('tenants', str(xml.Document(create_tenant)))
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def list_tenants(self):
"""Returns tenants."""
resp, body = self.get('tenants')
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def update_tenant(self, tenant_id, **kwargs):
"""Updates a tenant."""
- resp, body = self.get_tenant(tenant_id)
+ _, body = self.get_tenant(tenant_id)
name = kwargs.get('name', body['name'])
desc = kwargs.get('description', body['description'])
en = kwargs.get('enabled', body['enabled'])
@@ -72,6 +76,7 @@
resp, body = self.post('tenants/%s' % tenant_id,
str(xml.Document(update_tenant)))
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def create_user(self, name, password, tenant_id, email, **kwargs):
@@ -87,6 +92,7 @@
create_user.add_attr('enabled', str(kwargs['enabled']).lower())
resp, body = self.post('users', str(xml.Document(create_user)))
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def update_user(self, user_id, **kwargs):
@@ -97,6 +103,7 @@
resp, body = self.put('users/%s' % user_id,
str(xml.Document(update_user)))
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def enable_disable_user(self, user_id, enabled):
@@ -104,6 +111,7 @@
enable_user = xml.Element("user", enabled=str(enabled).lower())
resp, body = self.put('users/%s/enabled' % user_id,
str(xml.Document(enable_user)))
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def create_service(self, name, service_type, **kwargs):
@@ -116,6 +124,7 @@
description=kwargs.get('description'))
resp, body = self.post('OS-KSADM/services',
str(xml.Document(create_service)))
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def update_user_password(self, user_id, new_pass):
@@ -125,11 +134,13 @@
password=new_pass)
resp, body = self.put('users/%s/OS-KSADM/password' % user_id,
str(xml.Document(put_body)))
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
def list_extensions(self):
"""List all the extensions."""
resp, body = self.get('/extensions')
+ self.expected_success(200, resp.status)
return resp, self._parse_resp(body)
diff --git a/tempest/services/telemetry/telemetry_client_base.py b/tempest/services/telemetry/telemetry_client_base.py
index a073f54..b45c239 100644
--- a/tempest/services/telemetry/telemetry_client_base.py
+++ b/tempest/services/telemetry/telemetry_client_base.py
@@ -101,17 +101,17 @@
uri += "?%s" % urllib.urlencode(uri_dict)
return self.get(uri)
- def list_resources(self):
+ def list_resources(self, query=None):
uri = '%s/resources' % self.uri_prefix
- return self.get(uri)
+ return self.helper_list(uri, query)
- def list_meters(self):
+ def list_meters(self, query=None):
uri = '%s/meters' % self.uri_prefix
- return self.get(uri)
+ return self.helper_list(uri, query)
- def list_alarms(self):
+ def list_alarms(self, query=None):
uri = '%s/alarms' % self.uri_prefix
- return self.get(uri)
+ return self.helper_list(uri, query)
def list_statistics(self, meter, period=None, query=None):
uri = "%s/meters/%s/statistics" % (self.uri_prefix, meter)
diff --git a/tempest/tests/stress/test_stress.py b/tempest/tests/stress/test_stress.py
index 5a334c5..3dc2199 100644
--- a/tempest/tests/stress/test_stress.py
+++ b/tempest/tests/stress/test_stress.py
@@ -32,7 +32,7 @@
cmd = ' '.join([cmd, param])
LOG.info("running: '%s'" % cmd)
cmd_str = cmd
- cmd = shlex.split(cmd)
+ cmd = shlex.split(cmd.encode('utf-8'))
result = ''
result_err = ''
try:
diff --git a/tempest/tests/test_waiters.py b/tempest/tests/test_waiters.py
index 1f9825e..a29cb46 100644
--- a/tempest/tests/test_waiters.py
+++ b/tempest/tests/test_waiters.py
@@ -15,6 +15,7 @@
import time
import mock
+import testtools
from tempest.common import waiters
from tempest import exceptions
@@ -47,3 +48,221 @@
self.assertRaises(exceptions.AddImageException,
waiters.wait_for_image_status,
self.client, 'fake_image_id', 'active')
+
+
+class TestServerWaiters(base.TestCase):
+ def setUp(self):
+ super(TestServerWaiters, self).setUp()
+ self.client = mock.MagicMock()
+ self.client.build_timeout = 1
+ self.client.build_interval = 1
+
+ def test_wait_for_server_status(self):
+ self.client.get_server.return_value = (None, {'status':
+ 'active'}
+ )
+ start_time = int(time.time())
+ waiters.wait_for_server_status(self.client, 'fake_svr_id',
+ 'active'
+ )
+ end_time = int(time.time())
+ # Ensure waiter returns before build_timeout
+ self.assertTrue((end_time - start_time) < 2)
+
+ def test_wait_for_server_status_BUILD_from_not_UNKNOWN(self):
+ self.client.get_server.return_value = (None, {'status': 'active'})
+ start_time = int(time.time())
+ waiters.wait_for_server_status(self.client, 'fake_svr_id',
+ 'BUILD')
+ end_time = int(time.time())
+ # Ensure waiter returns before build_timeout
+ self.assertTrue((end_time - start_time) < 2)
+
+ def test_wait_for_server_status_ready_wait_with_BUILD(self):
+ self.client.get_server.return_value = (None, {'status': 'BUILD'})
+ start_time = int(time.time())
+ waiters.wait_for_server_status(self.client, 'fake_svr_id',
+ 'BUILD', True)
+ end_time = int(time.time())
+ # Ensure waiter returns before build_timeout
+ self.assertTrue((end_time - start_time) < 2)
+
+ def test_wait_for_server_status_ready_wait(self):
+ self.client.get_server.return_value = (None, {'status':
+ 'ERROR',
+ 'OS-EXT-STS:task_state':
+ 'n/a'
+ }
+ )
+ self.client.get_console_output.return_value = (None,
+ {'output': 'Server fake_svr_id failed to reach '
+ 'active status and task state n/a within the '
+ 'required time (1 s).\nCurrent status: SUSPENDED.'
+ '\nCurrent task state: None.'}
+ )
+ self.assertRaises(exceptions.BuildErrorException,
+ waiters.wait_for_server_status,
+ self.client, 'fake_svr_id', 'active',
+ ready_wait=True, extra_timeout=0,
+ raise_on_error=True
+ )
+
+ def test_wait_for_server_status_no_ready_wait(self):
+ self.client.get_server.return_value = (None, {'status':
+ 'ERROR',
+ 'OS-EXT-STS:task_state':
+ 'n/a'
+ }
+ )
+ start_time = int(time.time())
+ waiters.wait_for_server_status(self.client, 'fake_svr_id',
+ 'ERROR', ready_wait=False,
+ extra_timeout=10, raise_on_error=True
+ )
+ end_time = int(time.time())
+ # Ensure waiter returns before build_timeout + extra_timeout
+ self.assertTrue((end_time - start_time) < 12)
+
+ def test_wait_for_server_status_timeout(self):
+ self.client.get_server.return_value = (None, {'status': 'SUSPENDED'})
+ self.client.get_console_output.return_value = (None,
+ {'output': 'Server fake_svr_id failed to reach '
+ 'active status and task state n/a within the '
+ 'required time (1 s).\nCurrent status: SUSPENDED.'
+ '\nCurrent task state: None.'}
+ )
+ self.assertRaises(exceptions.TimeoutException,
+ waiters.wait_for_server_status,
+ self.client, 'fake_svr_id', 'active')
+
+ def test_wait_for_server_status_extra_timeout(self):
+ self.client.get_server.return_value = (None, {'status': 'SUSPENDED'})
+ start_time = int(time.time())
+ self.client.get_console_output.return_value = (None,
+ {'output': 'Server fake_svr_id failed to reach '
+ 'active status and task state n/a within the '
+ 'required time (10 s). \nCurrent status: SUSPENDED.'
+ '\nCurrent task state: None.'}
+ )
+ self.assertRaises(exceptions.TimeoutException,
+ waiters.wait_for_server_status,
+ self.client, 'fake_svr_id',
+ 'active', ready_wait=True,
+ extra_timeout=10, raise_on_error=True
+ )
+ end_time = int(time.time())
+ # Ensure waiter returns after build_timeout but
+ # before build_timeout+extra timeout
+ self.assertTrue(10 < (end_time - start_time) < 12)
+
+ def test_wait_for_server_status_error_on_server_create(self):
+ self.client.get_server.return_value = (None, {'status': 'ERROR'})
+ self.client.get_console_output.return_value = (None,
+ {'output': 'Server fake_svr_id failed to reach '
+ 'activestatus and task state n/a within the '
+ 'required time (1 s).\nCurrent status: ERROR.'
+ '\nCurrent task state: None.'}
+ )
+ self.assertRaises(exceptions.BuildErrorException,
+ waiters.wait_for_server_status,
+ self.client, 'fake_svr_id', 'active')
+
+ def test_wait_for_server_status_no_raise_on_error(self):
+ self.client.get_server.return_value = (None, {'status': 'ERROR'})
+ self.client.get_console_output.return_value = (None,
+ {'output': 'Server fake_svr_id failed to reach '
+ 'activestatus and task state n/a within the '
+ 'required time (1 s).\nCurrent status: ERROR.'
+ '\nCurrent task state: None.'}
+ )
+ self.assertRaises(exceptions.TimeoutException,
+ waiters.wait_for_server_status,
+ self.client, 'fake_svr_id', 'active',
+ ready_wait=True, extra_timeout=0,
+ raise_on_error=False
+ )
+
+ def test_wait_for_server_status_no_ready_wait_timeout(self):
+ self.client.get_server.return_value = (None, {'status': 'ERROR'})
+ self.client.get_console_output.return_value = (None,
+ {'output': 'Server fake_svr_id failed to reach '
+ 'active status and task state n/a within the '
+ 'required time (11 s).\nCurrent status: ERROR.'
+ '\nCurrent task state: None.'}
+ )
+ expected_msg = '''Request timed out
+Details: (TestServerWaiters:test_wait_for_server_status_no_ready_wait_timeout)\
+ Server fake_svr_id failed to reach active status and task state "n/a" within\
+ the required time (11 s). Current status: ERROR. Current task state: None.\
+'''
+ with testtools.ExpectedException(exceptions.TimeoutException,
+ testtools.matchers.AfterPreprocessing(
+ str,
+ testtools.matchers.Equals(expected_msg)
+ )
+ ):
+ waiters.wait_for_server_status(self.client, 'fake_svr_id',
+ 'active', ready_wait=False,
+ extra_timeout=10,
+ raise_on_error=False
+ )
+
+ def test_wait_for_server_status_ready_wait_timeout(self):
+ self.client.get_server.return_value = (None, {'status': 'ERROR'})
+ self.client.get_console_output.return_value = (None,
+ {'output': 'Server fake_svr_id failed to reach '
+ 'activestatus and task state n/a within the '
+ 'required time (11 s).\nCurrent status: ERROR.'
+ '\nCurrent task state: None.'}
+ )
+ expected_msg = '''Request timed out
+Details: (TestServerWaiters:test_wait_for_server_status_ready_wait_timeout)\
+ Server fake_svr_id failed to reach active status and task state "None" within\
+ the required time (11 s). Current status: ERROR. Current task state: None.\
+'''
+ with testtools.ExpectedException(exceptions.TimeoutException,
+ testtools.matchers.AfterPreprocessing(
+ str,
+ testtools.matchers.Equals(expected_msg)
+ )
+ ):
+ waiters.wait_for_server_status(self.client, 'fake_svr_id',
+ 'active', ready_wait=True,
+ extra_timeout=10,
+ raise_on_error=False
+ )
+
+ def test_wait_for_changing_server_status(self):
+ self.client.get_server.side_effect = [(None, {'status': 'BUILD'}),
+ (None, {'status': 'active'})]
+ start_time = int(time.time())
+ waiters.wait_for_server_status(self.client, 'fake_svr_id',
+ 'active', ready_wait=True,
+ extra_timeout=10,
+ raise_on_error=True
+ )
+ end_time = int(time.time())
+ # Ensure waiter returns before build_timeout + extra_timeout
+ self.assertTrue((end_time - start_time) < 12)
+
+ def test_wait_for_changing_server_task_status(self):
+ self.client.get_server.side_effect = [(None, {'status': 'BUILD',
+ 'OS-EXT-STS:task_state':
+ 'n/a'
+ }
+ ),
+ (None, {'status': 'active',
+ 'OS-EXT-STS:task_state':
+ 'None'
+ }
+ )
+ ]
+ start_time = int(time.time())
+ waiters.wait_for_server_status(self.client, 'fake_svr_id',
+ 'active', ready_wait=True,
+ extra_timeout=10,
+ raise_on_error=True
+ )
+ end_time = int(time.time())
+ # Ensure waiter returns before build_timeout + extra_timeout
+ self.assertTrue((end_time - start_time) < 12)
diff --git a/test-requirements.txt b/test-requirements.txt
index 13ef291..cd8154b 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,6 +1,5 @@
hacking>=0.9.2,<0.10
# needed for doc build
-docutils==0.9.1
sphinx>=1.1.2,!=1.2.0,<1.3
python-subunit>=0.0.18
oslosphinx
diff --git a/tox.ini b/tox.ini
index 7f69fad..4f2465a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -84,6 +84,11 @@
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
+[testenv:docs]
+commands = python setup.py build_sphinx {posargs}
+deps = -r{toxinidir}/requirements.txt
+ -r{toxinidir}/test-requirements.txt
+
[testenv:pep8]
commands =
flake8 {posargs}