Replace N block_device_mapping queries with 1
The ExtendedVolumes post-processing extension used to do N block_device_mapping queries (one query per instance in a 'nova list'). Instead, do one block_device_mapping query with an IN clause of instance UUIDs. Change-Id: I32a1bd0e05a7a938e531d00bedfab23a0bb68538 Partial-Bug: #1416132 Closes-Bug: #1359808
This commit is contained in:
parent
3be51f19ae
commit
110bb30d0f
|
@ -27,9 +27,7 @@ class ExtendedVolumesController(wsgi.Controller):
|
|||
super(ExtendedVolumesController, self).__init__(*args, **kwargs)
|
||||
self.api_version_2_3 = api_version_request.APIVersionRequest('2.3')
|
||||
|
||||
def _extend_server(self, context, server, instance, requested_version):
|
||||
bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
||||
context, instance.uuid)
|
||||
def _extend_server(self, context, server, requested_version, bdms):
|
||||
volumes_attached = []
|
||||
for bdm in bdms:
|
||||
if bdm.get('volume_id'):
|
||||
|
@ -44,25 +42,33 @@ class ExtendedVolumesController(wsgi.Controller):
|
|||
@wsgi.extends
|
||||
def show(self, req, resp_obj, id):
|
||||
context = req.environ['nova.context']
|
||||
version = req.api_version_request
|
||||
if soft_authorize(context):
|
||||
server = resp_obj.obj['server']
|
||||
db_instance = req.get_db_instance(server['id'])
|
||||
# server['id'] is guaranteed to be in the cache due to
|
||||
# the core API adding it in its 'show' method.
|
||||
self._extend_server(context, server, db_instance,
|
||||
req.api_version_request)
|
||||
bdms = objects.BlockDeviceMappingList.bdms_by_instance_uuid(
|
||||
context, [server['id']])
|
||||
instance_bdms = self._get_instance_bdms(bdms, server)
|
||||
self._extend_server(context, server, version, instance_bdms)
|
||||
|
||||
@wsgi.extends
|
||||
def detail(self, req, resp_obj):
|
||||
context = req.environ['nova.context']
|
||||
version = req.api_version_request
|
||||
if soft_authorize(context):
|
||||
servers = list(resp_obj.obj['servers'])
|
||||
instance_uuids = [server['id'] for server in servers]
|
||||
bdms = objects.BlockDeviceMappingList.bdms_by_instance_uuid(
|
||||
context, instance_uuids)
|
||||
for server in servers:
|
||||
db_instance = req.get_db_instance(server['id'])
|
||||
# server['id'] is guaranteed to be in the cache due to
|
||||
# the core API adding it in its 'detail' method.
|
||||
self._extend_server(context, server, db_instance,
|
||||
req.api_version_request)
|
||||
instance_bdms = self._get_instance_bdms(bdms, server)
|
||||
self._extend_server(context, server, version, instance_bdms)
|
||||
|
||||
def _get_instance_bdms(self, bdms, server):
|
||||
# server['id'] is guaranteed to be in the cache due to
|
||||
# the core API adding it in the 'detail' or 'show' method.
|
||||
# If that instance has since been deleted, it won't be in the
|
||||
# 'bdms' dictionary though, so use 'get' to avoid KeyErrors.
|
||||
return bdms.get(server['id'], [])
|
||||
|
||||
|
||||
class ExtendedVolumes(extensions.V21APIExtensionBase):
|
||||
|
|
|
@ -25,9 +25,7 @@ class ExtendedVolumesController(wsgi.Controller):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super(ExtendedVolumesController, self).__init__(*args, **kwargs)
|
||||
|
||||
def _extend_server(self, context, server, instance):
|
||||
bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
||||
context, instance.uuid)
|
||||
def _extend_server(self, context, server, bdms):
|
||||
volume_ids = [bdm.volume_id for bdm in bdms if bdm.volume_id]
|
||||
key = "%s:volumes_attached" % Extended_volumes.alias
|
||||
server[key] = [{'id': volume_id} for volume_id in volume_ids]
|
||||
|
@ -37,21 +35,29 @@ class ExtendedVolumesController(wsgi.Controller):
|
|||
context = req.environ['nova.context']
|
||||
if authorize(context):
|
||||
server = resp_obj.obj['server']
|
||||
db_instance = req.get_db_instance(server['id'])
|
||||
# server['id'] is guaranteed to be in the cache due to
|
||||
# the core API adding it in its 'show' method.
|
||||
self._extend_server(context, server, db_instance)
|
||||
bdms = objects.BlockDeviceMappingList.bdms_by_instance_uuid(
|
||||
context, [server['id']])
|
||||
instance_bdms = self._get_instance_bdms(bdms, server)
|
||||
self._extend_server(context, server, instance_bdms)
|
||||
|
||||
@wsgi.extends
|
||||
def detail(self, req, resp_obj):
|
||||
context = req.environ['nova.context']
|
||||
if authorize(context):
|
||||
servers = list(resp_obj.obj['servers'])
|
||||
instance_uuids = [server['id'] for server in servers]
|
||||
bdms = objects.BlockDeviceMappingList.bdms_by_instance_uuid(
|
||||
context, instance_uuids)
|
||||
for server in servers:
|
||||
db_instance = req.get_db_instance(server['id'])
|
||||
# server['id'] is guaranteed to be in the cache due to
|
||||
# the core API adding it in its 'detail' method.
|
||||
self._extend_server(context, server, db_instance)
|
||||
instance_bdms = self._get_instance_bdms(bdms, server)
|
||||
self._extend_server(context, server, instance_bdms)
|
||||
|
||||
def _get_instance_bdms(self, bdms, server):
|
||||
# server['id'] is guaranteed to be in the cache due to
|
||||
# the core API adding it in the 'detail' or 'show' method.
|
||||
# If that instance has since been deleted, it won't be in the
|
||||
# 'bdms' dictionary though, so use 'get' to avoid KeyErrors.
|
||||
return bdms.get(server['id'], [])
|
||||
|
||||
|
||||
class Extended_volumes(extensions.ExtensionDescriptor):
|
||||
|
|
|
@ -1197,6 +1197,14 @@ def block_device_mapping_update_or_create(context, values, legacy=True):
|
|||
return IMPL.block_device_mapping_update_or_create(context, values, legacy)
|
||||
|
||||
|
||||
def block_device_mapping_get_all_by_instance_uuids(context, instance_uuids,
|
||||
use_slave=False):
|
||||
"""Get all block device mapping belonging to a list of instances."""
|
||||
return IMPL.block_device_mapping_get_all_by_instance_uuids(context,
|
||||
instance_uuids,
|
||||
use_slave)
|
||||
|
||||
|
||||
def block_device_mapping_get_all_by_instance(context, instance_uuid,
|
||||
use_slave=False):
|
||||
"""Get all block device mapping belonging to an instance."""
|
||||
|
|
|
@ -3962,6 +3962,18 @@ def block_device_mapping_update_or_create(context, values, legacy=True):
|
|||
return result
|
||||
|
||||
|
||||
@require_context
|
||||
def block_device_mapping_get_all_by_instance_uuids(context, instance_uuids,
|
||||
use_slave=False):
|
||||
if not instance_uuids:
|
||||
return []
|
||||
return _block_device_mapping_get_query(
|
||||
context, use_slave=use_slave
|
||||
).filter(
|
||||
models.BlockDeviceMapping.instance_uuid.in_(instance_uuids)
|
||||
).all()
|
||||
|
||||
|
||||
@require_context
|
||||
def block_device_mapping_get_all_by_instance(context, instance_uuid,
|
||||
use_slave=False):
|
||||
|
|
|
@ -597,6 +597,11 @@ class VolumeNotFound(NotFound):
|
|||
msg_fmt = _("Volume %(volume_id)s could not be found.")
|
||||
|
||||
|
||||
class UndefinedRootBDM(NovaException):
|
||||
msg_fmt = _("Undefined Block Device Mapping root: BlockDeviceMappingList "
|
||||
"contains Block Device Mappings from multiple instances.")
|
||||
|
||||
|
||||
class BDMNotFound(NotFound):
|
||||
msg_fmt = _("No Block Device Mapping with id %(id)s.")
|
||||
|
||||
|
|
|
@ -308,6 +308,28 @@ def obj_to_primitive(obj):
|
|||
return obj
|
||||
|
||||
|
||||
def obj_make_dict_of_lists(context, list_cls, obj_list, item_key):
|
||||
"""Construct a dictionary of object lists, keyed by item_key.
|
||||
|
||||
:param:context: Request context
|
||||
:param:list_cls: The ObjectListBase class
|
||||
:param:obj_list: The list of objects to place in the dictionary
|
||||
:param:item_key: The object attribute name to use as a dictionary key
|
||||
"""
|
||||
|
||||
obj_lists = {}
|
||||
for obj in obj_list:
|
||||
key = getattr(obj, item_key)
|
||||
if key not in obj_lists:
|
||||
obj_lists[key] = list_cls()
|
||||
obj_lists[key].objects = []
|
||||
obj_lists[key].objects.append(obj)
|
||||
for key in obj_lists:
|
||||
obj_lists[key]._context = context
|
||||
obj_lists[key].obj_reset_changes()
|
||||
return obj_lists
|
||||
|
||||
|
||||
def obj_make_list(context, list_obj, item_cls, db_list, **extra_args):
|
||||
"""Construct an object list from a list of primitives.
|
||||
|
||||
|
|
|
@ -267,12 +267,33 @@ class BlockDeviceMappingList(base.ObjectListBase, base.NovaObject):
|
|||
# Version 1.14: BlockDeviceMapping <= version 1.13
|
||||
# Version 1.15: BlockDeviceMapping <= version 1.14
|
||||
# Version 1.16: BlockDeviceMapping <= version 1.15
|
||||
VERSION = '1.16'
|
||||
# Version 1.17: Add get_by_instance_uuids()
|
||||
VERSION = '1.17'
|
||||
|
||||
fields = {
|
||||
'objects': fields.ListOfObjectsField('BlockDeviceMapping'),
|
||||
}
|
||||
|
||||
@property
|
||||
def instance_uuids(self):
|
||||
return set(
|
||||
bdm.instance_uuid for bdm in self
|
||||
if bdm.obj_attr_is_set('instance_uuid')
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def bdms_by_instance_uuid(cls, context, instance_uuids):
|
||||
bdms = cls.get_by_instance_uuids(context, instance_uuids)
|
||||
return base.obj_make_dict_of_lists(
|
||||
context, cls, bdms, 'instance_uuid')
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_by_instance_uuids(cls, context, instance_uuids, use_slave=False):
|
||||
db_bdms = db.block_device_mapping_get_all_by_instance_uuids(
|
||||
context, instance_uuids, use_slave=use_slave)
|
||||
return base.obj_make_list(
|
||||
context, cls(), objects.BlockDeviceMapping, db_bdms or [])
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_by_instance_uuid(cls, context, instance_uuid, use_slave=False):
|
||||
db_bdms = db.block_device_mapping_get_all_by_instance(
|
||||
|
@ -281,6 +302,19 @@ class BlockDeviceMappingList(base.ObjectListBase, base.NovaObject):
|
|||
context, cls(), objects.BlockDeviceMapping, db_bdms or [])
|
||||
|
||||
def root_bdm(self):
|
||||
"""It only makes sense to call this method when the
|
||||
BlockDeviceMappingList contains BlockDeviceMappings from
|
||||
exactly one instance rather than BlockDeviceMappings from
|
||||
multiple instances.
|
||||
|
||||
For example, you should not call this method from a
|
||||
BlockDeviceMappingList created by get_by_instance_uuids(),
|
||||
but you may call this method from a BlockDeviceMappingList
|
||||
created by get_by_instance_uuid().
|
||||
"""
|
||||
|
||||
if len(self.instance_uuids) > 1:
|
||||
raise exception.UndefinedRootBDM()
|
||||
try:
|
||||
return next(bdm_obj for bdm_obj in self if bdm_obj.is_root)
|
||||
except StopIteration:
|
||||
|
|
|
@ -46,8 +46,8 @@ class ExtendedVolumesSampleJsonTests(test_servers.ServersSampleBase):
|
|||
|
||||
def test_show(self):
|
||||
uuid = self._post_server()
|
||||
self.stubs.Set(db, 'block_device_mapping_get_all_by_instance',
|
||||
fakes.stub_bdm_get_all_by_instance)
|
||||
self.stubs.Set(db, 'block_device_mapping_get_all_by_instance_uuids',
|
||||
fakes.stub_bdm_get_all_by_instance_uuids)
|
||||
response = self._do_get('servers/%s' % uuid)
|
||||
subs = self._get_regexes()
|
||||
subs['hostid'] = '[a-f0-9]+'
|
||||
|
@ -57,8 +57,8 @@ class ExtendedVolumesSampleJsonTests(test_servers.ServersSampleBase):
|
|||
|
||||
def test_detail(self):
|
||||
uuid = self._post_server()
|
||||
self.stubs.Set(db, 'block_device_mapping_get_all_by_instance',
|
||||
fakes.stub_bdm_get_all_by_instance)
|
||||
self.stubs.Set(db, 'block_device_mapping_get_all_by_instance_uuids',
|
||||
fakes.stub_bdm_get_all_by_instance_uuids)
|
||||
response = self._do_get('servers/detail')
|
||||
subs = self._get_regexes()
|
||||
subs['id'] = uuid
|
||||
|
|
|
@ -41,22 +41,43 @@ def fake_compute_get(*args, **kwargs):
|
|||
|
||||
|
||||
def fake_compute_get_all(*args, **kwargs):
|
||||
db_list = [fakes.stub_instance(1), fakes.stub_instance(2)]
|
||||
db_list = [
|
||||
fakes.stub_instance(1, uuid=UUID1),
|
||||
fakes.stub_instance(2, uuid=UUID2),
|
||||
]
|
||||
fields = instance_obj.INSTANCE_DEFAULT_FIELDS
|
||||
return instance_obj._make_instance_list(args[1],
|
||||
objects.InstanceList(),
|
||||
db_list, fields)
|
||||
|
||||
|
||||
def fake_bdms_get_all_by_instance(*args, **kwargs):
|
||||
return [fake_block_device.FakeDbBlockDeviceDict(
|
||||
{'volume_id': UUID1, 'source_type': 'volume',
|
||||
'destination_type': 'volume', 'id': 1,
|
||||
'delete_on_termination': True}),
|
||||
fake_block_device.FakeDbBlockDeviceDict(
|
||||
{'volume_id': UUID2, 'source_type': 'volume',
|
||||
'destination_type': 'volume', 'id': 2,
|
||||
'delete_on_termination': False})]
|
||||
def fake_bdms_get_all_by_instance_uuids(*args, **kwargs):
|
||||
return [
|
||||
fake_block_device.FakeDbBlockDeviceDict({
|
||||
'id': 1,
|
||||
'volume_id': 'some_volume_1',
|
||||
'instance_uuid': UUID1,
|
||||
'source_type': 'volume',
|
||||
'destination_type': 'volume',
|
||||
'delete_on_termination': True,
|
||||
}),
|
||||
fake_block_device.FakeDbBlockDeviceDict({
|
||||
'id': 2,
|
||||
'volume_id': 'some_volume_2',
|
||||
'instance_uuid': UUID2,
|
||||
'source_type': 'volume',
|
||||
'destination_type': 'volume',
|
||||
'delete_on_termination': False,
|
||||
}),
|
||||
fake_block_device.FakeDbBlockDeviceDict({
|
||||
'id': 3,
|
||||
'volume_id': 'some_volume_3',
|
||||
'instance_uuid': UUID2,
|
||||
'source_type': 'volume',
|
||||
'destination_type': 'volume',
|
||||
'delete_on_termination': False,
|
||||
}),
|
||||
]
|
||||
|
||||
|
||||
def fake_volume_get(*args, **kwargs):
|
||||
|
@ -66,7 +87,11 @@ def fake_volume_get(*args, **kwargs):
|
|||
class ExtendedVolumesTestV21(test.TestCase):
|
||||
content_type = 'application/json'
|
||||
prefix = 'os-extended-volumes:'
|
||||
exp_volumes = [{'id': UUID1}, {'id': UUID2}]
|
||||
exp_volumes_show = [{'id': 'some_volume_1'}]
|
||||
exp_volumes_detail = [
|
||||
[{'id': 'some_volume_1'}],
|
||||
[{'id': 'some_volume_2'}, {'id': 'some_volume_3'}],
|
||||
]
|
||||
wsgi_api_version = os_wsgi.DEFAULT_API_VERSION
|
||||
|
||||
def setUp(self):
|
||||
|
@ -74,8 +99,8 @@ class ExtendedVolumesTestV21(test.TestCase):
|
|||
fakes.stub_out_nw_api(self.stubs)
|
||||
self.stubs.Set(compute.api.API, 'get', fake_compute_get)
|
||||
self.stubs.Set(compute.api.API, 'get_all', fake_compute_get_all)
|
||||
self.stubs.Set(db, 'block_device_mapping_get_all_by_instance',
|
||||
fake_bdms_get_all_by_instance)
|
||||
self.stubs.Set(db, 'block_device_mapping_get_all_by_instance_uuids',
|
||||
fake_bdms_get_all_by_instance_uuids)
|
||||
self._setUp()
|
||||
self.app = self._setup_app()
|
||||
return_server = fakes.fake_instance_get()
|
||||
|
@ -113,7 +138,7 @@ class ExtendedVolumesTestV21(test.TestCase):
|
|||
self.assertEqual(200, res.status_int)
|
||||
server = self._get_server(res.body)
|
||||
actual = server.get('%svolumes_attached' % self.prefix)
|
||||
self.assertEqual(self.exp_volumes, actual)
|
||||
self.assertEqual(self.exp_volumes_show, actual)
|
||||
|
||||
def test_detail(self):
|
||||
res = self._make_request('/detail')
|
||||
|
@ -121,7 +146,7 @@ class ExtendedVolumesTestV21(test.TestCase):
|
|||
self.assertEqual(200, res.status_int)
|
||||
for i, server in enumerate(self._get_servers(res.body)):
|
||||
actual = server.get('%svolumes_attached' % self.prefix)
|
||||
self.assertEqual(self.exp_volumes, actual)
|
||||
self.assertEqual(self.exp_volumes_detail[i], actual)
|
||||
|
||||
|
||||
class ExtendedVolumesTestV2(ExtendedVolumesTestV21):
|
||||
|
@ -138,8 +163,18 @@ class ExtendedVolumesTestV2(ExtendedVolumesTestV21):
|
|||
|
||||
class ExtendedVolumesTestV23(ExtendedVolumesTestV21):
|
||||
|
||||
exp_volumes = [{'id': UUID1, 'delete_on_termination': True},
|
||||
{'id': UUID2, 'delete_on_termination': False}]
|
||||
exp_volumes_show = [
|
||||
{'id': 'some_volume_1', 'delete_on_termination': True},
|
||||
]
|
||||
exp_volumes_detail = [
|
||||
[
|
||||
{'id': 'some_volume_1', 'delete_on_termination': True},
|
||||
],
|
||||
[
|
||||
{'id': 'some_volume_2', 'delete_on_termination': False},
|
||||
{'id': 'some_volume_3', 'delete_on_termination': False},
|
||||
],
|
||||
]
|
||||
wsgi_api_version = '2.3'
|
||||
|
||||
|
||||
|
|
|
@ -682,13 +682,21 @@ def stub_snapshot_get_all(self, context):
|
|||
stub_snapshot(102, project_id='superduperfake')]
|
||||
|
||||
|
||||
def stub_bdm_get_all_by_instance(context, instance_uuid, use_slave=False):
|
||||
return [fake_block_device.FakeDbBlockDeviceDict(
|
||||
{'id': 1, 'source_type': 'volume', 'destination_type': 'volume',
|
||||
'volume_id': 'volume_id1', 'instance_uuid': instance_uuid}),
|
||||
fake_block_device.FakeDbBlockDeviceDict(
|
||||
{'id': 2, 'source_type': 'volume', 'destination_type': 'volume',
|
||||
'volume_id': 'volume_id2', 'instance_uuid': instance_uuid})]
|
||||
def stub_bdm_get_all_by_instance_uuids(context, instance_uuids,
|
||||
use_slave=False):
|
||||
i = 1
|
||||
result = []
|
||||
for instance_uuid in instance_uuids:
|
||||
for x in range(2): # add two BDMs per instance
|
||||
result.append(fake_block_device.FakeDbBlockDeviceDict({
|
||||
'id': i,
|
||||
'source_type': 'volume',
|
||||
'destination_type': 'volume',
|
||||
'volume_id': 'volume_id%d' % (i),
|
||||
'instance_uuid': instance_uuid,
|
||||
}))
|
||||
i += 1
|
||||
return result
|
||||
|
||||
|
||||
def fake_get_available_languages():
|
||||
|
|
|
@ -8947,6 +8947,7 @@ class ComputeAPITestCase(BaseTestCase):
|
|||
{'source_type': 'volume',
|
||||
'device_name': '/dev/vda',
|
||||
'volume_id': 'fake_volume_id',
|
||||
'instance_uuid': 'some_instance_uuid',
|
||||
'boot_index': 0,
|
||||
'destination_type': 'volume'})])
|
||||
self.assertTrue(
|
||||
|
@ -8958,11 +8959,13 @@ class ComputeAPITestCase(BaseTestCase):
|
|||
'device_name': '/dev/vda',
|
||||
'volume_id': 'fake_volume_id',
|
||||
'destination_type': 'local',
|
||||
'instance_uuid': 'some_instance_uuid',
|
||||
'boot_index': 0,
|
||||
'snapshot_id': None}),
|
||||
fake_block_device.FakeDbBlockDeviceDict(
|
||||
{'source_type': 'volume',
|
||||
'device_name': '/dev/vdb',
|
||||
'instance_uuid': 'some_instance_uuid',
|
||||
'boot_index': 1,
|
||||
'destination_type': 'volume',
|
||||
'volume_id': 'c2ec2156-d75e-11e2-985b-5254009297d6',
|
||||
|
@ -8975,6 +8978,7 @@ class ComputeAPITestCase(BaseTestCase):
|
|||
{'source_type': 'volume',
|
||||
'device_name': '/dev/vda',
|
||||
'snapshot_id': 'de8836ac-d75e-11e2-8271-5254009297d6',
|
||||
'instance_uuid': 'some_instance_uuid',
|
||||
'destination_type': 'volume',
|
||||
'boot_index': 0,
|
||||
'volume_id': None})])
|
||||
|
|
|
@ -5975,26 +5975,52 @@ class BlockDeviceMappingTestCase(test.TestCase):
|
|||
self.assertEqual(bdm_real['guest_format'], 'swap')
|
||||
db.block_device_mapping_destroy(self.ctxt, bdm_real['id'])
|
||||
|
||||
def test_block_device_mapping_get_all_by_instance(self):
|
||||
def test_block_device_mapping_get_all_by_instance_uuids(self):
|
||||
uuid1 = self.instance['uuid']
|
||||
uuid2 = db.instance_create(self.ctxt, {})['uuid']
|
||||
|
||||
bmds_values = [{'instance_uuid': uuid1,
|
||||
bdms_values = [{'instance_uuid': uuid1,
|
||||
'device_name': '/dev/vda'},
|
||||
{'instance_uuid': uuid2,
|
||||
'device_name': '/dev/vdb'},
|
||||
{'instance_uuid': uuid2,
|
||||
'device_name': '/dev/vdc'}]
|
||||
|
||||
for bdm in bmds_values:
|
||||
for bdm in bdms_values:
|
||||
self._create_bdm(bdm)
|
||||
|
||||
bmd = db.block_device_mapping_get_all_by_instance(self.ctxt, uuid1)
|
||||
self.assertEqual(len(bmd), 1)
|
||||
self.assertEqual(bmd[0]['device_name'], '/dev/vda')
|
||||
bdms = db.block_device_mapping_get_all_by_instance_uuids(
|
||||
self.ctxt, [])
|
||||
self.assertEqual(len(bdms), 0)
|
||||
|
||||
bmd = db.block_device_mapping_get_all_by_instance(self.ctxt, uuid2)
|
||||
self.assertEqual(len(bmd), 2)
|
||||
bdms = db.block_device_mapping_get_all_by_instance_uuids(
|
||||
self.ctxt, [uuid2])
|
||||
self.assertEqual(len(bdms), 2)
|
||||
|
||||
bdms = db.block_device_mapping_get_all_by_instance_uuids(
|
||||
self.ctxt, [uuid1, uuid2])
|
||||
self.assertEqual(len(bdms), 3)
|
||||
|
||||
def test_block_device_mapping_get_all_by_instance(self):
|
||||
uuid1 = self.instance['uuid']
|
||||
uuid2 = db.instance_create(self.ctxt, {})['uuid']
|
||||
|
||||
bdms_values = [{'instance_uuid': uuid1,
|
||||
'device_name': '/dev/vda'},
|
||||
{'instance_uuid': uuid2,
|
||||
'device_name': '/dev/vdb'},
|
||||
{'instance_uuid': uuid2,
|
||||
'device_name': '/dev/vdc'}]
|
||||
|
||||
for bdm in bdms_values:
|
||||
self._create_bdm(bdm)
|
||||
|
||||
bdms = db.block_device_mapping_get_all_by_instance(self.ctxt, uuid1)
|
||||
self.assertEqual(len(bdms), 1)
|
||||
self.assertEqual(bdms[0]['device_name'], '/dev/vda')
|
||||
|
||||
bdms = db.block_device_mapping_get_all_by_instance(self.ctxt, uuid2)
|
||||
self.assertEqual(len(bdms), 2)
|
||||
|
||||
def test_block_device_mapping_destroy(self):
|
||||
bdm = self._create_bdm({})
|
||||
|
|
|
@ -316,25 +316,62 @@ class TestRemoteBlockDeviceMappingObject(test_objects._RemoteTest,
|
|||
|
||||
|
||||
class _TestBlockDeviceMappingListObject(object):
|
||||
def fake_bdm(self, bdm_id):
|
||||
def fake_bdm(self, bdm_id, boot_index=-1, instance_uuid='fake-instance'):
|
||||
fake_bdm = fake_block_device.FakeDbBlockDeviceDict({
|
||||
'id': bdm_id, 'instance_uuid': 'fake-instance',
|
||||
'id': bdm_id,
|
||||
'boot_index': boot_index,
|
||||
'instance_uuid': instance_uuid,
|
||||
'device_name': '/dev/sda2',
|
||||
'source_type': 'snapshot',
|
||||
'destination_type': 'volume',
|
||||
'connection_info': "{'fake': 'connection_info'}",
|
||||
'snapshot_id': 'fake-snapshot-id-1',
|
||||
'boot_index': -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, ['fake-instance'])
|
||||
self.assertEqual(['fake-instance'], list(bdms_by_uuid.keys()))
|
||||
self.assertIsInstance(
|
||||
bdms_by_uuid['fake-instance'], objects.BlockDeviceMappingList)
|
||||
for faked, got in zip(fakes, bdms_by_uuid['fake-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, ['fake-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, ['fake-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, ['fake-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, 'fake_instance_uuid'))
|
||||
bdm_list = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
||||
self.context, 'fake-instance')
|
||||
for faked, got in zip(fakes, bdm_list):
|
||||
self.assertIsInstance(got, objects.BlockDeviceMapping)
|
||||
self.assertEqual(faked['id'], got.id)
|
||||
|
@ -342,11 +379,36 @@ class _TestBlockDeviceMappingListObject(object):
|
|||
@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, 'fake_instance_uuid'))
|
||||
bdm_list = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
||||
self.context, 'fake-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, 'fake-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, 'fake-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='uuid_1'),
|
||||
self.fake_bdm(456, instance_uuid='uuid_2')
|
||||
]
|
||||
get_all_by_inst.return_value = fakes
|
||||
bdm_list = objects.BlockDeviceMappingList.get_by_instance_uuid(
|
||||
self.context, 'fake-instance')
|
||||
self.assertRaises(exception.UndefinedRootBDM, bdm_list.root_bdm)
|
||||
|
||||
|
||||
class TestBlockDeviceMappingListObject(test_objects._LocalTest,
|
||||
_TestBlockDeviceMappingListObject):
|
||||
|
|
|
@ -1168,7 +1168,7 @@ object_data = {
|
|||
'BandwidthUsage': '1.2-c6e4c779c7f40f2407e3d70022e3cd1c',
|
||||
'BandwidthUsageList': '1.2-5fe7475ada6fe62413cbfcc06ec70746',
|
||||
'BlockDeviceMapping': '1.15-d44d8d694619e79c172a99b3c1d6261d',
|
||||
'BlockDeviceMappingList': '1.16-6fa262c059dad1d519b9fe05b9e4f404',
|
||||
'BlockDeviceMappingList': '1.17-1e568eecb91d06d4112db9fd656de235',
|
||||
'CellMapping': '1.0-7f1a7e85a22bbb7559fc730ab658b9bd',
|
||||
'ComputeNode': '1.14-a396975707b66281c5f404a68fccd395',
|
||||
'ComputeNodeList': '1.14-3b6f4f5ade621c40e70cb116db237844',
|
||||
|
|
Loading…
Reference in New Issue