We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
v2.2.0 fails to run; returns ImproperlyConfigured
### Issue type
[ ] Feature request <!-- Requesting the implementation of a new feature -->
[x] Bug report      <!-- Reporting unexpected or erroneous behavior -->
[ ] Documentation   <!-- Proposing a modification to the documentation -->


### Environment
* Python version:  3.4.3
* NetBox version:  2.2.0


### Description
The NetBox WSGI service fails to start, returning the following error:

```
ImproperlyConfigured: Requested setting DATABASES, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
```

This issue has been traced to code intended to verify the PostgreSQL database version during initialization. However, the required `settings` variable is not available at the time of execution.

This issues does not affect the development server (`manage.py runserver`).

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `netbox/netbox/__init__.py`
Content:
```
1 from distutils.version import StrictVersion
2 
3 from django.db import connection
4 from django.db.utils import OperationalError
5 
6 
7 # NetBox v2.2 and later requires PostgreSQL 9.4 or higher.
8 try:
9     with connection.cursor() as cursor:
10         cursor.execute("SELECT VERSION()")
11         row = cursor.fetchone()
12         pg_version = row[0].split()[1]
13         if StrictVersion(pg_version) < StrictVersion('9.4.0'):
14             raise Exception("PostgreSQL 9.4.0 or higher is required. ({} found)".format(pg_version))
15 
16 # Skip if the database is missing (e.g. for CI testing) or misconfigured.
17 except OperationalError:
18     pass
19
```

Path: `netbox/netbox/settings.py`
Content:
```
1 import logging
2 import os
3 import socket
4 
5 from django.contrib.messages import constants as messages
6 from django.core.exceptions import ImproperlyConfigured
7 
8 try:
9     from netbox import configuration
10 except ImportError:
11     raise ImproperlyConfigured(
12         "Configuration file is not present. Please define netbox/netbox/configuration.py per the documentation."
13     )
14 
15 
16 VERSION = '2.2.0'
17 
18 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
19 
20 # Import required configuration parameters
21 ALLOWED_HOSTS = DATABASE = SECRET_KEY = None
22 for setting in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY']:
23     try:
24         globals()[setting] = getattr(configuration, setting)
25     except AttributeError:
26         raise ImproperlyConfigured(
27             "Mandatory setting {} is missing from configuration.py.".format(setting)
28         )
29 
30 # Import optional configuration parameters
31 ADMINS = getattr(configuration, 'ADMINS', [])
32 BANNER_BOTTOM = getattr(configuration, 'BANNER_BOTTOM', '')
33 BANNER_LOGIN = getattr(configuration, 'BANNER_LOGIN', '')
34 BANNER_TOP = getattr(configuration, 'BANNER_TOP', '')
35 BASE_PATH = getattr(configuration, 'BASE_PATH', '')
36 if BASE_PATH:
37     BASE_PATH = BASE_PATH.strip('/') + '/'  # Enforce trailing slash only
38 CORS_ORIGIN_ALLOW_ALL = getattr(configuration, 'CORS_ORIGIN_ALLOW_ALL', False)
39 CORS_ORIGIN_REGEX_WHITELIST = getattr(configuration, 'CORS_ORIGIN_REGEX_WHITELIST', [])
40 CORS_ORIGIN_WHITELIST = getattr(configuration, 'CORS_ORIGIN_WHITELIST', [])
41 DATE_FORMAT = getattr(configuration, 'DATE_FORMAT', 'N j, Y')
42 DATETIME_FORMAT = getattr(configuration, 'DATETIME_FORMAT', 'N j, Y g:i a')
43 DEBUG = getattr(configuration, 'DEBUG', False)
44 ENFORCE_GLOBAL_UNIQUE = getattr(configuration, 'ENFORCE_GLOBAL_UNIQUE', False)
45 EMAIL = getattr(configuration, 'EMAIL', {})
46 LOGGING = getattr(configuration, 'LOGGING', {})
47 LOGIN_REQUIRED = getattr(configuration, 'LOGIN_REQUIRED', False)
48 MAINTENANCE_MODE = getattr(configuration, 'MAINTENANCE_MODE', False)
49 MAX_PAGE_SIZE = getattr(configuration, 'MAX_PAGE_SIZE', 1000)
50 MEDIA_ROOT = getattr(configuration, 'MEDIA_ROOT', os.path.join(BASE_DIR, 'media')).rstrip('/')
51 NAPALM_USERNAME = getattr(configuration, 'NAPALM_USERNAME', '')
52 NAPALM_PASSWORD = getattr(configuration, 'NAPALM_PASSWORD', '')
53 NAPALM_TIMEOUT = getattr(configuration, 'NAPALM_TIMEOUT', 30)
54 NAPALM_ARGS = getattr(configuration, 'NAPALM_ARGS', {})
55 PAGINATE_COUNT = getattr(configuration, 'PAGINATE_COUNT', 50)
56 PREFER_IPV4 = getattr(configuration, 'PREFER_IPV4', False)
57 REPORTS_ROOT = getattr(configuration, 'REPORTS_ROOT', os.path.join(BASE_DIR, 'reports')).rstrip('/')
58 SHORT_DATE_FORMAT = getattr(configuration, 'SHORT_DATE_FORMAT', 'Y-m-d')
59 SHORT_DATETIME_FORMAT = getattr(configuration, 'SHORT_DATETIME_FORMAT', 'Y-m-d H:i')
60 SHORT_TIME_FORMAT = getattr(configuration, 'SHORT_TIME_FORMAT', 'H:i:s')
61 TIME_FORMAT = getattr(configuration, 'TIME_FORMAT', 'g:i a')
62 TIME_ZONE = getattr(configuration, 'TIME_ZONE', 'UTC')
63 
64 CSRF_TRUSTED_ORIGINS = ALLOWED_HOSTS
65 
66 # Attempt to import LDAP configuration if it has been defined
67 LDAP_IGNORE_CERT_ERRORS = False
68 try:
69     from netbox.ldap_config import *
70     LDAP_CONFIGURED = True
71 except ImportError:
72     LDAP_CONFIGURED = False
73 
74 # LDAP configuration (optional)
75 if LDAP_CONFIGURED:
76     try:
77         import ldap
78         import django_auth_ldap
79         # Prepend LDAPBackend to the default ModelBackend
80         AUTHENTICATION_BACKENDS = [
81             'django_auth_ldap.backend.LDAPBackend',
82             'django.contrib.auth.backends.ModelBackend',
83         ]
84         # Optionally disable strict certificate checking
85         if LDAP_IGNORE_CERT_ERRORS:
86             ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
87         # Enable logging for django_auth_ldap
88         ldap_logger = logging.getLogger('django_auth_ldap')
89         ldap_logger.addHandler(logging.StreamHandler())
90         ldap_logger.setLevel(logging.DEBUG)
91     except ImportError:
92         raise ImproperlyConfigured(
93             "LDAP authentication has been configured, but django-auth-ldap is not installed. You can remove "
94             "netbox/ldap_config.py to disable LDAP."
95         )
96 
97 # Database
98 configuration.DATABASE.update({'ENGINE': 'django.db.backends.postgresql'})
99 DATABASES = {
100     'default': configuration.DATABASE,
101 }
102 
103 # Email
104 EMAIL_HOST = EMAIL.get('SERVER')
105 EMAIL_PORT = EMAIL.get('PORT', 25)
106 EMAIL_HOST_USER = EMAIL.get('USERNAME')
107 EMAIL_HOST_PASSWORD = EMAIL.get('PASSWORD')
108 EMAIL_TIMEOUT = EMAIL.get('TIMEOUT', 10)
109 SERVER_EMAIL = EMAIL.get('FROM_EMAIL')
110 EMAIL_SUBJECT_PREFIX = '[NetBox] '
111 
112 # Installed applications
113 INSTALLED_APPS = (
114     'django.contrib.admin',
115     'django.contrib.auth',
116     'django.contrib.contenttypes',
117     'django.contrib.sessions',
118     'django.contrib.messages',
119     'django.contrib.staticfiles',
120     'django.contrib.humanize',
121     'corsheaders',
122     'debug_toolbar',
123     'django_filters',
124     'django_tables2',
125     'mptt',
126     'rest_framework',
127     'rest_framework_swagger',
128     'circuits',
129     'dcim',
130     'ipam',
131     'extras',
132     'secrets',
133     'tenancy',
134     'users',
135     'utilities',
136     'virtualization',
137 )
138 
139 # Middleware
140 MIDDLEWARE = (
141     'debug_toolbar.middleware.DebugToolbarMiddleware',
142     'corsheaders.middleware.CorsMiddleware',
143     'django.contrib.sessions.middleware.SessionMiddleware',
144     'django.middleware.common.CommonMiddleware',
145     'django.middleware.csrf.CsrfViewMiddleware',
146     'django.contrib.auth.middleware.AuthenticationMiddleware',
147     'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
148     'django.contrib.messages.middleware.MessageMiddleware',
149     'django.middleware.clickjacking.XFrameOptionsMiddleware',
150     'django.middleware.security.SecurityMiddleware',
151     'utilities.middleware.LoginRequiredMiddleware',
152     'utilities.middleware.APIVersionMiddleware',
153 )
154 
155 ROOT_URLCONF = 'netbox.urls'
156 
157 TEMPLATES = [
158     {
159         'BACKEND': 'django.template.backends.django.DjangoTemplates',
160         'DIRS': [BASE_DIR + '/templates/'],
161         'APP_DIRS': True,
162         'OPTIONS': {
163             'context_processors': [
164                 'django.template.context_processors.debug',
165                 'django.template.context_processors.request',
166                 'django.template.context_processors.media',
167                 'django.contrib.auth.context_processors.auth',
168                 'django.contrib.messages.context_processors.messages',
169                 'utilities.context_processors.settings',
170             ],
171         },
172     },
173 ]
174 
175 # WSGI
176 WSGI_APPLICATION = 'netbox.wsgi.application'
177 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
178 USE_X_FORWARDED_HOST = True
179 
180 # Internationalization
181 LANGUAGE_CODE = 'en-us'
182 USE_I18N = True
183 USE_TZ = True
184 
185 # Static files (CSS, JavaScript, Images)
186 STATIC_ROOT = BASE_DIR + '/static/'
187 STATIC_URL = '/{}static/'.format(BASE_PATH)
188 STATICFILES_DIRS = (
189     os.path.join(BASE_DIR, "project-static"),
190 )
191 
192 # Media
193 MEDIA_URL = '/{}media/'.format(BASE_PATH)
194 
195 # Disable default limit of 1000 fields per request. Needed for bulk deletion of objects. (Added in Django 1.10.)
196 DATA_UPLOAD_MAX_NUMBER_FIELDS = None
197 
198 # Messages
199 MESSAGE_TAGS = {
200     messages.ERROR: 'danger',
201 }
202 
203 # Authentication URLs
204 LOGIN_URL = '/{}login/'.format(BASE_PATH)
205 
206 # Secrets
207 SECRETS_MIN_PUBKEY_SIZE = 2048
208 
209 # Django REST framework (API)
210 REST_FRAMEWORK_VERSION = VERSION[0:3]  # Use major.minor as API version
211 REST_FRAMEWORK = {
212     'ALLOWED_VERSIONS': [REST_FRAMEWORK_VERSION],
213     'DEFAULT_AUTHENTICATION_CLASSES': (
214         'rest_framework.authentication.SessionAuthentication',
215         'netbox.api.TokenAuthentication',
216     ),
217     'DEFAULT_FILTER_BACKENDS': (
218         'django_filters.rest_framework.DjangoFilterBackend',
219     ),
220     'DEFAULT_PAGINATION_CLASS': 'netbox.api.OptionalLimitOffsetPagination',
221     'DEFAULT_PERMISSION_CLASSES': (
222         'netbox.api.TokenPermissions',
223     ),
224     'DEFAULT_RENDERER_CLASSES': (
225         'rest_framework.renderers.JSONRenderer',
226         'netbox.api.FormlessBrowsableAPIRenderer',
227     ),
228     'DEFAULT_VERSION': REST_FRAMEWORK_VERSION,
229     'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning',
230     'PAGE_SIZE': PAGINATE_COUNT,
231     'VIEW_NAME_FUNCTION': 'netbox.api.get_view_name',
232 }
233 
234 # Django debug toolbar
235 INTERNAL_IPS = (
236     '127.0.0.1',
237     '::1',
238 )
239 
240 
241 try:
242     HOSTNAME = socket.gethostname()
243 except:
244     HOSTNAME = 'localhost'
245
```

Path: `netbox/extras/migrations/0008_reports.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # Generated by Django 1.11.4 on 2017-09-26 21:25
3 from __future__ import unicode_literals
4 
5 from django.conf import settings
6 import django.contrib.postgres.fields.jsonb
7 from django.db import migrations, models
8 import django.db.models.deletion
9 
10 
11 class Migration(migrations.Migration):
12 
13     dependencies = [
14         migrations.swappable_dependency(settings.AUTH_USER_MODEL),
15         ('extras', '0007_unicode_literals'),
16     ]
17 
18     operations = [
19         migrations.CreateModel(
20             name='ReportResult',
21             fields=[
22                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
23                 ('report', models.CharField(max_length=255, unique=True)),
24                 ('created', models.DateTimeField(auto_now_add=True)),
25                 ('failed', models.BooleanField()),
26                 ('data', django.contrib.postgres.fields.jsonb.JSONField()),
27                 ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
28             ],
29             options={
30                 'ordering': ['report'],
31             },
32         ),
33     ]
34
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/netbox/extras/migrations/0008_reports.py b/netbox/extras/migrations/0008_reports.py
--- a/netbox/extras/migrations/0008_reports.py
+++ b/netbox/extras/migrations/0008_reports.py
@@ -1,11 +1,30 @@
 # -*- coding: utf-8 -*-
 # Generated by Django 1.11.4 on 2017-09-26 21:25
 from __future__ import unicode_literals
+from distutils.version import StrictVersion
 
 from django.conf import settings
 import django.contrib.postgres.fields.jsonb
-from django.db import migrations, models
+from django.db import connection, migrations, models
 import django.db.models.deletion
+from django.db.utils import OperationalError
+
+
+def verify_postgresql_version(apps, schema_editor):
+    """
+    Verify that PostgreSQL is version 9.4 or higher.
+    """
+    try:
+        with connection.cursor() as cursor:
+            cursor.execute("SELECT VERSION()")
+            row = cursor.fetchone()
+            pg_version = row[0].split()[1]
+            if StrictVersion(pg_version) < StrictVersion('9.4.0'):
+                raise Exception("PostgreSQL 9.4.0 or higher is required ({} found). Upgrade PostgreSQL and then run migrations again.".format(pg_version))
+
+    # Skip if the database is missing (e.g. for CI testing) or misconfigured.
+    except OperationalError:
+        pass
 
 
 class Migration(migrations.Migration):
@@ -16,6 +35,7 @@
     ]
 
     operations = [
+        migrations.RunPython(verify_postgresql_version),
         migrations.CreateModel(
             name='ReportResult',
             fields=[
diff --git a/netbox/netbox/__init__.py b/netbox/netbox/__init__.py
--- a/netbox/netbox/__init__.py
+++ b/netbox/netbox/__init__.py
@@ -1,18 +0,0 @@
-from distutils.version import StrictVersion
-
-from django.db import connection
-from django.db.utils import OperationalError
-
-
-# NetBox v2.2 and later requires PostgreSQL 9.4 or higher.
-try:
-    with connection.cursor() as cursor:
-        cursor.execute("SELECT VERSION()")
-        row = cursor.fetchone()
-        pg_version = row[0].split()[1]
-        if StrictVersion(pg_version) < StrictVersion('9.4.0'):
-            raise Exception("PostgreSQL 9.4.0 or higher is required. ({} found)".format(pg_version))
-
-# Skip if the database is missing (e.g. for CI testing) or misconfigured.
-except OperationalError:
-    pass
diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py
--- a/netbox/netbox/settings.py
+++ b/netbox/netbox/settings.py
@@ -13,7 +13,7 @@
     )
 
 
-VERSION = '2.2.0'
+VERSION = '2.2.1'
 
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

{"golden_diff": "diff --git a/netbox/extras/migrations/0008_reports.py b/netbox/extras/migrations/0008_reports.py\n--- a/netbox/extras/migrations/0008_reports.py\n+++ b/netbox/extras/migrations/0008_reports.py\n@@ -1,11 +1,30 @@\n # -*- coding: utf-8 -*-\n # Generated by Django 1.11.4 on 2017-09-26 21:25\n from __future__ import unicode_literals\n+from distutils.version import StrictVersion\n \n from django.conf import settings\n import django.contrib.postgres.fields.jsonb\n-from django.db import migrations, models\n+from django.db import connection, migrations, models\n import django.db.models.deletion\n+from django.db.utils import OperationalError\n+\n+\n+def verify_postgresql_version(apps, schema_editor):\n+    \"\"\"\n+    Verify that PostgreSQL is version 9.4 or higher.\n+    \"\"\"\n+    try:\n+        with connection.cursor() as cursor:\n+            cursor.execute(\"SELECT VERSION()\")\n+            row = cursor.fetchone()\n+            pg_version = row[0].split()[1]\n+            if StrictVersion(pg_version) < StrictVersion('9.4.0'):\n+                raise Exception(\"PostgreSQL 9.4.0 or higher is required ({} found). Upgrade PostgreSQL and then run migrations again.\".format(pg_version))\n+\n+    # Skip if the database is missing (e.g. for CI testing) or misconfigured.\n+    except OperationalError:\n+        pass\n \n \n class Migration(migrations.Migration):\n@@ -16,6 +35,7 @@\n     ]\n \n     operations = [\n+        migrations.RunPython(verify_postgresql_version),\n         migrations.CreateModel(\n             name='ReportResult',\n             fields=[\ndiff --git a/netbox/netbox/__init__.py b/netbox/netbox/__init__.py\n--- a/netbox/netbox/__init__.py\n+++ b/netbox/netbox/__init__.py\n@@ -1,18 +0,0 @@\n-from distutils.version import StrictVersion\n-\n-from django.db import connection\n-from django.db.utils import OperationalError\n-\n-\n-# NetBox v2.2 and later requires PostgreSQL 9.4 or higher.\n-try:\n-    with connection.cursor() as cursor:\n-        cursor.execute(\"SELECT VERSION()\")\n-        row = cursor.fetchone()\n-        pg_version = row[0].split()[1]\n-        if StrictVersion(pg_version) < StrictVersion('9.4.0'):\n-            raise Exception(\"PostgreSQL 9.4.0 or higher is required. ({} found)\".format(pg_version))\n-\n-# Skip if the database is missing (e.g. for CI testing) or misconfigured.\n-except OperationalError:\n-    pass\ndiff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py\n--- a/netbox/netbox/settings.py\n+++ b/netbox/netbox/settings.py\n@@ -13,7 +13,7 @@\n     )\n \n \n-VERSION = '2.2.0'\n+VERSION = '2.2.1'\n \n BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))\n", "issue": "v2.2.0 fails to run; returns ImproperlyConfigured\n### Issue type\r\n[ ] Feature request <!-- Requesting the implementation of a new feature -->\r\n[x] Bug report      <!-- Reporting unexpected or erroneous behavior -->\r\n[ ] Documentation   <!-- Proposing a modification to the documentation -->\r\n\r\n\r\n### Environment\r\n* Python version:  3.4.3\r\n* NetBox version:  2.2.0\r\n\r\n\r\n### Description\r\nThe NetBox WSGI service fails to start, returning the following error:\r\n\r\n```\r\nImproperlyConfigured: Requested setting DATABASES, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.\r\n```\r\n\r\nThis issue has been traced to code intended to verify the PostgreSQL database version during initialization. However, the required `settings` variable is not available at the time of execution.\r\n\r\nThis issues does not affect the development server (`manage.py runserver`).\n", "before_files": [{"content": "from distutils.version import StrictVersion\n\nfrom django.db import connection\nfrom django.db.utils import OperationalError\n\n\n# NetBox v2.2 and later requires PostgreSQL 9.4 or higher.\ntry:\n    with connection.cursor() as cursor:\n        cursor.execute(\"SELECT VERSION()\")\n        row = cursor.fetchone()\n        pg_version = row[0].split()[1]\n        if StrictVersion(pg_version) < StrictVersion('9.4.0'):\n            raise Exception(\"PostgreSQL 9.4.0 or higher is required. ({} found)\".format(pg_version))\n\n# Skip if the database is missing (e.g. for CI testing) or misconfigured.\nexcept OperationalError:\n    pass\n", "path": "netbox/netbox/__init__.py"}, {"content": "import logging\nimport os\nimport socket\n\nfrom django.contrib.messages import constants as messages\nfrom django.core.exceptions import ImproperlyConfigured\n\ntry:\n    from netbox import configuration\nexcept ImportError:\n    raise ImproperlyConfigured(\n        \"Configuration file is not present. Please define netbox/netbox/configuration.py per the documentation.\"\n    )\n\n\nVERSION = '2.2.0'\n\nBASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))\n\n# Import required configuration parameters\nALLOWED_HOSTS = DATABASE = SECRET_KEY = None\nfor setting in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY']:\n    try:\n        globals()[setting] = getattr(configuration, setting)\n    except AttributeError:\n        raise ImproperlyConfigured(\n            \"Mandatory setting {} is missing from configuration.py.\".format(setting)\n        )\n\n# Import optional configuration parameters\nADMINS = getattr(configuration, 'ADMINS', [])\nBANNER_BOTTOM = getattr(configuration, 'BANNER_BOTTOM', '')\nBANNER_LOGIN = getattr(configuration, 'BANNER_LOGIN', '')\nBANNER_TOP = getattr(configuration, 'BANNER_TOP', '')\nBASE_PATH = getattr(configuration, 'BASE_PATH', '')\nif BASE_PATH:\n    BASE_PATH = BASE_PATH.strip('/') + '/'  # Enforce trailing slash only\nCORS_ORIGIN_ALLOW_ALL = getattr(configuration, 'CORS_ORIGIN_ALLOW_ALL', False)\nCORS_ORIGIN_REGEX_WHITELIST = getattr(configuration, 'CORS_ORIGIN_REGEX_WHITELIST', [])\nCORS_ORIGIN_WHITELIST = getattr(configuration, 'CORS_ORIGIN_WHITELIST', [])\nDATE_FORMAT = getattr(configuration, 'DATE_FORMAT', 'N j, Y')\nDATETIME_FORMAT = getattr(configuration, 'DATETIME_FORMAT', 'N j, Y g:i a')\nDEBUG = getattr(configuration, 'DEBUG', False)\nENFORCE_GLOBAL_UNIQUE = getattr(configuration, 'ENFORCE_GLOBAL_UNIQUE', False)\nEMAIL = getattr(configuration, 'EMAIL', {})\nLOGGING = getattr(configuration, 'LOGGING', {})\nLOGIN_REQUIRED = getattr(configuration, 'LOGIN_REQUIRED', False)\nMAINTENANCE_MODE = getattr(configuration, 'MAINTENANCE_MODE', False)\nMAX_PAGE_SIZE = getattr(configuration, 'MAX_PAGE_SIZE', 1000)\nMEDIA_ROOT = getattr(configuration, 'MEDIA_ROOT', os.path.join(BASE_DIR, 'media')).rstrip('/')\nNAPALM_USERNAME = getattr(configuration, 'NAPALM_USERNAME', '')\nNAPALM_PASSWORD = getattr(configuration, 'NAPALM_PASSWORD', '')\nNAPALM_TIMEOUT = getattr(configuration, 'NAPALM_TIMEOUT', 30)\nNAPALM_ARGS = getattr(configuration, 'NAPALM_ARGS', {})\nPAGINATE_COUNT = getattr(configuration, 'PAGINATE_COUNT', 50)\nPREFER_IPV4 = getattr(configuration, 'PREFER_IPV4', False)\nREPORTS_ROOT = getattr(configuration, 'REPORTS_ROOT', os.path.join(BASE_DIR, 'reports')).rstrip('/')\nSHORT_DATE_FORMAT = getattr(configuration, 'SHORT_DATE_FORMAT', 'Y-m-d')\nSHORT_DATETIME_FORMAT = getattr(configuration, 'SHORT_DATETIME_FORMAT', 'Y-m-d H:i')\nSHORT_TIME_FORMAT = getattr(configuration, 'SHORT_TIME_FORMAT', 'H:i:s')\nTIME_FORMAT = getattr(configuration, 'TIME_FORMAT', 'g:i a')\nTIME_ZONE = getattr(configuration, 'TIME_ZONE', 'UTC')\n\nCSRF_TRUSTED_ORIGINS = ALLOWED_HOSTS\n\n# Attempt to import LDAP configuration if it has been defined\nLDAP_IGNORE_CERT_ERRORS = False\ntry:\n    from netbox.ldap_config import *\n    LDAP_CONFIGURED = True\nexcept ImportError:\n    LDAP_CONFIGURED = False\n\n# LDAP configuration (optional)\nif LDAP_CONFIGURED:\n    try:\n        import ldap\n        import django_auth_ldap\n        # Prepend LDAPBackend to the default ModelBackend\n        AUTHENTICATION_BACKENDS = [\n            'django_auth_ldap.backend.LDAPBackend',\n            'django.contrib.auth.backends.ModelBackend',\n        ]\n        # Optionally disable strict certificate checking\n        if LDAP_IGNORE_CERT_ERRORS:\n            ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)\n        # Enable logging for django_auth_ldap\n        ldap_logger = logging.getLogger('django_auth_ldap')\n        ldap_logger.addHandler(logging.StreamHandler())\n        ldap_logger.setLevel(logging.DEBUG)\n    except ImportError:\n        raise ImproperlyConfigured(\n            \"LDAP authentication has been configured, but django-auth-ldap is not installed. You can remove \"\n            \"netbox/ldap_config.py to disable LDAP.\"\n        )\n\n# Database\nconfiguration.DATABASE.update({'ENGINE': 'django.db.backends.postgresql'})\nDATABASES = {\n    'default': configuration.DATABASE,\n}\n\n# Email\nEMAIL_HOST = EMAIL.get('SERVER')\nEMAIL_PORT = EMAIL.get('PORT', 25)\nEMAIL_HOST_USER = EMAIL.get('USERNAME')\nEMAIL_HOST_PASSWORD = EMAIL.get('PASSWORD')\nEMAIL_TIMEOUT = EMAIL.get('TIMEOUT', 10)\nSERVER_EMAIL = EMAIL.get('FROM_EMAIL')\nEMAIL_SUBJECT_PREFIX = '[NetBox] '\n\n# Installed applications\nINSTALLED_APPS = (\n    'django.contrib.admin',\n    'django.contrib.auth',\n    'django.contrib.contenttypes',\n    'django.contrib.sessions',\n    'django.contrib.messages',\n    'django.contrib.staticfiles',\n    'django.contrib.humanize',\n    'corsheaders',\n    'debug_toolbar',\n    'django_filters',\n    'django_tables2',\n    'mptt',\n    'rest_framework',\n    'rest_framework_swagger',\n    'circuits',\n    'dcim',\n    'ipam',\n    'extras',\n    'secrets',\n    'tenancy',\n    'users',\n    'utilities',\n    'virtualization',\n)\n\n# Middleware\nMIDDLEWARE = (\n    'debug_toolbar.middleware.DebugToolbarMiddleware',\n    'corsheaders.middleware.CorsMiddleware',\n    'django.contrib.sessions.middleware.SessionMiddleware',\n    'django.middleware.common.CommonMiddleware',\n    'django.middleware.csrf.CsrfViewMiddleware',\n    'django.contrib.auth.middleware.AuthenticationMiddleware',\n    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',\n    'django.contrib.messages.middleware.MessageMiddleware',\n    'django.middleware.clickjacking.XFrameOptionsMiddleware',\n    'django.middleware.security.SecurityMiddleware',\n    'utilities.middleware.LoginRequiredMiddleware',\n    'utilities.middleware.APIVersionMiddleware',\n)\n\nROOT_URLCONF = 'netbox.urls'\n\nTEMPLATES = [\n    {\n        'BACKEND': 'django.template.backends.django.DjangoTemplates',\n        'DIRS': [BASE_DIR + '/templates/'],\n        'APP_DIRS': True,\n        'OPTIONS': {\n            'context_processors': [\n                'django.template.context_processors.debug',\n                'django.template.context_processors.request',\n                'django.template.context_processors.media',\n                'django.contrib.auth.context_processors.auth',\n                'django.contrib.messages.context_processors.messages',\n                'utilities.context_processors.settings',\n            ],\n        },\n    },\n]\n\n# WSGI\nWSGI_APPLICATION = 'netbox.wsgi.application'\nSECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')\nUSE_X_FORWARDED_HOST = True\n\n# Internationalization\nLANGUAGE_CODE = 'en-us'\nUSE_I18N = True\nUSE_TZ = True\n\n# Static files (CSS, JavaScript, Images)\nSTATIC_ROOT = BASE_DIR + '/static/'\nSTATIC_URL = '/{}static/'.format(BASE_PATH)\nSTATICFILES_DIRS = (\n    os.path.join(BASE_DIR, \"project-static\"),\n)\n\n# Media\nMEDIA_URL = '/{}media/'.format(BASE_PATH)\n\n# Disable default limit of 1000 fields per request. Needed for bulk deletion of objects. (Added in Django 1.10.)\nDATA_UPLOAD_MAX_NUMBER_FIELDS = None\n\n# Messages\nMESSAGE_TAGS = {\n    messages.ERROR: 'danger',\n}\n\n# Authentication URLs\nLOGIN_URL = '/{}login/'.format(BASE_PATH)\n\n# Secrets\nSECRETS_MIN_PUBKEY_SIZE = 2048\n\n# Django REST framework (API)\nREST_FRAMEWORK_VERSION = VERSION[0:3]  # Use major.minor as API version\nREST_FRAMEWORK = {\n    'ALLOWED_VERSIONS': [REST_FRAMEWORK_VERSION],\n    'DEFAULT_AUTHENTICATION_CLASSES': (\n        'rest_framework.authentication.SessionAuthentication',\n        'netbox.api.TokenAuthentication',\n    ),\n    'DEFAULT_FILTER_BACKENDS': (\n        'django_filters.rest_framework.DjangoFilterBackend',\n    ),\n    'DEFAULT_PAGINATION_CLASS': 'netbox.api.OptionalLimitOffsetPagination',\n    'DEFAULT_PERMISSION_CLASSES': (\n        'netbox.api.TokenPermissions',\n    ),\n    'DEFAULT_RENDERER_CLASSES': (\n        'rest_framework.renderers.JSONRenderer',\n        'netbox.api.FormlessBrowsableAPIRenderer',\n    ),\n    'DEFAULT_VERSION': REST_FRAMEWORK_VERSION,\n    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning',\n    'PAGE_SIZE': PAGINATE_COUNT,\n    'VIEW_NAME_FUNCTION': 'netbox.api.get_view_name',\n}\n\n# Django debug toolbar\nINTERNAL_IPS = (\n    '127.0.0.1',\n    '::1',\n)\n\n\ntry:\n    HOSTNAME = socket.gethostname()\nexcept:\n    HOSTNAME = 'localhost'\n", "path": "netbox/netbox/settings.py"}, {"content": "# -*- coding: utf-8 -*-\n# Generated by Django 1.11.4 on 2017-09-26 21:25\nfrom __future__ import unicode_literals\n\nfrom django.conf import settings\nimport django.contrib.postgres.fields.jsonb\nfrom django.db import migrations, models\nimport django.db.models.deletion\n\n\nclass Migration(migrations.Migration):\n\n    dependencies = [\n        migrations.swappable_dependency(settings.AUTH_USER_MODEL),\n        ('extras', '0007_unicode_literals'),\n    ]\n\n    operations = [\n        migrations.CreateModel(\n            name='ReportResult',\n            fields=[\n                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\n                ('report', models.CharField(max_length=255, unique=True)),\n                ('created', models.DateTimeField(auto_now_add=True)),\n                ('failed', models.BooleanField()),\n                ('data', django.contrib.postgres.fields.jsonb.JSONField()),\n                ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),\n            ],\n            options={\n                'ordering': ['report'],\n            },\n        ),\n    ]\n", "path": "netbox/extras/migrations/0008_reports.py"}], "after_files": [{"content": "", "path": "netbox/netbox/__init__.py"}, {"content": "import logging\nimport os\nimport socket\n\nfrom django.contrib.messages import constants as messages\nfrom django.core.exceptions import ImproperlyConfigured\n\ntry:\n    from netbox import configuration\nexcept ImportError:\n    raise ImproperlyConfigured(\n        \"Configuration file is not present. Please define netbox/netbox/configuration.py per the documentation.\"\n    )\n\n\nVERSION = '2.2.1'\n\nBASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))\n\n# Import required configuration parameters\nALLOWED_HOSTS = DATABASE = SECRET_KEY = None\nfor setting in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY']:\n    try:\n        globals()[setting] = getattr(configuration, setting)\n    except AttributeError:\n        raise ImproperlyConfigured(\n            \"Mandatory setting {} is missing from configuration.py.\".format(setting)\n        )\n\n# Import optional configuration parameters\nADMINS = getattr(configuration, 'ADMINS', [])\nBANNER_BOTTOM = getattr(configuration, 'BANNER_BOTTOM', '')\nBANNER_LOGIN = getattr(configuration, 'BANNER_LOGIN', '')\nBANNER_TOP = getattr(configuration, 'BANNER_TOP', '')\nBASE_PATH = getattr(configuration, 'BASE_PATH', '')\nif BASE_PATH:\n    BASE_PATH = BASE_PATH.strip('/') + '/'  # Enforce trailing slash only\nCORS_ORIGIN_ALLOW_ALL = getattr(configuration, 'CORS_ORIGIN_ALLOW_ALL', False)\nCORS_ORIGIN_REGEX_WHITELIST = getattr(configuration, 'CORS_ORIGIN_REGEX_WHITELIST', [])\nCORS_ORIGIN_WHITELIST = getattr(configuration, 'CORS_ORIGIN_WHITELIST', [])\nDATE_FORMAT = getattr(configuration, 'DATE_FORMAT', 'N j, Y')\nDATETIME_FORMAT = getattr(configuration, 'DATETIME_FORMAT', 'N j, Y g:i a')\nDEBUG = getattr(configuration, 'DEBUG', False)\nENFORCE_GLOBAL_UNIQUE = getattr(configuration, 'ENFORCE_GLOBAL_UNIQUE', False)\nEMAIL = getattr(configuration, 'EMAIL', {})\nLOGGING = getattr(configuration, 'LOGGING', {})\nLOGIN_REQUIRED = getattr(configuration, 'LOGIN_REQUIRED', False)\nMAINTENANCE_MODE = getattr(configuration, 'MAINTENANCE_MODE', False)\nMAX_PAGE_SIZE = getattr(configuration, 'MAX_PAGE_SIZE', 1000)\nMEDIA_ROOT = getattr(configuration, 'MEDIA_ROOT', os.path.join(BASE_DIR, 'media')).rstrip('/')\nNAPALM_USERNAME = getattr(configuration, 'NAPALM_USERNAME', '')\nNAPALM_PASSWORD = getattr(configuration, 'NAPALM_PASSWORD', '')\nNAPALM_TIMEOUT = getattr(configuration, 'NAPALM_TIMEOUT', 30)\nNAPALM_ARGS = getattr(configuration, 'NAPALM_ARGS', {})\nPAGINATE_COUNT = getattr(configuration, 'PAGINATE_COUNT', 50)\nPREFER_IPV4 = getattr(configuration, 'PREFER_IPV4', False)\nREPORTS_ROOT = getattr(configuration, 'REPORTS_ROOT', os.path.join(BASE_DIR, 'reports')).rstrip('/')\nSHORT_DATE_FORMAT = getattr(configuration, 'SHORT_DATE_FORMAT', 'Y-m-d')\nSHORT_DATETIME_FORMAT = getattr(configuration, 'SHORT_DATETIME_FORMAT', 'Y-m-d H:i')\nSHORT_TIME_FORMAT = getattr(configuration, 'SHORT_TIME_FORMAT', 'H:i:s')\nTIME_FORMAT = getattr(configuration, 'TIME_FORMAT', 'g:i a')\nTIME_ZONE = getattr(configuration, 'TIME_ZONE', 'UTC')\n\nCSRF_TRUSTED_ORIGINS = ALLOWED_HOSTS\n\n# Attempt to import LDAP configuration if it has been defined\nLDAP_IGNORE_CERT_ERRORS = False\ntry:\n    from netbox.ldap_config import *\n    LDAP_CONFIGURED = True\nexcept ImportError:\n    LDAP_CONFIGURED = False\n\n# LDAP configuration (optional)\nif LDAP_CONFIGURED:\n    try:\n        import ldap\n        import django_auth_ldap\n        # Prepend LDAPBackend to the default ModelBackend\n        AUTHENTICATION_BACKENDS = [\n            'django_auth_ldap.backend.LDAPBackend',\n            'django.contrib.auth.backends.ModelBackend',\n        ]\n        # Optionally disable strict certificate checking\n        if LDAP_IGNORE_CERT_ERRORS:\n            ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)\n        # Enable logging for django_auth_ldap\n        ldap_logger = logging.getLogger('django_auth_ldap')\n        ldap_logger.addHandler(logging.StreamHandler())\n        ldap_logger.setLevel(logging.DEBUG)\n    except ImportError:\n        raise ImproperlyConfigured(\n            \"LDAP authentication has been configured, but django-auth-ldap is not installed. You can remove \"\n            \"netbox/ldap_config.py to disable LDAP.\"\n        )\n\n# Database\nconfiguration.DATABASE.update({'ENGINE': 'django.db.backends.postgresql'})\nDATABASES = {\n    'default': configuration.DATABASE,\n}\n\n# Email\nEMAIL_HOST = EMAIL.get('SERVER')\nEMAIL_PORT = EMAIL.get('PORT', 25)\nEMAIL_HOST_USER = EMAIL.get('USERNAME')\nEMAIL_HOST_PASSWORD = EMAIL.get('PASSWORD')\nEMAIL_TIMEOUT = EMAIL.get('TIMEOUT', 10)\nSERVER_EMAIL = EMAIL.get('FROM_EMAIL')\nEMAIL_SUBJECT_PREFIX = '[NetBox] '\n\n# Installed applications\nINSTALLED_APPS = (\n    'django.contrib.admin',\n    'django.contrib.auth',\n    'django.contrib.contenttypes',\n    'django.contrib.sessions',\n    'django.contrib.messages',\n    'django.contrib.staticfiles',\n    'django.contrib.humanize',\n    'corsheaders',\n    'debug_toolbar',\n    'django_filters',\n    'django_tables2',\n    'mptt',\n    'rest_framework',\n    'rest_framework_swagger',\n    'circuits',\n    'dcim',\n    'ipam',\n    'extras',\n    'secrets',\n    'tenancy',\n    'users',\n    'utilities',\n    'virtualization',\n)\n\n# Middleware\nMIDDLEWARE = (\n    'debug_toolbar.middleware.DebugToolbarMiddleware',\n    'corsheaders.middleware.CorsMiddleware',\n    'django.contrib.sessions.middleware.SessionMiddleware',\n    'django.middleware.common.CommonMiddleware',\n    'django.middleware.csrf.CsrfViewMiddleware',\n    'django.contrib.auth.middleware.AuthenticationMiddleware',\n    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',\n    'django.contrib.messages.middleware.MessageMiddleware',\n    'django.middleware.clickjacking.XFrameOptionsMiddleware',\n    'django.middleware.security.SecurityMiddleware',\n    'utilities.middleware.LoginRequiredMiddleware',\n    'utilities.middleware.APIVersionMiddleware',\n)\n\nROOT_URLCONF = 'netbox.urls'\n\nTEMPLATES = [\n    {\n        'BACKEND': 'django.template.backends.django.DjangoTemplates',\n        'DIRS': [BASE_DIR + '/templates/'],\n        'APP_DIRS': True,\n        'OPTIONS': {\n            'context_processors': [\n                'django.template.context_processors.debug',\n                'django.template.context_processors.request',\n                'django.template.context_processors.media',\n                'django.contrib.auth.context_processors.auth',\n                'django.contrib.messages.context_processors.messages',\n                'utilities.context_processors.settings',\n            ],\n        },\n    },\n]\n\n# WSGI\nWSGI_APPLICATION = 'netbox.wsgi.application'\nSECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')\nUSE_X_FORWARDED_HOST = True\n\n# Internationalization\nLANGUAGE_CODE = 'en-us'\nUSE_I18N = True\nUSE_TZ = True\n\n# Static files (CSS, JavaScript, Images)\nSTATIC_ROOT = BASE_DIR + '/static/'\nSTATIC_URL = '/{}static/'.format(BASE_PATH)\nSTATICFILES_DIRS = (\n    os.path.join(BASE_DIR, \"project-static\"),\n)\n\n# Media\nMEDIA_URL = '/{}media/'.format(BASE_PATH)\n\n# Disable default limit of 1000 fields per request. Needed for bulk deletion of objects. (Added in Django 1.10.)\nDATA_UPLOAD_MAX_NUMBER_FIELDS = None\n\n# Messages\nMESSAGE_TAGS = {\n    messages.ERROR: 'danger',\n}\n\n# Authentication URLs\nLOGIN_URL = '/{}login/'.format(BASE_PATH)\n\n# Secrets\nSECRETS_MIN_PUBKEY_SIZE = 2048\n\n# Django REST framework (API)\nREST_FRAMEWORK_VERSION = VERSION[0:3]  # Use major.minor as API version\nREST_FRAMEWORK = {\n    'ALLOWED_VERSIONS': [REST_FRAMEWORK_VERSION],\n    'DEFAULT_AUTHENTICATION_CLASSES': (\n        'rest_framework.authentication.SessionAuthentication',\n        'netbox.api.TokenAuthentication',\n    ),\n    'DEFAULT_FILTER_BACKENDS': (\n        'django_filters.rest_framework.DjangoFilterBackend',\n    ),\n    'DEFAULT_PAGINATION_CLASS': 'netbox.api.OptionalLimitOffsetPagination',\n    'DEFAULT_PERMISSION_CLASSES': (\n        'netbox.api.TokenPermissions',\n    ),\n    'DEFAULT_RENDERER_CLASSES': (\n        'rest_framework.renderers.JSONRenderer',\n        'netbox.api.FormlessBrowsableAPIRenderer',\n    ),\n    'DEFAULT_VERSION': REST_FRAMEWORK_VERSION,\n    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning',\n    'PAGE_SIZE': PAGINATE_COUNT,\n    'VIEW_NAME_FUNCTION': 'netbox.api.get_view_name',\n}\n\n# Django debug toolbar\nINTERNAL_IPS = (\n    '127.0.0.1',\n    '::1',\n)\n\n\ntry:\n    HOSTNAME = socket.gethostname()\nexcept:\n    HOSTNAME = 'localhost'\n", "path": "netbox/netbox/settings.py"}, {"content": "# -*- coding: utf-8 -*-\n# Generated by Django 1.11.4 on 2017-09-26 21:25\nfrom __future__ import unicode_literals\nfrom distutils.version import StrictVersion\n\nfrom django.conf import settings\nimport django.contrib.postgres.fields.jsonb\nfrom django.db import connection, migrations, models\nimport django.db.models.deletion\nfrom django.db.utils import OperationalError\n\n\ndef verify_postgresql_version(apps, schema_editor):\n    \"\"\"\n    Verify that PostgreSQL is version 9.4 or higher.\n    \"\"\"\n    try:\n        with connection.cursor() as cursor:\n            cursor.execute(\"SELECT VERSION()\")\n            row = cursor.fetchone()\n            pg_version = row[0].split()[1]\n            if StrictVersion(pg_version) < StrictVersion('9.4.0'):\n                raise Exception(\"PostgreSQL 9.4.0 or higher is required ({} found). Upgrade PostgreSQL and then run migrations again.\".format(pg_version))\n\n    # Skip if the database is missing (e.g. for CI testing) or misconfigured.\n    except OperationalError:\n        pass\n\n\nclass Migration(migrations.Migration):\n\n    dependencies = [\n        migrations.swappable_dependency(settings.AUTH_USER_MODEL),\n        ('extras', '0007_unicode_literals'),\n    ]\n\n    operations = [\n        migrations.RunPython(verify_postgresql_version),\n        migrations.CreateModel(\n            name='ReportResult',\n            fields=[\n                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\n                ('report', models.CharField(max_length=255, unique=True)),\n                ('created', models.DateTimeField(auto_now_add=True)),\n                ('failed', models.BooleanField()),\n                ('data', django.contrib.postgres.fields.jsonb.JSONField()),\n                ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),\n            ],\n            options={\n                'ordering': ['report'],\n            },\n        ),\n    ]\n", "path": "netbox/extras/migrations/0008_reports.py"}]}