Merge "Remove the security_group_default_rules tests"
diff --git a/.zuul.yaml b/.zuul.yaml
index d3cdab8..403c93d 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -698,8 +698,6 @@
             irrelevant-files: *tempest-irrelevant-files
         - neutron-grenade-multinode:
             irrelevant-files: *tempest-irrelevant-files
-        - neutron-grenade:
-            irrelevant-files: *tempest-irrelevant-files
         - grenade-py3:
             irrelevant-files: *tempest-irrelevant-files
         - devstack-plugin-ceph-tempest:
@@ -739,8 +737,6 @@
             irrelevant-files: *tempest-irrelevant-files
         - tempest-full:
             irrelevant-files: *tempest-irrelevant-files
-        - neutron-grenade:
-            irrelevant-files: *tempest-irrelevant-files
         - grenade-py3:
             irrelevant-files: *tempest-irrelevant-files
         - tempest-ipv6-only:
diff --git a/doc/source/overview.rst b/doc/source/overview.rst
index 423214d..e51b90b 100644
--- a/doc/source/overview.rst
+++ b/doc/source/overview.rst
@@ -116,7 +116,7 @@
     $ stestr run --black-regex '\[.*\bslow\b.*\]' '^tempest\.(api|scenario)'
 
    will run the same set of tests as the default gate jobs. Or you can
-   use `unittest`_ compatible test runners such as `testr`_, `pytest`_ etc.
+   use `unittest`_ compatible test runners such as `stestr`_, `pytest`_ etc.
 
    Tox also contains several existing job configurations. For example::
 
@@ -130,7 +130,6 @@
    to run the tests tagged as smoke.
 
 .. _unittest: https://docs.python.org/3/library/unittest.html
-.. _testr: https://testrepository.readthedocs.org/en/latest/MANUAL.html
 .. _stestr: https://stestr.readthedocs.org/en/latest/MANUAL.html
 .. _pytest: https://docs.pytest.org/en/latest/
 
@@ -269,14 +268,14 @@
     will have a configuration file already set up to work with your
     DevStack installation.
 
-Tempest is not tied to any single test runner, but `testr`_ is the most commonly
+Tempest is not tied to any single test runner, but `stestr`_ is the most commonly
 used tool. Also, the nosetests test runner is **not** recommended to run Tempest.
 
 After setting up your configuration file, you can execute the set of Tempest
-tests by using ``testr`` ::
+tests by using ``stestr``. By default, ``stestr`` runs tests in parallel ::
 
-    $ testr run --parallel
+    $ stestr run
 
 To run one single test serially ::
 
-    $ testr run tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_reboot_non_existent_server
+    $ stestr run --serial tempest.api.compute.servers.test_servers_negative.ServersNegativeTestJSON.test_reboot_non_existent_server
diff --git a/releasenotes/notes/Extend-cleanup-CLI-to-delete-regions-9f1dbda2c8de12e2.yaml b/releasenotes/notes/Extend-cleanup-CLI-to-delete-regions-9f1dbda2c8de12e2.yaml
new file mode 100644
index 0000000..e2fc5b3
--- /dev/null
+++ b/releasenotes/notes/Extend-cleanup-CLI-to-delete-regions-9f1dbda2c8de12e2.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    tempest cleanup CLI is extended about region deletion. Until now, the
+    regions have been neglected by tempest cleanup. From now on, tempest
+    cleanup is able to delete leftover regions as well.
diff --git a/releasenotes/notes/intermediate-ussuri-release-8aebeca312a6718c.yaml b/releasenotes/notes/intermediate-ussuri-release-8aebeca312a6718c.yaml
new file mode 100644
index 0000000..6caeacd
--- /dev/null
+++ b/releasenotes/notes/intermediate-ussuri-release-8aebeca312a6718c.yaml
@@ -0,0 +1,14 @@
+---
+prelude: >
+    This is an intermediate release during the Ussuri development cycle to
+    mark the end of support for EM Queens in Tempest.
+    After this release, Tempest will support below OpenStack Releases:
+
+      * Train
+      * Stein
+      * Rocky
+
+    Current development of Tempest is for OpenStack Ussuri development
+    cycle.
+
+    This is the last release of Tempest to officially support python2.7.
diff --git a/releasenotes/notes/subunit_describe_calls-ad7df689b9d63e3f.yaml b/releasenotes/notes/subunit_describe_calls-ad7df689b9d63e3f.yaml
new file mode 100644
index 0000000..e7fc3a0
--- /dev/null
+++ b/releasenotes/notes/subunit_describe_calls-ad7df689b9d63e3f.yaml
@@ -0,0 +1,8 @@
+---
+deprecations:
+  - |
+    Deprecated command for subunit-describe-calls
+
+features:
+  - |
+    Added new tempest subcommand for subunit-describe-calls
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index 43c102c..bfd8b2d 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -6,6 +6,8 @@
    :maxdepth: 1
 
    unreleased
+   v23.0.0
+   v22.1.0
    v22.0.0
    v21.0.0
    v20.0.0
diff --git a/releasenotes/source/v22.1.0.rst b/releasenotes/source/v22.1.0.rst
new file mode 100644
index 0000000..6a4fd1f
--- /dev/null
+++ b/releasenotes/source/v22.1.0.rst
@@ -0,0 +1,6 @@
+=====================
+v22.1.0 Release Notes
+=====================
+
+.. release-notes:: 22.1.0 Release Notes
+   :version: 22.1.0
diff --git a/releasenotes/source/v23.0.0.rst b/releasenotes/source/v23.0.0.rst
new file mode 100644
index 0000000..7c5edf8
--- /dev/null
+++ b/releasenotes/source/v23.0.0.rst
@@ -0,0 +1,6 @@
+=====================
+v23.0.0 Release Notes
+=====================
+
+.. release-notes:: 23.0.0 Release Notes
+   :version: 23.0.0
diff --git a/setup.cfg b/setup.cfg
index 5c1d24c..1e9b8e9 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -36,6 +36,7 @@
     subunit-describe-calls = tempest.cmd.subunit_describe_calls:entry_point
 tempest.cm =
     account-generator = tempest.cmd.account_generator:TempestAccountGenerator
+    subunit-describe-calls = tempest.cmd.subunit_describe_calls:TempestSubunitDescribeCalls
     init = tempest.cmd.init:TempestInit
     cleanup = tempest.cmd.cleanup:TempestCleanup
     list-plugins = tempest.cmd.list_plugins:TempestListPlugins
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index b1a7c52..836b975 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -31,6 +31,13 @@
 
 class LiveMigrationTestBase(base.BaseV2ComputeAdminTest):
 
+    # These tests don't attempt any SSH validation nor do they use
+    # floating IPs on the instance, so all we need is a network and
+    # a subnet so the instance being migrated has a single port, but
+    # we need that to make sure we are properly updating the port
+    # host bindings during the live migration.
+    create_default_network = True
+
     @classmethod
     def skip_checks(cls):
         super(LiveMigrationTestBase, cls).skip_checks()
@@ -44,16 +51,6 @@
                 "Less than 2 compute nodes, skipping migration test.")
 
     @classmethod
-    def setup_credentials(cls):
-        # These tests don't attempt any SSH validation nor do they use
-        # floating IPs on the instance, so all we need is a network and
-        # a subnet so the instance being migrated has a single port, but
-        # we need that to make sure we are properly updating the port
-        # host bindings during the live migration.
-        cls.set_network_resources(network=True, subnet=True)
-        super(LiveMigrationTestBase, cls).setup_credentials()
-
-    @classmethod
     def setup_clients(cls):
         super(LiveMigrationTestBase, cls).setup_clients()
         cls.admin_migration_client = cls.os_admin.migrations_client
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index aaf7a5a..7c2d9d2 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -39,6 +39,9 @@
     """Base test case class for all Compute API tests."""
 
     force_tenant_isolation = False
+    # Set this to True in subclasses to create a default network. See
+    # https://bugs.launchpad.net/tempest/+bug/1844568
+    create_default_network = False
 
     # TODO(andreaf) We should care also for the alt_manager here
     # but only once client lazy load in the manager is done
@@ -58,7 +61,10 @@
 
     @classmethod
     def setup_credentials(cls):
-        cls.set_network_resources()
+        # Setting network=True, subnet=True creates a default network
+        cls.set_network_resources(
+            network=cls.create_default_network,
+            subnet=cls.create_default_network)
         super(BaseV2ComputeTest, cls).setup_credentials()
 
     @classmethod
diff --git a/tempest/api/compute/security_groups/base.py b/tempest/api/compute/security_groups/base.py
index 49125d1..ef69a13 100644
--- a/tempest/api/compute/security_groups/base.py
+++ b/tempest/api/compute/security_groups/base.py
@@ -24,18 +24,14 @@
 class BaseSecurityGroupsTest(base.BaseV2ComputeTest):
     max_microversion = '2.35'
 
+    create_default_network = True
+
     @classmethod
     def skip_checks(cls):
         super(BaseSecurityGroupsTest, cls).skip_checks()
         if not utils.get_service_list()['network']:
             raise cls.skipException("network service not enabled.")
 
-    @classmethod
-    def setup_credentials(cls):
-        # A network and a subnet will be created for these tests
-        cls.set_network_resources(network=True, subnet=True)
-        super(BaseSecurityGroupsTest, cls).setup_credentials()
-
     @staticmethod
     def generate_random_security_group_id():
         if (CONF.service_available.neutron and
diff --git a/tempest/api/compute/servers/test_delete_server.py b/tempest/api/compute/servers/test_delete_server.py
index 0263b81..a7db88a 100644
--- a/tempest/api/compute/servers/test_delete_server.py
+++ b/tempest/api/compute/servers/test_delete_server.py
@@ -26,6 +26,7 @@
 
 
 class DeleteServersTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     # NOTE: Server creations of each test class should be under 10
     # for preventing "Quota exceeded for instances"
diff --git a/tempest/api/compute/servers/test_disk_config.py b/tempest/api/compute/servers/test_disk_config.py
index bc48069..5b8e7ab 100644
--- a/tempest/api/compute/servers/test_disk_config.py
+++ b/tempest/api/compute/servers/test_disk_config.py
@@ -24,6 +24,7 @@
 
 
 class ServerDiskConfigTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def skip_checks(cls):
diff --git a/tempest/api/compute/servers/test_instance_actions.py b/tempest/api/compute/servers/test_instance_actions.py
index b916a42..00837eb 100644
--- a/tempest/api/compute/servers/test_instance_actions.py
+++ b/tempest/api/compute/servers/test_instance_actions.py
@@ -19,6 +19,7 @@
 
 
 class InstanceActionsTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
@@ -54,6 +55,7 @@
 
 
 class InstanceActionsV221TestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     min_microversion = '2.21'
     max_microversion = 'latest'
diff --git a/tempest/api/compute/servers/test_instance_actions_negative.py b/tempest/api/compute/servers/test_instance_actions_negative.py
index 1d3a790..4b5a2c3 100644
--- a/tempest/api/compute/servers/test_instance_actions_negative.py
+++ b/tempest/api/compute/servers/test_instance_actions_negative.py
@@ -20,6 +20,7 @@
 
 
 class InstanceActionsNegativeTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index f0915de..b95db5c 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -20,6 +20,7 @@
 
 
 class ListServersNegativeTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/servers/test_multiple_create.py b/tempest/api/compute/servers/test_multiple_create.py
index 059454d..e176251 100644
--- a/tempest/api/compute/servers/test_multiple_create.py
+++ b/tempest/api/compute/servers/test_multiple_create.py
@@ -19,6 +19,7 @@
 
 
 class MultipleCreateTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @decorators.idempotent_id('61e03386-89c3-449c-9bb1-a06f423fd9d1')
     def test_multiple_create(self):
diff --git a/tempest/api/compute/servers/test_novnc.py b/tempest/api/compute/servers/test_novnc.py
index 7cf6d83..68e09e7 100644
--- a/tempest/api/compute/servers/test_novnc.py
+++ b/tempest/api/compute/servers/test_novnc.py
@@ -33,6 +33,7 @@
 
 
 class NoVNCConsoleTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def skip_checks(cls):
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 0e469c7..ff50836 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -707,16 +707,13 @@
     @testtools.skipUnless(CONF.compute_feature_enabled.vnc_console,
                           'VNC Console feature is disabled.')
     def test_get_vnc_console(self):
-        # Get the VNC console of type 'novnc' and 'xvpvnc'
-        console_types = ['novnc', 'xvpvnc']
-        for console_type in console_types:
-            if self.is_requested_microversion_compatible('2.5'):
-                body = self.client.get_vnc_console(
-                    self.server_id, type=console_type)['console']
-            else:
-                body = self.client.get_remote_console(
-                    self.server_id, console_type=console_type,
-                    protocol='vnc')['remote_console']
-            self.assertEqual(console_type, body['type'])
-            self.assertNotEqual('', body['url'])
-            self._validate_url(body['url'])
+        if self.is_requested_microversion_compatible('2.5'):
+            body = self.client.get_vnc_console(
+                self.server_id, type='novnc')['console']
+        else:
+            body = self.client.get_remote_console(
+                self.server_id, console_type='novnc',
+                protocol='vnc')['remote_console']
+        self.assertEqual('novnc', body['type'])
+        self.assertNotEqual('', body['url'])
+        self._validate_url(body['url'])
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index f79b05f..c936ce5 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -19,12 +19,7 @@
 
 
 class ServerAddressesTestJSON(base.BaseV2ComputeTest):
-
-    @classmethod
-    def setup_credentials(cls):
-        # This test module might use a network and a subnet
-        cls.set_network_resources(network=True, subnet=True)
-        super(ServerAddressesTestJSON, cls).setup_credentials()
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/servers/test_server_addresses_negative.py b/tempest/api/compute/servers/test_server_addresses_negative.py
index b2b3cc0..f33c6d9 100644
--- a/tempest/api/compute/servers/test_server_addresses_negative.py
+++ b/tempest/api/compute/servers/test_server_addresses_negative.py
@@ -20,11 +20,7 @@
 
 
 class ServerAddressesNegativeTestJSON(base.BaseV2ComputeTest):
-
-    @classmethod
-    def setup_credentials(cls):
-        cls.set_network_resources(network=True, subnet=True)
-        super(ServerAddressesNegativeTestJSON, cls).setup_credentials()
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/servers/test_server_group.py b/tempest/api/compute/servers/test_server_group.py
index 1b7cb96..4b5efaa 100644
--- a/tempest/api/compute/servers/test_server_group.py
+++ b/tempest/api/compute/servers/test_server_group.py
@@ -29,6 +29,7 @@
     policies = affinity/anti-affinity
     It also adds the tests for list and get details of server-groups
     """
+    create_default_network = True
 
     @classmethod
     def skip_checks(cls):
diff --git a/tempest/api/compute/servers/test_server_metadata.py b/tempest/api/compute/servers/test_server_metadata.py
index fe95018..9d87e1c 100644
--- a/tempest/api/compute/servers/test_server_metadata.py
+++ b/tempest/api/compute/servers/test_server_metadata.py
@@ -18,6 +18,7 @@
 
 
 class ServerMetadataTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/servers/test_server_password.py b/tempest/api/compute/servers/test_server_password.py
index e6a668a..7b31ede 100644
--- a/tempest/api/compute/servers/test_server_password.py
+++ b/tempest/api/compute/servers/test_server_password.py
@@ -19,6 +19,7 @@
 
 
 class ServerPasswordTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/compute/servers/test_server_tags.py b/tempest/api/compute/servers/test_server_tags.py
index 8d0a4e3..3893b01 100644
--- a/tempest/api/compute/servers/test_server_tags.py
+++ b/tempest/api/compute/servers/test_server_tags.py
@@ -26,6 +26,8 @@
     min_microversion = '2.26'
     max_microversion = 'latest'
 
+    create_default_network = True
+
     @classmethod
     def skip_checks(cls):
         super(ServerTagsTestJSON, cls).skip_checks()
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index 1e3e966..3a4bd6d 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -25,6 +25,7 @@
 
 
 class ServersTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 6cabf65..f42bb9c 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -30,6 +30,7 @@
 
 
 class ServersNegativeTestJSON(base.BaseV2ComputeTest):
+    create_default_network = True
 
     def setUp(self):
         super(ServersNegativeTestJSON, self).setUp()
diff --git a/tempest/api/compute/servers/test_virtual_interfaces.py b/tempest/api/compute/servers/test_virtual_interfaces.py
index f810ec5..dfd6ca4 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces.py
@@ -32,11 +32,7 @@
 
     depends_on_nova_network = True
 
-    @classmethod
-    def setup_credentials(cls):
-        # This test needs a network and a subnet
-        cls.set_network_resources(network=True, subnet=True)
-        super(VirtualInterfacesTestJSON, cls).setup_credentials()
+    create_default_network = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index 92524fc..bee2b7b 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -28,6 +28,7 @@
 
 class BaseAttachVolumeTest(base.BaseV2ComputeTest):
     """Base class for the attach volume tests in this module."""
+    create_default_network = True
 
     @classmethod
     def skip_checks(cls):
diff --git a/tempest/api/compute/volumes/test_attach_volume_negative.py b/tempest/api/compute/volumes/test_attach_volume_negative.py
index 6d08f90..9a506af 100644
--- a/tempest/api/compute/volumes/test_attach_volume_negative.py
+++ b/tempest/api/compute/volumes/test_attach_volume_negative.py
@@ -21,6 +21,7 @@
 
 
 class AttachVolumeNegativeTest(base.BaseV2ComputeTest):
+    create_default_network = True
 
     @classmethod
     def skip_checks(cls):
diff --git a/tempest/api/network/admin/test_agent_management.py b/tempest/api/network/admin/test_agent_management.py
deleted file mode 100644
index eaf477c..0000000
--- a/tempest/api/network/admin/test_agent_management.py
+++ /dev/null
@@ -1,93 +0,0 @@
-# Copyright 2013 IBM Corp.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest.api.network import base
-from tempest.common import tempest_fixtures as fixtures
-from tempest.common import utils
-from tempest.lib.common.utils import data_utils
-from tempest.lib import decorators
-from tempest.lib import exceptions as lib_exc
-
-
-class AgentManagementTestJSON(base.BaseAdminNetworkTest):
-
-    @classmethod
-    def skip_checks(cls):
-        super(AgentManagementTestJSON, cls).skip_checks()
-        if not utils.is_extension_enabled('agent', 'network'):
-            msg = "agent extension not enabled."
-            raise cls.skipException(msg)
-
-    @classmethod
-    def resource_setup(cls):
-        super(AgentManagementTestJSON, cls).resource_setup()
-        body = cls.admin_agents_client.list_agents()
-        agents = body['agents']
-        cls.agent = agents[0]
-
-    @decorators.idempotent_id('9c80f04d-11f3-44a4-8738-ed2f879b0ff4')
-    def test_list_agent(self):
-        body = self.admin_agents_client.list_agents()
-        agents = body['agents']
-        # Hearthbeats must be excluded from comparison
-        self.agent.pop('heartbeat_timestamp', None)
-        self.agent.pop('configurations', None)
-        for agent in agents:
-            agent.pop('heartbeat_timestamp', None)
-            agent.pop('configurations', None)
-        self.assertIn(self.agent, agents)
-
-    @decorators.idempotent_id('869bc8e8-0fda-4a30-9b71-f8a7cf58ca9f')
-    def test_show_agent(self):
-        body = self.admin_agents_client.show_agent(self.agent['id'])
-        agent = body['agent']
-        self.assertEqual(agent['id'], self.agent['id'])
-
-    @decorators.idempotent_id('371dfc5b-55b9-4cb5-ac82-c40eadaac941')
-    def test_update_agent_status(self):
-        origin_status = self.agent['admin_state_up']
-        # Try to update the 'admin_state_up' to the original
-        # one to avoid the negative effect.
-        agent_status = {'admin_state_up': origin_status}
-        body = self.admin_agents_client.update_agent(agent_id=self.agent['id'],
-                                                     agent=agent_status)
-        updated_status = body['agent']['admin_state_up']
-        self.assertEqual(origin_status, updated_status)
-
-    @decorators.idempotent_id('68a94a14-1243-46e6-83bf-157627e31556')
-    def test_update_agent_description(self):
-        self.useFixture(fixtures.LockFixture('agent_description'))
-        description = 'description for update agent.'
-        agent_description = {'description': description}
-        body = self.admin_agents_client.update_agent(agent_id=self.agent['id'],
-                                                     agent=agent_description)
-        self.addCleanup(self._restore_agent)
-        updated_description = body['agent']['description']
-        self.assertEqual(updated_description, description)
-
-    def _restore_agent(self):
-        """Restore the agent description after update test"""
-
-        description = self.agent['description'] or ''
-        origin_agent = {'description': description}
-        self.admin_agents_client.update_agent(agent_id=self.agent['id'],
-                                              agent=origin_agent)
-
-    @decorators.idempotent_id('b33af888-b6ac-4e68-a0ca-0444c2696cf9')
-    @decorators.attr(type=['negative'])
-    def test_delete_agent_negative(self):
-        non_existent_id = data_utils.rand_uuid()
-        self.assertRaises(
-            lib_exc.NotFound,
-            self.admin_agents_client.delete_agent, non_existent_id)
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index 56b5509..10121de 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -197,14 +197,14 @@
                          'Ports from multiple tenants are in the list resp')
         port_ids = [port['id'] for port in ports]
         fixed_ips = [port['fixed_ips'] for port in ports]
-        port_ips = []
-        for addr in fixed_ips:
-            port_ips.extend([port['ip_address'] for port in addr])
-
         port_net_ids = [port['network_id'] for port in ports]
         self.assertIn(port_1['port']['id'], port_ids)
-        self.assertIn(port_1_fixed_ip, port_ips)
         self.assertIn(network['id'], port_net_ids)
+        # Check that every port has a fixed_ip that matches the query
+        for addr in fixed_ips:
+            port_ips = [port['ip_address'] for port in addr]
+            self.assertIn(port_1_fixed_ip, port_ips,
+                          'Port not matching IP filter found')
 
     @decorators.idempotent_id('79895408-85d5-460d-94e7-9531c5fd9123')
     @testtools.skipUnless(
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index b4fb5a5..c54b16b 100644
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -136,7 +136,10 @@
         self._init_admin_ids()
 
         # available services
-        self.project_services = cleanup_service.get_project_cleanup_services()
+        self.project_associated_services = (
+            cleanup_service.get_project_associated_cleanup_services())
+        self.resource_cleanup_services = (
+            cleanup_service.get_resource_cleanup_services())
         self.global_services = cleanup_service.get_global_cleanup_services()
 
         if parsed_args.init_saved_state:
@@ -180,6 +183,10 @@
             svc = service(admin_mgr, **kwargs)
             svc.run()
 
+        for service in self.resource_cleanup_services:
+            svc = service(self.admin_mgr, **kwargs)
+            svc.run()
+
         if is_dry_run:
             with open(DRY_RUN_JSON, 'w+') as f:
                 f.write(json.dumps(self.dry_run_data, sort_keys=True,
@@ -204,7 +211,7 @@
                   'is_save_state': False,
                   'project_id': project_id,
                   'got_exceptions': self.GOT_EXCEPTIONS}
-        for service in self.project_services:
+        for service in self.project_associated_services:
             svc = service(self.admin_mgr, **kwargs)
             svc.run()
 
@@ -269,7 +276,11 @@
             svc = service(admin_mgr, **kwargs)
             svc.run()
 
-        for service in self.project_services:
+        for service in self.project_associated_services:
+            svc = service(admin_mgr, **kwargs)
+            svc.run()
+
+        for service in self.resource_cleanup_services:
             svc = service(admin_mgr, **kwargs)
             svc.run()
 
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 8b625d0..2b35ebf 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -730,6 +730,44 @@
 
 
 # begin global services
+class RegionService(BaseService):
+
+    def __init__(self, manager, **kwargs):
+        super(RegionService, self).__init__(kwargs)
+        self.client = manager.regions_client
+
+    def list(self):
+        client = self.client
+        regions = client.list_regions()
+        if not self.is_save_state:
+            regions = [region for region in regions['regions'] if region['id']
+                       not in self.saved_state_json['regions'].keys()]
+            return regions
+        else:
+            return regions['regions']
+
+    def delete(self):
+        client = self.client
+        regions = self.list()
+        for region in regions:
+            try:
+                client.delete_region(region['id'])
+            except Exception:
+                LOG.exception("Delete Region %s exception.", region['id'])
+
+    def dry_run(self):
+        regions = self.list()
+        self.data['regions'] = {}
+        for region in regions:
+            self.data['regions'][region['id']] = region
+
+    def save_state(self):
+        regions = self.list()
+        self.data['regions'] = {}
+        for region in regions:
+            self.data['regions'][region['id']] = region
+
+
 class FlavorService(BaseService):
     def __init__(self, manager, **kwargs):
         super(FlavorService, self).__init__(kwargs)
@@ -968,31 +1006,52 @@
             self.data['domains'][domain['id']] = domain['name']
 
 
-def get_project_cleanup_services():
-    project_services = []
+def get_project_associated_cleanup_services():
+    """Returns list of project service classes.
+
+    The list contains services whose resources need to be deleted prior,
+    the project they are associated with, deletion. The resources cannot be
+    most likely deleted after the project is deleted first.
+    """
+    project_associated_services = []
     # TODO(gmann): Tempest should provide some plugin hook for cleanup
     # script extension to plugin tests also.
     if IS_NOVA:
-        project_services.append(ServerService)
-        project_services.append(KeyPairService)
-        project_services.append(ServerGroupService)
-        project_services.append(NovaQuotaService)
-    if IS_NEUTRON:
-        project_services.append(NetworkFloatingIpService)
-        if utils.is_extension_enabled('metering', 'network'):
-            project_services.append(NetworkMeteringLabelRuleService)
-            project_services.append(NetworkMeteringLabelService)
-        project_services.append(NetworkRouterService)
-        project_services.append(NetworkPortService)
-        project_services.append(NetworkSubnetService)
-        project_services.append(NetworkService)
-        project_services.append(NetworkSecGroupService)
-        project_services.append(NetworkSubnetPoolsService)
+        project_associated_services.append(NovaQuotaService)
     if IS_CINDER:
-        project_services.append(SnapshotService)
-        project_services.append(VolumeService)
-        project_services.append(VolumeQuotaService)
-    return project_services
+        project_associated_services.append(VolumeQuotaService)
+    return project_associated_services
+
+
+def get_resource_cleanup_services():
+    """Returns list of project related classes.
+
+    The list contains services whose resources are associated with a project,
+    however, their deletion is possible also after the project is deleted
+    first.
+    """
+    resource_cleanup_services = []
+    # TODO(gmann): Tempest should provide some plugin hook for cleanup
+    # script extension to plugin tests also.
+    if IS_NOVA:
+        resource_cleanup_services.append(ServerService)
+        resource_cleanup_services.append(KeyPairService)
+        resource_cleanup_services.append(ServerGroupService)
+    if IS_NEUTRON:
+        resource_cleanup_services.append(NetworkFloatingIpService)
+        if utils.is_extension_enabled('metering', 'network'):
+            resource_cleanup_services.append(NetworkMeteringLabelRuleService)
+            resource_cleanup_services.append(NetworkMeteringLabelService)
+        resource_cleanup_services.append(NetworkRouterService)
+        resource_cleanup_services.append(NetworkPortService)
+        resource_cleanup_services.append(NetworkSubnetService)
+        resource_cleanup_services.append(NetworkService)
+        resource_cleanup_services.append(NetworkSecGroupService)
+        resource_cleanup_services.append(NetworkSubnetPoolsService)
+    if IS_CINDER:
+        resource_cleanup_services.append(SnapshotService)
+        resource_cleanup_services.append(VolumeService)
+    return resource_cleanup_services
 
 
 def get_global_cleanup_services():
@@ -1005,4 +1064,5 @@
     global_services.append(ProjectService)
     global_services.append(DomainService)
     global_services.append(RoleService)
+    global_services.append(RegionService)
     return global_services
diff --git a/tempest/cmd/subunit_describe_calls.py b/tempest/cmd/subunit_describe_calls.py
index 081fa7a..e029538 100644
--- a/tempest/cmd/subunit_describe_calls.py
+++ b/tempest/cmd/subunit_describe_calls.py
@@ -81,13 +81,19 @@
 import os
 import re
 import sys
+import traceback
 
+from cliff.command import Command
 from oslo_serialization import jsonutils as json
 import subunit
 import testtools
 
 
+DESCRIPTION = "Outputs all HTTP calls a given test made that were logged."
+
+
 class UrlParser(testtools.TestResult):
+
     uuid_re = re.compile(r'(^|[^0-9a-f])[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-'
                          '[0-9a-f]{4}-[0-9a-f]{12}([^0-9a-f]|$)')
     id_re = re.compile(r'(^|[^0-9a-z])[0-9a-z]{8}[0-9a-z]{4}[0-9a-z]{4}'
@@ -241,33 +247,12 @@
 
 
 class ArgumentParser(argparse.ArgumentParser):
+
     def __init__(self):
-        desc = "Outputs all HTTP calls a given test made that were logged."
+        desc = DESCRIPTION
         super(ArgumentParser, self).__init__(description=desc)
-
         self.prog = "subunit-describe-calls"
-
-        self.add_argument(
-            "-s", "--subunit", metavar="<subunit file>",
-            nargs="?", type=argparse.FileType('rb'), default=sys.stdin,
-            help="The path to the subunit output file.")
-
-        self.add_argument(
-            "-n", "--non-subunit-name", metavar="<non subunit name>",
-            default="pythonlogging",
-            help="The name used in subunit to describe the file contents.")
-
-        self.add_argument(
-            "-o", "--output-file", metavar="<output file>", default=None,
-            help="The output file name for the json.")
-
-        self.add_argument(
-            "-p", "--ports", metavar="<ports file>", default=None,
-            help="A JSON file describing the ports for each service.")
-
-        self.add_argument(
-            "-v", "--verbose", action='store_true', default=False,
-            help="Add Request and Response header and body data to stdout.")
+        _parser_add_args(self)
 
 
 def parse(stream, non_subunit_name, ports):
@@ -321,11 +306,63 @@
         sys.stdout.write('\n')
 
 
-def entry_point():
-    cl_args = ArgumentParser().parse_args()
+def entry_point(cl_args=None):
+    print('Running subunit_describe_calls ...')
+    if not cl_args:
+        print("Use of: 'subunit-describe-calls' is deprecated, "
+              "please use: 'tempest subunit-describe-calls'")
+        cl_args = ArgumentParser().parse_args()
     parser = parse(cl_args.subunit, cl_args.non_subunit_name, cl_args.ports)
     output(parser, cl_args.output_file, cl_args.verbose)
 
 
+def _parser_add_args(parser):
+    parser.add_argument(
+        "-s", "--subunit", metavar="<subunit file>",
+        nargs="?", type=argparse.FileType('rb'), default=sys.stdin,
+        help="The path to the subunit output file(default:stdin v1/v2 stream)"
+    )
+
+    parser.add_argument(
+        "-n", "--non-subunit-name", metavar="<non subunit name>",
+        default="pythonlogging",
+        help="The name used in subunit to describe the file contents."
+    )
+
+    parser.add_argument(
+        "-o", "--output-file", metavar="<output file>", default=None,
+        help="The output file name for the json."
+    )
+
+    parser.add_argument(
+        "-p", "--ports", metavar="<ports file>", default=None,
+        help="A JSON file describing the ports for each service."
+    )
+
+    parser.add_argument(
+        "-v", "--verbose", action='store_true', default=False,
+        help="Add Request and Response header and body data to stdout."
+    )
+
+
+class TempestSubunitDescribeCalls(Command):
+
+    def get_parser(self, prog_name):
+        parser = super(TempestSubunitDescribeCalls, self).get_parser(prog_name)
+        _parser_add_args(parser)
+        return parser
+
+    def take_action(self, parsed_args):
+        try:
+            entry_point(parsed_args)
+
+        except Exception:
+            traceback.print_exc()
+            raise
+
+    def get_description(self):
+        return DESCRIPTION
+
+
 if __name__ == "__main__":
     entry_point()
diff --git a/tempest/lib/api_schema/response/compute/v2_71/servers.py b/tempest/lib/api_schema/response/compute/v2_71/servers.py
index 0c526fb..5cf0f8a 100644
--- a/tempest/lib/api_schema/response/compute/v2_71/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_71/servers.py
@@ -69,7 +69,7 @@
 # need to keep this schema in this file to have the generic way to select the
 # right schema based on self.schema_versions_info mapping in service client.
 # ****** Schemas unchanged since microversion 2.70 ***
-list_servers_details = copy.deepcopy(servers270.list_servers_detail)
+list_servers_detail = copy.deepcopy(servers270.list_servers_detail)
 list_servers = copy.deepcopy(servers270.list_servers)
 show_server_diagnostics = copy.deepcopy(servers270.show_server_diagnostics)
 get_remote_consoles = copy.deepcopy(servers270.get_remote_consoles)
diff --git a/tempest/lib/common/ssh.py b/tempest/lib/common/ssh.py
index d4ec6ad..2ac1605 100644
--- a/tempest/lib/common/ssh.py
+++ b/tempest/lib/common/ssh.py
@@ -196,11 +196,13 @@
 
             exit_status = channel.recv_exit_status()
 
-            if 0 != exit_status:
-                raise exceptions.SSHExecCommandFailed(
-                    command=cmd, exit_status=exit_status,
-                    stderr=err_data, stdout=out_data)
-            return out_data
+        ssh.close()
+
+        if 0 != exit_status:
+            raise exceptions.SSHExecCommandFailed(
+                command=cmd, exit_status=exit_status,
+                stderr=err_data, stdout=out_data)
+        return out_data
 
     def test_connection_auth(self):
         """Raises an exception when we can not connect to server via ssh."""
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index f03e9de..b1919d4 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -249,12 +249,16 @@
 
         block_migration = (CONF.compute_feature_enabled.
                            block_migration_for_live_migration)
+        old_host = self.get_host_for_server(server['id'])
         self.admin_servers_client.live_migrate_server(
             server['id'], host=None, block_migration=block_migration,
             disk_over_commit=False)
         waiters.wait_for_server_status(self.servers_client,
                                        server['id'], 'ACTIVE')
 
+        new_host = self.get_host_for_server(server['id'])
+        self.assertNotEqual(old_host, new_host, 'Server did not migrate')
+
         self._wait_server_status_and_check_network_connectivity(
             server, keypair, floating_ip)
 
diff --git a/tempest/tests/cmd/test_cleanup_services.py b/tempest/tests/cmd/test_cleanup_services.py
index de0dbec..ae08d02 100644
--- a/tempest/tests/cmd/test_cleanup_services.py
+++ b/tempest/tests/cmd/test_cleanup_services.py
@@ -175,7 +175,8 @@
         "ports": {u'aa74aa4v-741a': u'saved-port'},
         "security_groups": {u'7q844add-3697': u'saved-sec-group'},
         "subnets": {u'55ttda4a-2584': u'saved-subnet'},
-        "subnetpools": {u'8acf64c1-43fc': u'saved-subnet-pool'}
+        "subnetpools": {u'8acf64c1-43fc': u'saved-subnet-pool'},
+        "regions": {u'RegionOne': {}}
     }
     # Mocked methods
     get_method = 'tempest.lib.common.rest_client.RestClient.get'
@@ -1202,6 +1203,57 @@
 
 
 # begin global services
+class TestRegionService(BaseCmdServiceTests):
+    service_class = 'RegionService'
+    service_name = 'regions'
+    response = {
+        "regions": [{
+            "parent_region_id": None,
+            "id": "RegionOne",
+            "links": {
+                    "self":
+                    "http://10.0.145.61:5000/v3/regions/RegionOne"
+                    },
+            "description": ""
+        },
+            {
+            "parent_region_id": None,
+            "id": "RegionTwo",
+            "links": {
+                "self":
+                    "http://10.0.145.61:5000/v3/regions/RegionTwo"
+                },
+            "description": ""
+            }],
+        "links": {
+            "self":
+                "http://10.0.145.61:5000/v3/regions",
+                "next": None,
+                "previous": None
+        }
+    }
+
+    def test_delete_pass(self):
+        delete_mock = [(self.get_method, self.response, 200),
+                       (self.delete_method, None, 204),
+                       (self.log_method, "exception", None)]
+        self._test_delete(delete_mock)
+
+    def test_delete_fail(self):
+        delete_mock = [(self.get_method, self.response, 200),
+                       (self.delete_method, 'error', None),
+                       (self.log_method, "exception", None)]
+        self._test_delete(delete_mock, fail=True)
+
+    def test_dry_run(self):
+        dry_mock = [(self.get_method, self.response, 200),
+                    (self.delete_method, "delete", None)]
+        self._test_dry_run_true(dry_mock)
+
+    def test_save_state(self):
+        self._test_saved_state_true([(self.get_method, self.response, 200)])
+
+
 class TestDomainService(BaseCmdServiceTests):
 
     service_class = 'DomainService'
diff --git a/tempest/tests/common/test_waiters.py b/tempest/tests/common/test_waiters.py
index 02e1c99..6275f22 100755
--- a/tempest/tests/common/test_waiters.py
+++ b/tempest/tests/common/test_waiters.py
@@ -54,44 +54,6 @@
                           waiters.wait_for_image_status,
                           self.client, 'fake_image_id', 'active')
 
-    @mock.patch.object(time, 'sleep')
-    def test_wait_for_volume_status_error_restoring(self, mock_sleep):
-        # Tests that the wait method raises VolumeRestoreErrorException if
-        # the volume status is 'error_restoring'.
-        client = mock.Mock(spec=volumes_client.VolumesClient,
-                           resource_type="volume",
-                           build_interval=1)
-        volume1 = {'volume': {'status': 'restoring-backup'}}
-        volume2 = {'volume': {'status': 'error_restoring'}}
-        mock_show = mock.Mock(side_effect=(volume1, volume2))
-        client.show_volume = mock_show
-        volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa'
-        self.assertRaises(exceptions.VolumeRestoreErrorException,
-                          waiters.wait_for_volume_resource_status,
-                          client, volume_id, 'available')
-        mock_show.assert_has_calls([mock.call(volume_id),
-                                    mock.call(volume_id)])
-        mock_sleep.assert_called_once_with(1)
-
-    @mock.patch.object(time, 'sleep')
-    def test_wait_for_volume_status_error_extending(self, mock_sleep):
-        # Tests that the wait method raises VolumeExtendErrorException if
-        # the volume status is 'error_extending'.
-        client = mock.Mock(spec=volumes_client.VolumesClient,
-                           resource_type="volume",
-                           build_interval=1)
-        volume1 = {'volume': {'status': 'extending'}}
-        volume2 = {'volume': {'status': 'error_extending'}}
-        mock_show = mock.Mock(side_effect=(volume1, volume2))
-        client.show_volume = mock_show
-        volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa'
-        self.assertRaises(exceptions.VolumeExtendErrorException,
-                          waiters.wait_for_volume_resource_status,
-                          client, volume_id, 'available')
-        mock_show.assert_has_calls([mock.call(volume_id),
-                                    mock.call(volume_id)])
-        mock_sleep.assert_called_once_with(1)
-
 
 class TestInterfaceWaiters(base.TestCase):
 
@@ -232,3 +194,41 @@
         show_volume.assert_has_calls([mock.call(mock.sentinel.volume_id),
                                       mock.call(mock.sentinel.volume_id),
                                       mock.call(mock.sentinel.volume_id)])
+
+    @mock.patch.object(time, 'sleep')
+    def test_wait_for_volume_status_error_restoring(self, mock_sleep):
+        # Tests that the wait method raises VolumeRestoreErrorException if
+        # the volume status is 'error_restoring'.
+        client = mock.Mock(spec=volumes_client.VolumesClient,
+                           resource_type="volume",
+                           build_interval=1)
+        volume1 = {'volume': {'status': 'restoring-backup'}}
+        volume2 = {'volume': {'status': 'error_restoring'}}
+        mock_show = mock.Mock(side_effect=(volume1, volume2))
+        client.show_volume = mock_show
+        volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa'
+        self.assertRaises(exceptions.VolumeRestoreErrorException,
+                          waiters.wait_for_volume_resource_status,
+                          client, volume_id, 'available')
+        mock_show.assert_has_calls([mock.call(volume_id),
+                                    mock.call(volume_id)])
+        mock_sleep.assert_called_once_with(1)
+
+    @mock.patch.object(time, 'sleep')
+    def test_wait_for_volume_status_error_extending(self, mock_sleep):
+        # Tests that the wait method raises VolumeExtendErrorException if
+        # the volume status is 'error_extending'.
+        client = mock.Mock(spec=volumes_client.VolumesClient,
+                           resource_type="volume",
+                           build_interval=1)
+        volume1 = {'volume': {'status': 'extending'}}
+        volume2 = {'volume': {'status': 'error_extending'}}
+        mock_show = mock.Mock(side_effect=(volume1, volume2))
+        client.show_volume = mock_show
+        volume_id = '7532b91e-aa0a-4e06-b3e5-20c0c5ee1caa'
+        self.assertRaises(exceptions.VolumeExtendErrorException,
+                          waiters.wait_for_volume_resource_status,
+                          client, volume_id, 'available')
+        mock_show.assert_has_calls([mock.call(volume_id),
+                                    mock.call(volume_id)])
+        mock_sleep.assert_called_once_with(1)
diff --git a/tempest/tests/lib/services/identity/v3/test_application_credentials_client.py b/tempest/tests/lib/services/identity/v3/test_application_credentials_client.py
index 9bf9b68..2774c44 100644
--- a/tempest/tests/lib/services/identity/v3/test_application_credentials_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_application_credentials_client.py
@@ -146,7 +146,7 @@
     def test_list_application_credential_with_bytes_body(self):
         self._test_list_app_creds(bytes_body=True)
 
-    def test_delete_trust(self):
+    def test_delete_application_credential(self):
         self.check_service_client_function(
             self.client.delete_application_credential,
             'tempest.lib.common.rest_client.RestClient.delete',
diff --git a/tempest/tests/lib/services/image/v2/test_image_members_client.py b/tempest/tests/lib/services/image/v2/test_image_members_client.py
index 703b6e1..2caa567 100644
--- a/tempest/tests/lib/services/image/v2/test_image_members_client.py
+++ b/tempest/tests/lib/services/image/v2/test_image_members_client.py
@@ -27,6 +27,28 @@
         "schema": "/v2/schemas/member"
     }
 
+    FAKE_LIST_IMAGE_MEMBERS = {
+        "members": [
+            {
+                "created_at": "2013-10-07T17:58:03Z",
+                "image_id": "dbc999e3-c52f-4200-bedd-3b18fe7f87fe",
+                "member_id": "123456789",
+                "schema": "/v2/schemas/member",
+                "status": "pending",
+                "updated_at": "2013-10-07T17:58:03Z"
+            },
+            {
+                "created_at": "2013-10-07T17:58:55Z",
+                "image_id": "dbc999e3-c52f-4200-bedd-3b18fe7f87fe",
+                "member_id": "987654321",
+                "schema": "/v2/schemas/member",
+                "status": "accepted",
+                "updated_at": "2013-10-08T12:08:55Z"
+            }
+        ],
+        "schema": "/v2/schemas/members"
+    }
+
     def setUp(self):
         super(TestImageMembersClient, self).setUp()
         fake_auth = fake_auth_provider.FakeAuthProvider()
@@ -34,6 +56,14 @@
                                                               'image',
                                                               'regionOne')
 
+    def _test_list_image_members(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_image_members,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_IMAGE_MEMBERS,
+            bytes_body,
+            image_id="dbc999e3-c52f-4200-bedd-3b18fe7f87fe")
+
     def _test_show_image_member(self, bytes_body=False):
         self.check_service_client_function(
             self.client.show_image_member,
@@ -62,6 +92,12 @@
             member_id="8989447062e04a818baf9e073fd04fa7",
             schema="/v2/schemas/member2")
 
+    def test_list_image_members_with_str_body(self):
+        self._test_list_image_members()
+
+    def test_list_image_members_with_bytes_body(self):
+        self._test_list_image_members(bytes_body=True)
+
     def test_show_image_member_with_str_body(self):
         self._test_show_image_member()
 
diff --git a/tempest/tests/lib/services/image/v2/test_namespaces_client.py b/tempest/tests/lib/services/image/v2/test_namespaces_client.py
index 4cb9d01..3b057ad 100644
--- a/tempest/tests/lib/services/image/v2/test_namespaces_client.py
+++ b/tempest/tests/lib/services/image/v2/test_namespaces_client.py
@@ -26,6 +26,51 @@
         "protected": True
     }
 
+    FAKE_LIST_NAMESPACES = {
+        "first": "/v2/metadefs/namespaces?sort_key=created_at&sort_dir=asc",
+        "namespaces": [
+            {
+                "created_at": "2014-08-28T17:13:06Z",
+                "description": "OS::Compute::Libvirt",
+                "display_name": "libvirt Driver Options",
+                "namespace": "OS::Compute::Libvirt",
+                "owner": "admin",
+                "protected": True,
+                "resource_type_associations": [
+                    {
+                        "created_at": "2014-08-28T17:13:06Z",
+                        "name": "OS::Glance::Image",
+                        "updated_at": "2014-08-28T17:13:06Z"
+                    }
+                ],
+                "schema": "/v2/schemas/metadefs/namespace",
+                "self": "/v2/metadefs/namespaces/OS::Compute::Libvirt",
+                "updated_at": "2014-08-28T17:13:06Z",
+                "visibility": "public"
+            },
+            {
+                "created_at": "2014-08-28T17:13:06Z",
+                "description": "OS::Compute::Quota",
+                "display_name": "Flavor Quota",
+                "namespace": "OS::Compute::Quota",
+                "owner": "admin",
+                "protected": True,
+                "resource_type_associations": [
+                    {
+                        "created_at": "2014-08-28T17:13:06Z",
+                        "name": "OS::Nova::Flavor",
+                        "updated_at": "2014-08-28T17:13:06Z"
+                    }
+                ],
+                "schema": "/v2/schemas/metadefs/namespace",
+                "self": "/v2/metadefs/namespaces/OS::Compute::Quota",
+                "updated_at": "2014-08-28T17:13:06Z",
+                "visibility": "public"
+            }
+        ],
+        "schema": "/v2/schemas/metadefs/namespaces"
+    }
+
     FAKE_UPDATE_NAMESPACE = {
         "namespace": "OS::Compute::Hypervisor",
         "visibility": "public",
@@ -48,6 +93,13 @@
             bytes_body,
             namespace="OS::Compute::Hypervisor")
 
+    def _test_list_namespaces(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_namespaces,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_NAMESPACES,
+            bytes_body)
+
     def _test_create_namespace(self, bytes_body=False):
         self.check_service_client_function(
             self.client.create_namespace,
@@ -74,6 +126,12 @@
     def test_show_namespace_with_bytes_body(self):
         self._test_show_namespace(bytes_body=True)
 
+    def test_list_namespaces_with_str_body(self):
+        self._test_list_namespaces()
+
+    def test_list_namespaces_with_bytes_body(self):
+        self._test_list_namespaces(bytes_body=True)
+
     def test_create_namespace_with_str_body(self):
         self._test_create_namespace()
 
diff --git a/tempest/tests/lib/services/volume/v3/test_groups_client.py b/tempest/tests/lib/services/volume/v3/test_groups_client.py
index 5a5ae88..8a2c4ea 100644
--- a/tempest/tests/lib/services/volume/v3/test_groups_client.py
+++ b/tempest/tests/lib/services/volume/v3/test_groups_client.py
@@ -59,11 +59,11 @@
             "volume_types": ["2103099d-7cc3-4e52-a2f1-23a5284416f3"],
             "status": "available",
             "availability_zone": "az1",
-            "created_at": "20127-06-20T03:50:07Z"
+            "created_at": "2017-06-20T03:50:07Z"
         }
     }
 
-    FAKE_LIST_GROUPS = {
+    FAKE_LIST_GROUP_DETAILS = {
         "groups": [
             {
                 "id": "0e701ab8-1bec-4b9f-b026-a7ba4af13578",
@@ -100,6 +100,19 @@
         ]
     }
 
+    FAKE_LIST_GROUPS = {
+        "groups": [
+            {
+                "id": "0e701ab8-1bec-4b9f-b026-a7ba4af13578",
+                "name": "group-001",
+            },
+            {
+                "id": "e479997c-650b-40a4-9dfe-77655818b0d2",
+                "name": "group-002",
+            }
+        ]
+    }
+
     def setUp(self):
         super(TestGroupsClient, self).setUp()
         fake_auth = fake_auth_provider.FakeAuthProvider()
@@ -123,13 +136,21 @@
             bytes_body,
             group_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5")
 
+    def _test_list_group_details(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_groups,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_GROUP_DETAILS,
+            bytes_body,
+            detail=True)
+
     def _test_list_groups(self, bytes_body=False):
         self.check_service_client_function(
             self.client.list_groups,
             'tempest.lib.common.rest_client.RestClient.get',
             self.FAKE_LIST_GROUPS,
             bytes_body,
-            detail=True)
+            detail=False)
 
     def test_create_group_with_str_body(self):
         self._test_create_group()
@@ -143,6 +164,12 @@
     def test_show_group_with_bytes_body(self):
         self._test_show_group(bytes_body=True)
 
+    def test_list_group_details_with_str_body(self):
+        self._test_list_group_details()
+
+    def test_list_group_details_with_bytes_body(self):
+        self._test_list_group_details(bytes_body=True)
+
     def test_list_groups_with_str_body(self):
         self._test_list_groups()
 
diff --git a/tempest/tests/lib/test_ssh.py b/tempest/tests/lib/test_ssh.py
index 37fe646..c849231 100644
--- a/tempest/tests/lib/test_ssh.py
+++ b/tempest/tests/lib/test_ssh.py
@@ -170,7 +170,8 @@
 
     @mock.patch('select.POLLIN', SELECT_POLLIN, create=True)
     def test_timeout_in_exec_command(self):
-        chan_mock, poll_mock, _ = self._set_mocks_for_select([0, 0, 0], True)
+        chan_mock, poll_mock, _, _ = (
+            self._set_mocks_for_select([0, 0, 0], True))
 
         # Test for a timeout condition immediately raised
         client = ssh.Client('localhost', 'root', timeout=2)
@@ -187,7 +188,7 @@
 
     @mock.patch('select.POLLIN', SELECT_POLLIN, create=True)
     def test_exec_command(self):
-        chan_mock, poll_mock, select_mock = (
+        chan_mock, poll_mock, select_mock, client_mock = (
             self._set_mocks_for_select([[1, 0, 0]], True))
 
         chan_mock.recv_exit_status.return_value = 0
@@ -211,6 +212,8 @@
         chan_mock.recv_stderr.assert_called_once_with(1024)
         chan_mock.recv_exit_status.assert_called_once_with()
 
+        client_mock.close.assert_called_once_with()
+
     def _set_mocks_for_select(self, poll_data, ito_value=False):
         gsc_mock = self.patch('tempest.lib.common.ssh.Client.'
                               '_get_ssh_connection')
@@ -235,14 +238,15 @@
         else:
             poll_mock.poll.return_value = poll_data
 
-        return chan_mock, poll_mock, select_mock
+        return chan_mock, poll_mock, select_mock, client_mock
 
     _utf8_string = six.unichr(1071)
     _utf8_bytes = _utf8_string.encode("utf-8")
 
     @mock.patch('select.POLLIN', SELECT_POLLIN, create=True)
     def test_exec_good_command_output(self):
-        chan_mock, poll_mock, _ = self._set_mocks_for_select([1, 0, 0])
+        chan_mock, poll_mock, _, _ = (
+            self._set_mocks_for_select([1, 0, 0]))
         closed_prop = mock.PropertyMock(return_value=True)
         type(chan_mock).closed = closed_prop
 
@@ -257,7 +261,8 @@
 
     @mock.patch('select.POLLIN', SELECT_POLLIN, create=True)
     def test_exec_bad_command_output(self):
-        chan_mock, poll_mock, _ = self._set_mocks_for_select([1, 0, 0])
+        chan_mock, poll_mock, _, _ = (
+            self._set_mocks_for_select([1, 0, 0]))
         closed_prop = mock.PropertyMock(return_value=True)
         type(chan_mock).closed = closed_prop
 
diff --git a/tools/tempest-integrated-gate-networking-blacklist.txt b/tools/tempest-integrated-gate-networking-blacklist.txt
index 9566f69..263b2e4 100644
--- a/tools/tempest-integrated-gate-networking-blacklist.txt
+++ b/tools/tempest-integrated-gate-networking-blacklist.txt
@@ -3,7 +3,9 @@
 
 # Skip Cinder, Glance, keystone and Swift API tests.
 tempest.api.volume
+tempest.api.compute.volumes
 tempest.api.image
+tempest.api.compute.images
 tempest.api.object_storage
 tempest.api.identity