1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #1683: Replaced default 500 handler with custom middleware to provide preliminary troubleshooting assistance

This commit is contained in:
Jeremy Stretch
2017-11-03 13:24:31 -04:00
parent f2fbd92f78
commit f77bf72de8
8 changed files with 101 additions and 32 deletions

View File

@ -148,6 +148,7 @@ MIDDLEWARE = (
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'utilities.middleware.ExceptionHandlingMiddleware',
'utilities.middleware.LoginRequiredMiddleware', 'utilities.middleware.LoginRequiredMiddleware',
'utilities.middleware.APIVersionMiddleware', 'utilities.middleware.APIVersionMiddleware',
) )

View File

@ -7,11 +7,10 @@ from django.conf.urls import include, url
from django.contrib import admin from django.contrib import admin
from django.views.static import serve 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 from users.views import LoginView, LogoutView
handler500 = handle_500
swagger_view = get_swagger_view(title='NetBox API') swagger_view = get_swagger_view(title='NetBox API')
_patterns = [ _patterns = [
@ -48,9 +47,6 @@ _patterns = [
# Serving static media in Django to pipe it through LoginRequiredMiddleware # Serving static media in Django to pipe it through LoginRequiredMiddleware
url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}), url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
# Error testing
url(r'^500/$', trigger_500),
# Admin # Admin
url(r'^admin/', admin.site.urls), url(r'^admin/', admin.site.urls),

View File

@ -247,23 +247,3 @@ class APIRootView(APIView):
('tenancy', reverse('tenancy-api:api-root', request=request, format=format)), ('tenancy', reverse('tenancy-api:api-root', request=request, format=format)),
('virtualization', reverse('virtualization-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."
)

View File

@ -12,7 +12,7 @@
<body> <body>
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div class="col-md-4 col-md-offset-4"> <div class="col-md-6 col-md-offset-3">
<div class="panel panel-danger" style="margin-top: 200px"> <div class="panel panel-danger" style="margin-top: 200px">
<div class="panel-heading"> <div class="panel-heading">
<strong> <strong>
@ -21,13 +21,20 @@
</strong> </strong>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<p>There was a problem with your request. This error has been logged and administrative staff have {% block message %}
been notified. Please return to the home page and try again.</p> <p>
<p>If you are responsible for this installation, please consider There was a problem with your request. Please contact an administrator.
<a href="https://github.com/digitalocean/netbox/issues">filing a bug report</a>. Additional </p>
information is provided below:</p> {% endblock %}
<hr />
<p>
The complete exception is provided below:
</p>
<pre><strong>{{ exception }}</strong><br /> <pre><strong>{{ exception }}</strong><br />
{{ error }}</pre> {{ error }}</pre>
<p>
If further assistance is required, please post to the <a href="https://groups.google.com/forum/#!forum/netbox-discuss">NetBox mailing list</a>.
</p>
<div class="text-right"> <div class="text-right">
<a href="{% url 'home' %}" class="btn btn-primary">Home Page</a> <a href="{% url 'home' %}" class="btn btn-primary">Home Page</a>
</div> </div>

View File

@ -0,0 +1,18 @@
{% extends '500.html' %}
{% block message %}
<p>
A module import error occurred during this request. Common causes include the following:
</p>
<p>
<i class="fa fa-warning"></i> <strong>Missing required packages</strong> - This installation of NetBox might be missing one or more required
Python packages. These packages are listed in <code>requirements.txt</code> and are normally installed as part
of the installation or upgrade process. To verify installed packages, run <code>pip freeze</code> from the
console and compare the output to the list of required packages.
</p>
<p>
<i class="fa fa-warning"></i> <strong>WSGI service not restarted after upgrade</strong> - 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.
</p>
{% endblock %}

View File

@ -0,0 +1,12 @@
{% extends '500.html' %}
{% block message %}
<p>
A file permission error was detected while processing this request. Common causes include the following:
</p>
<p>
<i class="fa fa-warning"></i> <strong>Insufficient write permission to the media root</strong> - The configured
media root is <code>{{ settings.MEDIA_ROOT }}</code>. Ensure that the user NetBox runs as has access to write
files to all locations within this path.
</p>
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends '500.html' %}
{% block message %}
<p>
A database programming error was detected while processing this request. Common causes include the following:
</p>
<p>
<i class="fa fa-warning"></i> <strong>Database migrations missing</strong> - 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
<code>python3 manage.py migrate</code> from the command line.
</p>
<p>
<i class="fa fa-warning"></i> <strong>Unsupported PostgreSQL version</strong> - 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
<code>SELECT VERSION()</code>.
</p>
{% endblock %}

View File

@ -1,7 +1,10 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import sys
from django.http import HttpResponseRedirect
from django.conf import settings 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 from django.urls import reverse
@ -39,3 +42,38 @@ class APIVersionMiddleware(object):
if request.path_info.startswith(api_path): if request.path_info.startswith(api_path):
response['API-Version'] = settings.REST_FRAMEWORK_VERSION response['API-Version'] = settings.REST_FRAMEWORK_VERSION
return response 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)