From e9f75adddb17662b28e0ce97d96a936171c19e56 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 29 Aug 2017 14:24:58 -0400 Subject: [PATCH] Ditched VMInterface in favor of reusing dcim.Interface --- netbox/dcim/constants.py | 10 ++-- netbox/dcim/migrations/0042_device_cluster.py | 22 --------- netbox/dcim/migrations/0042_virtualization.py | 32 +++++++++++++ netbox/dcim/models.py | 40 ++++++++++++---- .../0019_ipaddress_interface_to_gfk.py | 44 ----------------- netbox/ipam/models.py | 11 +---- .../inc/{vminterface.html => interface.html} | 10 ++-- .../virtualization/virtualmachine.html | 26 +++++----- netbox/virtualization/api/serializers.py | 27 ++++++----- netbox/virtualization/api/urls.py | 2 +- netbox/virtualization/api/views.py | 11 +++-- netbox/virtualization/forms.py | 20 ++++---- ...0001_initial.py => 0001_virtualization.py} | 27 ++--------- netbox/virtualization/models.py | 46 ------------------ netbox/virtualization/tables.py | 7 +-- netbox/virtualization/urls.py | 12 ++--- netbox/virtualization/views.py | 48 +++++++++---------- 17 files changed, 158 insertions(+), 237 deletions(-) delete mode 100644 netbox/dcim/migrations/0042_device_cluster.py create mode 100644 netbox/dcim/migrations/0042_virtualization.py delete mode 100644 netbox/ipam/migrations/0019_ipaddress_interface_to_gfk.py rename netbox/templates/virtualization/inc/{vminterface.html => interface.html} (83%) rename netbox/virtualization/migrations/{0001_initial.py => 0001_virtualization.py} (77%) diff --git a/netbox/dcim/constants.py b/netbox/dcim/constants.py index f2c047910..8758bb55e 100644 --- a/netbox/dcim/constants.py +++ b/netbox/dcim/constants.py @@ -92,13 +92,15 @@ IFACE_FF_JUNIPER_VCP = 5200 # Other IFACE_FF_OTHER = 32767 +VIFACE_FF_CHOICES = [ + [IFACE_FF_VIRTUAL, 'Virtual'], + [IFACE_FF_LAG, 'Link Aggregation Group (LAG)'], +] + IFACE_FF_CHOICES = [ [ 'Virtual interfaces', - [ - [IFACE_FF_VIRTUAL, 'Virtual'], - [IFACE_FF_LAG, 'Link Aggregation Group (LAG)'], - ] + VIFACE_FF_CHOICES, ], [ 'Ethernet (fixed)', diff --git a/netbox/dcim/migrations/0042_device_cluster.py b/netbox/dcim/migrations/0042_device_cluster.py deleted file mode 100644 index f9a0a8637..000000000 --- a/netbox/dcim/migrations/0042_device_cluster.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.4 on 2017-08-18 19:46 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('virtualization', '0001_initial'), - ('dcim', '0041_napalm_integration'), - ] - - operations = [ - migrations.AddField( - model_name='device', - name='cluster', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='devices', to='virtualization.Cluster'), - ), - ] diff --git a/netbox/dcim/migrations/0042_virtualization.py b/netbox/dcim/migrations/0042_virtualization.py new file mode 100644 index 000000000..70c299ccb --- /dev/null +++ b/netbox/dcim/migrations/0042_virtualization.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-08-29 17:49 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('virtualization', '0001_virtualization'), + ('dcim', '0041_napalm_integration'), + ] + + operations = [ + migrations.AddField( + model_name='device', + name='cluster', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='devices', to='virtualization.Cluster'), + ), + migrations.AddField( + model_name='interface', + name='virtual_machine', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='interfaces', to='virtualization.VirtualMachine'), + ), + migrations.AlterField( + model_name='interface', + name='device', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='interfaces', to='dcim.Device'), + ), + ] diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 5bb2996e0..adf0d80a3 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -1152,13 +1152,26 @@ class PowerOutlet(models.Model): @python_2_unicode_compatible class Interface(models.Model): """ - A physical data interface within a Device. An Interface can connect to exactly one other Interface via the creation - of an InterfaceConnection. + A network interface within a Device or VirtualMachine. A physical Interface can connect to exactly one other + Interface via the creation of an InterfaceConnection. """ - device = models.ForeignKey('Device', related_name='interfaces', on_delete=models.CASCADE) + device = models.ForeignKey( + to='Device', + on_delete=models.CASCADE, + related_name='interfaces', + null=True, + blank=True + ) + virtual_machine = models.ForeignKey( + to='virtualization.VirtualMachine', + on_delete=models.CASCADE, + related_name='interfaces', + null=True, + blank=True + ) lag = models.ForeignKey( - 'self', - models.SET_NULL, + to='self', + on_delete=models.SET_NULL, related_name='member_interfaces', null=True, blank=True, @@ -1175,11 +1188,6 @@ class Interface(models.Model): help_text="This interface is used only for out-of-band management" ) 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() @@ -1192,6 +1200,18 @@ class Interface(models.Model): def clean(self): + # An Interface must belong to a Device *or* to a VirtualMachine + if self.device and self.virtual_machine: + raise ValidationError("An interface cannot belong to both a device and a virtual machine.") + if not self.device and not self.virtual_machine: + raise ValidationError("An interface must belong to either a device or a virtual machine.") + + # VM interfaces must be virtual + if self.virtual_machine and self.form_factor not in VIRTUAL_IFACE_TYPES: + raise ValidationError({ + 'form_factor': "Virtual machines cannot have physical interfaces." + }) + # Virtual interfaces cannot be connected if self.form_factor in NONCONNECTABLE_IFACE_TYPES and self.is_connected: raise ValidationError({ diff --git a/netbox/ipam/migrations/0019_ipaddress_interface_to_gfk.py b/netbox/ipam/migrations/0019_ipaddress_interface_to_gfk.py deleted file mode 100644 index ab2f1b7f8..000000000 --- a/netbox/ipam/migrations/0019_ipaddress_interface_to_gfk.py +++ /dev/null @@ -1,44 +0,0 @@ -# -*- 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', - ) - ] diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index f053c3892..ddc1e9e48 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -409,15 +409,8 @@ class IPAddress(CreatedUpdatedModel, CustomFieldModel): role = models.PositiveSmallIntegerField( 'Role', choices=IPADDRESS_ROLE_CHOICES, blank=True, null=True, help_text='The functional role of this IP' ) - interface_type = models.ForeignKey( - 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') + interface = models.ForeignKey(Interface, related_name='ip_addresses', on_delete=models.CASCADE, blank=True, + null=True) nat_inside = models.OneToOneField('self', related_name='nat_outside', on_delete=models.SET_NULL, blank=True, null=True, verbose_name='NAT (Inside)', help_text="The IP for which this address is the \"outside\" IP") diff --git a/netbox/templates/virtualization/inc/vminterface.html b/netbox/templates/virtualization/inc/interface.html similarity index 83% rename from netbox/templates/virtualization/inc/vminterface.html rename to netbox/templates/virtualization/inc/interface.html index ac6d98672..5a08848da 100644 --- a/netbox/templates/virtualization/inc/vminterface.html +++ b/netbox/templates/virtualization/inc/interface.html @@ -1,5 +1,5 @@ - {% if selectable and perms.virtualization.change_vminterface or perms.virtualization.delete_vminterface %} + {% if selectable and perms.dcim.change_interface or perms.dcim.delete_interface %} @@ -13,13 +13,13 @@ {{ iface.mtu|default:"" }} {{ iface.mac_address|default:"" }} - {% if perms.virtualization.change_vminterface %} - + {% if perms.dcim.change_interface %} + {% endif %} - {% if perms.virtualization.delete_vminterface %} - + {% if perms.dcim.delete_interface %} + {% endif %} diff --git a/netbox/templates/virtualization/virtualmachine.html b/netbox/templates/virtualization/virtualmachine.html index 40f4445ea..cea8a0a83 100644 --- a/netbox/templates/virtualization/virtualmachine.html +++ b/netbox/templates/virtualization/virtualmachine.html @@ -133,7 +133,7 @@
- {% if perms.virtualization.change_vminterface or perms.virtualization.delete_vminterface %} + {% if perms.dcim.change_interface or perms.dcim.delete_interface %}
{% csrf_token %} @@ -145,13 +145,13 @@ - {% if perms.virtualization.change_vminterface and interfaces|length > 1 %} + {% if perms.dcim.change_interface and interfaces|length > 1 %} {% endif %} - {% if perms.virtualization.add_vminterface and interfaces|length > 10 %} - + {% if perms.dcim.add_interface and interfaces|length > 10 %} + Add interfaces {% endif %} @@ -159,28 +159,28 @@
{% for iface in interfaces %} - {% include 'virtualization/inc/vminterface.html' with selectable=True %} + {% include 'virtualization/inc/interface.html' with selectable=True %} {% empty %} {% endfor %}
No interfaces defined
- {% if perms.virtualization.add_vminterface or perms.virtualization.delete_vminterface %} + {% if perms.dcim.add_interface or perms.dcim.delete_interface %} {% endif %} - {% if perms.virtualization.delete_vminterface %} + {% if perms.dcim.delete_interface %} {% endif %} diff --git a/netbox/virtualization/api/serializers.py b/netbox/virtualization/api/serializers.py index d5062100d..42d3f237e 100644 --- a/netbox/virtualization/api/serializers.py +++ b/netbox/virtualization/api/serializers.py @@ -3,10 +3,12 @@ from __future__ import unicode_literals from rest_framework import serializers from dcim.api.serializers import NestedPlatformSerializer +from dcim.constants import VIFACE_FF_CHOICES +from dcim.models import Interface from extras.api.customfields import CustomFieldModelSerializer from tenancy.api.serializers import NestedTenantSerializer -from utilities.api import ValidatedModelSerializer -from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface +from utilities.api import ChoiceFieldSerializer, ValidatedModelSerializer +from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine # @@ -102,7 +104,7 @@ class NestedVirtualMachineSerializer(serializers.ModelSerializer): class WritableVirtualMachineSerializer(CustomFieldModelSerializer): class Meta: - model = Cluster + model = VirtualMachine fields = [ 'id', 'name', 'cluster', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', 'comments', 'custom_fields', ] @@ -112,28 +114,29 @@ class WritableVirtualMachineSerializer(CustomFieldModelSerializer): # VM interfaces # -class VMInterfaceSerializer(serializers.ModelSerializer): +class InterfaceSerializer(serializers.ModelSerializer): virtual_machine = NestedVirtualMachineSerializer() + form_factor = ChoiceFieldSerializer(choices=VIFACE_FF_CHOICES) class Meta: - model = VMInterface + model = Interface fields = [ - 'id', 'name', 'virtual_machine', 'enabled', 'mac_address', 'mtu', 'description', + 'id', 'name', 'virtual_machine', 'form_factor', 'enabled', 'mac_address', 'mtu', 'description', ] -class NestedVMInterfaceSerializer(serializers.ModelSerializer): - url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:vminterface-detail') +class NestedInterfaceSerializer(serializers.ModelSerializer): + url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:interface-detail') class Meta: - model = VMInterface + model = Interface fields = ['id', 'url', 'name'] -class WritableVMInterfaceSerializer(ValidatedModelSerializer): +class WritableInterfaceSerializer(ValidatedModelSerializer): class Meta: - model = VMInterface + model = Interface fields = [ - 'id', 'name', 'virtual_machine', 'enabled', 'mac_address', 'mtu', 'description', + 'id', 'name', 'virtual_machine', 'form_factor', 'enabled', 'mac_address', 'mtu', 'description', ] diff --git a/netbox/virtualization/api/urls.py b/netbox/virtualization/api/urls.py index a53fdbde2..34ecf4431 100644 --- a/netbox/virtualization/api/urls.py +++ b/netbox/virtualization/api/urls.py @@ -23,7 +23,7 @@ router.register(r'clusters', views.ClusterViewSet) # VirtualMachines router.register(r'virtual-machines', views.VirtualMachineViewSet) -router.register(r'vm-interfaces', views.VMInterfaceViewSet) +router.register(r'interfaces', views.InterfaceViewSet) app_name = 'virtualization-api' urlpatterns = router.urls diff --git a/netbox/virtualization/api/views.py b/netbox/virtualization/api/views.py index 4c1d065d6..315e1404e 100644 --- a/netbox/virtualization/api/views.py +++ b/netbox/virtualization/api/views.py @@ -2,10 +2,11 @@ from __future__ import unicode_literals from rest_framework.viewsets import ModelViewSet +from dcim.models import Interface from extras.api.views import CustomFieldModelViewSet from utilities.api import WritableSerializerMixin from virtualization import filters -from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface +from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine from . import serializers @@ -41,7 +42,7 @@ class VirtualMachineViewSet(WritableSerializerMixin, CustomFieldModelViewSet): filter_class = filters.VirtualMachineFilter -class VMInterfaceViewSet(WritableSerializerMixin, ModelViewSet): - queryset = VMInterface.objects.select_related('virtual_machine') - serializer_class = serializers.VMInterfaceSerializer - write_serializer_class = serializers.WritableVMInterfaceSerializer +class InterfaceViewSet(WritableSerializerMixin, ModelViewSet): + queryset = Interface.objects.filter(virtual_machine__isnull=False).select_related('virtual_machine') + serializer_class = serializers.InterfaceSerializer + write_serializer_class = serializers.WritableInterfaceSerializer diff --git a/netbox/virtualization/forms.py b/netbox/virtualization/forms.py index f0933e366..2dec7b912 100644 --- a/netbox/virtualization/forms.py +++ b/netbox/virtualization/forms.py @@ -5,8 +5,9 @@ from mptt.forms import TreeNodeChoiceField from django import forms from django.db.models import Count +from dcim.constants import VIFACE_FF_CHOICES from dcim.formfields import MACAddressFormField -from dcim.models import Device, Rack, Region, Site +from dcim.models import Device, Interface, Rack, Region, Site from extras.forms import CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm from tenancy.forms import TenancyForm from tenancy.models import Tenant @@ -15,7 +16,7 @@ from utilities.forms import ( ChainedModelChoiceField, ChainedModelMultipleChoiceField, ComponentForm, ConfirmationForm, ExpandableNameField, FilterChoiceField, SlugField, ) -from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface +from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine # @@ -230,18 +231,19 @@ class VirtualMachineFilterForm(BootstrapMixin, CustomFieldFilterForm): # VM interfaces # -class VMInterfaceForm(BootstrapMixin, forms.ModelForm): +class InterfaceForm(BootstrapMixin, forms.ModelForm): class Meta: - model = VMInterface - fields = ['virtual_machine', 'name', 'enabled', 'mac_address', 'mtu', 'description'] + model = Interface + fields = ['virtual_machine', 'name', 'form_factor', 'enabled', 'mac_address', 'mtu', 'description'] widgets = { 'virtual_machine': forms.HiddenInput(), } -class VMInterfaceCreateForm(ComponentForm): +class InterfaceCreateForm(ComponentForm): name_pattern = ExpandableNameField(label='Name') + form_factor = forms.ChoiceField(choices=VIFACE_FF_CHOICES) enabled = forms.BooleanField(required=False) mtu = forms.IntegerField(required=False, min_value=1, max_value=32767, label='MTU') mac_address = MACAddressFormField(required=False, label='MAC Address') @@ -253,11 +255,11 @@ class VMInterfaceCreateForm(ComponentForm): kwargs['initial'] = kwargs.get('initial', {}).copy() kwargs['initial'].update({'enabled': True}) - super(VMInterfaceCreateForm, self).__init__(*args, **kwargs) + super(InterfaceCreateForm, self).__init__(*args, **kwargs) -class VMInterfaceBulkEditForm(BootstrapMixin, BulkEditForm): - pk = forms.ModelMultipleChoiceField(queryset=VMInterface.objects.all(), widget=forms.MultipleHiddenInput) +class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm): + pk = forms.ModelMultipleChoiceField(queryset=Interface.objects.all(), widget=forms.MultipleHiddenInput) virtual_machine = forms.ModelChoiceField(queryset=VirtualMachine.objects.all(), widget=forms.HiddenInput) enabled = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect) mtu = forms.IntegerField(required=False, min_value=1, max_value=32767, label='MTU') diff --git a/netbox/virtualization/migrations/0001_initial.py b/netbox/virtualization/migrations/0001_virtualization.py similarity index 77% rename from netbox/virtualization/migrations/0001_initial.py rename to netbox/virtualization/migrations/0001_virtualization.py index cc0135b40..3b8441d21 100644 --- a/netbox/virtualization/migrations/0001_initial.py +++ b/netbox/virtualization/migrations/0001_virtualization.py @@ -1,8 +1,7 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.11.4 on 2017-08-18 19:46 +# Generated by Django 1.11.4 on 2017-08-29 17:49 from __future__ import unicode_literals -import dcim.fields from django.db import migrations, models import django.db.models.deletion import extras.models @@ -13,9 +12,9 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('dcim', '0041_napalm_integration'), - ('ipam', '0019_ipaddress_interface_to_gfk'), ('tenancy', '0003_unicode_literals'), + ('ipam', '0018_remove_service_uniqueness_constraint'), + ('dcim', '0041_napalm_integration'), ] operations = [ @@ -77,22 +76,6 @@ class Migration(migrations.Migration): }, bases=(models.Model, extras.models.CustomFieldModel), ), - migrations.CreateModel( - name='VMInterface', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=30)), - ('enabled', models.BooleanField(default=True)), - ('mac_address', dcim.fields.MACAddressField(blank=True, null=True, verbose_name='MAC Address')), - ('mtu', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='MTU')), - ('description', models.CharField(blank=True, max_length=100)), - ('virtual_machine', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='interfaces', to='virtualization.VirtualMachine')), - ], - options={ - 'verbose_name': 'VM interface', - 'ordering': ['virtual_machine', 'name'], - }, - ), migrations.AddField( model_name='cluster', name='group', @@ -103,8 +86,4 @@ class Migration(migrations.Migration): name='type', field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='clusters', to='virtualization.ClusterType'), ), - migrations.AlterUniqueTogether( - name='vminterface', - unique_together=set([('virtual_machine', 'name')]), - ), ] diff --git a/netbox/virtualization/models.py b/netbox/virtualization/models.py index d23c6f2df..8b644af2c 100644 --- a/netbox/virtualization/models.py +++ b/netbox/virtualization/models.py @@ -188,49 +188,3 @@ class VirtualMachine(CreatedUpdatedModel, CustomFieldModel): def get_absolute_url(self): return reverse('virtualization:virtualmachine', args=[self.pk]) - - -@python_2_unicode_compatible -class VMInterface(models.Model): - """ - A virtual interface which belongs to a VirtualMachine. Like the dcim.Interface model, IPAddresses can be assigned to - VMInterfaces. - """ - virtual_machine = models.ForeignKey( - to=VirtualMachine, - on_delete=models.CASCADE, - related_name='interfaces' - ) - name = models.CharField( - max_length=30 - ) - enabled = models.BooleanField( - default=True - ) - mac_address = MACAddressField( - blank=True, - null=True, - verbose_name='MAC Address' - ) - mtu = models.PositiveSmallIntegerField( - blank=True, - null=True, - verbose_name='MTU' - ) - description = models.CharField( - max_length=100, - blank=True - ) - ip_addresses = GenericRelation( - to='ipam.IPAddress', - content_type_field='interface_type', - object_id_field='interface_id' - ) - - class Meta: - ordering = ['virtual_machine', 'name'] - unique_together = ['virtual_machine', 'name'] - verbose_name = 'VM interface' - - def __str__(self): - return self.name diff --git a/netbox/virtualization/tables.py b/netbox/virtualization/tables.py index 97261f3ae..04db8c04c 100644 --- a/netbox/virtualization/tables.py +++ b/netbox/virtualization/tables.py @@ -3,8 +3,9 @@ from __future__ import unicode_literals import django_tables2 as tables from django_tables2.utils import Accessor +from dcim.models import Interface from utilities.tables import BaseTable, ToggleColumn -from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface +from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine CLUSTERTYPE_ACTIONS = """ @@ -89,8 +90,8 @@ class VirtualMachineTable(BaseTable): # VM components # -class VMInterfaceTable(BaseTable): +class InterfaceTable(BaseTable): class Meta(BaseTable.Meta): - model = VMInterface + model = Interface fields = ('name', 'enabled', 'description') diff --git a/netbox/virtualization/urls.py b/netbox/virtualization/urls.py index 3e6cf265b..222754dcb 100644 --- a/netbox/virtualization/urls.py +++ b/netbox/virtualization/urls.py @@ -41,11 +41,11 @@ urlpatterns = [ url(r'^virtual-machines/(?P\d+)/delete/$', views.VirtualMachineDeleteView.as_view(), name='virtualmachine_delete'), # VM interfaces - # url(r'^virtual-machines/interfaces/add/$', views.VMBulkAddVMInterfaceView.as_view(), name='vm_bulk_add_vminterface'), - url(r'^virtual-machines/(?P\d+)/interfaces/add/$', views.VMInterfaceCreateView.as_view(), name='vminterface_add'), - url(r'^virtual-machines/(?P\d+)/interfaces/edit/$', views.VMInterfaceBulkEditView.as_view(), name='vminterface_bulk_edit'), - url(r'^virtual-machines/(?P\d+)/interfaces/delete/$', views.VMInterfaceBulkDeleteView.as_view(), name='vminterface_bulk_delete'), - url(r'^vm-interfaces/(?P\d+)/edit/$', views.VMInterfaceEditView.as_view(), name='vminterface_edit'), - url(r'^vm-interfaces/(?P\d+)/delete/$', views.VMInterfaceDeleteView.as_view(), name='vminterface_delete'), + # url(r'^virtual-machines/interfaces/add/$', views.VMBulkAddInterfaceView.as_view(), name='vm_bulk_add_interface'), + url(r'^virtual-machines/(?P\d+)/interfaces/add/$', views.InterfaceCreateView.as_view(), name='interface_add'), + url(r'^virtual-machines/(?P\d+)/interfaces/edit/$', views.InterfaceBulkEditView.as_view(), name='interface_bulk_edit'), + url(r'^virtual-machines/(?P\d+)/interfaces/delete/$', views.InterfaceBulkDeleteView.as_view(), name='interface_bulk_delete'), + url(r'^vm-interfaces/(?P\d+)/edit/$', views.InterfaceEditView.as_view(), name='interface_edit'), + url(r'^vm-interfaces/(?P\d+)/delete/$', views.InterfaceDeleteView.as_view(), name='interface_delete'), ] diff --git a/netbox/virtualization/views.py b/netbox/virtualization/views.py index ff06280b3..599956e66 100644 --- a/netbox/virtualization/views.py +++ b/netbox/virtualization/views.py @@ -7,13 +7,13 @@ from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from django.views.generic import View -from dcim.models import Device +from dcim.models import Device, Interface from dcim.tables import DeviceTable from utilities.views import ( BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, ComponentDeleteView, ComponentEditView, ObjectDeleteView, ObjectEditView, ObjectListView, ) -from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface +from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine from . import filters from . import forms from . import tables @@ -235,7 +235,7 @@ class VirtualMachineView(View): def get(self, request, pk): vm = get_object_or_404(VirtualMachine.objects.select_related('tenant__group'), pk=pk) - interfaces = VMInterface.objects.filter(virtual_machine=vm) + interfaces = Interface.objects.filter(virtual_machine=vm) return render(request, 'virtualization/virtualmachine.html', { 'vm': vm, @@ -282,39 +282,39 @@ class VirtualMachineBulkEditView(PermissionRequiredMixin, BulkEditView): # VM interfaces # -class VMInterfaceCreateView(PermissionRequiredMixin, ComponentCreateView): - permission_required = 'virtualization.add_vminterface' +class InterfaceCreateView(PermissionRequiredMixin, ComponentCreateView): + permission_required = 'dcim.add_interface' parent_model = VirtualMachine parent_field = 'virtual_machine' - model = VMInterface - form = forms.VMInterfaceCreateForm - model_form = forms.VMInterfaceForm + model = Interface + form = forms.InterfaceCreateForm + model_form = forms.InterfaceForm template_name = 'virtualization/virtualmachine_component_add.html' -class VMInterfaceEditView(PermissionRequiredMixin, ComponentEditView): - permission_required = 'virtualization.change_vminterface' - model = VMInterface +class InterfaceEditView(PermissionRequiredMixin, ComponentEditView): + permission_required = 'dcim.change_interface' + model = Interface parent_field = 'virtual_machine' - form_class = forms.VMInterfaceForm + form_class = forms.InterfaceForm -class VMInterfaceDeleteView(PermissionRequiredMixin, ComponentDeleteView): - permission_required = 'virtualization.delete_vminterface' - model = VMInterface +class InterfaceDeleteView(PermissionRequiredMixin, ComponentDeleteView): + permission_required = 'dcim.delete_interface' + model = Interface parent_field = 'virtual_machine' -class VMInterfaceBulkEditView(PermissionRequiredMixin, BulkEditView): - permission_required = 'virtualization.change_vminterface' - cls = VMInterface +class InterfaceBulkEditView(PermissionRequiredMixin, BulkEditView): + permission_required = 'dcim.change_interface' + cls = Interface parent_cls = VirtualMachine - table = tables.VMInterfaceTable - form = forms.VMInterfaceBulkEditForm + table = tables.InterfaceTable + form = forms.InterfaceBulkEditForm -class VMInterfaceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): - permission_required = 'virtualization.delete_vminterface' - cls = VMInterface +class InterfaceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): + permission_required = 'dcim.delete_interface' + cls = Interface parent_cls = VirtualMachine - table = tables.VMInterfaceTable + table = tables.InterfaceTable