Merge "Switch to decorators.idempotent_id on compute.*"
diff --git a/tempest/api/volume/admin/test_volume_types_negative.py b/tempest/api/volume/admin/test_volume_types_negative.py
index 857e7d2..5332f1e 100644
--- a/tempest/api/volume/admin/test_volume_types_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_negative.py
@@ -51,6 +51,14 @@
                           self.admin_volume_types_client.delete_volume_type,
                           data_utils.rand_uuid())
 
+    @test.idempotent_id('8c09f849-f225-4d78-ba87-bffd9a5e0c6f')
+    def test_create_volume_with_private_volume_type(self):
+        # Should not be able to create volume with private volume type.
+        params = {'os-volume-type-access:is_public': False}
+        volume_type = self.create_volume_type(**params)
+        self.assertRaises(lib_exc.NotFound,
+                          self.create_volume, volume_type=volume_type['id'])
+
 
 class VolumeTypesNegativeV1Test(VolumeTypesNegativeV2Test):
     _api_version = 1
diff --git a/tempest/api/volume/v2/test_volumes_snapshots_list.py b/tempest/api/volume/v2/test_volumes_snapshots_list.py
new file mode 100644
index 0000000..8f68322
--- /dev/null
+++ b/tempest/api/volume/v2/test_volumes_snapshots_list.py
@@ -0,0 +1,96 @@
+# Copyright 2016 Red Hat, Inc.
+# 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 operator
+
+from tempest.api.volume import base
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+
+class VolumesV2SnapshotListTestJSON(base.BaseVolumeTest):
+
+    @classmethod
+    def skip_checks(cls):
+        super(VolumesV2SnapshotListTestJSON, cls).skip_checks()
+        if not CONF.volume_feature_enabled.snapshot:
+            raise cls.skipException("Cinder volume snapshots are disabled")
+
+    @classmethod
+    def resource_setup(cls):
+        super(VolumesV2SnapshotListTestJSON, cls).resource_setup()
+        cls.snapshot_id_list = []
+        # Create a volume
+        cls.volume_origin = cls.create_volume()
+        cls.name_field = cls.special_fields['name_field']
+        # Create 3 snapshots
+        for _ in range(3):
+            snapshot = cls.create_snapshot(cls.volume_origin['id'])
+            cls.snapshot_id_list.append(snapshot['id'])
+
+    def _list_snapshots_param_sort(self, sort_key, sort_dir):
+        """list snapshots by sort param"""
+        snap_list = self.snapshots_client.list_snapshots(
+            sort_key=sort_key, sort_dir=sort_dir)['snapshots']
+        self.assertNotEmpty(snap_list)
+        if sort_key is 'display_name':
+            sort_key = 'name'
+        # Note: On Cinder V2 API, 'display_name' works as a sort key
+        # on a request, a volume name appears as 'name' on the response.
+        # So Tempest needs to change the key name here for this inconsistent
+        # API behavior.
+        sorted_list = [snapshot[sort_key] for snapshot in snap_list]
+        msg = 'The list of snapshots was not sorted correctly.'
+        self.assertEqual(sorted(sorted_list, reverse=(sort_dir == 'desc')),
+                         sorted_list, msg)
+
+    @test.idempotent_id('c5513ada-64c1-4d28-83b9-af3307ec1388')
+    def test_snapshot_list_param_sort_id_asc(self):
+        self._list_snapshots_param_sort(sort_key='id', sort_dir='asc')
+
+    @test.idempotent_id('8a7fe058-0b41-402a-8afd-2dbc5a4a718b')
+    def test_snapshot_list_param_sort_id_desc(self):
+        self._list_snapshots_param_sort(sort_key='id', sort_dir='desc')
+
+    @test.idempotent_id('4052c3a0-2415-440a-a8cc-305a875331b0')
+    def test_snapshot_list_param_sort_created_at_asc(self):
+        self._list_snapshots_param_sort(sort_key='created_at', sort_dir='asc')
+
+    @test.idempotent_id('dcbbe24a-f3c0-4ec8-9274-55d48db8d1cf')
+    def test_snapshot_list_param_sort_created_at_desc(self):
+        self._list_snapshots_param_sort(sort_key='created_at', sort_dir='desc')
+
+    @test.idempotent_id('d58b5fed-0c37-42d3-8c5d-39014ac13c00')
+    def test_snapshot_list_param_sort_name_asc(self):
+        self._list_snapshots_param_sort(sort_key='display_name',
+                                        sort_dir='asc')
+
+    @test.idempotent_id('96ba6f4d-1f18-47e1-b4bc-76edc6c21250')
+    def test_snapshot_list_param_sort_name_desc(self):
+        self._list_snapshots_param_sort(sort_key='display_name',
+                                        sort_dir='desc')
+
+    @test.idempotent_id('05489dde-44bc-4961-a1f5-3ce7ee7824f7')
+    def test_snapshot_list_param_marker(self):
+        # The list of snapshots should end before the provided marker
+        params = {'marker': self.snapshot_id_list[1]}
+        snap_list = self.snapshots_client.list_snapshots(**params)['snapshots']
+        fetched_list_id = map(operator.itemgetter('id'), snap_list)
+        # Verify the list of snapshots ends before the provided
+        # marker(second snapshot), therefore only the first snapshot
+        # should displayed.
+        self.assertEqual(self.snapshot_id_list[:1], fetched_list_id)
diff --git a/tempest/tests/lib/services/identity/v3/test_roles_client.py b/tempest/tests/lib/services/identity/v3/test_roles_client.py
index bad1ef9..4f70b47 100644
--- a/tempest/tests/lib/services/identity/v3/test_roles_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_roles_client.py
@@ -18,32 +18,40 @@
 
 
 class TestRolesClient(base.BaseServiceTest):
+
+    FAKE_ROLE_ID = "1"
+    FAKE_ROLE_NAME = "test"
+    FAKE_DOMAIN_ID = "1"
+
+    FAKE_ROLE_ID_2 = "2"
+    FAKE_ROLE_NAME_2 = "test2"
+
     FAKE_ROLE_INFO = {
         "role": {
-            "domain_id": "1",
-            "id": "1",
-            "name": "test",
-            "links": "example.com"
+            "domain_id": FAKE_DOMAIN_ID,
+            "id": FAKE_ROLE_ID,
+            "name": FAKE_ROLE_NAME,
+            "links": {
+                "self": "http://example.com/identity/v3/roles/%s" % (
+                    FAKE_ROLE_ID)
+            }
         }
     }
 
-    FAKE_LIST_ROLES = {
-        "roles": [
-            {
-                "domain_id": "1",
-                "id": "1",
-                "name": "test",
-                "links": "example.com"
-            },
-            {
-                "domain_id": "2",
-                "id": "2",
-                "name": "test2",
-                "links": "example.com"
+    FAKE_ROLE_INFO_2 = {
+        "role": {
+            "domain_id": FAKE_DOMAIN_ID,
+            "id": FAKE_ROLE_ID_2,
+            "name": FAKE_ROLE_NAME_2,
+            "links": {
+                "self": "http://example.com/identity/v3/roles/%s" % (
+                    FAKE_ROLE_ID_2)
             }
-        ]
+        }
     }
 
+    FAKE_LIST_ROLES = {"roles": [FAKE_ROLE_INFO, FAKE_ROLE_INFO_2]}
+
     def setUp(self):
         super(TestRolesClient, self).setUp()
         fake_auth = fake_auth_provider.FakeAuthProvider()
@@ -56,8 +64,8 @@
             'tempest.lib.common.rest_client.RestClient.post',
             self.FAKE_ROLE_INFO,
             bytes_body,
-            domain_id="1",
-            name="test",
+            domain_id=self.FAKE_DOMAIN_ID,
+            name=self.FAKE_ROLE_NAME,
             status=201)
 
     def _test_show_role(self, bytes_body=False):
@@ -66,7 +74,7 @@
             'tempest.lib.common.rest_client.RestClient.get',
             self.FAKE_ROLE_INFO,
             bytes_body,
-            role_id="1")
+            role_id=self.FAKE_ROLE_ID)
 
     def _test_list_roles(self, bytes_body=False):
         self.check_service_client_function(
@@ -81,8 +89,8 @@
             'tempest.lib.common.rest_client.RestClient.patch',
             self.FAKE_ROLE_INFO,
             bytes_body,
-            role_id="1",
-            name="test")
+            role_id=self.FAKE_ROLE_ID,
+            name=self.FAKE_ROLE_NAME)
 
     def _test_create_user_role_on_project(self, bytes_body=False):
         self.check_service_client_function(
@@ -193,7 +201,7 @@
             self.client.delete_role,
             'tempest.lib.common.rest_client.RestClient.delete',
             {},
-            role_id="1",
+            role_id=self.FAKE_ROLE_ID,
             status=204)
 
     def test_create_user_role_on_project_with_str_body(self):