mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-24 17:38:37 -06:00
Optimize config queries
This commit is contained in:
parent
41ff1d0fc9
commit
fbf91dda7d
@ -1,7 +1,6 @@
|
|||||||
import socket
|
import socket
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.http import Http404, HttpResponse, HttpResponseForbidden
|
from django.http import Http404, HttpResponse, HttpResponseForbidden
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from drf_yasg import openapi
|
from drf_yasg import openapi
|
||||||
@ -21,7 +20,7 @@ from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired
|
|||||||
from netbox.api.exceptions import ServiceUnavailable
|
from netbox.api.exceptions import ServiceUnavailable
|
||||||
from netbox.api.metadata import ContentTypeMetadata
|
from netbox.api.metadata import ContentTypeMetadata
|
||||||
from netbox.api.views import ModelViewSet
|
from netbox.api.views import ModelViewSet
|
||||||
from netbox.config import Config
|
from netbox.config import get_config
|
||||||
from utilities.api import get_serializer_for_model
|
from utilities.api import get_serializer_for_model
|
||||||
from utilities.utils import count_related, decode_dict
|
from utilities.utils import count_related, decode_dict
|
||||||
from virtualization.models import VirtualMachine
|
from virtualization.models import VirtualMachine
|
||||||
@ -459,7 +458,7 @@ class DeviceViewSet(ConfigContextQuerySetMixin, CustomFieldModelViewSet):
|
|||||||
napalm_methods = request.GET.getlist('method')
|
napalm_methods = request.GET.getlist('method')
|
||||||
response = OrderedDict([(m, None) for m in napalm_methods])
|
response = OrderedDict([(m, None) for m in napalm_methods])
|
||||||
|
|
||||||
config = Config()
|
config = get_config()
|
||||||
username = config.NAPALM_USERNAME
|
username = config.NAPALM_USERNAME
|
||||||
password = config.NAPALM_PASSWORD
|
password = config.NAPALM_PASSWORD
|
||||||
timeout = config.NAPALM_TIMEOUT
|
timeout = config.NAPALM_TIMEOUT
|
||||||
|
@ -14,7 +14,7 @@ from dcim.choices import *
|
|||||||
from dcim.constants import *
|
from dcim.constants import *
|
||||||
from dcim.svg import RackElevationSVG
|
from dcim.svg import RackElevationSVG
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from netbox.config import Config
|
from netbox.config import get_config
|
||||||
from netbox.models import OrganizationalModel, PrimaryModel
|
from netbox.models import OrganizationalModel, PrimaryModel
|
||||||
from utilities.choices import ColorChoices
|
from utilities.choices import ColorChoices
|
||||||
from utilities.fields import ColorField, NaturalOrderingField
|
from utilities.fields import ColorField, NaturalOrderingField
|
||||||
@ -394,7 +394,7 @@ class Rack(PrimaryModel):
|
|||||||
"""
|
"""
|
||||||
elevation = RackElevationSVG(self, user=user, include_images=include_images, base_url=base_url)
|
elevation = RackElevationSVG(self, user=user, include_images=include_images, base_url=base_url)
|
||||||
if unit_width is None or unit_height is None:
|
if unit_width is None or unit_height is None:
|
||||||
config = Config()
|
config = get_config()
|
||||||
unit_width = unit_width or config.RACK_ELEVATION_DEFAULT_UNIT_WIDTH
|
unit_width = unit_width or config.RACK_ELEVATION_DEFAULT_UNIT_WIDTH
|
||||||
unit_height = unit_height or config.RACK_ELEVATION_DEFAULT_UNIT_HEIGHT
|
unit_height = unit_height or config.RACK_ELEVATION_DEFAULT_UNIT_HEIGHT
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
from django.conf import settings
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
|
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
@ -9,7 +8,7 @@ from rest_framework.decorators import action
|
|||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from ipam.models import *
|
from ipam.models import *
|
||||||
from netbox.config import Config
|
from netbox.config import get_config
|
||||||
from utilities.constants import ADVISORY_LOCK_KEYS
|
from utilities.constants import ADVISORY_LOCK_KEYS
|
||||||
from . import serializers
|
from . import serializers
|
||||||
|
|
||||||
@ -161,7 +160,7 @@ class AvailableIPsMixin:
|
|||||||
|
|
||||||
# Determine the maximum number of IPs to return
|
# Determine the maximum number of IPs to return
|
||||||
else:
|
else:
|
||||||
config = Config()
|
config = get_config()
|
||||||
PAGINATE_COUNT = config.PAGINATE_COUNT
|
PAGINATE_COUNT = config.PAGINATE_COUNT
|
||||||
MAX_PAGE_SIZE = config.MAX_PAGE_SIZE
|
MAX_PAGE_SIZE = config.MAX_PAGE_SIZE
|
||||||
try:
|
try:
|
||||||
|
@ -16,7 +16,7 @@ from ipam.fields import IPNetworkField, IPAddressField
|
|||||||
from ipam.managers import IPAddressManager
|
from ipam.managers import IPAddressManager
|
||||||
from ipam.querysets import PrefixQuerySet
|
from ipam.querysets import PrefixQuerySet
|
||||||
from ipam.validators import DNSValidator
|
from ipam.validators import DNSValidator
|
||||||
from netbox.config import Config
|
from netbox.config import get_config
|
||||||
from utilities.querysets import RestrictedQuerySet
|
from utilities.querysets import RestrictedQuerySet
|
||||||
from virtualization.models import VirtualMachine
|
from virtualization.models import VirtualMachine
|
||||||
|
|
||||||
@ -316,7 +316,7 @@ class Prefix(PrimaryModel):
|
|||||||
})
|
})
|
||||||
|
|
||||||
# Enforce unique IP space (if applicable)
|
# Enforce unique IP space (if applicable)
|
||||||
if (self.vrf is None and Config().ENFORCE_GLOBAL_UNIQUE) or (self.vrf and self.vrf.enforce_unique):
|
if (self.vrf is None and get_config().ENFORCE_GLOBAL_UNIQUE) or (self.vrf and self.vrf.enforce_unique):
|
||||||
duplicate_prefixes = self.get_duplicates()
|
duplicate_prefixes = self.get_duplicates()
|
||||||
if duplicate_prefixes:
|
if duplicate_prefixes:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
@ -811,7 +811,7 @@ class IPAddress(PrimaryModel):
|
|||||||
})
|
})
|
||||||
|
|
||||||
# Enforce unique IP space (if applicable)
|
# Enforce unique IP space (if applicable)
|
||||||
if (self.vrf is None and Config().ENFORCE_GLOBAL_UNIQUE) or (self.vrf and self.vrf.enforce_unique):
|
if (self.vrf is None and get_config().ENFORCE_GLOBAL_UNIQUE) or (self.vrf and self.vrf.enforce_unique):
|
||||||
duplicate_ips = self.get_duplicates()
|
duplicate_ips = self.get_duplicates()
|
||||||
if duplicate_ips and (
|
if duplicate_ips and (
|
||||||
self.role not in IPADDRESS_ROLES_NONUNIQUE or
|
self.role not in IPADDRESS_ROLES_NONUNIQUE or
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
from django.conf import settings
|
|
||||||
from django.db.models import QuerySet
|
from django.db.models import QuerySet
|
||||||
from rest_framework.pagination import LimitOffsetPagination
|
from rest_framework.pagination import LimitOffsetPagination
|
||||||
|
|
||||||
from netbox.config import Config
|
from netbox.config import get_config
|
||||||
|
|
||||||
|
|
||||||
class OptionalLimitOffsetPagination(LimitOffsetPagination):
|
class OptionalLimitOffsetPagination(LimitOffsetPagination):
|
||||||
@ -12,7 +11,7 @@ class OptionalLimitOffsetPagination(LimitOffsetPagination):
|
|||||||
MAX_PAGE_SIZE has been set to 0 or None.
|
MAX_PAGE_SIZE has been set to 0 or None.
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.default_limit = Config().PAGINATE_COUNT
|
self.default_limit = get_config().PAGINATE_COUNT
|
||||||
|
|
||||||
def paginate_queryset(self, queryset, request, view=None):
|
def paginate_queryset(self, queryset, request, view=None):
|
||||||
|
|
||||||
@ -44,7 +43,7 @@ class OptionalLimitOffsetPagination(LimitOffsetPagination):
|
|||||||
if limit < 0:
|
if limit < 0:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
# Enforce maximum page size, if defined
|
# Enforce maximum page size, if defined
|
||||||
MAX_PAGE_SIZE = Config().MAX_PAGE_SIZE
|
MAX_PAGE_SIZE = get_config().MAX_PAGE_SIZE
|
||||||
if MAX_PAGE_SIZE:
|
if MAX_PAGE_SIZE:
|
||||||
return MAX_PAGE_SIZE if limit == 0 else min(limit, MAX_PAGE_SIZE)
|
return MAX_PAGE_SIZE if limit == 0 else min(limit, MAX_PAGE_SIZE)
|
||||||
return limit
|
return limit
|
||||||
|
@ -1,14 +1,41 @@
|
|||||||
|
import logging
|
||||||
|
import threading
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
|
||||||
from .parameters import PARAMS
|
from .parameters import PARAMS
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'Config',
|
'clear_config',
|
||||||
'ConfigItem',
|
'ConfigItem',
|
||||||
|
'get_config',
|
||||||
'PARAMS',
|
'PARAMS',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_thread_locals = threading.local()
|
||||||
|
|
||||||
|
logger = logging.getLogger('netbox.config')
|
||||||
|
|
||||||
|
|
||||||
|
def get_config():
|
||||||
|
"""
|
||||||
|
Return the current NetBox configuration, pulling it from cache if not already loaded in memory.
|
||||||
|
"""
|
||||||
|
if not hasattr(_thread_locals, 'config'):
|
||||||
|
_thread_locals.config = Config()
|
||||||
|
logger.debug("Initialized configuration")
|
||||||
|
return _thread_locals.config
|
||||||
|
|
||||||
|
|
||||||
|
def clear_config():
|
||||||
|
"""
|
||||||
|
Delete the currently loaded configuration, if any.
|
||||||
|
"""
|
||||||
|
if hasattr(_thread_locals, 'config'):
|
||||||
|
del _thread_locals.config
|
||||||
|
logger.debug("Cleared configuration")
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
"""
|
"""
|
||||||
@ -19,6 +46,7 @@ class Config:
|
|||||||
self.config = cache.get('config')
|
self.config = cache.get('config')
|
||||||
self.version = cache.get('config_version')
|
self.version = cache.get('config_version')
|
||||||
self.defaults = {param.name: param.default for param in PARAMS}
|
self.defaults = {param.name: param.default for param in PARAMS}
|
||||||
|
logger.debug("Loaded configuration data from cache")
|
||||||
|
|
||||||
def __getattr__(self, item):
|
def __getattr__(self, item):
|
||||||
|
|
||||||
@ -46,5 +74,5 @@ class ConfigItem:
|
|||||||
self.item = item
|
self.item = item
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
config = Config()
|
config = get_config()
|
||||||
return getattr(config, self.item)
|
return getattr(config, self.item)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from django.conf import settings as django_settings
|
from django.conf import settings as django_settings
|
||||||
|
|
||||||
from extras.registry import registry
|
from extras.registry import registry
|
||||||
from netbox.config import Config
|
from netbox.config import get_config
|
||||||
|
|
||||||
|
|
||||||
def settings_and_registry(request):
|
def settings_and_registry(request):
|
||||||
@ -10,7 +10,7 @@ def settings_and_registry(request):
|
|||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
'settings': django_settings,
|
'settings': django_settings,
|
||||||
'config': Config(),
|
'config': get_config(),
|
||||||
'registry': registry,
|
'registry': registry,
|
||||||
'preferences': request.user.config if request.user.is_authenticated else {},
|
'preferences': request.user.config if request.user.is_authenticated else {},
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,12 @@ from django.http import Http404, HttpResponseRedirect
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from extras.context_managers import change_logging
|
from extras.context_managers import change_logging
|
||||||
|
from netbox.config import clear_config
|
||||||
from netbox.views import server_error
|
from netbox.views import server_error
|
||||||
from utilities.api import is_api_request, rest_api_server_error
|
from utilities.api import is_api_request, rest_api_server_error
|
||||||
|
|
||||||
|
|
||||||
class LoginRequiredMiddleware(object):
|
class LoginRequiredMiddleware:
|
||||||
"""
|
"""
|
||||||
If LOGIN_REQUIRED is True, redirect all non-authenticated users to the login page.
|
If LOGIN_REQUIRED is True, redirect all non-authenticated users to the login page.
|
||||||
"""
|
"""
|
||||||
@ -114,7 +115,7 @@ class RemoteUserMiddleware(RemoteUserMiddleware_):
|
|||||||
return groups
|
return groups
|
||||||
|
|
||||||
|
|
||||||
class ObjectChangeMiddleware(object):
|
class ObjectChangeMiddleware:
|
||||||
"""
|
"""
|
||||||
This middleware performs three functions in response to an object being created, updated, or deleted:
|
This middleware performs three functions in response to an object being created, updated, or deleted:
|
||||||
|
|
||||||
@ -144,7 +145,7 @@ class ObjectChangeMiddleware(object):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
class APIVersionMiddleware(object):
|
class APIVersionMiddleware:
|
||||||
"""
|
"""
|
||||||
If the request is for an API endpoint, include the API version as a response header.
|
If the request is for an API endpoint, include the API version as a response header.
|
||||||
"""
|
"""
|
||||||
@ -159,7 +160,20 @@ class APIVersionMiddleware(object):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
class ExceptionHandlingMiddleware(object):
|
class DynamicConfigMiddleware:
|
||||||
|
"""
|
||||||
|
Store the cached NetBox configuration in thread-local storage for the duration of the request.
|
||||||
|
"""
|
||||||
|
def __init__(self, get_response):
|
||||||
|
self.get_response = get_response
|
||||||
|
|
||||||
|
def __call__(self, request):
|
||||||
|
response = self.get_response(request)
|
||||||
|
clear_config()
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
class ExceptionHandlingMiddleware:
|
||||||
"""
|
"""
|
||||||
Intercept certain exceptions which are likely indicative of installation issues and provide helpful instructions
|
Intercept certain exceptions which are likely indicative of installation issues and provide helpful instructions
|
||||||
to the user.
|
to the user.
|
||||||
|
@ -335,6 +335,7 @@ MIDDLEWARE = [
|
|||||||
'netbox.middleware.ExceptionHandlingMiddleware',
|
'netbox.middleware.ExceptionHandlingMiddleware',
|
||||||
'netbox.middleware.RemoteUserMiddleware',
|
'netbox.middleware.RemoteUserMiddleware',
|
||||||
'netbox.middleware.LoginRequiredMiddleware',
|
'netbox.middleware.LoginRequiredMiddleware',
|
||||||
|
'netbox.middleware.DynamicConfigMiddleware',
|
||||||
'netbox.middleware.APIVersionMiddleware',
|
'netbox.middleware.APIVersionMiddleware',
|
||||||
'netbox.middleware.ObjectChangeMiddleware',
|
'netbox.middleware.ObjectChangeMiddleware',
|
||||||
'django_prometheus.middleware.PrometheusAfterMiddleware',
|
'django_prometheus.middleware.PrometheusAfterMiddleware',
|
||||||
|
@ -13,7 +13,7 @@ from django.utils.http import is_safe_url
|
|||||||
from django.views.decorators.debug import sensitive_post_parameters
|
from django.views.decorators.debug import sensitive_post_parameters
|
||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
|
|
||||||
from netbox.config import Config
|
from netbox.config import get_config
|
||||||
from utilities.forms import ConfirmationForm
|
from utilities.forms import ConfirmationForm
|
||||||
from .forms import LoginForm, PasswordChangeForm, TokenForm
|
from .forms import LoginForm, PasswordChangeForm, TokenForm
|
||||||
from .models import Token
|
from .models import Token
|
||||||
@ -53,7 +53,7 @@ class LoginView(View):
|
|||||||
|
|
||||||
# If maintenance mode is enabled, assume the database is read-only, and disable updating the user's
|
# If maintenance mode is enabled, assume the database is read-only, and disable updating the user's
|
||||||
# last_login time upon authentication.
|
# last_login time upon authentication.
|
||||||
if Config().MAINTENANCE_MODE:
|
if get_config().MAINTENANCE_MODE:
|
||||||
logger.warning("Maintenance mode enabled: disabling update of most recent login time")
|
logger.warning("Maintenance mode enabled: disabling update of most recent login time")
|
||||||
user_logged_in.disconnect(update_last_login, dispatch_uid='update_last_login')
|
user_logged_in.disconnect(update_last_login, dispatch_uid='update_last_login')
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from django.core.paginator import Paginator, Page
|
from django.core.paginator import Paginator, Page
|
||||||
|
|
||||||
from netbox.config import Config
|
from netbox.config import get_config
|
||||||
|
|
||||||
|
|
||||||
class EnhancedPaginator(Paginator):
|
class EnhancedPaginator(Paginator):
|
||||||
@ -14,9 +14,9 @@ class EnhancedPaginator(Paginator):
|
|||||||
try:
|
try:
|
||||||
per_page = int(per_page)
|
per_page = int(per_page)
|
||||||
if per_page < 1:
|
if per_page < 1:
|
||||||
per_page = Config().PAGINATE_COUNT
|
per_page = get_config().PAGINATE_COUNT
|
||||||
except ValueError:
|
except ValueError:
|
||||||
per_page = Config().PAGINATE_COUNT
|
per_page = get_config().PAGINATE_COUNT
|
||||||
|
|
||||||
# Set orphans count based on page size
|
# Set orphans count based on page size
|
||||||
if orphans is None and per_page <= 50:
|
if orphans is None and per_page <= 50:
|
||||||
@ -66,7 +66,7 @@ def get_paginate_count(request):
|
|||||||
|
|
||||||
Return the lesser of the calculated value and MAX_PAGE_SIZE.
|
Return the lesser of the calculated value and MAX_PAGE_SIZE.
|
||||||
"""
|
"""
|
||||||
config = Config()
|
config = get_config()
|
||||||
|
|
||||||
if 'per_page' in request.GET:
|
if 'per_page' in request.GET:
|
||||||
try:
|
try:
|
||||||
|
@ -14,7 +14,7 @@ from django.utils.html import strip_tags
|
|||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from markdown import markdown
|
from markdown import markdown
|
||||||
|
|
||||||
from netbox.config import Config
|
from netbox.config import get_config
|
||||||
from utilities.forms import get_selected_values, TableConfigForm
|
from utilities.forms import get_selected_values, TableConfigForm
|
||||||
from utilities.utils import foreground_color
|
from utilities.utils import foreground_color
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ def render_markdown(value):
|
|||||||
value = strip_tags(value)
|
value = strip_tags(value)
|
||||||
|
|
||||||
# Sanitize Markdown links
|
# Sanitize Markdown links
|
||||||
schemes = '|'.join(Config().ALLOWED_URL_SCHEMES)
|
schemes = '|'.join(get_config().ALLOWED_URL_SCHEMES)
|
||||||
pattern = fr'\[(.+)\]\((?!({schemes})).*:(.+)\)'
|
pattern = fr'\[(.+)\]\((?!({schemes})).*:(.+)\)'
|
||||||
value = re.sub(pattern, '[\\1](\\3)', value, flags=re.IGNORECASE)
|
value = re.sub(pattern, '[\\1](\\3)', value, flags=re.IGNORECASE)
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ from dcim.models import Region, Site
|
|||||||
from extras.choices import CustomFieldTypeChoices
|
from extras.choices import CustomFieldTypeChoices
|
||||||
from extras.models import CustomField
|
from extras.models import CustomField
|
||||||
from ipam.models import VLAN
|
from ipam.models import VLAN
|
||||||
from netbox.config import Config
|
from netbox.config import get_config
|
||||||
from utilities.testing import APITestCase, disable_warnings
|
from utilities.testing import APITestCase, disable_warnings
|
||||||
|
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ class APIPaginationTestCase(APITestCase):
|
|||||||
|
|
||||||
def test_default_page_size(self):
|
def test_default_page_size(self):
|
||||||
response = self.client.get(self.url, format='json', **self.header)
|
response = self.client.get(self.url, format='json', **self.header)
|
||||||
page_size = Config().PAGINATE_COUNT
|
page_size = get_config().PAGINATE_COUNT
|
||||||
self.assertLess(page_size, 100, "Default page size not sufficient for data set")
|
self.assertLess(page_size, 100, "Default page size not sufficient for data set")
|
||||||
|
|
||||||
self.assertHttpStatus(response, status.HTTP_200_OK)
|
self.assertHttpStatus(response, status.HTTP_200_OK)
|
||||||
|
@ -3,7 +3,7 @@ import re
|
|||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import _lazy_re_compile, BaseValidator, URLValidator
|
from django.core.validators import _lazy_re_compile, BaseValidator, URLValidator
|
||||||
|
|
||||||
from netbox.config import Config
|
from netbox.config import get_config
|
||||||
|
|
||||||
|
|
||||||
class EnhancedURLValidator(URLValidator):
|
class EnhancedURLValidator(URLValidator):
|
||||||
@ -24,7 +24,7 @@ class EnhancedURLValidator(URLValidator):
|
|||||||
def __init__(self, schemes=None, **kwargs):
|
def __init__(self, schemes=None, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
if schemes is not None:
|
if schemes is not None:
|
||||||
self.schemes = Config().ALLOWED_URL_SCHEMES
|
self.schemes = get_config().ALLOWED_URL_SCHEMES
|
||||||
|
|
||||||
|
|
||||||
class ExclusionValidator(BaseValidator):
|
class ExclusionValidator(BaseValidator):
|
||||||
|
@ -8,7 +8,7 @@ from dcim.models import BaseInterface, Device
|
|||||||
from extras.models import ConfigContextModel
|
from extras.models import ConfigContextModel
|
||||||
from extras.querysets import ConfigContextModelQuerySet
|
from extras.querysets import ConfigContextModelQuerySet
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from netbox.config import Config
|
from netbox.config import get_config
|
||||||
from netbox.models import OrganizationalModel, PrimaryModel
|
from netbox.models import OrganizationalModel, PrimaryModel
|
||||||
from utilities.fields import NaturalOrderingField
|
from utilities.fields import NaturalOrderingField
|
||||||
from utilities.ordering import naturalize_interface
|
from utilities.ordering import naturalize_interface
|
||||||
@ -340,7 +340,7 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def primary_ip(self):
|
def primary_ip(self):
|
||||||
if Config().PREFER_IPV4 and self.primary_ip4:
|
if get_config().PREFER_IPV4 and self.primary_ip4:
|
||||||
return self.primary_ip4
|
return self.primary_ip4
|
||||||
elif self.primary_ip6:
|
elif self.primary_ip6:
|
||||||
return self.primary_ip6
|
return self.primary_ip6
|
||||||
|
Loading…
Reference in New Issue
Block a user