Skip to content

Commit

Permalink
Fixing a rebuild race condition bug.
Browse files Browse the repository at this point in the history
A race condition caused servers to be undeletable and stay in rebuild state.
This patch handles exceptions on compute.manager side and sets the state
of the instances appropriately.

bug: 918958
Change-Id: I7369a63174284c5b9ed257cc129f611163d5841d
  • Loading branch information
ironcamel committed Jan 26, 2012
1 parent 9ca8654 commit 04ca11b
Showing 1 changed file with 21 additions and 8 deletions.
29 changes: 21 additions & 8 deletions nova/compute/manager.py
Expand Up @@ -187,6 +187,12 @@ def _instance_update(self, context, instance_id, **kwargs):
"""Update an instance in the database using kwargs as value."""
return self.db.instance_update(context, instance_id, kwargs)

def _set_instance_error_state(self, context, instance_uuid):
self._instance_update(context,
instance_uuid,
vm_state=vm_states.ERROR,
task_state=None)

def init_host(self):
"""Initialization for a standalone compute service."""
self.driver.init_host(host=self.host)
Expand Down Expand Up @@ -704,6 +710,19 @@ def rebuild_instance(self, context, instance_uuid, **kwargs):
:param injected_files: Files to inject
:param new_pass: password to set on rebuilt instance
"""
try:
self._rebuild_instance(context, instance_uuid, kwargs)
except exception.ImageNotFound:
msg = _("Cannot rebuild instance [%(instance_uuid)s]"
", because the given image does not exist.")
LOG.error(msg % instance_uuid, context=context)
self._set_instance_error_state(context, instance_uuid)
except Exception as exc:
msg = _("Cannot rebuild instance [%(instance_uuid)s]: %(exc)s")
LOG.error(msg % locals(), context=context)
self._set_instance_error_state(context, instance_uuid)

def _rebuild_instance(self, context, instance_uuid, kwargs):
context = context.elevated()

LOG.audit(_("Rebuilding instance %s"), instance_uuid, context=context)
Expand Down Expand Up @@ -945,10 +964,7 @@ def set_admin_password(self, context, instance_uuid, new_pass=None):
# Catch all here because this could be anything.
LOG.exception(e)
if i == max_tries - 1:
self._instance_update(context,
instance_id,
task_state=None,
vm_state=vm_states.ERROR)
self._set_instance_error_state(context, instance_id)
# We create a new exception here so that we won't
# potentially reveal password information to the
# API caller. The real exception is logged above
Expand Down Expand Up @@ -2203,10 +2219,7 @@ def error_out_instance_on_exception(self, context, instance_uuid):
with utils.save_and_reraise_exception():
msg = _('%s. Setting instance vm_state to ERROR')
LOG.error(msg % error)
self._instance_update(context,
instance_uuid,
vm_state=vm_states.ERROR,
task_state=None)
self._set_instance_error_state(context, instance_uuid)

def add_aggregate_host(self, context, aggregate_id, host):
"""Adds a host to a physical hypervisor pool."""
Expand Down

0 comments on commit 04ca11b

Please sign in to comment.