# 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 unittest import mock import uuid import ddt from rally.common import cfg from rally import exceptions from rally_openstack.common import service from rally_openstack.common.services.storage import block from rally_openstack.common.services.storage import cinder_common from tests.unit import fakes from tests.unit import test BASE_PATH = "rally_openstack.common.services.storage" CONF = cfg.CONF class FullCinder(service.Service, cinder_common.CinderMixin): """Implementation of CinderMixin with Service base class.""" pass @ddt.ddt class CinderMixinTestCase(test.ScenarioTestCase): def setUp(self): super(CinderMixinTestCase, self).setUp() self.clients = mock.MagicMock() self.cinder = self.clients.cinder.return_value self.name_generator = uuid.uuid1 self.version = "some" self.service = FullCinder( clients=self.clients, name_generator=self.name_generator) self.service.version = self.version def atomic_actions(self): return self.service._atomic_actions def test__get_client(self): self.assertEqual(self.cinder, self.service._get_client()) def test__update_resource_with_manage(self): resource = mock.MagicMock(id=1, manager=mock.MagicMock()) self.assertEqual(resource.manager.get.return_value, self.service._update_resource(resource)) resource.manager.get.assert_called_once_with( resource.id) @ddt.data({"resource": block.Volume(id=1, name="vol", size=1, status="st"), "attr": "volumes"}, {"resource": block.VolumeSnapshot(id=2, name="snapshot", volume_id=1, status="st"), "attr": "volume_snapshots"}, {"resource": block.VolumeBackup(id=3, name="backup", volume_id=1, status="st"), "attr": "backups"}) @ddt.unpack def test__update_resource_with_no_manage(self, resource, attr): self.assertEqual(getattr(self.cinder, attr).get.return_value, self.service._update_resource(resource)) getattr(self.cinder, attr).get.assert_called_once_with( resource.id) def test__update_resource_with_not_found(self): manager = mock.MagicMock() resource = fakes.FakeResource(manager=manager, status="ERROR") class NotFoundException(Exception): http_status = 404 manager.get = mock.MagicMock(side_effect=NotFoundException) self.assertRaises(exceptions.GetResourceNotFound, self.service._update_resource, resource) def test__update_resource_with_http_exception(self): manager = mock.MagicMock() resource = fakes.FakeResource(manager=manager, status="ERROR") class HTTPException(Exception): pass manager.get = mock.MagicMock(side_effect=HTTPException) self.assertRaises(exceptions.GetResourceFailure, self.service._update_resource, resource) def test__wait_available_volume(self): volume = fakes.FakeVolume() self.assertEqual(self.mock_wait_for_status.mock.return_value, self.service._wait_available_volume(volume)) self.mock_wait_for_status.mock.assert_called_once_with( volume, ready_statuses=["available"], update_resource=self.service._update_resource, timeout=CONF.openstack.cinder_volume_create_timeout, check_interval=CONF.openstack.cinder_volume_create_poll_interval ) def test_get_volume(self): self.assertEqual(self.cinder.volumes.get.return_value, self.service.get_volume(1)) self.cinder.volumes.get.assert_called_once_with(1) @mock.patch("%s.block.BlockStorage.create_volume" % BASE_PATH) def test_delete_volume(self, mock_create_volume): volume = mock_create_volume.return_value self.service.delete_volume(volume) self.cinder.volumes.delete.assert_called_once_with(volume) self.mock_wait_for_status.mock.assert_called_once_with( volume, ready_statuses=["deleted"], check_deletion=True, update_resource=self.service._update_resource, timeout=CONF.openstack.cinder_volume_delete_timeout, check_interval=CONF.openstack.cinder_volume_delete_poll_interval ) @mock.patch("%s.block.BlockStorage.create_volume" % BASE_PATH) def test_extend_volume(self, mock_create_volume): volume = mock_create_volume.return_value self.service._wait_available_volume = mock.MagicMock() self.service._wait_available_volume.return_value = fakes.FakeVolume() self.assertEqual(self.service._wait_available_volume.return_value, self.service.extend_volume(volume, 1)) self.cinder.volumes.extend.assert_called_once_with(volume, 1) self.service._wait_available_volume.assert_called_once_with(volume) def test_list_snapshots(self): self.assertEqual(self.cinder.volume_snapshots.list.return_value, self.service.list_snapshots()) self.cinder.volume_snapshots.list.assert_called_once_with(True) def test_set_metadata(self): volume = fakes.FakeVolume() self.service.set_metadata(volume, sets=2, set_size=4) calls = self.cinder.volumes.set_metadata.call_args_list self.assertEqual(2, len(calls)) for call in calls: call_volume, metadata = call[0] self.assertEqual(volume, call_volume) self.assertEqual(4, len(metadata)) def test_delete_metadata(self): volume = fakes.FakeVolume() keys = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"] self.service.delete_metadata(volume, keys, deletes=3, delete_size=4) calls = self.cinder.volumes.delete_metadata.call_args_list self.assertEqual(3, len(calls)) all_deleted = [] for call in calls: call_volume, del_keys = call[0] self.assertEqual(volume, call_volume) self.assertEqual(4, len(del_keys)) for key in del_keys: self.assertIn(key, keys) self.assertNotIn(key, all_deleted) all_deleted.append(key) def test_delete_metadata_not_enough_keys(self): volume = fakes.FakeVolume() keys = ["a", "b", "c", "d", "e"] self.assertRaises(exceptions.InvalidArgumentsException, self.service.delete_metadata, volume, keys, deletes=2, delete_size=3) def test_update_readonly_flag(self): fake_volume = mock.MagicMock() self.service.update_readonly_flag(fake_volume, "fake_flag") self.cinder.volumes.update_readonly_flag.assert_called_once_with( fake_volume, "fake_flag") @mock.patch("rally_openstack.common.services.image.image.Image") def test_upload_volume_to_image(self, mock_image): volume = mock.Mock() image = {"os-volume_upload_image": {"image_id": 1}} self.cinder.volumes.upload_to_image.return_value = (None, image) glance = mock_image.return_value self.service.generate_random_name = mock.Mock( return_value="test_vol") self.service.upload_volume_to_image(volume, False, "container", "disk") self.cinder.volumes.upload_to_image.assert_called_once_with( volume, False, "test_vol", "container", "disk") self.mock_wait_for_status.mock.assert_has_calls([ mock.call( volume, ready_statuses=["available"], update_resource=self.service._update_resource, timeout=CONF.openstack.cinder_volume_create_timeout, check_interval=CONF.openstack. cinder_volume_create_poll_interval), mock.call( glance.get_image.return_value, ready_statuses=["active"], update_resource=glance.get_image, timeout=CONF.openstack.glance_image_create_timeout, check_interval=CONF.openstack. glance_image_create_poll_interval) ]) glance.get_image.assert_called_once_with(1) def test_create_qos(self): specs = {"consumer": "both", "write_iops_sec": "10", "read_iops_sec": "1000"} random_name = "random_name" self.service.generate_random_name = mock.MagicMock( return_value=random_name) result = self.service.create_qos(specs) self.assertEqual( self.cinder.qos_specs.create.return_value, result ) self.cinder.qos_specs.create.assert_called_once_with(random_name, specs) def test_list_qos(self): result = self.service.list_qos(True) self.assertEqual( self.cinder.qos_specs.list.return_value, result ) self.cinder.qos_specs.list.assert_called_once_with(True) def test_get_qos(self): result = self.service.get_qos("qos") self.assertEqual( self.cinder.qos_specs.get.return_value, result) self.cinder.qos_specs.get.assert_called_once_with("qos") def test_set_qos(self): set_specs_args = {"test": "foo"} result = self.service.set_qos("qos", set_specs_args) self.assertEqual( self.cinder.qos_specs.set_keys.return_value, result) self.cinder.qos_specs.set_keys.assert_called_once_with("qos", set_specs_args) def test_qos_associate_type(self): self.service.qos_associate_type("qos", "type_id") self.cinder.qos_specs.associate.assert_called_once_with( "qos", "type_id") def test_qos_disassociate_type(self): self.service.qos_disassociate_type("qos", "type_id") self.cinder.qos_specs.disassociate.assert_called_once_with( "qos", "type_id") def test_delete_snapshot(self): snapshot = mock.Mock() self.service.delete_snapshot(snapshot) self.cinder.volume_snapshots.delete.assert_called_once_with(snapshot) self.mock_wait_for_status.mock.assert_called_once_with( snapshot, ready_statuses=["deleted"], check_deletion=True, update_resource=self.service._update_resource, timeout=cfg.CONF.openstack.cinder_volume_create_timeout, check_interval=cfg.CONF.openstack .cinder_volume_create_poll_interval) def test_delete_backup(self): backup = mock.Mock() self.service.delete_backup(backup) self.cinder.backups.delete.assert_called_once_with(backup) self.mock_wait_for_status.mock.assert_called_once_with( backup, ready_statuses=["deleted"], check_deletion=True, update_resource=self.service._update_resource, timeout=cfg.CONF.openstack.cinder_volume_create_timeout, check_interval=cfg.CONF.openstack .cinder_volume_create_poll_interval) def test_restore_backup(self): backup = mock.Mock() self.service._wait_available_volume = mock.MagicMock() self.service._wait_available_volume.return_value = mock.Mock() return_restore = self.service.restore_backup(backup.id, None) self.cinder.restores.restore.assert_called_once_with(backup.id, None) self.cinder.volumes.get.assert_called_once_with( self.cinder.restores.restore.return_value.volume_id) self.service._wait_available_volume.assert_called_once_with( self.cinder.volumes.get.return_value) self.assertEqual(self.service._wait_available_volume.return_value, return_restore) def test_list_backups(self): return_backups_list = self.service.list_backups() self.assertEqual( self.cinder.backups.list.return_value, return_backups_list) def test_list_transfers(self): return_transfers_list = self.service.list_transfers() self.assertEqual( self.cinder.transfers.list.return_value, return_transfers_list) def test_get_volume_type(self): self.assertEqual(self.cinder.volume_types.get.return_value, self.service.get_volume_type("volume_type")) self.cinder.volume_types.get.assert_called_once_with( "volume_type") def test_delete_volume_type(self): volume_type = mock.Mock() self.service.delete_volume_type(volume_type) self.cinder.volume_types.delete.assert_called_once_with( volume_type) def test_set_volume_type_keys(self): volume_type = mock.Mock() self.assertEqual(volume_type.set_keys.return_value, self.service.set_volume_type_keys( volume_type, metadata="metadata")) volume_type.set_keys.assert_called_once_with("metadata") def test_transfer_create(self): fake_volume = mock.MagicMock() random_name = "random_name" self.service.generate_random_name = mock.MagicMock( return_value=random_name) result = self.service.transfer_create(fake_volume.id) self.assertEqual( self.cinder.transfers.create.return_value, result) self.cinder.transfers.create.assert_called_once_with( fake_volume.id, name=random_name) def test_transfer_create_with_name(self): fake_volume = mock.MagicMock() result = self.service.transfer_create(fake_volume.id, name="t") self.assertEqual( self.cinder.transfers.create.return_value, result) self.cinder.transfers.create.assert_called_once_with( fake_volume.id, name="t") def test_transfer_accept(self): fake_transfer = mock.MagicMock() result = self.service.transfer_accept(fake_transfer.id, "fake_key") self.assertEqual( self.cinder.transfers.accept.return_value, result) self.cinder.transfers.accept.assert_called_once_with( fake_transfer.id, "fake_key") def test_create_encryption_type(self): volume_type = mock.Mock() specs = { "provider": "foo_pro", "cipher": "foo_cip", "key_size": 512, "control_location": "foo_con" } result = self.service.create_encryption_type(volume_type, specs) self.assertEqual( self.cinder.volume_encryption_types.create.return_value, result) self.cinder.volume_encryption_types.create.assert_called_once_with( volume_type, specs) def test_get_encryption_type(self): volume_type = mock.Mock() result = self.service.get_encryption_type(volume_type) self.assertEqual( self.cinder.volume_encryption_types.get.return_value, result) self.cinder.volume_encryption_types.get.assert_called_once_with( volume_type) def test_list_encryption_type(self): return_encryption_types_list = self.service.list_encryption_type() self.assertEqual(self.cinder.volume_encryption_types.list.return_value, return_encryption_types_list) def test_delete_encryption_type(self): resp = mock.MagicMock(status_code=202) self.cinder.volume_encryption_types.delete.return_value = [resp] self.service.delete_encryption_type("type") self.cinder.volume_encryption_types.delete.assert_called_once_with( "type") def test_delete_encryption_type_raise(self): resp = mock.MagicMock(status_code=404) self.cinder.volume_encryption_types.delete.return_value = [resp] self.assertRaises(exceptions.RallyException, self.service.delete_encryption_type, "type") self.cinder.volume_encryption_types.delete.assert_called_once_with( "type") def test_update_encryption_type(self): volume_type = mock.Mock() specs = { "provider": "foo_pro", "cipher": "foo_cip", "key_size": 512, "control_location": "foo_con" } result = self.service.update_encryption_type(volume_type, specs) self.assertEqual( self.cinder.volume_encryption_types.update.return_value, result) self.cinder.volume_encryption_types.update.assert_called_once_with( volume_type, specs) class FullUnifiedCinder(cinder_common.UnifiedCinderMixin, service.Service): """Implementation of UnifiedCinderMixin with Service base class.""" pass class UnifiedCinderMixinTestCase(test.TestCase): def setUp(self): super(UnifiedCinderMixinTestCase, self).setUp() self.clients = mock.MagicMock() self.name_generator = mock.MagicMock() self.impl = mock.MagicMock() self.version = "some" self.service = FullUnifiedCinder( clients=self.clients, name_generator=self.name_generator) self.service._impl = self.impl self.service.version = self.version def test__unify_backup(self): class SomeBackup(object): id = 1 name = "backup" volume_id = "volume" status = "st" backup = self.service._unify_backup(SomeBackup()) self.assertEqual(1, backup.id) self.assertEqual("backup", backup.name) self.assertEqual("volume", backup.volume_id) self.assertEqual("st", backup.status) def test__unify_transfer(self): class SomeTransfer(object): id = 1 name = "transfer" volume_id = "volume" status = "st" transfer = self.service._unify_backup(SomeTransfer()) self.assertEqual(1, transfer.id) self.assertEqual("transfer", transfer.name) self.assertEqual("volume", transfer.volume_id) self.assertEqual("st", transfer.status) def test__unify_qos(self): class Qos(object): id = 1 name = "qos" specs = {"key1": "value1"} qos = self.service._unify_qos(Qos()) self.assertEqual(1, qos.id) self.assertEqual("qos", qos.name) self.assertEqual({"key1": "value1"}, qos.specs) def test__unify_encryption_type(self): class SomeEncryptionType(object): encryption_id = 1 volume_type_id = "volume_type" encryption_type = self.service._unify_encryption_type( SomeEncryptionType()) self.assertEqual(1, encryption_type.id) self.assertEqual("volume_type", encryption_type.volume_type_id) def test_delete_volume(self): self.service.delete_volume("volume") self.service._impl.delete_volume.assert_called_once_with("volume") def test_set_metadata(self): self.assertEqual( self.service._impl.set_metadata.return_value, self.service.set_metadata("volume", sets=10, set_size=3)) self.service._impl.set_metadata.assert_called_once_with( "volume", set_size=3, sets=10) def test_delete_metadata(self): keys = ["a", "b"] self.service.delete_metadata("volume", keys=keys, deletes=10, delete_size=3) self.service._impl.delete_metadata.assert_called_once_with( "volume", keys=keys, delete_size=3, deletes=10) def test_update_readonly_flag(self): self.assertEqual( self.service._impl.update_readonly_flag.return_value, self.service.update_readonly_flag("volume", read_only=True)) self.service._impl.update_readonly_flag.assert_called_once_with( "volume", read_only=True) def test_upload_volume_to_image(self): self.assertEqual( self.service._impl.upload_volume_to_image.return_value, self.service.upload_volume_to_image("volume", force=False, container_format="bare", disk_format="raw")) self.service._impl.upload_volume_to_image.assert_called_once_with( "volume", container_format="bare", disk_format="raw", force=False) def test_create_qos(self): specs = {"consumer": "both", "write_iops_sec": "10", "read_iops_sec": "1000"} self.service._unify_qos = mock.MagicMock() self.assertEqual( self.service._unify_qos.return_value, self.service.create_qos(specs) ) self.service._impl.create_qos.assert_called_once_with(specs) self.service._unify_qos.assert_called_once_with( self.service._impl.create_qos.return_value ) def test_list_qos(self): self.service._unify_qos = mock.MagicMock() self.service._impl.list_qos.return_value = ["qos"] self.assertEqual( [self.service._unify_qos.return_value], self.service.list_qos(True) ) self.service._impl.list_qos.assert_called_once_with(True) self.service._unify_qos.assert_called_once_with("qos") def test_get_qos(self): self.service._unify_qos = mock.MagicMock() self.assertEqual( self.service._unify_qos.return_value, self.service.get_qos("qos")) self.service._impl.get_qos.assert_called_once_with("qos") self.service._unify_qos.assert_called_once_with( self.service._impl.get_qos.return_value ) def test_set_qos(self): set_specs_args = {"test": "foo"} self.service._unify_qos = mock.MagicMock() qos = mock.MagicMock() self.assertEqual( self.service._unify_qos.return_value, self.service.set_qos(qos, set_specs_args)) self.service._impl.set_qos.assert_called_once_with(qos.id, set_specs_args) self.service._unify_qos.assert_called_once_with(qos) def test_qos_associate_type(self): self.service._unify_qos = mock.MagicMock() self.assertEqual( self.service._unify_qos.return_value, self.service.qos_associate_type("qos", "type_id")) self.service._impl.qos_associate_type.assert_called_once_with( "qos", "type_id") self.service._unify_qos.assert_called_once_with("qos") def test_qos_disassociate_type(self): self.service._unify_qos = mock.MagicMock() self.assertEqual( self.service._unify_qos.return_value, self.service.qos_disassociate_type("qos", "type_id")) self.service._impl.qos_disassociate_type.assert_called_once_with( "qos", "type_id") self.service._unify_qos.assert_called_once_with("qos") def test_delete_snapshot(self): self.service.delete_snapshot("snapshot") self.service._impl.delete_snapshot.assert_called_once_with("snapshot") def test_delete_backup(self): self.service.delete_backup("backup") self.service._impl.delete_backup.assert_called_once_with("backup") def test_list_backups(self): self.service._unify_backup = mock.MagicMock() self.service._impl.list_backups.return_value = ["backup"] self.assertEqual([self.service._unify_backup.return_value], self.service.list_backups(detailed=True)) self.service._impl.list_backups.assert_called_once_with(detailed=True) self.service._unify_backup.assert_called_once_with( "backup") def test_list_transfers(self): self.service._unify_transfer = mock.MagicMock() self.service._impl.list_transfers.return_value = ["transfer"] self.assertEqual( [self.service._unify_transfer.return_value], self.service.list_transfers(detailed=True, search_opts=None)) self.service._impl.list_transfers.assert_called_once_with( detailed=True, search_opts=None) self.service._unify_transfer.assert_called_once_with( "transfer") def test_update_volume_type(self): self.assertEqual(self.service._impl.update_volume_type.return_value, self.service.update_volume_type("volume_type")) self.service._impl.update_volume_type.assert_called_once_with( volume_type="volume_type", name=None, description=None, is_public=None ) def test_get_volume_type(self): self.assertEqual(self.service._impl.get_volume_type.return_value, self.service.get_volume_type("volume_type")) self.service._impl.get_volume_type.assert_called_once_with( "volume_type") def test_delete_volume_type(self): self.assertEqual(self.service._impl.delete_volume_type.return_value, self.service.delete_volume_type("volume_type")) self.service._impl.delete_volume_type.assert_called_once_with( "volume_type") def test_add_type_access(self): self.assertEqual(self.service._impl.add_type_access.return_value, self.service.add_type_access(volume_type="some_type", project="some_project")) self.service._impl.add_type_access.assert_called_once_with( volume_type="some_type", project="some_project") def test_list_type_access(self): self.assertEqual(self.service._impl.list_type_access.return_value, self.service.list_type_access("some_type")) self.service._impl.list_type_access.assert_called_once_with( "some_type") def test_set_volume_type_keys(self): self.assertEqual(self.service._impl.set_volume_type_keys.return_value, self.service.set_volume_type_keys( "volume_type", metadata="metadata")) self.service._impl.set_volume_type_keys.assert_called_once_with( "volume_type", "metadata") def test_transfer_create(self): self.service._unify_transfer = mock.MagicMock() self.assertEqual(self.service._unify_transfer.return_value, self.service.transfer_create(1)) self.service._impl.transfer_create.assert_called_once_with( 1, name=None) self.service._unify_transfer.assert_called_once_with( self.service._impl.transfer_create.return_value) def test_transfer_accept(self): self.service._unify_transfer = mock.MagicMock() self.assertEqual(self.service._unify_transfer.return_value, self.service.transfer_accept(1, auth_key=2)) self.service._impl.transfer_accept.assert_called_once_with( 1, auth_key=2) self.service._unify_transfer.assert_called_once_with( self.service._impl.transfer_accept.return_value) def test_create_encryption_type(self): self.service._unify_encryption_type = mock.MagicMock() self.assertEqual( self.service._unify_encryption_type.return_value, self.service.create_encryption_type("type", specs=2)) self.service._impl.create_encryption_type.assert_called_once_with( "type", specs=2) self.service._unify_encryption_type.assert_called_once_with( self.service._impl.create_encryption_type.return_value) def test_get_encryption_type(self): self.service._unify_encryption_type = mock.MagicMock() self.assertEqual( self.service._unify_encryption_type.return_value, self.service.get_encryption_type("type")) self.service._impl.get_encryption_type.assert_called_once_with( "type") self.service._unify_encryption_type.assert_called_once_with( self.service._impl.get_encryption_type.return_value) def test_list_encryption_type(self): self.service._unify_encryption_type = mock.MagicMock() self.service._impl.list_encryption_type.return_value = ["encryption"] self.assertEqual([self.service._unify_encryption_type.return_value], self.service.list_encryption_type(search_opts=None)) self.service._impl.list_encryption_type.assert_called_once_with( search_opts=None) self.service._unify_encryption_type.assert_called_once_with( "encryption") def test_delete_encryption_type(self): self.service.delete_encryption_type("type") self.service._impl.delete_encryption_type.assert_called_once_with( "type") def test_update_encryption_type(self): self.service.update_encryption_type("type", specs=3) self.service._impl.update_encryption_type.assert_called_once_with( "type", specs=3)