Merge "[V3] Rename get_policy to show_policy"
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index b56c9e6..60abde7 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import time
+
 from tempest.api.identity import base
 from tempest.common.utils import data_utils
 from tempest import test
@@ -76,6 +78,14 @@
         new_password = data_utils.rand_name('pass1')
         self.client.update_user_password(user['id'], new_password,
                                          original_password)
+        # TODO(lbragstad): Sleeping after the response status has been checked
+        # and the body loaded as JSON allows requests to fail-fast. The sleep
+        # is necessary because keystone will err on the side of security and
+        # invalidate tokens within a small margin of error (within the same
+        # wall clock second) after a revocation event is issued (such as a
+        # password change). Remove this once keystone and Fernet support
+        # sub-second precision, see bug 1517697 for more details.
+        time.sleep(1)
         resp = self.token.auth(user_id=user['id'],
                                password=new_password).response
         subject_token = resp['x-subject-token']
diff --git a/tempest/api/identity/v2/test_ec2_credentials.py b/tempest/api/identity/v2/test_ec2_credentials.py
index 763d8de..88161a3 100644
--- a/tempest/api/identity/v2/test_ec2_credentials.py
+++ b/tempest/api/identity/v2/test_ec2_credentials.py
@@ -38,7 +38,7 @@
         """Create user ec2 credentials."""
         resp = self.non_admin_client.create_user_ec2_credentials(
             self.creds.credentials.user_id,
-            self.creds.credentials.tenant_id)["credential"]
+            tenant_id=self.creds.credentials.tenant_id)["credential"]
         access = resp['access']
         self.addCleanup(
             self.non_admin_client.delete_user_ec2_credentials,
@@ -56,12 +56,12 @@
         # create first ec2 credentials
         creds1 = self.non_admin_client.create_user_ec2_credentials(
             self.creds.credentials.user_id,
-            self.creds.credentials.tenant_id)["credential"]
+            tenant_id=self.creds.credentials.tenant_id)["credential"]
         created_creds.append(creds1['access'])
         # create second ec2 credentials
         creds2 = self.non_admin_client.create_user_ec2_credentials(
             self.creds.credentials.user_id,
-            self.creds.credentials.tenant_id)["credential"]
+            tenant_id=self.creds.credentials.tenant_id)["credential"]
         created_creds.append(creds2['access'])
         # add credentials to be cleaned up
         self.addCleanup(
@@ -86,7 +86,7 @@
         """Get the definite user ec2 credentials."""
         resp = self.non_admin_client.create_user_ec2_credentials(
             self.creds.credentials.user_id,
-            self.creds.credentials.tenant_id)["credential"]
+            tenant_id=self.creds.credentials.tenant_id)["credential"]
         self.addCleanup(
             self.non_admin_client.delete_user_ec2_credentials,
             self.creds.credentials.user_id, resp['access'])
@@ -102,7 +102,7 @@
         """Delete user ec2 credentials."""
         resp = self.non_admin_client.create_user_ec2_credentials(
             self.creds.credentials.user_id,
-            self.creds.credentials.tenant_id)["credential"]
+            tenant_id=self.creds.credentials.tenant_id)["credential"]
         access = resp['access']
         self.non_admin_client.delete_user_ec2_credentials(
             self.creds.credentials.user_id, access)
diff --git a/tempest/api/identity/v2/test_users.py b/tempest/api/identity/v2/test_users.py
index 03c6621..5f2a8c4 100644
--- a/tempest/api/identity/v2/test_users.py
+++ b/tempest/api/identity/v2/test_users.py
@@ -56,8 +56,8 @@
             old_pass=new_pass)
 
         # user updates own password
-        resp = self.non_admin_client.update_user_own_password(
-            user_id=user_id, new_pass=new_pass, old_pass=old_pass)['access']
+        self.non_admin_client.update_user_own_password(
+            user_id=user_id, new_pass=new_pass, old_pass=old_pass)
 
         # TODO(lbragstad): Sleeping after the response status has been checked
         # and the body loaded as JSON allows requests to fail-fast. The sleep
@@ -68,8 +68,6 @@
         # sub-second precision.
         time.sleep(1)
 
-        # check authorization with new token
-        self.non_admin_token_client.auth_token(resp['token']['id'])
         # check authorization with new password
         self.non_admin_token_client.auth(self.username,
                                          new_pass,
diff --git a/tempest/api_schema/response/compute/v2_1/volumes.py b/tempest/api_schema/response/compute/v2_1/volumes.py
deleted file mode 100644
index bb34acb..0000000
--- a/tempest/api_schema/response/compute/v2_1/volumes.py
+++ /dev/null
@@ -1,120 +0,0 @@
-# Copyright 2014 NEC Corporation.  All rights reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-create_get_volume = {
-    'status_code': [200],
-    'response_body': {
-        'type': 'object',
-        'properties': {
-            'volume': {
-                'type': 'object',
-                'properties': {
-                    'id': {'type': 'string'},
-                    'status': {'type': 'string'},
-                    'displayName': {'type': ['string', 'null']},
-                    'availabilityZone': {'type': 'string'},
-                    'createdAt': {'type': 'string'},
-                    'displayDescription': {'type': ['string', 'null']},
-                    'volumeType': {'type': ['string', 'null']},
-                    'snapshotId': {'type': ['string', 'null']},
-                    'metadata': {'type': 'object'},
-                    'size': {'type': 'integer'},
-                    'attachments': {
-                        'type': 'array',
-                        'items': {
-                            'type': 'object',
-                            'properties': {
-                                'id': {'type': 'string'},
-                                'device': {'type': 'string'},
-                                'volumeId': {'type': 'string'},
-                                'serverId': {'type': 'string'}
-                            },
-                            'additionalProperties': False,
-                            # NOTE- If volume is not attached to any server
-                            # then, 'attachments' attributes comes as array
-                            # with empty objects "[{}]" due to that elements
-                            # of 'attachments' cannot defined as 'required'.
-                            # If it would come as empty array "[]" then,
-                            # those elements can be defined as 'required'.
-                        }
-                    }
-                },
-                'additionalProperties': False,
-                'required': ['id', 'status', 'displayName', 'availabilityZone',
-                             'createdAt', 'displayDescription', 'volumeType',
-                             'snapshotId', 'metadata', 'size', 'attachments']
-            }
-        },
-        'additionalProperties': False,
-        'required': ['volume']
-    }
-}
-
-list_volumes = {
-    'status_code': [200],
-    'response_body': {
-        'type': 'object',
-        'properties': {
-            'volumes': {
-                'type': 'array',
-                'items': {
-                    'type': 'object',
-                    'properties': {
-                        'id': {'type': 'string'},
-                        'status': {'type': 'string'},
-                        'displayName': {'type': ['string', 'null']},
-                        'availabilityZone': {'type': 'string'},
-                        'createdAt': {'type': 'string'},
-                        'displayDescription': {'type': ['string', 'null']},
-                        'volumeType': {'type': ['string', 'null']},
-                        'snapshotId': {'type': ['string', 'null']},
-                        'metadata': {'type': 'object'},
-                        'size': {'type': 'integer'},
-                        'attachments': {
-                            'type': 'array',
-                            'items': {
-                                'type': 'object',
-                                'properties': {
-                                    'id': {'type': 'string'},
-                                    'device': {'type': 'string'},
-                                    'volumeId': {'type': 'string'},
-                                    'serverId': {'type': 'string'}
-                                },
-                                'additionalProperties': False,
-                                # NOTE- If volume is not attached to any server
-                                # then, 'attachments' attributes comes as array
-                                # with empty object "[{}]" due to that elements
-                                # of 'attachments' cannot defined as 'required'
-                                # If it would come as empty array "[]" then,
-                                # those elements can be defined as 'required'.
-                            }
-                        }
-                    },
-                    'additionalProperties': False,
-                    'required': ['id', 'status', 'displayName',
-                                 'availabilityZone', 'createdAt',
-                                 'displayDescription', 'volumeType',
-                                 'snapshotId', 'metadata', 'size',
-                                 'attachments']
-                }
-            }
-        },
-        'additionalProperties': False,
-        'required': ['volumes']
-    }
-}
-
-delete_volume = {
-    'status_code': [202]
-}
diff --git a/tempest/clients.py b/tempest/clients.py
index fe44094..2b3f28d 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -59,6 +59,8 @@
 from tempest_lib.services.compute.tenant_usages_client import \
     TenantUsagesClient
 from tempest_lib.services.compute.versions_client import VersionsClient
+from tempest_lib.services.compute.volumes_client import \
+    VolumesClient as ComputeVolumesClient
 from tempest_lib.services.identity.v2.token_client import TokenClient
 from tempest_lib.services.identity.v3.token_client import V3TokenClient
 
@@ -77,8 +79,6 @@
 from tempest.services.compute.json.server_groups_client import \
     ServerGroupsClient
 from tempest.services.compute.json.servers_client import ServersClient
-from tempest.services.compute.json.volumes_client import \
-    VolumesClient as ComputeVolumesClient
 from tempest.services.data_processing.v1_1.data_processing_client import \
     DataProcessingClient
 from tempest.services.database.json.flavors_client import \
diff --git a/tempest/services/botoclients.py b/tempest/services/botoclients.py
index e117719..9d452ff 100644
--- a/tempest/services/botoclients.py
+++ b/tempest/services/botoclients.py
@@ -101,8 +101,8 @@
                 break
         else:
             ec2_cred = (identity_client.create_user_ec2_credentials(
-                identity_client.user_id, identity_client.tenant_id)
-                ['credential'])
+                identity_client.user_id,
+                tenant_id=identity_client.tenant_id)['credential'])
         if not all((ec2_cred, ec2_cred['access'], ec2_cred['secret'])):
             raise lib_exc.NotFound("Unable to get access and secret keys")
         else:
diff --git a/tempest/services/compute/json/volumes_client.py b/tempest/services/compute/json/volumes_client.py
deleted file mode 100644
index 69d982e..0000000
--- a/tempest/services/compute/json/volumes_client.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright 2012 OpenStack Foundation
-# All Rights Reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
-from tempest_lib import exceptions as lib_exc
-
-from tempest.api_schema.response.compute.v2_1 import volumes as schema
-from tempest.common import service_client
-
-
-class VolumesClient(service_client.ServiceClient):
-
-    def list_volumes(self, detail=False, **params):
-        """List all the volumes created."""
-        url = 'os-volumes'
-
-        if detail:
-            url += '/detail'
-        if params:
-            url += '?%s' % urllib.urlencode(params)
-
-        resp, body = self.get(url)
-        body = json.loads(body)
-        self.validate_response(schema.list_volumes, resp, body)
-        return service_client.ResponseBody(resp, body)
-
-    def show_volume(self, volume_id):
-        """Returns the details of a single volume."""
-        url = "os-volumes/%s" % volume_id
-        resp, body = self.get(url)
-        body = json.loads(body)
-        self.validate_response(schema.create_get_volume, resp, body)
-        return service_client.ResponseBody(resp, body)
-
-    def create_volume(self, **kwargs):
-        """Creates a new Volume.
-
-        size(Required): Size of volume in GB.
-        Following optional keyword arguments are accepted:
-        display_name: Optional Volume Name.
-        metadata: A dictionary of values to be used as metadata.
-        """
-        post_body = json.dumps({'volume': kwargs})
-        resp, body = self.post('os-volumes', post_body)
-        body = json.loads(body)
-        self.validate_response(schema.create_get_volume, resp, body)
-        return service_client.ResponseBody(resp, body)
-
-    def delete_volume(self, volume_id):
-        """Deletes the Specified Volume."""
-        resp, body = self.delete("os-volumes/%s" % volume_id)
-        self.validate_response(schema.delete_volume, resp, body)
-        return service_client.ResponseBody(resp, body)
-
-    def is_resource_deleted(self, id):
-        try:
-            self.show_volume(id)
-        except lib_exc.NotFound:
-            return True
-        return False
-
-    @property
-    def resource_type(self):
-        """Returns the primary type of resource this client works with."""
-        return 'volume'
diff --git a/tempest/services/identity/v2/json/identity_client.py b/tempest/services/identity/v2/json/identity_client.py
index 3f6727d..3e7a598 100644
--- a/tempest/services/identity/v2/json/identity_client.py
+++ b/tempest/services/identity/v2/json/identity_client.py
@@ -307,8 +307,11 @@
         body = json.loads(body)
         return service_client.ResponseBody(resp, body)
 
-    def create_user_ec2_credentials(self, user_id, tenant_id):
-        post_body = json.dumps({'tenant_id': tenant_id})
+    def create_user_ec2_credentials(self, user_id, **kwargs):
+        # TODO(piyush): Current api-site doesn't contain this API description.
+        # After fixing the api-site, we need to fix here also for putting the
+        # link to api-site.
+        post_body = json.dumps(kwargs)
         resp, body = self.post('/users/%s/credentials/OS-EC2' % user_id,
                                post_body)
         self.expected_success(200, resp.status)
diff --git a/tempest/tests/common/test_service_clients.py b/tempest/tests/common/test_service_clients.py
index f051ac0..7e5f0cb 100644
--- a/tempest/tests/common/test_service_clients.py
+++ b/tempest/tests/common/test_service_clients.py
@@ -21,8 +21,6 @@
 from tempest.services.compute.json import security_group_rules_client
 from tempest.services.compute.json import server_groups_client
 from tempest.services.compute.json import servers_client
-from tempest.services.compute.json import volumes_client \
-    as compute_volumes_client
 from tempest.services.data_processing.v1_1 import data_processing_client
 from tempest.services.database.json import flavors_client as db_flavor_client
 from tempest.services.database.json import versions_client as db_version_client
@@ -93,7 +91,6 @@
             security_group_rules_client.SecurityGroupRulesClient,
             server_groups_client.ServerGroupsClient,
             servers_client.ServersClient,
-            compute_volumes_client.VolumesClient,
             data_processing_client.DataProcessingClient,
             db_flavor_client.DatabaseFlavorsClient,
             db_version_client.DatabaseVersionsClient,
diff --git a/tempest/tests/services/compute/test_volumes_client.py b/tempest/tests/services/compute/test_volumes_client.py
deleted file mode 100644
index 33d4bad..0000000
--- a/tempest/tests/services/compute/test_volumes_client.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# Copyright 2015 NEC Corporation.  All rights reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-import copy
-
-from oslotest import mockpatch
-from tempest_lib import exceptions as lib_exc
-
-from tempest.services.compute.json import volumes_client
-from tempest.tests import fake_auth_provider
-from tempest.tests.services.compute import base
-
-
-class TestVolumesClient(base.BaseComputeServiceTest):
-
-    FAKE_VOLUME = {
-        "id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
-        "displayName": u"v\u12345ol-001",
-        "displayDescription": u"Another \u1234volume.",
-        "size": 30,
-        "status": "Active",
-        "volumeType": "289da7f8-6440-407c-9fb4-7db01ec49164",
-        "metadata": {
-            "contents": "junk"
-        },
-        "availabilityZone": "us-east1",
-        "snapshotId": None,
-        "attachments": [],
-        "createdAt": "2012-02-14T20:53:07Z"
-    }
-
-    FAKE_VOLUMES = {"volumes": [FAKE_VOLUME]}
-
-    def setUp(self):
-        super(TestVolumesClient, self).setUp()
-        fake_auth = fake_auth_provider.FakeAuthProvider()
-        self.client = volumes_client.VolumesClient(
-            fake_auth, 'compute', 'regionOne')
-
-    def _test_list_volumes(self, bytes_body=False, **params):
-        self.check_service_client_function(
-            self.client.list_volumes,
-            'tempest.common.service_client.ServiceClient.get',
-            self.FAKE_VOLUMES, to_utf=bytes_body, **params)
-
-    def test_list_volumes_with_str_body(self):
-        self._test_list_volumes()
-
-    def test_list_volumes_with_byte_body(self):
-        self._test_list_volumes(bytes_body=True)
-
-    def test_list_volumes_with_params(self):
-        self._test_list_volumes(name='fake')
-
-    def _test_show_volume(self, bytes_body=False):
-        self.check_service_client_function(
-            self.client.show_volume,
-            'tempest.common.service_client.ServiceClient.get',
-            {"volume": self.FAKE_VOLUME},
-            to_utf=bytes_body, volume_id=self.FAKE_VOLUME['id'])
-
-    def test_show_volume_with_str_body(self):
-        self._test_show_volume()
-
-    def test_show_volume_with_bytes_body(self):
-        self._test_show_volume(bytes_body=True)
-
-    def _test_create_volume(self, bytes_body=False):
-        post_body = copy.deepcopy(self.FAKE_VOLUME)
-        del post_body['id']
-        del post_body['createdAt']
-        del post_body['status']
-        self.check_service_client_function(
-            self.client.create_volume,
-            'tempest.common.service_client.ServiceClient.post',
-            {"volume": self.FAKE_VOLUME},
-            to_utf=bytes_body, status=200, **post_body)
-
-    def test_create_volume_with_str_body(self):
-        self._test_create_volume()
-
-    def test_create_volume_with_bytes_body(self):
-        self._test_create_volume(bytes_body=True)
-
-    def test_delete_volume(self):
-        self.check_service_client_function(
-            self.client.delete_volume,
-            'tempest.common.service_client.ServiceClient.delete',
-            {}, status=202, volume_id=self.FAKE_VOLUME['id'])
-
-    def test_is_resource_deleted_true(self):
-        module = ('tempest.services.compute.json.volumes_client.'
-                  'VolumesClient.show_volume')
-        self.useFixture(mockpatch.Patch(
-            module, side_effect=lib_exc.NotFound))
-        self.assertTrue(self.client.is_resource_deleted('fake-id'))
-
-    def test_is_resource_deleted_false(self):
-        module = ('tempest.services.compute.json.volumes_client.'
-                  'VolumesClient.show_volume')
-        self.useFixture(mockpatch.Patch(
-            module, return_value={}))
-        self.assertFalse(self.client.is_resource_deleted('fake-id'))