diff options
Diffstat (limited to 'nova/tests/unit/virt/test_block_device.py')
-rw-r--r-- | nova/tests/unit/virt/test_block_device.py | 319 |
1 files changed, 177 insertions, 142 deletions
diff --git a/nova/tests/unit/virt/test_block_device.py b/nova/tests/unit/virt/test_block_device.py index aff6c5ef19..703f15967c 100644 --- a/nova/tests/unit/virt/test_block_device.py +++ b/nova/tests/unit/virt/test_block_device.py @@ -12,8 +12,9 @@ # License for the specific language governing permissions and limitations # under the License. -import mock from os_brick import encryptors +from unittest import mock + from oslo_serialization import jsonutils from oslo_utils.fixture import uuidsentinel as uuids @@ -35,6 +36,9 @@ ATTACHMENT_ID = uuids.attachment_id class TestDriverBlockDevice(test.NoDBTestCase): + # os-brick>=5.1 now uses external file system locks instead of internal + # locks so we need to set up locking + REQUIRES_LOCKING = True # This is used to signal if we're dealing with a new style volume # attachment (Cinder v3.44 flow). attachment_id = None @@ -45,7 +49,8 @@ class TestDriverBlockDevice(test.NoDBTestCase): 'volume': driver_block_device.DriverVolumeBlockDevice, 'volsnapshot': driver_block_device.DriverVolSnapshotBlockDevice, 'volimage': driver_block_device.DriverVolImageBlockDevice, - 'volblank': driver_block_device.DriverVolBlankBlockDevice + 'volblank': driver_block_device.DriverVolBlankBlockDevice, + 'image': driver_block_device.DriverImageBlockDevice, } swap_bdm_dict = block_device.BlockDeviceDict( @@ -74,14 +79,22 @@ class TestDriverBlockDevice(test.NoDBTestCase): 'volume_size': 4, 'guest_format': 'ext4', 'delete_on_termination': True, - 'boot_index': -1}) + 'boot_index': -1, + 'encrypted': False, + 'encryption_secret_uuid': None, + 'encryption_format': None, + 'encryption_options': None}) ephemeral_driver_bdm = { 'device_name': '/dev/sdc1', 'size': 4, 'device_type': 'disk', 'guest_format': 'ext4', - 'disk_bus': 'scsi'} + 'disk_bus': 'scsi', + 'encrypted': False, + 'encryption_secret_uuid': None, + 'encryption_format': None, + 'encryption_options': None} volume_bdm_dict = block_device.BlockDeviceDict( {'id': 3, 'instance_uuid': uuids.instance, @@ -206,6 +219,35 @@ class TestDriverBlockDevice(test.NoDBTestCase): 'boot_index': -1, 'volume_type': None} + image_bdm_dict = block_device.BlockDeviceDict( + {'id': 7, 'instance_uuid': uuids.instance, + 'device_name': '/dev/vda', + 'source_type': 'image', + 'destination_type': 'local', + 'disk_bus': 'virtio', + 'device_type': 'disk', + 'guest_format': 'ext4', + 'boot_index': 0, + 'image_id': 'fake-image-id-1', + 'volume_size': 5, + 'encrypted': True, + 'encryption_secret_uuid': uuids.secret, + 'encryption_format': 'plain', + 'encryption_options': None}) + + image_driver_bdm = { + 'device_name': '/dev/vda', + 'device_type': 'disk', + 'guest_format': 'ext4', + 'disk_bus': 'virtio', + 'boot_index': 0, + 'image_id': 'fake-image-id-1', + 'size': 5, + 'encrypted': True, + 'encryption_secret_uuid': uuids.secret, + 'encryption_format': 'plain', + 'encryption_options': None} + def setUp(self): super(TestDriverBlockDevice, self).setUp() self.volume_api = mock.MagicMock(autospec=cinder.API) @@ -215,6 +257,8 @@ class TestDriverBlockDevice(test.NoDBTestCase): # create bdm objects for testing self.swap_bdm = fake_block_device.fake_bdm_object( self.context, self.swap_bdm_dict) + self.image_bdm = fake_block_device.fake_bdm_object( + self.context, self.image_bdm_dict) self.ephemeral_bdm = fake_block_device.fake_bdm_object( self.context, self.ephemeral_bdm_dict) self.volume_bdm = fake_block_device.fake_bdm_object( @@ -333,6 +377,10 @@ class TestDriverBlockDevice(test.NoDBTestCase): if field == 'attachment_id': # Must set UUID values on UUID fields. fake_value = ATTACHMENT_ID + elif isinstance(test_bdm._bdm_obj.fields[fld], + fields.UUIDField): + # Generically handle other UUID fields. + fake_value = uuids.fake_value else: fake_value = 'fake_changed_value' test_bdm[field] = fake_value @@ -373,6 +421,20 @@ class TestDriverBlockDevice(test.NoDBTestCase): def test_driver_swap_default_size(self): self._test_driver_default_size('swap') + def test_driver_image_block_device(self): + self._test_driver_device("image") + + def test_driver_image_default_size(self): + self._test_driver_default_size('image') + + def test_driver_image_block_device_destination_not_local(self): + self._test_driver_device('image') + bdm = self.image_bdm_dict.copy() + bdm['destination_type'] = 'volume' + self.assertRaises(driver_block_device._InvalidType, + self.driver_classes['image'], + fake_block_device.fake_bdm_object(self.context, bdm)) + def test_driver_ephemeral_block_device(self): self._test_driver_device("ephemeral") @@ -402,7 +464,7 @@ class TestDriverBlockDevice(test.NoDBTestCase): self.assertEqual(test_bdm.volume_size, 3) self.assertEqual('fake-snapshot-id-1', test_bdm.get('snapshot_id')) - def test_driver_image_block_device(self): + def test_driver_volume_image_block_device(self): self._test_driver_device('volimage') test_bdm = self.driver_classes['volimage']( @@ -412,7 +474,7 @@ class TestDriverBlockDevice(test.NoDBTestCase): self.assertEqual(test_bdm.volume_size, 1) self.assertEqual('fake-image-id-1', test_bdm.get('image_id')) - def test_driver_image_block_device_destination_local(self): + def test_driver_volume_image_block_device_destination_local(self): self._test_driver_device('volimage') bdm = self.volimage_bdm_dict.copy() bdm['destination_type'] = 'local' @@ -433,24 +495,23 @@ class TestDriverBlockDevice(test.NoDBTestCase): def _test_call_wait_func(self, delete_on_termination, delete_fail=False): test_bdm = self.driver_classes['volume'](self.volume_bdm) test_bdm['delete_on_termination'] = delete_on_termination - with mock.patch.object(self.volume_api, 'delete') as vol_delete: - wait_func = mock.MagicMock() - mock_exception = exception.VolumeNotCreated(volume_id='fake-id', - seconds=1, - attempts=1, - volume_status='error') - wait_func.side_effect = mock_exception - - if delete_on_termination and delete_fail: - vol_delete.side_effect = Exception() - - self.assertRaises(exception.VolumeNotCreated, - test_bdm._call_wait_func, - context=self.context, - wait_func=wait_func, - volume_api=self.volume_api, - volume_id='fake-id') - self.assertEqual(delete_on_termination, vol_delete.called) + if delete_on_termination and delete_fail: + self.volume_api.delete.side_effect = Exception() + + wait_func = mock.MagicMock() + mock_exception = exception.VolumeNotCreated(volume_id='fake-id', + seconds=1, + attempts=1, + volume_status='error') + wait_func.side_effect = mock_exception + + self.assertRaises(exception.VolumeNotCreated, + test_bdm._call_wait_func, + context=self.context, + wait_func=wait_func, + volume_api=self.volume_api, + volume_id='fake-id') + self.assertEqual(delete_on_termination, self.volume_api.delete.called) def test_call_wait_delete_volume(self): self._test_call_wait_func(True) @@ -483,25 +544,24 @@ class TestDriverBlockDevice(test.NoDBTestCase): volume['shared_targets'] = True volume['service_uuid'] = uuids.service_uuid + if delete_attachment_raises: + self.volume_api.attachment_delete.side_effect = ( + delete_attachment_raises) + + self.virt_driver.get_volume_connector.return_value = connector + with test.nested( mock.patch.object(driver_bdm, '_get_volume', return_value=volume), - mock.patch.object(self.virt_driver, 'get_volume_connector', - return_value=connector), mock.patch('os_brick.initiator.utils.guard_connection'), - mock.patch.object(self.volume_api, 'attachment_delete'), - ) as (mock_get_volume, mock_get_connector, mock_guard, - vapi_attach_del): - - if delete_attachment_raises: - vapi_attach_del.side_effect = delete_attachment_raises + ) as (mock_get_volume, mock_guard): driver_bdm.detach(elevated_context, instance, self.volume_api, self.virt_driver, attachment_id=attachment_id) mock_guard.assert_called_once_with(volume) - vapi_attach_del.assert_called_once_with(elevated_context, - attachment_id) + self.volume_api.attachment_delete.assert_called_once_with( + elevated_context, attachment_id) def test_volume_delete_attachment_with_shared_targets(self): self.test_volume_delete_attachment(include_shared_targets=True) @@ -952,31 +1012,28 @@ class TestDriverBlockDevice(test.NoDBTestCase): instance = fake_instance.fake_instance_obj(mock.sentinel.ctx, **{'uuid': uuids.uuid}) - with test.nested( - mock.patch.object(self.volume_api, 'get_snapshot', - return_value=snapshot), - mock.patch.object(self.volume_api, 'create', return_value=volume), - mock.patch.object(self.volume_api, 'delete'), - ) as (vol_get_snap, vol_create, vol_delete): - wait_func = mock.MagicMock() - mock_exception = exception.VolumeNotCreated(volume_id=volume['id'], - seconds=1, - attempts=1, - volume_status='error') - wait_func.side_effect = mock_exception - self.assertRaises(exception.VolumeNotCreated, - test_bdm.attach, context=self.context, - instance=instance, - volume_api=self.volume_api, - virt_driver=self.virt_driver, - wait_func=wait_func) - - vol_get_snap.assert_called_once_with( - self.context, 'fake-snapshot-id-1') - vol_create.assert_called_once_with( - self.context, 3, '', '', availability_zone=None, - snapshot=snapshot, volume_type=None) - vol_delete.assert_called_once_with(self.context, volume['id']) + self.volume_api.get_snapshot.return_value = snapshot + self.volume_api.create.return_value = volume + wait_func = mock.MagicMock() + mock_exception = exception.VolumeNotCreated(volume_id=volume['id'], + seconds=1, + attempts=1, + volume_status='error') + wait_func.side_effect = mock_exception + self.assertRaises(exception.VolumeNotCreated, + test_bdm.attach, context=self.context, + instance=instance, + volume_api=self.volume_api, + virt_driver=self.virt_driver, + wait_func=wait_func) + + self.volume_api.get_snapshot.assert_called_once_with( + self.context, 'fake-snapshot-id-1') + self.volume_api.create.assert_called_once_with( + self.context, 3, '', '', availability_zone=None, + snapshot=snapshot, volume_type=None) + self.volume_api.delete.assert_called_once_with( + self.context, volume['id']) def test_snapshot_attach_volume(self): test_bdm = self.driver_classes['volsnapshot']( @@ -984,19 +1041,17 @@ class TestDriverBlockDevice(test.NoDBTestCase): instance = {'id': 'fake_id', 'uuid': uuids.uuid} - with test.nested( - mock.patch.object(self.driver_classes['volume'], 'attach'), - mock.patch.object(self.volume_api, 'get_snapshot'), - mock.patch.object(self.volume_api, 'create'), - ) as (mock_attach, mock_get_snapshot, mock_create): + with mock.patch.object( + self.driver_classes['volume'], 'attach' + ) as mock_attach: test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) self.assertEqual('fake-volume-id-2', test_bdm.volume_id) mock_attach.assert_called_once_with( self.context, instance, self.volume_api, self.virt_driver) # Make sure theses are not called - mock_get_snapshot.assert_not_called() - mock_create.assert_not_called() + self.volume_api.get_snapshot.assert_not_called() + self.volume_api.create.assert_not_called() def test_snapshot_attach_no_volume_and_no_volume_type(self): bdm = self.driver_classes['volsnapshot'](self.volsnapshot_bdm) @@ -1006,15 +1061,10 @@ class TestDriverBlockDevice(test.NoDBTestCase): original_volume = {'id': uuids.original_volume_id, 'volume_type_id': 'original_volume_type'} new_volume = {'id': uuids.new_volume_id} - with test.nested( - mock.patch.object(self.driver_classes['volume'], 'attach'), - mock.patch.object(self.volume_api, 'get_snapshot', - return_value=snapshot), - mock.patch.object(self.volume_api, 'get', - return_value=original_volume), - mock.patch.object(self.volume_api, 'create', - return_value=new_volume), - ) as (mock_attach, mock_get_snapshot, mock_get, mock_create): + self.volume_api.get_snapshot.return_value = snapshot + self.volume_api.get.return_value = original_volume + self.volume_api.create.return_value = new_volume + with mock.patch.object(self.driver_classes["volume"], "attach"): bdm.volume_id = None bdm.volume_type = None bdm.attach(self.context, instance, self.volume_api, @@ -1022,10 +1072,11 @@ class TestDriverBlockDevice(test.NoDBTestCase): # Assert that the original volume type is fetched, stored within # the bdm and then used to create the new snapshot based volume. - mock_get.assert_called_once_with(self.context, - uuids.original_volume_id) + self.volume_api.get.assert_called_once_with( + self.context, uuids.original_volume_id) self.assertEqual('original_volume_type', bdm.volume_type) - mock_create.assert_called_once_with(self.context, bdm.volume_size, + self.volume_api.create.assert_called_once_with( + self.context, bdm.volume_size, '', '', volume_type='original_volume_type', snapshot=snapshot, availability_zone=None) @@ -1097,27 +1148,25 @@ class TestDriverBlockDevice(test.NoDBTestCase): instance = fake_instance.fake_instance_obj(mock.sentinel.ctx, **{'uuid': uuids.uuid}) - with test.nested( - mock.patch.object(self.volume_api, 'create', return_value=volume), - mock.patch.object(self.volume_api, 'delete'), - ) as (vol_create, vol_delete): - wait_func = mock.MagicMock() - mock_exception = exception.VolumeNotCreated(volume_id=volume['id'], - seconds=1, - attempts=1, - volume_status='error') - wait_func.side_effect = mock_exception - self.assertRaises(exception.VolumeNotCreated, - test_bdm.attach, context=self.context, - instance=instance, - volume_api=self.volume_api, - virt_driver=self.virt_driver, - wait_func=wait_func) - - vol_create.assert_called_once_with( - self.context, 1, '', '', image_id=image['id'], - availability_zone=None, volume_type=None) - vol_delete.assert_called_once_with(self.context, volume['id']) + self.volume_api.create.return_value = volume + wait_func = mock.MagicMock() + mock_exception = exception.VolumeNotCreated(volume_id=volume['id'], + seconds=1, + attempts=1, + volume_status='error') + wait_func.side_effect = mock_exception + self.assertRaises(exception.VolumeNotCreated, + test_bdm.attach, context=self.context, + instance=instance, + volume_api=self.volume_api, + virt_driver=self.virt_driver, + wait_func=wait_func) + + self.volume_api.create.assert_called_once_with( + self.context, 1, '', '', image_id=image['id'], + availability_zone=None, volume_type=None) + self.volume_api.delete.assert_called_once_with( + self.context, volume['id']) def test_image_attach_volume(self): test_bdm = self.driver_classes['volimage']( @@ -1125,19 +1174,17 @@ class TestDriverBlockDevice(test.NoDBTestCase): instance = {'id': 'fake_id', 'uuid': uuids.uuid} - with test.nested( - mock.patch.object(self.driver_classes['volume'], 'attach'), - mock.patch.object(self.volume_api, 'get_snapshot'), - mock.patch.object(self.volume_api, 'create'), - ) as (mock_attch, mock_get_snapshot, mock_create): + with mock.patch.object( + self.driver_classes['volume'], 'attach' + ) as mock_attach: test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) self.assertEqual('fake-volume-id-2', test_bdm.volume_id) - mock_attch.assert_called_once_with( + mock_attach.assert_called_once_with( self.context, instance, self.volume_api, self.virt_driver) # Make sure theses are not called - mock_get_snapshot.assert_not_called() - mock_create.assert_not_called() + self.volume_api.get_snapshot.assert_not_called() + self.volume_api.create.assert_not_called() def test_blank_attach_fail_volume(self): no_blank_volume = self.volblank_bdm_dict.copy() @@ -1149,30 +1196,26 @@ class TestDriverBlockDevice(test.NoDBTestCase): **{'uuid': uuids.uuid}) volume = {'id': 'fake-volume-id-2', 'display_name': '%s-blank-vol' % uuids.uuid} + self.volume_api.create.return_value = volume + wait_func = mock.MagicMock() + mock_exception = exception.VolumeNotCreated(volume_id=volume['id'], + seconds=1, + attempts=1, + volume_status='error') + wait_func.side_effect = mock_exception + self.assertRaises(exception.VolumeNotCreated, + test_bdm.attach, context=self.context, + instance=instance, + volume_api=self.volume_api, + virt_driver=self.virt_driver, + wait_func=wait_func) - with test.nested( - mock.patch.object(self.volume_api, 'create', return_value=volume), - mock.patch.object(self.volume_api, 'delete'), - ) as (vol_create, vol_delete): - wait_func = mock.MagicMock() - mock_exception = exception.VolumeNotCreated(volume_id=volume['id'], - seconds=1, - attempts=1, - volume_status='error') - wait_func.side_effect = mock_exception - self.assertRaises(exception.VolumeNotCreated, - test_bdm.attach, context=self.context, - instance=instance, - volume_api=self.volume_api, - virt_driver=self.virt_driver, - wait_func=wait_func) - - vol_create.assert_called_once_with( - self.context, test_bdm.volume_size, - '%s-blank-vol' % uuids.uuid, - '', volume_type=None, availability_zone=None) - vol_delete.assert_called_once_with( - self.context, volume['id']) + self.volume_api.create.assert_called_once_with( + self.context, test_bdm.volume_size, + '%s-blank-vol' % uuids.uuid, + '', volume_type=None, availability_zone=None) + self.volume_api.delete.assert_called_once_with( + self.context, volume['id']) def test_blank_attach_volume(self): no_blank_volume = self.volblank_bdm_dict.copy() @@ -1278,12 +1321,8 @@ class TestDriverBlockDevice(test.NoDBTestCase): def test_is_implemented(self): for bdm in (self.volimage_bdm, self.volume_bdm, self.swap_bdm, - self.ephemeral_bdm, self.volsnapshot_bdm): + self.ephemeral_bdm, self.volsnapshot_bdm, self.image_bdm): self.assertTrue(driver_block_device.is_implemented(bdm)) - local_image = self.volimage_bdm_dict.copy() - local_image['destination_type'] = 'local' - self.assertFalse(driver_block_device.is_implemented( - fake_block_device.fake_bdm_object(self.context, local_image))) def test_is_block_device_mapping(self): test_swap = self.driver_classes['swap'](self.swap_bdm) @@ -1481,13 +1520,9 @@ class TestDriverBlockDevice(test.NoDBTestCase): 'display_name': 'fake-snapshot-vol'} self.stub_volume_create(volume) - with test.nested( - mock.patch.object(self.volume_api, 'get_snapshot', - return_value=snapshot), - mock.patch.object(volume_class, 'attach') - ) as ( - vol_get_snap, vol_attach - ): + self.volume_api.get_snapshot.return_value = snapshot + + with mock.patch.object(volume_class, 'attach') as vol_attach: test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) |