From 0ec22a2b0db258cd342aedb635fe7263bd510562 Mon Sep 17 00:00:00 2001 From: Jay Lau Date: Tue, 13 Aug 2013 11:06:56 +0800 Subject: [PATCH] Disable retry filter with force_hosts or force_nodes If customer deploy a VM with force_hosts or force_nodes options, then there is no need to retry even if retry filter was enabled. Fix bug 1211597 Change-Id: I2948f48b5c4982cc29899b76889d7d8f0db47449 --- nova/scheduler/filter_scheduler.py | 6 ++- nova/scheduler/utils.py | 4 +- nova/tests/scheduler/test_filter_scheduler.py | 38 +++++++++++++++++++ nova/tests/scheduler/test_scheduler_utils.py | 20 ++++++++-- 4 files changed, 61 insertions(+), 7 deletions(-) diff --git a/nova/scheduler/filter_scheduler.py b/nova/scheduler/filter_scheduler.py index b2920b57c..cb91951ec 100644 --- a/nova/scheduler/filter_scheduler.py +++ b/nova/scheduler/filter_scheduler.py @@ -245,12 +245,14 @@ class FilterScheduler(driver.Scheduler): request. If maximum retries is exceeded, raise NoValidHost. """ max_attempts = self._max_attempts() - retry = filter_properties.pop('retry', {}) + force_hosts = filter_properties.get('force_hosts', []) + force_nodes = filter_properties.get('force_nodes', []) - if max_attempts == 1: + if max_attempts == 1 or force_hosts or force_nodes: # re-scheduling is disabled. return + retry = filter_properties.pop('retry', {}) # retry is enabled, update attempt count: if retry: retry['num_attempts'] += 1 diff --git a/nova/scheduler/utils.py b/nova/scheduler/utils.py index 316e88c64..8ef0e04eb 100644 --- a/nova/scheduler/utils.py +++ b/nova/scheduler/utils.py @@ -121,7 +121,9 @@ def _add_retry_host(filter_properties, host, node): node has already been tried. """ retry = filter_properties.get('retry', None) - if not retry: + force_hosts = filter_properties.get('force_hosts', []) + force_nodes = filter_properties.get('force_nodes', []) + if not retry or force_hosts or force_nodes: return hosts = retry['hosts'] hosts.append([host, node]) diff --git a/nova/tests/scheduler/test_filter_scheduler.py b/nova/tests/scheduler/test_filter_scheduler.py index ac790bd41..de4bf584e 100644 --- a/nova/tests/scheduler/test_filter_scheduler.py +++ b/nova/tests/scheduler/test_filter_scheduler.py @@ -229,6 +229,44 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase): # should not have retry info in the populated filter properties: self.assertFalse("retry" in filter_properties) + def test_retry_force_hosts(self): + # Retry info should not get populated when re-scheduling is off. + self.flags(scheduler_max_attempts=2) + sched = fakes.FakeFilterScheduler() + + instance_properties = {'project_id': '12345', 'os_type': 'Linux'} + request_spec = dict(instance_properties=instance_properties) + filter_properties = dict(force_hosts=['force_host']) + + self.mox.StubOutWithMock(db, 'compute_node_get_all') + db.compute_node_get_all(mox.IgnoreArg()).AndReturn([]) + self.mox.ReplayAll() + + sched._schedule(self.context, request_spec, + filter_properties=filter_properties) + + # should not have retry info in the populated filter properties: + self.assertFalse("retry" in filter_properties) + + def test_retry_force_nodes(self): + # Retry info should not get populated when re-scheduling is off. + self.flags(scheduler_max_attempts=2) + sched = fakes.FakeFilterScheduler() + + instance_properties = {'project_id': '12345', 'os_type': 'Linux'} + request_spec = dict(instance_properties=instance_properties) + filter_properties = dict(force_nodes=['force_node']) + + self.mox.StubOutWithMock(db, 'compute_node_get_all') + db.compute_node_get_all(mox.IgnoreArg()).AndReturn([]) + self.mox.ReplayAll() + + sched._schedule(self.context, request_spec, + filter_properties=filter_properties) + + # should not have retry info in the populated filter properties: + self.assertFalse("retry" in filter_properties) + def test_retry_attempt_one(self): # Test retry logic on initial scheduling attempt. self.flags(scheduler_max_attempts=2) diff --git a/nova/tests/scheduler/test_scheduler_utils.py b/nova/tests/scheduler/test_scheduler_utils.py index ff3e8168b..84db590f5 100644 --- a/nova/tests/scheduler/test_scheduler_utils.py +++ b/nova/tests/scheduler/test_scheduler_utils.py @@ -92,9 +92,15 @@ class SchedulerUtilsTestCase(test.NoDBTestCase): self._test_set_vm_state_and_notify(request_spec, expected_uuids) def _test_populate_filter_props(self, host_state_obj=True, - with_retry=True): + with_retry=True, + force_hosts=[], + force_nodes=[]): if with_retry: - filter_properties = dict(retry=dict(hosts=[])) + if not force_hosts and not force_nodes: + filter_properties = dict(retry=dict(hosts=[])) + else: + filter_properties = dict(force_hosts=force_hosts, + force_nodes=force_nodes) else: filter_properties = dict() @@ -110,13 +116,13 @@ class SchedulerUtilsTestCase(test.NoDBTestCase): scheduler_utils.populate_filter_properties(filter_properties, host_state) - if with_retry: + if with_retry and not force_hosts and not force_nodes: # So we can check for 2 hosts scheduler_utils.populate_filter_properties(filter_properties, host_state) self.assertEqual('fake-limits', filter_properties['limits']) - if with_retry: + if with_retry and not force_hosts and not force_nodes: self.assertEqual([['fake-host', 'fake-node'], ['fake-host', 'fake-node']], filter_properties['retry']['hosts']) @@ -131,3 +137,9 @@ class SchedulerUtilsTestCase(test.NoDBTestCase): def test_populate_filter_props_no_retry(self): self._test_populate_filter_props(with_retry=False) + + def test_populate_filter_props_force_hosts_no_retry(self): + self._test_populate_filter_props(force_hosts=['force-host']) + + def test_populate_filter_props_force_nodes_no_retry(self): + self._test_populate_filter_props(force_nodes=['force-node'])