Merge "Make bdms querying in multi-cell use scatter-gather and ignore down cell"

This commit is contained in:
Zuul 2018-02-09 17:55:18 +00:00 committed by Gerrit Code Review
commit aee7340132
2 changed files with 60 additions and 6 deletions

View File

@ -13,12 +13,16 @@
# under the License. # under the License.
"""The Extended Volumes API extension.""" """The Extended Volumes API extension."""
from oslo_log import log as logging
from nova.api.openstack import api_version_request from nova.api.openstack import api_version_request
from nova.api.openstack import wsgi from nova.api.openstack import wsgi
from nova import context from nova import context
from nova import objects from nova import objects
from nova.policies import extended_volumes as ev_policies from nova.policies import extended_volumes as ev_policies
LOG = logging.getLogger(__name__)
class ExtendedVolumesController(wsgi.Controller): class ExtendedVolumesController(wsgi.Controller):
def _extend_server(self, context, server, req, bdms): def _extend_server(self, context, server, req, bdms):
@ -60,12 +64,19 @@ class ExtendedVolumesController(wsgi.Controller):
{inst_map.cell_mapping.uuid: inst_map.cell_mapping}) {inst_map.cell_mapping.uuid: inst_map.cell_mapping})
bdms = {} bdms = {}
for cell_mapping in cell_mappings.values(): results = context.scatter_gather_cells(
with context.target_cell(ctxt, cell_mapping) as cctxt: ctxt, cell_mappings.values(), 60,
bdms.update( objects.BlockDeviceMappingList.bdms_by_instance_uuid,
objects.BlockDeviceMappingList.bdms_by_instance_uuid( instance_uuids)
cctxt, instance_uuids)) for cell_uuid, result in results.items():
if result is context.raised_exception_sentinel:
LOG.warning('Failed to get block device mappings for cell %s',
cell_uuid)
elif result is context.did_not_respond_sentinel:
LOG.warning('Timeout getting block device mappings for cell '
'%s', cell_uuid)
else:
bdms.update(result)
return bdms return bdms
@wsgi.extends @wsgi.extends

View File

@ -165,6 +165,49 @@ class ExtendedVolumesTestV21(test.TestCase):
actual = server.get('%svolumes_attached' % self.prefix) actual = server.get('%svolumes_attached' % self.prefix)
self.assertEqual(self.exp_volumes_detail[i], actual) self.assertEqual(self.exp_volumes_detail[i], actual)
@mock.patch.object(objects.InstanceMappingList, 'get_by_instance_uuids')
@mock.patch('nova.context.scatter_gather_cells')
def test_detail_with_cell_failures(self, mock_sg,
mock_get_by_instance_uuids):
mock_get_by_instance_uuids.return_value = [
objects.InstanceMapping(
instance_uuid=UUID1,
cell_mapping=objects.CellMapping(
uuid=uuids.cell1,
transport_url='fake://nowhere/',
database_connection=uuids.cell1)),
objects.InstanceMapping(
instance_uuid=UUID2,
cell_mapping=objects.CellMapping(
uuid=uuids.cell2,
transport_url='fake://nowhere/',
database_connection=uuids.cell2))
]
bdm = fake_bdms_get_all_by_instance_uuids()
fake_bdm = fake_block_device.fake_bdm_object(
nova_context.RequestContext, bdm[0])
mock_sg.return_value = {
uuids.cell1: {UUID1: [fake_bdm]},
uuids.cell2: nova_context.raised_exception_sentinel
}
res = self._make_request('/detail')
mock_get_by_instance_uuids.assert_called_once_with(
test.MatchType(nova_context.RequestContext), [UUID1, UUID2])
self.assertEqual(200, res.status_int)
# we would get an empty list for the second instance
# which is in the down cell, however this would printed
# in the logs.
for i, server in enumerate(self._get_servers(res.body)):
actual = server.get('%svolumes_attached' % self.prefix)
if i == 0:
self.assertEqual(self.exp_volumes_detail[i], actual)
else:
self.assertEqual([], actual)
class ExtendedVolumesTestV23(ExtendedVolumesTestV21): class ExtendedVolumesTestV23(ExtendedVolumesTestV21):