diff --git a/docs/release-notes/version-2.6.md b/docs/release-notes/version-2.6.md index 792e8990a..1bc1c136b 100644 --- a/docs/release-notes/version-2.6.md +++ b/docs/release-notes/version-2.6.md @@ -2,6 +2,7 @@ ## Enhancements +* [#3509](https://github.com/netbox-community/netbox/issues/3509) - Added IPAddressVar for custom scripts * [#3525](https://github.com/netbox-community/netbox/issues/3525) - Enable IP address filtering with multiple address terms ## Bug Fixes @@ -42,7 +43,7 @@ * [#3872](https://github.com/netbox-community/netbox/issues/3872) - Paginate related IPs on the IP address view * [#3876](https://github.com/netbox-community/netbox/issues/3876) - Fix minimum/maximum value rendering for site ASN field * [#3882](https://github.com/netbox-community/netbox/issues/3882) - Fix filtering of devices by rack group -* [#3898](https://github.com/netbox-community/netbox/issues/3898) - Fix references to deleted cables without a label +* [#3898](https://github.com/netbox-community/netbox/issues/3898) - Fix references to deleted cables without a label * [#3905](https://github.com/netbox-community/netbox/issues/3905) - Fix divide-by-zero on power feeds with low power values --- diff --git a/netbox/extras/scripts.py b/netbox/extras/scripts.py index 4876595a3..4ea4765d7 100644 --- a/netbox/extras/scripts.py +++ b/netbox/extras/scripts.py @@ -14,7 +14,7 @@ from django.db import transaction from mptt.forms import TreeNodeChoiceField, TreeNodeMultipleChoiceField from mptt.models import MPTTModel -from ipam.formfields import IPFormField +from ipam.formfields import IPAddressFormField, IPNetworkFormField from utilities.exceptions import AbortTransaction from utilities.validators import MaxPrefixLengthValidator, MinPrefixLengthValidator from .constants import LOG_DEFAULT, LOG_FAILURE, LOG_INFO, LOG_SUCCESS, LOG_WARNING @@ -27,6 +27,7 @@ __all__ = [ 'ChoiceVar', 'FileVar', 'IntegerVar', + 'IPAddressVar', 'IPNetworkVar', 'MultiObjectVar', 'ObjectVar', @@ -196,11 +197,18 @@ class FileVar(ScriptVariable): form_field = forms.FileField +class IPAddressVar(ScriptVariable): + """ + An IPv4 or IPv6 address. + """ + form_field = IPAddressFormField + + class IPNetworkVar(ScriptVariable): """ An IPv4 or IPv6 prefix. """ - form_field = IPFormField + form_field = IPNetworkFormField def __init__(self, min_prefix_length=None, max_prefix_length=None, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/netbox/ipam/fields.py b/netbox/ipam/fields.py index 845820432..da750a09c 100644 --- a/netbox/ipam/fields.py +++ b/netbox/ipam/fields.py @@ -3,7 +3,7 @@ from django.db import models from netaddr import AddrFormatError, IPNetwork, IPAddress from . import lookups -from .formfields import IPFormField +from .formfields import IPNetworkFormField def prefix_validator(prefix): @@ -40,7 +40,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()} diff --git a/netbox/ipam/formfields.py b/netbox/ipam/formfields.py index 2909a54b1..d76351f33 100644 --- a/netbox/ipam/formfields.py +++ b/netbox/ipam/formfields.py @@ -1,13 +1,35 @@ 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 CIDR mask).", + } + + def to_python(self, value): + if not value: + return None + + if isinstance(value, IPAddress): + return value + + # Prevent CIDR masks; an IPAddress doesn't have one + if len(value.split('/')) != 1: + raise ValidationError('CIDR mask (e.g. /24) is not allowed.') + + try: + return IPAddress(value) + 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).", }