1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Converted IPAddress.interface to a GenericForeignKey

This commit is contained in:
Jeremy Stretch
2017-08-18 16:57:20 -04:00
parent 97536c4e9b
commit 5930a64203
9 changed files with 106 additions and 32 deletions

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.4 on 2017-08-16 21:06 # Generated by Django 1.11.4 on 2017-08-18 19:46
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

View File

@ -1175,6 +1175,11 @@ class Interface(models.Model):
help_text="This interface is used only for out-of-band management" help_text="This interface is used only for out-of-band management"
) )
description = models.CharField(max_length=100, blank=True) description = models.CharField(max_length=100, blank=True)
ip_addresses = GenericRelation(
to='ipam.IPAddress',
content_type_field='interface_type',
object_id_field='interface_id'
)
objects = InterfaceQuerySet.as_manager() objects = InterfaceQuerySet.as_manager()

View File

@ -134,7 +134,11 @@ class PrefixViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
# #
class IPAddressViewSet(WritableSerializerMixin, CustomFieldModelViewSet): class IPAddressViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
queryset = IPAddress.objects.select_related('vrf__tenant', 'tenant', 'interface__device', 'nat_inside') queryset = IPAddress.objects.select_related(
'vrf__tenant', 'tenant', 'nat_inside'
).prefetch_related(
'interface__device'
)
serializer_class = serializers.IPAddressSerializer serializer_class = serializers.IPAddressSerializer
write_serializer_class = serializers.WritableIPAddressSerializer write_serializer_class = serializers.WritableIPAddressSerializer
filter_class = filters.IPAddressFilter filter_class = filters.IPAddressFilter

View File

@ -70,7 +70,7 @@
"family": 4, "family": 4,
"address": "10.0.255.1/32", "address": "10.0.255.1/32",
"vrf": null, "vrf": null,
"interface": 3, "interface_id": 3,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -84,7 +84,7 @@
"family": 4, "family": 4,
"address": "169.254.254.1/31", "address": "169.254.254.1/31",
"vrf": null, "vrf": null,
"interface": 4, "interface_id": 4,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -98,7 +98,7 @@
"family": 4, "family": 4,
"address": "10.0.255.2/32", "address": "10.0.255.2/32",
"vrf": null, "vrf": null,
"interface": 185, "interface_id": 185,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -112,7 +112,7 @@
"family": 4, "family": 4,
"address": "169.254.1.1/31", "address": "169.254.1.1/31",
"vrf": null, "vrf": null,
"interface": 213, "interface_id": 213,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -126,7 +126,7 @@
"family": 4, "family": 4,
"address": "10.0.254.1/24", "address": "10.0.254.1/24",
"vrf": null, "vrf": null,
"interface": 12, "interface_id": 12,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -140,7 +140,7 @@
"family": 4, "family": 4,
"address": "10.15.21.1/31", "address": "10.15.21.1/31",
"vrf": null, "vrf": null,
"interface": 218, "interface_id": 218,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -154,7 +154,7 @@
"family": 4, "family": 4,
"address": "10.15.21.2/31", "address": "10.15.21.2/31",
"vrf": null, "vrf": null,
"interface": 9, "interface_id": 9,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -168,7 +168,7 @@
"family": 4, "family": 4,
"address": "10.15.22.1/31", "address": "10.15.22.1/31",
"vrf": null, "vrf": null,
"interface": 8, "interface_id": 8,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -182,7 +182,7 @@
"family": 4, "family": 4,
"address": "10.15.20.1/31", "address": "10.15.20.1/31",
"vrf": null, "vrf": null,
"interface": 7, "interface_id": 7,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -196,7 +196,7 @@
"family": 4, "family": 4,
"address": "10.16.20.1/31", "address": "10.16.20.1/31",
"vrf": null, "vrf": null,
"interface": 216, "interface_id": 216,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -210,7 +210,7 @@
"family": 4, "family": 4,
"address": "10.15.22.2/31", "address": "10.15.22.2/31",
"vrf": null, "vrf": null,
"interface": 206, "interface_id": 206,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -224,7 +224,7 @@
"family": 4, "family": 4,
"address": "10.16.22.1/31", "address": "10.16.22.1/31",
"vrf": null, "vrf": null,
"interface": 217, "interface_id": 217,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -238,7 +238,7 @@
"family": 4, "family": 4,
"address": "10.16.22.2/31", "address": "10.16.22.2/31",
"vrf": null, "vrf": null,
"interface": 205, "interface_id": 205,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -252,7 +252,7 @@
"family": 4, "family": 4,
"address": "10.16.20.2/31", "address": "10.16.20.2/31",
"vrf": null, "vrf": null,
"interface": 211, "interface_id": 211,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -266,7 +266,7 @@
"family": 4, "family": 4,
"address": "10.15.22.2/31", "address": "10.15.22.2/31",
"vrf": null, "vrf": null,
"interface": 212, "interface_id": 212,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -280,7 +280,7 @@
"family": 4, "family": 4,
"address": "10.0.254.2/32", "address": "10.0.254.2/32",
"vrf": null, "vrf": null,
"interface": 188, "interface_id": 188,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -294,7 +294,7 @@
"family": 4, "family": 4,
"address": "169.254.1.1/31", "address": "169.254.1.1/31",
"vrf": null, "vrf": null,
"interface": 200, "interface_id": 200,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }
@ -308,7 +308,7 @@
"family": 4, "family": 4,
"address": "169.254.1.2/31", "address": "169.254.1.2/31",
"vrf": null, "vrf": null,
"interface": 194, "interface_id": 194,
"nat_inside": null, "nat_inside": null,
"description": "" "description": ""
} }

View File

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.4 on 2017-08-18 19:31
from __future__ import unicode_literals
from django.contrib.contenttypes.models import ContentType
from django.db import migrations, models
import django.db.models.deletion
def set_interface_type(apps, schema_editor):
"""
Set the interface_type field to 'Interface' for all IP addresses assigned to an Interface.
"""
Interface = apps.get_model('dcim', 'Interface')
interface_type = ContentType.objects.get_for_model(Interface)
IPAddress = apps.get_model('ipam', 'IPAddress')
IPAddress.objects.filter(interface__isnull=False).update(interface_type=interface_type)
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('ipam', '0018_remove_service_uniqueness_constraint'),
]
operations = [
migrations.AddField(
model_name='ipaddress',
name='interface_type',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='contenttypes.ContentType'),
),
migrations.RunPython(set_interface_type),
migrations.AlterField(
model_name='IPAddress',
name='interface',
field=models.PositiveIntegerField(blank=True, null=True),
),
migrations.RenameField(
model_name='IPAddress',
old_name='interface',
new_name='interface_id',
)
]

View File

@ -2,10 +2,12 @@ from __future__ import unicode_literals
import netaddr import netaddr
from django.conf import settings from django.conf import settings
from django.contrib.contenttypes.fields import GenericRelation from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models from django.db import models
from django.db.models import Q
from django.db.models.expressions import RawSQL from django.db.models.expressions import RawSQL
from django.urls import reverse from django.urls import reverse
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
@ -407,8 +409,15 @@ class IPAddress(CreatedUpdatedModel, CustomFieldModel):
role = models.PositiveSmallIntegerField( role = models.PositiveSmallIntegerField(
'Role', choices=IPADDRESS_ROLE_CHOICES, blank=True, null=True, help_text='The functional role of this IP' 'Role', choices=IPADDRESS_ROLE_CHOICES, blank=True, null=True, help_text='The functional role of this IP'
) )
interface = models.ForeignKey(Interface, related_name='ip_addresses', on_delete=models.CASCADE, blank=True, interface_type = models.ForeignKey(
null=True) to=ContentType,
on_delete=models.PROTECT,
limit_choices_to=Q(app_label='dcim', model='interface') | Q(app_label='virtualization', model='vminterface'),
blank=True,
null=True
)
interface_id = models.PositiveIntegerField(blank=True, null=True)
interface = GenericForeignKey('interface_type', 'interface_id')
nat_inside = models.OneToOneField('self', related_name='nat_outside', on_delete=models.SET_NULL, blank=True, nat_inside = models.OneToOneField('self', related_name='nat_outside', on_delete=models.SET_NULL, blank=True,
null=True, verbose_name='NAT (Inside)', null=True, verbose_name='NAT (Inside)',
help_text="The IP for which this address is the \"outside\" IP") help_text="The IP for which this address is the \"outside\" IP")

View File

@ -594,7 +594,11 @@ class PrefixBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
# #
class IPAddressListView(ObjectListView): class IPAddressListView(ObjectListView):
queryset = IPAddress.objects.select_related('vrf__tenant', 'tenant', 'interface__device', 'nat_inside') queryset = IPAddress.objects.select_related(
'vrf__tenant', 'tenant', 'nat_inside'
).prefetch_related(
'interface__device'
)
filter = filters.IPAddressFilter filter = filters.IPAddressFilter
filter_form = forms.IPAddressFilterForm filter_form = forms.IPAddressFilterForm
table = tables.IPAddressDetailTable table = tables.IPAddressDetailTable
@ -605,7 +609,7 @@ class IPAddressView(View):
def get(self, request, pk): def get(self, request, pk):
ipaddress = get_object_or_404(IPAddress.objects.select_related('interface__device'), pk=pk) ipaddress = get_object_or_404(IPAddress.objects.select_related('vrf__tenant', 'tenant'), pk=pk)
# Parent prefixes table # Parent prefixes table
parent_prefixes = Prefix.objects.filter( parent_prefixes = Prefix.objects.filter(
@ -622,12 +626,14 @@ class IPAddressView(View):
).exclude( ).exclude(
pk=ipaddress.pk pk=ipaddress.pk
).select_related( ).select_related(
'interface__device', 'nat_inside' 'nat_inside'
).prefetch_related(
'interface__device'
) )
duplicate_ips_table = tables.IPAddressTable(list(duplicate_ips), orderable=False) duplicate_ips_table = tables.IPAddressTable(list(duplicate_ips), orderable=False)
# Related IP table # Related IP table
related_ips = IPAddress.objects.select_related( related_ips = IPAddress.objects.prefetch_related(
'interface__device' 'interface__device'
).exclude( ).exclude(
address=str(ipaddress.address) address=str(ipaddress.address)
@ -681,7 +687,7 @@ class IPAddressBulkImportView(PermissionRequiredMixin, BulkImportView):
class IPAddressBulkEditView(PermissionRequiredMixin, BulkEditView): class IPAddressBulkEditView(PermissionRequiredMixin, BulkEditView):
permission_required = 'ipam.change_ipaddress' permission_required = 'ipam.change_ipaddress'
cls = IPAddress cls = IPAddress
queryset = IPAddress.objects.select_related('vrf__tenant', 'tenant', 'interface__device') queryset = IPAddress.objects.select_related('vrf__tenant', 'tenant').prefetch_related('interface__device')
filter = filters.IPAddressFilter filter = filters.IPAddressFilter
table = tables.IPAddressTable table = tables.IPAddressTable
form = forms.IPAddressBulkEditForm form = forms.IPAddressBulkEditForm
@ -691,7 +697,7 @@ class IPAddressBulkEditView(PermissionRequiredMixin, BulkEditView):
class IPAddressBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): class IPAddressBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'ipam.delete_ipaddress' permission_required = 'ipam.delete_ipaddress'
cls = IPAddress cls = IPAddress
queryset = IPAddress.objects.select_related('vrf__tenant', 'tenant', 'interface__device') queryset = IPAddress.objects.select_related('vrf__tenant', 'tenant').prefetch_related('interface__device')
filter = filters.IPAddressFilter filter = filters.IPAddressFilter
table = tables.IPAddressTable table = tables.IPAddressTable
default_return_url = 'ipam:ipaddress_list' default_return_url = 'ipam:ipaddress_list'

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.4 on 2017-08-16 21:06 # Generated by Django 1.11.4 on 2017-08-18 19:46
from __future__ import unicode_literals from __future__ import unicode_literals
import dcim.fields import dcim.fields
@ -13,9 +13,9 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('tenancy', '0003_unicode_literals'),
('dcim', '0041_napalm_integration'), ('dcim', '0041_napalm_integration'),
('ipam', '0018_remove_service_uniqueness_constraint'), ('ipam', '0019_ipaddress_interface_to_gfk'),
('tenancy', '0003_unicode_literals'),
] ]
operations = [ operations = [
@ -89,6 +89,7 @@ class Migration(migrations.Migration):
('virtual_machine', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='interfaces', to='virtualization.VirtualMachine')), ('virtual_machine', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='interfaces', to='virtualization.VirtualMachine')),
], ],
options={ options={
'verbose_name': 'VM interface',
'ordering': ['virtual_machine', 'name'], 'ordering': ['virtual_machine', 'name'],
}, },
), ),

View File

@ -221,6 +221,11 @@ class VMInterface(models.Model):
max_length=100, max_length=100,
blank=True blank=True
) )
ip_addresses = GenericRelation(
to='ipam.IPAddress',
content_type_field='interface_type',
object_id_field='interface_id'
)
class Meta: class Meta:
ordering = ['virtual_machine', 'name'] ordering = ['virtual_machine', 'name']