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