Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion netbox/extras/lookups.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,22 @@ def as_sql(self, compiler, connection):
return f"CAST(LENGTH({sql}) AS BOOLEAN) IS TRUE", params


class NetHost(Lookup):
"""
Similar to ipam.lookups.NetHost, but casts the field to INET.
"""
lookup_name = 'net_host'

def as_sql(self, qn, connection):
lhs, lhs_params = self.process_lhs(qn, connection)
rhs, rhs_params = self.process_rhs(qn, connection)
params = lhs_params + rhs_params
return 'HOST(CAST(%s AS INET)) = HOST(%s)' % (lhs, rhs), params


class NetContainsOrEquals(Lookup):
"""
This lookup has the same functionality as the one from the ipam app except lhs is cast to inet
Similar to ipam.lookups.NetContainsOrEquals, but casts the field to INET.
"""
lookup_name = 'net_contains_or_equals'

Expand All @@ -32,4 +45,5 @@ def as_sql(self, qn, connection):


CharField.register_lookup(Empty)
CachedValueField.register_lookup(NetHost)
CachedValueField.register_lookup(NetContainsOrEquals)
15 changes: 15 additions & 0 deletions netbox/ipam/models/ip.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@ def family(self):
return self.prefix.version
return None

@property
def ipv6_full(self):
if self.prefix and self.prefix.version == 6:
return netaddr.IPAddress(self.prefix).format(netaddr.ipv6_full)

def get_child_prefixes(self):
"""
Return all Prefixes within this Aggregate
Expand Down Expand Up @@ -330,6 +335,11 @@ def family(self):
def mask_length(self):
return self.prefix.prefixlen if self.prefix else None

@property
def ipv6_full(self):
if self.prefix and self.prefix.version == 6:
return netaddr.IPAddress(self.prefix).format(netaddr.ipv6_full)

@property
def depth(self):
return self._depth
Expand Down Expand Up @@ -808,6 +818,11 @@ def __init__(self, *args, **kwargs):
self._original_assigned_object_id = self.__dict__.get('assigned_object_id')
self._original_assigned_object_type_id = self.__dict__.get('assigned_object_type_id')

@property
def ipv6_full(self):
if self.address and self.address.version == 6:
return netaddr.IPAddress(self.address).format(netaddr.ipv6_full)

def get_duplicates(self):
return IPAddress.objects.filter(
vrf=self.vrf,
Expand Down
8 changes: 5 additions & 3 deletions netbox/netbox/search/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,13 @@ def search(self, value, user=None, object_types=None, lookup=DEFAULT_LOOKUP_TYPE
if lookup in (LookupTypes.STARTSWITH, LookupTypes.ENDSWITH):
# "Starts/ends with" matches are valid only on string values
query_filter &= Q(type=FieldTypes.STRING)
elif lookup == LookupTypes.PARTIAL:
elif lookup in (LookupTypes.PARTIAL, LookupTypes.EXACT):
try:
# If the value looks like an IP address, add an extra match for CIDR values
# If the value looks like an IP address, add extra filters for CIDR/INET values
address = str(netaddr.IPNetwork(value.strip()).cidr)
query_filter |= Q(type=FieldTypes.CIDR) & Q(value__net_contains_or_equals=address)
query_filter |= Q(type=FieldTypes.INET) & Q(value__net_host=address)
if lookup == LookupTypes.PARTIAL:
query_filter |= Q(type=FieldTypes.CIDR) & Q(value__net_contains_or_equals=address)
except (AddrFormatError, ValueError):
pass

Expand Down