From: Akihiro Motoki Date: Wed, 12 Feb 2014 14:18:36 +0000 (+0900) Subject: Use save_and_reraise_exception when reraise exception X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=b3ec1cd6578a19413893a6b2ef276532c44c2a4f;p=openstack-build%2Fneutron-build.git Use save_and_reraise_exception when reraise exception This commit fixes neutron core and common codes. Partial-Bug: #1279813 Change-Id: Id109924c7ff9b4f0d74c23665016a54bfd7dff77 --- diff --git a/neutron/agent/l3_agent.py b/neutron/agent/l3_agent.py index 9931b3666..01132cc79 100644 --- a/neutron/agent/l3_agent.py +++ b/neutron/agent/l3_agent.py @@ -35,6 +35,7 @@ from neutron.common import topics from neutron.common import utils as common_utils from neutron import context from neutron import manager +from neutron.openstack.common import excutils from neutron.openstack.common import importutils from neutron.openstack.common import lockutils from neutron.openstack.common import log as logging @@ -302,14 +303,13 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager): try: return self.plugin_rpc.get_external_network_id(self.context) except rpc_common.RemoteError as e: - if e.exc_type == 'TooManyExternalNetworks': - msg = _( - "The 'gateway_external_network_id' option must be " - "configured for this agent as Neutron has more than " - "one external network.") - raise Exception(msg) - else: - raise + with excutils.save_and_reraise_exception(): + if e.exc_type == 'TooManyExternalNetworks': + msg = _( + "The 'gateway_external_network_id' option must be " + "configured for this agent as Neutron has more than " + "one external network.") + raise Exception(msg) def _router_added(self, router_id, router): ri = RouterInfo(router_id, self.root_helper, diff --git a/neutron/agent/linux/utils.py b/neutron/agent/linux/utils.py index fdb8d0d4d..72b17b425 100644 --- a/neutron/agent/linux/utils.py +++ b/neutron/agent/linux/utils.py @@ -28,6 +28,7 @@ from eventlet.green import subprocess from eventlet import greenthread from neutron.common import utils +from neutron.openstack.common import excutils from neutron.openstack.common import log as logging @@ -116,10 +117,11 @@ def find_child_pids(pid): try: raw_pids = execute(['ps', '--ppid', pid, '-o', 'pid=']) except RuntimeError as e: - # Exception has already been logged by execute - no_children_found = 'Exit code: 1' in str(e) - if no_children_found: - return [] # Unexpected errors are the responsibility of the caller - raise + with excutils.save_and_reraise_exception() as ctxt: + # Exception has already been logged by execute + no_children_found = 'Exit code: 1' in str(e) + if no_children_found: + ctxt.reraise = False + return [] return [x.strip() for x in raw_pids.split('\n') if x.strip()] diff --git a/neutron/agent/metadata/agent.py b/neutron/agent/metadata/agent.py index ce2751630..40dae1e60 100644 --- a/neutron/agent/metadata/agent.py +++ b/neutron/agent/metadata/agent.py @@ -35,6 +35,7 @@ from neutron.common import constants as n_const from neutron.common import topics from neutron.common import utils from neutron import context +from neutron.openstack.common import excutils from neutron.openstack.common import log as logging from neutron.openstack.common import loopingcall from neutron.openstack.common import service @@ -255,8 +256,9 @@ class UnixDomainMetadataProxy(object): try: os.unlink(cfg.CONF.metadata_proxy_socket) except OSError: - if os.path.exists(cfg.CONF.metadata_proxy_socket): - raise + with excutils.save_and_reraise_exception() as ctxt: + if not os.path.exists(cfg.CONF.metadata_proxy_socket): + ctxt.reraise = False else: os.makedirs(dirname, 0o755) diff --git a/neutron/common/exceptions.py b/neutron/common/exceptions.py index 9e77832b4..1b23a5274 100644 --- a/neutron/common/exceptions.py +++ b/neutron/common/exceptions.py @@ -19,6 +19,8 @@ Neutron base exception handling. """ +from neutron.openstack.common import excutils + class NeutronException(Exception): """Base Neutron Exception. @@ -34,11 +36,11 @@ class NeutronException(Exception): super(NeutronException, self).__init__(self.message % kwargs) self.msg = self.message % kwargs except Exception: - if self.use_fatal_exceptions(): - raise - else: - # at least get the core message out if something happened - super(NeutronException, self).__init__(self.message) + with excutils.save_and_reraise_exception() as ctxt: + if not self.use_fatal_exceptions(): + ctxt.reraise = False + # at least get the core message out if something happened + super(NeutronException, self).__init__(self.message) def __unicode__(self): return unicode(self.msg) diff --git a/neutron/db/agents_db.py b/neutron/db/agents_db.py index 960085f97..938c30fa2 100644 --- a/neutron/db/agents_db.py +++ b/neutron/db/agents_db.py @@ -26,6 +26,7 @@ from neutron.db import models_v2 from neutron.extensions import agent as ext_agent from neutron import manager from neutron.openstack.common.db import exception as db_exc +from neutron.openstack.common import excutils from neutron.openstack.common import jsonutils from neutron.openstack.common import log as logging from neutron.openstack.common import timeutils @@ -178,21 +179,22 @@ class AgentDbMixin(ext_agent.AgentPluginBase): try: return self._create_or_update_agent(context, agent) except db_exc.DBDuplicateEntry as e: - if e.columns == ['agent_type', 'host']: - # It might happen that two or more concurrent transactions are - # trying to insert new rows having the same value of - # (agent_type, host) pair at the same time (if there has been - # no such entry in the table and multiple agent status updates - # are being processed at the moment). In this case having a - # unique constraint on (agent_type, host) columns guarantees - # that only one transaction will succeed and insert a new agent - # entry, others will fail and be rolled back. That means we - # must retry them one more time: no INSERTs will be issued, - # because _get_agent_by_type_and_host() will return the - # existing agent entry, which will be updated multiple times - return self._create_or_update_agent(context, agent) - - raise + with excutils.save_and_reraise_exception() as ctxt: + if e.columns == ['agent_type', 'host']: + # It might happen that two or more concurrent transactions + # are trying to insert new rows having the same value of + # (agent_type, host) pair at the same time (if there has + # been no such entry in the table and multiple agent status + # updates are being processed at the moment). In this case + # having a unique constraint on (agent_type, host) columns + # guarantees that only one transaction will succeed and + # insert a new agent entry, others will fail and be rolled + # back. That means we must retry them one more time: no + # INSERTs will be issued, because + # _get_agent_by_type_and_host() will return the existing + # agent entry, which will be updated multiple times + ctxt.reraise = False + return self._create_or_update_agent(context, agent) class AgentExtRpcCallback(object): diff --git a/neutron/db/dhcp_rpc_base.py b/neutron/db/dhcp_rpc_base.py index 056141270..b945fec27 100644 --- a/neutron/db/dhcp_rpc_base.py +++ b/neutron/db/dhcp_rpc_base.py @@ -22,6 +22,7 @@ from neutron.common import utils from neutron.extensions import portbindings from neutron import manager from neutron.openstack.common.db import exception as db_exc +from neutron.openstack.common import excutils from neutron.openstack.common import log as logging @@ -58,20 +59,22 @@ class DhcpRpcCallbackMixin(object): raise n_exc.Invalid(message=msg) except (db_exc.DBError, n_exc.NetworkNotFound, n_exc.SubnetNotFound, n_exc.IpAddressGenerationFailure) as e: - if isinstance(e, n_exc.IpAddressGenerationFailure): - # Check if the subnet still exists and if it does not, this is - # the reason why the ip address generation failed. In any other - # unlikely event re-raise - try: - subnet_id = port['port']['fixed_ips'][0]['subnet_id'] - plugin.get_subnet(context, subnet_id) - except n_exc.SubnetNotFound: - pass - else: - raise - network_id = port['port']['network_id'] - LOG.warn(_("Port for network %(net_id)s could not be created: " - "%(reason)s") % {"net_id": network_id, 'reason': e}) + with excutils.save_and_reraise_exception() as ctxt: + ctxt.reraise = False + if isinstance(e, n_exc.IpAddressGenerationFailure): + # Check if the subnet still exists and if it does not, + # this is the reason why the ip address generation failed. + # In any other unlikely event re-raise + try: + subnet_id = port['port']['fixed_ips'][0]['subnet_id'] + plugin.get_subnet(context, subnet_id) + except n_exc.SubnetNotFound: + pass + else: + ctxt.reraise = True + network_id = port['port']['network_id'] + LOG.warn(_("Port for network %(net_id)s could not be created: " + "%(reason)s") % {"net_id": network_id, 'reason': e}) def get_active_networks(self, context, **kwargs): """Retrieve and return a list of the active network ids.""" diff --git a/neutron/db/loadbalancer/loadbalancer_db.py b/neutron/db/loadbalancer/loadbalancer_db.py index 5968c9a7c..7c711b6b6 100644 --- a/neutron/db/loadbalancer/loadbalancer_db.py +++ b/neutron/db/loadbalancer/loadbalancer_db.py @@ -30,6 +30,7 @@ from neutron.extensions import loadbalancer from neutron.extensions.loadbalancer import LoadBalancerPluginBase from neutron import manager from neutron.openstack.common.db import exception +from neutron.openstack.common import excutils from neutron.openstack.common import log as logging from neutron.openstack.common import uuidutils from neutron.plugins.common import constants @@ -204,16 +205,15 @@ class LoadBalancerPluginDb(LoadBalancerPluginBase, try: r = self._get_by_id(context, model, id) except exc.NoResultFound: - if issubclass(model, Vip): - raise loadbalancer.VipNotFound(vip_id=id) - elif issubclass(model, Pool): - raise loadbalancer.PoolNotFound(pool_id=id) - elif issubclass(model, Member): - raise loadbalancer.MemberNotFound(member_id=id) - elif issubclass(model, HealthMonitor): - raise loadbalancer.HealthMonitorNotFound(monitor_id=id) - else: - raise + with excutils.save_and_reraise_exception(): + if issubclass(model, Vip): + raise loadbalancer.VipNotFound(vip_id=id) + elif issubclass(model, Pool): + raise loadbalancer.PoolNotFound(pool_id=id) + elif issubclass(model, Member): + raise loadbalancer.MemberNotFound(member_id=id) + elif issubclass(model, HealthMonitor): + raise loadbalancer.HealthMonitorNotFound(monitor_id=id) return r def assert_modification_allowed(self, obj): diff --git a/neutron/db/vpn/vpn_db.py b/neutron/db/vpn/vpn_db.py index 46406da72..cbcf6efe9 100644 --- a/neutron/db/vpn/vpn_db.py +++ b/neutron/db/vpn/vpn_db.py @@ -32,6 +32,7 @@ from neutron.db import models_v2 from neutron.extensions import vpnaas from neutron.extensions.vpnaas import VPNPluginBase from neutron import manager +from neutron.openstack.common import excutils from neutron.openstack.common import log as logging from neutron.openstack.common import uuidutils from neutron.plugins.common import constants @@ -178,18 +179,17 @@ class VPNPluginDb(VPNPluginBase, base_db.CommonDbMixin): try: r = self._get_by_id(context, model, v_id) except exc.NoResultFound: - if issubclass(model, IPsecSiteConnection): - raise vpnaas.IPsecSiteConnectionNotFound( - ipsec_site_conn_id=v_id - ) - elif issubclass(model, IKEPolicy): - raise vpnaas.IKEPolicyNotFound(ikepolicy_id=v_id) - elif issubclass(model, IPsecPolicy): - raise vpnaas.IPsecPolicyNotFound(ipsecpolicy_id=v_id) - elif issubclass(model, VPNService): - raise vpnaas.VPNServiceNotFound(vpnservice_id=v_id) - else: - raise + with excutils.save_and_reraise_exception(): + if issubclass(model, IPsecSiteConnection): + raise vpnaas.IPsecSiteConnectionNotFound( + ipsec_site_conn_id=v_id + ) + elif issubclass(model, IKEPolicy): + raise vpnaas.IKEPolicyNotFound(ikepolicy_id=v_id) + elif issubclass(model, IPsecPolicy): + raise vpnaas.IPsecPolicyNotFound(ipsecpolicy_id=v_id) + elif issubclass(model, VPNService): + raise vpnaas.VPNServiceNotFound(vpnservice_id=v_id) return r def assert_update_allowed(self, obj): diff --git a/neutron/policy.py b/neutron/policy.py index c4c241a58..6906373c9 100644 --- a/neutron/policy.py +++ b/neutron/policy.py @@ -27,6 +27,7 @@ from neutron.api.v2 import attributes from neutron.common import exceptions import neutron.common.utils as utils from neutron import manager +from neutron.openstack.common import excutils from neutron.openstack.common import importutils from neutron.openstack.common import log as logging from neutron.openstack.common import policy @@ -274,8 +275,8 @@ class OwnerCheck(policy.Check): fields=[parent_field]) target[self.target_field] = data[parent_field] except Exception: - LOG.exception(_('Policy check error while calling %s!'), f) - raise + with excutils.save_and_reraise_exception(): + LOG.exception(_('Policy check error while calling %s!'), f) match = self.match % target if self.kind in creds: return match == unicode(creds[self.kind]) diff --git a/neutron/service.py b/neutron/service.py index 32362343c..d0c2d7eaa 100644 --- a/neutron/service.py +++ b/neutron/service.py @@ -25,6 +25,7 @@ from oslo.config import cfg from neutron.common import config from neutron.common import legacy from neutron import context +from neutron.openstack.common import excutils from neutron.openstack.common import importutils from neutron.openstack.common import log as logging from neutron.openstack.common import loopingcall @@ -102,8 +103,9 @@ def serve_wsgi(cls): service = cls.create('quantum') service.start() except Exception: - LOG.exception(_('Unrecoverable error: please check log for details.')) - raise + with excutils.save_and_reraise_exception(): + LOG.exception(_('Unrecoverable error: please check log ' + 'for details.')) return service diff --git a/neutron/services/loadbalancer/drivers/haproxy/namespace_driver.py b/neutron/services/loadbalancer/drivers/haproxy/namespace_driver.py index c3aa7adfe..e0b028d16 100644 --- a/neutron/services/loadbalancer/drivers/haproxy/namespace_driver.py +++ b/neutron/services/loadbalancer/drivers/haproxy/namespace_driver.py @@ -27,6 +27,7 @@ from neutron.agent.linux import ip_lib from neutron.agent.linux import utils from neutron.common import exceptions from neutron.common import utils as n_utils +from neutron.openstack.common import excutils from neutron.openstack.common import importutils from neutron.openstack.common import log as logging from neutron.plugins.common import constants @@ -65,10 +66,10 @@ class HaproxyNSDriver(agent_device_driver.AgentDeviceDriver): try: vif_driver = importutils.import_object(conf.interface_driver, conf) except ImportError: - msg = (_('Error importing interface driver: %s') - % conf.haproxy.interface_driver) - LOG.error(msg) - raise + with excutils.save_and_reraise_exception(): + msg = (_('Error importing interface driver: %s') + % conf.haproxy.interface_driver) + LOG.error(msg) self.vif_driver = vif_driver self.plugin_rpc = plugin_rpc diff --git a/neutron/services/service_base.py b/neutron/services/service_base.py index 2730dee6d..100979b9a 100644 --- a/neutron/services/service_base.py +++ b/neutron/services/service_base.py @@ -21,6 +21,7 @@ import six from neutron.api import extensions from neutron.db import servicetype_db as sdb +from neutron.openstack.common import excutils from neutron.openstack.common import importutils from neutron.openstack.common import log as logging from neutron.services import provider_configuration as pconf @@ -84,11 +85,11 @@ def load_drivers(service_type, plugin): {'provider': provider['driver'], 'service_type': service_type}) except ImportError: - LOG.exception(_("Error loading provider '%(provider)s' for " - "service %(service_type)s"), - {'provider': provider['driver'], - 'service_type': service_type}) - raise + with excutils.save_and_reraise_exception(): + LOG.exception(_("Error loading provider '%(provider)s' for " + "service %(service_type)s"), + {'provider': provider['driver'], + 'service_type': service_type}) default_provider = None try: diff --git a/neutron/wsgi.py b/neutron/wsgi.py index 8898e7af6..9d9ff7b90 100644 --- a/neutron/wsgi.py +++ b/neutron/wsgi.py @@ -40,6 +40,7 @@ from neutron.common import constants from neutron.common import exceptions as exception from neutron import context from neutron.openstack.common.db.sqlalchemy import session +from neutron.openstack.common import excutils from neutron.openstack.common import gettextutils from neutron.openstack.common import jsonutils from neutron.openstack.common import log as logging @@ -176,9 +177,10 @@ class Server(object): sock = wrap_ssl(sock) except socket.error as err: - if err.errno != errno.EADDRINUSE: - raise - eventlet.sleep(0.1) + with excutils.save_and_reraise_exception() as ctxt: + if err.errno == errno.EADDRINUSE: + ctxt.reraise = False + eventlet.sleep(0.1) if not sock: raise RuntimeError(_("Could not bind to %(host)s:%(port)s " "after trying for %(time)d seconds") % @@ -698,19 +700,18 @@ class XMLDeserializer(TextDeserializer): return result return dict({root_tag: result}, **links) except Exception as e: - parseError = False - # Python2.7 - if (hasattr(etree, 'ParseError') and - isinstance(e, getattr(etree, 'ParseError'))): - parseError = True - # Python2.6 - elif isinstance(e, expat.ExpatError): - parseError = True - if parseError: - msg = _("Cannot understand XML") - raise exception.MalformedRequestBody(reason=msg) - else: - raise + with excutils.save_and_reraise_exception(): + parseError = False + # Python2.7 + if (hasattr(etree, 'ParseError') and + isinstance(e, getattr(etree, 'ParseError'))): + parseError = True + # Python2.6 + elif isinstance(e, expat.ExpatError): + parseError = True + if parseError: + msg = _("Cannot understand XML") + raise exception.MalformedRequestBody(reason=msg) def _from_xml_node(self, node, listnames): """Convert a minidom node to a simple Python type. @@ -832,8 +833,9 @@ class RequestDeserializer(object): try: deserializer = self.get_body_deserializer(content_type) except exception.InvalidContentType: - LOG.debug(_("Unable to deserialize body as provided Content-Type")) - raise + with excutils.save_and_reraise_exception(): + LOG.debug(_("Unable to deserialize body as provided " + "Content-Type")) return deserializer.deserialize(request.body, action)