Merge pull request #4178 from netbox-community/4081-drop-ip-family

Closes #4081: Drop the family column from IP objects
This commit is contained in:
Jeremy Stretch 2020-02-14 15:42:19 -05:00 committed by GitHub
commit f6cbce65fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 264 additions and 214 deletions

View File

@ -9,6 +9,7 @@
* [#2519](https://github.com/netbox-community/netbox/issues/2519) - Avoid race condition when provisioning "next available" IPs/prefixes via the API * [#2519](https://github.com/netbox-community/netbox/issues/2519) - Avoid race condition when provisioning "next available" IPs/prefixes via the API
* [#4168](https://github.com/netbox-community/netbox/issues/4168) - Role is not required when creating a virtual machine * [#4168](https://github.com/netbox-community/netbox/issues/4168) - Role is not required when creating a virtual machine
* [#4175](https://github.com/netbox-community/netbox/issues/4175) - Fix potential exception when bulk editing objects from a filtered list
--- ---

View File

@ -1857,14 +1857,14 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
# Collect interface IPs # Collect interface IPs
interface_ips = IPAddress.objects.prefetch_related('interface').filter( interface_ips = IPAddress.objects.prefetch_related('interface').filter(
family=family, interface_id__in=interface_ids address__family=family, interface_id__in=interface_ids
) )
if interface_ips: if interface_ips:
ip_list = [(ip.id, '{} ({})'.format(ip.address, ip.interface)) for ip in interface_ips] ip_list = [(ip.id, '{} ({})'.format(ip.address, ip.interface)) for ip in interface_ips]
ip_choices.append(('Interface IPs', ip_list)) ip_choices.append(('Interface IPs', ip_list))
# Collect NAT IPs # Collect NAT IPs
nat_ips = IPAddress.objects.prefetch_related('nat_inside').filter( nat_ips = IPAddress.objects.prefetch_related('nat_inside').filter(
family=family, nat_inside__interface__in=interface_ids address__family=family, nat_inside__interface__in=interface_ids
) )
if nat_ips: if nat_ips:
ip_list = [(ip.id, '{} ({})'.format(ip.address, ip.nat_inside.address)) for ip in nat_ips] ip_list = [(ip.id, '{} ({})'.format(ip.address, ip.nat_inside.address)) for ip in nat_ips]

View File

@ -1144,8 +1144,8 @@ class DeviceTestCase(TestCase):
# Assign primary IPs for filtering # Assign primary IPs for filtering
ipaddresses = ( ipaddresses = (
IPAddress(family=4, address='192.0.2.1/24', interface=interfaces[0]), IPAddress(address='192.0.2.1/24', interface=interfaces[0]),
IPAddress(family=4, address='192.0.2.2/24', interface=interfaces[1]), IPAddress(address='192.0.2.2/24', interface=interfaces[1]),
) )
IPAddress.objects.bulk_create(ipaddresses) IPAddress.objects.bulk_create(ipaddresses)
Device.objects.filter(pk=devices[0].pk).update(primary_ip4=ipaddresses[0]) Device.objects.filter(pk=devices[0].pk).update(primary_ip4=ipaddresses[0])

View File

@ -63,6 +63,7 @@ IPNetworkField.register_lookup(lookups.NetContained)
IPNetworkField.register_lookup(lookups.NetContainedOrEqual) IPNetworkField.register_lookup(lookups.NetContainedOrEqual)
IPNetworkField.register_lookup(lookups.NetContains) IPNetworkField.register_lookup(lookups.NetContains)
IPNetworkField.register_lookup(lookups.NetContainsOrEquals) IPNetworkField.register_lookup(lookups.NetContainsOrEquals)
IPNetworkField.register_lookup(lookups.NetFamily)
IPNetworkField.register_lookup(lookups.NetMaskLength) IPNetworkField.register_lookup(lookups.NetMaskLength)
@ -90,4 +91,5 @@ IPAddressField.register_lookup(lookups.NetContainsOrEquals)
IPAddressField.register_lookup(lookups.NetHost) IPAddressField.register_lookup(lookups.NetHost)
IPAddressField.register_lookup(lookups.NetIn) IPAddressField.register_lookup(lookups.NetIn)
IPAddressField.register_lookup(lookups.NetHostContained) IPAddressField.register_lookup(lookups.NetHostContained)
IPAddressField.register_lookup(lookups.NetFamily)
IPAddressField.register_lookup(lookups.NetMaskLength) IPAddressField.register_lookup(lookups.NetMaskLength)

View File

@ -73,6 +73,10 @@ class AggregateFilterSet(CustomFieldFilterSet, CreatedUpdatedFilterSet):
method='search', method='search',
label='Search', label='Search',
) )
family = django_filters.NumberFilter(
field_name='prefix',
lookup_expr='family'
)
prefix = django_filters.CharFilter( prefix = django_filters.CharFilter(
method='filter_prefix', method='filter_prefix',
label='Prefix', label='Prefix',
@ -91,7 +95,7 @@ class AggregateFilterSet(CustomFieldFilterSet, CreatedUpdatedFilterSet):
class Meta: class Meta:
model = Aggregate model = Aggregate
fields = ['family', 'date_added'] fields = ('date_added',)
def search(self, queryset, name, value): def search(self, queryset, name, value):
if not value.strip(): if not value.strip():
@ -134,6 +138,10 @@ class PrefixFilterSet(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilt
method='search', method='search',
label='Search', label='Search',
) )
family = django_filters.NumberFilter(
field_name='prefix',
lookup_expr='family'
)
prefix = django_filters.CharFilter( prefix = django_filters.CharFilter(
method='filter_prefix', method='filter_prefix',
label='Prefix', label='Prefix',
@ -211,7 +219,7 @@ class PrefixFilterSet(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilt
class Meta: class Meta:
model = Prefix model = Prefix
fields = ['family', 'is_pool'] fields = ('is_pool',)
def search(self, queryset, name, value): def search(self, queryset, name, value):
if not value.strip(): if not value.strip():
@ -282,6 +290,10 @@ class IPAddressFilterSet(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedF
method='search', method='search',
label='Search', label='Search',
) )
family = django_filters.NumberFilter(
field_name='address',
lookup_expr='family'
)
parent = django_filters.CharFilter( parent = django_filters.CharFilter(
method='search_by_parent', method='search_by_parent',
label='Parent prefix', label='Parent prefix',
@ -350,7 +362,7 @@ class IPAddressFilterSet(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedF
class Meta: class Meta:
model = IPAddress model = IPAddress
fields = ['family', 'dns_name'] fields = ('dns_name',)
def search(self, queryset, name, value): def search(self, queryset, name, value):
if not value.strip(): if not value.strip():

View File

@ -154,6 +154,15 @@ class NetHostContained(Lookup):
return 'CAST(HOST(%s) AS INET) << %s' % (lhs, rhs), params return 'CAST(HOST(%s) AS INET) << %s' % (lhs, rhs), params
class NetFamily(Transform):
lookup_name = 'family'
function = 'FAMILY'
@property
def output_field(self):
return IntegerField()
class NetMaskLength(Transform): class NetMaskLength(Transform):
lookup_name = 'net_mask_length' lookup_name = 'net_mask_length'
function = 'MASKLEN' function = 'MASKLEN'

View File

@ -13,4 +13,4 @@ class IPAddressManager(models.Manager):
IP address as a /32 or /128. IP address as a /32 or /128.
""" """
qs = super().get_queryset() qs = super().get_queryset()
return qs.annotate(host=RawSQL('INET(HOST(ipam_ipaddress.address))', [])).order_by('family', 'host') return qs.annotate(host=RawSQL('INET(HOST(ipam_ipaddress.address))', [])).order_by('host')

View File

@ -0,0 +1,38 @@
# Generated by Django 2.2.9 on 2020-02-14 19:36
from django.db import migrations
import django.db.models.expressions
class Migration(migrations.Migration):
dependencies = [
('ipam', '0034_fix_ipaddress_status_dhcp'),
]
operations = [
migrations.AlterModelOptions(
name='aggregate',
options={'ordering': ('prefix', 'pk')},
),
migrations.AlterModelOptions(
name='ipaddress',
options={'ordering': ('address', 'pk'), 'verbose_name': 'IP address', 'verbose_name_plural': 'IP addresses'},
),
migrations.AlterModelOptions(
name='prefix',
options={'ordering': (django.db.models.expressions.OrderBy(django.db.models.expressions.F('vrf'), nulls_first=True), 'prefix', 'pk'), 'verbose_name_plural': 'prefixes'},
),
migrations.RemoveField(
model_name='aggregate',
name='family',
),
migrations.RemoveField(
model_name='ipaddress',
name='family',
),
migrations.RemoveField(
model_name='prefix',
name='family',
),
]

View File

@ -150,9 +150,6 @@ class Aggregate(ChangeLoggedModel, CustomFieldModel):
An aggregate exists at the root level of the IP address space hierarchy in NetBox. Aggregates are used to organize An aggregate exists at the root level of the IP address space hierarchy in NetBox. Aggregates are used to organize
the hierarchy and track the overall utilization of available address space. Each Aggregate is assigned to a RIR. the hierarchy and track the overall utilization of available address space. Each Aggregate is assigned to a RIR.
""" """
family = models.PositiveSmallIntegerField(
choices=IPAddressFamilyChoices
)
prefix = IPNetworkField() prefix = IPNetworkField()
rir = models.ForeignKey( rir = models.ForeignKey(
to='ipam.RIR', to='ipam.RIR',
@ -182,7 +179,7 @@ class Aggregate(ChangeLoggedModel, CustomFieldModel):
] ]
class Meta: class Meta:
ordering = ('family', 'prefix', 'pk') # (family, prefix) may be non-unique ordering = ('prefix', 'pk') # prefix may be non-unique
def __str__(self): def __str__(self):
return str(self.prefix) return str(self.prefix)
@ -225,12 +222,6 @@ class Aggregate(ChangeLoggedModel, CustomFieldModel):
) )
}) })
def save(self, *args, **kwargs):
if self.prefix:
# Infer address family from IPNetwork object
self.family = self.prefix.version
super().save(*args, **kwargs)
def to_csv(self): def to_csv(self):
return ( return (
self.prefix, self.prefix,
@ -239,6 +230,12 @@ class Aggregate(ChangeLoggedModel, CustomFieldModel):
self.description, self.description,
) )
@property
def family(self):
if self.prefix:
return self.prefix.version
return None
def get_utilization(self): def get_utilization(self):
""" """
Determine the prefix utilization of the aggregate and return it as a percentage. Determine the prefix utilization of the aggregate and return it as a percentage.
@ -291,10 +288,6 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
VRFs. A Prefix must be assigned a status and may optionally be assigned a used-define Role. A Prefix can also be VRFs. A Prefix must be assigned a status and may optionally be assigned a used-define Role. A Prefix can also be
assigned to a VLAN where appropriate. assigned to a VLAN where appropriate.
""" """
family = models.PositiveSmallIntegerField(
choices=IPAddressFamilyChoices,
editable=False
)
prefix = IPNetworkField( prefix = IPNetworkField(
help_text='IPv4 or IPv6 network with mask' help_text='IPv4 or IPv6 network with mask'
) )
@ -376,7 +369,7 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
} }
class Meta: class Meta:
ordering = (F('vrf').asc(nulls_first=True), 'family', 'prefix', 'pk') # (vrf, family, prefix) may be non-unique ordering = (F('vrf').asc(nulls_first=True), 'prefix', 'pk') # (vrf, prefix) may be non-unique
verbose_name_plural = 'prefixes' verbose_name_plural = 'prefixes'
def __str__(self): def __str__(self):
@ -423,9 +416,6 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
# Clear host bits from prefix # Clear host bits from prefix
self.prefix = self.prefix.cidr self.prefix = self.prefix.cidr
# Record address family
self.family = self.prefix.version
super().save(*args, **kwargs) super().save(*args, **kwargs)
def to_csv(self): def to_csv(self):
@ -442,6 +432,12 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
self.description, self.description,
) )
@property
def family(self):
if self.prefix:
return self.prefix.version
return None
def _set_prefix_length(self, value): def _set_prefix_length(self, value):
""" """
Expose the IPNetwork object's prefixlen attribute on the parent model so that it can be manipulated directly, Expose the IPNetwork object's prefixlen attribute on the parent model so that it can be manipulated directly,
@ -501,9 +497,9 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
# All IP addresses within a point-to-point prefix (IPv4 /31 or IPv6 /127) are considered usable # All IP addresses within a point-to-point prefix (IPv4 /31 or IPv6 /127) are considered usable
if ( if (
self.family == 4 and self.prefix.prefixlen == 31 # RFC 3021 self.prefix.version == 4 and self.prefix.prefixlen == 31 # RFC 3021
) or ( ) or (
self.family == 6 and self.prefix.prefixlen == 127 # RFC 6164 self.prefix.version == 6 and self.prefix.prefixlen == 127 # RFC 6164
): ):
return available_ips return available_ips
@ -546,7 +542,7 @@ class Prefix(ChangeLoggedModel, CustomFieldModel):
# Compile an IPSet to avoid counting duplicate IPs # Compile an IPSet to avoid counting duplicate IPs
child_count = netaddr.IPSet([ip.address.ip for ip in self.get_child_ips()]).size child_count = netaddr.IPSet([ip.address.ip for ip in self.get_child_ips()]).size
prefix_size = self.prefix.size prefix_size = self.prefix.size
if self.family == 4 and self.prefix.prefixlen < 31 and not self.is_pool: if self.prefix.version == 4 and self.prefix.prefixlen < 31 and not self.is_pool:
prefix_size -= 2 prefix_size -= 2
return int(float(child_count) / prefix_size * 100) return int(float(child_count) / prefix_size * 100)
@ -562,10 +558,6 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel):
for example, when mapping public addresses to private addresses. When an Interface has been assigned an IPAddress for example, when mapping public addresses to private addresses. When an Interface has been assigned an IPAddress
which has a NAT outside IP, that Interface's Device can use either the inside or outside IP as its primary IP. which has a NAT outside IP, that Interface's Device can use either the inside or outside IP as its primary IP.
""" """
family = models.PositiveSmallIntegerField(
choices=IPAddressFamilyChoices,
editable=False
)
address = IPAddressField( address = IPAddressField(
help_text='IPv4 or IPv6 address (with mask)' help_text='IPv4 or IPv6 address (with mask)'
) )
@ -659,7 +651,7 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel):
} }
class Meta: class Meta:
ordering = ('family', 'address', 'pk') # (family, address) may be non-unique ordering = ('address', 'pk') # address may be non-unique
verbose_name = 'IP address' verbose_name = 'IP address'
verbose_name_plural = 'IP addresses' verbose_name_plural = 'IP addresses'
@ -727,10 +719,6 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
# Record address family
if isinstance(self.address, netaddr.IPNetwork):
self.family = self.address.version
# Force dns_name to lowercase # Force dns_name to lowercase
self.dns_name = self.dns_name.lower() self.dns_name = self.dns_name.lower()
@ -754,9 +742,9 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel):
def to_csv(self): def to_csv(self):
# Determine if this IP is primary for a Device # Determine if this IP is primary for a Device
if self.family == 4 and getattr(self, 'primary_ip4_for', False): if self.address.version == 4 and getattr(self, 'primary_ip4_for', False):
is_primary = True is_primary = True
elif self.family == 6 and getattr(self, 'primary_ip6_for', False): elif self.address.version == 6 and getattr(self, 'primary_ip6_for', False):
is_primary = True is_primary = True
else: else:
is_primary = False is_primary = False
@ -775,6 +763,12 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel):
self.description, self.description,
) )
@property
def family(self):
if self.address:
return self.address.version
return None
def _set_mask_length(self, value): def _set_mask_length(self, value):
""" """
Expose the IPNetwork object's prefixlen attribute on the parent model so that it can be manipulated directly, Expose the IPNetwork object's prefixlen attribute on the parent model so that it can be manipulated directly,

View File

@ -96,12 +96,12 @@ class AggregateTestCase(TestCase):
RIR.objects.bulk_create(rirs) RIR.objects.bulk_create(rirs)
aggregates = ( aggregates = (
Aggregate(family=4, prefix='10.1.0.0/16', rir=rirs[0], date_added='2020-01-01'), Aggregate(prefix='10.1.0.0/16', rir=rirs[0], date_added='2020-01-01'),
Aggregate(family=4, prefix='10.2.0.0/16', rir=rirs[0], date_added='2020-01-02'), Aggregate(prefix='10.2.0.0/16', rir=rirs[0], date_added='2020-01-02'),
Aggregate(family=4, prefix='10.3.0.0/16', rir=rirs[1], date_added='2020-01-03'), Aggregate(prefix='10.3.0.0/16', rir=rirs[1], date_added='2020-01-03'),
Aggregate(family=6, prefix='2001:db8:1::/48', rir=rirs[1], date_added='2020-01-04'), Aggregate(prefix='2001:db8:1::/48', rir=rirs[1], date_added='2020-01-04'),
Aggregate(family=6, prefix='2001:db8:2::/48', rir=rirs[2], date_added='2020-01-05'), Aggregate(prefix='2001:db8:2::/48', rir=rirs[2], date_added='2020-01-05'),
Aggregate(family=6, prefix='2001:db8:3::/48', rir=rirs[2], date_added='2020-01-06'), Aggregate(prefix='2001:db8:3::/48', rir=rirs[2], date_added='2020-01-06'),
) )
Aggregate.objects.bulk_create(aggregates) Aggregate.objects.bulk_create(aggregates)
@ -199,16 +199,16 @@ class PrefixTestCase(TestCase):
Role.objects.bulk_create(roles) Role.objects.bulk_create(roles)
prefixes = ( prefixes = (
Prefix(family=4, prefix='10.0.0.0/24', site=None, vrf=None, vlan=None, role=None, is_pool=True), Prefix(prefix='10.0.0.0/24', site=None, vrf=None, vlan=None, role=None, is_pool=True),
Prefix(family=4, prefix='10.0.1.0/24', site=sites[0], vrf=vrfs[0], vlan=vlans[0], role=roles[0]), Prefix(prefix='10.0.1.0/24', site=sites[0], vrf=vrfs[0], vlan=vlans[0], role=roles[0]),
Prefix(family=4, prefix='10.0.2.0/24', site=sites[1], vrf=vrfs[1], vlan=vlans[1], role=roles[1], status=PrefixStatusChoices.STATUS_DEPRECATED), Prefix(prefix='10.0.2.0/24', site=sites[1], vrf=vrfs[1], vlan=vlans[1], role=roles[1], status=PrefixStatusChoices.STATUS_DEPRECATED),
Prefix(family=4, prefix='10.0.3.0/24', site=sites[2], vrf=vrfs[2], vlan=vlans[2], role=roles[2], status=PrefixStatusChoices.STATUS_RESERVED), Prefix(prefix='10.0.3.0/24', site=sites[2], vrf=vrfs[2], vlan=vlans[2], role=roles[2], status=PrefixStatusChoices.STATUS_RESERVED),
Prefix(family=6, prefix='2001:db8::/64', site=None, vrf=None, vlan=None, role=None, is_pool=True), Prefix(prefix='2001:db8::/64', site=None, vrf=None, vlan=None, role=None, is_pool=True),
Prefix(family=6, prefix='2001:db8:0:1::/64', site=sites[0], vrf=vrfs[0], vlan=vlans[0], role=roles[0]), Prefix(prefix='2001:db8:0:1::/64', site=sites[0], vrf=vrfs[0], vlan=vlans[0], role=roles[0]),
Prefix(family=6, prefix='2001:db8:0:2::/64', site=sites[1], vrf=vrfs[1], vlan=vlans[1], role=roles[1], status=PrefixStatusChoices.STATUS_DEPRECATED), Prefix(prefix='2001:db8:0:2::/64', site=sites[1], vrf=vrfs[1], vlan=vlans[1], role=roles[1], status=PrefixStatusChoices.STATUS_DEPRECATED),
Prefix(family=6, prefix='2001:db8:0:3::/64', site=sites[2], vrf=vrfs[2], vlan=vlans[2], role=roles[2], status=PrefixStatusChoices.STATUS_RESERVED), Prefix(prefix='2001:db8:0:3::/64', site=sites[2], vrf=vrfs[2], vlan=vlans[2], role=roles[2], status=PrefixStatusChoices.STATUS_RESERVED),
Prefix(family=4, prefix='10.0.0.0/16'), Prefix(prefix='10.0.0.0/16'),
Prefix(family=6, prefix='2001:db8::/32'), Prefix(prefix='2001:db8::/32'),
) )
Prefix.objects.bulk_create(prefixes) Prefix.objects.bulk_create(prefixes)
@ -333,16 +333,16 @@ class IPAddressTestCase(TestCase):
Interface.objects.bulk_create(interfaces) Interface.objects.bulk_create(interfaces)
ipaddresses = ( ipaddresses = (
IPAddress(family=4, address='10.0.0.1/24', vrf=None, interface=None, status=IPAddressStatusChoices.STATUS_ACTIVE, dns_name='ipaddress-a'), IPAddress(address='10.0.0.1/24', vrf=None, interface=None, status=IPAddressStatusChoices.STATUS_ACTIVE, dns_name='ipaddress-a'),
IPAddress(family=4, address='10.0.0.2/24', vrf=vrfs[0], interface=interfaces[0], status=IPAddressStatusChoices.STATUS_ACTIVE, dns_name='ipaddress-b'), IPAddress(address='10.0.0.2/24', vrf=vrfs[0], interface=interfaces[0], status=IPAddressStatusChoices.STATUS_ACTIVE, dns_name='ipaddress-b'),
IPAddress(family=4, address='10.0.0.3/24', vrf=vrfs[1], interface=interfaces[1], status=IPAddressStatusChoices.STATUS_RESERVED, role=IPAddressRoleChoices.ROLE_VIP, dns_name='ipaddress-c'), IPAddress(address='10.0.0.3/24', vrf=vrfs[1], interface=interfaces[1], status=IPAddressStatusChoices.STATUS_RESERVED, role=IPAddressRoleChoices.ROLE_VIP, dns_name='ipaddress-c'),
IPAddress(family=4, address='10.0.0.4/24', vrf=vrfs[2], interface=interfaces[2], status=IPAddressStatusChoices.STATUS_DEPRECATED, role=IPAddressRoleChoices.ROLE_SECONDARY, dns_name='ipaddress-d'), IPAddress(address='10.0.0.4/24', vrf=vrfs[2], interface=interfaces[2], status=IPAddressStatusChoices.STATUS_DEPRECATED, role=IPAddressRoleChoices.ROLE_SECONDARY, dns_name='ipaddress-d'),
IPAddress(family=4, address='10.0.0.1/25', vrf=None, interface=None, status=IPAddressStatusChoices.STATUS_ACTIVE), IPAddress(address='10.0.0.1/25', vrf=None, interface=None, status=IPAddressStatusChoices.STATUS_ACTIVE),
IPAddress(family=6, address='2001:db8::1/64', vrf=None, interface=None, status=IPAddressStatusChoices.STATUS_ACTIVE, dns_name='ipaddress-a'), IPAddress(address='2001:db8::1/64', vrf=None, interface=None, status=IPAddressStatusChoices.STATUS_ACTIVE, dns_name='ipaddress-a'),
IPAddress(family=6, address='2001:db8::2/64', vrf=vrfs[0], interface=interfaces[3], status=IPAddressStatusChoices.STATUS_ACTIVE, dns_name='ipaddress-b'), IPAddress(address='2001:db8::2/64', vrf=vrfs[0], interface=interfaces[3], status=IPAddressStatusChoices.STATUS_ACTIVE, dns_name='ipaddress-b'),
IPAddress(family=6, address='2001:db8::3/64', vrf=vrfs[1], interface=interfaces[4], status=IPAddressStatusChoices.STATUS_RESERVED, role=IPAddressRoleChoices.ROLE_VIP, dns_name='ipaddress-c'), IPAddress(address='2001:db8::3/64', vrf=vrfs[1], interface=interfaces[4], status=IPAddressStatusChoices.STATUS_RESERVED, role=IPAddressRoleChoices.ROLE_VIP, dns_name='ipaddress-c'),
IPAddress(family=6, address='2001:db8::4/64', vrf=vrfs[2], interface=interfaces[5], status=IPAddressStatusChoices.STATUS_DEPRECATED, role=IPAddressRoleChoices.ROLE_SECONDARY, dns_name='ipaddress-d'), IPAddress(address='2001:db8::4/64', vrf=vrfs[2], interface=interfaces[5], status=IPAddressStatusChoices.STATUS_DEPRECATED, role=IPAddressRoleChoices.ROLE_SECONDARY, dns_name='ipaddress-d'),
IPAddress(family=6, address='2001:db8::1/65', vrf=None, interface=None, status=IPAddressStatusChoices.STATUS_ACTIVE), IPAddress(address='2001:db8::1/65', vrf=None, interface=None, status=IPAddressStatusChoices.STATUS_ACTIVE),
) )
IPAddress.objects.bulk_create(ipaddresses) IPAddress.objects.bulk_create(ipaddresses)

View File

@ -15,22 +15,22 @@ class TestAggregate(TestCase):
# 25% utilization # 25% utilization
Prefix.objects.bulk_create(( Prefix.objects.bulk_create((
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.0.0/12')), Prefix(prefix=netaddr.IPNetwork('10.0.0.0/12')),
Prefix(family=4, prefix=netaddr.IPNetwork('10.16.0.0/12')), Prefix(prefix=netaddr.IPNetwork('10.16.0.0/12')),
Prefix(family=4, prefix=netaddr.IPNetwork('10.32.0.0/12')), Prefix(prefix=netaddr.IPNetwork('10.32.0.0/12')),
Prefix(family=4, prefix=netaddr.IPNetwork('10.48.0.0/12')), Prefix(prefix=netaddr.IPNetwork('10.48.0.0/12')),
)) ))
self.assertEqual(aggregate.get_utilization(), 25) self.assertEqual(aggregate.get_utilization(), 25)
# 50% utilization # 50% utilization
Prefix.objects.bulk_create(( Prefix.objects.bulk_create((
Prefix(family=4, prefix=netaddr.IPNetwork('10.64.0.0/10')), Prefix(prefix=netaddr.IPNetwork('10.64.0.0/10')),
)) ))
self.assertEqual(aggregate.get_utilization(), 50) self.assertEqual(aggregate.get_utilization(), 50)
# 100% utilization # 100% utilization
Prefix.objects.bulk_create(( Prefix.objects.bulk_create((
Prefix(family=4, prefix=netaddr.IPNetwork('10.128.0.0/9')), Prefix(prefix=netaddr.IPNetwork('10.128.0.0/9')),
)) ))
self.assertEqual(aggregate.get_utilization(), 100) self.assertEqual(aggregate.get_utilization(), 100)
@ -39,9 +39,9 @@ class TestPrefix(TestCase):
def test_get_duplicates(self): def test_get_duplicates(self):
prefixes = Prefix.objects.bulk_create(( prefixes = Prefix.objects.bulk_create((
Prefix(family=4, prefix=netaddr.IPNetwork('192.0.2.0/24')), Prefix(prefix=netaddr.IPNetwork('192.0.2.0/24')),
Prefix(family=4, prefix=netaddr.IPNetwork('192.0.2.0/24')), Prefix(prefix=netaddr.IPNetwork('192.0.2.0/24')),
Prefix(family=4, prefix=netaddr.IPNetwork('192.0.2.0/24')), Prefix(prefix=netaddr.IPNetwork('192.0.2.0/24')),
)) ))
duplicate_prefix_pks = [p.pk for p in prefixes[0].get_duplicates()] duplicate_prefix_pks = [p.pk for p in prefixes[0].get_duplicates()]
@ -54,11 +54,11 @@ class TestPrefix(TestCase):
VRF(name='VRF 3'), VRF(name='VRF 3'),
)) ))
prefixes = Prefix.objects.bulk_create(( prefixes = Prefix.objects.bulk_create((
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.0.0/16'), status=PrefixStatusChoices.STATUS_CONTAINER), Prefix(prefix=netaddr.IPNetwork('10.0.0.0/16'), status=PrefixStatusChoices.STATUS_CONTAINER),
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.0.0/24'), vrf=None), Prefix(prefix=netaddr.IPNetwork('10.0.0.0/24'), vrf=None),
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.1.0/24'), vrf=vrfs[0]), Prefix(prefix=netaddr.IPNetwork('10.0.1.0/24'), vrf=vrfs[0]),
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.2.0/24'), vrf=vrfs[1]), Prefix(prefix=netaddr.IPNetwork('10.0.2.0/24'), vrf=vrfs[1]),
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.3.0/24'), vrf=vrfs[2]), Prefix(prefix=netaddr.IPNetwork('10.0.3.0/24'), vrf=vrfs[2]),
)) ))
child_prefix_pks = {p.pk for p in prefixes[0].get_child_prefixes()} child_prefix_pks = {p.pk for p in prefixes[0].get_child_prefixes()}
@ -79,13 +79,13 @@ class TestPrefix(TestCase):
VRF(name='VRF 3'), VRF(name='VRF 3'),
)) ))
parent_prefix = Prefix.objects.create( parent_prefix = Prefix.objects.create(
family=4, prefix=netaddr.IPNetwork('10.0.0.0/16'), status=PrefixStatusChoices.STATUS_CONTAINER prefix=netaddr.IPNetwork('10.0.0.0/16'), status=PrefixStatusChoices.STATUS_CONTAINER
) )
ips = IPAddress.objects.bulk_create(( ips = IPAddress.objects.bulk_create((
IPAddress(family=4, address=netaddr.IPNetwork('10.0.0.1/24'), vrf=None), IPAddress(address=netaddr.IPNetwork('10.0.0.1/24'), vrf=None),
IPAddress(family=4, address=netaddr.IPNetwork('10.0.1.1/24'), vrf=vrfs[0]), IPAddress(address=netaddr.IPNetwork('10.0.1.1/24'), vrf=vrfs[0]),
IPAddress(family=4, address=netaddr.IPNetwork('10.0.2.1/24'), vrf=vrfs[1]), IPAddress(address=netaddr.IPNetwork('10.0.2.1/24'), vrf=vrfs[1]),
IPAddress(family=4, address=netaddr.IPNetwork('10.0.3.1/24'), vrf=vrfs[2]), IPAddress(address=netaddr.IPNetwork('10.0.3.1/24'), vrf=vrfs[2]),
)) ))
child_ip_pks = {p.pk for p in parent_prefix.get_child_ips()} child_ip_pks = {p.pk for p in parent_prefix.get_child_ips()}
@ -102,10 +102,10 @@ class TestPrefix(TestCase):
def test_get_available_prefixes(self): def test_get_available_prefixes(self):
prefixes = Prefix.objects.bulk_create(( prefixes = Prefix.objects.bulk_create((
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.0.0/16')), # Parent prefix Prefix(prefix=netaddr.IPNetwork('10.0.0.0/16')), # Parent prefix
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.0.0/20')), Prefix(prefix=netaddr.IPNetwork('10.0.0.0/20')),
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.32.0/20')), Prefix(prefix=netaddr.IPNetwork('10.0.32.0/20')),
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.128.0/18')), Prefix(prefix=netaddr.IPNetwork('10.0.128.0/18')),
)) ))
missing_prefixes = netaddr.IPSet([ missing_prefixes = netaddr.IPSet([
netaddr.IPNetwork('10.0.16.0/20'), netaddr.IPNetwork('10.0.16.0/20'),
@ -119,15 +119,15 @@ class TestPrefix(TestCase):
def test_get_available_ips(self): def test_get_available_ips(self):
parent_prefix = Prefix.objects.create(family=4, prefix=netaddr.IPNetwork('10.0.0.0/28')) parent_prefix = Prefix.objects.create(prefix=netaddr.IPNetwork('10.0.0.0/28'))
IPAddress.objects.bulk_create(( IPAddress.objects.bulk_create((
IPAddress(family=4, address=netaddr.IPNetwork('10.0.0.1/26')), IPAddress(address=netaddr.IPNetwork('10.0.0.1/26')),
IPAddress(family=4, address=netaddr.IPNetwork('10.0.0.3/26')), IPAddress(address=netaddr.IPNetwork('10.0.0.3/26')),
IPAddress(family=4, address=netaddr.IPNetwork('10.0.0.5/26')), IPAddress(address=netaddr.IPNetwork('10.0.0.5/26')),
IPAddress(family=4, address=netaddr.IPNetwork('10.0.0.7/26')), IPAddress(address=netaddr.IPNetwork('10.0.0.7/26')),
IPAddress(family=4, address=netaddr.IPNetwork('10.0.0.9/26')), IPAddress(address=netaddr.IPNetwork('10.0.0.9/26')),
IPAddress(family=4, address=netaddr.IPNetwork('10.0.0.11/26')), IPAddress(address=netaddr.IPNetwork('10.0.0.11/26')),
IPAddress(family=4, address=netaddr.IPNetwork('10.0.0.13/26')), IPAddress(address=netaddr.IPNetwork('10.0.0.13/26')),
)) ))
missing_ips = netaddr.IPSet([ missing_ips = netaddr.IPSet([
'10.0.0.2/32', '10.0.0.2/32',
@ -145,40 +145,39 @@ class TestPrefix(TestCase):
def test_get_first_available_prefix(self): def test_get_first_available_prefix(self):
prefixes = Prefix.objects.bulk_create(( prefixes = Prefix.objects.bulk_create((
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.0.0/16')), # Parent prefix Prefix(prefix=netaddr.IPNetwork('10.0.0.0/16')), # Parent prefix
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.0.0/24')), Prefix(prefix=netaddr.IPNetwork('10.0.0.0/24')),
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.1.0/24')), Prefix(prefix=netaddr.IPNetwork('10.0.1.0/24')),
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.2.0/24')), Prefix(prefix=netaddr.IPNetwork('10.0.2.0/24')),
)) ))
self.assertEqual(prefixes[0].get_first_available_prefix(), netaddr.IPNetwork('10.0.3.0/24')) self.assertEqual(prefixes[0].get_first_available_prefix(), netaddr.IPNetwork('10.0.3.0/24'))
Prefix.objects.create(family=4, prefix=netaddr.IPNetwork('10.0.3.0/24')) Prefix.objects.create(prefix=netaddr.IPNetwork('10.0.3.0/24'))
self.assertEqual(prefixes[0].get_first_available_prefix(), netaddr.IPNetwork('10.0.4.0/22')) self.assertEqual(prefixes[0].get_first_available_prefix(), netaddr.IPNetwork('10.0.4.0/22'))
def test_get_first_available_ip(self): def test_get_first_available_ip(self):
parent_prefix = Prefix.objects.create(family=4, prefix=netaddr.IPNetwork('10.0.0.0/24')) parent_prefix = Prefix.objects.create(prefix=netaddr.IPNetwork('10.0.0.0/24'))
IPAddress.objects.bulk_create(( IPAddress.objects.bulk_create((
IPAddress(family=4, address=netaddr.IPNetwork('10.0.0.1/24')), IPAddress(address=netaddr.IPNetwork('10.0.0.1/24')),
IPAddress(family=4, address=netaddr.IPNetwork('10.0.0.2/24')), IPAddress(address=netaddr.IPNetwork('10.0.0.2/24')),
IPAddress(family=4, address=netaddr.IPNetwork('10.0.0.3/24')), IPAddress(address=netaddr.IPNetwork('10.0.0.3/24')),
)) ))
self.assertEqual(parent_prefix.get_first_available_ip(), '10.0.0.4/24') self.assertEqual(parent_prefix.get_first_available_ip(), '10.0.0.4/24')
IPAddress.objects.create(family=4, address=netaddr.IPNetwork('10.0.0.4/24')) IPAddress.objects.create(address=netaddr.IPNetwork('10.0.0.4/24'))
self.assertEqual(parent_prefix.get_first_available_ip(), '10.0.0.5/24') self.assertEqual(parent_prefix.get_first_available_ip(), '10.0.0.5/24')
def test_get_utilization(self): def test_get_utilization(self):
# Container Prefix # Container Prefix
prefix = Prefix.objects.create( prefix = Prefix.objects.create(
family=4,
prefix=netaddr.IPNetwork('10.0.0.0/24'), prefix=netaddr.IPNetwork('10.0.0.0/24'),
status=PrefixStatusChoices.STATUS_CONTAINER status=PrefixStatusChoices.STATUS_CONTAINER
) )
Prefix.objects.bulk_create(( Prefix.objects.bulk_create((
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.0.0/26')), Prefix(prefix=netaddr.IPNetwork('10.0.0.0/26')),
Prefix(family=4, prefix=netaddr.IPNetwork('10.0.0.128/26')), Prefix(prefix=netaddr.IPNetwork('10.0.0.128/26')),
)) ))
self.assertEqual(prefix.get_utilization(), 50) self.assertEqual(prefix.get_utilization(), 50)
@ -187,7 +186,7 @@ class TestPrefix(TestCase):
prefix.save() prefix.save()
IPAddress.objects.bulk_create( IPAddress.objects.bulk_create(
# Create 32 IPAddresses within the Prefix # Create 32 IPAddresses within the Prefix
[IPAddress(family=4, address=netaddr.IPNetwork('10.0.0.{}/24'.format(i))) for i in range(1, 33)] [IPAddress(address=netaddr.IPNetwork('10.0.0.{}/24'.format(i))) for i in range(1, 33)]
) )
self.assertEqual(prefix.get_utilization(), 12) # ~= 12% self.assertEqual(prefix.get_utilization(), 12) # ~= 12%
@ -224,9 +223,9 @@ class TestIPAddress(TestCase):
def test_get_duplicates(self): def test_get_duplicates(self):
ips = IPAddress.objects.bulk_create(( ips = IPAddress.objects.bulk_create((
IPAddress(family=4, address=netaddr.IPNetwork('192.0.2.1/24')), IPAddress(address=netaddr.IPNetwork('192.0.2.1/24')),
IPAddress(family=4, address=netaddr.IPNetwork('192.0.2.1/24')), IPAddress(address=netaddr.IPNetwork('192.0.2.1/24')),
IPAddress(family=4, address=netaddr.IPNetwork('192.0.2.1/24')), IPAddress(address=netaddr.IPNetwork('192.0.2.1/24')),
)) ))
duplicate_ip_pks = [p.pk for p in ips[0].get_duplicates()] duplicate_ip_pks = [p.pk for p in ips[0].get_duplicates()]

View File

@ -42,45 +42,45 @@ class PrefixOrderingTestCase(OrderingTestBase):
# Setup Prefixes # Setup Prefixes
prefixes = ( prefixes = (
Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=None, family=4, prefix=netaddr.IPNetwork('192.168.0.0/16')), Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=None, prefix=netaddr.IPNetwork('192.168.0.0/16')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, family=4, prefix=netaddr.IPNetwork('192.168.0.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, prefix=netaddr.IPNetwork('192.168.0.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, family=4, prefix=netaddr.IPNetwork('192.168.1.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, prefix=netaddr.IPNetwork('192.168.1.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, family=4, prefix=netaddr.IPNetwork('192.168.2.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, prefix=netaddr.IPNetwork('192.168.2.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, family=4, prefix=netaddr.IPNetwork('192.168.3.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, prefix=netaddr.IPNetwork('192.168.3.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, family=4, prefix=netaddr.IPNetwork('192.168.4.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, prefix=netaddr.IPNetwork('192.168.4.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, family=4, prefix=netaddr.IPNetwork('192.168.5.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, prefix=netaddr.IPNetwork('192.168.5.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.0.0.0/8')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.0.0.0/8')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.0.0.0/16')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.0.0.0/16')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.0.0.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.0.0.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.0.1.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.0.1.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.0.2.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.0.2.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.0.3.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.0.3.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.0.4.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.0.4.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.1.0.0/16')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.1.0.0/16')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.1.1.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.1.1.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.1.2.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.1.2.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.1.3.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.1.3.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.1.4.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.1.4.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.2.0.0/16')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.2.0.0/16')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.2.1.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.2.1.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.2.2.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.2.2.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.2.3.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.2.3.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.2.4.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.2.4.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=vrfb, family=4, prefix=netaddr.IPNetwork('172.16.0.0/12')), Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=vrfb, prefix=netaddr.IPNetwork('172.16.0.0/12')),
Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=vrfb, family=4, prefix=netaddr.IPNetwork('172.16.0.0/16')), Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=vrfb, prefix=netaddr.IPNetwork('172.16.0.0/16')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, prefix=netaddr.IPNetwork('172.16.0.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, prefix=netaddr.IPNetwork('172.16.0.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, prefix=netaddr.IPNetwork('172.16.1.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, prefix=netaddr.IPNetwork('172.16.1.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, prefix=netaddr.IPNetwork('172.16.2.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, prefix=netaddr.IPNetwork('172.16.2.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, prefix=netaddr.IPNetwork('172.16.3.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, prefix=netaddr.IPNetwork('172.16.3.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, prefix=netaddr.IPNetwork('172.16.4.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, prefix=netaddr.IPNetwork('172.16.4.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=vrfb, family=4, prefix=netaddr.IPNetwork('172.17.0.0/16')), Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=vrfb, prefix=netaddr.IPNetwork('172.17.0.0/16')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, prefix=netaddr.IPNetwork('172.17.0.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, prefix=netaddr.IPNetwork('172.17.0.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, prefix=netaddr.IPNetwork('172.17.1.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, prefix=netaddr.IPNetwork('172.17.1.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, prefix=netaddr.IPNetwork('172.17.2.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, prefix=netaddr.IPNetwork('172.17.2.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, prefix=netaddr.IPNetwork('172.17.3.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, prefix=netaddr.IPNetwork('172.17.3.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, prefix=netaddr.IPNetwork('172.17.4.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfb, prefix=netaddr.IPNetwork('172.17.4.0/24')),
) )
Prefix.objects.bulk_create(prefixes) Prefix.objects.bulk_create(prefixes)
@ -109,15 +109,15 @@ class PrefixOrderingTestCase(OrderingTestBase):
# Setup Prefixes # Setup Prefixes
prefixes = [ prefixes = [
Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=None, family=4, prefix=netaddr.IPNetwork('10.0.0.0/8')), Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=None, prefix=netaddr.IPNetwork('10.0.0.0/8')),
Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=None, family=4, prefix=netaddr.IPNetwork('10.0.0.0/16')), Prefix(status=PrefixStatusChoices.STATUS_CONTAINER, vrf=None, prefix=netaddr.IPNetwork('10.0.0.0/16')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, family=4, prefix=netaddr.IPNetwork('10.1.0.0/16')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, prefix=netaddr.IPNetwork('10.1.0.0/16')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, family=4, prefix=netaddr.IPNetwork('192.168.0.0/16')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=None, prefix=netaddr.IPNetwork('192.168.0.0/16')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.0.0.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.0.0.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.0.1.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.0.1.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.0.1.0/25')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.0.1.0/25')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.1.0.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.1.0.0/24')),
Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, prefix=netaddr.IPNetwork('10.1.1.0/24')), Prefix(status=PrefixStatusChoices.STATUS_ACTIVE, vrf=vrfa, prefix=netaddr.IPNetwork('10.1.1.0/24')),
] ]
Prefix.objects.bulk_create(prefixes) Prefix.objects.bulk_create(prefixes)
@ -136,39 +136,39 @@ class IPAddressOrderingTestCase(OrderingTestBase):
# Setup Addresses # Setup Addresses
addresses = ( addresses = (
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.0.0.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.0.0.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.0.1.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.0.1.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.0.2.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.0.2.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.0.3.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.0.3.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.0.4.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.0.4.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.1.0.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.1.0.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.1.1.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.1.1.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.1.2.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.1.2.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.1.3.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.1.3.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.1.4.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.1.4.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.2.0.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.2.0.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.2.1.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.2.1.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.2.2.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.2.2.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.2.3.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.2.3.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, family=4, address=netaddr.IPNetwork('10.2.4.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfa, address=netaddr.IPNetwork('10.2.4.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.16.0.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, address=netaddr.IPNetwork('172.16.0.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.16.1.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, address=netaddr.IPNetwork('172.16.1.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.16.2.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, address=netaddr.IPNetwork('172.16.2.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.16.3.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, address=netaddr.IPNetwork('172.16.3.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.16.4.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, address=netaddr.IPNetwork('172.16.4.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.17.0.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, address=netaddr.IPNetwork('172.17.0.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.17.1.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, address=netaddr.IPNetwork('172.17.1.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.17.2.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, address=netaddr.IPNetwork('172.17.2.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.17.3.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, address=netaddr.IPNetwork('172.17.3.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, family=4, address=netaddr.IPNetwork('172.17.4.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=vrfb, address=netaddr.IPNetwork('172.17.4.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, family=4, address=netaddr.IPNetwork('192.168.0.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.0.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, family=4, address=netaddr.IPNetwork('192.168.1.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.1.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, family=4, address=netaddr.IPNetwork('192.168.2.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.2.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, family=4, address=netaddr.IPNetwork('192.168.3.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.3.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, family=4, address=netaddr.IPNetwork('192.168.4.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.4.1/24')),
IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, family=4, address=netaddr.IPNetwork('192.168.5.1/24')), IPAddress(status=IPAddressStatusChoices.STATUS_ACTIVE, vrf=None, address=netaddr.IPNetwork('192.168.5.1/24')),
) )
IPAddress.objects.bulk_create(addresses) IPAddress.objects.bulk_create(addresses)

View File

@ -82,13 +82,12 @@ class AggregateTestCase(ViewTestCases.PrimaryObjectViewTestCase):
RIR.objects.bulk_create(rirs) RIR.objects.bulk_create(rirs)
Aggregate.objects.bulk_create([ Aggregate.objects.bulk_create([
Aggregate(family=4, prefix=IPNetwork('10.1.0.0/16'), rir=rirs[0]), Aggregate(prefix=IPNetwork('10.1.0.0/16'), rir=rirs[0]),
Aggregate(family=4, prefix=IPNetwork('10.2.0.0/16'), rir=rirs[0]), Aggregate(prefix=IPNetwork('10.2.0.0/16'), rir=rirs[0]),
Aggregate(family=4, prefix=IPNetwork('10.3.0.0/16'), rir=rirs[0]), Aggregate(prefix=IPNetwork('10.3.0.0/16'), rir=rirs[0]),
]) ])
cls.form_data = { cls.form_data = {
'family': 4,
'prefix': IPNetwork('10.99.0.0/16'), 'prefix': IPNetwork('10.99.0.0/16'),
'rir': rirs[1].pk, 'rir': rirs[1].pk,
'date_added': datetime.date(2020, 1, 1), 'date_added': datetime.date(2020, 1, 1),
@ -161,9 +160,9 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase):
) )
Prefix.objects.bulk_create([ Prefix.objects.bulk_create([
Prefix(family=4, prefix=IPNetwork('10.1.0.0/16'), vrf=vrfs[0], site=sites[0], role=roles[0]), Prefix(prefix=IPNetwork('10.1.0.0/16'), vrf=vrfs[0], site=sites[0], role=roles[0]),
Prefix(family=4, prefix=IPNetwork('10.2.0.0/16'), vrf=vrfs[0], site=sites[0], role=roles[0]), Prefix(prefix=IPNetwork('10.2.0.0/16'), vrf=vrfs[0], site=sites[0], role=roles[0]),
Prefix(family=4, prefix=IPNetwork('10.3.0.0/16'), vrf=vrfs[0], site=sites[0], role=roles[0]), Prefix(prefix=IPNetwork('10.3.0.0/16'), vrf=vrfs[0], site=sites[0], role=roles[0]),
]) ])
cls.form_data = { cls.form_data = {
@ -209,9 +208,9 @@ class IPAddressTestCase(ViewTestCases.PrimaryObjectViewTestCase):
) )
IPAddress.objects.bulk_create([ IPAddress.objects.bulk_create([
IPAddress(family=4, address=IPNetwork('192.0.2.1/24'), vrf=vrfs[0]), IPAddress(address=IPNetwork('192.0.2.1/24'), vrf=vrfs[0]),
IPAddress(family=4, address=IPNetwork('192.0.2.2/24'), vrf=vrfs[0]), IPAddress(address=IPNetwork('192.0.2.2/24'), vrf=vrfs[0]),
IPAddress(family=4, address=IPNetwork('192.0.2.3/24'), vrf=vrfs[0]), IPAddress(address=IPNetwork('192.0.2.3/24'), vrf=vrfs[0]),
]) ])
cls.form_data = { cls.form_data = {

View File

@ -207,7 +207,7 @@ class RIRListView(PermissionRequiredMixin, ObjectListView):
'deprecated': 0, 'deprecated': 0,
'available': 0, 'available': 0,
} }
aggregate_list = Aggregate.objects.filter(family=family, rir=rir) aggregate_list = Aggregate.objects.filter(prefix__family=family, rir=rir)
for aggregate in aggregate_list: for aggregate in aggregate_list:
queryset = Prefix.objects.filter(prefix__net_contained_or_equal=str(aggregate.prefix)) queryset = Prefix.objects.filter(prefix__net_contained_or_equal=str(aggregate.prefix))

View File

@ -64,7 +64,7 @@
<table class="table table-hover panel-body attr-table"> <table class="table table-hover panel-body attr-table">
<tr> <tr>
<td>Family</td> <td>Family</td>
<td>{{ aggregate.get_family_display }}</td> <td>IPv{{ aggregate.family }}</td>
</tr> </tr>
<tr> <tr>
<td>RIR</td> <td>RIR</td>

View File

@ -65,7 +65,7 @@
<table class="table table-hover panel-body attr-table"> <table class="table table-hover panel-body attr-table">
<tr> <tr>
<td>Family</td> <td>Family</td>
<td>{{ ipaddress.get_family_display }}</td> <td>IPv{{ ipaddress.family }}</td>
</tr> </tr>
<tr> <tr>
<td>VRF</td> <td>VRF</td>

View File

@ -85,7 +85,7 @@
<table class="table table-hover panel-body attr-table"> <table class="table table-hover panel-body attr-table">
<tr> <tr>
<td>Family</td> <td>Family</td>
<td>{{ prefix.get_family_display }}</td> <td>IPv{{ prefix.family }}</td>
</tr> </tr>
<tr> <tr>
<td>VRF</td> <td>VRF</td>

View File

@ -51,12 +51,12 @@
<div class="pull-left noprint"> <div class="pull-left noprint">
{% block bulk_buttons %}{% endblock %} {% block bulk_buttons %}{% endblock %}
{% if bulk_edit_url and permissions.change %} {% if bulk_edit_url and permissions.change %}
<button type="submit" name="_edit" formaction="{% url bulk_edit_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-warning btn-sm"> <button type="submit" name="_edit" formaction="{% url bulk_edit_url %}" class="btn btn-warning btn-sm">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit Selected <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Edit Selected
</button> </button>
{% endif %} {% endif %}
{% if bulk_delete_url and permissions.delete %} {% if bulk_delete_url and permissions.delete %}
<button type="submit" name="_delete" formaction="{% url bulk_delete_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-danger btn-sm"> <button type="submit" name="_delete" formaction="{% url bulk_delete_url %}" class="btn btn-danger btn-sm">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete Selected <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete Selected
</button> </button>
{% endif %} {% endif %}

View File

@ -634,7 +634,7 @@ class BulkEditView(GetReturnURLMixin, View):
post_data['pk'] = [obj.pk for obj in self.filterset(request.GET, model.objects.only('pk')).qs] post_data['pk'] = [obj.pk for obj in self.filterset(request.GET, model.objects.only('pk')).qs]
if '_apply' in request.POST: if '_apply' in request.POST:
form = self.form(model, request.POST, initial=request.GET) form = self.form(model, request.POST)
if form.is_valid(): if form.is_valid():
custom_fields = form.custom_fields if hasattr(form, 'custom_fields') else [] custom_fields = form.custom_fields if hasattr(form, 'custom_fields') else []
@ -718,10 +718,6 @@ class BulkEditView(GetReturnURLMixin, View):
else: else:
# Pass the PK list as initial data to avoid binding the form # Pass the PK list as initial data to avoid binding the form
initial_data = querydict_to_dict(post_data) initial_data = querydict_to_dict(post_data)
# Append any normal initial data (passed as GET parameters)
initial_data.update(request.GET)
form = self.form(model, initial=initial_data) form = self.form(model, initial=initial_data)
# Retrieve objects being edited # Retrieve objects being edited

View File

@ -408,7 +408,7 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
ip_choices = [(None, '---------')] ip_choices = [(None, '---------')]
# Collect interface IPs # Collect interface IPs
interface_ips = IPAddress.objects.prefetch_related('interface').filter( interface_ips = IPAddress.objects.prefetch_related('interface').filter(
family=family, interface__virtual_machine=self.instance address__family=family, interface__virtual_machine=self.instance
) )
if interface_ips: if interface_ips:
ip_choices.append( ip_choices.append(
@ -418,7 +418,7 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
) )
# Collect NAT IPs # Collect NAT IPs
nat_ips = IPAddress.objects.prefetch_related('nat_inside').filter( nat_ips = IPAddress.objects.prefetch_related('nat_inside').filter(
family=family, nat_inside__interface__virtual_machine=self.instance address__family=family, nat_inside__interface__virtual_machine=self.instance
) )
if nat_ips: if nat_ips:
ip_choices.append( ip_choices.append(