Merge "Use built-in print() instead of print statement"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index cd57354..78e6aac 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -28,7 +28,8 @@
uri = http://127.0.0.1:5000/v2.0/
# URL for where to find the OpenStack V3 Identity API endpoint (Keystone)
uri_v3 = http://127.0.0.1:5000/v3/
-# The identity region
+# The identity region. Also used as the other services' region name unless
+# they are set explicitly.
region = RegionOne
# This should be the username of a user WITHOUT administrative privileges
@@ -137,6 +138,11 @@
# this value as "compute"
catalog_type = compute
+# The name of a region for compute. If empty or commented-out, the value of
+# identity.region is used instead. If no such region is found in the service
+# catalog, the first found one is used.
+#region = RegionOne
+
# Does the Compute API support creation of images?
create_image_enabled = true
@@ -186,6 +192,11 @@
# this value as "image"
catalog_type = image
+# The name of a region for image. If empty or commented-out, the value of
+# identity.region is used instead. If no such region is found in the service
+# catalog, the first found one is used.
+#region = RegionOne
+
# The version of the OpenStack Images API to use
api_version = 1
@@ -201,6 +212,11 @@
# Catalog type of the Neutron Service
catalog_type = network
+# The name of a region for network. If empty or commented-out, the value of
+# identity.region is used instead. If no such region is found in the service
+# catalog, the first found one is used.
+#region = RegionOne
+
# A large private cidr block from which to allocate smaller blocks for
# tenant networks.
tenant_network_cidr = 10.100.0.0/16
@@ -230,6 +246,10 @@
# Unless you have a custom Keystone service catalog implementation, you
# probably want to leave this value as "volume"
catalog_type = volume
+# The name of a region for volume. If empty or commented-out, the value of
+# identity.region is used instead. If no such region is found in the service
+# catalog, the first found one is used.
+#region = RegionOne
# The disk format to use when copying a volume to image
disk_format = raw
# Number of seconds to wait while looping to check the status of a
@@ -260,6 +280,11 @@
# this value as "object-store"
catalog_type = object-store
+# The name of a region for object storage. If empty or commented-out, the
+# value of identity.region is used instead. If no such region is found in
+# the service catalog, the first found one is used.
+#region = RegionOne
+
# Number of seconds to time on waiting for a container to container
# synchronization complete
container_sync_timeout = 120
@@ -318,6 +343,16 @@
build_interval = 1
[orchestration]
+# The type of endpoint for an Orchestration API service. Unless you have a
+# custom Keystone service catalog implementation, you probably want to leave
+# this value as "orchestration"
+catalog_type = orchestration
+
+# The name of a region for orchestration. If empty or commented-out, the value
+# of identity.region is used instead. If no such region is found in the service
+# catalog, the first found one is used.
+#region = RegionOne
+
# Status change wait interval
build_interval = 1
@@ -395,3 +430,7 @@
log_check_interval = 60
# The default number of threads created while stress test
default_thread_number_per_action=4
+
+[debug]
+# Enable diagnostic commands
+enable = True
diff --git a/tempest/api/README.rst b/tempest/api/README.rst
index 9d8dc10..9eac19d 100644
--- a/tempest/api/README.rst
+++ b/tempest/api/README.rst
@@ -1,5 +1,5 @@
-Tempest Guide to API tests
-==========================
+Tempest Field Guide to API tests
+================================
What are these tests?
diff --git a/tempest/api/compute/admin/test_aggregates.py b/tempest/api/compute/admin/test_aggregates.py
index 0bb0460..a5dceca 100644
--- a/tempest/api/compute/admin/test_aggregates.py
+++ b/tempest/api/compute/admin/test_aggregates.py
@@ -61,12 +61,12 @@
# Create and delete an aggregate.
aggregate_name = rand_name(self.aggregate_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name)
- self.assertEquals(200, resp.status)
- self.assertEquals(aggregate_name, aggregate['name'])
- self.assertEquals(None, aggregate['availability_zone'])
+ self.assertEqual(200, resp.status)
+ self.assertEqual(aggregate_name, aggregate['name'])
+ self.assertEqual(None, aggregate['availability_zone'])
resp, _ = self.client.delete_aggregate(aggregate['id'])
- self.assertEquals(200, resp.status)
+ self.assertEqual(200, resp.status)
self.client.wait_for_resource_deletion(aggregate['id'])
@attr(type='gate')
@@ -75,12 +75,12 @@
aggregate_name = rand_name(self.aggregate_name_prefix)
az_name = rand_name(self.az_name_prefix)
resp, aggregate = self.client.create_aggregate(aggregate_name, az_name)
- self.assertEquals(200, resp.status)
- self.assertEquals(aggregate_name, aggregate['name'])
- self.assertEquals(az_name, aggregate['availability_zone'])
+ self.assertEqual(200, resp.status)
+ self.assertEqual(aggregate_name, aggregate['name'])
+ self.assertEqual(az_name, aggregate['availability_zone'])
resp, _ = self.client.delete_aggregate(aggregate['id'])
- self.assertEquals(200, resp.status)
+ self.assertEqual(200, resp.status)
self.client.wait_for_resource_deletion(aggregate['id'])
@attr(type='gate')
@@ -91,7 +91,7 @@
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
resp, aggregates = self.client.list_aggregates()
- self.assertEquals(200, resp.status)
+ self.assertEqual(200, resp.status)
self.assertIn((aggregate['id'], aggregate['availability_zone']),
map(lambda x: (x['id'], x['availability_zone']),
aggregates))
@@ -104,10 +104,10 @@
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
resp, body = self.client.get_aggregate(aggregate['id'])
- self.assertEquals(200, resp.status)
- self.assertEquals(aggregate['name'], body['name'])
- self.assertEquals(aggregate['availability_zone'],
- body['availability_zone'])
+ self.assertEqual(200, resp.status)
+ self.assertEqual(aggregate['name'], body['name'])
+ self.assertEqual(aggregate['availability_zone'],
+ body['availability_zone'])
@attr(type=['negative', 'gate'])
def test_aggregate_create_as_user(self):
@@ -166,17 +166,17 @@
self.addCleanup(self.client.delete_aggregate, aggregate['id'])
resp, body = self.client.add_host(aggregate['id'], self.host)
- self.assertEquals(200, resp.status)
- self.assertEquals(aggregate_name, body['name'])
- self.assertEquals(aggregate['availability_zone'],
- body['availability_zone'])
+ self.assertEqual(200, resp.status)
+ self.assertEqual(aggregate_name, body['name'])
+ self.assertEqual(aggregate['availability_zone'],
+ body['availability_zone'])
self.assertIn(self.host, body['hosts'])
resp, body = self.client.remove_host(aggregate['id'], self.host)
- self.assertEquals(200, resp.status)
- self.assertEquals(aggregate_name, body['name'])
- self.assertEquals(aggregate['availability_zone'],
- body['availability_zone'])
+ self.assertEqual(200, resp.status)
+ self.assertEqual(aggregate_name, body['name'])
+ self.assertEqual(aggregate['availability_zone'],
+ body['availability_zone'])
self.assertNotIn(self.host, body['hosts'])
@attr(type='gate')
@@ -191,10 +191,10 @@
resp, aggregates = self.client.list_aggregates()
aggs = filter(lambda x: x['id'] == aggregate['id'], aggregates)
- self.assertEquals(1, len(aggs))
+ self.assertEqual(1, len(aggs))
agg = aggs[0]
- self.assertEquals(aggregate_name, agg['name'])
- self.assertEquals(None, agg['availability_zone'])
+ self.assertEqual(aggregate_name, agg['name'])
+ self.assertEqual(None, agg['availability_zone'])
self.assertIn(self.host, agg['hosts'])
@attr(type='gate')
@@ -208,8 +208,8 @@
self.addCleanup(self.client.remove_host, aggregate['id'], self.host)
resp, body = self.client.get_aggregate(aggregate['id'])
- self.assertEquals(aggregate_name, body['name'])
- self.assertEquals(None, body['availability_zone'])
+ self.assertEqual(aggregate_name, body['name'])
+ self.assertEqual(None, body['availability_zone'])
self.assertIn(self.host, body['hosts'])
@attr(type='gate')
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index db5a5bb..b693227 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -136,8 +136,8 @@
# Delete the flavor
new_flavor_id = flavor['id']
resp_delete, body = self.client.delete_flavor(new_flavor_id)
- self.assertEquals(200, resp.status)
- self.assertEquals(202, resp_delete.status)
+ self.assertEqual(200, resp.status)
+ self.assertEqual(202, resp_delete.status)
# Deleted flavors can be seen via detailed GET
resp, flavor = self.client.get_flavor_details(new_flavor_id)
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs.py b/tempest/api/compute/admin/test_flavors_extra_specs.py
index ace77a6..e1e75cb 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs.py
@@ -102,7 +102,7 @@
self.flavor['id'])
self.assertEqual(resp.status, 200)
for key in specs:
- self.assertEquals(body[key], specs[key])
+ self.assertEqual(body[key], specs[key])
@attr(type=['negative', 'gate'])
def test_flavor_non_admin_unset_keys(self):
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index 2f0ed6b..97fbd8b 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -166,7 +166,7 @@
def test_delete_image_id_is_over_35_character_limit(self):
# Return an error while trying to delete image with id over limit
self.assertRaises(exceptions.NotFound, self.client.delete_image,
- '11a22b9-120q-5555-cc11-00ab112223gj-3fac')
+ '11a22b9-12a9-5555-cc11-00ab112223fa-3fac')
class ImagesTestXML(ImagesTestJSON):
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index 3ff2538..1dff806 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -81,7 +81,7 @@
# Update the server with a new name
resp, server = self.client.update_server(server['id'],
name='newname')
- self.assertEquals(200, resp.status)
+ self.assertEqual(200, resp.status)
self.client.wait_for_server_status(server['id'], 'ACTIVE')
# Verify the name of the server has changed
diff --git a/tempest/api/compute/test_live_block_migration.py b/tempest/api/compute/test_live_block_migration.py
index 84fd653..7c60859 100644
--- a/tempest/api/compute/test_live_block_migration.py
+++ b/tempest/api/compute/test_live_block_migration.py
@@ -110,7 +110,7 @@
target_host = self._get_host_other_than(actual_host)
self._migrate_server_to(server_id, target_host)
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
- self.assertEquals(target_host, self._get_host_for_server(server_id))
+ self.assertEqual(target_host, self._get_host_for_server(server_id))
@testtools.skipIf(not CONF.compute.live_migration_available,
'Live migration not available')
@@ -122,7 +122,7 @@
self.assertRaises(exceptions.BadRequest, self._migrate_server_to,
server_id, target_host)
- self.assertEquals('ACTIVE', self._get_server_status(server_id))
+ self.assertEqual('ACTIVE', self._get_server_status(server_id))
@testtools.skipIf(not CONF.compute.live_migration_available or
not CONF.compute.use_block_migration_for_live_migration,
@@ -153,7 +153,7 @@
self._migrate_server_to(server_id, target_host)
self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
- self.assertEquals(target_host, self._get_host_for_server(server_id))
+ self.assertEqual(target_host, self._get_host_for_server(server_id))
@classmethod
def tearDownClass(cls):
diff --git a/tempest/api/identity/admin/test_roles.py b/tempest/api/identity/admin/test_roles.py
index ac145c6..c234efd 100644
--- a/tempest/api/identity/admin/test_roles.py
+++ b/tempest/api/identity/admin/test_roles.py
@@ -171,7 +171,7 @@
user['id'], role['id'])
resp, body = self.client.remove_user_role(tenant['id'], user['id'],
user_role['id'])
- self.assertEquals(resp['status'], '204')
+ self.assertEqual(resp['status'], '204')
@attr(type='gate')
def test_remove_user_role_by_unauthorized_user(self):
diff --git a/tempest/api/identity/admin/test_services.py b/tempest/api/identity/admin/test_services.py
index 2be0c29..508c177 100644
--- a/tempest/api/identity/admin/test_services.py
+++ b/tempest/api/identity/admin/test_services.py
@@ -50,7 +50,7 @@
self.assertTrue(resp['status'].startswith('2'))
# verifying the existence of service created
self.assertIn('id', fetched_service)
- self.assertEquals(fetched_service['id'], service_data['id'])
+ self.assertEqual(fetched_service['id'], service_data['id'])
self.assertIn('name', fetched_service)
self.assertEqual(fetched_service['name'], service_data['name'])
self.assertIn('type', fetched_service)
diff --git a/tempest/api/identity/admin/test_users.py b/tempest/api/identity/admin/test_users.py
index 3455b5d..057e633 100644
--- a/tempest/api/identity/admin/test_users.py
+++ b/tempest/api/identity/admin/test_users.py
@@ -109,9 +109,9 @@
resp, user = self.client.create_user(alt_user2, self.alt_password,
self.data.tenant['id'],
self.alt_email)
- self.assertEquals('200', resp['status'])
+ self.assertEqual('200', resp['status'])
resp, body = self.client.delete_user(user['id'])
- self.assertEquals('204', resp['status'])
+ self.assertEqual('204', resp['status'])
@attr(type=['negative', 'gate'])
def test_delete_users_by_unauthorized_user(self):
@@ -236,7 +236,7 @@
resp, user1 = self.client.create_user(alt_tenant_user1, 'password1',
self.data.tenant['id'],
'user1@123')
- self.assertEquals('200', resp['status'])
+ self.assertEqual('200', resp['status'])
user_ids.append(user1['id'])
self.data.users.append(user1)
@@ -244,7 +244,7 @@
resp, user2 = self.client.create_user(alt_tenant_user2, 'password2',
self.data.tenant['id'],
'user2@123')
- self.assertEquals('200', resp['status'])
+ self.assertEqual('200', resp['status'])
user_ids.append(user2['id'])
self.data.users.append(user2)
# List of users for the respective tenant ID
@@ -273,22 +273,22 @@
user_ids.append(user['id'])
resp, role = self.client.assign_user_role(tenant['id'], user['id'],
role['id'])
- self.assertEquals('200', resp['status'])
+ self.assertEqual('200', resp['status'])
alt_user2 = rand_name('second_user_')
resp, second_user = self.client.create_user(alt_user2, 'password1',
self.data.tenant['id'],
'user2@123')
- self.assertEquals('200', resp['status'])
+ self.assertEqual('200', resp['status'])
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.assertEquals('200', resp['status'])
+ self.assertEqual('200', resp['status'])
# List of users with roles for the respective tenant ID
resp, body = self.client.list_users_for_tenant(self.data.tenant['id'])
- self.assertEquals('200', resp['status'])
+ self.assertEqual('200', resp['status'])
for i in body:
fetched_user_ids.append(i['id'])
# verifying the user Id in the list
diff --git a/tempest/api/identity/admin/v3/test_credentials.py b/tempest/api/identity/admin/v3/test_credentials.py
index efd2f83..cda5863 100644
--- a/tempest/api/identity/admin/v3/test_credentials.py
+++ b/tempest/api/identity/admin/v3/test_credentials.py
@@ -112,8 +112,7 @@
if c not in fetched_cred_ids]
self.assertEqual(0, len(missing_creds),
"Failed to find cred %s in fetched list" %
- ', '.join(m_cred for m_cred
- in missing_creds))
+ ', '.join(m_cred for m_cred in missing_creds))
class CredentialsTestXML(CredentialsTestJSON):
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index bf7a554..50e9702 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -116,7 +116,7 @@
self.assertEqual(0, len(missing_projects),
"Failed to find project %s in fetched list" %
', '.join(m_project for m_project
- in missing_projects))
+ in missing_projects))
class UsersV3TestXML(UsersV3TestJSON):
diff --git a/tempest/api/image/v1/test_image_members.py b/tempest/api/image/v1/test_image_members.py
index 29bcaf4..fcbde50 100644
--- a/tempest/api/image/v1/test_image_members.py
+++ b/tempest/api/image/v1/test_image_members.py
@@ -42,7 +42,7 @@
disk_format='raw',
is_public=True,
data=image_file)
- self.assertEquals(201, resp.status)
+ self.assertEqual(201, resp.status)
image_id = image['id']
return image_id
@@ -50,9 +50,9 @@
def test_add_image_member(self):
image = self._create_image()
resp = self.client.add_member(self.tenants[0], image)
- self.assertEquals(204, resp.status)
+ self.assertEqual(204, resp.status)
resp, body = self.client.get_image_membership(image)
- self.assertEquals(200, resp.status)
+ self.assertEqual(200, resp.status)
members = body['members']
members = map(lambda x: x['member_id'], members)
self.assertIn(self.tenants[0], members)
@@ -61,12 +61,12 @@
def test_get_shared_images(self):
image = self._create_image()
resp = self.client.add_member(self.tenants[0], image)
- self.assertEquals(204, resp.status)
+ self.assertEqual(204, resp.status)
share_image = self._create_image()
resp = self.client.add_member(self.tenants[0], share_image)
- self.assertEquals(204, resp.status)
+ self.assertEqual(204, resp.status)
resp, body = self.client.get_shared_images(self.tenants[0])
- self.assertEquals(200, resp.status)
+ self.assertEqual(200, resp.status)
images = body['shared_images']
images = map(lambda x: x['image_id'], images)
self.assertIn(share_image, images)
@@ -76,10 +76,10 @@
def test_remove_member(self):
image_id = self._create_image()
resp = self.client.add_member(self.tenants[0], image_id)
- self.assertEquals(204, resp.status)
+ self.assertEqual(204, resp.status)
resp = self.client.delete_member(self.tenants[0], image_id)
- self.assertEquals(204, resp.status)
+ self.assertEqual(204, resp.status)
resp, body = self.client.get_image_membership(image_id)
- self.assertEquals(200, resp.status)
+ self.assertEqual(200, resp.status)
members = body['members']
- self.assertEquals(0, len(members))
+ self.assertEqual(0, len(members))
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 3ae718c..4a4bf60 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -58,9 +58,15 @@
cls.ports = []
cls.pools = []
cls.vips = []
+ cls.members = []
+ cls.health_monitors = []
@classmethod
def tearDownClass(cls):
+ for health_monitor in cls.health_monitors:
+ cls.client.delete_health_monitor(health_monitor['id'])
+ for member in cls.members:
+ cls.client.delete_member(member['id'])
for vip in cls.vips:
cls.client.delete_vip(vip['id'])
for pool in cls.pools:
@@ -135,3 +141,23 @@
vip = body['vip']
cls.vips.append(vip)
return vip
+
+ @classmethod
+ def create_member(cls, protocol_port, pool):
+ """Wrapper utility that returns a test member."""
+ resp, body = cls.client.create_member("10.0.9.46",
+ protocol_port,
+ pool['id'])
+ member = body['member']
+ cls.members.append(member)
+ return member
+
+ @classmethod
+ def create_health_monitor(cls, delay, max_retries, Type, timeout):
+ """Wrapper utility that returns a test health monitor."""
+ resp, body = cls.client.create_health_monitor(delay,
+ max_retries,
+ Type, timeout)
+ health_monitor = body['health_monitor']
+ cls.health_monitors.append(health_monitor)
+ return health_monitor
diff --git a/tempest/api/network/test_load_balancer.py b/tempest/api/network/test_load_balancer.py
index 3880f4f..62017dc 100644
--- a/tempest/api/network/test_load_balancer.py
+++ b/tempest/api/network/test_load_balancer.py
@@ -34,6 +34,9 @@
delete vIP
update pool
delete pool
+ show pool
+ list pool
+ health monitoring operations
"""
@classmethod
@@ -47,6 +50,8 @@
cls.pool = cls.create_pool(pool_name, "ROUND_ROBIN",
"HTTP", cls.subnet)
cls.vip = cls.create_vip(vip_name, "HTTP", 80, cls.subnet, cls.pool)
+ cls.member = cls.create_member(80, cls.pool)
+ cls.health_monitor = cls.create_health_monitor(4, 3, "TCP", 1)
@attr(type='smoke')
def test_list_vips(self):
@@ -101,6 +106,105 @@
self.assertEqual(self.vip['id'], vip['id'])
self.assertEqual(self.vip['name'], vip['name'])
+ @attr(type='smoke')
+ def test_show_pool(self):
+ # Verifies the details of a pool
+ resp, body = self.client.show_pool(self.pool['id'])
+ self.assertEqual('200', resp['status'])
+ pool = body['pool']
+ self.assertEqual(self.pool['id'], pool['id'])
+ self.assertEqual(self.pool['name'], pool['name'])
+
+ @attr(type='smoke')
+ def test_list_pools(self):
+ # Verify the pool exists in the list of all pools
+ resp, body = self.client.list_pools()
+ self.assertEqual('200', resp['status'])
+ pools = body['pools']
+ self.assertIn(self.pool['id'], [p['id'] for p in pools])
+
+ @attr(type='smoke')
+ def test_list_members(self):
+ # Verify the member exists in the list of all members
+ resp, body = self.client.list_members()
+ self.assertEqual('200', resp['status'])
+ members = body['members']
+ self.assertIn(self.member['id'], [m['id'] for m in members])
+
+ @attr(type='smoke')
+ def test_create_update_delete_member(self):
+ # Creates a member
+ resp, body = self.client.create_member("10.0.9.46", 80,
+ self.pool['id'])
+ self.assertEqual('201', resp['status'])
+ member = body['member']
+ # Verification of member update
+ admin_state = [False, 'False']
+ resp, body = self.client.update_member(admin_state[0], member['id'])
+ self.assertEqual('200', resp['status'])
+ updated_member = body['member']
+ self.assertIn(updated_member['admin_state_up'], admin_state)
+ # Verification of member delete
+ resp, body = self.client.delete_member(member['id'])
+ self.assertEqual('204', resp['status'])
+
+ @attr(type='smoke')
+ def test_show_member(self):
+ # Verifies the details of a member
+ resp, body = self.client.show_member(self.member['id'])
+ self.assertEqual('200', resp['status'])
+ member = body['member']
+ self.assertEqual(self.member['id'], member['id'])
+ self.assertEqual(self.member['admin_state_up'],
+ member['admin_state_up'])
+
+ @attr(type='smoke')
+ def test_list_health_monitors(self):
+ # Verify the health monitor exists in the list of all health monitors
+ resp, body = self.client.list_health_monitors()
+ self.assertEqual('200', resp['status'])
+ health_monitors = body['health_monitors']
+ self.assertIn(self.health_monitor['id'],
+ [h['id'] for h in health_monitors])
+
+ @attr(type='smoke')
+ def test_create_update_delete_health_monitor(self):
+ # Creates a health_monitor
+ resp, body = self.client.create_health_monitor(4, 3, "TCP", 1)
+ self.assertEqual('201', resp['status'])
+ health_monitor = body['health_monitor']
+ # Verification of health_monitor update
+ admin_state = [False, 'False']
+ resp, body = self.client.update_health_monitor(admin_state[0],
+ health_monitor['id'])
+ self.assertEqual('200', resp['status'])
+ updated_health_monitor = body['health_monitor']
+ self.assertIn(updated_health_monitor['admin_state_up'], admin_state)
+ # Verification of health_monitor delete
+ resp, body = self.client.delete_health_monitor(health_monitor['id'])
+ self.assertEqual('204', resp['status'])
+
+ @attr(type='smoke')
+ def test_show_health_monitor(self):
+ # Verifies the details of a health_monitor
+ resp, body = self.client.show_health_monitor(self.health_monitor['id'])
+ self.assertEqual('200', resp['status'])
+ health_monitor = body['health_monitor']
+ self.assertEqual(self.health_monitor['id'], health_monitor['id'])
+ self.assertEqual(self.health_monitor['admin_state_up'],
+ health_monitor['admin_state_up'])
+
+ @attr(type='smoke')
+ def test_associate_disassociate_health_monitor_with_pool(self):
+ # Verify that a health monitor can be associated with a pool
+ resp, body = (self.client.associate_health_monitor_with_pool
+ (self.health_monitor['id'], self.pool['id']))
+ self.assertEqual('201', resp['status'])
+ # Verify that a health monitor can be disassociated from a pool
+ resp, body = (self.client.disassociate_health_monitor_with_pool
+ (self.health_monitor['id'], self.pool['id']))
+ self.assertEqual('204', resp['status'])
+
class LoadBalancerXML(LoadBalancerJSON):
_interface = 'xml'
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index b443933..d4201ee 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -59,7 +59,7 @@
params = {'limit': limit}
resp, container_list = \
self.account_client.list_account_containers(params=params)
- self.assertEquals(len(container_list), limit)
+ self.assertEqual(len(container_list), limit)
@attr(type='smoke')
def test_list_containers_with_marker(self):
@@ -70,11 +70,11 @@
params = {'marker': self.containers[-1]}
resp, container_list = \
self.account_client.list_account_containers(params=params)
- self.assertEquals(len(container_list), 0)
+ self.assertEqual(len(container_list), 0)
params = {'marker': self.containers[self.containers_count / 2]}
resp, container_list = \
self.account_client.list_account_containers(params=params)
- self.assertEquals(len(container_list), self.containers_count / 2 - 1)
+ self.assertEqual(len(container_list), self.containers_count / 2 - 1)
@attr(type='smoke')
def test_list_containers_with_end_marker(self):
@@ -85,11 +85,11 @@
params = {'end_marker': self.containers[0]}
resp, container_list = \
self.account_client.list_account_containers(params=params)
- self.assertEquals(len(container_list), 0)
+ self.assertEqual(len(container_list), 0)
params = {'end_marker': self.containers[self.containers_count / 2]}
resp, container_list = \
self.account_client.list_account_containers(params=params)
- self.assertEquals(len(container_list), self.containers_count / 2)
+ self.assertEqual(len(container_list), self.containers_count / 2)
@attr(type='smoke')
def test_list_containers_with_limit_and_marker(self):
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index 12b03b5..70fe1a3 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -34,7 +34,7 @@
self.assertEqual(202, resp.status)
self.client.wait_for_resource_deletion(volume_id)
- def _volume_create_get_delete(self, **kwargs):
+ def _volume_create_get_update_delete(self, **kwargs):
# Create a volume, Get it's details and Delete the volume
volume = {}
v_name = rand_name('Volume')
@@ -74,6 +74,29 @@
if 'imageRef' not in kwargs:
self.assertEqual(fetched_volume['bootable'], False)
+ # Update Volume
+ new_v_name = rand_name('new-Volume')
+ new_desc = 'This is the new description of volume'
+ resp, update_volume = \
+ self.client.update_volume(volume['id'],
+ display_name=new_v_name,
+ display_description=new_desc)
+ # Assert response body for update_volume method
+ self.assertEqual(200, resp.status)
+ self.assertEqual(new_v_name, update_volume['display_name'])
+ self.assertEqual(new_desc, update_volume['display_description'])
+ # Assert response body for get_volume method
+ resp, updated_volume = self.client.get_volume(volume['id'])
+ self.assertEqual(200, resp.status)
+ self.assertEqual(volume['id'], updated_volume['id'])
+ self.assertEqual(new_v_name, updated_volume['display_name'])
+ self.assertEqual(new_desc, updated_volume['display_description'])
+ self.assertEqual(metadata, updated_volume['metadata'])
+ if 'imageRef' in kwargs:
+ self.assertEqual(updated_volume['bootable'], True)
+ if 'imageRef' not in kwargs:
+ self.assertEqual(updated_volume['bootable'], False)
+
@attr(type='gate')
def test_volume_get_metadata_none(self):
# Create a volume without passing metadata, get details, and delete
@@ -94,19 +117,20 @@
self.assertEqual(fetched_volume['metadata'], {})
@attr(type='smoke')
- def test_volume_create_get_delete(self):
- self._volume_create_get_delete()
+ def test_volume_create_get_update_delete(self):
+ self._volume_create_get_update_delete()
@attr(type='smoke')
@services('image')
- def test_volume_create_get_delete_from_image(self):
- self._volume_create_get_delete(imageRef=self.config.compute.image_ref)
+ def test_volume_create_get_update_delete_from_image(self):
+ self._volume_create_get_update_delete(imageRef=self.
+ config.compute.image_ref)
@attr(type='gate')
- def test_volume_create_get_delete_as_clone(self):
+ def test_volume_create_get_update_delete_as_clone(self):
origin = self.create_volume(size=1,
display_name="Volume Origin")
- self._volume_create_get_delete(source_volid=origin['id'])
+ self._volume_create_get_update_delete(source_volid=origin['id'])
class VolumesGetTestXML(VolumesGetTest):
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 0328b44..6b186e5 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -38,7 +38,7 @@
super(VolumesSnapshotTest, cls).tearDownClass()
@attr(type='gate')
- def test_snapshot_create_get_list_delete(self):
+ def test_snapshot_create_get_list_update_delete(self):
# Create a snapshot
s_name = rand_name('snap')
snapshot = self.create_snapshot(self.volume_origin['id'],
@@ -58,6 +58,24 @@
snaps_data = [(f['id'], f['display_name']) for f in snaps_list]
self.assertIn(tracking_data, snaps_data)
+ # Updates snapshot with new values
+ new_s_name = rand_name('new-snap')
+ new_desc = 'This is the new description of snapshot.'
+ resp, update_snapshot = \
+ self.snapshots_client.update_snapshot(snapshot['id'],
+ display_name=new_s_name,
+ display_description=new_desc)
+ # Assert response body for update_snapshot method
+ self.assertEqual(200, resp.status)
+ self.assertEqual(new_s_name, update_snapshot['display_name'])
+ self.assertEqual(new_desc, update_snapshot['display_description'])
+ # Assert response body for get_snapshot method
+ resp, updated_snapshot = \
+ self.snapshots_client.get_snapshot(snapshot['id'])
+ self.assertEqual(200, resp.status)
+ self.assertEqual(new_s_name, updated_snapshot['display_name'])
+ self.assertEqual(new_desc, updated_snapshot['display_description'])
+
# Delete the snapshot
self.snapshots_client.delete_snapshot(snapshot['id'])
self.assertEqual(200, resp.status)
diff --git a/tempest/cli/README.rst b/tempest/cli/README.rst
index f86adf3..dcd940b 100644
--- a/tempest/cli/README.rst
+++ b/tempest/cli/README.rst
@@ -1,5 +1,5 @@
-Tempest Guide to CLI tests
-==========================
+Tempest Field Guide to CLI tests
+================================
What are these tests?
diff --git a/tempest/cli/__init__.py b/tempest/cli/__init__.py
index cbb8d08..b082b1e 100644
--- a/tempest/cli/__init__.py
+++ b/tempest/cli/__init__.py
@@ -95,9 +95,11 @@
"""Executes given command with auth attributes appended."""
# TODO(jogo) make admin=False work
creds = ('--os-username %s --os-tenant-name %s --os-password %s '
- '--os-auth-url %s ' % (self.identity.admin_username,
- self.identity.admin_tenant_name, self.identity.admin_password,
- self.identity.uri))
+ '--os-auth-url %s ' %
+ (self.identity.admin_username,
+ self.identity.admin_tenant_name,
+ self.identity.admin_password,
+ self.identity.uri))
flags = creds + ' ' + flags
return self.cmd(cmd, action, flags, params, fail_ok)
diff --git a/tempest/cli/simple_read_only/test_cinder.py b/tempest/cli/simple_read_only/test_cinder.py
index 21acae8..3ff997a 100644
--- a/tempest/cli/simple_read_only/test_cinder.py
+++ b/tempest/cli/simple_read_only/test_cinder.py
@@ -114,4 +114,7 @@
self.cinder('list', flags='--retries 3')
def test_cinder_region_list(self):
- self.cinder('list', flags='--os-region-name ' + self.identity.region)
+ region = self.config.volume.region
+ if not region:
+ region = self.config.identity.region
+ self.cinder('list', flags='--os-region-name ' + region)
diff --git a/tempest/common/commands.py b/tempest/common/commands.py
new file mode 100644
index 0000000..4fc85b6
--- /dev/null
+++ b/tempest/common/commands.py
@@ -0,0 +1,76 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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 shlex
+import subprocess
+
+from tempest.openstack.common import log as logging
+
+LOG = logging.getLogger(__name__)
+
+# NOTE(afazekas):
+# These commands assumes the tempest node is the same as
+# the only one service node. all-in-one installation.
+
+
+def sudo_cmd_call(cmd):
+ args = shlex.split(cmd)
+ subprocess_args = {'stdout': subprocess.PIPE,
+ 'stderr': subprocess.STDOUT}
+ try:
+ proc = subprocess.Popen(['/usr/bin/sudo'] + args, **subprocess_args)
+ return proc.communicate()[0]
+ if proc.returncode != 0:
+ LOG.error(cmd + "returned with: " +
+ proc.returncode + "exit status")
+ except subprocess.CalledProcessError as e:
+ LOG.error("command output:\n%s" % e.output)
+
+
+def ip_addr_raw():
+ return sudo_cmd_call("ip a")
+
+
+def ip_route_raw():
+ return sudo_cmd_call("ip r")
+
+
+def ip_ns_raw():
+ return sudo_cmd_call("ip netns list")
+
+
+def iptables_raw(table):
+ return sudo_cmd_call("iptables -v -S -t " + table)
+
+
+def ip_ns_list():
+ return ip_ns_raw().split()
+
+
+def ip_ns_exec(ns, cmd):
+ return sudo_cmd_call(" ".join(("ip netns exec", ns, cmd)))
+
+
+def ip_ns_addr(ns):
+ return ip_ns_exec(ns, "ip a")
+
+
+def ip_ns_route(ns):
+ return ip_ns_exec(ns, "ip r")
+
+
+def iptables_ns(ns, table):
+ return ip_ns_exec(ns, "iptables -v -S -t " + table)
diff --git a/tempest/common/debug.py b/tempest/common/debug.py
new file mode 100644
index 0000000..69c933c
--- /dev/null
+++ b/tempest/common/debug.py
@@ -0,0 +1,41 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.common import commands
+from tempest import config
+
+from tempest.openstack.common import log as logging
+
+LOG = logging.getLogger(__name__)
+
+tables = ['filter', 'nat', 'mangle']
+
+
+def log_ip_ns():
+ if not config.TempestConfig().debug.enable:
+ return
+ LOG.info("Host Addr:\n" + commands.ip_addr_raw())
+ LOG.info("Host Route:\n" + commands.ip_route_raw())
+ for table in ['filter', 'nat', 'mangle']:
+ LOG.info('Host %s table:\n%s', table, commands.iptables_raw(table))
+ ns_list = commands.ip_ns_list()
+ LOG.info("Host ns list" + str(ns_list))
+ for ns in ns_list:
+ LOG.info("ns(%s) Addr:\n%s", ns, commands.ip_ns_addr(ns))
+ LOG.info("ns(%s) Route:\n%s", ns, commands.ip_ns_route(ns))
+ for table in ['filter', 'nat', 'mangle']:
+ LOG.info('ns(%s) table(%s):\n%s', ns, table,
+ commands.iptables_ns(ns, table))
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index 8dfff6e..81393a9 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -49,7 +49,17 @@
self.service = None
self.token = None
self.base_url = None
- self.region = {'compute': self.config.identity.region}
+ self.region = {}
+ for cfgname in dir(self.config):
+ # Find all config.FOO.catalog_type and assume FOO is a service.
+ cfg = getattr(self.config, cfgname)
+ catalog_type = getattr(cfg, 'catalog_type', None)
+ if not catalog_type:
+ continue
+ service_region = getattr(cfg, 'region', None)
+ if not service_region:
+ service_region = self.config.identity.region
+ self.region[catalog_type] = service_region
self.endpoint_url = 'publicURL'
self.headers = {'Content-Type': 'application/%s' % self.TYPE,
'Accept': 'application/%s' % self.TYPE}
diff --git a/tempest/config.py b/tempest/config.py
index b386968..8058753 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -44,7 +44,10 @@
help='Full URI of the OpenStack Identity API (Keystone), v3'),
cfg.StrOpt('region',
default='RegionOne',
- help="The identity region name to use."),
+ help="The identity region name to use. Also used as the other "
+ "services' region name unless they are set explicitly. "
+ "If no such region is found in the service catalog, the "
+ "first found one is used."),
cfg.StrOpt('username',
default='demo',
help="Username to use for Nova API requests."),
@@ -200,6 +203,12 @@
cfg.StrOpt('catalog_type',
default='compute',
help="Catalog type of the Compute service."),
+ cfg.StrOpt('region',
+ default='',
+ help="The compute region name to use. If empty, the value "
+ "of identity.region is used instead. If no such region "
+ "is found in the service catalog, the first found one is "
+ "used."),
cfg.StrOpt('path_to_private_key',
default=None,
help="Path to a private key file for SSH access to remote "
@@ -255,6 +264,12 @@
cfg.StrOpt('catalog_type',
default='image',
help='Catalog type of the Image service.'),
+ cfg.StrOpt('region',
+ default='',
+ help="The image region name to use. If empty, the value "
+ "of identity.region is used instead. If no such region "
+ "is found in the service catalog, the first found one is "
+ "used."),
cfg.StrOpt('http_image',
default='http://download.cirros-cloud.net/0.3.1/'
'cirros-0.3.1-x86_64-uec.tar.gz',
@@ -275,6 +290,12 @@
cfg.StrOpt('catalog_type',
default='network',
help='Catalog type of the Neutron service.'),
+ cfg.StrOpt('region',
+ default='',
+ help="The network region name to use. If empty, the value "
+ "of identity.region is used instead. If no such region "
+ "is found in the service catalog, the first found one is "
+ "used."),
cfg.StrOpt('tenant_network_cidr',
default="10.100.0.0/16",
help="The cidr block to allocate tenant networks from"),
@@ -315,6 +336,12 @@
cfg.StrOpt('catalog_type',
default='Volume',
help="Catalog type of the Volume Service"),
+ cfg.StrOpt('region',
+ default='',
+ help="The volume region name to use. If empty, the value "
+ "of identity.region is used instead. If no such region "
+ "is found in the service catalog, the first found one is "
+ "used."),
cfg.BoolOpt('multi_backend_enabled',
default=False,
help="Runs Cinder multi-backend test (requires 2 backends)"),
@@ -349,6 +376,12 @@
cfg.StrOpt('catalog_type',
default='object-store',
help="Catalog type of the Object-Storage service."),
+ cfg.StrOpt('region',
+ default='',
+ help="The object-storage region name to use. If empty, the "
+ "value of identity.region is used instead. If no such "
+ "region is found in the service catalog, the first found "
+ "one is used."),
cfg.StrOpt('container_sync_timeout',
default=120,
help="Number of seconds to time on waiting for a container"
@@ -380,6 +413,12 @@
cfg.StrOpt('catalog_type',
default='orchestration',
help="Catalog type of the Orchestration service."),
+ cfg.StrOpt('region',
+ default='',
+ help="The orchestration region name to use. If empty, the "
+ "value of identity.region is used instead. If no such "
+ "region is found in the service catalog, the first found "
+ "one is used."),
cfg.BoolOpt('allow_tenant_isolation',
default=False,
help="Allows test cases to create/destroy tenants and "
@@ -589,6 +628,21 @@
for opt in ServiceAvailableGroup:
conf.register_opt(opt, group='service_available')
+debug_group = cfg.OptGroup(name="debug",
+ title="Debug System")
+
+DebugGroup = [
+ cfg.BoolOpt('enable',
+ default=True,
+ help="Enable diagnostic commands"),
+]
+
+
+def register_debug_opts(conf):
+ conf.register_group(debug_group)
+ for opt in DebugGroup:
+ conf.register_opt(opt, group='debug')
+
@singleton
class TempestConfig:
diff --git a/tempest/scenario/README.rst b/tempest/scenario/README.rst
index 98b74e4..eea889a 100644
--- a/tempest/scenario/README.rst
+++ b/tempest/scenario/README.rst
@@ -1,5 +1,5 @@
-Tempest Guide to Scenario tests
-===============================
+Tempest Field Guide to Scenario tests
+=====================================
What are these tests?
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 21c37b9..9137b93 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -425,7 +425,7 @@
self.addCleanup(image_client.images.delete, image_id)
self.status_timeout(image_client.images, image_id, 'active')
snapshot_image = image_client.images.get(image_id)
- self.assertEquals(name, snapshot_image.name)
+ self.assertEqual(name, snapshot_image.name)
LOG.debug("Created snapshot image %s for server %s",
snapshot_image.name, server.name)
return snapshot_image
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 9d7086c..daa7d13 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -17,6 +17,7 @@
# under the License.
from tempest.api.network import common as net_common
+from tempest.common import debug
from tempest.common.utils.data_utils import rand_name
from tempest import config
from tempest.openstack.common import log as logging
@@ -202,21 +203,25 @@
self.assertIn(myrouter.name, seen_router_names)
self.assertIn(myrouter.id, seen_router_ids)
+ def _create_server(self, name, network):
+ tenant_id = network.tenant_id
+ keypair_name = self.keypairs[tenant_id].name
+ security_groups = [self.security_groups[tenant_id].name]
+ create_kwargs = {
+ 'nics': [
+ {'net-id': network.id},
+ ],
+ 'key_name': keypair_name,
+ 'security_groups': security_groups,
+ }
+ server = self.create_server(self.compute_client, name=name,
+ create_kwargs=create_kwargs)
+ return server
+
def _create_servers(self):
for i, network in enumerate(self.networks):
- tenant_id = network.tenant_id
name = rand_name('server-smoke-%d-' % i)
- keypair_name = self.keypairs[tenant_id].name
- security_groups = [self.security_groups[tenant_id].name]
- create_kwargs = {
- 'nics': [
- {'net-id': network.id},
- ],
- 'key_name': keypair_name,
- 'security_groups': security_groups,
- }
- server = self.create_server(self.compute_client, name=name,
- create_kwargs=create_kwargs)
+ server = self._create_server(name, network)
self.servers.append(server)
def _check_tenant_network_connectivity(self):
@@ -246,10 +251,17 @@
# key-based authentication by cloud-init.
ssh_login = self.config.compute.image_ssh_user
private_key = self.keypairs[self.tenant_id].private_key
- for server, floating_ips in self.floating_ips.iteritems():
- for floating_ip in floating_ips:
- ip_address = floating_ip.floating_ip_address
- self._check_vm_connectivity(ip_address, ssh_login, private_key)
+ try:
+ for server, floating_ips in self.floating_ips.iteritems():
+ for floating_ip in floating_ips:
+ ip_address = floating_ip.floating_ip_address
+ self._check_vm_connectivity(ip_address,
+ ssh_login,
+ private_key)
+ except Exception as exc:
+ LOG.exception(exc)
+ debug.log_ip_ns()
+ raise exc
@attr(type='smoke')
@services('compute', 'network')
@@ -259,6 +271,6 @@
self._create_networks()
self._check_networks()
self._create_servers()
- self._check_tenant_network_connectivity()
self._assign_floating_ips()
self._check_public_network_connectivity()
+ self._check_tenant_network_connectivity()
diff --git a/tempest/scenario/test_server_advanced_ops.py b/tempest/scenario/test_server_advanced_ops.py
index cf72cd4..9c50489 100644
--- a/tempest/scenario/test_server_advanced_ops.py
+++ b/tempest/scenario/test_server_advanced_ops.py
@@ -15,7 +15,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-from tempest.common.utils.data_utils import rand_name
from tempest.openstack.common import log as logging
from tempest.scenario import manager
from tempest.test import services
@@ -49,18 +48,7 @@
@services('compute')
def test_resize_server_confirm(self):
# We create an instance for use in this test
- i_name = rand_name('instance')
- flavor_id = self.config.compute.flavor_ref
- base_image_id = self.config.compute.image_ref
- self.instance = self.compute_client.servers.create(
- i_name, base_image_id, flavor_id)
- self.assertEqual(self.instance.name, i_name)
- self.set_resource('instance', self.instance)
- self.assertEqual(self.instance.status, 'BUILD')
- instance_id = self.get_resource('instance').id
- self.status_timeout(
- self.compute_client.servers, instance_id, 'ACTIVE')
- instance = self.get_resource('instance')
+ instance = self.create_server(self.compute_client)
instance_id = instance.id
resize_flavor = self.config.compute.flavor_ref_alt
LOG.debug("Resizing instance %s from flavor %s to flavor %s",
@@ -78,18 +66,7 @@
@services('compute')
def test_server_sequence_suspend_resume(self):
# We create an instance for use in this test
- i_name = rand_name('instance')
- flavor_id = self.config.compute.flavor_ref
- base_image_id = self.config.compute.image_ref
- self.instance = self.compute_client.servers.create(
- i_name, base_image_id, flavor_id)
- self.assertEqual(self.instance.name, i_name)
- self.set_resource('instance', self.instance)
- self.assertEqual(self.instance.status, 'BUILD')
- instance_id = self.get_resource('instance').id
- self.status_timeout(
- self.compute_client.servers, instance_id, 'ACTIVE')
- instance = self.get_resource('instance')
+ instance = self.create_server(self.compute_client)
instance_id = instance.id
LOG.debug("Suspending instance %s. Current status: %s",
instance_id, instance.status)
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index c5a4aaf..ab464e3 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -92,7 +92,7 @@
self.addCleanup(cleaner)
self._wait_for_volume_status(volume, 'available')
self._wait_for_volume_snapshot_status(snapshot, 'available')
- self.assertEquals(snapshot_name, snapshot.display_name)
+ self.assertEqual(snapshot_name, snapshot.display_name)
return snapshot
def _wait_for_volume_status(self, volume, status):
diff --git a/tempest/services/botoclients.py b/tempest/services/botoclients.py
index 66fb7af..a689c89 100644
--- a/tempest/services/botoclients.py
+++ b/tempest/services/botoclients.py
@@ -111,7 +111,10 @@
aws_secret = config.boto.aws_secret
purl = urlparse.urlparse(config.boto.ec2_url)
- region = boto.ec2.regioninfo.RegionInfo(name=config.identity.region,
+ region_name = config.compute.region
+ if not region_name:
+ region_name = config.identity.region
+ region = boto.ec2.regioninfo.RegionInfo(name=region_name,
endpoint=purl.hostname)
port = purl.port
if port is None:
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index bc0a6cf..369dd81 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -478,3 +478,123 @@
resp, body = self.put(uri, body=body, headers=self.headers)
body = json.loads(body)
return resp, body
+
+ def list_pools(self):
+ uri = '%s/lb/pools' % (self.uri_prefix)
+ resp, body = self.get(uri, self.headers)
+ body = json.loads(body)
+ return resp, body
+
+ def show_pool(self, uuid):
+ uri = '%s/lb/pools/%s' % (self.uri_prefix, uuid)
+ resp, body = self.get(uri, self.headers)
+ body = json.loads(body)
+ return resp, body
+
+ def list_members(self):
+ uri = '%s/lb/members' % (self.uri_prefix)
+ resp, body = self.get(uri, self.headers)
+ body = json.loads(body)
+ return resp, body
+
+ def create_member(self, address, protocol_port, pool_id):
+ post_body = {
+ "member": {
+ "protocol_port": protocol_port,
+ "pool_id": pool_id,
+ "address": address
+ }
+ }
+ body = json.dumps(post_body)
+ uri = '%s/lb/members' % (self.uri_prefix)
+ resp, body = self.post(uri, headers=self.headers, body=body)
+ body = json.loads(body)
+ return resp, body
+
+ def show_member(self, uuid):
+ uri = '%s/lb/members/%s' % (self.uri_prefix, uuid)
+ resp, body = self.get(uri, self.headers)
+ body = json.loads(body)
+ return resp, body
+
+ def delete_member(self, uuid):
+ uri = '%s/lb/members/%s' % (self.uri_prefix, uuid)
+ resp, body = self.delete(uri, self.headers)
+ return resp, body
+
+ def update_member(self, admin_state_up, member_id):
+ put_body = {
+ "member": {
+ "admin_state_up": admin_state_up
+ }
+ }
+ body = json.dumps(put_body)
+ uri = '%s/lb/members/%s' % (self.uri_prefix, member_id)
+ resp, body = self.put(uri, body=body, headers=self.headers)
+ body = json.loads(body)
+ return resp, body
+
+ def list_health_monitors(self):
+ uri = '%s/lb/health_monitors' % (self.uri_prefix)
+ resp, body = self.get(uri, self.headers)
+ body = json.loads(body)
+ return resp, body
+
+ def create_health_monitor(self, delay, max_retries, Type, timeout):
+ post_body = {
+ "health_monitor": {
+ "delay": delay,
+ "max_retries": max_retries,
+ "type": Type,
+ "timeout": timeout
+ }
+ }
+ body = json.dumps(post_body)
+ uri = '%s/lb/health_monitors' % (self.uri_prefix)
+ resp, body = self.post(uri, headers=self.headers, body=body)
+ body = json.loads(body)
+ return resp, body
+
+ def show_health_monitor(self, uuid):
+ uri = '%s/lb/health_monitors/%s' % (self.uri_prefix, uuid)
+ resp, body = self.get(uri, self.headers)
+ body = json.loads(body)
+ return resp, body
+
+ def delete_health_monitor(self, uuid):
+ uri = '%s/lb/health_monitors/%s' % (self.uri_prefix, uuid)
+ resp, body = self.delete(uri, self.headers)
+ return resp, body
+
+ def update_health_monitor(self, admin_state_up, uuid):
+ put_body = {
+ "health_monitor": {
+ "admin_state_up": admin_state_up
+ }
+ }
+ body = json.dumps(put_body)
+ uri = '%s/lb/health_monitors/%s' % (self.uri_prefix, uuid)
+ resp, body = self.put(uri, body=body, headers=self.headers)
+ body = json.loads(body)
+ return resp, body
+
+ def associate_health_monitor_with_pool(self, health_monitor_id,
+ pool_id):
+ post_body = {
+ "health_monitor": {
+ "id": health_monitor_id,
+ }
+ }
+ body = json.dumps(post_body)
+ uri = '%s/lb/pools/%s/health_monitors' % (self.uri_prefix,
+ pool_id)
+ resp, body = self.post(uri, headers=self.headers, body=body)
+ body = json.loads(body)
+ return resp, body
+
+ def disassociate_health_monitor_with_pool(self, health_monitor_id,
+ pool_id):
+ uri = '%s/lb/pools/%s/health_monitors/%s' % (self.uri_prefix, pool_id,
+ health_monitor_id)
+ resp, body = self.delete(uri, headers=self.headers)
+ return resp, body
diff --git a/tempest/services/network/xml/network_client.py b/tempest/services/network/xml/network_client.py
index 6881479..a9b5512 100755
--- a/tempest/services/network/xml/network_client.py
+++ b/tempest/services/network/xml/network_client.py
@@ -331,6 +331,103 @@
body = _root_tag_fetcher_and_xml_to_json_parse(body)
return resp, body
+ def list_members(self):
+ url = '%s/lb/members' % (self.uri_prefix)
+ resp, body = self.get(url, self.headers)
+ members = self._parse_array(etree.fromstring(body))
+ members = {"members": members}
+ return resp, members
+
+ def create_member(self, address, protocol_port, pool_id):
+ uri = '%s/lb/members' % (self.uri_prefix)
+ post_body = Element("member")
+ p1 = Element("address", address)
+ p2 = Element("protocol_port", protocol_port)
+ p3 = Element("pool_id", pool_id)
+ post_body.append(p1)
+ post_body.append(p2)
+ post_body.append(p3)
+ resp, body = self.post(uri, str(Document(post_body)), self.headers)
+ body = _root_tag_fetcher_and_xml_to_json_parse(body)
+ return resp, body
+
+ def delete_member(self, member_id):
+ uri = '%s/lb/members/%s' % (self.uri_prefix, str(member_id))
+ return self.delete(uri, self.headers)
+
+ def show_member(self, member_id):
+ uri = '%s/lb/members/%s' % (self.uri_prefix, str(member_id))
+ resp, body = self.get(uri, self.headers)
+ body = _root_tag_fetcher_and_xml_to_json_parse(body)
+ return resp, body
+
+ def update_member(self, admin_state_up, member_id):
+ uri = '%s/lb/members/%s' % (self.uri_prefix, str(member_id))
+ put_body = Element("member")
+ p2 = Element("admin_state_up", admin_state_up)
+ put_body.append(p2)
+ resp, body = self.put(uri, str(Document(put_body)), self.headers)
+ body = _root_tag_fetcher_and_xml_to_json_parse(body)
+ return resp, body
+
+ def list_health_monitors(self):
+ uri = '%s/lb/health_monitors' % (self.uri_prefix)
+ resp, body = self.get(uri, self.headers)
+ body = self._parse_array(etree.fromstring(body))
+ body = {"health_monitors": body}
+ return resp, body
+
+ def create_health_monitor(self, delay, max_retries, Type, timeout):
+ uri = '%s/lb/health_monitors' % (self.uri_prefix)
+ post_body = Element("health_monitor")
+ p1 = Element("delay", delay)
+ p2 = Element("max_retries", max_retries)
+ p3 = Element("type", Type)
+ p4 = Element("timeout", timeout)
+ post_body.append(p1)
+ post_body.append(p2)
+ post_body.append(p3)
+ post_body.append(p4)
+ resp, body = self.post(uri, str(Document(post_body)), self.headers)
+ body = _root_tag_fetcher_and_xml_to_json_parse(body)
+ return resp, body
+
+ def delete_health_monitor(self, uuid):
+ uri = '%s/lb/health_monitors/%s' % (self.uri_prefix, str(uuid))
+ return self.delete(uri, self.headers)
+
+ def show_health_monitor(self, uuid):
+ uri = '%s/lb/health_monitors/%s' % (self.uri_prefix, str(uuid))
+ resp, body = self.get(uri, self.headers)
+ body = _root_tag_fetcher_and_xml_to_json_parse(body)
+ return resp, body
+
+ def update_health_monitor(self, admin_state_up, uuid):
+ uri = '%s/lb/health_monitors/%s' % (self.uri_prefix, str(uuid))
+ put_body = Element("health_monitor")
+ p2 = Element("admin_state_up", admin_state_up)
+ put_body.append(p2)
+ resp, body = self.put(uri, str(Document(put_body)), self.headers)
+ body = _root_tag_fetcher_and_xml_to_json_parse(body)
+ return resp, body
+
+ def associate_health_monitor_with_pool(self, health_monitor_id,
+ pool_id):
+ uri = '%s/lb/pools/%s/health_monitors' % (self.uri_prefix,
+ pool_id)
+ post_body = Element("health_monitor")
+ p1 = Element("id", health_monitor_id,)
+ post_body.append(p1)
+ resp, body = self.post(uri, str(Document(post_body)), self.headers)
+ body = _root_tag_fetcher_and_xml_to_json_parse(body)
+ return resp, body
+
+ def disassociate_health_monitor_with_pool(self, health_monitor_id,
+ pool_id):
+ uri = '%s/lb/pools/%s/health_monitors/%s' % (self.uri_prefix, pool_id,
+ health_monitor_id)
+ return self.delete(uri, self.headers)
+
def _root_tag_fetcher_and_xml_to_json_parse(xml_returned_body):
body = ET.fromstring(xml_returned_body)
diff --git a/tempest/services/volume/json/snapshots_client.py b/tempest/services/volume/json/snapshots_client.py
index ce2da90..10ba3fd 100644
--- a/tempest/services/volume/json/snapshots_client.py
+++ b/tempest/services/volume/json/snapshots_client.py
@@ -76,6 +76,14 @@
body = json.loads(body)
return resp, body['snapshot']
+ def update_snapshot(self, snapshot_id, **kwargs):
+ """Updates a snapshot."""
+ put_body = json.dumps({'snapshot': kwargs})
+ resp, body = self.put('snapshots/%s' % snapshot_id, put_body,
+ self.headers)
+ body = json.loads(body)
+ return resp, body['snapshot']
+
# NOTE(afazekas): just for the wait function
def _get_snapshot_status(self, snapshot_id):
resp, body = self.get_snapshot(snapshot_id)
diff --git a/tempest/services/volume/json/volumes_client.py b/tempest/services/volume/json/volumes_client.py
index c35452e..32b6270 100644
--- a/tempest/services/volume/json/volumes_client.py
+++ b/tempest/services/volume/json/volumes_client.py
@@ -85,6 +85,14 @@
body = json.loads(body)
return resp, body['volume']
+ def update_volume(self, volume_id, **kwargs):
+ """Updates the Specified Volume."""
+ put_body = json.dumps({'volume': kwargs})
+ resp, body = self.put('volumes/%s' % volume_id, put_body,
+ self.headers)
+ body = json.loads(body)
+ return resp, body['volume']
+
def delete_volume(self, volume_id):
"""Deletes the Specified Volume."""
return self.delete("volumes/%s" % str(volume_id))
diff --git a/tempest/services/volume/xml/snapshots_client.py b/tempest/services/volume/xml/snapshots_client.py
index 3596017..b7ba56b 100644
--- a/tempest/services/volume/xml/snapshots_client.py
+++ b/tempest/services/volume/xml/snapshots_client.py
@@ -90,6 +90,16 @@
body = xml_to_json(etree.fromstring(body))
return resp, body
+ def update_snapshot(self, snapshot_id, **kwargs):
+ """Updates a snapshot."""
+ put_body = Element("snapshot", xmlns=XMLNS_11, **kwargs)
+
+ resp, body = self.put('snapshots/%s' % snapshot_id,
+ str(Document(put_body)),
+ self.headers)
+ body = xml_to_json(etree.fromstring(body))
+ return resp, body
+
# NOTE(afazekas): just for the wait function
def _get_snapshot_status(self, snapshot_id):
resp, body = self.get_snapshot(snapshot_id)
diff --git a/tempest/services/volume/xml/volumes_client.py b/tempest/services/volume/xml/volumes_client.py
index 9fa7a1e..7915637 100644
--- a/tempest/services/volume/xml/volumes_client.py
+++ b/tempest/services/volume/xml/volumes_client.py
@@ -151,6 +151,16 @@
body = xml_to_json(etree.fromstring(body))
return resp, body
+ def update_volume(self, volume_id, **kwargs):
+ """Updates the Specified Volume."""
+ put_body = Element("volume", xmlns=XMLNS_11, **kwargs)
+
+ resp, body = self.put('volumes/%s' % volume_id,
+ str(Document(put_body)),
+ self.headers)
+ body = xml_to_json(etree.fromstring(body))
+ return resp, body
+
def delete_volume(self, volume_id):
"""Deletes the Specified Volume."""
return self.delete("volumes/%s" % str(volume_id))
diff --git a/tempest/tests/README.rst b/tempest/tests/README.rst
index 4098686..33d321f 100644
--- a/tempest/tests/README.rst
+++ b/tempest/tests/README.rst
@@ -1,5 +1,5 @@
-Tempest Guide to Unit tests
-===========================
+Tempest Field Guide to Unit tests
+=================================
What are these tests?
---------------------
diff --git a/tempest/tests/test_wrappers.py b/tempest/tests/test_wrappers.py
index aeea98d..1a5af00 100644
--- a/tempest/tests/test_wrappers.py
+++ b/tempest/tests/test_wrappers.py
@@ -60,7 +60,7 @@
subprocess.call(['git', 'init'])
exit_code = subprocess.call('sh pretty_tox.sh tests.passing',
shell=True, stdout=DEVNULL, stderr=DEVNULL)
- self.assertEquals(exit_code, 0)
+ self.assertEqual(exit_code, 0)
@attr(type='smoke')
def test_pretty_tox_fails(self):
@@ -76,7 +76,7 @@
subprocess.call(['git', 'init'])
exit_code = subprocess.call('sh pretty_tox.sh', shell=True,
stdout=DEVNULL, stderr=DEVNULL)
- self.assertEquals(exit_code, 1)
+ self.assertEqual(exit_code, 1)
@attr(type='smoke')
def test_pretty_tox_serial(self):
@@ -88,7 +88,7 @@
os.chdir(self.directory)
exit_code = subprocess.call('sh pretty_tox_serial.sh tests.passing',
shell=True, stdout=DEVNULL, stderr=DEVNULL)
- self.assertEquals(exit_code, 0)
+ self.assertEqual(exit_code, 0)
@attr(type='smoke')
def test_pretty_tox_serial_fails(self):
@@ -100,4 +100,4 @@
os.chdir(self.directory)
exit_code = subprocess.call('sh pretty_tox_serial.sh', shell=True,
stdout=DEVNULL, stderr=DEVNULL)
- self.assertEquals(exit_code, 1)
+ self.assertEqual(exit_code, 1)
diff --git a/tempest/thirdparty/README.rst b/tempest/thirdparty/README.rst
index b775817..53cb54b 100644
--- a/tempest/thirdparty/README.rst
+++ b/tempest/thirdparty/README.rst
@@ -1,5 +1,5 @@
-Tempest Guide to Third Party API tests
-======================================
+Tempest Field Guide to Third Party API tests
+============================================
What are these tests?
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index a848fc9..7fab364 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -176,25 +176,25 @@
instance.add_tag('key1', value='value1')
tags = self.ec2_client.get_all_tags()
- self.assertEquals(tags[0].name, 'key1')
- self.assertEquals(tags[0].value, 'value1')
+ self.assertEqual(tags[0].name, 'key1')
+ self.assertEqual(tags[0].value, 'value1')
tags = self.ec2_client.get_all_tags(filters={'key': 'key1'})
- self.assertEquals(tags[0].name, 'key1')
- self.assertEquals(tags[0].value, 'value1')
+ self.assertEqual(tags[0].name, 'key1')
+ self.assertEqual(tags[0].value, 'value1')
tags = self.ec2_client.get_all_tags(filters={'value': 'value1'})
- self.assertEquals(tags[0].name, 'key1')
- self.assertEquals(tags[0].value, 'value1')
+ self.assertEqual(tags[0].name, 'key1')
+ self.assertEqual(tags[0].value, 'value1')
tags = self.ec2_client.get_all_tags(filters={'key': 'value2'})
- self.assertEquals(len(tags), 0)
+ self.assertEqual(len(tags), 0)
for instance in reservation.instances:
instance.remove_tag('key1', value='value1')
tags = self.ec2_client.get_all_tags()
- self.assertEquals(len(tags), 0)
+ self.assertEqual(len(tags), 0)
for instance in reservation.instances:
instance.stop()
diff --git a/tempest/thirdparty/boto/utils/wait.py b/tempest/thirdparty/boto/utils/wait.py
index 1507deb..a44e283 100644
--- a/tempest/thirdparty/boto/utils/wait.py
+++ b/tempest/thirdparty/boto/utils/wait.py
@@ -54,8 +54,7 @@
raise TestCase.failureException("State change timeout exceeded!"
'(%ds) While waiting'
'for %s at "%s"' %
- (dtime,
- final_set, status))
+ (dtime, final_set, status))
time.sleep(default_check_interval)
old_status = status
status = lfunction()
@@ -78,8 +77,7 @@
raise TestCase.failureException('Pattern find timeout exceeded!'
'(%ds) While waiting for'
'"%s" pattern in "%s"' %
- (dtime,
- regexp, text))
+ (dtime, regexp, text))
time.sleep(default_check_interval)
diff --git a/test-requirements.txt b/test-requirements.txt
index 6c313ca..1ede25e 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -2,3 +2,4 @@
# needed for doc build
docutils==0.9.1
sphinx>=1.1.2
+python-subunit