Compute: Catch binding failed exception while init host

While compute starts it will init all instances,
if an exception is raised from one instance
(e.g NovaException during plug_vifs), then the
compute process exits unexpectedly because of
this unhandled exception.
This commit changes the NovaException to more
appropriate VirtualInterfacePlugException and
catches it during init host, as well as the
instance is set to error state, with this change
the compute process can be started normally even
if this VirtualInterfacePlugException is raised.

Closes-bug: #1324041

Conflicts:
	nova/tests/unit/compute/test_compute_mgr.py
	nova/virt/ironic/driver.py
	nova/virt/libvirt/vif.py

Change-Id: Ia584dba66affb86787e3069df19bd17b89cb5c49
(cherry picked from commit 16ac50b1e7)
This commit is contained in:
Wangpan 2014-11-13 06:10:40 +00:00 committed by Artom Lifshitz
parent bbf65ab569
commit e9cf07b96f
4 changed files with 36 additions and 2 deletions

View File

@ -915,6 +915,12 @@ class ComputeManager(manager.Manager):
self.driver.plug_vifs(instance, net_info)
except NotImplementedError as e:
LOG.debug(e, instance=instance)
except exception.VirtualInterfacePlugException:
# we don't want an exception to block the init_host
LOG.exception(_("Vifs plug failed"), instance=instance)
self._set_instance_error_state(context, instance)
return
if instance.task_state == task_states.RESIZE_MIGRATING:
# We crashed during resize/migration, so roll back for safety
try:

View File

@ -156,6 +156,10 @@ class VirtualInterfaceMacAddressException(NovaException):
"unique mac address failed")
class VirtualInterfacePlugException(NovaException):
msg_fmt = _("Virtual interface plugin failed")
class GlanceConnectionFailed(NovaException):
msg_fmt = _("Connection to glance host %(host)s:%(port)s failed: "
"%(reason)s")

View File

@ -272,6 +272,30 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
self.mox.VerifyAll()
self.mox.UnsetStubs()
def test_init_instance_with_binding_failed_vif_type(self):
# this instance will plug a 'binding_failed' vif
instance = fake_instance.fake_instance_obj(
self.context,
uuid='fake-uuid',
info_cache=None,
power_state=power_state.RUNNING,
vm_state=vm_states.ACTIVE,
task_state=None,
expected_attrs=['info_cache'])
with contextlib.nested(
mock.patch.object(context, 'get_admin_context',
return_value=self.context),
mock.patch.object(compute_utils, 'get_nw_info_for_instance',
return_value=network_model.NetworkInfo()),
mock.patch.object(self.compute.driver, 'plug_vifs',
side_effect=exception.VirtualInterfacePlugException(
"Unexpected vif_type=binding_failed")),
mock.patch.object(self.compute, '_set_instance_error_state')
) as (get_admin_context, get_nw_info, plug_vifs, set_error_state):
self.compute._init_instance(self.context, instance)
set_error_state.assert_called_once_with(self.context, instance)
def test_init_instance_failed_resume_sets_error(self):
instance = fake_instance.fake_instance_obj(
self.context,

View File

@ -592,7 +592,7 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
'vif': vif})
if vif_type is None:
raise exception.NovaException(
raise exception.VirtualInterfacePlugException(
_("vif_type parameter must be present "
"for this vif_driver implementation"))
elif vif_type == network_model.VIF_TYPE_BRIDGE:
@ -612,7 +612,7 @@ class LibvirtGenericVIFDriver(LibvirtBaseVIFDriver):
elif vif_type == network_model.VIF_TYPE_MIDONET:
self.plug_midonet(instance, vif)
else:
raise exception.NovaException(
raise exception.VirtualInterfacePlugException(
_("Unexpected vif_type=%s") % vif_type)
def unplug_bridge(self, instance, vif):