Fix regression issues with cells target filter

1) Skip scheduling if a cell filter already took care of it
2) Call build_instances or schedule_run_instance (deprecated) depending on
   which method the caller used.

bug 1224465

Change-Id: I391e1c4f288c9dc3e1308ee8c001a662e0f4c1b8
This commit is contained in:
Brian Elliott 2013-09-10 20:13:51 +00:00
parent 4e842e38a2
commit 2dbea4a9f5
4 changed files with 45 additions and 7 deletions

View File

@ -63,7 +63,12 @@ class TargetCellFilter(filters.BaseCellFilter):
if cell_name == filter_properties['routing_path']: if cell_name == filter_properties['routing_path']:
return [scheduler.state_manager.get_my_state()] return [scheduler.state_manager.get_my_state()]
ctxt = filter_properties['context'] ctxt = filter_properties['context']
scheduler.msg_runner.schedule_run_instance(ctxt, cell_name,
filter_properties['host_sched_kwargs']) # NOTE(belliott) Remove after deprecated schedule_run_instance
# code goes away:
schedule = filter_properties['cell_scheduler_method']
schedule = getattr(scheduler.msg_runner, schedule)
schedule(ctxt, cell_name, filter_properties['host_sched_kwargs'])
# Returning None means to skip further scheduling, because we # Returning None means to skip further scheduling, because we
# handled it. # handled it.

View File

@ -246,6 +246,10 @@ class CellsScheduler(base.Base):
'routing_path': message.routing_path, 'routing_path': message.routing_path,
'host_sched_kwargs': build_inst_kwargs, 'host_sched_kwargs': build_inst_kwargs,
'request_spec': request_spec}) 'request_spec': request_spec})
# NOTE(belliott) remove when deprecated schedule_run_instance
# code gets removed.
filter_properties['cell_scheduler_method'] = 'build_instances'
self._schedule_build_to_cells(message, instance_uuids, self._schedule_build_to_cells(message, instance_uuids,
filter_properties, self._build_instances, build_inst_kwargs) filter_properties, self._build_instances, build_inst_kwargs)
@ -258,6 +262,10 @@ class CellsScheduler(base.Base):
'routing_path': message.routing_path, 'routing_path': message.routing_path,
'host_sched_kwargs': host_sched_kwargs, 'host_sched_kwargs': host_sched_kwargs,
'request_spec': request_spec}) 'request_spec': request_spec})
# NOTE(belliott) remove when deprecated schedule_run_instance
# code gets removed.
filter_properties['cell_scheduler_method'] = 'schedule_run_instance'
self._schedule_build_to_cells(message, instance_uuids, self._schedule_build_to_cells(message, instance_uuids,
filter_properties, self._run_instance, host_sched_kwargs) filter_properties, self._run_instance, host_sched_kwargs)
@ -268,6 +276,10 @@ class CellsScheduler(base.Base):
for i in xrange(max(0, CONF.cells.scheduler_retries) + 1): for i in xrange(max(0, CONF.cells.scheduler_retries) + 1):
try: try:
target_cells = self._grab_target_cells(filter_properties) target_cells = self._grab_target_cells(filter_properties)
if target_cells is None:
# a filter took care of scheduling. skip.
return
return method(message, target_cells, instance_uuids, return method(message, target_cells, instance_uuids,
method_kwargs) method_kwargs)
except exception.NoCellsAvailable: except exception.NoCellsAvailable:

View File

@ -154,10 +154,10 @@ class TestTargetCellFilter(_FilterTestClass):
'routing_path': current_cell, 'routing_path': current_cell,
'scheduler': self.scheduler, 'scheduler': self.scheduler,
'context': self.context, 'context': self.context,
'host_sched_kwargs': 'meow'} 'host_sched_kwargs': 'meow',
'cell_scheduler_method': 'schedule_run_instance'}
# None is returned to bypass further scheduling. # None is returned to bypass further scheduling.
self.assertEqual(None, self.assertEqual(None, self._filter_cells(cells, filter_props))
self._filter_cells(cells, filter_props))
# The filter should have re-scheduled to the child cell itself. # The filter should have re-scheduled to the child cell itself.
expected_info = {'ctxt': self.context, expected_info = {'ctxt': self.context,
'cell': 'fake!cell!path', 'cell': 'fake!cell!path',

View File

@ -422,6 +422,23 @@ class CellsSchedulerTestCase(test.TestCase):
self.assertEqual(self.instance_uuids, call_info['errored_uuids1']) self.assertEqual(self.instance_uuids, call_info['errored_uuids1'])
self.assertEqual(self.instance_uuids, call_info['errored_uuids2']) self.assertEqual(self.instance_uuids, call_info['errored_uuids2'])
def test_filter_schedule_skipping(self):
# if a filter handles scheduling, short circuit
def _grab(filter_properties):
return None
self.stubs.Set(self.scheduler, '_grab_target_cells', _grab)
def _test(self, *args):
raise test.TestingException("shouldn't be called")
try:
self.scheduler._schedule_build_to_cells(None, None, None, _test,
None)
except test.TestingException:
self.fail("Scheduling did not properly short circuit")
def test_cells_filter_args_correct(self): def test_cells_filter_args_correct(self):
# Re-init our fakes with some filters. # Re-init our fakes with some filters.
our_path = 'nova.tests.cells.test_cells_scheduler' our_path = 'nova.tests.cells.test_cells_scheduler'
@ -488,7 +505,9 @@ class CellsSchedulerTestCase(test.TestCase):
'scheduler': self.scheduler, 'scheduler': self.scheduler,
'routing_path': self.my_cell_state.name, 'routing_path': self.my_cell_state.name,
'host_sched_kwargs': host_sched_kwargs, 'host_sched_kwargs': host_sched_kwargs,
'request_spec': self.request_spec} 'request_spec': self.request_spec,
'cell_scheduler_method':
'schedule_run_instance'}
self.assertEqual(expected_filt_props, call_info['filt_props']) self.assertEqual(expected_filt_props, call_info['filt_props'])
self.assertEqual([FakeFilterClass1, FakeFilterClass2], self.assertEqual([FakeFilterClass1, FakeFilterClass2],
call_info['filt_classes']) call_info['filt_classes'])
@ -593,7 +612,9 @@ class CellsSchedulerTestCase(test.TestCase):
'scheduler': self.scheduler, 'scheduler': self.scheduler,
'routing_path': self.my_cell_state.name, 'routing_path': self.my_cell_state.name,
'host_sched_kwargs': host_sched_kwargs, 'host_sched_kwargs': host_sched_kwargs,
'request_spec': self.request_spec} 'request_spec': self.request_spec,
'cell_scheduler_method':
'schedule_run_instance'}
self.assertEqual(expected_filt_props, call_info['weight_props']) self.assertEqual(expected_filt_props, call_info['weight_props'])
self.assertEqual([FakeWeightClass1, FakeWeightClass2], self.assertEqual([FakeWeightClass1, FakeWeightClass2],
call_info['weight_classes']) call_info['weight_classes'])