From 977cad3830e90117d7e16bebcb7074d957400376 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 9 Oct 2017 15:42:06 -0400 Subject: [PATCH] Added bulk import views for RIRs, roles, and VLAN groups --- netbox/dcim/forms.py | 1 - netbox/ipam/forms.py | 42 ++++++++++++++++++++++++++++++ netbox/ipam/urls.py | 3 +++ netbox/ipam/views.py | 21 +++++++++++++++ netbox/templates/inc/nav_menu.html | 6 ++--- 5 files changed, 69 insertions(+), 4 deletions(-) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index da21f2859..820477e24 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -666,7 +666,6 @@ class PlatformCSVForm(forms.ModelForm): fields = ['name', 'slug', 'napalm_driver'] help_texts = { 'name': 'Platform name', - # 'color': 'RGB color in hexadecimal (e.g. 00ff00)' } diff --git a/netbox/ipam/forms.py b/netbox/ipam/forms.py index 1e4c3ed2d..5ed405c8d 100644 --- a/netbox/ipam/forms.py +++ b/netbox/ipam/forms.py @@ -97,6 +97,17 @@ class RIRForm(BootstrapMixin, forms.ModelForm): fields = ['name', 'slug', 'is_private'] +class RIRCSVForm(forms.ModelForm): + slug = SlugField() + + class Meta: + model = RIR + fields = ['name', 'slug', 'is_private'] + help_texts = { + 'name': 'RIR name', + } + + class RIRFilterForm(BootstrapMixin, forms.Form): is_private = forms.NullBooleanField(required=False, label='Private', widget=forms.Select(choices=[ ('', '---------'), @@ -169,6 +180,17 @@ class RoleForm(BootstrapMixin, forms.ModelForm): fields = ['name', 'slug'] +class RoleCSVForm(forms.ModelForm): + slug = SlugField() + + class Meta: + model = Role + fields = ['name', 'slug'] + help_texts = { + 'name': 'Role name', + } + + # # Prefixes # @@ -718,6 +740,26 @@ class VLANGroupForm(BootstrapMixin, forms.ModelForm): fields = ['site', 'name', 'slug'] +class VLANGroupCSVForm(forms.ModelForm): + 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.', + } + ) + slug = SlugField() + + class Meta: + model = VLANGroup + fields = ['site', 'name', 'slug'] + help_texts = { + 'name': 'Name of VLAN group', + } + + class VLANGroupFilterForm(BootstrapMixin, forms.Form): site = FilterChoiceField( queryset=Site.objects.annotate(filter_count=Count('vlan_groups')), diff --git a/netbox/ipam/urls.py b/netbox/ipam/urls.py index 15634c0ee..c5723ef94 100644 --- a/netbox/ipam/urls.py +++ b/netbox/ipam/urls.py @@ -21,6 +21,7 @@ urlpatterns = [ # RIRs url(r'^rirs/$', views.RIRListView.as_view(), name='rir_list'), url(r'^rirs/add/$', views.RIRCreateView.as_view(), name='rir_add'), + url(r'^rirs/import/$', views.RIRBulkImportView.as_view(), name='rir_import'), url(r'^rirs/delete/$', views.RIRBulkDeleteView.as_view(), name='rir_bulk_delete'), url(r'^rirs/(?P[\w-]+)/edit/$', views.RIREditView.as_view(), name='rir_edit'), @@ -37,6 +38,7 @@ urlpatterns = [ # Roles url(r'^roles/$', views.RoleListView.as_view(), name='role_list'), url(r'^roles/add/$', views.RoleCreateView.as_view(), name='role_add'), + url(r'^roles/import/$', views.RoleBulkImportView.as_view(), name='role_import'), url(r'^roles/delete/$', views.RoleBulkDeleteView.as_view(), name='role_bulk_delete'), url(r'^roles/(?P[\w-]+)/edit/$', views.RoleEditView.as_view(), name='role_edit'), @@ -65,6 +67,7 @@ urlpatterns = [ # VLAN groups url(r'^vlan-groups/$', views.VLANGroupListView.as_view(), name='vlangroup_list'), url(r'^vlan-groups/add/$', views.VLANGroupCreateView.as_view(), name='vlangroup_add'), + url(r'^vlan-groups/import/$', views.VLANGroupBulkImportView.as_view(), name='vlangroup_import'), url(r'^vlan-groups/delete/$', views.VLANGroupBulkDeleteView.as_view(), name='vlangroup_bulk_delete'), url(r'^vlan-groups/(?P\d+)/edit/$', views.VLANGroupEditView.as_view(), name='vlangroup_edit'), diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 1723b08d7..7cf24614f 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -261,6 +261,13 @@ class RIREditView(RIRCreateView): permission_required = 'ipam.change_rir' +class RIRBulkImportView(PermissionRequiredMixin, BulkImportView): + permission_required = 'ipam.add_rir' + model_form = forms.RIRCSVForm + table = tables.RIRTable + default_return_url = 'ipam:rir_list' + + class RIRBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): permission_required = 'ipam.delete_rir' cls = RIR @@ -407,6 +414,13 @@ class RoleEditView(RoleCreateView): permission_required = 'ipam.change_role' +class RoleBulkImportView(PermissionRequiredMixin, BulkImportView): + permission_required = 'ipam.add_role' + model_form = forms.RoleCSVForm + table = tables.RoleTable + default_return_url = 'ipam:role_list' + + class RoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): permission_required = 'ipam.delete_role' cls = Role @@ -745,6 +759,13 @@ class VLANGroupEditView(VLANGroupCreateView): permission_required = 'ipam.change_vlangroup' +class VLANGroupBulkImportView(PermissionRequiredMixin, BulkImportView): + permission_required = 'ipam.add_vlangroup' + model_form = forms.VLANGroupCSVForm + table = tables.VLANGroupTable + default_return_url = 'ipam:vlangroup_list' + + class VLANGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): permission_required = 'ipam.delete_vlangroup' cls = VLANGroup diff --git a/netbox/templates/inc/nav_menu.html b/netbox/templates/inc/nav_menu.html index 64b3c9678..cd1e96aa5 100644 --- a/netbox/templates/inc/nav_menu.html +++ b/netbox/templates/inc/nav_menu.html @@ -211,7 +211,7 @@ {% if perms.ipam.add_role %}
- +
{% endif %} Prefix/VLAN Roles @@ -231,7 +231,7 @@ {% if perms.ipam.add_rir %}
- +
{% endif %} RIRs @@ -262,7 +262,7 @@ {% if perms.ipam.add_vlangroup %}
- +
{% endif %} VLAN Groups