Merge "Revert "Refactoring the exceptions lists""

This commit is contained in:
Jenkins
2015-04-07 02:04:47 +00:00
committed by Gerrit Code Review
9 changed files with 121 additions and 150 deletions

View File

@@ -23,6 +23,12 @@ class LazySettings(LazyObject):
HORIZON_CONFIG = copy.copy(DEFAULT_CONFIG) HORIZON_CONFIG = copy.copy(DEFAULT_CONFIG)
HORIZON_CONFIG.update(settings.HORIZON_CONFIG) HORIZON_CONFIG.update(settings.HORIZON_CONFIG)
# Ensure we always have our exception configuration...
for exc_category in ['unauthorized', 'not_found', 'recoverable']:
if exc_category not in HORIZON_CONFIG['exceptions']:
default_exc_config = DEFAULT_CONFIG['exceptions'][exc_category]
HORIZON_CONFIG['exceptions'][exc_category] = default_exc_config
# Ensure our password validator always exists... # Ensure our password validator always exists...
if 'regex' not in HORIZON_CONFIG['password_validator']: if 'regex' not in HORIZON_CONFIG['password_validator']:
default_pw_regex = DEFAULT_CONFIG['password_validator']['regex'] default_pw_regex = DEFAULT_CONFIG['password_validator']['regex']

View File

@@ -31,6 +31,11 @@ HORIZON_CONFIG = {
# URL for additional help with this site. # URL for additional help with this site.
'help_url': None, 'help_url': None,
# Exception configuration.
'exceptions': {'unauthorized': [],
'not_found': [],
'recoverable': []},
# Password configuration. # Password configuration.
'password_validator': {'regex': '.*', 'password_validator': {'regex': '.*',
'help_text': _("Password is not accepted")}, 'help_text': _("Password is not accepted")},

View File

@@ -22,7 +22,6 @@ import sys
import six import six
from django.conf import settings
from django.core.management import color_style # noqa from django.core.management import color_style # noqa
from django.http import HttpRequest # noqa from django.http import HttpRequest # noqa
from django.utils import encoding from django.utils import encoding
@@ -30,6 +29,7 @@ from django.utils.translation import ugettext_lazy as _
from django.views.debug import CLEANSED_SUBSTITUTE # noqa from django.views.debug import CLEANSED_SUBSTITUTE # noqa
from django.views.debug import SafeExceptionReporterFilter # noqa from django.views.debug import SafeExceptionReporterFilter # noqa
from horizon.conf import HORIZON_CONFIG # noqa
from horizon import messages from horizon import messages
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@@ -202,6 +202,12 @@ class HandledException(HorizonException):
self.wrapped = wrapped self.wrapped = wrapped
UNAUTHORIZED = tuple(HORIZON_CONFIG['exceptions']['unauthorized'])
NOT_FOUND = tuple(HORIZON_CONFIG['exceptions']['not_found'])
RECOVERABLE = (AlreadyExists, Conflict, NotAvailable, ServiceCatalogException)
RECOVERABLE += tuple(HORIZON_CONFIG['exceptions']['recoverable'])
def error_color(msg): def error_color(msg):
return color_style().ERROR_OUTPUT(msg) return color_style().ERROR_OUTPUT(msg)
@@ -274,6 +280,13 @@ def handle_recoverable(request, message, redirect, ignore, escalate, handled,
return RecoverableError # return to normal code flow return RecoverableError # return to normal code flow
HANDLE_EXC_METHODS = [
{'exc': UNAUTHORIZED, 'handler': handle_unauthorized, 'set_wrap': False},
{'exc': NOT_FOUND, 'handler': handle_notfound, 'set_wrap': True},
{'exc': RECOVERABLE, 'handler': handle_recoverable, 'set_wrap': True},
]
def handle(request, message=None, redirect=None, ignore=False, def handle(request, message=None, redirect=None, ignore=False,
escalate=False, log_level=None, force_log=None): escalate=False, log_level=None, force_log=None):
"""Centralized error handling for Horizon. """Centralized error handling for Horizon.
@@ -303,19 +316,6 @@ def handle(request, message=None, redirect=None, ignore=False,
class indicating the type of exception that was encountered will be class indicating the type of exception that was encountered will be
returned. returned.
""" """
HORIZON_CONFIG = settings.HORIZON_CONFIG
UNAUTHORIZED = tuple(HORIZON_CONFIG['exceptions']['unauthorized'])
NOT_FOUND = tuple(HORIZON_CONFIG['exceptions']['not_found'])
RECOVERABLE = (AlreadyExists, Conflict, NotAvailable,
ServiceCatalogException)
RECOVERABLE += tuple(HORIZON_CONFIG['exceptions']['recoverable'])
HANDLE_EXC_METHODS = [
{'exc': UNAUTHORIZED, 'handler': handle_unauthorized,
'set_wrap': False},
{'exc': NOT_FOUND, 'handler': handle_notfound, 'set_wrap': True},
{'exc': RECOVERABLE, 'handler': handle_recoverable, 'set_wrap': True}
]
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
log_method = getattr(LOG, log_level or "exception") log_method = getattr(LOG, log_level or "exception")
force_log = force_log or os.environ.get("HORIZON_TEST_RUN", False) force_log = force_log or os.environ.get("HORIZON_TEST_RUN", False)

View File

@@ -20,17 +20,6 @@ import os
import socket import socket
import sys import sys
from cinderclient import exceptions as cinderclient
from glanceclient.common import exceptions as glanceclient
from heatclient import exc as heatclient
from keystoneclient import exceptions as keystoneclient
from neutronclient.common import exceptions as neutronclient
from novaclient import exceptions as novaclient
from requests import exceptions as requests
from saharaclient.api import base as saharaclient
from swiftclient import client as swiftclient
from troveclient import exceptions as troveclient
import django import django
from django.utils import html_parser from django.utils import html_parser
from openstack_dashboard.static_settings import get_staticfiles_dirs # noqa from openstack_dashboard.static_settings import get_staticfiles_dirs # noqa
@@ -146,37 +135,6 @@ HORIZON_CONFIG = {
}, },
'user_home': None, 'user_home': None,
'help_url': "http://example.com", 'help_url': "http://example.com",
'exceptions': {'recoverable': (keystoneclient.ClientException,
keystoneclient.AuthorizationFailure,
keystoneclient.Forbidden,
cinderclient.ClientException,
cinderclient.ConnectionError,
cinderclient.Forbidden,
novaclient.ClientException,
novaclient.Forbidden,
glanceclient.ClientException,
neutronclient.Forbidden,
neutronclient.NeutronClientException,
swiftclient.ClientException,
heatclient.HTTPForbidden,
heatclient.HTTPException,
troveclient.ClientException,
saharaclient.APIException,
requests.RequestException),
'not_found': (keystoneclient.NotFound,
cinderclient.NotFound,
novaclient.NotFound,
glanceclient.NotFound,
neutronclient.NotFound,
heatclient.HTTPNotFound,
troveclient.NotFound),
'unauthorized': (keystoneclient.Unauthorized,
cinderclient.Unauthorized,
novaclient.Unauthorized,
glanceclient.Unauthorized,
neutronclient.Unauthorized,
heatclient.HTTPUnauthorized,
troveclient.Unauthorized)}
} }
COMPRESS_ENABLED = True COMPRESS_ENABLED = True

View File

@@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import functools import functools
import itertools
import json import json
import logging import logging
@@ -22,6 +21,7 @@ from django.utils import decorators
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from horizon import exceptions
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@@ -31,6 +31,9 @@ class AjaxError(Exception):
self.http_status = http_status self.http_status = http_status
super(AjaxError, self).__init__(msg) super(AjaxError, self).__init__(msg)
http_errors = exceptions.UNAUTHORIZED + exceptions.NOT_FOUND + \
exceptions.RECOVERABLE + (AjaxError, )
class CreatedResponse(http.HttpResponse): class CreatedResponse(http.HttpResponse):
def __init__(self, location, data=None): def __init__(self, location, data=None):
@@ -107,8 +110,6 @@ def ajax(authenticated=True, data_required=False):
return JSONResponse('request requires JSON body', 400) return JSONResponse('request requires JSON body', 400)
# invoke the wrapped function, handling exceptions sanely # invoke the wrapped function, handling exceptions sanely
horizon_exc = settings.HORIZON_CONFIG['exceptions'].values()
api_exc = itertools.chain([AjaxError, ], *horizon_exc)
try: try:
data = function(self, request, *args, **kw) data = function(self, request, *args, **kw)
if isinstance(data, http.HttpResponse): if isinstance(data, http.HttpResponse):
@@ -116,15 +117,18 @@ def ajax(authenticated=True, data_required=False):
elif data is None: elif data is None:
return JSONResponse('', status=204) return JSONResponse('', status=204)
return JSONResponse(data) return JSONResponse(data)
except tuple(api_exc) as e: except http_errors as e:
# exception was raised with a specific HTTP status
if hasattr(e, 'http_status'): if hasattr(e, 'http_status'):
http_status = e.http_status http_status = e.http_status
elif hasattr(e, 'code'):
http_status = e.code
else: else:
http_status = getattr(e, 'code', 500) log.exception('HTTP exception with no status/code')
log.exception('API Error: %s', e) return JSONResponse(str(e), 500)
return JSONResponse(str(e), http_status) return JSONResponse(str(e), http_status)
except Exception as e: except Exception as e:
log.exception('Internal Error: %s', e) log.exception('error invoking apiclient')
return JSONResponse(str(e), 500) return JSONResponse(str(e), 500)
return _wrapped return _wrapped

View File

@@ -0,0 +1,73 @@
# Copyright 2012 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Copyright 2012 Nebula, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from cinderclient import exceptions as cinderclient
from glanceclient.common import exceptions as glanceclient
from heatclient import exc as heatclient
from keystoneclient import exceptions as keystoneclient
from neutronclient.common import exceptions as neutronclient
from novaclient import exceptions as novaclient
from requests import exceptions as requests
from saharaclient.api import base as saharaclient
from swiftclient import client as swiftclient
from troveclient import exceptions as troveclient
UNAUTHORIZED = (
keystoneclient.Unauthorized,
cinderclient.Unauthorized,
novaclient.Unauthorized,
glanceclient.Unauthorized,
neutronclient.Unauthorized,
heatclient.HTTPUnauthorized,
troveclient.Unauthorized,
)
NOT_FOUND = (
keystoneclient.NotFound,
cinderclient.NotFound,
novaclient.NotFound,
glanceclient.NotFound,
neutronclient.NotFound,
heatclient.HTTPNotFound,
troveclient.NotFound,
)
# NOTE(gabriel): This is very broad, and may need to be dialed in.
RECOVERABLE = (
keystoneclient.ClientException,
# AuthorizationFailure is raised when Keystone is "unavailable".
keystoneclient.AuthorizationFailure,
keystoneclient.Forbidden,
cinderclient.ClientException,
cinderclient.ConnectionError,
cinderclient.Forbidden,
novaclient.ClientException,
novaclient.Forbidden,
glanceclient.ClientException,
neutronclient.Forbidden,
neutronclient.NeutronClientException,
swiftclient.ClientException,
heatclient.HTTPForbidden,
heatclient.HTTPException,
troveclient.ClientException,
saharaclient.APIException,
requests.RequestException,
)

View File

@@ -2,6 +2,7 @@ import os
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from openstack_dashboard import exceptions
DEBUG = True DEBUG = True
TEMPLATE_DEBUG = DEBUG TEMPLATE_DEBUG = DEBUG
@@ -73,9 +74,9 @@ HORIZON_CONFIG = {
'types': ['alert-success', 'alert-info'] 'types': ['alert-success', 'alert-info']
}, },
'help_url': "http://docs.openstack.org", 'help_url': "http://docs.openstack.org",
'exceptions': {'recoverable': [], 'exceptions': {'recoverable': exceptions.RECOVERABLE,
'not_found': [], 'not_found': exceptions.NOT_FOUND,
'unauthorized': []}, 'unauthorized': exceptions.UNAUTHORIZED},
'modal_backdrop': 'static', 'modal_backdrop': 'static',
'angular_modules': [], 'angular_modules': [],
'js_files': [], 'js_files': [],

View File

@@ -21,20 +21,10 @@ import os
import sys import sys
import warnings import warnings
from cinderclient import exceptions as cinderclient
from glanceclient.common import exceptions as glanceclient
from heatclient import exc as heatclient
from keystoneclient import exceptions as keystoneclient
from neutronclient.common import exceptions as neutronclient
from novaclient import exceptions as novaclient
from requests import exceptions as requests
from saharaclient.api import base as saharaclient
from swiftclient import client as swiftclient
from troveclient import exceptions as troveclient
import django import django
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from openstack_dashboard import exceptions
from openstack_dashboard.static_settings import get_staticfiles_dirs # noqa from openstack_dashboard.static_settings import get_staticfiles_dirs # noqa
@@ -69,37 +59,9 @@ HORIZON_CONFIG = {
'types': ['alert-success', 'alert-info'] 'types': ['alert-success', 'alert-info']
}, },
'help_url': "http://docs.openstack.org", 'help_url': "http://docs.openstack.org",
'exceptions': {'recoverable': (keystoneclient.ClientException, 'exceptions': {'recoverable': exceptions.RECOVERABLE,
keystoneclient.AuthorizationFailure, 'not_found': exceptions.NOT_FOUND,
keystoneclient.Forbidden, 'unauthorized': exceptions.UNAUTHORIZED},
cinderclient.ClientException,
cinderclient.ConnectionError,
cinderclient.Forbidden,
novaclient.ClientException,
novaclient.Forbidden,
glanceclient.ClientException,
neutronclient.Forbidden,
neutronclient.NeutronClientException,
swiftclient.ClientException,
heatclient.HTTPForbidden,
heatclient.HTTPException,
troveclient.ClientException,
saharaclient.APIException,
requests.RequestException),
'not_found': (keystoneclient.NotFound,
cinderclient.NotFound,
novaclient.NotFound,
glanceclient.NotFound,
neutronclient.NotFound,
heatclient.HTTPNotFound,
troveclient.NotFound),
'unauthorized': (keystoneclient.Unauthorized,
cinderclient.Unauthorized,
novaclient.Unauthorized,
glanceclient.Unauthorized,
neutronclient.Unauthorized,
heatclient.HTTPUnauthorized,
troveclient.Unauthorized)},
'angular_modules': [], 'angular_modules': [],
'js_files': [], 'js_files': [],
'js_spec_files': [], 'js_spec_files': [],

View File

@@ -12,19 +12,9 @@
import os import os
from cinderclient import exceptions as cinderclient
from glanceclient.common import exceptions as glanceclient
from heatclient import exc as heatclient
from keystoneclient import exceptions as keystoneclient
from neutronclient.common import exceptions as neutronclient
from novaclient import exceptions as novaclient
from requests import exceptions as requests
from saharaclient.api import base as saharaclient
from swiftclient import client as swiftclient
from troveclient import exceptions as troveclient
from horizon.test.settings import * # noqa from horizon.test.settings import * # noqa
from horizon.utils import secret_key from horizon.utils import secret_key
from openstack_dashboard import exceptions
from openstack_dashboard.static_settings import get_staticfiles_dirs # noqa from openstack_dashboard.static_settings import get_staticfiles_dirs # noqa
STATICFILES_DIRS = get_staticfiles_dirs() STATICFILES_DIRS = get_staticfiles_dirs()
@@ -76,39 +66,11 @@ HORIZON_CONFIG = {
}, },
'user_home': None, 'user_home': None,
'help_url': "http://docs.openstack.org", 'help_url': "http://docs.openstack.org",
'exceptions': {'recoverable': exceptions.RECOVERABLE,
'not_found': exceptions.NOT_FOUND,
'unauthorized': exceptions.UNAUTHORIZED},
'angular_modules': [], 'angular_modules': [],
'js_files': [], 'js_files': [],
'exceptions': {'recoverable': (keystoneclient.ClientException,
keystoneclient.AuthorizationFailure,
keystoneclient.Forbidden,
cinderclient.ClientException,
cinderclient.ConnectionError,
cinderclient.Forbidden,
novaclient.ClientException,
novaclient.Forbidden,
glanceclient.ClientException,
neutronclient.Forbidden,
neutronclient.NeutronClientException,
swiftclient.ClientException,
heatclient.HTTPForbidden,
heatclient.HTTPException,
troveclient.ClientException,
saharaclient.APIException,
requests.RequestException),
'not_found': (keystoneclient.NotFound,
cinderclient.NotFound,
novaclient.NotFound,
glanceclient.NotFound,
neutronclient.NotFound,
heatclient.HTTPNotFound,
troveclient.NotFound),
'unauthorized': (keystoneclient.Unauthorized,
cinderclient.Unauthorized,
novaclient.Unauthorized,
glanceclient.Unauthorized,
neutronclient.Unauthorized,
heatclient.HTTPUnauthorized,
troveclient.Unauthorized)},
} }
# Set to True to allow users to upload images to glance via Horizon server. # Set to True to allow users to upload images to glance via Horizon server.