Merge "Enhance test_server_actions_rbac with index/detail/show server actions."
diff --git a/patrole_tempest_plugin/tests/api/compute/test_quota_sets_rbac.py b/patrole_tempest_plugin/tests/api/compute/test_quota_sets_rbac.py
new file mode 100644
index 0000000..a7f8447
--- /dev/null
+++ b/patrole_tempest_plugin/tests/api/compute/test_quota_sets_rbac.py
@@ -0,0 +1,106 @@
+# 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.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+from tempest import test
+
+from patrole_tempest_plugin import rbac_rule_validation
+from patrole_tempest_plugin.tests.api.compute import rbac_base
+
+
+class QuotaSetsRbacTest(rbac_base.BaseV2ComputeRbacTest):
+
+ @classmethod
+ def setup_clients(cls):
+ super(QuotaSetsRbacTest, cls).setup_clients()
+ cls.client = cls.quotas_client
+ cls.projects_client = cls.os.projects_client
+
+ @classmethod
+ def skip_checks(cls):
+ super(QuotaSetsRbacTest, cls).skip_checks()
+ if not test.is_extension_enabled('os-quota-sets', 'compute'):
+ msg = "%s skipped as quotas extension not enabled."\
+ % cls.__name__
+ raise cls.skipException(msg)
+
+ @classmethod
+ def resource_setup(cls):
+ super(QuotaSetsRbacTest, cls).resource_setup()
+ cls.tenant_id = cls.quotas_client.tenant_id
+ cls.user_id = cls.quotas_client.user_id
+ cls.quota_set = set(('injected_file_content_bytes',
+ 'metadata_items', 'injected_files',
+ 'ram', 'floating_ips', 'fixed_ips', 'key_pair',
+ 'injected_file_path_bytes', 'instances',
+ 'security_group_rules', 'cores',
+ 'security_groups'))
+
+ @decorators.idempotent_id('8229ceb0-db6a-4a2c-99c2-de226905d8b6')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-quota-sets:update")
+ def test_update_quota_set(self):
+ default_quota_set = self.client.show_default_quota_set(
+ self.tenant_id)['quota_set']
+ default_quota_set.pop('id')
+ new_quota_set = {'injected_file_content_bytes': 20480}
+
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.client.update_quota_set(self.tenant_id,
+ force=True,
+ **new_quota_set)['quota_set']
+ self.addCleanup(self.client.update_quota_set, self.tenant_id,
+ **default_quota_set)
+
+ @decorators.idempotent_id('58df5613-8f3c-400a-8b4b-2bae624d05e9')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-quota-sets:defaults")
+ def test_show_default_quota_set(self):
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.client.show_default_quota_set(self.tenant_id)['quota_set']
+
+ @decorators.idempotent_id('e8169ac4-c402-4864-894e-aba74e3a459c')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-quota-sets:show")
+ def test_show_quota_set(self):
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.client.show_quota_set(self.tenant_id)['quota_set']
+
+ @decorators.idempotent_id('4e240644-bf61-4872-9c32-8289ee2fdbbd')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-quota-sets:delete")
+ def test_delete_quota_set(self):
+ project_name = data_utils.rand_name('project')
+ project = self.projects_client.create_project(name=project_name)
+ project_id = project['project']['id']
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.projects_client.delete_project, project_id)
+
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.client.delete_quota_set(project_id)
+
+ @decorators.idempotent_id('ac9184b6-f3b3-4e17-a632-4b92c6500f86')
+ @rbac_rule_validation.action(
+ service="nova",
+ rule="os_compute_api:os-quota-sets:detail")
+ def test_show_quota_set_details(self):
+ self.rbac_utils.switch_role(self, switchToRbacRole=True)
+ self.client.show_quota_set(self.tenant_id, detail=True)['quota_set']
diff --git a/patrole_tempest_plugin/tests/api/volume/admin/test_volumes_backup_admin_rbac.py b/patrole_tempest_plugin/tests/api/volume/admin/test_volumes_backup_admin_rbac.py
index e78f80d..a89aa87 100644
--- a/patrole_tempest_plugin/tests/api/volume/admin/test_volumes_backup_admin_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/admin/test_volumes_backup_admin_rbac.py
@@ -13,7 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+from oslo_serialization import base64
+from oslo_serialization import jsonutils as json
from tempest import config
+from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest import test
@@ -36,6 +39,18 @@
super(VolumesBackupsAdminRbacTest, cls).resource_setup()
cls.volume = cls.create_volume()
+ def _decode_url(self, backup_url):
+ return json.loads(base64.decode_as_text(backup_url))
+
+ def _encode_backup(self, backup):
+ retval = json.dumps(backup)
+ return base64.encode_as_text(retval)
+
+ def _modify_backup_url(self, backup_url, changes):
+ backup = self._decode_url(backup_url)
+ backup.update(changes)
+ return self._encode_backup(backup)
+
@test.attr(type='slow')
@rbac_rule_validation.action(service="cinder",
rule="backup:backup-export")
@@ -58,11 +73,14 @@
# Export a temp backup
export_backup = self.backups_client.export_backup(
backup['id'])['backup-record']
+ new_id = data_utils.rand_uuid()
+ new_url = self._modify_backup_url(
+ export_backup['backup_url'], {'id': new_id})
# Import the temp backup
self.rbac_utils.switch_role(self, switchToRbacRole=True)
import_backup = self.backups_client.import_backup(
backup_service=export_backup['backup_service'],
- backup_url=export_backup['backup_url'])['backup']
+ backup_url=new_url)['backup']
self.addCleanup(self.backups_client.delete_backup, import_backup['id'])
diff --git a/patrole_tempest_plugin/tests/api/volume/rbac_base.py b/patrole_tempest_plugin/tests/api/volume/rbac_base.py
index c762473..2a14b19 100644
--- a/patrole_tempest_plugin/tests/api/volume/rbac_base.py
+++ b/patrole_tempest_plugin/tests/api/volume/rbac_base.py
@@ -57,7 +57,8 @@
cls.rbac_utils.switch_role(cls, switchToRbacRole=False)
version_checker = {
1: [cls.os.volume_hosts_client, cls.os.volume_types_client],
- 2: [cls.os.volume_hosts_v2_client, cls.os.volume_types_v2_client]
+ 2: [cls.os.volume_hosts_v2_client, cls.os.volume_types_v2_client],
+ 3: [cls.os.volume_hosts_v2_client, cls.os.volume_types_v2_client]
}
cls.volume_hosts_client, cls.volume_types_client = \
version_checker[cls._api_version]
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 d4ede3d..996e2b7 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
@@ -13,6 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+import testtools
+
+from tempest.common import compute
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import data_utils
@@ -28,58 +31,56 @@
class VolumesActionsRbacTest(rbac_base.BaseVolumeRbacTest):
@classmethod
- def skip_checks(cls):
- super(VolumesActionsRbacTest, cls).skip_checks()
- # Nova is needed to create a server
- if not CONF.service_available.nova:
- skip_msg = ("%s skipped as nova is not available" % cls.__name__)
- raise cls.skipException(skip_msg)
- # Glance is needed to create an image
- if not CONF.service_available.glance:
- skip_msg = ("%s skipped as glance is not available" % cls.__name__)
- raise cls.skipException(skip_msg)
-
- @classmethod
def setup_clients(cls):
super(VolumesActionsRbacTest, cls).setup_clients()
cls.client = cls.os.volumes_client
- cls.image_client = cls.os.image_client
@classmethod
def resource_setup(cls):
super(VolumesActionsRbacTest, cls).resource_setup()
cls.volume = cls.create_volume()
- def _attach_volume(self):
- server = self.create_server(wait_until='ACTIVE')
+ def _create_server(self):
+ body, _ = compute.create_test_server(self.os, wait_until='ACTIVE')
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.servers_client.delete_server, body['id'])
+ return body
+
+ def _attach_volume(self, server):
self.servers_client.attach_volume(
server['id'], volumeId=self.volume['id'],
device='/dev/%s' % CONF.compute.volume_device_name)
- waiters.wait_for_volume_status(self.client,
- self.volume['id'], 'in-use')
+ waiters.wait_for_volume_resource_status(
+ self.client, self.volume['id'], 'in-use')
self.addCleanup(self._detach_volume)
def _detach_volume(self):
self.client.detach_volume(self.volume['id'])
- waiters.wait_for_volume_status(self.client, self.volume['id'],
- 'available')
+ waiters.wait_for_volume_resource_status(
+ self.client, self.volume['id'], 'available')
+ @testtools.skipUnless(CONF.service_available.nova,
+ "Nova is required to create a server")
@rbac_rule_validation.action(service="cinder", rule="volume:attach")
@decorators.idempotent_id('f97b10e4-2eed-4f8b-8632-71c02cb9fe42')
def test_attach_volume_to_instance(self):
+ server = self._create_server()
self.rbac_utils.switch_role(self, switchToRbacRole=True)
# Attach the volume
- self._attach_volume()
+ self._attach_volume(server)
@rbac_rule_validation.action(service="cinder", rule="volume:detach")
@decorators.idempotent_id('5a042f6a-688b-42e6-a02e-fe5c47b89b07')
def test_detach_volume_to_instance(self):
# Attach the volume
- self._attach_volume()
+ server = self._create_server()
+ self._attach_volume(server)
self.rbac_utils.switch_role(self, switchToRbacRole=True)
# 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):
@@ -87,20 +88,22 @@
# 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")
@decorators.idempotent_id('b0d0da46-903c-4445-893e-20e680d68b50')
def test_volume_upload(self):
+ self.image_client = self.os.image_client
image_name = data_utils.rand_name('image')
self.rbac_utils.switch_role(self, switchToRbacRole=True)
body = self.client.upload_volume(
self.volume['id'], image_name=image_name,
disk_format=CONF.volume.disk_format)['os-volume_upload_image']
- image_id = body['image_id']
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.image_client.delete_image,
- image_id)
- waiters.wait_for_image_status(self.image_client, image_id, 'active')
+ body['image_id'])
+ waiters.wait_for_volume_resource_status(
+ self.client, self.volume['id'], 'available')
@rbac_rule_validation.action(service="cinder",
rule="volume:update_readonly_flag")
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volume_transfers_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volume_transfers_rbac.py
index 5c86da4..358733f 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volume_transfers_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volume_transfers_rbac.py
@@ -26,7 +26,7 @@
class VolumesTransfersRbacTest(rbac_base.BaseVolumeRbacTest):
- credentials = ['alt', 'admin']
+ credentials = ['primary', 'admin', 'alt']
@classmethod
def setup_clients(cls):
@@ -46,8 +46,8 @@
# the test to fail
test_utils.call_and_ignore_notfound_exc(
self.client.delete_volume_transfer, transfer['id'])
- waiters.wait_for_volume_status(self.client, self.volume['id'],
- 'available')
+ waiters.wait_for_volume_resource_status(
+ self.client, self.volume['id'], 'available')
def _create_transfer(self):
transfer = self.client.create_volume_transfer(
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py
index 9902f0d..8480d01 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volumes_backup_rbac.py
@@ -16,6 +16,7 @@
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from patrole_tempest_plugin import rbac_rule_validation
@@ -34,7 +35,7 @@
def create_backup(self, volume_id):
backup_name = data_utils.rand_name(
- self.__class__.__name__ + '-Backup')
+ self.__class__.__name__ + '-backup')
backup = self.backups_client.create_backup(
volume_id=volume_id, name=backup_name)['backup']
self.addCleanup(self.backups_client.delete_backup, backup['id'])
@@ -47,19 +48,30 @@
super(VolumesBackupsRbacTest, cls).resource_setup()
cls.volume = cls.create_volume()
+ def _create_backup(self, volume_id):
+ backup_name = data_utils.rand_name('backup')
+ backup = self.backups_client.create_backup(
+ volume_id=volume_id, name=backup_name)['backup']
+ self.addCleanup(
+ test_utils.call_and_ignore_notfound_exc,
+ self.backups_client.delete_backup, backup['id'])
+ waiters.wait_for_volume_resource_status(
+ self.backups_client, backup['id'], 'available')
+ return backup
+
@rbac_rule_validation.action(service="cinder",
rule="backup:create")
@decorators.idempotent_id('6887ec94-0bcf-4ab7-b30f-3808a4b5a2a5')
def test_volume_backup_create(self):
self.rbac_utils.switch_role(self, switchToRbacRole=True)
- self.create_backup(volume_id=self.volume['id'])
+ self._create_backup(volume_id=self.volume['id'])
@rbac_rule_validation.action(service="cinder",
rule="backup:get")
@decorators.idempotent_id('abd92bdd-b0fb-4dc4-9cfc-de9e968f8c8a')
def test_volume_backup_get(self):
# Create a temp backup
- backup = self.create_backup(volume_id=self.volume['id'])
+ backup = self._create_backup(volume_id=self.volume['id'])
# Get a given backup
self.rbac_utils.switch_role(self, switchToRbacRole=True)
self.backups_client.show_backup(backup['id'])
@@ -76,17 +88,19 @@
@decorators.idempotent_id('9c794bf9-2446-4f41-8fe0-80b71e757f9d')
def test_volume_backup_restore(self):
# Create a temp backup
- backup = self.create_backup(volume_id=self.volume['id'])
+ backup = self._create_backup(volume_id=self.volume['id'])
# Restore backup
self.rbac_utils.switch_role(self, switchToRbacRole=True)
- self.backups_client.restore_backup(backup['id'])['restore']
+ restore = self.backups_client.restore_backup(backup['id'])['restore']
+ waiters.wait_for_volume_resource_status(
+ self.backups_client, restore['backup_id'], 'available')
@rbac_rule_validation.action(service="cinder",
rule="backup:delete")
@decorators.idempotent_id('d5d0c6a2-413d-437e-a73f-4bf2b41a20ed')
def test_volume_backup_delete(self):
# Create a temp backup
- backup = self.create_backup(volume_id=self.volume['id'])
+ backup = self._create_backup(volume_id=self.volume['id'])
self.rbac_utils.switch_role(self, switchToRbacRole=True)
# Delete backup
self.backups_client.delete_backup(backup['id'])
diff --git a/patrole_tempest_plugin/tests/api/volume/test_volumes_extend_rbac.py b/patrole_tempest_plugin/tests/api/volume/test_volumes_extend_rbac.py
index e8c620f..64493c5 100644
--- a/patrole_tempest_plugin/tests/api/volume/test_volumes_extend_rbac.py
+++ b/patrole_tempest_plugin/tests/api/volume/test_volumes_extend_rbac.py
@@ -39,8 +39,8 @@
self.rbac_utils.switch_role(self, switchToRbacRole=True)
self.volumes_client.extend_volume(self.volume['id'],
new_size=extend_size)
- waiters.wait_for_volume_status(self.volumes_client, self.volume['id'],
- 'available')
+ waiters.wait_for_volume_resource_status(
+ self.volumes_client, self.volume['id'], 'available')
class VolumesExtendV3RbacTest(VolumesExtendRbacTest):