From 26b7c43ca1fe94f937d6a6d89b3114ce9931c74d Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Sat, 21 Jan 2012 08:04:19 +0000 Subject: Make start_instance cast directly to compute host Fixes bug 918615 start_instance doesn't need to go through scheduler because it still has instance['host'] set and resources are still accounted for in the scheduler, which means there's still room to restart it on its assigned host (even though it is deleted from the virt layer) Change-Id: I3cdd73b7ad2297b57f7e36be84819ff233ac8f08 --- nova/compute/api.py | 6 +----- nova/scheduler/manager.py | 32 +++++++++++++--------------- nova/scheduler/multi.py | 1 - nova/scheduler/simple.py | 7 ------ nova/tests/scheduler/test_multi_scheduler.py | 7 ++++-- nova/tests/scheduler/test_scheduler.py | 28 ------------------------ 6 files changed, 21 insertions(+), 60 deletions(-) diff --git a/nova/compute/api.py b/nova/compute/api.py index f154103cf..ca28f3871 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -948,11 +948,7 @@ class API(base.Base): # TODO(yamahata): injected_files isn't supported right now. # It is used only for osapi. not for ec2 api. # availability_zone isn't used by run_instance. - rpc.cast(context, - FLAGS.scheduler_topic, - {"method": "start_instance", - "args": {"topic": FLAGS.compute_topic, - "instance_uuid": instance_uuid}}) + self._cast_compute_message('start_instance', context, instance) #NOTE(bcwaldon): no policy check here since it should be rolled in to # search_opts in get_all diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py index 33e77cd05..498759530 100644 --- a/nova/scheduler/manager.py +++ b/nova/scheduler/manager.py @@ -105,28 +105,26 @@ class SchedulerManager(manager.Manager): with utils.save_and_reraise_exception(): self._set_instance_error(method, context, ex, *args, **kwargs) - # NOTE (David Subiros) : If the exception is raised during run_instance - # method, we may or may not have an instance_id def _set_instance_error(self, method, context, ex, *args, **kwargs): """Sets VM to Error state""" LOG.warning(_("Failed to schedule_%(method)s: %(ex)s") % locals()) - if method != "start_instance" and method != "run_instance": + # FIXME(comstud): Re-factor this somehow. Not sure this belongs + # in the scheduler manager like this. Needs to support more than + # run_instance + if method != "run_instance": return - # FIXME(comstud): Clean this up after fully on UUIDs. - instance_id = kwargs.get('instance_uuid', kwargs.get('instance_id')) - if not instance_id: - # FIXME(comstud): We should make this easier. run_instance - # only sends a request_spec, and an instance may or may not - # have been created in the API (or scheduler) already. If it - # was created, there's a 'uuid' set in the instance_properties - # of the request_spec. - request_spec = kwargs.get('request_spec', {}) - properties = request_spec.get('instance_properties', {}) - instance_id = properties.get('uuid', {}) - if instance_id: - LOG.warning(_("Setting instance %(instance_id)s to " + # FIXME(comstud): We should make this easier. run_instance + # only sends a request_spec, and an instance may or may not + # have been created in the API (or scheduler) already. If it + # was created, there's a 'uuid' set in the instance_properties + # of the request_spec. + request_spec = kwargs.get('request_spec', {}) + properties = request_spec.get('instance_properties', {}) + instance_uuid = properties.get('uuid', {}) + if instance_uuid: + LOG.warning(_("Setting instance %(instance_uuid)s to " "ERROR state.") % locals()) - db.instance_update(context, instance_id, + db.instance_update(context, instance_uuid, {'vm_state': vm_states.ERROR}) # NOTE (masumotok) : This method should be moved to nova.api.ec2.admin. diff --git a/nova/scheduler/multi.py b/nova/scheduler/multi.py index 83ecd8e63..31d92583b 100644 --- a/nova/scheduler/multi.py +++ b/nova/scheduler/multi.py @@ -36,7 +36,6 @@ flags.DEFINE_string('volume_scheduler_driver', # A mapping of methods to topics so we can figure out which driver to use. _METHOD_MAP = {'run_instance': 'compute', - 'start_instance': 'compute', 'prep_resize': 'compute', 'live_migration': 'compute', 'create_volume': 'volume', diff --git a/nova/scheduler/simple.py b/nova/scheduler/simple.py index 64ebfb757..9ce3473ee 100644 --- a/nova/scheduler/simple.py +++ b/nova/scheduler/simple.py @@ -100,13 +100,6 @@ class SimpleScheduler(chance.ChanceScheduler): del request_spec['instance_properties']['uuid'] return instances - def schedule_start_instance(self, context, instance_id, *_args, **_kwargs): - instance_ref = db.instance_get(context, instance_id) - host = self._schedule_instance(context, instance_ref, - *_args, **_kwargs) - driver.cast_to_compute_host(context, host, 'start_instance', - instance_id=instance_id, **_kwargs) - def schedule_create_volume(self, context, volume_id, *_args, **_kwargs): """Picks a host that is up and has the fewest volumes.""" elevated = context.elevated() diff --git a/nova/tests/scheduler/test_multi_scheduler.py b/nova/tests/scheduler/test_multi_scheduler.py index cefc31b7e..7468a2447 100644 --- a/nova/tests/scheduler/test_multi_scheduler.py +++ b/nova/tests/scheduler/test_multi_scheduler.py @@ -31,7 +31,10 @@ class FakeComputeScheduler(driver.Scheduler): def schedule_run_instance(self, *args, **kwargs): pass - def schedule_start_instance(self, *args, **kwargs): + def schedule_live_migration(self, *args, **kwargs): + pass + + def schedule_prep_resize(self, *args, **kwargs): pass def schedule(self, *args, **kwargs): @@ -76,7 +79,7 @@ class MultiDriverTestCase(test_scheduler.SchedulerTestCase): compute_driver = mgr.drivers['compute'] volume_driver = mgr.drivers['volume'] - test_methods = {compute_driver: ['run_instance', 'start_instance'], + test_methods = {compute_driver: ['run_instance', 'prep_resize'], volume_driver: ['create_volume', 'create_volumes']} for driver, methods in test_methods.iteritems(): diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py index 19591c080..73b538768 100644 --- a/nova/tests/scheduler/test_scheduler.py +++ b/nova/tests/scheduler/test_scheduler.py @@ -231,34 +231,6 @@ class SchedulerManagerTestCase(test.TestCase): self.manager.run_instance(self.context, self.topic, *self.fake_args, **self.fake_kwargs) - def test_start_instance_exception_puts_instance_in_error_state(self): - """Test that an NoValidHost exception for start_instance puts - the instance in ERROR state and eats the exception. - """ - - fake_instance_id = 'fake-instance-id' - self.fake_kwargs['instance_id'] = fake_instance_id - - # Make sure the method exists that we're going to test call - def stub_method(*args, **kwargs): - pass - - setattr(self.manager.driver, 'schedule_start_instance', stub_method) - - self.mox.StubOutWithMock(self.manager.driver, - 'schedule_start_instance') - self.mox.StubOutWithMock(db, 'instance_update') - - self.manager.driver.schedule_start_instance(self.context, - *self.fake_args, **self.fake_kwargs).AndRaise( - exception.NoValidHost(reason="")) - db.instance_update(self.context, fake_instance_id, - {'vm_state': vm_states.ERROR}) - - self.mox.ReplayAll() - self.manager.start_instance(self.context, self.topic, - *self.fake_args, **self.fake_kwargs) - class SchedulerTestCase(test.TestCase): """Test case for base scheduler driver class""" -- cgit