def test_init(self): def fake_validate(obj, dct): pass self.stub_out('nova.block_device.BlockDeviceDict._fields', set(['field1', 'field2'])) self.stub_out('nova.block_device.BlockDeviceDict._db_only_fields', set(['db_field1', 'db_field2'])) self.stub_out('nova.block_device.BlockDeviceDict._validate', fake_validate) # Make sure db fields are not picked up if they are not # in the original dict dev_dict = block_device.BlockDeviceDict({ 'field1': 'foo', 'field2': 'bar', 'db_field1': 'baz' }) self.assertIn('field1', dev_dict) self.assertIn('field2', dev_dict) self.assertIn('db_field1', dev_dict) self.assertNotIn('db_field2', dev_dict) # Make sure all expected fields are defaulted dev_dict = block_device.BlockDeviceDict({'field1': 'foo'}) self.assertIn('field1', dev_dict) self.assertIn('field2', dev_dict) self.assertIsNone(dev_dict['field2']) self.assertNotIn('db_field1', dev_dict) self.assertNotIn('db_field2', dev_dict) # Unless they are not meant to be dev_dict = block_device.BlockDeviceDict({'field1': 'foo'}, do_not_default=set(['field2'])) self.assertIn('field1', dev_dict) self.assertNotIn('field2', dev_dict) self.assertNotIn('db_field1', dev_dict) self.assertNotIn('db_field2', dev_dict) # Passing kwargs to constructor works dev_dict = block_device.BlockDeviceDict(field1='foo') self.assertIn('field1', dev_dict) self.assertIn('field2', dev_dict) self.assertIsNone(dev_dict['field2']) dev_dict = block_device.BlockDeviceDict({'field1': 'foo'}, field2='bar') self.assertEqual('foo', dev_dict['field1']) self.assertEqual('bar', dev_dict['field2'])
def create(*args, **kwargs): self.assertFalse(kwargs['legacy_bdm']) for expected, received in zip(bdm_expected, kwargs['block_device_mapping']): self.assertThat(block_device.BlockDeviceDict(expected), matchers.DictMatches(received)) return old_create(*args, **kwargs)
def test_validate(self): self.assertRaises(exception.InvalidBDMFormat, block_device.BlockDeviceDict, {'bogus_field': 'lame_val'}) lame_bdm = dict(self.new_mapping[2]) del lame_bdm['source_type'] self.assertRaises(exception.InvalidBDMFormat, block_device.BlockDeviceDict, lame_bdm) lame_bdm['no_device'] = True block_device.BlockDeviceDict(lame_bdm) lame_dev_bdm = dict(self.new_mapping[2]) lame_dev_bdm['device_name'] = "not a valid name" self.assertRaises(exception.InvalidBDMFormat, block_device.BlockDeviceDict, lame_dev_bdm) lame_dev_bdm['device_name'] = "" self.assertRaises(exception.InvalidBDMFormat, block_device.BlockDeviceDict, lame_dev_bdm) cool_volume_size_bdm = dict(self.new_mapping[2]) cool_volume_size_bdm['volume_size'] = '42' cool_volume_size_bdm = block_device.BlockDeviceDict( cool_volume_size_bdm) self.assertEqual(42, cool_volume_size_bdm['volume_size']) lame_volume_size_bdm = dict(self.new_mapping[2]) lame_volume_size_bdm['volume_size'] = 'some_non_int_string' self.assertRaises(exception.InvalidBDMFormat, block_device.BlockDeviceDict, lame_volume_size_bdm) truthy_bdm = dict(self.new_mapping[2]) truthy_bdm['delete_on_termination'] = '1' truthy_bdm = block_device.BlockDeviceDict(truthy_bdm) self.assertTrue(truthy_bdm['delete_on_termination']) verbose_bdm = dict(self.new_mapping[2]) verbose_bdm['boot_index'] = 'first' self.assertRaises(exception.InvalidBDMFormat, block_device.BlockDeviceDict, verbose_bdm)
def test_init_prepend_dev_to_device_name(self): bdm = {'id': 3, 'instance_uuid': 'fake-instance', 'device_name': 'vda', 'source_type': 'volume', 'destination_type': 'volume', 'volume_id': 'fake-volume-id-1', 'boot_index': 0} bdm_dict = block_device.BlockDeviceDict(bdm) self.assertEqual('/dev/vda', bdm_dict['device_name']) bdm['device_name'] = '/dev/vdb' bdm_dict = block_device.BlockDeviceDict(bdm) self.assertEqual('/dev/vdb', bdm_dict['device_name']) bdm['device_name'] = None bdm_dict = block_device.BlockDeviceDict(bdm) self.assertIsNone(bdm_dict['device_name'])
def test_init(self): self.stubs.Set(block_device.BlockDeviceDict, '_fields', set(['field1', 'field2'])) self.stubs.Set(block_device.BlockDeviceDict, '_db_only_fields', set(['db_field1', 'db_field2'])) # Make sure db fields are not picked up if they are not # in the original dict dev_dict = block_device.BlockDeviceDict({ 'field1': 'foo', 'field2': 'bar', 'db_field1': 'baz' }) self.assertTrue('field1' in dev_dict) self.assertTrue('field2' in dev_dict) self.assertTrue('db_field1' in dev_dict) self.assertFalse('db_field2' in dev_dict) # Make sure all expected fields are defaulted dev_dict = block_device.BlockDeviceDict({'field1': 'foo'}) self.assertTrue('field1' in dev_dict) self.assertTrue('field2' in dev_dict) self.assertTrue(dev_dict['field2'] is None) self.assertFalse('db_field1' in dev_dict) self.assertFalse('db_field2' in dev_dict) # Unless they are not meant to be dev_dict = block_device.BlockDeviceDict({'field1': 'foo'}, do_not_default=set(['field2'])) self.assertTrue('field1' in dev_dict) self.assertFalse('field2' in dev_dict) self.assertFalse('db_field1' in dev_dict) self.assertFalse('db_field2' in dev_dict) # Assert basic validation works # NOTE (ndipanov): Move to separate test once we have # more complex validations in place self.assertRaises(exception.InvalidBDMFormat, block_device.BlockDeviceDict, { 'field1': 'foo', 'bogus_field': 'lame_val' })
def test_init_boolify_delete_on_termination(self): # Make sure that when delete_on_termination is not passed it's # still set to False and not None bdm = {'id': 3, 'instance_uuid': 'fake-instance', 'device_name': 'vda', 'source_type': 'volume', 'destination_type': 'volume', 'volume_id': 'fake-volume-id-1', 'boot_index': 0} bdm_dict = block_device.BlockDeviceDict(bdm) self.assertFalse(bdm_dict['delete_on_termination'])
def test_update_block_device_mapping(self): instance_type = {'swap': 1, 'ephemeral_gb': 1} instance = self._create_fake_instance_obj() bdms = [block_device.BlockDeviceDict({'source_type': 'image', 'destination_type': 'local', 'image_id': 'fake-image', 'boot_index': 0})] self.compute_api._update_block_device_mapping( instance_type, instance.uuid, bdms) bdms = db.block_device_mapping_get_all_by_instance( self.context, instance['uuid']) self.assertEqual(0, len(bdms))
def test_init(self): def fake_validate(obj, dct): pass self.stubs.Set(block_device.BlockDeviceDict, '_fields', set(['field1', 'field2'])) self.stubs.Set(block_device.BlockDeviceDict, '_db_only_fields', set(['db_field1', 'db_field2'])) self.stubs.Set(block_device.BlockDeviceDict, '_validate', fake_validate) # Make sure db fields are not picked up if they are not # in the original dict dev_dict = block_device.BlockDeviceDict({ 'field1': 'foo', 'field2': 'bar', 'db_field1': 'baz' }) self.assertTrue('field1' in dev_dict) self.assertTrue('field2' in dev_dict) self.assertTrue('db_field1' in dev_dict) self.assertFalse('db_field2' in dev_dict) # Make sure all expected fields are defaulted dev_dict = block_device.BlockDeviceDict({'field1': 'foo'}) self.assertTrue('field1' in dev_dict) self.assertTrue('field2' in dev_dict) self.assertTrue(dev_dict['field2'] is None) self.assertFalse('db_field1' in dev_dict) self.assertFalse('db_field2' in dev_dict) # Unless they are not meant to be dev_dict = block_device.BlockDeviceDict({'field1': 'foo'}, do_not_default=set(['field2'])) self.assertTrue('field1' in dev_dict) self.assertFalse('field2' in dev_dict) self.assertFalse('db_field1' in dev_dict) self.assertFalse('db_field2' in dev_dict)
def __init__(self, bdm): # TODO(ndipanov): Remove this check when we have all the rpc methods # use objects for block devices. if isinstance(bdm, obj_base.NovaObject): self.__dict__['_bdm_obj'] = bdm else: self.__dict__['_bdm_obj'] = objects.BlockDeviceMapping() self._bdm_obj.update(block_device.BlockDeviceDict(bdm)) self._bdm_obj.obj_reset_changes() if self._bdm_obj.no_device: raise _NotTransformable() self.update({field: None for field in self._fields}) self._transform()
def _fake_bdm(volume_id, target_lun): connection_info = {'driver_volume_type': 'fibre_channel', 'data': {'volume_id': volume_id, 'target_lun': target_lun, 'initiator_target_map': {'21000024F5': ['50050768']}}} mapping_dict = {'source_type': 'volume', 'volume_id': volume_id, 'destination_type': 'volume', 'connection_info': jsonutils.dumps(connection_info), } bdm_dict = nova_block_device.BlockDeviceDict(mapping_dict) bdm_obj = bdmobj.BlockDeviceMapping(**bdm_dict) return nova_virt_bdm.DriverVolumeBlockDevice(bdm_obj)
def test_from_api_valid_source_to_local_mapping_with_string_bi(self): api_dict = {'id': 1, 'source_type': 'image', 'destination_type': 'local', 'volume_id': 'fake-volume-id-1', 'uuid': 1, 'boot_index': '0'} retexp = block_device.BlockDeviceDict( {'id': 1, 'source_type': 'image', 'image_id': 1, 'destination_type': 'local', 'volume_id': 'fake-volume-id-1', 'boot_index': 0}) self.assertEqual(retexp, block_device.BlockDeviceDict.from_api(api_dict, True))
from nova import context from nova import objects from nova.objects import block_device as block_device_obj from nova import test from nova.tests.unit import fake_instance from nova.virt import imagecache CONF = cfg.CONF swap_bdm_128 = [ block_device.BlockDeviceDict({ 'id': 1, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sdb1', 'source_type': 'blank', 'destination_type': 'local', 'delete_on_termination': True, 'guest_format': 'swap', 'disk_bus': 'scsi', 'volume_size': 128, 'boot_index': -1 }) ] swap_bdm_256 = [ block_device.BlockDeviceDict({ 'id': 1, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sdb1', 'source_type': 'blank', 'destination_type': 'local', 'delete_on_termination': True,
class TestDriverBlockDevice(test.NoDBTestCase): driver_classes = { 'swap': driver_block_device.DriverSwapBlockDevice, 'ephemeral': driver_block_device.DriverEphemeralBlockDevice, 'volume': driver_block_device.DriverVolumeBlockDevice, 'snapshot': driver_block_device.DriverSnapshotBlockDevice, 'image': driver_block_device.DriverImageBlockDevice, 'blank': driver_block_device.DriverBlankBlockDevice } swap_bdm_dict = block_device.BlockDeviceDict( {'id': 1, 'instance_uuid': uuids.instance, 'device_name': '/dev/sdb1', 'source_type': 'blank', 'destination_type': 'local', 'delete_on_termination': True, 'guest_format': 'swap', 'disk_bus': 'scsi', 'volume_size': 2, 'boot_index': -1}) swap_driver_bdm = { 'device_name': '/dev/sdb1', 'swap_size': 2, 'disk_bus': 'scsi'} swap_legacy_driver_bdm = { 'device_name': '/dev/sdb1', 'swap_size': 2} ephemeral_bdm_dict = block_device.BlockDeviceDict( {'id': 2, 'instance_uuid': uuids.instance, 'device_name': '/dev/sdc1', 'source_type': 'blank', 'destination_type': 'local', 'disk_bus': 'scsi', 'device_type': 'disk', 'volume_size': 4, 'guest_format': 'ext4', 'delete_on_termination': True, 'boot_index': -1}) ephemeral_driver_bdm = { 'device_name': '/dev/sdc1', 'size': 4, 'device_type': 'disk', 'guest_format': 'ext4', 'disk_bus': 'scsi'} ephemeral_legacy_driver_bdm = { 'device_name': '/dev/sdc1', 'size': 4, 'virtual_name': 'ephemeral0', 'num': 0} volume_bdm_dict = block_device.BlockDeviceDict( {'id': 3, 'instance_uuid': uuids.instance, 'device_name': '/dev/sda1', 'source_type': 'volume', 'disk_bus': 'scsi', 'device_type': 'disk', 'volume_size': 8, 'destination_type': 'volume', 'volume_id': 'fake-volume-id-1', 'guest_format': 'ext4', 'connection_info': '{"fake": "connection_info"}', 'delete_on_termination': False, 'boot_index': 0}) volume_driver_bdm = { 'mount_device': '/dev/sda1', 'connection_info': {"fake": "connection_info"}, 'delete_on_termination': False, 'disk_bus': 'scsi', 'device_type': 'disk', 'guest_format': 'ext4', 'boot_index': 0} volume_legacy_driver_bdm = { 'mount_device': '/dev/sda1', 'connection_info': {"fake": "connection_info"}, 'delete_on_termination': False} snapshot_bdm_dict = block_device.BlockDeviceDict( {'id': 4, 'instance_uuid': uuids.instance, 'device_name': '/dev/sda2', 'delete_on_termination': True, 'volume_size': 3, 'disk_bus': 'scsi', 'device_type': 'disk', 'source_type': 'snapshot', 'destination_type': 'volume', 'connection_info': '{"fake": "connection_info"}', 'snapshot_id': 'fake-snapshot-id-1', 'volume_id': 'fake-volume-id-2', 'boot_index': -1}) snapshot_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': {"fake": "connection_info"}, 'delete_on_termination': True, 'disk_bus': 'scsi', 'device_type': 'disk', 'guest_format': None, 'boot_index': -1} snapshot_legacy_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': {"fake": "connection_info"}, 'delete_on_termination': True} image_bdm_dict = block_device.BlockDeviceDict( {'id': 5, 'instance_uuid': uuids.instance, 'device_name': '/dev/sda2', 'delete_on_termination': True, 'volume_size': 1, 'disk_bus': 'scsi', 'device_type': 'disk', 'source_type': 'image', 'destination_type': 'volume', 'connection_info': '{"fake": "connection_info"}', 'image_id': 'fake-image-id-1', 'volume_id': 'fake-volume-id-2', 'boot_index': -1}) image_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': {"fake": "connection_info"}, 'delete_on_termination': True, 'disk_bus': 'scsi', 'device_type': 'disk', 'guest_format': None, 'boot_index': -1} image_legacy_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': {"fake": "connection_info"}, 'delete_on_termination': True} blank_bdm_dict = block_device.BlockDeviceDict( {'id': 6, 'instance_uuid': uuids.instance, 'device_name': '/dev/sda2', 'delete_on_termination': True, 'volume_size': 3, 'disk_bus': 'scsi', 'device_type': 'disk', 'source_type': 'blank', 'destination_type': 'volume', 'connection_info': '{"fake": "connection_info"}', 'snapshot_id': 'fake-snapshot-id-1', 'volume_id': 'fake-volume-id-2', 'boot_index': -1}) blank_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': {"fake": "connection_info"}, 'delete_on_termination': True, 'disk_bus': 'scsi', 'device_type': 'disk', 'guest_format': None, 'boot_index': -1} blank_legacy_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': {"fake": "connection_info"}, 'delete_on_termination': True} def setUp(self): super(TestDriverBlockDevice, self).setUp() self.volume_api = self.mox.CreateMock(cinder.API) self.virt_driver = self.mox.CreateMock(driver.ComputeDriver) self.context = context.RequestContext('fake_user', 'fake_project') # create bdm objects for testing self.swap_bdm = fake_block_device.fake_bdm_object( self.context, self.swap_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( self.context, self.volume_bdm_dict) self.snapshot_bdm = fake_block_device.fake_bdm_object( self.context, self.snapshot_bdm_dict) self.image_bdm = fake_block_device.fake_bdm_object( self.context, self.image_bdm_dict) self.blank_bdm = fake_block_device.fake_bdm_object( self.context, self.blank_bdm_dict) def test_no_device_raises(self): for name, cls in self.driver_classes.items(): bdm = fake_block_device.fake_bdm_object( self.context, {'no_device': True}) self.assertRaises(driver_block_device._NotTransformable, cls, bdm) def _test_driver_device(self, name): db_bdm = getattr(self, "%s_bdm" % name) test_bdm = self.driver_classes[name](db_bdm) self.assertThat(test_bdm, matchers.DictMatches( getattr(self, "%s_driver_bdm" % name))) for k, v in db_bdm.items(): field_val = getattr(test_bdm._bdm_obj, k) if isinstance(field_val, bool): v = bool(v) self.assertEqual(field_val, v) self.assertThat(test_bdm.legacy(), matchers.DictMatches( getattr(self, "%s_legacy_driver_bdm" % name))) # Test passthru attributes for passthru in test_bdm._proxy_as_attr: self.assertEqual(getattr(test_bdm, passthru), getattr(test_bdm._bdm_obj, passthru)) # Make sure that all others raise _invalidType for other_name, cls in self.driver_classes.items(): if other_name == name: continue self.assertRaises(driver_block_device._InvalidType, cls, getattr(self, '%s_bdm' % name)) # Test the save method with mock.patch.object(test_bdm._bdm_obj, 'save') as save_mock: for fld, alias in test_bdm._update_on_save.items(): # We can't set fake values on enums, like device_type, # so skip those. if not isinstance(test_bdm._bdm_obj.fields[fld], fields.BaseEnumField): test_bdm[alias or fld] = 'fake_changed_value' test_bdm.save() for fld, alias in test_bdm._update_on_save.items(): self.assertEqual(test_bdm[alias or fld], getattr(test_bdm._bdm_obj, fld)) save_mock.assert_called_once_with() def check_save(): self.assertEqual(set([]), test_bdm._bdm_obj.obj_what_changed()) # Test that nothing is set on the object if there are no actual changes test_bdm._bdm_obj.obj_reset_changes() with mock.patch.object(test_bdm._bdm_obj, 'save') as save_mock: save_mock.side_effect = check_save test_bdm.save() def _test_driver_default_size(self, name): size = 'swap_size' if name == 'swap' else 'size' no_size_bdm = getattr(self, "%s_bdm_dict" % name).copy() no_size_bdm['volume_size'] = None driver_bdm = self.driver_classes[name]( fake_block_device.fake_bdm_object(self.context, no_size_bdm)) self.assertEqual(driver_bdm[size], 0) del no_size_bdm['volume_size'] driver_bdm = self.driver_classes[name]( fake_block_device.fake_bdm_object(self.context, no_size_bdm)) self.assertEqual(driver_bdm[size], 0) def test_driver_swap_block_device(self): self._test_driver_device("swap") def test_driver_swap_default_size(self): self._test_driver_default_size('swap') def test_driver_ephemeral_block_device(self): self._test_driver_device("ephemeral") def test_driver_ephemeral_default_size(self): self._test_driver_default_size('ephemeral') def test_driver_volume_block_device(self): self._test_driver_device("volume") test_bdm = self.driver_classes['volume']( self.volume_bdm) self.assertEqual(test_bdm['connection_info'], jsonutils.loads(test_bdm._bdm_obj.connection_info)) self.assertEqual(test_bdm._bdm_obj.id, 3) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-1') self.assertEqual(test_bdm.volume_size, 8) def test_driver_snapshot_block_device(self): self._test_driver_device("snapshot") test_bdm = self.driver_classes['snapshot']( self.snapshot_bdm) self.assertEqual(test_bdm._bdm_obj.id, 4) self.assertEqual(test_bdm.snapshot_id, 'fake-snapshot-id-1') self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') self.assertEqual(test_bdm.volume_size, 3) def test_driver_image_block_device(self): self._test_driver_device('image') test_bdm = self.driver_classes['image']( self.image_bdm) self.assertEqual(test_bdm._bdm_obj.id, 5) self.assertEqual(test_bdm.image_id, 'fake-image-id-1') self.assertEqual(test_bdm.volume_size, 1) def test_driver_image_block_device_destination_local(self): self._test_driver_device('image') bdm = self.image_bdm_dict.copy() bdm['destination_type'] = 'local' self.assertRaises(driver_block_device._InvalidType, self.driver_classes['image'], fake_block_device.fake_bdm_object(self.context, bdm)) def test_driver_blank_block_device(self): self._test_driver_device('blank') test_bdm = self.driver_classes['blank']( self.blank_bdm) self.assertEqual(6, test_bdm._bdm_obj.id) self.assertEqual('fake-volume-id-2', test_bdm.volume_id) self.assertEqual(3, test_bdm.volume_size) 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) def test_call_wait_delete_volume(self): self._test_call_wait_func(True) def test_call_wait_delete_volume_fail(self): self._test_call_wait_func(True, True) def test_call_wait_no_delete_volume(self): self._test_call_wait_func(False) def _test_volume_attach(self, driver_bdm, bdm_dict, fake_volume, check_attach=True, fail_check_attach=False, driver_attach=False, fail_driver_attach=False, volume_attach=True, fail_volume_attach=False, access_mode='rw', availability_zone=None): elevated_context = self.context.elevated() self.stubs.Set(self.context, 'elevated', lambda: elevated_context) self.mox.StubOutWithMock(driver_bdm._bdm_obj, 'save') self.mox.StubOutWithMock(encryptors, 'get_encryption_metadata') instance_detail = {'id': '123', 'uuid': uuids.uuid, 'availability_zone': availability_zone} instance = fake_instance.fake_instance_obj(self.context, **instance_detail) connector = {'ip': 'fake_ip', 'host': 'fake_host'} connection_info = {'data': {'access_mode': access_mode}} expected_conn_info = {'data': {'access_mode': access_mode}, 'serial': fake_volume['id']} enc_data = {'fake': 'enc_data'} self.volume_api.get(self.context, fake_volume['id']).AndReturn(fake_volume) if check_attach: if not fail_check_attach: self.volume_api.check_attach(self.context, fake_volume, instance=instance).AndReturn(None) else: self.volume_api.check_attach(self.context, fake_volume, instance=instance).AndRaise( test.TestingException) driver_bdm._bdm_obj.save().AndReturn(None) return instance, expected_conn_info self.virt_driver.get_volume_connector(instance).AndReturn(connector) self.volume_api.initialize_connection( elevated_context, fake_volume['id'], connector).AndReturn(connection_info) if driver_attach: encryptors.get_encryption_metadata( elevated_context, self.volume_api, fake_volume['id'], connection_info).AndReturn(enc_data) if not fail_driver_attach: self.virt_driver.attach_volume( elevated_context, expected_conn_info, instance, bdm_dict['device_name'], disk_bus=bdm_dict['disk_bus'], device_type=bdm_dict['device_type'], encryption=enc_data).AndReturn(None) else: self.virt_driver.attach_volume( elevated_context, expected_conn_info, instance, bdm_dict['device_name'], disk_bus=bdm_dict['disk_bus'], device_type=bdm_dict['device_type'], encryption=enc_data).AndRaise(test.TestingException) self.volume_api.terminate_connection( elevated_context, fake_volume['id'], connector).AndReturn(None) driver_bdm._bdm_obj.save().AndReturn(None) return instance, expected_conn_info if volume_attach: driver_bdm._bdm_obj.save().AndReturn(None) if not fail_volume_attach: self.volume_api.attach(elevated_context, fake_volume['id'], uuids.uuid, bdm_dict['device_name'], mode=access_mode).AndReturn(None) else: self.volume_api.attach(elevated_context, fake_volume['id'], uuids.uuid, bdm_dict['device_name'], mode=access_mode).AndRaise( test.TestingException) if driver_attach: self.virt_driver.detach_volume( expected_conn_info, instance, bdm_dict['device_name'], encryption=enc_data).AndReturn(None) self.volume_api.terminate_connection( elevated_context, fake_volume['id'], connector).AndReturn(None) self.volume_api.detach(elevated_context, fake_volume['id']).AndReturn(None) driver_bdm._bdm_obj.save().AndReturn(None) return instance, expected_conn_info def test_volume_attach(self): test_bdm = self.driver_classes['volume']( self.volume_bdm) volume = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} instance, expected_conn_info = self._test_volume_attach( test_bdm, self.volume_bdm, volume) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) self.assertThat(test_bdm['connection_info'], matchers.DictMatches(expected_conn_info)) def test_volume_attach_ro(self): test_bdm = self.driver_classes['volume'](self.volume_bdm) volume = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} instance, expected_conn_info = self._test_volume_attach( test_bdm, self.volume_bdm, volume, access_mode='ro') self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) self.assertThat(test_bdm['connection_info'], matchers.DictMatches(expected_conn_info)) def test_volume_attach_update_size(self): test_bdm = self.driver_classes['volume'](self.volume_bdm) test_bdm.volume_size = None volume = {'id': 'fake-volume-id-1', 'attach_status': 'detached', 'size': 42} instance, expected_conn_info = self._test_volume_attach( test_bdm, self.volume_bdm, volume) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) self.assertEqual(expected_conn_info, test_bdm['connection_info']) self.assertEqual(42, test_bdm.volume_size) def test_volume_attach_check_attach_fails(self): test_bdm = self.driver_classes['volume']( self.volume_bdm) volume = {'id': 'fake-volume-id-1'} instance, _ = self._test_volume_attach( test_bdm, self.volume_bdm, volume, fail_check_attach=True) self.mox.ReplayAll() self.assertRaises(test.TestingException, test_bdm.attach, self.context, instance, self.volume_api, self.virt_driver) def test_volume_no_volume_attach(self): test_bdm = self.driver_classes['volume']( self.volume_bdm) volume = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} instance, expected_conn_info = self._test_volume_attach( test_bdm, self.volume_bdm, volume, check_attach=False, driver_attach=False) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, do_check_attach=False, do_driver_attach=False) self.assertThat(test_bdm['connection_info'], matchers.DictMatches(expected_conn_info)) def test_volume_attach_no_check_driver_attach(self): test_bdm = self.driver_classes['volume']( self.volume_bdm) volume = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} instance, expected_conn_info = self._test_volume_attach( test_bdm, self.volume_bdm, volume, check_attach=False, driver_attach=True) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, do_check_attach=False, do_driver_attach=True) self.assertThat(test_bdm['connection_info'], matchers.DictMatches(expected_conn_info)) def test_volume_attach_driver_attach_fails(self): test_bdm = self.driver_classes['volume']( self.volume_bdm) volume = {'id': 'fake-volume-id-1'} instance, _ = self._test_volume_attach( test_bdm, self.volume_bdm, volume, driver_attach=True, fail_driver_attach=True) self.mox.ReplayAll() self.assertRaises(test.TestingException, test_bdm.attach, self.context, instance, self.volume_api, self.virt_driver, do_driver_attach=True) def test_volume_attach_volume_attach_fails(self): test_bdm = self.driver_classes['volume']( self.volume_bdm) volume = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} instance, _ = self._test_volume_attach( test_bdm, self.volume_bdm, volume, driver_attach=True, fail_volume_attach=True) self.mox.ReplayAll() self.assertRaises(test.TestingException, test_bdm.attach, self.context, instance, self.volume_api, self.virt_driver, do_driver_attach=True) def test_volume_attach_no_driver_attach_volume_attach_fails(self): test_bdm = self.driver_classes['volume']( self.volume_bdm) volume = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} instance, _ = self._test_volume_attach( test_bdm, self.volume_bdm, volume, fail_volume_attach=True) self.mox.ReplayAll() self.assertRaises(test.TestingException, test_bdm.attach, self.context, instance, self.volume_api, self.virt_driver, do_driver_attach=False) def test_refresh_connection(self): test_bdm = self.driver_classes['snapshot']( self.snapshot_bdm) instance = {'id': 'fake_id', 'uuid': uuids.uuid} connector = {'ip': 'fake_ip', 'host': 'fake_host'} connection_info = {'data': {'multipath_id': 'fake_multipath_id'}} expected_conn_info = {'data': {'multipath_id': 'fake_multipath_id'}, 'serial': 'fake-volume-id-2'} self.mox.StubOutWithMock(test_bdm._bdm_obj, 'save') self.virt_driver.get_volume_connector(instance).AndReturn(connector) self.volume_api.initialize_connection( self.context, test_bdm.volume_id, connector).AndReturn(connection_info) test_bdm._bdm_obj.save().AndReturn(None) self.mox.ReplayAll() test_bdm.refresh_connection_info(self.context, instance, self.volume_api, self.virt_driver) self.assertThat(test_bdm['connection_info'], matchers.DictMatches(expected_conn_info)) def test_snapshot_attach_no_volume(self): no_volume_snapshot = self.snapshot_bdm_dict.copy() no_volume_snapshot['volume_id'] = None test_bdm = self.driver_classes['snapshot']( fake_block_device.fake_bdm_object( self.context, no_volume_snapshot)) snapshot = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} volume = {'id': 'fake-volume-id-2', 'attach_status': 'detached'} wait_func = self.mox.CreateMockAnything() self.volume_api.get_snapshot(self.context, 'fake-snapshot-id-1').AndReturn(snapshot) self.volume_api.create(self.context, 3, '', '', snapshot, availability_zone=None).AndReturn(volume) wait_func(self.context, 'fake-volume-id-2').AndReturn(None) instance, expected_conn_info = self._test_volume_attach( test_bdm, no_volume_snapshot, volume) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, wait_func) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') def test_snapshot_attach_no_volume_cinder_cross_az_attach_false(self): # Tests that the volume created from the snapshot has the same AZ as # the instance. self.flags(cross_az_attach=False, group='cinder') no_volume_snapshot = self.snapshot_bdm_dict.copy() no_volume_snapshot['volume_id'] = None test_bdm = self.driver_classes['snapshot']( fake_block_device.fake_bdm_object( self.context, no_volume_snapshot)) snapshot = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} volume = {'id': 'fake-volume-id-2', 'attach_status': 'detached'} wait_func = self.mox.CreateMockAnything() self.volume_api.get_snapshot(self.context, 'fake-snapshot-id-1').AndReturn(snapshot) self.volume_api.create(self.context, 3, '', '', snapshot, availability_zone='test-az').AndReturn(volume) wait_func(self.context, 'fake-volume-id-2').AndReturn(None) instance, expected_conn_info = self._test_volume_attach( test_bdm, no_volume_snapshot, volume, availability_zone='test-az') self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, wait_func) self.assertEqual('fake-volume-id-2', test_bdm.volume_id) def test_snapshot_attach_fail_volume(self): fail_volume_snapshot = self.snapshot_bdm_dict.copy() fail_volume_snapshot['volume_id'] = None test_bdm = self.driver_classes['snapshot']( fake_block_device.fake_bdm_object( self.context, fail_volume_snapshot)) snapshot = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} volume = {'id': 'fake-volume-id-2', 'attach_status': 'detached'} 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, '', '', snapshot, availability_zone=None) vol_delete.assert_called_once_with(self.context, volume['id']) def test_snapshot_attach_volume(self): test_bdm = self.driver_classes['snapshot']( self.snapshot_bdm) instance = {'id': 'fake_id', 'uuid': uuids.uuid} volume_class = self.driver_classes['volume'] self.mox.StubOutWithMock(volume_class, 'attach') # Make sure theses are not called self.mox.StubOutWithMock(self.volume_api, 'get_snapshot') self.mox.StubOutWithMock(self.volume_api, 'create') volume_class.attach(self.context, instance, self.volume_api, self.virt_driver, do_check_attach=True ).AndReturn(None) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') def test_image_attach_no_volume(self): no_volume_image = self.image_bdm_dict.copy() no_volume_image['volume_id'] = None test_bdm = self.driver_classes['image']( fake_block_device.fake_bdm_object( self.context, no_volume_image)) image = {'id': 'fake-image-id-1'} volume = {'id': 'fake-volume-id-2', 'attach_status': 'detached'} wait_func = self.mox.CreateMockAnything() self.volume_api.create(self.context, 1, '', '', image_id=image['id'], availability_zone=None).AndReturn(volume) wait_func(self.context, 'fake-volume-id-2').AndReturn(None) instance, expected_conn_info = self._test_volume_attach( test_bdm, no_volume_image, volume) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, wait_func) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') def test_image_attach_no_volume_cinder_cross_az_attach_false(self): # Tests that the volume created from the image has the same AZ as the # instance. self.flags(cross_az_attach=False, group='cinder') no_volume_image = self.image_bdm_dict.copy() no_volume_image['volume_id'] = None test_bdm = self.driver_classes['image']( fake_block_device.fake_bdm_object( self.context, no_volume_image)) image = {'id': 'fake-image-id-1'} volume = {'id': 'fake-volume-id-2', 'attach_status': 'detached'} wait_func = self.mox.CreateMockAnything() self.volume_api.create(self.context, 1, '', '', image_id=image['id'], availability_zone='test-az').AndReturn(volume) wait_func(self.context, 'fake-volume-id-2').AndReturn(None) instance, expected_conn_info = self._test_volume_attach( test_bdm, no_volume_image, volume, availability_zone='test-az') self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, wait_func) self.assertEqual('fake-volume-id-2', test_bdm.volume_id) def test_image_attach_fail_volume(self): fail_volume_image = self.image_bdm_dict.copy() fail_volume_image['volume_id'] = None test_bdm = self.driver_classes['image']( fake_block_device.fake_bdm_object( self.context, fail_volume_image)) image = {'id': 'fake-image-id-1'} volume = {'id': 'fake-volume-id-2', 'attach_status': 'detached'} 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) vol_delete.assert_called_once_with(self.context, volume['id']) def test_image_attach_volume(self): test_bdm = self.driver_classes['image']( self.image_bdm) instance = {'id': 'fake_id', 'uuid': uuids.uuid} volume_class = self.driver_classes['volume'] self.mox.StubOutWithMock(volume_class, 'attach') # Make sure theses are not called self.mox.StubOutWithMock(self.volume_api, 'get_snapshot') self.mox.StubOutWithMock(self.volume_api, 'create') volume_class.attach(self.context, instance, self.volume_api, self.virt_driver, do_check_attach=True ).AndReturn(None) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') def test_blank_attach_fail_volume(self): no_blank_volume = self.blank_bdm_dict.copy() no_blank_volume['volume_id'] = None test_bdm = self.driver_classes['blank']( fake_block_device.fake_bdm_object( self.context, no_blank_volume)) instance = fake_instance.fake_instance_obj(mock.sentinel.ctx, **{'uuid': uuids.uuid}) volume = {'id': 'fake-volume-id-2', 'display_name': '%s-blank-vol' % 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, test_bdm.volume_size, '%s-blank-vol' % uuids.uuid, '', availability_zone=None) vol_delete.assert_called_once_with( self.context, volume['id']) def test_blank_attach_volume(self): no_blank_volume = self.blank_bdm_dict.copy() no_blank_volume['volume_id'] = None test_bdm = self.driver_classes['blank']( fake_block_device.fake_bdm_object( self.context, no_blank_volume)) instance = fake_instance.fake_instance_obj(mock.sentinel.ctx, **{'uuid': uuids.uuid}) volume_class = self.driver_classes['volume'] volume = {'id': 'fake-volume-id-2', 'display_name': '%s-blank-vol' % uuids.uuid} with test.nested( mock.patch.object(self.volume_api, 'create', return_value=volume), mock.patch.object(volume_class, 'attach') ) as (vol_create, vol_attach): test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) vol_create.assert_called_once_with( self.context, test_bdm.volume_size, '%s-blank-vol' % uuids.uuid, '', availability_zone=None) vol_attach.assert_called_once_with(self.context, instance, self.volume_api, self.virt_driver, do_check_attach=True) self.assertEqual('fake-volume-id-2', test_bdm.volume_id) def test_blank_attach_volume_cinder_cross_az_attach_false(self): # Tests that the blank volume created is in the same availability zone # as the instance. self.flags(cross_az_attach=False, group='cinder') no_blank_volume = self.blank_bdm_dict.copy() no_blank_volume['volume_id'] = None test_bdm = self.driver_classes['blank']( fake_block_device.fake_bdm_object( self.context, no_blank_volume)) updates = {'uuid': uuids.uuid, 'availability_zone': 'test-az'} instance = fake_instance.fake_instance_obj(mock.sentinel.ctx, **updates) volume_class = self.driver_classes['volume'] volume = {'id': 'fake-volume-id-2', 'display_name': '%s-blank-vol' % uuids.uuid} with mock.patch.object(self.volume_api, 'create', return_value=volume) as vol_create: with mock.patch.object(volume_class, 'attach') as vol_attach: test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) vol_create.assert_called_once_with( self.context, test_bdm.volume_size, '%s-blank-vol' % uuids.uuid, '', availability_zone='test-az') vol_attach.assert_called_once_with(self.context, instance, self.volume_api, self.virt_driver, do_check_attach=True) self.assertEqual('fake-volume-id-2', test_bdm.volume_id) def test_convert_block_devices(self): bdms = objects.BlockDeviceMappingList( objects=[self.volume_bdm, self.ephemeral_bdm]) converted = driver_block_device._convert_block_devices( self.driver_classes['volume'], bdms) self.assertEqual(converted, [self.volume_driver_bdm]) def test_convert_all_volumes(self): converted = driver_block_device.convert_all_volumes() self.assertEqual([], converted) converted = driver_block_device.convert_all_volumes( self.volume_bdm, self.ephemeral_bdm, self.image_bdm, self.blank_bdm, self.snapshot_bdm) self.assertEqual(converted, [self.volume_driver_bdm, self.image_driver_bdm, self.blank_driver_bdm, self.snapshot_driver_bdm]) def test_convert_volume(self): self.assertIsNone(driver_block_device.convert_volume(self.swap_bdm)) self.assertEqual(self.volume_driver_bdm, driver_block_device.convert_volume(self.volume_bdm)) self.assertEqual(self.snapshot_driver_bdm, driver_block_device.convert_volume(self.snapshot_bdm)) def test_legacy_block_devices(self): test_snapshot = self.driver_classes['snapshot']( self.snapshot_bdm) block_device_mapping = [test_snapshot, test_snapshot] legacy_bdm = driver_block_device.legacy_block_devices( block_device_mapping) self.assertEqual(legacy_bdm, [self.snapshot_legacy_driver_bdm, self.snapshot_legacy_driver_bdm]) # Test that the ephemerals work as expected test_ephemerals = [self.driver_classes['ephemeral']( self.ephemeral_bdm) for _ in range(2)] expected = [self.ephemeral_legacy_driver_bdm.copy() for _ in range(2)] expected[0]['virtual_name'] = 'ephemeral0' expected[0]['num'] = 0 expected[1]['virtual_name'] = 'ephemeral1' expected[1]['num'] = 1 legacy_ephemerals = driver_block_device.legacy_block_devices( test_ephemerals) self.assertEqual(expected, legacy_ephemerals) def test_get_swap(self): swap = [self.swap_driver_bdm] legacy_swap = [self.swap_legacy_driver_bdm] no_swap = [self.volume_driver_bdm] self.assertEqual(swap[0], driver_block_device.get_swap(swap)) self.assertEqual(legacy_swap[0], driver_block_device.get_swap(legacy_swap)) self.assertIsNone(driver_block_device.get_swap(no_swap)) self.assertIsNone(driver_block_device.get_swap([])) def test_is_implemented(self): for bdm in (self.image_bdm, self.volume_bdm, self.swap_bdm, self.ephemeral_bdm, self.snapshot_bdm): self.assertTrue(driver_block_device.is_implemented(bdm)) local_image = self.image_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) test_ephemeral = self.driver_classes['ephemeral'](self.ephemeral_bdm) test_image = self.driver_classes['image'](self.image_bdm) test_snapshot = self.driver_classes['snapshot'](self.snapshot_bdm) test_volume = self.driver_classes['volume'](self.volume_bdm) test_blank = self.driver_classes['blank'](self.blank_bdm) for bdm in (test_image, test_snapshot, test_volume, test_blank): self.assertTrue(driver_block_device.is_block_device_mapping( bdm._bdm_obj)) for bdm in (test_swap, test_ephemeral): self.assertFalse(driver_block_device.is_block_device_mapping( bdm._bdm_obj)) def test_get_volume_create_az_cinder_cross_az_attach_true(self): # Tests that we get None back if cinder.cross_az_attach=True even if # the instance has an AZ assigned. Note that since cross_az_attach # defaults to True we don't need to set a flag explicitly for the test. updates = {'availability_zone': 'test-az'} instance = fake_instance.fake_instance_obj(self.context, **updates) self.assertIsNone( driver_block_device._get_volume_create_az_value(instance)) def test_refresh_conn_infos(self): # Only DriverVolumeBlockDevice derived devices should refresh their # connection_info during a refresh_conn_infos call. test_volume = mock.MagicMock( spec=driver_block_device.DriverVolumeBlockDevice) test_image = mock.MagicMock( spec=driver_block_device.DriverImageBlockDevice) test_snapshot = mock.MagicMock( spec=driver_block_device.DriverSnapshotBlockDevice) test_blank = mock.MagicMock( spec=driver_block_device.DriverBlankBlockDevice) test_eph = mock.MagicMock( spec=driver_block_device.DriverEphemeralBlockDevice) test_swap = mock.MagicMock( spec=driver_block_device.DriverSwapBlockDevice) block_device_mapping = [test_volume, test_image, test_eph, test_snapshot, test_swap, test_blank] driver_block_device.refresh_conn_infos(block_device_mapping, mock.sentinel.refresh_context, mock.sentinel.refresh_instance, mock.sentinel.refresh_vol_api, mock.sentinel.refresh_virt_drv) for test_mock in [test_volume, test_image, test_snapshot, test_blank]: test_mock.refresh_connection_info.assert_called_once_with( mock.sentinel.refresh_context, mock.sentinel.refresh_instance, mock.sentinel.refresh_vol_api, mock.sentinel.refresh_virt_drv) # NOTE(lyarwood): Can't think of a better way of testing this as we # can't assert_not_called if the method isn't in the spec. self.assertFalse(hasattr(test_eph, 'refresh_connection_info')) self.assertFalse(hasattr(test_swap, 'refresh_connection_info'))
def create(*args, **kwargs): self.assertThat( block_device.BlockDeviceDict(self.bdm[0]), matchers.DictMatches(kwargs['block_device_mapping'][0])) return old_create(*args, **kwargs)
class TestDriverBlockDevice(test.NoDBTestCase): driver_classes = { 'swap': driver_block_device.DriverSwapBlockDevice, 'ephemeral': driver_block_device.DriverEphemeralBlockDevice, 'volume': driver_block_device.DriverVolumeBlockDevice, 'snapshot': driver_block_device.DriverSnapshotBlockDevice, 'image': driver_block_device.DriverImageBlockDevice, 'blank': driver_block_device.DriverBlankBlockDevice } swap_bdm = block_device.BlockDeviceDict({ 'id': 1, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sdb1', 'source_type': 'blank', 'destination_type': 'local', 'delete_on_termination': True, 'guest_format': 'swap', 'disk_bus': 'scsi', 'volume_size': 2, 'boot_index': -1 }) swap_driver_bdm = { 'device_name': '/dev/sdb1', 'swap_size': 2, 'disk_bus': 'scsi' } swap_legacy_driver_bdm = {'device_name': '/dev/sdb1', 'swap_size': 2} ephemeral_bdm = block_device.BlockDeviceDict({ 'id': 2, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sdc1', 'source_type': 'blank', 'destination_type': 'local', 'disk_bus': 'scsi', 'device_type': 'disk', 'volume_size': 4, 'guest_format': 'ext4', 'delete_on_termination': True, 'boot_index': -1 }) ephemeral_driver_bdm = { 'device_name': '/dev/sdc1', 'size': 4, 'device_type': 'disk', 'guest_format': 'ext4', 'disk_bus': 'scsi' } ephemeral_legacy_driver_bdm = { 'device_name': '/dev/sdc1', 'size': 4, 'virtual_name': 'ephemeral0', 'num': 0 } volume_bdm = block_device.BlockDeviceDict({ 'id': 3, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sda1', 'source_type': 'volume', 'disk_bus': 'scsi', 'device_type': 'disk', 'volume_size': 8, 'destination_type': 'volume', 'volume_id': 'fake-volume-id-1', 'guest_format': 'ext4', 'connection_info': '{"fake": "connection_info"}', 'delete_on_termination': False, 'boot_index': 0 }) volume_driver_bdm = { 'mount_device': '/dev/sda1', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': False, 'disk_bus': 'scsi', 'device_type': 'disk', 'guest_format': 'ext4', 'boot_index': 0 } volume_legacy_driver_bdm = { 'mount_device': '/dev/sda1', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': False } snapshot_bdm = block_device.BlockDeviceDict({ 'id': 4, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sda2', 'delete_on_termination': True, 'volume_size': 3, 'disk_bus': 'scsi', 'device_type': 'disk', 'source_type': 'snapshot', 'destination_type': 'volume', 'connection_info': '{"fake": "connection_info"}', 'snapshot_id': 'fake-snapshot-id-1', 'volume_id': 'fake-volume-id-2', 'boot_index': -1 }) snapshot_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': True, 'disk_bus': 'scsi', 'device_type': 'disk', 'guest_format': None, 'boot_index': -1 } snapshot_legacy_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': True } image_bdm = block_device.BlockDeviceDict({ 'id': 5, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sda2', 'delete_on_termination': True, 'volume_size': 1, 'disk_bus': 'scsi', 'device_type': 'disk', 'source_type': 'image', 'destination_type': 'volume', 'connection_info': '{"fake": "connection_info"}', 'image_id': 'fake-image-id-1', 'volume_id': 'fake-volume-id-2', 'boot_index': -1 }) image_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': True, 'disk_bus': 'scsi', 'device_type': 'disk', 'guest_format': None, 'boot_index': -1 } image_legacy_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': True } blank_bdm = block_device.BlockDeviceDict({ 'id': 6, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sda2', 'delete_on_termination': True, 'volume_size': 3, 'disk_bus': 'scsi', 'device_type': 'disk', 'source_type': 'blank', 'destination_type': 'volume', 'connection_info': '{"fake": "connection_info"}', 'snapshot_id': 'fake-snapshot-id-1', 'volume_id': 'fake-volume-id-2', 'boot_index': -1 }) blank_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': True, 'disk_bus': 'scsi', 'device_type': 'disk', 'guest_format': None, 'boot_index': -1 } blank_legacy_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': True } def setUp(self): super(TestDriverBlockDevice, self).setUp() self.volume_api = self.mox.CreateMock(cinder.API) self.virt_driver = self.mox.CreateMock(driver.ComputeDriver) self.context = context.RequestContext('fake_user', 'fake_project') def test_no_device_raises(self): for name, cls in self.driver_classes.items(): self.assertRaises(driver_block_device._NotTransformable, cls, {'no_device': True}) def _test_driver_device(self, name): db_bdm = getattr(self, "%s_bdm" % name) test_bdm = self.driver_classes[name](db_bdm) self.assertThat( test_bdm, matchers.DictMatches(getattr(self, "%s_driver_bdm" % name))) for k, v in six.iteritems(db_bdm): field_val = getattr(test_bdm._bdm_obj, k) if isinstance(field_val, bool): v = bool(v) self.assertEqual(field_val, v) self.assertThat( test_bdm.legacy(), matchers.DictMatches(getattr(self, "%s_legacy_driver_bdm" % name))) # Test passthru attributes for passthru in test_bdm._proxy_as_attr: self.assertEqual(getattr(test_bdm, passthru), getattr(test_bdm._bdm_obj, passthru)) # Make sure that all others raise _invalidType for other_name, cls in six.iteritems(self.driver_classes): if other_name == name: continue self.assertRaises(driver_block_device._InvalidType, cls, getattr(self, '%s_bdm' % name)) # Test the save method with mock.patch.object(test_bdm._bdm_obj, 'save') as save_mock: for fld, alias in six.iteritems(test_bdm._update_on_save): test_bdm[alias or fld] = 'fake_changed_value' test_bdm.save() for fld, alias in six.iteritems(test_bdm._update_on_save): self.assertEqual(test_bdm[alias or fld], getattr(test_bdm._bdm_obj, fld)) save_mock.assert_called_once_with() def check_save(): self.assertEqual(set([]), test_bdm._bdm_obj.obj_what_changed()) # Test that nothing is set on the object if there are no actual changes test_bdm._bdm_obj.obj_reset_changes() with mock.patch.object(test_bdm._bdm_obj, 'save') as save_mock: save_mock.side_effect = check_save test_bdm.save() def _test_driver_default_size(self, name): size = 'swap_size' if name == 'swap' else 'size' no_size_bdm = getattr(self, "%s_bdm" % name).copy() no_size_bdm['volume_size'] = None driver_bdm = self.driver_classes[name](no_size_bdm) self.assertEqual(driver_bdm[size], 0) del no_size_bdm['volume_size'] driver_bdm = self.driver_classes[name](no_size_bdm) self.assertEqual(driver_bdm[size], 0) def test_driver_swap_block_device(self): self._test_driver_device("swap") def test_driver_swap_default_size(self): self._test_driver_default_size('swap') def test_driver_ephemeral_block_device(self): self._test_driver_device("ephemeral") def test_driver_ephemeral_default_size(self): self._test_driver_default_size('ephemeral') def test_driver_volume_block_device(self): self._test_driver_device("volume") test_bdm = self.driver_classes['volume'](self.volume_bdm) self.assertEqual(test_bdm['connection_info'], jsonutils.loads(test_bdm._bdm_obj.connection_info)) self.assertEqual(test_bdm._bdm_obj.id, 3) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-1') self.assertEqual(test_bdm.volume_size, 8) def test_driver_snapshot_block_device(self): self._test_driver_device("snapshot") test_bdm = self.driver_classes['snapshot'](self.snapshot_bdm) self.assertEqual(test_bdm._bdm_obj.id, 4) self.assertEqual(test_bdm.snapshot_id, 'fake-snapshot-id-1') self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') self.assertEqual(test_bdm.volume_size, 3) def test_driver_image_block_device(self): self._test_driver_device('image') test_bdm = self.driver_classes['image'](self.image_bdm) self.assertEqual(test_bdm._bdm_obj.id, 5) self.assertEqual(test_bdm.image_id, 'fake-image-id-1') self.assertEqual(test_bdm.volume_size, 1) def test_driver_image_block_device_destination_local(self): self._test_driver_device('image') bdm = self.image_bdm.copy() bdm['destination_type'] = 'local' self.assertRaises(driver_block_device._InvalidType, self.driver_classes['image'], bdm) def test_driver_blank_block_device(self): self._test_driver_device('blank') test_bdm = self.driver_classes['blank'](self.blank_bdm) self.assertEqual(6, test_bdm._bdm_obj.id) self.assertEqual('fake-volume-id-2', test_bdm.volume_id) self.assertEqual(3, test_bdm.volume_size) def _test_volume_attach(self, driver_bdm, bdm_dict, fake_volume, check_attach=True, fail_check_attach=False, driver_attach=False, fail_driver_attach=False, volume_attach=True, fail_volume_attach=False, access_mode='rw'): elevated_context = self.context.elevated() self.stubs.Set(self.context, 'elevated', lambda: elevated_context) self.mox.StubOutWithMock(driver_bdm._bdm_obj, 'save') self.mox.StubOutWithMock(encryptors, 'get_encryption_metadata') instance_detail = {'id': '123', 'uuid': 'fake_uuid'} instance = fake_instance.fake_instance_obj(self.context, **instance_detail) connector = {'ip': 'fake_ip', 'host': 'fake_host'} connection_info = {'data': {'access_mode': access_mode}} expected_conn_info = { 'data': { 'access_mode': access_mode }, 'serial': fake_volume['id'] } enc_data = {'fake': 'enc_data'} self.volume_api.get(self.context, fake_volume['id']).AndReturn(fake_volume) if check_attach: if not fail_check_attach: self.volume_api.check_attach(self.context, fake_volume, instance=instance).AndReturn(None) else: self.volume_api.check_attach(self.context, fake_volume, instance=instance).AndRaise( test.TestingException) driver_bdm._bdm_obj.save().AndReturn(None) return instance, expected_conn_info self.virt_driver.get_volume_connector(instance).AndReturn(connector) self.volume_api.initialize_connection( elevated_context, fake_volume['id'], connector).AndReturn(connection_info) if driver_attach: encryptors.get_encryption_metadata( elevated_context, self.volume_api, fake_volume['id'], connection_info).AndReturn(enc_data) if not fail_driver_attach: self.virt_driver.attach_volume( elevated_context, expected_conn_info, instance, bdm_dict['device_name'], disk_bus=bdm_dict['disk_bus'], device_type=bdm_dict['device_type'], encryption=enc_data).AndReturn(None) else: self.virt_driver.attach_volume( elevated_context, expected_conn_info, instance, bdm_dict['device_name'], disk_bus=bdm_dict['disk_bus'], device_type=bdm_dict['device_type'], encryption=enc_data).AndRaise(test.TestingException) self.volume_api.terminate_connection(elevated_context, fake_volume['id'], connector).AndReturn(None) driver_bdm._bdm_obj.save().AndReturn(None) return instance, expected_conn_info if volume_attach: driver_bdm._bdm_obj.save().AndReturn(None) if not fail_volume_attach: self.volume_api.attach(elevated_context, fake_volume['id'], 'fake_uuid', bdm_dict['device_name'], mode=access_mode).AndReturn(None) else: self.volume_api.attach(elevated_context, fake_volume['id'], 'fake_uuid', bdm_dict['device_name'], mode=access_mode).AndRaise( test.TestingException) driver_bdm._bdm_obj.save().AndReturn(None) return instance, expected_conn_info def test_volume_attach(self): test_bdm = self.driver_classes['volume'](self.volume_bdm) volume = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} instance, expected_conn_info = self._test_volume_attach( test_bdm, self.volume_bdm, volume) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) self.assertThat(test_bdm['connection_info'], matchers.DictMatches(expected_conn_info)) def test_volume_attach_ro(self): test_bdm = self.driver_classes['volume'](self.volume_bdm) volume = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} instance, expected_conn_info = self._test_volume_attach( test_bdm, self.volume_bdm, volume, access_mode='ro') self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) self.assertThat(test_bdm['connection_info'], matchers.DictMatches(expected_conn_info)) def test_volume_attach_check_attach_fails(self): test_bdm = self.driver_classes['volume'](self.volume_bdm) volume = {'id': 'fake-volume-id-1'} instance, _ = self._test_volume_attach(test_bdm, self.volume_bdm, volume, fail_check_attach=True) self.mox.ReplayAll() self.assertRaises(test.TestingException, test_bdm.attach, self.context, instance, self.volume_api, self.virt_driver) def test_volume_no_volume_attach(self): test_bdm = self.driver_classes['volume'](self.volume_bdm) volume = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} instance, expected_conn_info = self._test_volume_attach( test_bdm, self.volume_bdm, volume, check_attach=False, driver_attach=False) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, do_check_attach=False, do_driver_attach=False) self.assertThat(test_bdm['connection_info'], matchers.DictMatches(expected_conn_info)) def test_volume_attach_no_check_driver_attach(self): test_bdm = self.driver_classes['volume'](self.volume_bdm) volume = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} instance, expected_conn_info = self._test_volume_attach( test_bdm, self.volume_bdm, volume, check_attach=False, driver_attach=True) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, do_check_attach=False, do_driver_attach=True) self.assertThat(test_bdm['connection_info'], matchers.DictMatches(expected_conn_info)) def test_volume_attach_driver_attach_fails(self): test_bdm = self.driver_classes['volume'](self.volume_bdm) volume = {'id': 'fake-volume-id-1'} instance, _ = self._test_volume_attach(test_bdm, self.volume_bdm, volume, driver_attach=True, fail_driver_attach=True) self.mox.ReplayAll() self.assertRaises(test.TestingException, test_bdm.attach, self.context, instance, self.volume_api, self.virt_driver, do_driver_attach=True) def test_volume_attach_volume_attach_fails(self): test_bdm = self.driver_classes['volume'](self.volume_bdm) volume = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} instance, _ = self._test_volume_attach(test_bdm, self.volume_bdm, volume, driver_attach=True, fail_volume_attach=True) self.mox.ReplayAll() self.assertRaises(test.TestingException, test_bdm.attach, self.context, instance, self.volume_api, self.virt_driver, do_driver_attach=True) def test_refresh_connection(self): test_bdm = self.driver_classes['snapshot'](self.snapshot_bdm) instance = {'id': 'fake_id', 'uuid': 'fake_uuid'} connector = {'ip': 'fake_ip', 'host': 'fake_host'} connection_info = {'data': {'multipath_id': 'fake_multipath_id'}} expected_conn_info = { 'data': { 'multipath_id': 'fake_multipath_id' }, 'serial': 'fake-volume-id-2' } self.mox.StubOutWithMock(test_bdm._bdm_obj, 'save') self.virt_driver.get_volume_connector(instance).AndReturn(connector) self.volume_api.initialize_connection( self.context, test_bdm.volume_id, connector).AndReturn(connection_info) test_bdm._bdm_obj.save().AndReturn(None) self.mox.ReplayAll() test_bdm.refresh_connection_info(self.context, instance, self.volume_api, self.virt_driver) self.assertThat(test_bdm['connection_info'], matchers.DictMatches(expected_conn_info)) def test_snapshot_attach_no_volume(self): no_volume_snapshot = self.snapshot_bdm.copy() no_volume_snapshot['volume_id'] = None test_bdm = self.driver_classes['snapshot'](no_volume_snapshot) snapshot = {'id': 'fake-volume-id-1', 'attach_status': 'detached'} volume = {'id': 'fake-volume-id-2', 'attach_status': 'detached'} wait_func = self.mox.CreateMockAnything() self.volume_api.get_snapshot(self.context, 'fake-snapshot-id-1').AndReturn(snapshot) self.volume_api.create(self.context, 3, '', '', snapshot, availability_zone=None).AndReturn(volume) wait_func(self.context, 'fake-volume-id-2').AndReturn(None) instance, expected_conn_info = self._test_volume_attach( test_bdm, no_volume_snapshot, volume) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, wait_func) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') def test_snapshot_attach_volume(self): test_bdm = self.driver_classes['snapshot'](self.snapshot_bdm) instance = {'id': 'fake_id', 'uuid': 'fake_uuid'} volume_class = self.driver_classes['volume'] self.mox.StubOutWithMock(volume_class, 'attach') # Make sure theses are not called self.mox.StubOutWithMock(self.volume_api, 'get_snapshot') self.mox.StubOutWithMock(self.volume_api, 'create') volume_class.attach(self.context, instance, self.volume_api, self.virt_driver, do_check_attach=True).AndReturn(None) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') def test_image_attach_no_volume(self): no_volume_image = self.image_bdm.copy() no_volume_image['volume_id'] = None test_bdm = self.driver_classes['image'](no_volume_image) image = {'id': 'fake-image-id-1'} volume = {'id': 'fake-volume-id-2', 'attach_status': 'detached'} wait_func = self.mox.CreateMockAnything() self.volume_api.create(self.context, 1, '', '', image_id=image['id'], availability_zone=None).AndReturn(volume) wait_func(self.context, 'fake-volume-id-2').AndReturn(None) instance, expected_conn_info = self._test_volume_attach( test_bdm, no_volume_image, volume) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, wait_func) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') def test_image_attach_volume(self): test_bdm = self.driver_classes['image'](self.image_bdm) instance = {'id': 'fake_id', 'uuid': 'fake_uuid'} volume_class = self.driver_classes['volume'] self.mox.StubOutWithMock(volume_class, 'attach') # Make sure theses are not called self.mox.StubOutWithMock(self.volume_api, 'get_snapshot') self.mox.StubOutWithMock(self.volume_api, 'create') volume_class.attach(self.context, instance, self.volume_api, self.virt_driver, do_check_attach=True).AndReturn(None) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') def test_blank_attach_volume(self): no_blank_volume = self.blank_bdm.copy() no_blank_volume['volume_id'] = None test_bdm = self.driver_classes['blank'](no_blank_volume) instance = fake_instance.fake_instance_obj(mock.sentinel.ctx, **{'uuid': 'fake-uuid'}) volume_class = self.driver_classes['volume'] volume = { 'id': 'fake-volume-id-2', 'display_name': 'fake-uuid-blank-vol' } with contextlib.nested( mock.patch.object(self.volume_api, 'create', return_value=volume), mock.patch.object(volume_class, 'attach')) as (vol_create, vol_attach): test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) vol_create.assert_called_once_with( self.context, test_bdm.volume_size, 'fake-uuid-blank-vol', '', availability_zone=instance.availability_zone) vol_attach.assert_called_once_with(self.context, instance, self.volume_api, self.virt_driver, do_check_attach=True) self.assertEqual('fake-volume-id-2', test_bdm.volume_id) def test_convert_block_devices(self): converted = driver_block_device._convert_block_devices( self.driver_classes['volume'], [self.volume_bdm, self.ephemeral_bdm]) self.assertEqual(converted, [self.volume_driver_bdm]) def test_convert_all_volumes(self): converted = driver_block_device.convert_all_volumes() self.assertEqual([], converted) converted = driver_block_device.convert_all_volumes( self.volume_bdm, self.ephemeral_bdm, self.image_bdm, self.blank_bdm, self.snapshot_bdm) self.assertEqual(converted, [ self.volume_driver_bdm, self.image_driver_bdm, self.blank_driver_bdm, self.snapshot_driver_bdm ]) def test_convert_volume(self): self.assertIsNone(driver_block_device.convert_volume(self.swap_bdm)) self.assertEqual(self.volume_driver_bdm, driver_block_device.convert_volume(self.volume_bdm)) self.assertEqual(self.snapshot_driver_bdm, driver_block_device.convert_volume(self.snapshot_bdm)) def test_legacy_block_devices(self): test_snapshot = self.driver_classes['snapshot'](self.snapshot_bdm) block_device_mapping = [test_snapshot, test_snapshot] legacy_bdm = driver_block_device.legacy_block_devices( block_device_mapping) self.assertEqual( legacy_bdm, [self.snapshot_legacy_driver_bdm, self.snapshot_legacy_driver_bdm]) # Test that the ephemerals work as expected test_ephemerals = [ self.driver_classes['ephemeral'](self.ephemeral_bdm) for _ in range(2) ] expected = [self.ephemeral_legacy_driver_bdm.copy() for _ in range(2)] expected[0]['virtual_name'] = 'ephemeral0' expected[0]['num'] = 0 expected[1]['virtual_name'] = 'ephemeral1' expected[1]['num'] = 1 legacy_ephemerals = driver_block_device.legacy_block_devices( test_ephemerals) self.assertEqual(expected, legacy_ephemerals) def test_get_swap(self): swap = [self.swap_driver_bdm] legacy_swap = [self.swap_legacy_driver_bdm] no_swap = [self.volume_driver_bdm] self.assertEqual(swap[0], driver_block_device.get_swap(swap)) self.assertEqual(legacy_swap[0], driver_block_device.get_swap(legacy_swap)) self.assertIsNone(driver_block_device.get_swap(no_swap)) self.assertIsNone(driver_block_device.get_swap([])) def test_is_implemented(self): for bdm in (self.image_bdm, self.volume_bdm, self.swap_bdm, self.ephemeral_bdm, self.snapshot_bdm): self.assertTrue(driver_block_device.is_implemented(bdm)) local_image = self.image_bdm.copy() local_image['destination_type'] = 'local' self.assertFalse(driver_block_device.is_implemented(local_image)) def test_is_block_device_mapping(self): test_swap = self.driver_classes['swap'](self.swap_bdm) test_ephemeral = self.driver_classes['ephemeral'](self.ephemeral_bdm) test_image = self.driver_classes['image'](self.image_bdm) test_snapshot = self.driver_classes['snapshot'](self.snapshot_bdm) test_volume = self.driver_classes['volume'](self.volume_bdm) test_blank = self.driver_classes['blank'](self.blank_bdm) for bdm in (test_image, test_snapshot, test_volume, test_blank): self.assertTrue( driver_block_device.is_block_device_mapping(bdm._bdm_obj)) for bdm in (test_swap, test_ephemeral): self.assertFalse( driver_block_device.is_block_device_mapping(bdm._bdm_obj))
def get_image_mapping(self): return block_device.BlockDeviceDict(self).get_image_mapping()
class TestDriverBlockDevice(test.NoDBTestCase): driver_classes = { 'swap': driver_block_device.DriverSwapBlockDevice, 'ephemeral': driver_block_device.DriverEphemeralBlockDevice, 'volume': driver_block_device.DriverVolumeBlockDevice, 'snapshot': driver_block_device.DriverSnapshotBlockDevice, 'image': driver_block_device.DriverImageBlockDevice } swap_bdm = block_device.BlockDeviceDict({ 'id': 1, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sdb1', 'source_type': 'blank', 'destination_type': 'local', 'delete_on_termination': True, 'guest_format': 'swap', 'disk_bus': 'scsi', 'volume_size': 2, 'boot_index': -1 }) swap_driver_bdm = { 'device_name': '/dev/sdb1', 'swap_size': 2, 'disk_bus': 'scsi' } swap_legacy_driver_bdm = {'device_name': '/dev/sdb1', 'swap_size': 2} ephemeral_bdm = block_device.BlockDeviceDict({ 'id': 2, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sdc1', 'source_type': 'blank', 'destination_type': 'local', 'disk_bus': 'scsi', 'device_type': 'disk', 'volume_size': 4, 'guest_format': 'ext4', 'delete_on_termination': True, 'boot_index': -1 }) ephemeral_driver_bdm = { 'device_name': '/dev/sdc1', 'size': 4, 'device_type': 'disk', 'guest_format': 'ext4', 'disk_bus': 'scsi' } ephemeral_legacy_driver_bdm = { 'device_name': '/dev/sdc1', 'size': 4, 'virtual_name': 'ephemeral0', 'num': 0 } volume_bdm = block_device.BlockDeviceDict({ 'id': 3, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sda1', 'source_type': 'volume', 'disk_bus': 'scsi', 'device_type': 'disk', 'volume_size': 8, 'destination_type': 'volume', 'volume_id': 'fake-volume-id-1', 'guest_format': 'ext4', 'connection_info': '{"fake": "connection_info"}', 'delete_on_termination': False, 'boot_index': 0 }) volume_driver_bdm = { 'mount_device': '/dev/sda1', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': False, 'disk_bus': 'scsi', 'device_type': 'disk', 'guest_format': 'ext4', 'boot_index': 0 } volume_legacy_driver_bdm = { 'mount_device': '/dev/sda1', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': False } snapshot_bdm = block_device.BlockDeviceDict({ 'id': 4, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sda2', 'delete_on_termination': True, 'volume_size': 3, 'disk_bus': 'scsi', 'device_type': 'disk', 'source_type': 'snapshot', 'destination_type': 'volume', 'connection_info': '{"fake": "connection_info"}', 'snapshot_id': 'fake-snapshot-id-1', 'volume_id': 'fake-volume-id-2', 'boot_index': -1 }) snapshot_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': True, 'disk_bus': 'scsi', 'device_type': 'disk', 'guest_format': None, 'boot_index': -1 } snapshot_legacy_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': True } image_bdm = block_device.BlockDeviceDict({ 'id': 5, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sda2', 'delete_on_termination': True, 'volume_size': 1, 'disk_bus': 'scsi', 'device_type': 'disk', 'source_type': 'image', 'destination_type': 'volume', 'connection_info': '{"fake": "connection_info"}', 'image_id': 'fake-image-id-1', 'volume_id': 'fake-volume-id-2', 'boot_index': -1 }) image_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': True, 'disk_bus': 'scsi', 'device_type': 'disk', 'guest_format': None, 'boot_index': -1 } image_legacy_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': True } def setUp(self): super(TestDriverBlockDevice, self).setUp() self.volume_api = self.mox.CreateMock(cinder.API) self.virt_driver = self.mox.CreateMock(driver.ComputeDriver) self.db_api = self.mox.CreateMock(conductor_api.API) self.context = context.RequestContext('fake_user', 'fake_project') def test_driver_block_device_base_class(self): self.base_class_transform_called = False class DummyBlockDevice(driver_block_device.DriverBlockDevice): _fields = set(['foo', 'bar']) _legacy_fields = set(['foo', 'baz']) def _transform(inst, bdm): self.base_class_transform_called = True dummy_device = DummyBlockDevice({'foo': 'foo_val', 'id': 42}) self.assertTrue(self.base_class_transform_called) self.assertThat(dummy_device, matchers.DictMatches({ 'foo': None, 'bar': None })) self.assertEquals(dummy_device.id, 42) self.assertThat(dummy_device.legacy(), matchers.DictMatches({ 'foo': None, 'baz': None })) self.assertRaises(driver_block_device._NotTransformable, DummyBlockDevice, {'no_device': True}) def _test_driver_device(self, name): test_bdm = self.driver_classes[name](getattr(self, "%s_bdm" % name)) self.assertThat( test_bdm, matchers.DictMatches(getattr(self, "%s_driver_bdm" % name))) self.assertThat( test_bdm.legacy(), matchers.DictMatches(getattr(self, "%s_legacy_driver_bdm" % name))) # Make sure that all others raise _invalidType for other_name, cls in self.driver_classes.iteritems(): if other_name == name: continue self.assertRaises(driver_block_device._InvalidType, cls, getattr(self, '%s_bdm' % name)) def _test_driver_default_size(self, name): size = 'swap_size' if name == 'swap' else 'size' no_size_bdm = getattr(self, "%s_bdm" % name).copy() no_size_bdm['volume_size'] = None driver_bdm = self.driver_classes[name](no_size_bdm) self.assertEqual(driver_bdm[size], 0) del no_size_bdm['volume_size'] driver_bdm = self.driver_classes[name](no_size_bdm) self.assertEqual(driver_bdm[size], 0) def test_driver_swap_block_device(self): self._test_driver_device("swap") def test_driver_swap_default_size(self): self._test_driver_default_size('swap') def test_driver_ephemeral_block_device(self): self._test_driver_device("ephemeral") def test_driver_ephemeral_default_size(self): self._test_driver_default_size('ephemeral') def test_driver_volume_block_device(self): self._test_driver_device("volume") test_bdm = self.driver_classes['volume'](self.volume_bdm) self.assertEquals(test_bdm.id, 3) self.assertEquals(test_bdm.volume_id, 'fake-volume-id-1') self.assertEquals(test_bdm.volume_size, 8) def test_driver_snapshot_block_device(self): self._test_driver_device("snapshot") test_bdm = self.driver_classes['snapshot'](self.snapshot_bdm) self.assertEquals(test_bdm.id, 4) self.assertEquals(test_bdm.snapshot_id, 'fake-snapshot-id-1') self.assertEquals(test_bdm.volume_id, 'fake-volume-id-2') self.assertEquals(test_bdm.volume_size, 3) def test_driver_image_block_device(self): self._test_driver_device('image') test_bdm = self.driver_classes['image'](self.image_bdm) self.assertEquals(test_bdm.id, 5) self.assertEquals(test_bdm.image_id, 'fake-image-id-1') self.assertEquals(test_bdm.volume_size, 1) def test_driver_image_block_device_destination_local(self): self._test_driver_device('image') bdm = self.image_bdm.copy() bdm['destination_type'] = 'local' self.assertRaises(driver_block_device._InvalidType, self.driver_classes['image'], bdm) def test_volume_attach(self): test_bdm = self.driver_classes['volume'](self.volume_bdm) elevated_context = self.context.elevated() self.stubs.Set(self.context, 'elevated', lambda: elevated_context) instance = {'id': 'fake_id', 'uuid': 'fake_uuid'} volume = {'id': 'fake-volume-id-1'} connector = {'ip': 'fake_ip', 'host': 'fake_host'} connection_info = {'data': {}} expected_conn_info = {'data': {}, 'serial': 'fake-volume-id-1'} self.volume_api.get(self.context, 'fake-volume-id-1').AndReturn(volume) self.volume_api.check_attach(self.context, volume, instance=instance).AndReturn(None) self.virt_driver.get_volume_connector(instance).AndReturn(connector) self.volume_api.initialize_connection( elevated_context, volume['id'], connector).AndReturn(connection_info) self.volume_api.attach(elevated_context, 'fake-volume-id-1', 'fake_uuid', '/dev/sda1').AndReturn(None) self.db_api.block_device_mapping_update( elevated_context, 3, {'connection_info': jsonutils.dumps(expected_conn_info)}) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, self.db_api) self.assertThat(test_bdm['connection_info'], matchers.DictMatches(expected_conn_info)) def test_refresh_connection(self): test_bdm = self.driver_classes['snapshot'](self.snapshot_bdm) instance = {'id': 'fake_id', 'uuid': 'fake_uuid'} connector = {'ip': 'fake_ip', 'host': 'fake_host'} connection_info = {'data': {}} expected_conn_info = {'data': {}, 'serial': 'fake-volume-id-2'} self.virt_driver.get_volume_connector(instance).AndReturn(connector) self.volume_api.initialize_connection( self.context, test_bdm.volume_id, connector).AndReturn(connection_info) self.db_api.block_device_mapping_update( self.context, 4, {'connection_info': jsonutils.dumps(expected_conn_info)}) self.mox.ReplayAll() test_bdm.refresh_connection_info(self.context, instance, self.volume_api, self.virt_driver, self.db_api) self.assertThat(test_bdm['connection_info'], matchers.DictMatches(expected_conn_info)) def test_snapshot_attach_no_volume(self): no_volume_snapshot = self.snapshot_bdm.copy() no_volume_snapshot['volume_id'] = None test_bdm = self.driver_classes['snapshot'](no_volume_snapshot) instance = {'id': 'fake_id', 'uuid': 'fake_uuid'} snapshot = {'id': 'fake-snapshot-id-1'} volume = {'id': 'fake-volume-id-2'} wait_func = self.mox.CreateMockAnything() volume_class = self.driver_classes['volume'] self.mox.StubOutWithMock(volume_class, 'attach') self.volume_api.get_snapshot(self.context, 'fake-snapshot-id-1').AndReturn(snapshot) self.volume_api.create(self.context, 3, '', '', snapshot).AndReturn(volume) wait_func(self.context, 'fake-volume-id-2').AndReturn(None) self.db_api.block_device_mapping_update(self.context, 4, { 'volume_id': 'fake-volume-id-2' }).AndReturn(None) volume_class.attach(self.context, instance, self.volume_api, self.virt_driver, self.db_api).AndReturn(None) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, self.db_api, wait_func) self.assertEquals(test_bdm.volume_id, 'fake-volume-id-2') def test_snapshot_attach_volume(self): test_bdm = self.driver_classes['snapshot'](self.snapshot_bdm) instance = {'id': 'fake_id', 'uuid': 'fake_uuid'} volume_class = self.driver_classes['volume'] self.mox.StubOutWithMock(volume_class, 'attach') # Make sure theses are not called self.mox.StubOutWithMock(self.volume_api, 'get_snapshot') self.mox.StubOutWithMock(self.volume_api, 'create') self.mox.StubOutWithMock(self.db_api, 'block_device_mapping_update') volume_class.attach(self.context, instance, self.volume_api, self.virt_driver, self.db_api).AndReturn(None) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, self.db_api) self.assertEquals(test_bdm.volume_id, 'fake-volume-id-2') def test_image_attach_no_volume(self): no_volume_image = self.image_bdm.copy() no_volume_image['volume_id'] = None test_bdm = self.driver_classes['image'](no_volume_image) instance = {'id': 'fake_id', 'uuid': 'fake_uuid'} image = {'id': 'fake-image-id-1'} volume = {'id': 'fake-volume-id-2'} wait_func = self.mox.CreateMockAnything() volume_class = self.driver_classes['volume'] self.mox.StubOutWithMock(volume_class, 'attach') self.volume_api.create(self.context, 1, '', '', image_id=image['id']).AndReturn(volume) wait_func(self.context, 'fake-volume-id-2').AndReturn(None) self.db_api.block_device_mapping_update(self.context, 5, { 'volume_id': 'fake-volume-id-2' }).AndReturn(None) volume_class.attach(self.context, instance, self.volume_api, self.virt_driver, self.db_api).AndReturn(None) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, self.db_api, wait_func) self.assertEquals(test_bdm.volume_id, 'fake-volume-id-2') def test_image_attach_volume(self): test_bdm = self.driver_classes['image'](self.image_bdm) instance = {'id': 'fake_id', 'uuid': 'fake_uuid'} volume_class = self.driver_classes['volume'] self.mox.StubOutWithMock(volume_class, 'attach') # Make sure theses are not called self.mox.StubOutWithMock(self.volume_api, 'get_snapshot') self.mox.StubOutWithMock(self.volume_api, 'create') self.mox.StubOutWithMock(self.db_api, 'block_device_mapping_update') volume_class.attach(self.context, instance, self.volume_api, self.virt_driver, self.db_api).AndReturn(None) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, self.db_api) self.assertEquals(test_bdm.volume_id, 'fake-volume-id-2') def test_convert_block_devices(self): converted = driver_block_device._convert_block_devices( self.driver_classes['volume'], [self.volume_bdm, self.ephemeral_bdm]) self.assertEquals(converted, [self.volume_driver_bdm]) def test_legacy_block_devices(self): test_snapshot = self.driver_classes['snapshot'](self.snapshot_bdm) block_device_mapping = [test_snapshot, test_snapshot] legacy_bdm = driver_block_device.legacy_block_devices( block_device_mapping) self.assertEquals( legacy_bdm, [self.snapshot_legacy_driver_bdm, self.snapshot_legacy_driver_bdm]) # Test that the ephemerals work as expected test_ephemerals = [ self.driver_classes['ephemeral'](self.ephemeral_bdm) for _ in xrange(2) ] expected = [self.ephemeral_legacy_driver_bdm.copy() for _ in xrange(2)] expected[0]['virtual_name'] = 'ephemeral0' expected[0]['num'] = 0 expected[1]['virtual_name'] = 'ephemeral1' expected[1]['num'] = 1 legacy_ephemerals = driver_block_device.legacy_block_devices( test_ephemerals) self.assertEquals(expected, legacy_ephemerals) def test_get_swap(self): swap = [self.swap_driver_bdm] legacy_swap = [self.swap_legacy_driver_bdm] no_swap = [self.volume_driver_bdm] self.assertEquals(swap[0], driver_block_device.get_swap(swap)) self.assertEquals(legacy_swap[0], driver_block_device.get_swap(legacy_swap)) self.assertEquals(no_swap, driver_block_device.get_swap(no_swap)) self.assertIsNone(driver_block_device.get_swap([])) def test_is_implemented(self): for bdm in (self.image_bdm, self.volume_bdm, self.swap_bdm, self.ephemeral_bdm, self.snapshot_bdm): self.assertTrue(driver_block_device.is_implemented(bdm)) local_image = self.image_bdm.copy() local_image['destination_type'] = 'local' self.assertFalse(driver_block_device.is_implemented(local_image))
from nova.compute import vm_states import nova.conf from nova import context from nova import objects from nova.objects import block_device as block_device_obj from nova import test from nova.tests.unit import fake_instance from nova.virt import imagecache CONF = nova.conf.CONF swap_bdm_128 = [block_device.BlockDeviceDict( {'id': 1, 'instance_uuid': uuids.instance, 'device_name': '/dev/sdb1', 'source_type': 'blank', 'destination_type': 'local', 'delete_on_termination': True, 'guest_format': 'swap', 'disk_bus': 'scsi', 'volume_size': 128, 'boot_index': -1})] swap_bdm_256 = [block_device.BlockDeviceDict( {'id': 1, 'instance_uuid': uuids.instance, 'device_name': '/dev/sdb1', 'source_type': 'blank', 'destination_type': 'local', 'delete_on_termination': True, 'guest_format': 'swap', 'disk_bus': 'scsi', 'volume_size': 256, 'boot_index': -1})]
class TestDriverBlockDevice(test.NoDBTestCase): driver_classes = { 'swap': driver_block_device.DriverSwapBlockDevice, 'ephemeral': driver_block_device.DriverEphemeralBlockDevice, 'volume': driver_block_device.DriverVolumeBlockDevice, 'snapshot': driver_block_device.DriverSnapshotBlockDevice, 'image': driver_block_device.DriverImageBlockDevice } swap_bdm = block_device.BlockDeviceDict({ 'id': 1, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sdb1', 'source_type': 'blank', 'destination_type': 'local', 'delete_on_termination': True, 'guest_format': 'swap', 'disk_bus': 'scsi', 'volume_size': 2, 'boot_index': -1 }) swap_driver_bdm = { 'device_name': '/dev/sdb1', 'swap_size': 2, 'disk_bus': 'scsi' } swap_legacy_driver_bdm = {'device_name': '/dev/sdb1', 'swap_size': 2} ephemeral_bdm = block_device.BlockDeviceDict({ 'id': 2, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sdc1', 'source_type': 'blank', 'destination_type': 'local', 'disk_bus': 'scsi', 'device_type': 'disk', 'volume_size': 4, 'guest_format': 'ext4', 'delete_on_termination': True, 'boot_index': -1 }) ephemeral_driver_bdm = { 'device_name': '/dev/sdc1', 'size': 4, 'device_type': 'disk', 'guest_format': 'ext4', 'disk_bus': 'scsi' } ephemeral_legacy_driver_bdm = { 'device_name': '/dev/sdc1', 'size': 4, 'virtual_name': 'ephemeral0', 'num': 0 } volume_bdm = block_device.BlockDeviceDict({ 'id': 3, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sda1', 'source_type': 'volume', 'disk_bus': 'scsi', 'device_type': 'disk', 'volume_size': 8, 'destination_type': 'volume', 'volume_id': 'fake-volume-id-1', 'guest_format': 'ext4', 'connection_info': '{"fake": "connection_info"}', 'delete_on_termination': False, 'boot_index': 0 }) volume_driver_bdm = { 'mount_device': '/dev/sda1', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': False, 'disk_bus': 'scsi', 'device_type': 'disk', 'guest_format': 'ext4', 'boot_index': 0 } volume_legacy_driver_bdm = { 'mount_device': '/dev/sda1', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': False } snapshot_bdm = block_device.BlockDeviceDict({ 'id': 4, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sda2', 'delete_on_termination': True, 'volume_size': 3, 'disk_bus': 'scsi', 'device_type': 'disk', 'source_type': 'snapshot', 'destination_type': 'volume', 'connection_info': '{"fake": "connection_info"}', 'snapshot_id': 'fake-snapshot-id-1', 'volume_id': 'fake-volume-id-2', 'boot_index': -1 }) snapshot_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': True, 'disk_bus': 'scsi', 'device_type': 'disk', 'guest_format': None, 'boot_index': -1 } snapshot_legacy_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': True } image_bdm = block_device.BlockDeviceDict({ 'id': 5, 'instance_uuid': 'fake-instance', 'device_name': '/dev/sda2', 'delete_on_termination': True, 'volume_size': 1, 'disk_bus': 'scsi', 'device_type': 'disk', 'source_type': 'image', 'destination_type': 'volume', 'connection_info': '{"fake": "connection_info"}', 'image_id': 'fake-image-id-1', 'volume_id': 'fake-volume-id-2', 'boot_index': -1 }) image_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': True, 'disk_bus': 'scsi', 'device_type': 'disk', 'guest_format': None, 'boot_index': -1 } image_legacy_driver_bdm = { 'mount_device': '/dev/sda2', 'connection_info': { "fake": "connection_info" }, 'delete_on_termination': True } def setUp(self): super(TestDriverBlockDevice, self).setUp() self.volume_api = self.mox.CreateMock(cinder.API) self.virt_driver = self.mox.CreateMock(driver.ComputeDriver) self.context = context.RequestContext('fake_user', 'fake_project') def test_no_device_raises(self): for name, cls in self.driver_classes.items(): self.assertRaises(driver_block_device._NotTransformable, cls, {'no_device': True}) def _test_driver_device(self, name): db_bdm = getattr(self, "%s_bdm" % name) test_bdm = self.driver_classes[name](db_bdm) self.assertThat( test_bdm, matchers.DictMatches(getattr(self, "%s_driver_bdm" % name))) for k, v in db_bdm.iteritems(): field_val = getattr(test_bdm._bdm_obj, k) if isinstance(field_val, bool): v = bool(v) self.assertEqual(field_val, v) self.assertThat( test_bdm.legacy(), matchers.DictMatches(getattr(self, "%s_legacy_driver_bdm" % name))) # Test passthru attributes for passthru in test_bdm._proxy_as_attr: self.assertEqual(getattr(test_bdm, passthru), getattr(test_bdm._bdm_obj, passthru)) for no_pass in set(db_bdm.keys()) - test_bdm._proxy_as_attr: self.assertRaises(AttributeError, getattr, test_bdm, no_pass) # Make sure that all others raise _invalidType for other_name, cls in self.driver_classes.iteritems(): if other_name == name: continue self.assertRaises(driver_block_device._InvalidType, cls, getattr(self, '%s_bdm' % name)) # Test the save method with mock.patch.object(test_bdm._bdm_obj, 'save') as save_mock: test_bdm.save(self.context) for fld, alias in test_bdm._update_on_save.iteritems(): self.assertEqual(test_bdm[alias or fld], getattr(test_bdm._bdm_obj, fld)) save_mock.assert_called_once_with(self.context) def _test_driver_default_size(self, name): size = 'swap_size' if name == 'swap' else 'size' no_size_bdm = getattr(self, "%s_bdm" % name).copy() no_size_bdm['volume_size'] = None driver_bdm = self.driver_classes[name](no_size_bdm) self.assertEqual(driver_bdm[size], 0) del no_size_bdm['volume_size'] driver_bdm = self.driver_classes[name](no_size_bdm) self.assertEqual(driver_bdm[size], 0) def test_driver_swap_block_device(self): self._test_driver_device("swap") def test_driver_swap_default_size(self): self._test_driver_default_size('swap') def test_driver_ephemeral_block_device(self): self._test_driver_device("ephemeral") def test_driver_ephemeral_default_size(self): self._test_driver_default_size('ephemeral') def test_driver_volume_block_device(self): self._test_driver_device("volume") test_bdm = self.driver_classes['volume'](self.volume_bdm) self.assertEqual(test_bdm['connection_info'], jsonutils.loads(test_bdm._bdm_obj.connection_info)) self.assertEqual(test_bdm._bdm_obj.id, 3) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-1') self.assertEqual(test_bdm.volume_size, 8) def test_driver_snapshot_block_device(self): self._test_driver_device("snapshot") test_bdm = self.driver_classes['snapshot'](self.snapshot_bdm) self.assertEqual(test_bdm._bdm_obj.id, 4) self.assertEqual(test_bdm.snapshot_id, 'fake-snapshot-id-1') self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') self.assertEqual(test_bdm.volume_size, 3) def test_driver_image_block_device(self): self._test_driver_device('image') test_bdm = self.driver_classes['image'](self.image_bdm) self.assertEqual(test_bdm._bdm_obj.id, 5) self.assertEqual(test_bdm.image_id, 'fake-image-id-1') self.assertEqual(test_bdm.volume_size, 1) def test_driver_image_block_device_destination_local(self): self._test_driver_device('image') bdm = self.image_bdm.copy() bdm['destination_type'] = 'local' self.assertRaises(driver_block_device._InvalidType, self.driver_classes['image'], bdm) def _test_volume_attach(self, driver_bdm, bdm_dict, fake_volume): elevated_context = self.context.elevated() self.stubs.Set(self.context, 'elevated', lambda: elevated_context) self.mox.StubOutWithMock(driver_bdm._bdm_obj, 'save') instance = {'id': 'fake_id', 'uuid': 'fake_uuid'} connector = {'ip': 'fake_ip', 'host': 'fake_host'} connection_info = {'data': {}} expected_conn_info = {'data': {}, 'serial': fake_volume['id']} self.volume_api.get(self.context, fake_volume['id']).AndReturn(fake_volume) self.volume_api.check_attach(self.context, fake_volume, instance=instance).AndReturn(None) self.virt_driver.get_volume_connector(instance).AndReturn(connector) self.volume_api.initialize_connection( elevated_context, fake_volume['id'], connector).AndReturn(connection_info) self.volume_api.attach(elevated_context, fake_volume['id'], 'fake_uuid', bdm_dict['device_name']).AndReturn(None) driver_bdm._bdm_obj.save(self.context).AndReturn(None) return instance, expected_conn_info def test_volume_attach(self): test_bdm = self.driver_classes['volume'](self.volume_bdm) volume = {'id': 'fake-volume-id-1'} instance, expected_conn_info = self._test_volume_attach( test_bdm, self.volume_bdm, volume) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) self.assertThat(test_bdm['connection_info'], matchers.DictMatches(expected_conn_info)) def test_refresh_connection(self): test_bdm = self.driver_classes['snapshot'](self.snapshot_bdm) instance = {'id': 'fake_id', 'uuid': 'fake_uuid'} connector = {'ip': 'fake_ip', 'host': 'fake_host'} connection_info = {'data': {}} expected_conn_info = {'data': {}, 'serial': 'fake-volume-id-2'} self.mox.StubOutWithMock(test_bdm._bdm_obj, 'save') self.virt_driver.get_volume_connector(instance).AndReturn(connector) self.volume_api.initialize_connection( self.context, test_bdm.volume_id, connector).AndReturn(connection_info) test_bdm._bdm_obj.save(self.context).AndReturn(None) self.mox.ReplayAll() test_bdm.refresh_connection_info(self.context, instance, self.volume_api, self.virt_driver) self.assertThat(test_bdm['connection_info'], matchers.DictMatches(expected_conn_info)) def test_snapshot_attach_no_volume(self): no_volume_snapshot = self.snapshot_bdm.copy() no_volume_snapshot['volume_id'] = None test_bdm = self.driver_classes['snapshot'](no_volume_snapshot) snapshot = {'id': 'fake-snapshot-id-1'} volume = {'id': 'fake-volume-id-2'} wait_func = self.mox.CreateMockAnything() self.volume_api.get_snapshot(self.context, 'fake-snapshot-id-1').AndReturn(snapshot) self.volume_api.create(self.context, 3, '', '', snapshot).AndReturn(volume) wait_func(self.context, 'fake-volume-id-2').AndReturn(None) instance, expected_conn_info = self._test_volume_attach( test_bdm, no_volume_snapshot, volume) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, wait_func) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') def test_snapshot_attach_volume(self): test_bdm = self.driver_classes['snapshot'](self.snapshot_bdm) instance = {'id': 'fake_id', 'uuid': 'fake_uuid'} volume_class = self.driver_classes['volume'] self.mox.StubOutWithMock(volume_class, 'attach') # Make sure theses are not called self.mox.StubOutWithMock(self.volume_api, 'get_snapshot') self.mox.StubOutWithMock(self.volume_api, 'create') volume_class.attach(self.context, instance, self.volume_api, self.virt_driver).AndReturn(None) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') def test_image_attach_no_volume(self): no_volume_image = self.image_bdm.copy() no_volume_image['volume_id'] = None test_bdm = self.driver_classes['image'](no_volume_image) image = {'id': 'fake-image-id-1'} volume = {'id': 'fake-volume-id-2'} wait_func = self.mox.CreateMockAnything() self.volume_api.create(self.context, 1, '', '', image_id=image['id']).AndReturn(volume) wait_func(self.context, 'fake-volume-id-2').AndReturn(None) instance, expected_conn_info = self._test_volume_attach( test_bdm, no_volume_image, volume) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver, wait_func) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') def test_image_attach_volume(self): test_bdm = self.driver_classes['image'](self.image_bdm) instance = {'id': 'fake_id', 'uuid': 'fake_uuid'} volume_class = self.driver_classes['volume'] self.mox.StubOutWithMock(volume_class, 'attach') # Make sure theses are not called self.mox.StubOutWithMock(self.volume_api, 'get_snapshot') self.mox.StubOutWithMock(self.volume_api, 'create') volume_class.attach(self.context, instance, self.volume_api, self.virt_driver).AndReturn(None) self.mox.ReplayAll() test_bdm.attach(self.context, instance, self.volume_api, self.virt_driver) self.assertEqual(test_bdm.volume_id, 'fake-volume-id-2') def test_convert_block_devices(self): converted = driver_block_device._convert_block_devices( self.driver_classes['volume'], [self.volume_bdm, self.ephemeral_bdm]) self.assertEqual(converted, [self.volume_driver_bdm]) def test_legacy_block_devices(self): test_snapshot = self.driver_classes['snapshot'](self.snapshot_bdm) block_device_mapping = [test_snapshot, test_snapshot] legacy_bdm = driver_block_device.legacy_block_devices( block_device_mapping) self.assertEqual( legacy_bdm, [self.snapshot_legacy_driver_bdm, self.snapshot_legacy_driver_bdm]) # Test that the ephemerals work as expected test_ephemerals = [ self.driver_classes['ephemeral'](self.ephemeral_bdm) for _ in xrange(2) ] expected = [self.ephemeral_legacy_driver_bdm.copy() for _ in xrange(2)] expected[0]['virtual_name'] = 'ephemeral0' expected[0]['num'] = 0 expected[1]['virtual_name'] = 'ephemeral1' expected[1]['num'] = 1 legacy_ephemerals = driver_block_device.legacy_block_devices( test_ephemerals) self.assertEqual(expected, legacy_ephemerals) def test_get_swap(self): swap = [self.swap_driver_bdm] legacy_swap = [self.swap_legacy_driver_bdm] no_swap = [self.volume_driver_bdm] self.assertEqual(swap[0], driver_block_device.get_swap(swap)) self.assertEqual(legacy_swap[0], driver_block_device.get_swap(legacy_swap)) self.assertEqual(no_swap, driver_block_device.get_swap(no_swap)) self.assertIsNone(driver_block_device.get_swap([])) def test_is_implemented(self): for bdm in (self.image_bdm, self.volume_bdm, self.swap_bdm, self.ephemeral_bdm, self.snapshot_bdm): self.assertTrue(driver_block_device.is_implemented(bdm)) local_image = self.image_bdm.copy() local_image['destination_type'] = 'local' self.assertFalse(driver_block_device.is_implemented(local_image))