587 lines
25 KiB
Python
587 lines
25 KiB
Python
# Copyright 2013 Red Hat Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import mock
|
|
from oslo_utils.fixture import uuidsentinel as uuids
|
|
|
|
from nova import context
|
|
from nova.db import api as db
|
|
from nova.db.sqlalchemy import api as db_api
|
|
from nova.db.sqlalchemy import models as db_models
|
|
from nova import exception
|
|
from nova import objects
|
|
from nova.objects import block_device as block_device_obj
|
|
from nova import test
|
|
from nova.tests.unit import fake_block_device
|
|
from nova.tests.unit import fake_instance
|
|
from nova.tests.unit.objects import test_objects
|
|
|
|
|
|
class _TestBlockDeviceMappingObject(object):
|
|
def fake_bdm(self, instance=None):
|
|
instance = instance or {}
|
|
fake_bdm = fake_block_device.FakeDbBlockDeviceDict({
|
|
'id': 123,
|
|
'uuid': uuids.bdm,
|
|
'instance_uuid': instance.get('uuid') or uuids.instance,
|
|
'attachment_id': None,
|
|
'device_name': '/dev/sda2',
|
|
'source_type': 'snapshot',
|
|
'destination_type': 'volume',
|
|
'connection_info': "{'fake': 'connection_info'}",
|
|
'snapshot_id': 'fake-snapshot-id-1',
|
|
'boot_index': -1
|
|
})
|
|
if instance:
|
|
fake_bdm['instance'] = instance
|
|
return fake_bdm
|
|
|
|
def test_save(self):
|
|
fake_bdm = self.fake_bdm()
|
|
with mock.patch.object(db, 'block_device_mapping_update',
|
|
return_value=fake_bdm) as bdm_update_mock:
|
|
bdm_object = objects.BlockDeviceMapping(context=self.context)
|
|
bdm_object.id = 123
|
|
bdm_object.volume_id = 'fake_volume_id'
|
|
bdm_object.save()
|
|
|
|
bdm_update_mock.assert_called_once_with(
|
|
self.context, 123, {'volume_id': 'fake_volume_id'},
|
|
legacy=False)
|
|
|
|
def test_save_instance_changed(self):
|
|
bdm_object = objects.BlockDeviceMapping(context=self.context)
|
|
bdm_object.instance = objects.Instance()
|
|
self.assertRaises(exception.ObjectActionError,
|
|
bdm_object.save)
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_update', return_value=None)
|
|
def test_save_not_found(self, bdm_update):
|
|
bdm_object = objects.BlockDeviceMapping(context=self.context)
|
|
bdm_object.id = 123
|
|
self.assertRaises(exception.BDMNotFound, bdm_object.save)
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_volume_id')
|
|
def test_get_by_volume_id(self, get_by_vol_id):
|
|
# NOTE(danms): Include two results to make sure the first was picked.
|
|
# An invalid second item shouldn't be touched -- if it is, it'll
|
|
# fail from_db_object().
|
|
get_by_vol_id.return_value = [self.fake_bdm(),
|
|
None]
|
|
|
|
vol_bdm = objects.BlockDeviceMapping.get_by_volume_id(
|
|
self.context, 'fake-volume-id')
|
|
for attr in block_device_obj.BLOCK_DEVICE_OPTIONAL_ATTRS:
|
|
self.assertFalse(vol_bdm.obj_attr_is_set(attr))
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_volume_id')
|
|
def test_get_by_volume_id_not_found(self, get_by_vol_id):
|
|
get_by_vol_id.return_value = None
|
|
|
|
self.assertRaises(exception.VolumeBDMNotFound,
|
|
objects.BlockDeviceMapping.get_by_volume_id,
|
|
self.context, 'fake-volume-id')
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_volume_id')
|
|
def test_get_by_volume_instance_uuid_mismatch(self, get_by_vol_id):
|
|
fake_bdm_vol = self.fake_bdm(instance={'uuid': 'other-fake-instance'})
|
|
get_by_vol_id.return_value = [fake_bdm_vol]
|
|
|
|
self.assertRaises(exception.InvalidVolume,
|
|
objects.BlockDeviceMapping.get_by_volume_id,
|
|
self.context, 'fake-volume-id',
|
|
instance_uuid='fake-instance')
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_volume_id')
|
|
def test_get_by_volume_id_with_expected(self, get_by_vol_id):
|
|
get_by_vol_id.return_value = [self.fake_bdm(
|
|
fake_instance.fake_db_instance())]
|
|
|
|
vol_bdm = objects.BlockDeviceMapping.get_by_volume_id(
|
|
self.context, 'fake-volume-id', expected_attrs=['instance'])
|
|
for attr in block_device_obj.BLOCK_DEVICE_OPTIONAL_ATTRS:
|
|
self.assertTrue(vol_bdm.obj_attr_is_set(attr))
|
|
get_by_vol_id.assert_called_once_with(self.context, 'fake-volume-id',
|
|
['instance'])
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_volume_id')
|
|
def test_get_by_volume_returned_single(self, get_all):
|
|
fake_bdm_vol = self.fake_bdm()
|
|
get_all.return_value = [fake_bdm_vol]
|
|
vol_bdm = objects.BlockDeviceMapping.get_by_volume(
|
|
self.context, 'fake-volume-id')
|
|
self.assertEqual(fake_bdm_vol['id'], vol_bdm.id)
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_volume_id')
|
|
def test_get_by_volume_returned_multiple(self, get_all):
|
|
fake_bdm_vol1 = self.fake_bdm()
|
|
fake_bdm_vol2 = self.fake_bdm()
|
|
get_all.return_value = [fake_bdm_vol1, fake_bdm_vol2]
|
|
self.assertRaises(exception.VolumeBDMIsMultiAttach,
|
|
objects.BlockDeviceMapping.get_by_volume,
|
|
self.context, 'fake-volume-id')
|
|
|
|
@mock.patch.object(db,
|
|
'block_device_mapping_get_by_instance_and_volume_id')
|
|
def test_get_by_instance_and_volume_id(self, mock_get):
|
|
fake_inst = fake_instance.fake_db_instance()
|
|
mock_get.return_value = self.fake_bdm(fake_inst)
|
|
|
|
obj_bdm = objects.BlockDeviceMapping
|
|
vol_bdm = obj_bdm.get_by_volume_and_instance(
|
|
self.context, 'fake-volume-id', 'fake-instance-id')
|
|
for attr in block_device_obj.BLOCK_DEVICE_OPTIONAL_ATTRS:
|
|
self.assertFalse(vol_bdm.obj_attr_is_set(attr))
|
|
|
|
@mock.patch.object(db,
|
|
'block_device_mapping_get_by_instance_and_volume_id')
|
|
def test_test_get_by_instance_and_volume_id_with_expected(self, mock_get):
|
|
fake_inst = fake_instance.fake_db_instance()
|
|
mock_get.return_value = self.fake_bdm(fake_inst)
|
|
|
|
obj_bdm = objects.BlockDeviceMapping
|
|
vol_bdm = obj_bdm.get_by_volume_and_instance(
|
|
self.context, 'fake-volume-id', fake_inst['uuid'],
|
|
expected_attrs=['instance'])
|
|
for attr in block_device_obj.BLOCK_DEVICE_OPTIONAL_ATTRS:
|
|
self.assertTrue(vol_bdm.obj_attr_is_set(attr))
|
|
mock_get.assert_called_once_with(self.context, 'fake-volume-id',
|
|
fake_inst['uuid'], ['instance'])
|
|
|
|
@mock.patch.object(db,
|
|
'block_device_mapping_get_by_instance_and_volume_id')
|
|
def test_get_by_instance_and_volume_id_not_found(self, mock_get):
|
|
mock_get.return_value = None
|
|
|
|
obj_bdm = objects.BlockDeviceMapping
|
|
self.assertRaises(exception.VolumeBDMNotFound,
|
|
obj_bdm.get_by_volume_and_instance,
|
|
self.context, 'fake-volume-id', 'fake-instance-id')
|
|
|
|
def _test_create_mocked(self, update_or_create=False):
|
|
values = {'source_type': 'volume', 'volume_id': 'fake-vol-id',
|
|
'destination_type': 'volume',
|
|
'instance_uuid': uuids.instance,
|
|
'attachment_id': None}
|
|
fake_bdm = fake_block_device.FakeDbBlockDeviceDict(values)
|
|
|
|
with test.nested(
|
|
mock.patch.object(
|
|
db, 'block_device_mapping_create', return_value=fake_bdm),
|
|
mock.patch.object(
|
|
db, 'block_device_mapping_update_or_create',
|
|
return_value=fake_bdm),
|
|
) as (bdm_create_mock, bdm_update_or_create_mock):
|
|
bdm = objects.BlockDeviceMapping(context=self.context, **values)
|
|
if update_or_create:
|
|
method = bdm.update_or_create
|
|
else:
|
|
method = bdm.create
|
|
|
|
method()
|
|
if update_or_create:
|
|
bdm_update_or_create_mock.assert_called_once_with(
|
|
self.context, values, legacy=False)
|
|
else:
|
|
bdm_create_mock.assert_called_once_with(
|
|
self.context, values, legacy=False)
|
|
|
|
def test_create(self):
|
|
self._test_create_mocked()
|
|
|
|
def test_update_or_create(self):
|
|
self._test_create_mocked(update_or_create=True)
|
|
|
|
def test_create_fails(self):
|
|
values = {'source_type': 'volume', 'volume_id': 'fake-vol-id',
|
|
'destination_type': 'volume',
|
|
'instance_uuid': uuids.instance}
|
|
bdm = objects.BlockDeviceMapping(context=self.context, **values)
|
|
bdm.create()
|
|
|
|
self.assertRaises(exception.ObjectActionError,
|
|
bdm.create)
|
|
|
|
def test_create_fails_instance(self):
|
|
values = {'source_type': 'volume', 'volume_id': 'fake-vol-id',
|
|
'destination_type': 'volume',
|
|
'instance_uuid': uuids.instance,
|
|
'instance': objects.Instance()}
|
|
bdm = objects.BlockDeviceMapping(context=self.context, **values)
|
|
self.assertRaises(exception.ObjectActionError,
|
|
bdm.create)
|
|
|
|
def test_destroy(self):
|
|
values = {'source_type': 'volume', 'volume_id': 'fake-vol-id',
|
|
'destination_type': 'volume', 'id': 1,
|
|
'instance_uuid': uuids.instance, 'device_name': 'fake'}
|
|
with mock.patch.object(db, 'block_device_mapping_destroy') as bdm_del:
|
|
bdm = objects.BlockDeviceMapping(context=self.context, **values)
|
|
bdm.destroy()
|
|
bdm_del.assert_called_once_with(self.context, values['id'])
|
|
|
|
def test_is_image_true(self):
|
|
bdm = objects.BlockDeviceMapping(context=self.context,
|
|
source_type='image')
|
|
self.assertTrue(bdm.is_image)
|
|
|
|
def test_is_image_false(self):
|
|
bdm = objects.BlockDeviceMapping(context=self.context,
|
|
source_type='snapshot')
|
|
self.assertFalse(bdm.is_image)
|
|
|
|
def test_is_volume_true(self):
|
|
bdm = objects.BlockDeviceMapping(context=self.context,
|
|
destination_type='volume')
|
|
self.assertTrue(bdm.is_volume)
|
|
|
|
def test_is_volume_false(self):
|
|
bdm = objects.BlockDeviceMapping(context=self.context,
|
|
destination_type='local')
|
|
self.assertFalse(bdm.is_volume)
|
|
|
|
def test_obj_load_attr_not_instance(self):
|
|
"""Tests that lazy-loading something other than the instance field
|
|
results in an error.
|
|
"""
|
|
bdm = objects.BlockDeviceMapping(self.context, **self.fake_bdm())
|
|
self.assertRaises(exception.ObjectActionError,
|
|
bdm.obj_load_attr, 'invalid')
|
|
|
|
def test_obj_load_attr_orphaned(self):
|
|
"""Tests that lazy-loading the instance field on an orphaned BDM
|
|
results in an error.
|
|
"""
|
|
bdm = objects.BlockDeviceMapping(context=None, **self.fake_bdm())
|
|
self.assertRaises(exception.OrphanedObjectError, bdm.obj_load_attr,
|
|
'instance')
|
|
|
|
@mock.patch.object(objects.Instance, 'get_by_uuid',
|
|
return_value=objects.Instance(uuid=uuids.instance))
|
|
def test_obj_load_attr_instance(self, mock_inst_get_by_uuid):
|
|
"""Tests lazy-loading the instance field."""
|
|
bdm = objects.BlockDeviceMapping(self.context, **self.fake_bdm())
|
|
self.assertEqual(mock_inst_get_by_uuid.return_value, bdm.instance)
|
|
mock_inst_get_by_uuid.assert_called_once_with(
|
|
self.context, bdm.instance_uuid)
|
|
|
|
def test_obj_make_compatible_pre_1_17(self):
|
|
values = {'source_type': 'volume', 'volume_id': 'fake-vol-id',
|
|
'destination_type': 'volume',
|
|
'instance_uuid': uuids.instance, 'tag': 'fake-tag'}
|
|
bdm = objects.BlockDeviceMapping(context=self.context, **values)
|
|
data = lambda x: x['nova_object.data']
|
|
primitive = data(bdm.obj_to_primitive(target_version='1.17'))
|
|
self.assertIn('tag', primitive)
|
|
primitive = data(bdm.obj_to_primitive(target_version='1.16'))
|
|
self.assertNotIn('tag', primitive)
|
|
self.assertIn('volume_id', primitive)
|
|
|
|
def test_obj_make_compatible_pre_1_18(self):
|
|
values = {'source_type': 'volume', 'volume_id': 'fake-vol-id',
|
|
'destination_type': 'volume',
|
|
'instance_uuid': uuids.instance,
|
|
'attachment_id': uuids.attachment_id}
|
|
bdm = objects.BlockDeviceMapping(context=self.context, **values)
|
|
data = lambda x: x['nova_object.data']
|
|
primitive = data(bdm.obj_to_primitive(target_version='1.17'))
|
|
self.assertNotIn('attachment_id', primitive)
|
|
self.assertIn('volume_id', primitive)
|
|
|
|
def test_obj_make_compatible_pre_1_19(self):
|
|
values = {'source_type': 'volume', 'volume_id': 'fake-vol-id',
|
|
'destination_type': 'volume',
|
|
'instance_uuid': uuids.instance, 'uuid': uuids.bdm}
|
|
bdm = objects.BlockDeviceMapping(context=self.context, **values)
|
|
data = lambda x: x['nova_object.data']
|
|
primitive = data(bdm.obj_to_primitive(target_version='1.18'))
|
|
self.assertNotIn('uuid', primitive)
|
|
self.assertIn('volume_id', primitive)
|
|
|
|
def test_obj_make_compatible_pre_1_20(self):
|
|
values = {'source_type': 'volume', 'volume_id': 'fake-vol-id',
|
|
'destination_type': 'volume',
|
|
'instance_uuid': uuids.instance,
|
|
'volume_type': 'fake-lvm-1'}
|
|
bdm = objects.BlockDeviceMapping(context=self.context, **values)
|
|
data = lambda x: x['nova_object.data']
|
|
primitive = data(bdm.obj_to_primitive(target_version='1.19'))
|
|
self.assertNotIn('volume_type', primitive)
|
|
self.assertIn('volume_id', primitive)
|
|
|
|
|
|
class TestBlockDeviceMappingUUIDMigration(test.TestCase):
|
|
def setUp(self):
|
|
super(TestBlockDeviceMappingUUIDMigration, self).setUp()
|
|
self.context = context.RequestContext('fake-user-id',
|
|
'fake-project-id')
|
|
|
|
self.orig_create_uuid = \
|
|
objects.BlockDeviceMapping._create_uuid
|
|
|
|
@staticmethod
|
|
@db_api.pick_context_manager_writer
|
|
def _create_legacy_bdm(context, deleted=False):
|
|
# Create a BDM with no uuid
|
|
values = {'instance_uuid': uuids.instance_uuid}
|
|
bdm_ref = db_models.BlockDeviceMapping()
|
|
bdm_ref.update(values)
|
|
bdm_ref.save(context.session)
|
|
|
|
if deleted:
|
|
bdm_ref.soft_delete(context.session)
|
|
|
|
return bdm_ref
|
|
|
|
@mock.patch.object(objects.BlockDeviceMapping, '_create_uuid')
|
|
def test_populate_uuid(self, mock_create_uuid):
|
|
mock_create_uuid.side_effect = self.orig_create_uuid
|
|
|
|
self._create_legacy_bdm(self.context)
|
|
bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
|
self.context, uuids.instance_uuid)
|
|
|
|
# UUID should have been populated
|
|
uuid = bdms[0].uuid
|
|
self.assertIsNotNone(uuid)
|
|
|
|
bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
|
self.context, uuids.instance_uuid)
|
|
|
|
# UUID should not have changed
|
|
self.assertEqual(uuid, bdms[0].uuid)
|
|
self.assertEqual(1, mock_create_uuid.call_count)
|
|
|
|
def test_create_uuid_race(self):
|
|
# If threads read a legacy BDM object concurrently, we can end up
|
|
# calling _create_uuid multiple times. Assert that calling _create_uuid
|
|
# multiple times yields the same uuid.
|
|
|
|
# NOTE(mdbooth): _create_uuid handles all forms of race, including any
|
|
# amount of overlapping. I have not attempted to write unit tests for
|
|
# all potential execution orders. This test is sufficient to
|
|
# demonstrate that the compare-and-swap works correctly, and we trust
|
|
# the correctness of the database for the rest.
|
|
|
|
db_bdm = self._create_legacy_bdm(self.context)
|
|
uuid1 = objects.BlockDeviceMapping._create_uuid(self.context,
|
|
db_bdm['id'])
|
|
|
|
bdm = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
|
self.context, uuids.instance_uuid)[0]
|
|
self.assertEqual(uuid1, bdm.uuid)
|
|
|
|
# We would only ever call this twice if we raced
|
|
# This is also testing that the compare-and-swap doesn't overwrite an
|
|
# existing uuid if we hit that race.
|
|
uuid2 = objects.BlockDeviceMapping._create_uuid(self.context,
|
|
bdm['id'])
|
|
|
|
self.assertEqual(uuid1, uuid2)
|
|
|
|
def _assert_online_migration(self, expected_total, expected_done,
|
|
limit=10):
|
|
total, done = objects.BlockDeviceMapping.populate_uuids(
|
|
self.context, limit)
|
|
self.assertEqual(expected_total, total)
|
|
self.assertEqual(expected_done, done)
|
|
|
|
def test_online_migration(self):
|
|
self._assert_online_migration(0, 0)
|
|
|
|
# Create 2 BDMs, one with a uuid and one without
|
|
self._create_legacy_bdm(self.context)
|
|
db_api.block_device_mapping_create(self.context,
|
|
{'uuid': uuids.bdm2, 'instance_uuid': uuids.instance_uuid},
|
|
legacy=False)
|
|
|
|
# Run the online migration. We should find 1 and update 1
|
|
self._assert_online_migration(1, 1)
|
|
|
|
# Fetch the BDMs and check we didn't modify the uuid of bdm2
|
|
bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
|
self.context, uuids.instance_uuid)
|
|
bdm_uuids = [bdm.uuid for bdm in bdms]
|
|
self.assertIn(uuids.bdm2, bdm_uuids)
|
|
self.assertNotIn(None, bdm_uuids)
|
|
|
|
# Run the online migration again to see nothing was processed
|
|
self._assert_online_migration(0, 0)
|
|
|
|
# Assert that we assign a uuid to a deleted bdm.
|
|
self._create_legacy_bdm(self.context, deleted=True)
|
|
self._assert_online_migration(1, 1)
|
|
|
|
# Test that we don't migrate more than the limit
|
|
for i in range(0, 3):
|
|
self._create_legacy_bdm(self.context)
|
|
self._assert_online_migration(2, 2, limit=2)
|
|
|
|
|
|
class TestBlockDeviceMappingObject(test_objects._LocalTest,
|
|
_TestBlockDeviceMappingObject):
|
|
pass
|
|
|
|
|
|
class TestRemoteBlockDeviceMappingObject(test_objects._RemoteTest,
|
|
_TestBlockDeviceMappingObject):
|
|
pass
|
|
|
|
|
|
class _TestBlockDeviceMappingListObject(object):
|
|
def fake_bdm(self, bdm_id, boot_index=-1, instance_uuid=uuids.instance):
|
|
fake_bdm = fake_block_device.FakeDbBlockDeviceDict({
|
|
'id': bdm_id,
|
|
'boot_index': boot_index,
|
|
'instance_uuid': instance_uuid,
|
|
'attachment_id': None,
|
|
'device_name': '/dev/sda2',
|
|
'source_type': 'snapshot',
|
|
'destination_type': 'volume',
|
|
'connection_info': "{'fake': 'connection_info'}",
|
|
'snapshot_id': 'fake-snapshot-id-1',
|
|
})
|
|
return fake_bdm
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_instance_uuids')
|
|
def test_bdms_by_instance_uuid(self, get_all_by_inst_uuids):
|
|
fakes = [self.fake_bdm(123), self.fake_bdm(456)]
|
|
get_all_by_inst_uuids.return_value = fakes
|
|
bdms_by_uuid = objects.BlockDeviceMappingList.bdms_by_instance_uuid(
|
|
self.context, [uuids.instance])
|
|
self.assertEqual([uuids.instance], list(bdms_by_uuid.keys()))
|
|
self.assertIsInstance(
|
|
bdms_by_uuid[uuids.instance], objects.BlockDeviceMappingList)
|
|
for faked, got in zip(fakes, bdms_by_uuid[uuids.instance]):
|
|
self.assertIsInstance(got, objects.BlockDeviceMapping)
|
|
self.assertEqual(faked['id'], got.id)
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_instance_uuids')
|
|
def test_bdms_by_instance_uuid_no_result(self, get_all_by_inst_uuids):
|
|
get_all_by_inst_uuids.return_value = None
|
|
bdms_by_uuid = objects.BlockDeviceMappingList.bdms_by_instance_uuid(
|
|
self.context, [uuids.instance])
|
|
self.assertEqual({}, bdms_by_uuid)
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_instance_uuids')
|
|
def test_get_by_instance_uuids(self, get_all_by_inst_uuids):
|
|
fakes = [self.fake_bdm(123), self.fake_bdm(456)]
|
|
get_all_by_inst_uuids.return_value = fakes
|
|
bdm_list = objects.BlockDeviceMappingList.get_by_instance_uuids(
|
|
self.context, [uuids.instance])
|
|
for faked, got in zip(fakes, bdm_list):
|
|
self.assertIsInstance(got, objects.BlockDeviceMapping)
|
|
self.assertEqual(faked['id'], got.id)
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_instance_uuids')
|
|
def test_get_by_instance_uuids_no_result(self, get_all_by_inst_uuids):
|
|
get_all_by_inst_uuids.return_value = None
|
|
bdm_list = objects.BlockDeviceMappingList.get_by_instance_uuids(
|
|
self.context, [uuids.instance])
|
|
self.assertEqual(0, len(bdm_list))
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_instance')
|
|
def test_get_by_instance_uuid(self, get_all_by_inst):
|
|
fakes = [self.fake_bdm(123), self.fake_bdm(456)]
|
|
get_all_by_inst.return_value = fakes
|
|
bdm_list = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
|
self.context, uuids.instance)
|
|
for faked, got in zip(fakes, bdm_list):
|
|
self.assertIsInstance(got, objects.BlockDeviceMapping)
|
|
self.assertEqual(faked['id'], got.id)
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_instance')
|
|
def test_get_by_instance_uuid_no_result(self, get_all_by_inst):
|
|
get_all_by_inst.return_value = None
|
|
bdm_list = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
|
self.context, uuids.instance)
|
|
self.assertEqual(0, len(bdm_list))
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_instance')
|
|
def test_root_bdm(self, get_all_by_inst):
|
|
fakes = [self.fake_bdm(123), self.fake_bdm(456, boot_index=0)]
|
|
get_all_by_inst.return_value = fakes
|
|
bdm_list = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
|
self.context, uuids.instance)
|
|
self.assertEqual(456, bdm_list.root_bdm().id)
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_instance')
|
|
def test_root_bdm_empty_bdm_list(self, get_all_by_inst):
|
|
get_all_by_inst.return_value = None
|
|
bdm_list = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
|
self.context, uuids.instance)
|
|
self.assertIsNone(bdm_list.root_bdm())
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_instance')
|
|
def test_root_bdm_undefined(self, get_all_by_inst):
|
|
fakes = [
|
|
self.fake_bdm(123, instance_uuid=uuids.instance_1),
|
|
self.fake_bdm(456, instance_uuid=uuids.instance_2)
|
|
]
|
|
get_all_by_inst.return_value = fakes
|
|
bdm_list = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
|
self.context, uuids.bdm_instance)
|
|
self.assertRaises(exception.UndefinedRootBDM, bdm_list.root_bdm)
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_volume_id')
|
|
def test_get_by_volume(self, get_all_by_volume_id):
|
|
fakes = [
|
|
self.fake_bdm(123, instance_uuid=uuids.instance_1),
|
|
self.fake_bdm(456, instance_uuid=uuids.instance_2),
|
|
]
|
|
get_all_by_volume_id.return_value = fakes
|
|
bdm_list = objects.BlockDeviceMappingList.get_by_volume(
|
|
self.context, uuids.volume_id)
|
|
for faked, res in zip(fakes, bdm_list):
|
|
self.assertIsInstance(res, objects.BlockDeviceMapping)
|
|
self.assertEqual(faked['id'], res.id)
|
|
|
|
@mock.patch.object(db, 'block_device_mapping_get_all_by_volume_id',
|
|
new=mock.Mock(return_value=None))
|
|
def test_get_by_volume_no_result(self):
|
|
self.assertRaises(
|
|
exception.VolumeBDMNotFound,
|
|
objects.BlockDeviceMappingList.get_by_volume,
|
|
self.context,
|
|
uuids.volume_id,
|
|
)
|
|
|
|
|
|
class TestBlockDeviceMappingListObject(test_objects._LocalTest,
|
|
_TestBlockDeviceMappingListObject):
|
|
pass
|
|
|
|
|
|
class TestRemoteBlockDeviceMappingListObject(
|
|
test_objects._RemoteTest, _TestBlockDeviceMappingListObject):
|
|
pass
|
|
|
|
|
|
class TestBlockDeviceUtils(test.NoDBTestCase):
|
|
def test_make_list_from_dicts(self):
|
|
ctx = context.get_admin_context()
|
|
dicts = [{'id': 1}, {'id': 2}]
|
|
objs = block_device_obj.block_device_make_list_from_dicts(ctx,
|
|
dicts)
|
|
self.assertIsInstance(objs, block_device_obj.BlockDeviceMappingList)
|
|
self.assertEqual(2, len(objs))
|
|
self.assertEqual(1, objs[0].id)
|
|
self.assertEqual(2, objs[1].id)
|
|
|
|
def test_make_list_from_dicts_empty(self):
|
|
ctx = context.get_admin_context()
|
|
objs = block_device_obj.block_device_make_list_from_dicts(ctx, [])
|
|
self.assertIsInstance(objs, block_device_obj.BlockDeviceMappingList)
|
|
self.assertEqual(0, len(objs))
|