Parcourir la source

Converted IPAM import views to new scheme

Jeremy Stretch il y a 8 ans
Parent
commit
c82658440f

+ 139 - 65
netbox/ipam/forms.py

@@ -9,8 +9,8 @@ from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFi
 from tenancy.forms import TenancyForm
 from tenancy.models import Tenant
 from utilities.forms import (
-    APISelect, BootstrapMixin, BulkEditNullBooleanSelect, BulkImportForm, ChainedModelChoiceField, CSVDataField,
-    ExpandableIPAddressField, FilterChoiceField, Livesearch, ReturnURLForm, SlugField, add_blank_choice,
+    APISelect, BootstrapMixin, BulkEditNullBooleanSelect, ChainedModelChoiceField, ExpandableIPAddressField,
+    FilterChoiceField, Livesearch, ReturnURLForm, SlugField, add_blank_choice,
 )
 from .models import (
     Aggregate, IPAddress, IPADDRESS_STATUS_CHOICES, Prefix, PREFIX_STATUS_CHOICES, RIR, Role, Service, VLAN,
@@ -48,19 +48,22 @@ class VRFForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
 
 
-class VRFFromCSVForm(forms.ModelForm):
-    tenant = forms.ModelChoiceField(Tenant.objects.all(), to_field_name='name', required=False,
-                                    error_messages={'invalid_choice': 'Tenant not found.'})
+class VRFCSVForm(forms.ModelForm):
+    tenant = forms.ModelChoiceField(
+        queryset=Tenant.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Name of assigned tenant',
+        error_messages={
+            'invalid_choice': 'Tenant not found.',
+        }
+    )
 
     class Meta:
         model = VRF
         fields = ['name', 'rd', 'tenant', 'enforce_unique', 'description']
 
 
-class VRFImportForm(BootstrapMixin, BulkImportForm):
-    csv = CSVDataField(csv_form=VRFFromCSVForm)
-
-
 class VRFBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=VRF.objects.all(), widget=forms.MultipleHiddenInput)
     tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
@@ -116,19 +119,21 @@ class AggregateForm(BootstrapMixin, CustomFieldForm):
         }
 
 
-class AggregateFromCSVForm(forms.ModelForm):
-    rir = forms.ModelChoiceField(queryset=RIR.objects.all(), to_field_name='name',
-                                 error_messages={'invalid_choice': 'RIR not found.'})
+class AggregateCSVForm(forms.ModelForm):
+    rir = forms.ModelChoiceField(
+        queryset=RIR.objects.all(),
+        to_field_name='name',
+        help_text='Name of parent RIR',
+        error_messages={
+            'invalid_choice': 'RIR not found.',
+        }
+    )
 
     class Meta:
         model = Aggregate
         fields = ['prefix', 'rir', 'date_added', 'description']
 
 
-class AggregateImportForm(BootstrapMixin, BulkImportForm):
-    csv = CSVDataField(csv_form=AggregateFromCSVForm)
-
-
 class AggregateBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=Aggregate.objects.all(), widget=forms.MultipleHiddenInput)
     rir = forms.ModelChoiceField(queryset=RIR.objects.all(), required=False, label='RIR')
@@ -197,18 +202,54 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         self.fields['vrf'].empty_label = 'Global'
 
 
-class PrefixFromCSVForm(forms.ModelForm):
-    vrf = forms.ModelChoiceField(queryset=VRF.objects.all(), required=False, to_field_name='rd',
-                                 error_messages={'invalid_choice': 'VRF not found.'})
-    tenant = forms.ModelChoiceField(Tenant.objects.all(), to_field_name='name', required=False,
-                                    error_messages={'invalid_choice': 'Tenant not found.'})
-    site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False, to_field_name='name',
-                                  error_messages={'invalid_choice': 'Site not found.'})
-    vlan_group_name = forms.CharField(required=False)
-    vlan_vid = forms.IntegerField(required=False)
-    status = forms.CharField()
-    role = forms.ModelChoiceField(queryset=Role.objects.all(), required=False, to_field_name='name',
-                                  error_messages={'invalid_choice': 'Invalid role.'})
+class PrefixCSVForm(forms.ModelForm):
+    vrf = forms.ModelChoiceField(
+        queryset=VRF.objects.all(),
+        required=False,
+        to_field_name='rd',
+        help_text='Route distinguisher of parent VRF',
+        error_messages={
+            'invalid_choice': 'VRF not found.',
+        }
+    )
+    tenant = forms.ModelChoiceField(
+        queryset=Tenant.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Name of assigned tenant',
+        error_messages={
+            'invalid_choice': 'Tenant not found.',
+        }
+    )
+    site = forms.ModelChoiceField(
+        queryset=Site.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Name of parent site',
+        error_messages={
+            'invalid_choice': 'Site not found.',
+        }
+    )
+    vlan_group_name = forms.CharField(
+        help_text='Group name of assigned VLAN',
+        required=False
+    )
+    vlan_vid = forms.IntegerField(
+        help_text='Numeric ID of assigned VLAN',
+        required=False
+    )
+    status = forms.CharField(
+        help_text='Status name'
+    )
+    role = forms.ModelChoiceField(
+        queryset=Role.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Role name',
+        error_messages={
+            'invalid_choice': 'Invalid role.',
+        }
+    )
 
     class Meta:
         model = Prefix
@@ -219,8 +260,6 @@ class PrefixFromCSVForm(forms.ModelForm):
 
     def clean(self):
 
-        super(PrefixFromCSVForm, self).clean()
-
         site = self.cleaned_data.get('site')
         vlan_group_name = self.cleaned_data.get('vlan_group_name')
         vlan_vid = self.cleaned_data.get('vlan_vid')
@@ -258,10 +297,6 @@ class PrefixFromCSVForm(forms.ModelForm):
             raise ValidationError("Invalid status: {}".format(self.cleaned_data['status']))
 
 
-class PrefixImportForm(BootstrapMixin, BulkImportForm):
-    csv = CSVDataField(csv_form=PrefixFromCSVForm)
-
-
 class PrefixBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=Prefix.objects.all(), widget=forms.MultipleHiddenInput)
     site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False)
@@ -513,16 +548,45 @@ class IPAddressBulkAddForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         self.fields['vrf'].empty_label = 'Global'
 
 
-class IPAddressFromCSVForm(forms.ModelForm):
-    vrf = forms.ModelChoiceField(queryset=VRF.objects.all(), required=False, to_field_name='rd',
-                                 error_messages={'invalid_choice': 'VRF not found.'})
-    tenant = forms.ModelChoiceField(Tenant.objects.all(), to_field_name='name', required=False,
-                                    error_messages={'invalid_choice': 'Tenant not found.'})
-    status = forms.CharField()
-    device = forms.ModelChoiceField(queryset=Device.objects.all(), required=False, to_field_name='name',
-                                    error_messages={'invalid_choice': 'Device not found.'})
-    interface_name = forms.CharField(required=False)
-    is_primary = forms.BooleanField(required=False)
+class IPAddressCSVForm(forms.ModelForm):
+    vrf = forms.ModelChoiceField(
+        queryset=VRF.objects.all(),
+        required=False,
+        to_field_name='rd',
+        help_text='Route distinguisher of the assigned VRF',
+        error_messages={
+            'invalid_choice': 'VRF not found.',
+        }
+    )
+    tenant = forms.ModelChoiceField(
+        queryset=Tenant.objects.all(),
+        to_field_name='name',
+        required=False,
+        help_text='Name of the assigned tenant',
+        error_messages={
+            'invalid_choice': 'Tenant not found.',
+        }
+    )
+    status = forms.CharField(
+        help_text='Status name'
+    )
+    device = forms.ModelChoiceField(
+        queryset=Device.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Name of assigned Device',
+        error_messages={
+            'invalid_choice': 'Device not found.',
+        }
+    )
+    interface_name = forms.CharField(
+        help_text='Name of assigned interface',
+        required=False
+    )
+    is_primary = forms.BooleanField(
+        help_text='This is the primary IP for the assigned device',
+        required=False
+    )
 
     class Meta:
         model = IPAddress
@@ -569,11 +633,7 @@ class IPAddressFromCSVForm(forms.ModelForm):
             elif self.instance.address.version == 6:
                 self.instance.primary_ip6_for = self.cleaned_data['device']
 
-        return super(IPAddressFromCSVForm, self).save(*args, **kwargs)
-
-
-class IPAddressImportForm(BootstrapMixin, BulkImportForm):
-    csv = CSVDataField(csv_form=IPAddressFromCSVForm)
+        return super(IPAddressCSVForm, self).save(*args, **kwargs)
 
 
 class IPAddressBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
@@ -673,20 +733,40 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldForm):
         }
 
 
-class VLANFromCSVForm(forms.ModelForm):
+class VLANCSVForm(forms.ModelForm):
     site = forms.ModelChoiceField(
-        queryset=Site.objects.all(), required=False, to_field_name='name',
-        error_messages={'invalid_choice': 'Site not found.'}
+        queryset=Site.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Name of parent site',
+        error_messages={
+            'invalid_choice': 'Site not found.',
+        }
+    )
+    group_name = forms.CharField(
+        help_text='Name of parent VLAN group',
+        required=False
     )
-    group_name = forms.CharField(required=False)
     tenant = forms.ModelChoiceField(
-        Tenant.objects.all(), to_field_name='name', required=False,
-        error_messages={'invalid_choice': 'Tenant not found.'}
+        queryset=Tenant.objects.all(),
+        to_field_name='name',
+        required=False,
+        help_text='Name of assigned tenant',
+        error_messages={
+            'invalid_choice': 'Tenant not found.',
+        }
+    )
+    status = forms.CharField(
+        help_text='Status name'
     )
-    status = forms.CharField()
     role = forms.ModelChoiceField(
-        queryset=Role.objects.all(), required=False, to_field_name='name',
-        error_messages={'invalid_choice': 'Invalid role.'}
+        queryset=Role.objects.all(),
+        required=False,
+        to_field_name='name',
+        help_text='Name of assigned role',
+        error_messages={
+            'invalid_choice': 'Invalid role.',
+        }
     )
 
     class Meta:
@@ -695,8 +775,6 @@ class VLANFromCSVForm(forms.ModelForm):
 
     def clean(self):
 
-        super(VLANFromCSVForm, self).clean()
-
         # Validate VLANGroup
         group_name = self.cleaned_data.get('group_name')
         if group_name:
@@ -714,7 +792,7 @@ class VLANFromCSVForm(forms.ModelForm):
 
     def save(self, *args, **kwargs):
 
-        vlan = super(VLANFromCSVForm, self).save(commit=False)
+        vlan = super(VLANCSVForm, self).save(commit=False)
 
         # Assign VLANGroup by site and name
         if self.cleaned_data['group_name']:
@@ -725,10 +803,6 @@ class VLANFromCSVForm(forms.ModelForm):
         return vlan
 
 
-class VLANImportForm(BootstrapMixin, BulkImportForm):
-    csv = CSVDataField(csv_form=VLANFromCSVForm)
-
-
 class VLANBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
     pk = forms.ModelMultipleChoiceField(queryset=VLAN.objects.all(), widget=forms.MultipleHiddenInput)
     site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False)

+ 12 - 16
netbox/ipam/views.py

@@ -13,7 +13,8 @@ from django.views.generic import View
 from dcim.models import Device
 from utilities.paginator import EnhancedPaginator
 from utilities.views import (
-    BulkAddView, BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
+    BulkAddView, BulkDeleteView, BulkEditView, BulkImportView, BulkImportView2, ObjectDeleteView, ObjectEditView,
+    ObjectListView,
 )
 from . import filters, forms, tables
 from .models import (
@@ -128,11 +129,10 @@ class VRFDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     default_return_url = 'ipam:vrf_list'
 
 
-class VRFBulkImportView(PermissionRequiredMixin, BulkImportView):
+class VRFBulkImportView(PermissionRequiredMixin, BulkImportView2):
     permission_required = 'ipam.add_vrf'
-    form = forms.VRFImportForm
+    model_form = forms.VRFCSVForm
     table = tables.VRFTable
-    template_name = 'ipam/vrf_import.html'
     default_return_url = 'ipam:vrf_list'
 
 
@@ -339,11 +339,10 @@ class AggregateDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     default_return_url = 'ipam:aggregate_list'
 
 
-class AggregateBulkImportView(PermissionRequiredMixin, BulkImportView):
+class AggregateBulkImportView(PermissionRequiredMixin, BulkImportView2):
     permission_required = 'ipam.add_aggregate'
-    form = forms.AggregateImportForm
+    model_form = forms.AggregateCSVForm
     table = tables.AggregateTable
-    template_name = 'ipam/aggregate_import.html'
     default_return_url = 'ipam:aggregate_list'
 
 
@@ -536,11 +535,10 @@ class PrefixDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     default_return_url = 'ipam:prefix_list'
 
 
-class PrefixBulkImportView(PermissionRequiredMixin, BulkImportView):
+class PrefixBulkImportView(PermissionRequiredMixin, BulkImportView2):
     permission_required = 'ipam.add_prefix'
-    form = forms.PrefixImportForm
+    model_form = forms.PrefixCSVForm
     table = tables.PrefixTable
-    template_name = 'ipam/prefix_import.html'
     default_return_url = 'ipam:prefix_list'
 
 
@@ -638,11 +636,10 @@ class IPAddressBulkAddView(PermissionRequiredMixin, BulkAddView):
     default_return_url = 'ipam:ipaddress_list'
 
 
-class IPAddressBulkImportView(PermissionRequiredMixin, BulkImportView):
+class IPAddressBulkImportView(PermissionRequiredMixin, BulkImportView2):
     permission_required = 'ipam.add_ipaddress'
-    form = forms.IPAddressImportForm
+    model_form = forms.IPAddressCSVForm
     table = tables.IPAddressTable
-    template_name = 'ipam/ipaddress_import.html'
     default_return_url = 'ipam:ipaddress_list'
 
     def save_obj(self, obj):
@@ -746,11 +743,10 @@ class VLANDeleteView(PermissionRequiredMixin, ObjectDeleteView):
     default_return_url = 'ipam:vlan_list'
 
 
-class VLANBulkImportView(PermissionRequiredMixin, BulkImportView):
+class VLANBulkImportView(PermissionRequiredMixin, BulkImportView2):
     permission_required = 'ipam.add_vlan'
-    form = forms.VLANImportForm
+    model_form = forms.VLANCSVForm
     table = tables.VLANTable
-    template_name = 'ipam/vlan_import.html'
     default_return_url = 'ipam:vlan_list'
 
 

+ 0 - 40
netbox/templates/ipam/aggregate_import.html

@@ -1,40 +0,0 @@
-{% extends 'utilities/obj_import.html' %}
-
-{% block title %}Aggregate Import{% endblock %}
-
-{% block instructions %}
-    <h4>CSV Format</h4>
-    <table class="table">
-        <thead>
-            <tr>
-                <th>Field</th>
-                <th>Description</th>
-                <th>Example</th>
-            </tr>
-        </thead>
-        <tbody>
-            <tr>
-                <td>Prefix</td>
-                <td>IPv4 or IPv6 network</td>
-                <td>172.16.0.0/12</td>
-            </tr>
-            <tr>
-                <td>RIR</td>
-                <td>Name of RIR</td>
-                <td>RFC 1918</td>
-            </tr>
-            <tr>
-                <td>Date Added</td>
-                <td>Date in YYYY-MM-DD format (optional)</td>
-                <td>2016-02-23</td>
-            </tr>
-            <tr>
-                <td>Description</td>
-                <td>Short description (optional)</td>
-                <td>Private IPv4 space</td>
-            </tr>
-        </tbody>
-    </table>
-    <h4>Example</h4>
-    <pre>172.16.0.0/12,RFC 1918,2016-02-23,Private IPv4 space</pre>
-{% endblock %}

+ 0 - 60
netbox/templates/ipam/ipaddress_import.html

@@ -1,60 +0,0 @@
-{% extends 'utilities/obj_import.html' %}
-
-{% block title %}IP Address Import{% endblock %}
-
-{% block instructions %}
-    <h4>CSV Format</h4>
-    <table class="table">
-        <thead>
-            <tr>
-                <th>Field</th>
-                <th>Description</th>
-                <th>Example</th>
-            </tr>
-        </thead>
-        <tbody>
-            <tr>
-                <td>Address</td>
-                <td>IPv4 or IPv6 address</td>
-                <td>192.0.2.42/24</td>
-            </tr>
-            <tr>
-                <td>VRF</td>
-                <td>VRF route distinguisher (optional)</td>
-                <td>65000:123</td>
-            </tr>
-            <tr>
-                <td>Tenant</td>
-                <td>Name of tenant (optional)</td>
-                <td>ABC01</td>
-            </tr>
-            <tr>
-                <td>Status</td>
-                <td>Current status</td>
-                <td>Active</td>
-            </tr>
-            <tr>
-                <td>Device</td>
-                <td>Device name (optional)</td>
-                <td>switch12</td>
-            </tr>
-            <tr>
-                <td>Interface</td>
-                <td>Interface name (optional)</td>
-                <td>ge-0/0/31</td>
-            </tr>
-            <tr>
-                <td>Is Primary</td>
-                <td>If "true", IP will be primary for device (optional)</td>
-                <td>True</td>
-            </tr>
-            <tr>
-                <td>Description</td>
-                <td>Short description (optional)</td>
-                <td>Management IP</td>
-            </tr>
-        </tbody>
-    </table>
-    <h4>Example</h4>
-    <pre>192.0.2.42/24,65000:123,ABC01,Active,switch12,ge-0/0/31,True,Management IP</pre>
-{% endblock %}

+ 0 - 70
netbox/templates/ipam/prefix_import.html

@@ -1,70 +0,0 @@
-{% extends 'utilities/obj_import.html' %}
-
-{% block title %}Prefix Import{% endblock %}
-
-{% block instructions %}
-    <h4>CSV Format</h4>
-    <table class="table">
-        <thead>
-            <tr>
-                <th>Field</th>
-                <th>Description</th>
-                <th>Example</th>
-            </tr>
-        </thead>
-        <tbody>
-            <tr>
-                <td>Prefix</td>
-                <td>IPv4 or IPv6 network</td>
-                <td>192.168.42.0/24</td>
-            </tr>
-            <tr>
-                <td>VRF</td>
-                <td>VRF route distinguisher (optional)</td>
-                <td>65000:123</td>
-            </tr>
-            <tr>
-                <td>Tenant</td>
-                <td>Name of tenant (optional)</td>
-                <td>ABC01</td>
-            </tr>
-            <tr>
-                <td>Site</td>
-                <td>Name of assigned site (optional)</td>
-                <td>HQ</td>
-            </tr>
-            <tr>
-                <td>VLAN Group</td>
-                <td>Name of group for VLAN selection (optional)</td>
-                <td>Customers</td>
-            </tr>
-            <tr>
-                <td>VLAN ID</td>
-                <td>Numeric VLAN ID (optional)</td>
-                <td>801</td>
-            </tr>
-            <tr>
-                <td>Status</td>
-                <td>Current status</td>
-                <td>Active</td>
-            </tr>
-            <tr>
-                <td>Role</td>
-                <td>Functional role (optional)</td>
-                <td>Customer</td>
-            </tr>
-            <tr>
-                <td>Is a pool</td>
-                <td>True if all IPs are considered usable</td>
-                <td>False</td>
-            </tr>
-            <tr>
-                <td>Description</td>
-                <td>Short description (optional)</td>
-                <td>7th floor WiFi</td>
-            </tr>
-        </tbody>
-    </table>
-    <h4>Example</h4>
-    <pre>192.168.42.0/24,65000:123,ABC01,HQ,Customers,801,Active,Customer,False,7th floor WiFi</pre>
-{% endblock %}

+ 0 - 60
netbox/templates/ipam/vlan_import.html

@@ -1,60 +0,0 @@
-{% extends 'utilities/obj_import.html' %}
-
-{% block title %}VLAN Import{% endblock %}
-
-{% block instructions %}
-    <h4>CSV Format</h4>
-    <table class="table">
-        <thead>
-            <tr>
-                <th>Field</th>
-                <th>Description</th>
-                <th>Example</th>
-            </tr>
-        </thead>
-        <tbody>
-            <tr>
-                <td>Site</td>
-                <td>Name of assigned site (optional)</td>
-                <td>LAS2</td>
-            </tr>
-            <tr>
-                <td>Group</td>
-                <td>Name of VLAN group (optional)</td>
-                <td>Backend Network</td>
-            </tr>
-            <tr>
-                <td>ID</td>
-                <td>Configured VLAN ID</td>
-                <td>1400</td>
-            </tr>
-            <tr>
-                <td>Name</td>
-                <td>Configured VLAN name</td>
-                <td>Cameras</td>
-            </tr>
-            <tr>
-                <td>Tenant</td>
-                <td>Name of tenant (optional)</td>
-                <td>Internal</td>
-            </tr>
-            <tr>
-                <td>Status</td>
-                <td>Current status</td>
-                <td>Active</td>
-            </tr>
-            <tr>
-                <td>Role</td>
-                <td>Functional role (optional)</td>
-                <td>Security</td>
-            </tr>
-            <tr>
-                <td>Description</td>
-                <td>Short description (optional)</td>
-                <td>Security team only</td>
-            </tr>
-        </tbody>
-    </table>
-    <h4>Example</h4>
-    <pre>LAS2,Backend Network,1400,Cameras,Internal,Active,Security,Security team only</pre>
-{% endblock %}

+ 0 - 45
netbox/templates/ipam/vrf_import.html

@@ -1,45 +0,0 @@
-{% extends 'utilities/obj_import.html' %}
-
-{% block title %}VRF Import{% endblock %}
-
-{% block instructions %}
-    <h4>CSV Format</h4>
-    <table class="table">
-        <thead>
-            <tr>
-                <th>Field</th>
-                <th>Description</th>
-                <th>Example</th>
-            </tr>
-        </thead>
-        <tbody>
-            <tr>
-                <td>Name</td>
-                <td>Name of VRF</td>
-                <td>Customer_ABC</td>
-            </tr>
-            <tr>
-                <td>RD</td>
-                <td>Route distinguisher</td>
-                <td>65000:123456</td>
-            </tr>
-            <tr>
-                <td>Tenant</td>
-                <td>Name of tenant (optional)</td>
-                <td>ABC01</td>
-            </tr>
-            <tr>
-                <td>Enforce uniqueness</td>
-                <td>Prevent duplicate prefixes/IP addresses</td>
-                <td>True</td>
-            </tr>
-            <tr>
-                <td>Description</td>
-                <td>Short description (optional)</td>
-                <td>Native VRF for customer ABC</td>
-            </tr>
-        </tbody>
-    </table>
-    <h4>Example</h4>
-    <pre>Customer_ABC,65000:123456,ABC01,True,Native VRF for customer ABC</pre>
-{% endblock %}