mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Merge v2.5 work
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
from django.conf import settings
|
||||
from django.contrib.admin import AdminSite
|
||||
from django.contrib.auth.models import Group, User
|
||||
from django.contrib.auth.admin import GroupAdmin, UserAdmin
|
||||
from django.contrib.auth.models import Group, User
|
||||
from taggit.admin import TagAdmin
|
||||
from taggit.models import Tag
|
||||
|
||||
|
@@ -1,5 +1,3 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from rest_framework import authentication, exceptions
|
||||
from rest_framework.pagination import LimitOffsetPagination
|
||||
@@ -59,16 +57,15 @@ class TokenPermissions(DjangoModelPermissions):
|
||||
"""
|
||||
def __init__(self):
|
||||
# LOGIN_REQUIRED determines whether read-only access is provided to anonymous users.
|
||||
from django.conf import settings
|
||||
self.authenticated_users_only = settings.LOGIN_REQUIRED
|
||||
super(TokenPermissions, self).__init__()
|
||||
super().__init__()
|
||||
|
||||
def has_permission(self, request, view):
|
||||
# If token authentication is in use, verify that the token allows write operations (for unsafe methods).
|
||||
if request.method not in SAFE_METHODS and isinstance(request.auth, Token):
|
||||
if not request.auth.write_enabled:
|
||||
return False
|
||||
return super(TokenPermissions, self).has_permission(request, view)
|
||||
return super().has_permission(request, view)
|
||||
|
||||
|
||||
#
|
||||
@@ -84,10 +81,17 @@ class OptionalLimitOffsetPagination(LimitOffsetPagination):
|
||||
|
||||
def paginate_queryset(self, queryset, request, view=None):
|
||||
|
||||
try:
|
||||
self.count = queryset.count()
|
||||
except (AttributeError, TypeError):
|
||||
if hasattr(queryset, 'all'):
|
||||
# TODO: This breaks filtering by annotated values
|
||||
# Make a clone of the queryset with any annotations stripped (performance hack)
|
||||
qs = queryset.all()
|
||||
qs.query.annotations.clear()
|
||||
self.count = qs.count()
|
||||
|
||||
else:
|
||||
# We're dealing with an iterable, not a QuerySet
|
||||
self.count = len(queryset)
|
||||
|
||||
self.limit = self.get_limit(request)
|
||||
self.offset = self.get_offset(request)
|
||||
self.request = request
|
||||
@@ -128,7 +132,7 @@ class OptionalLimitOffsetPagination(LimitOffsetPagination):
|
||||
if not self.limit:
|
||||
return None
|
||||
|
||||
return super(OptionalLimitOffsetPagination, self).get_next_link()
|
||||
return super().get_next_link()
|
||||
|
||||
def get_previous_link(self):
|
||||
|
||||
@@ -136,7 +140,7 @@ class OptionalLimitOffsetPagination(LimitOffsetPagination):
|
||||
if not self.limit:
|
||||
return None
|
||||
|
||||
return super(OptionalLimitOffsetPagination, self).get_previous_link()
|
||||
return super().get_previous_link()
|
||||
|
||||
|
||||
#
|
||||
|
@@ -91,6 +91,10 @@ LOGGING = {}
|
||||
# are permitted to access most data in NetBox (excluding secrets) but not make any changes.
|
||||
LOGIN_REQUIRED = False
|
||||
|
||||
# The length of time (in seconds) for which a user will remain logged into the web UI before being prompted to
|
||||
# re-authenticate. (Default: 1209600 [14 days])
|
||||
LOGIN_TIMEOUT = None
|
||||
|
||||
# Setting this to True will display a "maintenance mode" banner at the top of every page.
|
||||
MAINTENANCE_MODE = False
|
||||
|
||||
@@ -121,10 +125,6 @@ PAGINATE_COUNT = 50
|
||||
# prefer IPv4 instead.
|
||||
PREFER_IPV4 = False
|
||||
|
||||
# The Webhook event backend is disabled by default. Set this to True to enable it. Note that this requires a Redis
|
||||
# database be configured and accessible by NetBox (see `REDIS` below).
|
||||
WEBHOOKS_ENABLED = False
|
||||
|
||||
# Redis database settings (optional). A Redis database is required only if the webhooks backend is enabled.
|
||||
REDIS = {
|
||||
'HOST': 'localhost',
|
||||
@@ -138,9 +138,18 @@ REDIS = {
|
||||
# this setting is derived from the installed location.
|
||||
# REPORTS_ROOT = '/opt/netbox/netbox/reports'
|
||||
|
||||
# By default, NetBox will store session data in the database. Alternatively, a file path can be specified here to use
|
||||
# local file storage instead. (This can be useful for enabling authentication on a standby instance with read-only
|
||||
# database access.) Note that the user as which NetBox runs must have read and write permissions to this path.
|
||||
SESSION_FILE_PATH = None
|
||||
|
||||
# Time zone (default: UTC)
|
||||
TIME_ZONE = 'UTC'
|
||||
|
||||
# The webhooks backend is disabled by default. Set this to True to enable it. Note that this requires a Redis
|
||||
# database be configured and accessible by NetBox.
|
||||
WEBHOOKS_ENABLED = False
|
||||
|
||||
# Date/time formatting. See the following link for supported formats:
|
||||
# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date
|
||||
DATE_FORMAT = 'N j, Y'
|
||||
|
@@ -1,5 +1,3 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django import forms
|
||||
|
||||
from utilities.forms import BootstrapMixin
|
||||
|
@@ -7,6 +7,13 @@ import warnings
|
||||
from django.contrib.messages import constants as messages
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
||||
# Check for Python 3.5+
|
||||
if sys.version_info < (3, 5):
|
||||
raise RuntimeError(
|
||||
"NetBox requires Python 3.5 or higher (current: Python {})".format(sys.version.split()[0])
|
||||
)
|
||||
|
||||
# Check for configuration file
|
||||
try:
|
||||
from netbox import configuration
|
||||
except ImportError:
|
||||
@@ -14,15 +21,8 @@ except ImportError:
|
||||
"Configuration file is not present. Please define netbox/netbox/configuration.py per the documentation."
|
||||
)
|
||||
|
||||
# Raise a deprecation warning for Python 2.x
|
||||
if sys.version_info[0] < 3:
|
||||
warnings.warn(
|
||||
"Support for Python 2 will be removed in NetBox v2.5. Please consider migration to Python 3 at your earliest "
|
||||
"opportunity. Guidance is available in the documentation at http://netbox.readthedocs.io/.",
|
||||
DeprecationWarning
|
||||
)
|
||||
|
||||
VERSION = '2.4.9'
|
||||
VERSION = '2.5-beta2'
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
@@ -55,6 +55,7 @@ ENFORCE_GLOBAL_UNIQUE = getattr(configuration, 'ENFORCE_GLOBAL_UNIQUE', False)
|
||||
EMAIL = getattr(configuration, 'EMAIL', {})
|
||||
LOGGING = getattr(configuration, 'LOGGING', {})
|
||||
LOGIN_REQUIRED = getattr(configuration, 'LOGIN_REQUIRED', False)
|
||||
LOGIN_TIMEOUT = getattr(configuration, 'LOGIN_TIMEOUT', None)
|
||||
MAINTENANCE_MODE = getattr(configuration, 'MAINTENANCE_MODE', False)
|
||||
MAX_PAGE_SIZE = getattr(configuration, 'MAX_PAGE_SIZE', 1000)
|
||||
MEDIA_ROOT = getattr(configuration, 'MEDIA_ROOT', os.path.join(BASE_DIR, 'media')).rstrip('/')
|
||||
@@ -66,6 +67,7 @@ PAGINATE_COUNT = getattr(configuration, 'PAGINATE_COUNT', 50)
|
||||
PREFER_IPV4 = getattr(configuration, 'PREFER_IPV4', False)
|
||||
REPORTS_ROOT = getattr(configuration, 'REPORTS_ROOT', os.path.join(BASE_DIR, 'reports')).rstrip('/')
|
||||
REDIS = getattr(configuration, 'REDIS', {})
|
||||
SESSION_FILE_PATH = getattr(configuration, 'SESSION_FILE_PATH', None)
|
||||
SHORT_DATE_FORMAT = getattr(configuration, 'SHORT_DATE_FORMAT', 'Y-m-d')
|
||||
SHORT_DATETIME_FORMAT = getattr(configuration, 'SHORT_DATETIME_FORMAT', 'Y-m-d H:i')
|
||||
SHORT_TIME_FORMAT = getattr(configuration, 'SHORT_TIME_FORMAT', 'H:i:s')
|
||||
@@ -112,6 +114,17 @@ DATABASES = {
|
||||
'default': configuration.DATABASE,
|
||||
}
|
||||
|
||||
# Sessions
|
||||
if LOGIN_TIMEOUT is not None:
|
||||
if type(LOGIN_TIMEOUT) is not int or LOGIN_TIMEOUT < 0:
|
||||
raise ImproperlyConfigured(
|
||||
"LOGIN_TIMEOUT must be a positive integer (value: {})".format(LOGIN_TIMEOUT)
|
||||
)
|
||||
# Django default is 1209600 seconds (14 days)
|
||||
SESSION_COOKIE_AGE = LOGIN_TIMEOUT
|
||||
if SESSION_FILE_PATH is not None:
|
||||
SESSION_ENGINE = 'django.contrib.sessions.backends.file'
|
||||
|
||||
# Redis
|
||||
REDIS_HOST = REDIS.get('HOST', 'localhost')
|
||||
REDIS_PORT = REDIS.get('PORT', 6379)
|
||||
@@ -235,7 +248,7 @@ SECRETS_MIN_PUBKEY_SIZE = 2048
|
||||
|
||||
# Django filters
|
||||
FILTERS_NULL_CHOICE_LABEL = 'None'
|
||||
FILTERS_NULL_CHOICE_VALUE = '0' # Must be a string
|
||||
FILTERS_NULL_CHOICE_VALUE = 'null'
|
||||
|
||||
# Django REST framework (API)
|
||||
REST_FRAMEWORK_VERSION = VERSION[0:3] # Use major.minor as API version
|
||||
|
@@ -1,10 +1,8 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf.urls import include, url
|
||||
from django.views.static import serve
|
||||
from drf_yasg.views import get_schema_view
|
||||
from drf_yasg import openapi
|
||||
from drf_yasg.views import get_schema_view
|
||||
|
||||
from netbox.views import APIRootView, HomeView, SearchView
|
||||
from users.views import LoginView, LogoutView
|
||||
|
@@ -1,8 +1,6 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from django.db.models import Count
|
||||
from django.db.models import Count, F
|
||||
from django.shortcuts import render
|
||||
from django.views.generic import View
|
||||
from rest_framework.response import Response
|
||||
@@ -16,8 +14,7 @@ from dcim.filters import (
|
||||
DeviceFilter, DeviceTypeFilter, RackFilter, RackGroupFilter, SiteFilter, VirtualChassisFilter
|
||||
)
|
||||
from dcim.models import (
|
||||
ConsolePort, Device, DeviceType, InterfaceConnection, PowerPort, Rack, RackGroup, Site,
|
||||
VirtualChassis
|
||||
Cable, ConsolePort, Device, DeviceType, Interface, PowerPort, Rack, RackGroup, Site, VirtualChassis
|
||||
)
|
||||
from dcim.tables import (
|
||||
DeviceDetailTable, DeviceTypeTable, RackTable, RackGroupTable, SiteTable, VirtualChassisTable
|
||||
@@ -159,6 +156,18 @@ class HomeView(View):
|
||||
|
||||
def get(self, request):
|
||||
|
||||
connected_consoleports = ConsolePort.objects.filter(
|
||||
connected_endpoint__isnull=False
|
||||
)
|
||||
connected_powerports = PowerPort.objects.filter(
|
||||
connected_endpoint__isnull=False
|
||||
)
|
||||
connected_interfaces = Interface.objects.filter(
|
||||
_connected_interface__isnull=False,
|
||||
pk__lt=F('_connected_interface')
|
||||
)
|
||||
cables = Cable.objects.all()
|
||||
|
||||
stats = {
|
||||
|
||||
# Organization
|
||||
@@ -168,9 +177,10 @@ class HomeView(View):
|
||||
# DCIM
|
||||
'rack_count': Rack.objects.count(),
|
||||
'device_count': Device.objects.count(),
|
||||
'interface_connections_count': InterfaceConnection.objects.count(),
|
||||
'console_connections_count': ConsolePort.objects.filter(cs_port__isnull=False).count(),
|
||||
'power_connections_count': PowerPort.objects.filter(power_outlet__isnull=False).count(),
|
||||
'interface_connections_count': connected_interfaces.count(),
|
||||
'cable_count': cables.count(),
|
||||
'console_connections_count': connected_consoleports.count(),
|
||||
'power_connections_count': connected_powerports.count(),
|
||||
|
||||
# IPAM
|
||||
'vrf_count': VRF.objects.count(),
|
||||
|
@@ -2,7 +2,6 @@ import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "netbox.settings")
|
||||
|
||||
application = get_wsgi_application()
|
||||
|
Reference in New Issue
Block a user