Merge "Revert "Refactoring the exceptions lists""
This commit is contained in:
commit
0fb9a982e7
@ -23,6 +23,12 @@ class LazySettings(LazyObject):
|
||||
HORIZON_CONFIG = copy.copy(DEFAULT_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...
|
||||
if 'regex' not in HORIZON_CONFIG['password_validator']:
|
||||
default_pw_regex = DEFAULT_CONFIG['password_validator']['regex']
|
||||
|
@ -31,6 +31,11 @@ HORIZON_CONFIG = {
|
||||
# URL for additional help with this site.
|
||||
'help_url': None,
|
||||
|
||||
# Exception configuration.
|
||||
'exceptions': {'unauthorized': [],
|
||||
'not_found': [],
|
||||
'recoverable': []},
|
||||
|
||||
# Password configuration.
|
||||
'password_validator': {'regex': '.*',
|
||||
'help_text': _("Password is not accepted")},
|
||||
|
@ -22,7 +22,6 @@ import sys
|
||||
|
||||
import six
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management import color_style # noqa
|
||||
from django.http import HttpRequest # noqa
|
||||
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 SafeExceptionReporterFilter # noqa
|
||||
|
||||
from horizon.conf import HORIZON_CONFIG # noqa
|
||||
from horizon import messages
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -202,6 +202,12 @@ class HandledException(HorizonException):
|
||||
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):
|
||||
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
|
||||
|
||||
|
||||
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,
|
||||
escalate=False, log_level=None, force_log=None):
|
||||
"""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
|
||||
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()
|
||||
log_method = getattr(LOG, log_level or "exception")
|
||||
force_log = force_log or os.environ.get("HORIZON_TEST_RUN", False)
|
||||
|
@ -20,17 +20,6 @@ import os
|
||||
import socket
|
||||
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
|
||||
from django.utils import html_parser
|
||||
from openstack_dashboard.static_settings import get_staticfiles_dirs # noqa
|
||||
@ -146,37 +135,6 @@ HORIZON_CONFIG = {
|
||||
},
|
||||
'user_home': None,
|
||||
'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
|
||||
|
@ -12,7 +12,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import functools
|
||||
import itertools
|
||||
import json
|
||||
import logging
|
||||
|
||||
@ -22,6 +21,7 @@ from django.utils import decorators
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from horizon import exceptions
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -31,6 +31,9 @@ class AjaxError(Exception):
|
||||
self.http_status = http_status
|
||||
super(AjaxError, self).__init__(msg)
|
||||
|
||||
http_errors = exceptions.UNAUTHORIZED + exceptions.NOT_FOUND + \
|
||||
exceptions.RECOVERABLE + (AjaxError, )
|
||||
|
||||
|
||||
class CreatedResponse(http.HttpResponse):
|
||||
def __init__(self, location, data=None):
|
||||
@ -107,8 +110,6 @@ def ajax(authenticated=True, data_required=False):
|
||||
return JSONResponse('request requires JSON body', 400)
|
||||
|
||||
# invoke the wrapped function, handling exceptions sanely
|
||||
horizon_exc = settings.HORIZON_CONFIG['exceptions'].values()
|
||||
api_exc = itertools.chain([AjaxError, ], *horizon_exc)
|
||||
try:
|
||||
data = function(self, request, *args, **kw)
|
||||
if isinstance(data, http.HttpResponse):
|
||||
@ -116,15 +117,18 @@ def ajax(authenticated=True, data_required=False):
|
||||
elif data is None:
|
||||
return JSONResponse('', status=204)
|
||||
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'):
|
||||
http_status = e.http_status
|
||||
elif hasattr(e, 'code'):
|
||||
http_status = e.code
|
||||
else:
|
||||
http_status = getattr(e, 'code', 500)
|
||||
log.exception('API Error: %s', e)
|
||||
log.exception('HTTP exception with no status/code')
|
||||
return JSONResponse(str(e), 500)
|
||||
return JSONResponse(str(e), http_status)
|
||||
except Exception as e:
|
||||
log.exception('Internal Error: %s', e)
|
||||
log.exception('error invoking apiclient')
|
||||
return JSONResponse(str(e), 500)
|
||||
|
||||
return _wrapped
|
||||
|
73
openstack_dashboard/exceptions.py
Normal file
73
openstack_dashboard/exceptions.py
Normal 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,
|
||||
)
|
@ -2,6 +2,7 @@ import os
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from openstack_dashboard import exceptions
|
||||
|
||||
DEBUG = True
|
||||
TEMPLATE_DEBUG = DEBUG
|
||||
@ -73,9 +74,9 @@ HORIZON_CONFIG = {
|
||||
'types': ['alert-success', 'alert-info']
|
||||
},
|
||||
'help_url': "http://docs.openstack.org",
|
||||
'exceptions': {'recoverable': [],
|
||||
'not_found': [],
|
||||
'unauthorized': []},
|
||||
'exceptions': {'recoverable': exceptions.RECOVERABLE,
|
||||
'not_found': exceptions.NOT_FOUND,
|
||||
'unauthorized': exceptions.UNAUTHORIZED},
|
||||
'modal_backdrop': 'static',
|
||||
'angular_modules': [],
|
||||
'js_files': [],
|
||||
|
@ -21,20 +21,10 @@ import os
|
||||
import sys
|
||||
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
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from openstack_dashboard import exceptions
|
||||
from openstack_dashboard.static_settings import get_staticfiles_dirs # noqa
|
||||
|
||||
|
||||
@ -69,37 +59,9 @@ HORIZON_CONFIG = {
|
||||
'types': ['alert-success', 'alert-info']
|
||||
},
|
||||
'help_url': "http://docs.openstack.org",
|
||||
'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)},
|
||||
'exceptions': {'recoverable': exceptions.RECOVERABLE,
|
||||
'not_found': exceptions.NOT_FOUND,
|
||||
'unauthorized': exceptions.UNAUTHORIZED},
|
||||
'angular_modules': [],
|
||||
'js_files': [],
|
||||
'js_spec_files': [],
|
||||
|
@ -12,19 +12,9 @@
|
||||
|
||||
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.utils import secret_key
|
||||
from openstack_dashboard import exceptions
|
||||
from openstack_dashboard.static_settings import get_staticfiles_dirs # noqa
|
||||
|
||||
STATICFILES_DIRS = get_staticfiles_dirs()
|
||||
@ -76,39 +66,11 @@ HORIZON_CONFIG = {
|
||||
},
|
||||
'user_home': None,
|
||||
'help_url': "http://docs.openstack.org",
|
||||
'exceptions': {'recoverable': exceptions.RECOVERABLE,
|
||||
'not_found': exceptions.NOT_FOUND,
|
||||
'unauthorized': exceptions.UNAUTHORIZED},
|
||||
'angular_modules': [],
|
||||
'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.
|
||||
|
Loading…
Reference in New Issue
Block a user