From f77bf72de824bd86a60feb61ebb9b13264f5f9d5 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 3 Nov 2017 13:24:31 -0400 Subject: [PATCH] Closes #1683: Replaced default 500 handler with custom middleware to provide preliminary troubleshooting assistance --- netbox/netbox/settings.py | 1 + netbox/netbox/urls.py | 6 +-- netbox/netbox/views.py | 20 ---------- netbox/templates/500.html | 19 ++++++--- netbox/templates/exceptions/import_error.html | 18 +++++++++ .../exceptions/permission_error.html | 12 ++++++ .../exceptions/programming_error.html | 17 ++++++++ netbox/utilities/middleware.py | 40 ++++++++++++++++++- 8 files changed, 101 insertions(+), 32 deletions(-) create mode 100644 netbox/templates/exceptions/import_error.html create mode 100644 netbox/templates/exceptions/permission_error.html create mode 100644 netbox/templates/exceptions/programming_error.html diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 0283731fe..d4fbc2359 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -148,6 +148,7 @@ MIDDLEWARE = ( 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.security.SecurityMiddleware', + 'utilities.middleware.ExceptionHandlingMiddleware', 'utilities.middleware.LoginRequiredMiddleware', 'utilities.middleware.APIVersionMiddleware', ) diff --git a/netbox/netbox/urls.py b/netbox/netbox/urls.py index 1c8051c06..3c0f8de9f 100644 --- a/netbox/netbox/urls.py +++ b/netbox/netbox/urls.py @@ -7,11 +7,10 @@ from django.conf.urls import include, url from django.contrib import admin from django.views.static import serve -from netbox.views import APIRootView, handle_500, HomeView, SearchView, trigger_500 +from netbox.views import APIRootView, HomeView, SearchView from users.views import LoginView, LogoutView -handler500 = handle_500 swagger_view = get_swagger_view(title='NetBox API') _patterns = [ @@ -48,9 +47,6 @@ _patterns = [ # Serving static media in Django to pipe it through LoginRequiredMiddleware url(r'^media/(?P.*)$', serve, {'document_root': settings.MEDIA_ROOT}), - # Error testing - url(r'^500/$', trigger_500), - # Admin url(r'^admin/', admin.site.urls), diff --git a/netbox/netbox/views.py b/netbox/netbox/views.py index f41ff53c2..ce1171235 100644 --- a/netbox/netbox/views.py +++ b/netbox/netbox/views.py @@ -247,23 +247,3 @@ class APIRootView(APIView): ('tenancy', reverse('tenancy-api:api-root', request=request, format=format)), ('virtualization', reverse('virtualization-api:api-root', request=request, format=format)), ))) - - -def handle_500(request): - """ - Custom server error handler - """ - type_, error, traceback = sys.exc_info() - return render(request, '500.html', { - 'exception': str(type_), - 'error': error, - }, status=500) - - -def trigger_500(request): - """ - Hot-wired method of triggering a server error to test reporting - """ - raise Exception( - "Congratulations, you've triggered an exception! Go tell all your friends what an exceptional person you are." - ) diff --git a/netbox/templates/500.html b/netbox/templates/500.html index 2857325b9..1da608a48 100644 --- a/netbox/templates/500.html +++ b/netbox/templates/500.html @@ -12,7 +12,7 @@
-
+
@@ -21,13 +21,20 @@
-

There was a problem with your request. This error has been logged and administrative staff have - been notified. Please return to the home page and try again.

-

If you are responsible for this installation, please consider - filing a bug report. Additional - information is provided below:

+ {% block message %} +

+ There was a problem with your request. Please contact an administrator. +

+ {% endblock %} +
+

+ The complete exception is provided below: +

{{ exception }}
{{ error }}
+

+ If further assistance is required, please post to the NetBox mailing list. +

diff --git a/netbox/templates/exceptions/import_error.html b/netbox/templates/exceptions/import_error.html new file mode 100644 index 000000000..20dc3728b --- /dev/null +++ b/netbox/templates/exceptions/import_error.html @@ -0,0 +1,18 @@ +{% extends '500.html' %} + +{% block message %} +

+ A module import error occurred during this request. Common causes include the following: +

+

+ Missing required packages - This installation of NetBox might be missing one or more required + Python packages. These packages are listed in requirements.txt and are normally installed as part + of the installation or upgrade process. To verify installed packages, run pip freeze from the + console and compare the output to the list of required packages. +

+

+ WSGI service not restarted after upgrade - If this installation has recently been upgraded, + check that the WSGI service (e.g. gunicorn or uWSGI) has been restarted. This ensures that the new code is + running. +

+{% endblock %} diff --git a/netbox/templates/exceptions/permission_error.html b/netbox/templates/exceptions/permission_error.html new file mode 100644 index 000000000..9898f25dc --- /dev/null +++ b/netbox/templates/exceptions/permission_error.html @@ -0,0 +1,12 @@ +{% extends '500.html' %} + +{% block message %} +

+ A file permission error was detected while processing this request. Common causes include the following: +

+

+ Insufficient write permission to the media root - The configured + media root is {{ settings.MEDIA_ROOT }}. Ensure that the user NetBox runs as has access to write + files to all locations within this path. +

+{% endblock %} diff --git a/netbox/templates/exceptions/programming_error.html b/netbox/templates/exceptions/programming_error.html new file mode 100644 index 000000000..6f10c2e27 --- /dev/null +++ b/netbox/templates/exceptions/programming_error.html @@ -0,0 +1,17 @@ +{% extends '500.html' %} + +{% block message %} +

+ A database programming error was detected while processing this request. Common causes include the following: +

+

+ Database migrations missing - When upgrading to a new NetBox release, the upgrade script must + be run to apply any new database migrations. You can run migrations manually by executing + python3 manage.py migrate from the command line. +

+

+ Unsupported PostgreSQL version - Ensure that PostgreSQL version 9.4 or higher is in use. You + can check this by connecting to the database using NetBox's credentials and issuing a query for + SELECT VERSION(). +

+{% endblock %} diff --git a/netbox/utilities/middleware.py b/netbox/utilities/middleware.py index d5d151c12..b79ecd041 100644 --- a/netbox/utilities/middleware.py +++ b/netbox/utilities/middleware.py @@ -1,7 +1,10 @@ from __future__ import unicode_literals +import sys -from django.http import HttpResponseRedirect from django.conf import settings +from django.db import ProgrammingError +from django.http import HttpResponseRedirect +from django.shortcuts import render from django.urls import reverse @@ -39,3 +42,38 @@ class APIVersionMiddleware(object): if request.path_info.startswith(api_path): response['API-Version'] = settings.REST_FRAMEWORK_VERSION return response + + +class ExceptionHandlingMiddleware(object): + """ + Intercept certain exceptions which are likely indicative of installation issues and provide helpful instructions + to the user. + """ + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + return self.get_response(request) + + def process_exception(self, request, exception): + + # Raise exceptions if in debug mode + if settings.DEBUG: + raise exception + + # Determine the type of exception + if isinstance(exception, ProgrammingError): + template_name = 'exceptions/programming_error.html' + elif isinstance(exception, ImportError): + template_name = 'exceptions/import_error.html' + elif isinstance(exception, PermissionError): + template_name = 'exceptions/permission_error.html' + else: + template_name = '500.html' + + # Return an error message + type_, error, traceback = sys.exc_info() + return render(request, template_name, { + 'exception': str(type_), + 'error': error, + }, status=500)