diff --git a/nova/compute/manager.py b/nova/compute/manager.py index f43397e365c8..e0a5e2b3fa97 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -1054,16 +1054,33 @@ class ComputeManager(manager.SchedulerDependentManager): for db_instance in db_instances: name = db_instance['name'] + db_state = db_instance['state'] vm_instance = vm_instances.get(name) + if vm_instance is None: - LOG.info(_("Found instance '%(name)s' in DB but no VM. " - "Setting state to shutoff.") % locals()) - vm_state = power_state.SHUTOFF + # NOTE(justinsb): We have to be very careful here, because a + # concurrent operation could be in progress (e.g. a spawn) + if db_state == power_state.NOSTATE: + # Assume that NOSTATE => spawning + # TODO(justinsb): This does mean that if we crash during a + # spawn, the machine will never leave the spawning state, + # but this is just the way nova is; this function isn't + # trying to correct that problem. + # We could have a separate task to correct this error. + # TODO(justinsb): What happens during a live migration? + LOG.info(_("Found instance '%(name)s' in DB but no VM. " + "State=%(db_state)s, so assuming spawn is in " + "progress.") % locals()) + vm_state = db_state + else: + LOG.info(_("Found instance '%(name)s' in DB but no VM. " + "State=%(db_state)s, so setting state to " + "shutoff.") % locals()) + vm_state = power_state.SHUTOFF else: vm_state = vm_instance.state vms_not_found_in_db.remove(name) - db_state = db_instance['state'] if vm_state != db_state: LOG.info(_("DB/VM state mismatch. Changing state from " "'%(db_state)s' to '%(vm_state)s'") % locals())