Merge "Fix failing v2 identity user tests by adding admin_only kwarg."
diff --git a/patrole_tempest_plugin/tests/api/network/test_ports_rbac.py b/patrole_tempest_plugin/tests/api/network/test_ports_rbac.py
index 093459e..b45999c 100644
--- a/patrole_tempest_plugin/tests/api/network/test_ports_rbac.py
+++ b/patrole_tempest_plugin/tests/api/network/test_ports_rbac.py
@@ -22,6 +22,7 @@
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
+from patrole_tempest_plugin import rbac_exceptions
 from patrole_tempest_plugin import rbac_rule_validation
 from patrole_tempest_plugin.tests.api.network import rbac_base as base
 
@@ -34,25 +35,24 @@
     @classmethod
     def resource_setup(cls):
         super(PortsRbacTest, cls).resource_setup()
-        cls.admin_network = cls.create_network()
+        cls.network = cls.create_network()
 
         # Create a subnet by admin user
         cls.cidr = netaddr.IPNetwork(CONF.network.project_network_cidr)
 
-        cls.admin_subnet = cls.create_subnet(cls.admin_network,
-                                             cidr=cls.cidr,
-                                             mask_bits=24)
-        cls.admin_ip_range = netaddr.IPRange(
-            cls.admin_subnet['allocation_pools'][0]['start'],
-            cls.admin_subnet['allocation_pools'][0]['end'])
+        cls.subnet = cls.create_subnet(cls.network, cidr=cls.cidr,
+                                       mask_bits=24)
+        cls.ip_range = netaddr.IPRange(
+            cls.subnet['allocation_pools'][0]['start'],
+            cls.subnet['allocation_pools'][0]['end'])
 
         # Create a port by admin user
-        body = cls.ports_client.create_port(network_id=cls.admin_network['id'])
-        cls.admin_port = body['port']
-        cls.ports.append(cls.admin_port)
-        ipaddr = cls.admin_port['fixed_ips'][0]['ip_address']
-        cls.admin_port_ip_address = ipaddr
-        cls.admin_port_mac_address = cls.admin_port['mac_address']
+        body = cls.ports_client.create_port(network_id=cls.network['id'])
+        cls.port = body['port']
+        cls.ports.append(cls.port)
+        ipaddr = cls.port['fixed_ips'][0]['ip_address']
+        cls.port_ip_address = ipaddr
+        cls.port_mac_address = cls.port['mac_address']
 
     def _create_port(self, **post_body):
 
@@ -72,7 +72,7 @@
     def test_create_port(self):
 
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        post_body = {'network_id': self.admin_network['id']}
+        post_body = {'network_id': self.network['id']}
         self._create_port(**post_body)
 
     @rbac_rule_validation.action(service="neutron",
@@ -80,7 +80,7 @@
     @decorators.idempotent_id('a54bd6b8-a7eb-4101-bfe8-093930b0d660')
     def test_create_port_binding_host_id(self):
 
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'binding:host_id': "rbac_test_host"}
 
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
@@ -91,12 +91,12 @@
     @decorators.idempotent_id('2551e10d-006a-413c-925a-8c6f834c09ac')
     def test_create_port_fixed_ips(self):
         # Pick an ip address within the allocation_pools range
-        ip_address = random.choice(list(self.admin_ip_range))
+        ip_address = random.choice(list(self.ip_range))
 
         fixed_ips = [{'ip_address': ip_address},
-                     {'subnet_id': self.admin_subnet['id']}]
+                     {'subnet_id': self.subnet['id']}]
 
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'fixed_ips': fixed_ips}
 
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
@@ -107,7 +107,7 @@
     @decorators.idempotent_id('aee6d0be-a7f3-452f-aefc-796b4eb9c9a8')
     def test_create_port_mac_address(self):
 
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'mac_address': data_utils.rand_mac_address()}
 
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
@@ -120,7 +120,7 @@
 
         binding_profile = {"foo": "1"}
 
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'binding:profile': binding_profile}
 
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
@@ -132,10 +132,10 @@
     def test_create_port_allowed_address_pairs(self):
 
         # Create port with allowed address pair attribute
-        allowed_address_pairs = [{'ip_address': self.admin_port_ip_address,
-                                  'mac_address': self.admin_port_mac_address}]
+        allowed_address_pairs = [{'ip_address': self.port_ip_address,
+                                  'mac_address': self.port_mac_address}]
 
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'allowed_address_pairs': allowed_address_pairs}
 
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
@@ -147,11 +147,10 @@
     @decorators.idempotent_id('a9d41cb8-78a2-4b97-985c-44e4064416f4')
     def test_show_port(self):
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.ports_client.show_port(self.admin_port['id'])
+        self.ports_client.show_port(self.port['id'])
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="get_port:binding:vif_type",
-                                 expected_error_code=404)
+                                 rule="get_port:binding:vif_type")
     @decorators.idempotent_id('125aff0b-8fed-4f8e-8410-338616594b06')
     def test_show_port_binding_vif_type(self):
 
@@ -159,12 +158,16 @@
         fields = ['binding:vif_type']
 
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.ports_client.show_port(self.admin_port['id'],
-                                    fields=fields)
+
+        retrieved_port = self.ports_client.show_port(
+            self.port['id'], fields=fields)['port']
+
+        # Rather than throwing a 403, the field is not present, so raise exc.
+        if fields[0] not in retrieved_port:
+            raise rbac_exceptions.RbacActionFailed
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="get_port:binding:vif_details",
-                                 expected_error_code=404)
+                                 rule="get_port:binding:vif_details")
     @decorators.idempotent_id('e42bfd77-fcce-45ee-9728-3424300f0d6f')
     def test_show_port_binding_vif_details(self):
 
@@ -172,58 +175,70 @@
         fields = ['binding:vif_details']
 
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.ports_client.show_port(self.admin_port['id'],
-                                    fields=fields)
+
+        retrieved_port = self.ports_client.show_port(
+            self.port['id'], fields=fields)['port']
+
+        # Rather than throwing a 403, the field is not present, so raise exc.
+        if fields[0] not in retrieved_port:
+            raise rbac_exceptions.RbacActionFailed
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="get_port:binding:host_id",
-                                 expected_error_code=404)
+                                 rule="get_port:binding:host_id")
     @decorators.idempotent_id('8e61bcdc-6f81-443c-833e-44410266551e')
     def test_show_port_binding_host_id(self):
 
         # Verify specific fields of a port
         fields = ['binding:host_id']
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'binding:host_id': data_utils.rand_name('host-id')}
         port = self._create_port(**post_body)
 
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.ports_client.show_port(port['id'],
-                                    fields=fields)
+
+        retrieved_port = self.ports_client.show_port(
+            port['id'], fields=fields)['port']
+
+        # Rather than throwing a 403, the field is not present, so raise exc.
+        if fields[0] not in retrieved_port:
+            raise rbac_exceptions.RbacActionFailed
 
     @rbac_rule_validation.action(service="neutron",
-                                 rule="get_port:binding:profile",
-                                 expected_error_code=404)
+                                 rule="get_port:binding:profile")
     @decorators.idempotent_id('d497cea9-c4ad-42e0-acc9-8d257d6b01fc')
     def test_show_port_binding_profile(self):
 
         # Verify specific fields of a port
         fields = ['binding:profile']
         binding_profile = {"foo": "1"}
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'binding:profile': binding_profile}
         port = self._create_port(**post_body)
 
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.ports_client.show_port(port['id'],
-                                    fields=fields)
+
+        retrieved_port = self.ports_client.show_port(
+            port['id'], fields=fields)['port']
+
+        # Rather than throwing a 403, the field is not present, so raise exc.
+        if fields[0] not in retrieved_port:
+            raise rbac_exceptions.RbacActionFailed
 
     @rbac_rule_validation.action(service="neutron",
                                  rule="update_port")
     @decorators.idempotent_id('afa80981-3c59-42fd-9531-3bcb2cd03711')
     def test_update_port(self):
 
-        port = self.create_port(self.admin_network)
+        port = self.create_port(self.network)
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.ports_client.update_port(port['id'],
-                                      admin_state_up=False)
+        self.ports_client.update_port(port['id'], admin_state_up=False)
 
     @rbac_rule_validation.action(service="neutron",
                                  rule="update_port:mac_address")
     @decorators.idempotent_id('507140c8-7b14-4d63-b627-2103691d887e')
     def test_update_port_mac_address(self):
 
-        port = self.create_port(self.admin_network)
+        port = self.create_port(self.network)
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.ports_client.update_port(
             port['id'],
@@ -235,9 +250,9 @@
     def test_update_port_fixed_ips(self):
 
         # Pick an ip address within the allocation_pools range
-        ip_address = random.choice(list(self.admin_ip_range))
+        ip_address = random.choice(list(self.ip_range))
         fixed_ips = [{'ip_address': ip_address}]
-        post_body = {'network_id': self.admin_network['id']}
+        post_body = {'network_id': self.network['id']}
         port = self._create_port(**post_body)
 
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
@@ -249,7 +264,7 @@
     @decorators.idempotent_id('795541af-6652-4e35-9581-fd58224f7545')
     def test_update_port_security_enabled(self):
 
-        port = self.create_port(self.admin_network)
+        port = self.create_port(self.network)
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.ports_client.update_port(port['id'],
                                       security_groups=[])
@@ -259,7 +274,7 @@
     @decorators.idempotent_id('24206a72-0d90-4712-918c-5c9a1ebef64d')
     def test_update_port_binding_host_id(self):
 
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'binding:host_id': 'rbac_test_host'}
         port = self._create_port(**post_body)
 
@@ -275,7 +290,7 @@
     def test_update_port_binding_profile(self):
 
         binding_profile = {"foo": "1"}
-        post_body = {'network_id': self.admin_network['id'],
+        post_body = {'network_id': self.network['id'],
                      'binding:profile': binding_profile}
 
         port = self._create_port(**post_body)
@@ -292,11 +307,11 @@
     @decorators.idempotent_id('729c2151-bb49-4f4f-9d58-3ed8819b7582')
     def test_update_port_allowed_address_pairs(self):
 
-        ip_address = random.choice(list(self.admin_ip_range))
+        ip_address = random.choice(list(self.ip_range))
         # Update allowed address pair attribute of port
         address_pairs = [{'ip_address': ip_address,
                           'mac_address': data_utils.rand_mac_address()}]
-        post_body = {'network_id': self.admin_network['id']}
+        post_body = {'network_id': self.network['id']}
         port = self._create_port(**post_body)
 
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
@@ -309,6 +324,6 @@
     @decorators.idempotent_id('1cf8e582-bc09-46cb-b32a-82bf991ad56f')
     def test_delete_port(self):
 
-        port = self._create_port(network_id=self.admin_network['id'])
+        port = self._create_port(network_id=self.network['id'])
         self.rbac_utils.switch_role(self, switchToRbacRole=True)
         self.ports_client.delete_port(port['id'])
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py
index 996e2b7..29f6a80 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_actions_rbac.py
@@ -79,15 +79,6 @@
         # Detach the volume
         self._detach_volume()
 
-    @testtools.skipUnless(CONF.service_available.nova,
-                          "Nova is needed to create a server")
-    @rbac_rule_validation.action(service="cinder", rule="volume:get")
-    @decorators.idempotent_id('c4c3fdd5-b1b1-49c3-b977-a9f40ee9257a')
-    def test_get_volume_attachment(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        # Get attachment
-        self.client.show_volume(self.volume['id'])
-
     @testtools.skipIf(True, "Patrole bug #1672799")
     @rbac_rule_validation.action(service="cinder",
                                  rule="volume:copy_volume_to_image")
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_basic_crud.py b/patrole_tempest_plugin/tests/api/volume/test_volume_basic_crud.py
new file mode 100644
index 0000000..70f53fd
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_basic_crud.py
@@ -0,0 +1,78 @@
+# Copyright 2017 AT&T 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.
+
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.volume import rbac_base
+
+CONF = config.CONF
+
+
+class VolumesV2BasicCrudRbacTest(rbac_base.BaseVolumeRbacTest):
+
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="volume:create")
+    @decorators.idempotent_id('426b08ef-6394-4d06-9128-965d5a6c38ef')
+    def test_create_volume(self):
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.create_volume()
+
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="volume:delete")
+    @decorators.idempotent_id('6de9f9c2-509f-4558-867b-af21c7163be4')
+    def test_delete_volume(self):
+        volume = self.create_volume()
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.volumes_client.delete_volume(volume['id'])
+
+    @rbac_rule_validation.action(service="cinder", rule="volume:get")
+    @decorators.idempotent_id('c4c3fdd5-b1b1-49c3-b977-a9f40ee9257a')
+    def test_get_volume(self):
+        volume = self.create_volume()
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.volumes_client.show_volume(volume['id'])
+
+    @rbac_rule_validation.action(service="cinder",
+                                 rule="volume:get_all")
+    @decorators.idempotent_id('e3ab7906-b04b-4c45-aa11-1104d302f940')
+    def test_volume_list(self):
+        # Get a list of Volumes
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.volumes_client.list_volumes()
+
+    @rbac_rule_validation.action(
+        service="cinder",
+        rule="volume_extension:get_volumes_image_metadata")
+    @decorators.idempotent_id('3d48ca91-f02b-4616-a69d-4a8b296c8529')
+    def test_volume_list_image_metadata(self):
+        # Get a list of Volumes
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.volumes_client.list_volumes(detail=True)
+
+    @rbac_rule_validation.action(service="cinder", rule="volume:update")
+    @decorators.idempotent_id('b751b889-9a9b-40d8-ae7d-4b0f65e71ac7')
+    def test_update_volume(self):
+        volume = self.create_volume()
+        new_name = data_utils.rand_name('volume')
+        self.rbac_utils.switch_role(self, switchToRbacRole=True)
+        self.volumes_client.update_volume(volume['id'],
+                                          name=new_name)
+
+
+class VolumesV3BasicCrudRbacTest(VolumesV2BasicCrudRbacTest):
+    _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_create_delete_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_create_delete_rbac.py
deleted file mode 100644
index d028180..0000000
--- a/patrole_tempest_plugin/tests/api/volume/test_volume_create_delete_rbac.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright 2017 AT&T 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.
-
-from oslo_log import log as logging
-
-from tempest import config
-from tempest.lib import decorators
-from tempest.lib import exceptions
-
-from patrole_tempest_plugin import rbac_exceptions
-from patrole_tempest_plugin import rbac_rule_validation
-from patrole_tempest_plugin.tests.api.volume import rbac_base
-
-CONF = config.CONF
-LOG = logging.getLogger(__name__)
-
-
-class CreateDeleteVolumeRbacTest(rbac_base.BaseVolumeRbacTest):
-
-    def _create_volume(self):
-        # create_volume waits for volume status to be
-        # "available" before returning and automatically
-        # cleans up at the end of testing
-        volume = self.create_volume()
-        return volume
-
-    @rbac_rule_validation.action(service="cinder",
-                                 rule="volume:create")
-    @decorators.idempotent_id('426b08ef-6394-4d06-9128-965d5a6c38ef')
-    def test_create_volume(self):
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        # Create a volume
-        self._create_volume()
-
-    @rbac_rule_validation.action(service="cinder",
-                                 rule="volume:delete")
-    @decorators.idempotent_id('6de9f9c2-509f-4558-867b-af21c7163be4')
-    def test_delete_volume(self):
-        try:
-            # Create a volume
-            volume = self._create_volume()
-            self.rbac_utils.switch_role(self, switchToRbacRole=True)
-            # Delete a volume
-            self.volumes_client.delete_volume(volume['id'])
-        except exceptions.NotFound as e:
-            raise rbac_exceptions.RbacActionFailed(e)
-
-
-class CreateDeleteVolumeV3RbacTest(CreateDeleteVolumeRbacTest):
-    _api_version = 3
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volumes_list_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volumes_list_rbac.py
deleted file mode 100644
index 8c0a9e0..0000000
--- a/patrole_tempest_plugin/tests/api/volume/test_volumes_list_rbac.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2017 AT&T Corp
-# 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 tempest import config
-from tempest.lib import decorators
-
-from patrole_tempest_plugin import rbac_rule_validation
-from patrole_tempest_plugin.tests.api.volume import rbac_base
-
-CONF = config.CONF
-
-
-class VolumesListRbacTest(rbac_base.BaseVolumeRbacTest):
-
-    @classmethod
-    def setup_clients(cls):
-        super(VolumesListRbacTest, cls).setup_clients()
-        cls.client = cls.os.volumes_client
-
-    @rbac_rule_validation.action(service="cinder",
-                                 rule="volume:get_all")
-    @decorators.idempotent_id('e3ab7906-b04b-4c45-aa11-1104d302f940')
-    def test_volume_list(self):
-        # Get a list of Volumes
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.list_volumes()
-
-    @rbac_rule_validation.action(
-        service="cinder",
-        rule="volume_extension:get_volumes_image_metadata")
-    @decorators.idempotent_id('3d48ca91-f02b-4616-a69d-4a8b296c8529')
-    def test_volume_list_image_metadata(self):
-        # Get a list of Volumes
-        self.rbac_utils.switch_role(self, switchToRbacRole=True)
-        self.client.list_volumes(detail=True)
-
-
-class VolumeListV3RbacTest(VolumesListRbacTest):
-    _api_version = 3