Skip to content

Commit

Permalink
Handle binding_failed vif plug errors on compute restart
Browse files Browse the repository at this point in the history
Like change Ia584dba66affb86787e3069df19bd17b89cb5c49 which
came before, is port binding fails and we have a "binding_failed"
vif type in the info cache, we'll fail to plug vifs for an
instance on compute restart which will prevent the service
from restarting. Before the os-vif conversion code, this was
handled with VirtualInterfacePlugException but the os-vif conversion
code fails in a different way by raising a generic NovaException
because the os-vif conversion utility doesn't handle a vif_type of
"binding_failed".

To resolve this and make the os-vif flow for binding_failed behave
the same as the legacy path, we implement a translation function
in os_vif_util for binding_failed which will make the plug_vifs
code raise VirtualInterfacePlugException which is what the
_init_instance code in ComputeManager is already handling.

Admittedly this isn't the smartest thing and doesn't attempt
to recover / fix the instance networking info, but it at least
gives a more clear indication of what's wrong and lets the
nova-compute service start up. A note is left in the
_init_instance error handling that we could potentially try
to heal binding_failed vifs in _heal_instance_info_cache, but
that would need to be done in a separate change since it's more
invasive.

Change-Id: Ia963a093a1b26d90b4de2e8fc623031cf175aece
Closes-Bug: #1784579
  • Loading branch information
mriedem committed Aug 9, 2018
1 parent 9d54673 commit cdf8ba5
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 5 deletions.
11 changes: 9 additions & 2 deletions nova/compute/manager.py
Expand Up @@ -959,8 +959,15 @@ def _init_instance(self, context, instance):
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)
# NOTE(mriedem): If we get here, it could be because the vif_type
# in the cache is "binding_failed". The only way to fix that is to
# try and bind the ports again, which would be expensive here on
# host startup. We could add a check to _heal_instance_info_cache
# to handle this, but probably only if the instance task_state is
# None.
LOG.exception('Virtual interface plugging failed for instance. '
'The port binding:host_id may need to be manually '
'updated.', instance=instance)
self._set_instance_obj_error_state(context, instance)
return

Expand Down
14 changes: 14 additions & 0 deletions nova/network/os_vif_util.py
Expand Up @@ -481,6 +481,20 @@ def _nova_to_osvif_vif_hostdev_physical(vif):
raise NotImplementedError()


# VIF_TYPE_BINDING_FAILED = 'binding_failed'
def _nova_to_osvif_vif_binding_failed(vif):
"""Special handler for the "binding_failed" vif type.
The "binding_failed" vif type indicates port binding to a host failed
and we are trying to plug the vifs again, which will fail because we
do not know the actual real vif type, like ovs, bridge, etc. We raise
NotImplementedError to indicate to the caller that we cannot handle
this type of vif rather than the generic "Unsupported VIF type" error
in nova_to_osvif_vif.
"""
raise NotImplementedError()


def nova_to_osvif_vif(vif):
"""Convert a Nova VIF model to an os-vif object
Expand Down
18 changes: 15 additions & 3 deletions nova/tests/unit/network/test_os_vif_util.py
Expand Up @@ -14,6 +14,7 @@

from os_vif import objects as osv_objects
from os_vif.objects import fields as os_vif_fields
import six

from nova import exception
from nova.network import model
Expand Down Expand Up @@ -1013,9 +1014,20 @@ def test_nova_to_osvif_vif_unknown(self):
subnets=[]),
)

self.assertRaises(exception.NovaException,
os_vif_util.nova_to_osvif_vif,
vif)
ex = self.assertRaises(exception.NovaException,
os_vif_util.nova_to_osvif_vif, vif)
self.assertIn('Unsupported VIF type wibble', six.text_type(ex))

def test_nova_to_osvif_vif_binding_failed(self):
vif = model.VIF(
id="dc065497-3c8d-4f44-8fb4-e1d33c16a536",
type="binding_failed",
address="22:52:25:62:e2:aa",
network=model.Network(
id="b82c1929-051e-481d-8110-4669916c7915",
label="Demo Net",
subnets=[]),)
self.assertIsNone(os_vif_util.nova_to_osvif_vif(vif))

def test_nova_to_osvif_vhostuser_vrouter(self):
vif = model.VIF(
Expand Down

0 comments on commit cdf8ba5

Please sign in to comment.