Ver Fonte

Introduce IPAddressVar and IPAddressWithMaskVar

Jeremy Stretch há 6 anos atrás
pai
commit
f41564b578

+ 13 - 2
docs/additional-features/custom-scripts.md

@@ -124,7 +124,7 @@ Arbitrary text of any length. Renders as multi-line text input field.
 
 Stored a numeric integer. Options include:
 
-* `min_value:` - Minimum value
+* `min_value` - Minimum value
 * `max_value` - Maximum value
 
 ### BooleanVar
@@ -158,9 +158,20 @@ A NetBox object. The list of available objects is defined by the queryset parame
 
 An uploaded file. Note that uploaded files are present in memory only for the duration of the script's execution: They will not be save for future use.
 
+### IPAddressVar
+
+An IPv4 or IPv6 address, without a mask. Returns a `netaddr.IPAddress` object.
+
+### IPAddressWithMaskVar
+
+An IPv4 or IPv6 address with a mask. Returns a `netaddr.IPNetwork` object which includes the mask.
+
 ### IPNetworkVar
 
-An IPv4 or IPv6 network with a mask.
+An IPv4 or IPv6 network with a mask. Returns a `netaddr.IPNetwork` object. Two attributes are available to validate the provided mask:
+
+* `min_prefix_length` - Minimum length of the mask (default: none)
+* `max_prefix_length` - Maximum length of the mask (default: none)
 
 ### Default Options
 

+ 32 - 11
netbox/extras/scripts.py

@@ -14,10 +14,10 @@ from django.db import transaction
 from mptt.forms import TreeNodeChoiceField, TreeNodeMultipleChoiceField
 from mptt.models import MPTTModel
 
-from ipam.formfields import IPFormField
-from utilities.exceptions import AbortTransaction
-from ipam.validators import MaxPrefixLengthValidator, MinPrefixLengthValidator
+from ipam.formfields import IPAddressFormField, IPNetworkFormField
+from ipam.validators import MaxPrefixLengthValidator, MinPrefixLengthValidator, prefix_validator
 from .constants import LOG_DEFAULT, LOG_FAILURE, LOG_INFO, LOG_SUCCESS, LOG_WARNING
+from utilities.exceptions import AbortTransaction
 from .forms import ScriptForm
 from .signals import purge_changelog
 
@@ -27,6 +27,8 @@ __all__ = [
     'ChoiceVar',
     'FileVar',
     'IntegerVar',
+    'IPAddressVar',
+    'IPAddressWithMaskVar',
     'IPNetworkVar',
     'MultiObjectVar',
     'ObjectVar',
@@ -48,15 +50,19 @@ class ScriptVariable:
 
     def __init__(self, label='', description='', default=None, required=True):
 
-        # Default field attributes
-        self.field_attrs = {
-            'help_text': description,
-            'required': required
-        }
+        # Initialize field attributes
+        if not hasattr(self, 'field_attrs'):
+            self.field_attrs = {}
+        if description:
+            self.field_attrs['help_text'] = description
         if label:
             self.field_attrs['label'] = label
         if default:
             self.field_attrs['initial'] = default
+        if required:
+            self.field_attrs['required'] = True
+        if 'validators' not in self.field_attrs:
+            self.field_attrs['validators'] = []
 
     def as_field(self):
         """
@@ -196,17 +202,32 @@ class FileVar(ScriptVariable):
     form_field = forms.FileField
 
 
+class IPAddressVar(ScriptVariable):
+    """
+    An IPv4 or IPv6 address without a mask.
+    """
+    form_field = IPAddressFormField
+
+
+class IPAddressWithMaskVar(ScriptVariable):
+    """
+    An IPv4 or IPv6 address with a mask.
+    """
+    form_field = IPNetworkFormField
+
+
 class IPNetworkVar(ScriptVariable):
     """
     An IPv4 or IPv6 prefix.
     """
-    form_field = IPFormField
+    form_field = IPNetworkFormField
+    field_attrs = {
+        'validators': [prefix_validator]
+    }
 
     def __init__(self, min_prefix_length=None, max_prefix_length=None, *args, **kwargs):
         super().__init__(*args, **kwargs)
 
-        self.field_attrs['validators'] = list()
-
         # Optional minimum/maximum prefix lengths
         if min_prefix_length is not None:
             self.field_attrs['validators'].append(

+ 2 - 2
netbox/ipam/fields.py

@@ -3,7 +3,7 @@ from django.db import models
 from netaddr import AddrFormatError, IPNetwork
 
 from . import lookups, validators
-from .formfields import IPFormField
+from .formfields import IPNetworkFormField
 
 
 class BaseIPField(models.Field):
@@ -33,7 +33,7 @@ class BaseIPField(models.Field):
         return str(self.to_python(value))
 
     def form_class(self):
-        return IPFormField
+        return IPNetworkFormField
 
     def formfield(self, **kwargs):
         defaults = {'form_class': self.form_class()}

+ 22 - 2
netbox/ipam/formfields.py

@@ -1,13 +1,33 @@
 from django import forms
 from django.core.exceptions import ValidationError
-from netaddr import IPNetwork, AddrFormatError
+from netaddr import IPAddress, IPNetwork, AddrFormatError
 
 
 #
 # Form fields
 #
 
-class IPFormField(forms.Field):
+class IPAddressFormField(forms.Field):
+    default_error_messages = {
+        'invalid': "Enter a valid IPv4 or IPv6 address (without a mask).",
+    }
+
+    def to_python(self, value):
+        if not value:
+            return None
+
+        if isinstance(value, IPAddress):
+            return value
+
+        try:
+            return IPAddress(value)
+        except ValueError:
+            raise ValidationError('This field requires an IP address without a mask.')
+        except AddrFormatError:
+            raise ValidationError("Please specify a valid IPv4 or IPv6 address.")
+
+
+class IPNetworkFormField(forms.Field):
     default_error_messages = {
         'invalid': "Enter a valid IPv4 or IPv6 address (with CIDR mask).",
     }