|
|
@@ -1,7 +1,6 @@
|
|
|
import json
|
|
|
|
|
|
from django import forms
|
|
|
-from django.conf import settings
|
|
|
from django.utils.safestring import mark_safe
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
|
@@ -10,7 +9,6 @@ from core.models import ContentType
|
|
|
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
|
|
|
from extras.choices import *
|
|
|
from extras.models import *
|
|
|
-from netbox.config import get_config, PARAMS
|
|
|
from netbox.forms import NetBoxModelForm
|
|
|
from tenancy.models import Tenant, TenantGroup
|
|
|
from utilities.forms import BootstrapMixin, add_blank_choice
|
|
|
@@ -21,11 +19,9 @@ from utilities.forms.fields import (
|
|
|
from utilities.forms.widgets import ChoicesWidget
|
|
|
from virtualization.models import Cluster, ClusterGroup, ClusterType
|
|
|
|
|
|
-
|
|
|
__all__ = (
|
|
|
'BookmarkForm',
|
|
|
'ConfigContextForm',
|
|
|
- 'ConfigRevisionForm',
|
|
|
'ConfigTemplateForm',
|
|
|
'CustomFieldChoiceSetForm',
|
|
|
'CustomFieldForm',
|
|
|
@@ -445,116 +441,3 @@ class JournalEntryForm(NetBoxModelForm):
|
|
|
'assigned_object_type': forms.HiddenInput,
|
|
|
'assigned_object_id': forms.HiddenInput,
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
-EMPTY_VALUES = ('', None, [], ())
|
|
|
-
|
|
|
-
|
|
|
-class ConfigFormMetaclass(forms.models.ModelFormMetaclass):
|
|
|
-
|
|
|
- def __new__(mcs, name, bases, attrs):
|
|
|
-
|
|
|
- # Emulate a declared field for each supported configuration parameter
|
|
|
- param_fields = {}
|
|
|
- for param in PARAMS:
|
|
|
- field_kwargs = {
|
|
|
- 'required': False,
|
|
|
- 'label': param.label,
|
|
|
- 'help_text': param.description,
|
|
|
- }
|
|
|
- field_kwargs.update(**param.field_kwargs)
|
|
|
- param_fields[param.name] = param.field(**field_kwargs)
|
|
|
- attrs.update(param_fields)
|
|
|
-
|
|
|
- return super().__new__(mcs, name, bases, attrs)
|
|
|
-
|
|
|
-
|
|
|
-class ConfigRevisionForm(BootstrapMixin, forms.ModelForm, metaclass=ConfigFormMetaclass):
|
|
|
- """
|
|
|
- Form for creating a new ConfigRevision.
|
|
|
- """
|
|
|
-
|
|
|
- fieldsets = (
|
|
|
- (_('Rack Elevations'), ('RACK_ELEVATION_DEFAULT_UNIT_HEIGHT', 'RACK_ELEVATION_DEFAULT_UNIT_WIDTH')),
|
|
|
- (_('Power'), ('POWERFEED_DEFAULT_VOLTAGE', 'POWERFEED_DEFAULT_AMPERAGE', 'POWERFEED_DEFAULT_MAX_UTILIZATION')),
|
|
|
- (_('IPAM'), ('ENFORCE_GLOBAL_UNIQUE', 'PREFER_IPV4')),
|
|
|
- (_('Security'), ('ALLOWED_URL_SCHEMES',)),
|
|
|
- (_('Banners'), ('BANNER_LOGIN', 'BANNER_MAINTENANCE', 'BANNER_TOP', 'BANNER_BOTTOM')),
|
|
|
- (_('Pagination'), ('PAGINATE_COUNT', 'MAX_PAGE_SIZE')),
|
|
|
- (_('Validation'), ('CUSTOM_VALIDATORS', 'PROTECTION_RULES')),
|
|
|
- (_('User Preferences'), ('DEFAULT_USER_PREFERENCES',)),
|
|
|
- (_('Miscellaneous'), (
|
|
|
- 'MAINTENANCE_MODE', 'GRAPHQL_ENABLED', 'CHANGELOG_RETENTION', 'JOB_RETENTION', 'MAPS_URL',
|
|
|
- )),
|
|
|
- (_('Config Revision'), ('comment',))
|
|
|
- )
|
|
|
-
|
|
|
- class Meta:
|
|
|
- model = ConfigRevision
|
|
|
- fields = '__all__'
|
|
|
- widgets = {
|
|
|
- 'BANNER_LOGIN': forms.Textarea(attrs={'class': 'font-monospace'}),
|
|
|
- 'BANNER_MAINTENANCE': forms.Textarea(attrs={'class': 'font-monospace'}),
|
|
|
- 'BANNER_TOP': forms.Textarea(attrs={'class': 'font-monospace'}),
|
|
|
- 'BANNER_BOTTOM': forms.Textarea(attrs={'class': 'font-monospace'}),
|
|
|
- 'CUSTOM_VALIDATORS': forms.Textarea(attrs={'class': 'font-monospace'}),
|
|
|
- 'PROTECTION_RULES': forms.Textarea(attrs={'class': 'font-monospace'}),
|
|
|
- 'comment': forms.Textarea(),
|
|
|
- }
|
|
|
-
|
|
|
- def __init__(self, *args, **kwargs):
|
|
|
- super().__init__(*args, **kwargs)
|
|
|
-
|
|
|
- # Append current parameter values to form field help texts and check for static configurations
|
|
|
- config = get_config()
|
|
|
- for param in PARAMS:
|
|
|
- value = getattr(config, param.name)
|
|
|
-
|
|
|
- # Set the field's initial value, if it can be serialized. (This may not be the case e.g. for
|
|
|
- # CUSTOM_VALIDATORS, which may reference Python objects.)
|
|
|
- try:
|
|
|
- json.dumps(value)
|
|
|
- if type(value) in (tuple, list):
|
|
|
- self.fields[param.name].initial = ', '.join(value)
|
|
|
- else:
|
|
|
- self.fields[param.name].initial = value
|
|
|
- except TypeError:
|
|
|
- pass
|
|
|
-
|
|
|
- # Check whether this parameter is statically configured (e.g. in configuration.py)
|
|
|
- if hasattr(settings, param.name):
|
|
|
- self.fields[param.name].disabled = True
|
|
|
- self.fields[param.name].help_text = _(
|
|
|
- 'This parameter has been defined statically and cannot be modified.'
|
|
|
- )
|
|
|
- continue
|
|
|
-
|
|
|
- # Set the field's help text
|
|
|
- help_text = self.fields[param.name].help_text
|
|
|
- if help_text:
|
|
|
- help_text += '<br />' # Line break
|
|
|
- help_text += _('Current value: <strong>{value}</strong>').format(value=value or '—')
|
|
|
- if value == param.default:
|
|
|
- help_text += _(' (default)')
|
|
|
- self.fields[param.name].help_text = help_text
|
|
|
-
|
|
|
- def save(self, commit=True):
|
|
|
- instance = super().save(commit=False)
|
|
|
-
|
|
|
- # Populate JSON data on the instance
|
|
|
- instance.data = self.render_json()
|
|
|
-
|
|
|
- if commit:
|
|
|
- instance.save()
|
|
|
-
|
|
|
- return instance
|
|
|
-
|
|
|
- def render_json(self):
|
|
|
- json = {}
|
|
|
-
|
|
|
- # Iterate through each field and populate non-empty values
|
|
|
- for field_name in self.declared_fields:
|
|
|
- if field_name in self.cleaned_data and self.cleaned_data[field_name] not in EMPTY_VALUES:
|
|
|
- json[field_name] = self.cleaned_data[field_name]
|
|
|
-
|
|
|
- return json
|