Merge "Modify the group types date"
diff --git a/tempest/api/identity/v3/test_tokens.py b/tempest/api/identity/v3/test_tokens.py
index f13aa10..fa1c47f 100644
--- a/tempest/api/identity/v3/test_tokens.py
+++ b/tempest/api/identity/v3/test_tokens.py
@@ -43,7 +43,15 @@
         self.assertEqual(authenticated_token, token_body)
         # test to see if token has been properly authenticated
         self.assertEqual(authenticated_token['user']['id'], user_id)
-        self.assertEqual(authenticated_token['user']['name'], username)
+        # NOTE: resource name that are case-sensitive in keystone
+        # depends on backends such as MySQL or LDAP which are
+        # case-insensitive, case-preserving. Resource name is
+        # returned as it is stored in the backend, not as it is
+        # requested. Verifying the username with both lower-case to
+        # avoid failure on different backends
+        self.assertEqual(
+            authenticated_token['user']['name'].lower(), username.lower())
+
         self.non_admin_client.delete_token(subject_token)
         self.assertRaises(
             lib_exc.NotFound, self.non_admin_client.show_token, subject_token)
@@ -84,10 +92,17 @@
             self.assertIsNotNone(subject_id, 'Expected user ID in token.')
 
         subject_name = resp['user']['name']
+
         if username:
-            self.assertEqual(subject_name, username)
+            # NOTE: resource name that are case-sensitive in keystone
+            # depends on backends such as MySQL or LDAP which are
+            # case-insensitive, case-preserving. Resource name is
+            # returned as it is stored in the backend, not as it is
+            # requested. Verifying the username with both lower-case to
+            # avoid failure on different backends
+            self.assertEqual(subject_name.lower(), username.lower())
         else:
-            # Expect a user name, but don't know what it will be.
+            # Expect a user name, but don't know what it will be
             self.assertIsNotNone(subject_name, 'Expected user name in token.')
 
         self.assertEqual(resp['methods'][0], 'password')
@@ -110,7 +125,15 @@
             subject_token)['token']
         self.assertEqual(resp['x-subject-token'], subject_token)
         self.assertEqual(token_details['user']['id'], user.user_id)
-        self.assertEqual(token_details['user']['name'], user.username)
+        # NOTE: resource name that are case-sensitive in keystone
+        # depends on backends such as MySQL or LDAP which are
+        # case-insensitive, case-preserving. Resource name is
+        # returned as it is stored in the backend, not as it is
+        # requested. Verifying the username with both lower-case to
+        # avoid failure on different backends
+        self.assertEqual(
+            token_details['user']['name'].lower(),
+            user.username.lower())
         # Perform Delete Token
         self.non_admin_client.delete_token(subject_token)
         self.assertRaises(lib_exc.NotFound,
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
index f0d7264..645a952 100644
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-#
 # Copyright 2014 Dell Inc.
 # 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
@@ -72,6 +70,15 @@
     deleted unless the ``--delete-tempest-conf-objects`` flag is used to
     force their deletion.
 
+.. note::
+
+    If during execution of ``tempest cleanup`` NotImplemented exception
+    occurres, ``tempest cleanup`` won't fail on that, it will be logged only.
+    NotImplemented errors are ignored because they are an outcome of some
+    extensions being disabled and ``tempest cleanup`` is not checking their
+    availability as it tries to clean up as much as possible without any
+    complicated logic.
+
 """
 import sys
 import traceback
@@ -85,6 +92,7 @@
 from tempest.common import credentials_factory as credentials
 from tempest.common import identity
 from tempest import config
+from tempest.lib import exceptions
 
 SAVED_STATE_JSON = "saved_state.json"
 DRY_RUN_JSON = "dry_run.json"
@@ -105,7 +113,13 @@
             LOG.exception("Failure during cleanup")
             traceback.print_exc()
             raise
-        if self.GOT_EXCEPTIONS:
+        # ignore NotImplemented errors as those are an outcome of some
+        # extensions being disabled and cleanup is not checking their
+        # availability as it tries to clean up as much as possible without
+        # any complicated logic
+        critical_exceptions = [ex for ex in self.GOT_EXCEPTIONS if
+                               not isinstance(ex, exceptions.NotImplemented)]
+        if critical_exceptions:
             raise Exception(self.GOT_EXCEPTIONS)
 
     def init(self, parsed_args):
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index e2e1bfb..8b625d0 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 # Copyright 2015 Dell Inc.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -144,7 +142,7 @@
             msg = ("Got NotImplemented error in %s, full exception: %s" %
                    (str(self.__class__), str(exc)))
             LOG.exception(msg)
-            self.got_exceptions.append(msg)
+            self.got_exceptions.append(exc)
 
 
 class SnapshotService(BaseService):
diff --git a/tempest/cmd/list_plugins.py b/tempest/cmd/list_plugins.py
index 86732da..51decc7 100644
--- a/tempest/cmd/list_plugins.py
+++ b/tempest/cmd/list_plugins.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
 # 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
diff --git a/tempest/lib/services/network/quotas_client.py b/tempest/lib/services/network/quotas_client.py
index c479799..997d201 100644
--- a/tempest/lib/services/network/quotas_client.py
+++ b/tempest/lib/services/network/quotas_client.py
@@ -35,10 +35,22 @@
         return self.delete_resource(uri)
 
     def show_quotas(self, tenant_id, **fields):
+        """Show quota for a project.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://docs.openstack.org/api-ref/network/v2/index.html#list-quotas-for-a-project
+        """
         uri = '/quotas/%s' % tenant_id
         return self.show_resource(uri, **fields)
 
     def list_quotas(self, **filters):
+        """List quotas for projects with non default quota values.
+
+        For a full list of available parameters, please refer to the official
+        API reference:
+        https://docs.openstack.org/api-ref/network/v2/index.html#list-quotas-for-projects-with-non-default-quota-values
+        """
         uri = '/quotas'
         return self.list_resources(uri, **filters)
 
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 918e958..5a5ae88 100644
--- a/tempest/tests/lib/services/volume/v3/test_groups_client.py
+++ b/tempest/tests/lib/services/volume/v3/test_groups_client.py
@@ -20,27 +20,22 @@
 class TestGroupsClient(base.BaseServiceTest):
     FAKE_CREATE_GROUP = {
         "group": {
-            "name": "group-001",
-            "description": "Test group 1",
-            "group_type": "0e58433f-d108-4bf3-a22c-34e6b71ef86b",
-            "volume_types": ["2103099d-7cc3-4e52-a2f1-23a5284416f3"],
-            "availability_zone": "az1",
+            "id": "6f519a48-3183-46cf-a32f-41815f816666",
+            "name": "first_group"
         }
     }
 
     FAKE_CREATE_GROUP_FROM_GROUP_SNAPSHOT = {
-        "create-from-src": {
-            "name": "group-002",
-            "description": "Test group 2",
-            "group_snapshot_id": "79c9afdb-7e46-4d71-9249-1f022886963c",
+        "group": {
+            "id": "6f519a48-3183-46cf-a32f-41815f816668",
+            "name": "first_group"
         }
     }
 
     FAKE_CREATE_GROUP_FROM_GROUP = {
-        "create-from-src": {
-            "name": "group-003",
-            "description": "Test group 3",
-            "source_group_id": "e92f9dc7-0b20-492d-8ab2-3ad8fdac270e",
+        "group": {
+            "id": "6f519a48-3183-46cf-a32f-41815f816667",
+            "name": "other_group"
         }
     }