From 8279240ee30d55d127e4d964a9861b721ac7cc74 Mon Sep 17 00:00:00 2001 From: Dean Troyer Date: Fri, 20 Jan 2012 16:39:41 -0600 Subject: [PATCH] Handle error in associate floating IP (bug 845507) * Raise NoFloatingIpInterface when associate floating IP has an interface that doesn't exist. * Return 500 Internal server Error, indicate only that associate action failed Change-Id: I6b032f7554795de64bce8e669d20269210c62e33 --- .../openstack/compute/contrib/floating_ips.py | 3 +++ nova/exception.py | 4 +++ nova/network/api.py | 2 +- nova/network/manager.py | 27 ++++++++++++++----- nova/tests/test_network.py | 17 ++++++++++++ 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/nova/api/openstack/compute/contrib/floating_ips.py b/nova/api/openstack/compute/contrib/floating_ips.py index 3cfbc0604649..ab9dfb8aa3f2 100644 --- a/nova/api/openstack/compute/contrib/floating_ips.py +++ b/nova/api/openstack/compute/contrib/floating_ips.py @@ -206,6 +206,9 @@ class FloatingIPActionController(wsgi.Controller): raise webob.exc.HTTPBadRequest(explanation=e.message) except exception.NotAuthorized, e: raise webob.exc.HTTPUnauthorized() + except rpc.RemoteError: + msg = _("Associate floating ip failed") + raise webob.exc.HTTPInternalServerError(explanation=msg) return webob.Response(status_int=202) diff --git a/nova/exception.py b/nova/exception.py index a60c82f716fb..68046979eefa 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -584,6 +584,10 @@ class NoFloatingIpsDefined(NotFound): message = _("Zero floating ips exist.") +class NoFloatingIpInterface(NotFound): + message = _("Interface %(interface)s not found.") + + class KeypairNotFound(NotFound): message = _("Keypair %(name)s not found for user %(user_id)s") diff --git a/nova/network/api.py b/nova/network/api.py index 83ef7a56600b..dac012e1c945 100644 --- a/nova/network/api.py +++ b/nova/network/api.py @@ -123,7 +123,7 @@ class API(base.Base): ensures floating ip is allocated to the project in context """ - rpc.cast(context, + rpc.call(context, FLAGS.network_topic, {'method': 'associate_floating_ip', 'args': {'floating_address': floating_address, diff --git a/nova/network/manager.py b/nova/network/manager.py index 5e9035a1258c..f1a07cd81420 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -226,10 +226,15 @@ class FloatingIP(object): for floating_ip in floating_ips: if floating_ip.get('fixed_ip', None): fixed_address = floating_ip['fixed_ip']['address'] - # NOTE(vish): The False here is because we ignore the case - # that the ip is already bound. - self.driver.bind_floating_ip(floating_ip['address'], - floating_ip['interface']) + interface = floating_ip['interface'] + try: + self.driver.bind_floating_ip(floating_ip['address'], + interface) + except exception.ProcessExecutionError: + msg = _('Interface %(interface)s not found' % locals()) + LOG.debug(msg) + raise exception.NoFloatingIpInterface(interface=interface) + self.driver.ensure_floating_forward(floating_ip['address'], fixed_address) @@ -415,8 +420,18 @@ class FloatingIP(object): floating_address, fixed_address, self.host) - # gogo driver time - self.driver.bind_floating_ip(floating_address, interface) + try: + # gogo driver time + self.driver.bind_floating_ip(floating_address, interface) + except exception.ProcessExecutionError as e: + fixed_address = self.db.floating_ip_disassociate(context, + floating_address) + if "Cannot find device" in str(e): + msg = _('Interface %(interface)s not found' % locals()) + LOG.error(msg) + raise exception.NoFloatingIpInterface(interface=interface) + raise + self.driver.ensure_floating_forward(floating_address, fixed_address) @wrap_check_policy diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index 573a308e12ec..200251b7ee2b 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -636,6 +636,23 @@ class VlanNetworkTestCase(test.TestCase): def fake7(*args, **kwargs): self.local = True + def fake8(*args, **kwargs): + raise exception.ProcessExecutionError('', + 'Cannot find device "em0"\n') + + # raises because interface doesn't exist + self.stubs.Set(self.network.db, + 'floating_ip_fixed_ip_associate', + fake1) + self.stubs.Set(self.network.db, 'floating_ip_disassociate', fake1) + self.stubs.Set(self.network.driver, 'bind_floating_ip', fake8) + self.assertRaises(exception.NoFloatingIpInterface, + self.network._associate_floating_ip, + ctxt, + mox.IgnoreArg(), + mox.IgnoreArg(), + mox.IgnoreArg()) + self.stubs.Set(self.network, '_floating_ip_owned_by_project', fake1) # raises because floating_ip is already associated to a fixed_ip