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

This patch makes the querying of bdms from multiple cells in the
_get_instance_bdms_in_multiple_cells function of extended_volumes use
scatter_gather_cells thus making the process, parallel. It also adds
warnings in case a cell is not available; which the operator can later
tweak, if an exception needs to be raised. So for now, cells that are
not reachable are ignored and it proceeds to the next cell.

Change-Id: I0e05eb1e2ad37962968b79100bf4a96c7d6ddd8f
Closes-Bug: #1747650
(cherry picked from commit ea6757092d)
This commit is contained in:
Surya Seetharaman 2018-02-06 12:36:50 +01:00 committed by Matt Riedemann
parent 01b756f960
commit a564fe1ac2
2 changed files with 60 additions and 6 deletions

View File

@ -13,12 +13,16 @@
# under the License.
"""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 wsgi
from nova import context
from nova import objects
from nova.policies import extended_volumes as ev_policies
LOG = logging.getLogger(__name__)
class ExtendedVolumesController(wsgi.Controller):
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})
bdms = {}
for cell_mapping in cell_mappings.values():
with context.target_cell(ctxt, cell_mapping) as cctxt:
bdms.update(
objects.BlockDeviceMappingList.bdms_by_instance_uuid(
cctxt, instance_uuids))
results = context.scatter_gather_cells(
ctxt, cell_mappings.values(), 60,
objects.BlockDeviceMappingList.bdms_by_instance_uuid,
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
@wsgi.extends

View File

@ -165,6 +165,49 @@ class ExtendedVolumesTestV21(test.TestCase):
actual = server.get('%svolumes_attached' % self.prefix)
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):