Merge "Update "test_unmanage_manage_snapshot" test to support some params"
diff --git a/doc/source/conf.py b/doc/source/conf.py
index f11d96a..b9e22b5 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -155,8 +155,7 @@
 git_cmd = ["git", "log", "--pretty=format:'%ad, commit %h'", "--date=local",
    "-n1"]
 try:
-    html_last_updated_fmt = str(
-        subprocess.Popen(git_cmd, stdout=subprocess.PIPE).communicate()[0])
+    html_last_updated_fmt = subprocess.check_output(git_cmd).decode('utf-8')
 except Exception:
     warnings.warn('Cannot get last updated time from git repository. '
                   'Not setting "html_last_updated_fmt".')
diff --git a/tempest/api/compute/admin/test_flavors_access.py b/tempest/api/compute/admin/test_flavors_access.py
index 5a38acc..2c236ec 100644
--- a/tempest/api/compute/admin/test_flavors_access.py
+++ b/tempest/api/compute/admin/test_flavors_access.py
@@ -50,7 +50,7 @@
 
         flavor_access = (self.admin_flavors_client.list_flavor_access(
                          flavor['id'])['flavor_access'])
-        self.assertEqual(len(flavor_access), 0, str(flavor_access))
+        self.assertEmpty(flavor_access)
 
     @decorators.idempotent_id('59e622f6-bdf6-45e3-8ba8-fedad905a6b4')
     def test_flavor_access_add_remove(self):
diff --git a/tempest/api/compute/admin/test_hosts.py b/tempest/api/compute/admin/test_hosts.py
index 5b3bb2c..0e1e7ed 100644
--- a/tempest/api/compute/admin/test_hosts.py
+++ b/tempest/api/compute/admin/test_hosts.py
@@ -36,7 +36,7 @@
         hosts = self.client.list_hosts()['hosts']
         host = hosts[0]
         hosts = self.client.list_hosts(zone=host['zone'])['hosts']
-        self.assertGreaterEqual(len(hosts), 1)
+        self.assertNotEmpty(hosts)
         self.assertIn(host, hosts)
 
     @decorators.idempotent_id('9af3c171-fbf4-4150-a624-22109733c2a6')
@@ -58,12 +58,12 @@
         hosts = self.client.list_hosts()['hosts']
 
         hosts = [host for host in hosts if host['service'] == 'compute']
-        self.assertGreaterEqual(len(hosts), 1)
+        self.assertNotEmpty(hosts)
 
         for host in hosts:
             hostname = host['host_name']
             resources = self.client.show_host(hostname)['host']
-            self.assertGreaterEqual(len(resources), 1)
+            self.assertNotEmpty(resources)
             host_resource = resources[0]['resource']
             self.assertIsNotNone(host_resource)
             self.assertIsNotNone(host_resource['cpu'])
diff --git a/tempest/api/compute/admin/test_networks.py b/tempest/api/compute/admin/test_networks.py
index 0ea0a78..acb0d90 100644
--- a/tempest/api/compute/admin/test_networks.py
+++ b/tempest/api/compute/admin/test_networks.py
@@ -62,4 +62,4 @@
             self.assertIn(configured_network, [x['label'] for x in networks])
         else:
             network_labels = [x['label'] for x in networks]
-            self.assertGreaterEqual(len(network_labels), 1)
+            self.assertNotEmpty(network_labels)
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index 92b1ff1..022ceba 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -48,9 +48,9 @@
 
         # We do not know the exact network configuration, but an instance
         # should at least have a single public or private address
-        self.assertGreaterEqual(len(addresses), 1)
+        self.assertNotEmpty(addresses)
         for network_addresses in addresses.values():
-            self.assertGreaterEqual(len(network_addresses), 1)
+            self.assertNotEmpty(network_addresses)
             for address in network_addresses:
                 self.assertTrue(address['addr'])
                 self.assertTrue(address['version'])
diff --git a/tempest/api/network/admin/test_agent_management.py b/tempest/api/network/admin/test_agent_management.py
index 6389489..7304db9 100644
--- a/tempest/api/network/admin/test_agent_management.py
+++ b/tempest/api/network/admin/test_agent_management.py
@@ -49,7 +49,7 @@
     @decorators.idempotent_id('e335be47-b9a1-46fd-be30-0874c0b751e6')
     def test_list_agents_non_admin(self):
         body = self.agents_client.list_agents()
-        self.assertEqual(len(body["agents"]), 0)
+        self.assertEmpty(body["agents"])
 
     @decorators.idempotent_id('869bc8e8-0fda-4a30-9b71-f8a7cf58ca9f')
     def test_show_agent(self):
diff --git a/tempest/api/network/admin/test_metering_extensions.py b/tempest/api/network/admin/test_metering_extensions.py
index 2b789e7..21a7ab4 100644
--- a/tempest/api/network/admin/test_metering_extensions.py
+++ b/tempest/api/network/admin/test_metering_extensions.py
@@ -74,7 +74,7 @@
         # Asserting that the label is not found in list after deletion
         labels = self.admin_metering_labels_client.list_metering_labels(
             id=metering_label_id)
-        self.assertEqual(len(labels['metering_labels']), 0)
+        self.assertEmpty(labels['metering_labels'])
 
     def _delete_metering_label_rule(self, metering_label_rule_id):
         client = self.admin_metering_label_rules_client
diff --git a/tempest/api/network/admin/test_routers.py b/tempest/api/network/admin/test_routers.py
index ec8d260..07c4157 100644
--- a/tempest/api/network/admin/test_routers.py
+++ b/tempest/api/network/admin/test_routers.py
@@ -134,7 +134,7 @@
         self.assertEqual(len(list_body['ports']), 1)
         gw_port = list_body['ports'][0]
         fixed_ips = gw_port['fixed_ips']
-        self.assertGreaterEqual(len(fixed_ips), 1)
+        self.assertNotEmpty(fixed_ips)
         # Assert that all of the IPs from the router gateway port
         # are allocated from a valid public subnet.
         public_net_body = self.admin_networks_client.show_network(
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index d78cd1e..128544b 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -156,7 +156,7 @@
         self.assertEqual(len(list_body['ports']), 1)
         gw_port = list_body['ports'][0]
         fixed_ips = gw_port['fixed_ips']
-        self.assertGreaterEqual(len(fixed_ips), 1)
+        self.assertNotEmpty(fixed_ips)
         # Assert that all of the IPs from the router gateway port
         # are allocated from a valid public subnet.
         public_net_body = self.admin_networks_client.show_network(
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index e54b6e7..811e530 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -101,7 +101,7 @@
         # Check only the format of common headers with custom matcher
         self.assertThat(resp, custom_matchers.AreAllWellFormatted())
 
-        self.assertEqual(len(container_list), 0)
+        self.assertEmpty(container_list)
 
     @decorators.idempotent_id('1c7efa35-e8a2-4b0b-b5ff-862c7fd83704')
     def test_list_containers_with_format_json(self):
@@ -162,7 +162,7 @@
             self.account_client.list_account_containers(params=params)
         self.assertHeaders(resp, 'Account', 'GET')
 
-        self.assertEqual(len(container_list), 0)
+        self.assertEmpty(container_list)
 
         params = {'marker': self.containers[self.containers_count // 2]}
         resp, container_list = \
@@ -182,7 +182,7 @@
         resp, container_list = \
             self.account_client.list_account_containers(params=params)
         self.assertHeaders(resp, 'Account', 'GET')
-        self.assertEqual(len(container_list), 0)
+        self.assertEmpty(container_list)
 
         params = {'end_marker': self.containers[self.containers_count // 2]}
         resp, container_list = \
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 21ea6ae..e9d2de0 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -414,7 +414,7 @@
             self.container_name,
             object_name)
         self.assertIn('x-object-manifest', resp)
-        self.assertNotEqual(len(resp['x-object-manifest']), 0)
+        self.assertNotEmpty(resp['x-object-manifest'])
 
     @decorators.idempotent_id('0dbbe89c-6811-4d84-a2df-eca2bdd40c0e')
     def test_update_object_metadata_with_x_object_metakey(self):
@@ -521,10 +521,10 @@
         self.assertTrue(resp['etag'].endswith('\"'))
         self.assertTrue(resp['etag'].strip('\"').isalnum())
         self.assertTrue(re.match("^\d+\.?\d*\Z", resp['x-timestamp']))
-        self.assertNotEqual(len(resp['content-type']), 0)
+        self.assertNotEmpty(resp['content-type'])
         self.assertTrue(re.match("^tx[0-9a-f]{21}-[0-9a-f]{10}.*",
                                  resp['x-trans-id']))
-        self.assertNotEqual(len(resp['date']), 0)
+        self.assertNotEmpty(resp['date'])
         self.assertEqual(resp['accept-ranges'], 'bytes')
         self.assertEqual(resp['x-object-manifest'],
                          '%s/%s' % (self.container_name, object_name))
@@ -613,10 +613,10 @@
         self.assertTrue(resp['etag'].endswith('\"'))
         self.assertTrue(resp['etag'].strip('\"').isalnum())
         self.assertTrue(re.match("^\d+\.?\d*\Z", resp['x-timestamp']))
-        self.assertNotEqual(len(resp['content-type']), 0)
+        self.assertNotEmpty(resp['content-type'])
         self.assertTrue(re.match("^tx[0-9a-f]{21}-[0-9a-f]{10}.*",
                                  resp['x-trans-id']))
-        self.assertNotEqual(len(resp['date']), 0)
+        self.assertNotEmpty(resp['date'])
         self.assertEqual(resp['accept-ranges'], 'bytes')
         self.assertEqual(resp['x-object-manifest'],
                          '%s/%s' % (self.container_name, object_name))
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index ac717f8..af1024c 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -57,8 +57,6 @@
                          "to the requested name")
         self.assertIsNotNone(volume['id'],
                              "Field volume id is empty or not found.")
-        waiters.wait_for_volume_resource_status(self.volumes_client,
-                                                volume['id'], 'available')
 
         # Update volume with new volume_type
         self.volumes_client.retype_volume(volume['id'],
diff --git a/tempest/api/volume/admin/test_volumes_actions.py b/tempest/api/volume/admin/test_volumes_actions.py
index acff7cd..b81a477 100644
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -70,7 +70,7 @@
     @test.services('compute')
     def test_force_detach_volume(self):
         # Create a server and a volume
-        server_id = self.create_server(wait_until='ACTIVE')['id']
+        server_id = self.create_server()['id']
         volume_id = self.create_volume()['id']
 
         # Attach volume
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index eace92d..8d66156 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -217,7 +217,7 @@
                 cls.snapshots_client.wait_for_resource_deletion,
                 snapshot)
 
-    def create_server(self, **kwargs):
+    def create_server(self, wait_until='ACTIVE', **kwargs):
         name = kwargs.pop(
             'name',
             data_utils.rand_name(self.__class__.__name__ + '-instance'))
@@ -227,6 +227,7 @@
             self.os_primary,
             tenant_network=tenant_network,
             name=name,
+            wait_until=wait_until,
             **kwargs)
 
         self.addCleanup(test_utils.call_and_ignore_notfound_exc,
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
index 5a192ac..2c13a3c 100644
--- a/tempest/api/volume/test_volume_transfers.py
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -13,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from testtools import matchers
-
 from tempest.api.volume import base
 from tempest.common import waiters
 from tempest.lib import decorators
@@ -56,7 +54,7 @@
         # List volume transfers, the result should be greater than
         # or equal to 1
         body = self.client.list_volume_transfers()['transfers']
-        self.assertThat(len(body), matchers.GreaterThan(0))
+        self.assertNotEmpty(body)
 
         # Accept a volume transfer by alt_tenant
         body = self.alt_client.accept_volume_transfer(
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index 0e7f1e9..8541c6d 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -38,7 +38,7 @@
     @test.services('compute')
     def test_attach_detach_volume_to_instance(self):
         # Create a server
-        server = self.create_server(wait_until='ACTIVE')
+        server = self.create_server()
         # Volume is attached and detached successfully from an instance
         self.volumes_client.attach_volume(self.volume['id'],
                                           instance_uuid=server['id'],
@@ -69,7 +69,7 @@
     @test.services('compute')
     def test_get_volume_attachment(self):
         # Create a server
-        server = self.create_server(wait_until='ACTIVE')
+        server = self.create_server()
         # Verify that a volume's attachment information is retrieved
         self.volumes_client.attach_volume(self.volume['id'],
                                           instance_uuid=server['id'],
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
index 5ad209c..da4324a 100644
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -108,7 +108,7 @@
         volume = self.create_volume()
         self.addCleanup(self.volumes_client.delete_volume,
                         volume['id'])
-        server = self.create_server(wait_until='ACTIVE')
+        server = self.create_server()
         # Attach volume to instance
         self.attach_volume(server['id'], volume['id'])
         # Create backup using force flag
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index 9180088..4e19e62 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -170,7 +170,7 @@
     @decorators.idempotent_id('f5e56b0a-5d02-43c1-a2a7-c9b792c2e3f6')
     @test.services('compute')
     def test_attach_volumes_with_nonexistent_volume_id(self):
-        server = self.create_server(wait_until='ACTIVE')
+        server = self.create_server()
 
         self.assertRaises(lib_exc.NotFound,
                           self.volumes_client.attach_volume,
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 99918eb..44c1def 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -39,7 +39,7 @@
     @test.services('compute')
     def test_snapshot_create_delete_with_volume_in_use(self):
         # Create a test instance
-        server = self.create_server(wait_until='ACTIVE')
+        server = self.create_server()
         self.attach_volume(server['id'], self.volume_origin['id'])
 
         # Snapshot a volume which attached to an instance with force=False
@@ -65,7 +65,7 @@
         snapshot1 = self.create_snapshot(self.volume_origin['id'])
 
         # Create a server and attach it
-        server = self.create_server(wait_until='ACTIVE')
+        server = self.create_server()
         self.attach_volume(server['id'], self.volume_origin['id'])
 
         # Now that the volume is attached, create another snapshots
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 9319d2a..99a628e 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -64,10 +64,14 @@
                 # Show header line too
                 selected.append(l)
             # lsblk lists disk type in a column right-aligned with TYPE
-            elif pos > 0 and l[pos:pos + 4] == "disk":
+            elif pos is not None and pos > 0 and l[pos:pos + 4] == "disk":
                 selected.append(l)
 
-        return "\n".join(selected)
+        if selected:
+            return "\n".join(selected)
+        else:
+            msg = "'TYPE' column is requred but the output doesn't have it: "
+            raise tempest.lib.exceptions.TempestException(msg + output)
 
     def get_boot_time(self):
         cmd = 'cut -f1 -d. /proc/uptime'
@@ -89,12 +93,12 @@
     def get_nic_name_by_mac(self, address):
         cmd = "ip -o link | awk '/%s/ {print $2}'" % address
         nic = self.exec_command(cmd)
-        return nic.strip().strip(":").lower()
+        return nic.strip().strip(":").split('@')[0].lower()
 
     def get_nic_name_by_ip(self, address):
         cmd = "ip -o addr | awk '/%s/ {print $2}'" % address
         nic = self.exec_command(cmd)
-        return nic.strip().strip(":").lower()
+        return nic.strip().strip(":").split('@')[0].lower()
 
     def get_dns_servers(self):
         cmd = 'cat /etc/resolv.conf'
diff --git a/tempest/common/validation_resources.py b/tempest/common/validation_resources.py
index b15796f..9e83a07 100644
--- a/tempest/common/validation_resources.py
+++ b/tempest/common/validation_resources.py
@@ -80,10 +80,23 @@
             validation_data['security_group'] = \
                 create_ssh_security_group(os, add_rule)
         if validation_resources['floating_ip']:
-            floating_client = os.compute_floating_ips_client
-            validation_data.update(
-                floating_client.create_floating_ip(
-                    pool=CONF.network.floating_network_name))
+            if CONF.service_available.neutron:
+                floatingip = os.floating_ips_client.create_floatingip(
+                    floating_network_id=CONF.network.public_network_id)
+                # validation_resources['floating_ip'] has historically looked
+                # like a compute API POST /os-floating-ips response, so we need
+                # to mangle it a bit for a Neutron response with different
+                # fields.
+                validation_data['floating_ip'] = floatingip['floatingip']
+                validation_data['floating_ip']['ip'] = (
+                    floatingip['floatingip']['floating_ip_address'])
+            else:
+                # NOTE(mriedem): The os-floating-ips compute API was deprecated
+                # in the 2.36 microversion. Any tests for CRUD operations on
+                # floating IPs using the compute API should be capped at 2.35.
+                validation_data.update(
+                    os.compute_floating_ips_client.create_floating_ip(
+                        pool=CONF.network.floating_network_name))
     return validation_data
 
 
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 1ca9365..f25ab1d 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -195,7 +195,7 @@
 
         tenant_network = self.get_tenant_network()
 
-        body, servers = compute.create_test_server(
+        body, _ = compute.create_test_server(
             clients,
             tenant_network=tenant_network,
             wait_until=wait_until,
@@ -822,7 +822,7 @@
     def _get_network_by_name(self, network_name):
         net = self.os_admin.networks_client.list_networks(
             name=network_name)['networks']
-        self.assertNotEqual(len(net), 0,
+        self.assertNotEmpty(net,
                             "Unable to get network by name: %s" % network_name)
         return net[0]
 
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index c06d239..25227be 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -52,7 +52,7 @@
 
     def _get_host_name(self):
         hosts = self.hosts_client.list_hosts()['hosts']
-        self.assertGreaterEqual(len(hosts), 1)
+        self.assertNotEmpty(hosts)
         computes = [x for x in hosts if x['service'] == 'compute']
         return computes[0]['host_name']
 
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index ec6d362..c8add8b 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -62,7 +62,7 @@
         if test.is_extension_enabled('security-group', 'network'):
             security_group = self._create_security_group()
             security_groups = [{'name': security_group['name']}]
-        network, subnet, router = self.create_networks()
+        network, _, _ = self.create_networks()
         server = self.create_server(
             networks=[{'uuid': network['id']}],
             key_name=keypair['name'],
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index c76c082..4efeffd 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -212,7 +212,7 @@
             self.servers, mtu=mtu)
 
     def _disassociate_floating_ips(self):
-        floating_ip, server = self.floating_ip_tuple
+        floating_ip, _ = self.floating_ip_tuple
         self._disassociate_floating_ip(floating_ip)
         self.floating_ip_tuple = Floating_IP_tuple(
             floating_ip, None)
@@ -287,7 +287,7 @@
                                               "guest after %s sec"
                                               % CONF.network.build_timeout)
 
-        num, new_nic = self.diff_list[0]
+        _, new_nic = self.diff_list[0]
         ssh_client.exec_command("sudo ip addr add %s/%s dev %s" % (
                                 new_port['fixed_ips'][0]['ip_address'],
                                 CONF.network.project_network_mask_bits,
@@ -295,7 +295,7 @@
         ssh_client.exec_command("sudo ip link set %s up" % new_nic)
 
     def _get_server_nics(self, ssh_client):
-        reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+):')
+        reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+)[@]?.*:')
         ipatxt = ssh_client.exec_command("ip address")
         return reg.findall(ipatxt)
 
@@ -630,7 +630,7 @@
                 admin_state_up attribute of instance port to True
         """
         self._setup_network_and_servers()
-        floating_ip, server = self.floating_ip_tuple
+        _, server = self.floating_ip_tuple
         server_id = server['id']
         port_id = self.os_admin.ports_client.list_ports(
             device_id=server_id)['ports'][0]['id']
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 3504a44..6d9addd 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -171,7 +171,7 @@
 
         # Turn on 2nd NIC for Cirros when dualnet
         if dualnet:
-            network, network_v6 = net_list
+            _, network_v6 = net_list
             self.turn_nic6_on(sshv4_1, sid1, network_v6['id'])
             self.turn_nic6_on(sshv4_2, sid2, network_v6['id'])
 
diff --git a/tempest/tests/lib/services/base.py b/tempest/tests/lib/services/base.py
index 71b7f2d..90c9f63 100644
--- a/tempest/tests/lib/services/base.py
+++ b/tempest/tests/lib/services/base.py
@@ -31,12 +31,42 @@
 
     def check_service_client_function(self, function, function2mock,
                                       body, to_utf=False, status=200,
-                                      headers=None, **kwargs):
+                                      headers=None, mock_args=None,
+                                      **kwargs):
+        """Mock a service client function for unit testing.
+
+        :param function: The service client function to call.
+        :param function2mock: The REST call to mock inside the service client
+               function.
+        :param body: Expected response body returned by the service client
+               function.
+        :param to_utf: Whether to use UTF-8 encoding for request.
+        :param status: Expected response status returned by the service client
+               function.
+        :param headers: Expected headers returned by the service client
+               function.
+        :param mock_args: List/dict/value of expected args/kwargs called by
+               function2mock. For example:
+               * If mock_args=['foo'] then ``assert_called_once_with('foo')``
+                 is called.
+               * If mock_args={'foo': 'bar'} then
+                 ``assert_called_once_with(foo='bar')`` is called.
+               * If mock_args='foo' then ``assert_called_once_with('foo')``
+                 is called.
+        :param kwargs: kwargs that are passed to function.
+        """
         mocked_response = self.create_response(body, to_utf, status, headers)
-        self.useFixture(fixtures.MockPatch(
+        fixture = self.useFixture(fixtures.MockPatch(
             function2mock, return_value=mocked_response))
         if kwargs:
             resp = function(**kwargs)
         else:
             resp = function()
         self.assertEqual(body, resp)
+
+        if isinstance(mock_args, list):
+            fixture.mock.assert_called_once_with(*mock_args)
+        elif isinstance(mock_args, dict):
+            fixture.mock.assert_called_once_with(**mock_args)
+        elif mock_args is not None:
+            fixture.mock.assert_called_once_with(mock_args)
diff --git a/tempest/tests/lib/services/identity/v3/test_services_client.py b/tempest/tests/lib/services/identity/v3/test_services_client.py
index f87fcce..b464644 100644
--- a/tempest/tests/lib/services/identity/v3/test_services_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_services_client.py
@@ -101,12 +101,15 @@
             bytes_body,
             service_id="686766")
 
-    def _test_list_services(self, bytes_body=False):
+    def _test_list_services(self, bytes_body=False, mock_args='services',
+                            **params):
         self.check_service_client_function(
             self.client.list_services,
             'tempest.lib.common.rest_client.RestClient.get',
             self.FAKE_LIST_SERVICES,
-            bytes_body)
+            bytes_body,
+            mock_args=[mock_args],
+            **params)
 
     def _test_update_service(self, bytes_body=False):
         self.check_service_client_function(
@@ -134,6 +137,10 @@
     def test_list_services_with_bytes_body(self):
         self._test_list_services(bytes_body=True)
 
+    def test_list_services_with_params(self):
+        self._test_list_services(
+            type='fake-type', mock_args='services?type=fake-type')
+
     def test_update_service_with_str_body(self):
         self._test_update_service()
 
diff --git a/tools/check_logs.py b/tools/check_logs.py
index f82b387..fc21f75 100755
--- a/tools/check_logs.py
+++ b/tools/check_logs.py
@@ -25,7 +25,6 @@
 import six.moves.urllib.request as urlreq
 import yaml
 
-
 # DEVSTACK_GATE_GRENADE is either unset if grenade is not running
 # or a string describing what type of grenade run to perform.
 is_grenade = os.environ.get('DEVSTACK_GATE_GRENADE') is not None
@@ -137,7 +136,7 @@
     with open(WHITELIST_FILE) as stream:
         loaded = yaml.safe_load(stream)
         if loaded:
-            for (name, l) in loaded.iteritems():
+            for (name, l) in six.iteritems(loaded):
                 for w in l:
                     assert 'module' in w, 'no module in %s' % name
                     assert 'message' in w, 'no message in %s' % name
diff --git a/tools/find_stack_traces.py b/tools/find_stack_traces.py
index 2ba8b16..1f2b88b 100755
--- a/tools/find_stack_traces.py
+++ b/tools/find_stack_traces.py
@@ -126,8 +126,8 @@
 
 
 def print_stats(items, fname, verbose=False):
-    errors = len(filter(lambda x: x.level == "ERROR", items))
-    traces = len(filter(lambda x: x.level == "TRACE", items))
+    errors = len([x for x in items if x.level == "ERROR"])
+    traces = len([x for x in items if x.level == "TRACE"])
     print("%d ERRORS found in %s" % (errors, fname))
     print("%d TRACES found in %s" % (traces, fname))
 
diff --git a/tools/generate-tempest-plugins-list.py b/tools/generate-tempest-plugins-list.py
index acb29af..8d26c25 100644
--- a/tools/generate-tempest-plugins-list.py
+++ b/tools/generate-tempest-plugins-list.py
@@ -65,7 +65,7 @@
 # json library won't choke.
 projects = sorted(filter(is_in_openstack_namespace, json.loads(r.text[4:])))
 
-found_plugins = filter(has_tempest_plugin, projects)
+found_plugins = list(filter(has_tempest_plugin, projects))
 
 # Every element of the found_plugins list begins with "openstack/".
 # We drop those initial 10 octets when printing the list.