| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900 |
- from netaddr import IPNetwork, IPSet
- from netaddr.core import AddrFormatError
- from django_tables2 import RequestConfig
- from django.conf import settings
- from django.contrib import messages
- from django.contrib.auth.decorators import permission_required
- from django.contrib.auth.mixins import PermissionRequiredMixin
- from django.core.urlresolvers import reverse
- from django.db.models import ProtectedError
- from django.http import HttpResponseRedirect
- from django.shortcuts import get_object_or_404, redirect, render
- from django.utils.http import urlencode
- from dcim.models import Device
- from extras.models import ExportTemplate
- from utilities.error_handlers import handle_protectederror
- from utilities.forms import ConfirmationForm
- from utilities.paginator import EnhancedPaginator
- from utilities.views import BulkImportView, BulkEditView, BulkDeleteView
- from .filters import AggregateFilter, PrefixFilter, IPAddressFilter, VLANFilter, VRFFilter
- from .forms import AggregateForm, AggregateImportForm, AggregateBulkEditForm, AggregateBulkDeleteForm, \
- AggregateFilterForm, PrefixForm, PrefixImportForm, PrefixBulkEditForm, PrefixBulkDeleteForm, PrefixFilterForm, \
- IPAddressForm, IPAddressImportForm, IPAddressBulkEditForm, IPAddressBulkDeleteForm, IPAddressFilterForm, VLANForm, \
- VLANImportForm, VLANBulkEditForm, VLANBulkDeleteForm, VRFForm, VRFImportForm, VRFBulkEditForm, VRFBulkDeleteForm, \
- VLANFilterForm
- from .models import VRF, Aggregate, Prefix, VLAN
- from .tables import AggregateTable, AggregateBulkEditTable, PrefixTable, PrefixBriefTable, PrefixBulkEditTable, \
- IPAddress, IPAddressBriefTable, IPAddressTable, IPAddressBulkEditTable, VLANTable, VLANBulkEditTable, VRFTable, \
- VRFBulkEditTable
- def add_available_prefixes(parent, prefix_list):
- """
- Create fake Prefix objects for all unallocated space within a prefix.
- """
- # Find all unallocated space
- available_prefixes = IPSet(parent) ^ IPSet([p.prefix for p in prefix_list])
- available_prefixes = [Prefix(prefix=p) for p in available_prefixes.iter_cidrs()]
- # Concatenate and sort complete list of children
- prefix_list = list(prefix_list) + available_prefixes
- prefix_list.sort(key=lambda p: p.prefix)
- return prefix_list
- #
- # VRFs
- #
- def vrf_list(request):
- queryset = VRF.objects.all()
- queryset = VRFFilter(request.GET, queryset).qs
- # annotate_depth(queryset)
- # Export
- if 'export' in request.GET:
- et = get_object_or_404(ExportTemplate, content_type__model='vrf', name=request.GET.get('export'))
- response = et.to_response(context_dict={'queryset': queryset}, filename='netbox_vrfs')
- return response
- if request.user.has_perm('ipam.change_vrf') or request.user.has_perm('ipam.delete_vrf'):
- vrf_table = VRFBulkEditTable(queryset)
- else:
- vrf_table = VRFTable(queryset)
- RequestConfig(request, paginate={'per_page': settings.PAGINATE_COUNT, 'klass': EnhancedPaginator}).configure(vrf_table)
- export_templates = ExportTemplate.objects.filter(content_type__model='vrf')
- return render(request, 'ipam/vrf_list.html', {
- 'vrf_table': vrf_table,
- 'export_templates': export_templates,
- })
- def vrf(request, pk):
- vrf = get_object_or_404(VRF.objects.all(), pk=pk)
- prefixes = Prefix.objects.filter(vrf=vrf)
- return render(request, 'ipam/vrf.html', {
- 'vrf': vrf,
- 'prefixes': prefixes,
- })
- @permission_required('ipam.add_vrf')
- def vrf_add(request):
- if request.method == 'POST':
- form = VRFForm(request.POST)
- if form.is_valid():
- vrf = form.save()
- messages.success(request, "Added new VRF: {0}".format(vrf))
- if '_addanother' in request.POST:
- return redirect('ipam:vrf_add')
- else:
- return redirect('ipam:vrf', pk=vrf.pk)
- else:
- form = VRFForm()
- return render(request, 'ipam/vrf_edit.html', {
- 'form': form,
- 'cancel_url': reverse('ipam:vrf_list'),
- })
- @permission_required('ipam.change_vrf')
- def vrf_edit(request, pk):
- vrf = get_object_or_404(VRF, pk=pk)
- if request.method == 'POST':
- form = VRFForm(request.POST, instance=vrf)
- if form.is_valid():
- vrf = form.save()
- messages.success(request, "Modified VRF {0}".format(vrf))
- return redirect('ipam:vrf', pk=vrf.pk)
- else:
- form = VRFForm(instance=vrf)
- return render(request, 'ipam/vrf_edit.html', {
- 'vrf': vrf,
- 'form': form,
- 'cancel_url': reverse('ipam:vrf', kwargs={'pk': vrf.pk}),
- })
- @permission_required('ipam.delete_vrf')
- def vrf_delete(request, pk):
- vrf = get_object_or_404(VRF, pk=pk)
- if request.method == 'POST':
- form = ConfirmationForm(request.POST)
- if form.is_valid():
- try:
- vrf.delete()
- messages.success(request, "VRF {0} has been deleted".format(vrf))
- return redirect('ipam:vrf_list')
- except ProtectedError, e:
- handle_protectederror(vrf, request, e)
- return redirect('ipam:vrf', pk=vrf.pk)
- else:
- form = ConfirmationForm()
- return render(request, 'ipam/vrf_delete.html', {
- 'vrf': vrf,
- 'form': form,
- 'cancel_url': reverse('ipam:vrf', kwargs={'pk': vrf.pk})
- })
- class VRFBulkImportView(PermissionRequiredMixin, BulkImportView):
- permission_required = 'ipam.add_vrf'
- form = VRFImportForm
- table = VRFTable
- template_name = 'ipam/vrf_import.html'
- obj_list_url = 'ipam:vrf_list'
- class VRFBulkEditView(PermissionRequiredMixin, BulkEditView):
- permission_required = 'ipam.change_vrf'
- cls = VRF
- form = VRFBulkEditForm
- template_name = 'ipam/vrf_bulk_edit.html'
- redirect_url = 'ipam:vrf_list'
- def update_objects(self, pk_list, form):
- fields_to_update = {}
- for field in ['description']:
- if form.cleaned_data[field]:
- fields_to_update[field] = form.cleaned_data[field]
- updated_count = self.cls.objects.filter(pk__in=pk_list).update(**fields_to_update)
- messages.success(self.request, "Updated {} VRFs".format(updated_count))
- class VRFBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
- permission_required = 'ipam.delete_vrf'
- cls = VRF
- form = VRFBulkDeleteForm
- template_name = 'ipam/vrf_bulk_delete.html'
- redirect_url = 'ipam:vrf_list'
- #
- # Aggregates
- #
- def aggregate_list(request):
- queryset = Aggregate.objects.select_related('rir').extra(
- select = {
- 'child_count': 'SELECT COUNT(*) FROM ipam_prefix WHERE ipam_prefix.prefix <<= ipam_aggregate.prefix',
- }
- )
- queryset = AggregateFilter(request.GET, queryset).qs
- # Export
- if 'export' in request.GET:
- et = get_object_or_404(ExportTemplate, content_type__model='aggregate', name=request.GET.get('export'))
- response = et.to_response(context_dict={'queryset': queryset}, filename='netbox_aggregates')
- return response
- if request.user.has_perm('ipam.change_aggregate') or request.user.has_perm('ipam.delete_aggregate'):
- aggregate_table = AggregateBulkEditTable(queryset)
- else:
- aggregate_table = AggregateTable(queryset)
- RequestConfig(request, paginate={'per_page': settings.PAGINATE_COUNT, 'klass': EnhancedPaginator})\
- .configure(aggregate_table)
- export_templates = ExportTemplate.objects.filter(content_type__model='aggregate')
- return render(request, 'ipam/aggregate_list.html', {
- 'aggregate_table': aggregate_table,
- 'export_templates': export_templates,
- 'filter_form': AggregateFilterForm(request.GET, label_suffix=''),
- })
- def aggregate(request, pk):
- aggregate = get_object_or_404(Aggregate, pk=pk)
- # Find all child prefixes contained by this aggregate
- child_prefixes = Prefix.objects.filter(prefix__net_contained_or_equal=str(aggregate.prefix))\
- .select_related('site', 'status', 'role').annotate_depth(limit=0)
- child_prefixes = add_available_prefixes(aggregate.prefix, child_prefixes)
- if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'):
- prefix_table = PrefixBulkEditTable(child_prefixes)
- else:
- prefix_table = PrefixTable(child_prefixes)
- RequestConfig(request, paginate={'per_page': settings.PAGINATE_COUNT, 'klass': EnhancedPaginator})\
- .configure(prefix_table)
- return render(request, 'ipam/aggregate.html', {
- 'aggregate': aggregate,
- 'prefix_table': prefix_table,
- })
- @permission_required('ipam.add_aggregate')
- def aggregate_add(request):
- if request.method == 'POST':
- form = AggregateForm(request.POST)
- if form.is_valid():
- aggregate = form.save()
- messages.success(request, "Added new aggregate: {0}".format(aggregate.prefix))
- if '_addanother' in request.POST:
- return redirect('ipam:aggregate_add')
- else:
- return redirect('ipam:aggregate', pk=aggregate.pk)
- else:
- form = AggregateForm()
- return render(request, 'ipam/aggregate_edit.html', {
- 'form': form,
- 'cancel_url': reverse('ipam:aggregate_list'),
- })
- @permission_required('ipam.change_aggregate')
- def aggregate_edit(request, pk):
- aggregate = get_object_or_404(Aggregate, pk=pk)
- if request.method == 'POST':
- form = AggregateForm(request.POST, instance=aggregate)
- if form.is_valid():
- aggregate = form.save()
- messages.success(request, "Modified aggregate {0}".format(aggregate.prefix))
- return redirect('ipam:aggregate', pk=aggregate.pk)
- else:
- form = AggregateForm(instance=aggregate)
- return render(request, 'ipam/aggregate_edit.html', {
- 'aggregate': aggregate,
- 'form': form,
- 'cancel_url': reverse('ipam:aggregate', kwargs={'pk': aggregate.pk}),
- })
- @permission_required('ipam.delete_aggregate')
- def aggregate_delete(request, pk):
- aggregate = get_object_or_404(Aggregate, pk=pk)
- if request.method == 'POST':
- form = ConfirmationForm(request.POST)
- if form.is_valid():
- try:
- aggregate.delete()
- messages.success(request, "Aggregate {0} has been deleted".format(aggregate))
- return redirect('ipam:aggregate_list')
- except ProtectedError, e:
- handle_protectederror(aggregate, request, e)
- return redirect('ipam:aggregate', pk=aggregate.pk)
- else:
- form = ConfirmationForm()
- return render(request, 'ipam/aggregate_delete.html', {
- 'aggregate': aggregate,
- 'form': form,
- 'cancel_url': reverse('ipam:aggregate', kwargs={'pk': aggregate.pk})
- })
- class AggregateBulkImportView(PermissionRequiredMixin, BulkImportView):
- permission_required = 'ipam.add_aggregate'
- form = AggregateImportForm
- table = AggregateTable
- template_name = 'ipam/aggregate_import.html'
- obj_list_url = 'ipam:aggregate_list'
- class AggregateBulkEditView(PermissionRequiredMixin, BulkEditView):
- permission_required = 'ipam.change_aggregate'
- cls = Aggregate
- form = AggregateBulkEditForm
- template_name = 'ipam/aggregate_bulk_edit.html'
- redirect_url = 'ipam:aggregate_list'
- def update_objects(self, pk_list, form):
- fields_to_update = {}
- for field in ['rir', 'date_added', 'description']:
- if form.cleaned_data[field]:
- fields_to_update[field] = form.cleaned_data[field]
- updated_count = self.cls.objects.filter(pk__in=pk_list).update(**fields_to_update)
- messages.success(self.request, "Updated {} aggregates".format(updated_count))
- class AggregateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
- permission_required = 'ipam.delete_aggregate'
- cls = Aggregate
- form = AggregateBulkDeleteForm
- template_name = 'ipam/aggregate_bulk_delete.html'
- redirect_url = 'ipam:aggregate_list'
- #
- # Prefixes
- #
- def prefix_list(request):
- queryset = Prefix.objects.select_related('site', 'status', 'role')
- queryset = PrefixFilter(request.GET, queryset).qs
- # Export
- if 'export' in request.GET:
- et = get_object_or_404(ExportTemplate, content_type__model='prefix', name=request.GET.get('export'))
- response = et.to_response(context_dict={'queryset': queryset}, filename='netbox_prefixes')
- return response
- # Show only top-level prefixes by default
- limit = None if request.GET.get('expand') else 0
- prefixes = queryset.annotate_depth(limit=limit)
- if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'):
- prefix_table = PrefixBulkEditTable(prefixes)
- else:
- prefix_table = PrefixTable(prefixes)
- RequestConfig(request, paginate={'per_page': settings.PAGINATE_COUNT, 'klass': EnhancedPaginator}).configure(prefix_table)
- export_templates = ExportTemplate.objects.filter(content_type__model='prefix')
- return render(request, 'ipam/prefix_list.html', {
- 'prefix_table': prefix_table,
- 'export_templates': export_templates,
- 'filter_form': PrefixFilterForm(request.GET, label_suffix=''),
- })
- def prefix(request, pk):
- prefix = get_object_or_404(Prefix.objects.select_related('site', 'vlan', 'status', 'role'), pk=pk)
- try:
- aggregate = Aggregate.objects.get(prefix__net_contains_or_equals=str(prefix.prefix))
- except Aggregate.DoesNotExist:
- aggregate = None
- # Count child IP addresses
- ipaddress_count = IPAddress.objects.filter(address__net_contained_or_equal=str(prefix.prefix)).count()
- # Parent prefixes table
- parent_prefixes = Prefix.objects.filter(vrf=prefix.vrf, prefix__net_contains=str(prefix.prefix))\
- .select_related('site', 'status', 'role').annotate_depth()
- parent_prefix_table = PrefixBriefTable(parent_prefixes)
- # Duplicate prefixes table
- duplicate_prefixes = Prefix.objects.filter(vrf=prefix.vrf, prefix=str(prefix.prefix)).exclude(pk=prefix.pk)\
- .select_related('site', 'status', 'role')
- duplicate_prefix_table = PrefixBriefTable(duplicate_prefixes)
- # Child prefixes table
- child_prefixes = Prefix.objects.filter(vrf=prefix.vrf, prefix__net_contained=str(prefix.prefix))\
- .select_related('site', 'status', 'role').annotate_depth(limit=0)
- if child_prefixes:
- child_prefixes = add_available_prefixes(prefix.prefix, child_prefixes)
- if request.user.has_perm('ipam.change_prefix') or request.user.has_perm('ipam.delete_prefix'):
- child_prefix_table = PrefixBulkEditTable(child_prefixes)
- else:
- child_prefix_table = PrefixTable(child_prefixes)
- RequestConfig(request, paginate={'per_page': settings.PAGINATE_COUNT, 'klass': EnhancedPaginator})\
- .configure(child_prefix_table)
- return render(request, 'ipam/prefix.html', {
- 'prefix': prefix,
- 'aggregate': aggregate,
- 'ipaddress_count': ipaddress_count,
- 'parent_prefix_table': parent_prefix_table,
- 'child_prefix_table': child_prefix_table,
- 'duplicate_prefix_table': duplicate_prefix_table,
- })
- @permission_required('ipam.add_prefix')
- def prefix_add(request):
- if request.method == 'POST':
- form = PrefixForm(request.POST)
- if form.is_valid():
- prefix = form.save()
- messages.success(request, "Added new prefix: {0}".format(prefix.prefix))
- if '_addanother' in request.POST:
- return redirect('ipam:prefix_add')
- else:
- return redirect('ipam:prefix', pk=prefix.pk)
- else:
- form = PrefixForm(initial={
- 'site': request.GET.get('site'),
- 'vrf': request.GET.get('vrf'),
- 'prefix': request.GET.get('prefix'),
- })
- return render(request, 'ipam/prefix_edit.html', {
- 'form': form,
- 'cancel_url': reverse('ipam:prefix_list'),
- })
- @permission_required('ipam.change_prefix')
- def prefix_edit(request, pk):
- prefix = get_object_or_404(Prefix, pk=pk)
- if request.method == 'POST':
- form = PrefixForm(request.POST, instance=prefix)
- if form.is_valid():
- prefix = form.save()
- messages.success(request, "Modified prefix {0}".format(prefix.prefix))
- return redirect('ipam:prefix', pk=prefix.pk)
- else:
- form = PrefixForm(instance=prefix)
- return render(request, 'ipam/prefix_edit.html', {
- 'prefix': prefix,
- 'form': form,
- 'cancel_url': reverse('ipam:prefix', kwargs={'pk': prefix.pk}),
- })
- @permission_required('ipam.delete_prefix')
- def prefix_delete(request, pk):
- prefix = get_object_or_404(Prefix, pk=pk)
- if request.method == 'POST':
- form = ConfirmationForm(request.POST)
- if form.is_valid():
- try:
- prefix.delete()
- messages.success(request, "Prefix {0} has been deleted".format(prefix))
- return redirect('ipam:prefix_list')
- except ProtectedError, e:
- handle_protectederror(prefix, request, e)
- return redirect('ipam:prefix', pk=prefix.pk)
- else:
- form = ConfirmationForm()
- return render(request, 'ipam/prefix_delete.html', {
- 'prefix': prefix,
- 'form': form,
- 'cancel_url': reverse('ipam:prefix', kwargs={'pk': prefix.pk})
- })
- class PrefixBulkImportView(PermissionRequiredMixin, BulkImportView):
- permission_required = 'ipam.add_prefix'
- form = PrefixImportForm
- table = PrefixTable
- template_name = 'ipam/prefix_import.html'
- obj_list_url = 'ipam:prefix_list'
- class PrefixBulkEditView(PermissionRequiredMixin, BulkEditView):
- permission_required = 'ipam.change_prefix'
- cls = Prefix
- form = PrefixBulkEditForm
- template_name = 'ipam/prefix_bulk_edit.html'
- redirect_url = 'ipam:prefix_list'
- def update_objects(self, pk_list, form):
- fields_to_update = {}
- if form.cleaned_data['vrf']:
- fields_to_update['vrf'] = form.cleaned_data['vrf']
- elif form.cleaned_data['vrf_global']:
- fields_to_update['vrf'] = None
- for field in ['site', 'status', 'role', 'description']:
- if form.cleaned_data[field]:
- fields_to_update[field] = form.cleaned_data[field]
- updated_count = self.cls.objects.filter(pk__in=pk_list).update(**fields_to_update)
- messages.success(self.request, "Updated {} prefixes".format(updated_count))
- class PrefixBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
- permission_required = 'ipam.delete_prefix'
- cls = Prefix
- form = PrefixBulkDeleteForm
- template_name = 'ipam/prefix_bulk_delete.html'
- redirect_url = 'ipam:prefix_list'
- def prefix_ipaddresses(request, pk):
- prefix = get_object_or_404(Prefix.objects.all(), pk=pk)
- # Find all IPAddresses belonging to this Prefix
- ipaddresses = IPAddress.objects.filter(address__net_contained_or_equal=str(prefix.prefix))\
- .select_related('vrf', 'interface__device', 'primary_for')
- if request.user.has_perm('ipam.change_ipaddress') or request.user.has_perm('ipam.delete_ipaddress'):
- ip_table = IPAddressBulkEditTable(ipaddresses)
- else:
- ip_table = IPAddressTable(ipaddresses)
- RequestConfig(request, paginate={'per_page': settings.PAGINATE_COUNT, 'klass': EnhancedPaginator})\
- .configure(ip_table)
- return render(request, 'ipam/prefix_ipaddresses.html', {
- 'prefix': prefix,
- 'ip_table': ip_table,
- })
- #
- # IP addresses
- #
- def ipaddress_list(request):
- queryset = IPAddress.objects.select_related('vrf', 'interface__device', 'primary_for')
- queryset = IPAddressFilter(request.GET, queryset).qs
- # Export
- if 'export' in request.GET:
- et = get_object_or_404(ExportTemplate, content_type__model='ipaddress', name=request.GET.get('export'))
- response = et.to_response(context_dict={'queryset': queryset}, filename='netbox_ips')
- return response
- if request.user.has_perm('ipam.change_ipaddress') or request.user.has_perm('ipam.delete_ipaddress'):
- ip_table = IPAddressBulkEditTable(queryset)
- else:
- ip_table = IPAddressTable(queryset)
- RequestConfig(request, paginate={'per_page': settings.PAGINATE_COUNT, 'klass': EnhancedPaginator}).configure(ip_table)
- export_templates = ExportTemplate.objects.filter(content_type__model='ipaddress')
- # If searching and no IPAddresses were found, include a list of parent prefixes matching the query
- prefix_table = None
- if request.GET.get('q') and not queryset:
- try:
- ip = str(IPNetwork(request.GET.get('q')))
- prefix_table = PrefixTable(Prefix.objects.filter(prefix__net_contains_or_equals=ip))
- RequestConfig(request).configure(prefix_table)
- except AddrFormatError:
- pass
- return render(request, 'ipam/ipaddress_list.html', {
- 'ip_table': ip_table,
- 'prefix_table': prefix_table,
- 'export_templates': export_templates,
- 'filter_form': IPAddressFilterForm(request.GET, label_suffix=''),
- })
- def ipaddress(request, pk):
- ipaddress = get_object_or_404(IPAddress.objects.select_related('interface__device'), pk=pk)
- parent_prefixes = Prefix.objects.filter(vrf=ipaddress.vrf, prefix__net_contains=str(ipaddress.address.ip))
- related_ips = IPAddress.objects.select_related('interface__device').exclude(pk=ipaddress.pk).filter(vrf=ipaddress.vrf, address__net_contained_or_equal=str(ipaddress.address))
- related_ips_table = IPAddressBriefTable(related_ips)
- RequestConfig(request, paginate={'per_page': settings.PAGINATE_COUNT, 'klass': EnhancedPaginator}).configure(related_ips_table)
- return render(request, 'ipam/ipaddress.html', {
- 'ipaddress': ipaddress,
- 'parent_prefixes': parent_prefixes,
- 'related_ips_table': related_ips_table,
- })
- @permission_required('ipam.add_ipaddress')
- def ipaddress_add(request):
- if request.method == 'POST':
- form = IPAddressForm(request.POST)
- if form.is_valid():
- ipaddress = form.save()
- messages.success(request, "Created new IP Address: {0}".format(ipaddress))
- if '_addanother' in request.POST:
- return redirect('ipam:ipaddress_add')
- else:
- return redirect('ipam:ipaddress', pk=ipaddress.pk)
- else:
- form = IPAddressForm(initial={
- 'ipaddress': request.GET.get('ipaddress', None),
- })
- return render(request, 'ipam/ipaddress_edit.html', {
- 'form': form,
- 'cancel_url': reverse('ipam:ipaddress_list'),
- })
- @permission_required('ipam.change_ipaddress')
- def ipaddress_edit(request, pk):
- ipaddress = get_object_or_404(IPAddress, pk=pk)
- if request.method == 'POST':
- form = IPAddressForm(request.POST, instance=ipaddress)
- if form.is_valid():
- ipaddress = form.save()
- messages.success(request, "Modified IP address {0}".format(ipaddress))
- return redirect('ipam:ipaddress', pk=ipaddress.pk)
- else:
- form = IPAddressForm(instance=ipaddress)
- return render(request, 'ipam/ipaddress_edit.html', {
- 'ipaddress': ipaddress,
- 'form': form,
- 'cancel_url': reverse('ipam:ipaddress', kwargs={'pk': ipaddress.pk}),
- })
- @permission_required('ipam.delete_ipaddress')
- def ipaddress_delete(request, pk):
- ipaddress = get_object_or_404(IPAddress, pk=pk)
- if request.method == 'POST':
- form = ConfirmationForm(request.POST)
- if form.is_valid():
- try:
- ipaddress.delete()
- messages.success(request, "IP address {0} has been deleted".format(ipaddress))
- if ipaddress.interface:
- return redirect('dcim:device', pk=ipaddress.interface.device.pk)
- else:
- return redirect('ipam:ipaddress_list')
- except ProtectedError, e:
- handle_protectederror(ipaddress, request, e)
- return redirect('ipam:ipaddress', pk=ipaddress.pk)
- else:
- form = ConfirmationForm()
- # Upon cancellation, redirect to the assigned device if one exists
- if ipaddress.interface:
- cancel_url = reverse('dcim:device', kwargs={'pk': ipaddress.interface.device.pk})
- else:
- cancel_url = reverse('ipam:ipaddress_list')
- return render(request, 'ipam/ipaddress_delete.html', {
- 'ipaddress': ipaddress,
- 'form': form,
- 'cancel_url': cancel_url,
- })
- class IPAddressBulkImportView(PermissionRequiredMixin, BulkImportView):
- permission_required = 'ipam.add_ipaddress'
- form = IPAddressImportForm
- table = IPAddressTable
- template_name = 'ipam/ipaddress_import.html'
- obj_list_url = 'ipam:ipaddress_list'
- def save_obj(self, obj):
- obj.save()
- # Update primary IP for device if needed
- try:
- device = obj.primary_for
- device.primary_ip = obj
- device.save()
- except Device.DoesNotExist:
- pass
- class IPAddressBulkEditView(PermissionRequiredMixin, BulkEditView):
- permission_required = 'ipam.change_ipaddress'
- cls = IPAddress
- form = IPAddressBulkEditForm
- template_name = 'ipam/ipaddress_bulk_edit.html'
- redirect_url = 'ipam:ipaddress_list'
- def update_objects(self, pk_list, form):
- fields_to_update = {}
- if form.cleaned_data['vrf']:
- fields_to_update['vrf'] = form.cleaned_data['vrf']
- elif form.cleaned_data['vrf_global']:
- fields_to_update['vrf'] = None
- for field in ['description']:
- if form.cleaned_data[field]:
- fields_to_update[field] = form.cleaned_data[field]
- updated_count = self.cls.objects.filter(pk__in=pk_list).update(**fields_to_update)
- messages.success(self.request, "Updated {} IP addresses".format(updated_count))
- class IPAddressBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
- permission_required = 'ipam.delete_ipaddress'
- cls = IPAddress
- form = IPAddressBulkDeleteForm
- template_name = 'ipam/ipaddress_bulk_delete.html'
- redirect_url = 'ipam:ipaddress_list'
- #
- # VLANs
- #
- def vlan_list(request):
- queryset = VLAN.objects.select_related('site', 'status', 'role')
- queryset = VLANFilter(request.GET, queryset).qs
- # Export
- if 'export' in request.GET:
- et = get_object_or_404(ExportTemplate, content_type__model='vlan', name=request.GET.get('export'))
- response = et.to_response(context_dict={'queryset': queryset}, filename='netbox_vlans')
- return response
- if request.user.has_perm('ipam.change_vlan') or request.user.has_perm('ipam.delete_vlan'):
- vlan_table = VLANBulkEditTable(queryset)
- else:
- vlan_table = VLANTable(queryset)
- RequestConfig(request, paginate={'per_page': settings.PAGINATE_COUNT, 'klass': EnhancedPaginator}).configure(vlan_table)
- export_templates = ExportTemplate.objects.filter(content_type__model='vlan')
- return render(request, 'ipam/vlan_list.html', {
- 'vlan_table': vlan_table,
- 'export_templates': export_templates,
- 'filter_form': VLANFilterForm(request.GET, label_suffix=''),
- })
- def vlan(request, pk):
- vlan = get_object_or_404(VLAN.objects.select_related('site', 'status', 'role'), pk=pk)
- prefixes = Prefix.objects.filter(vlan=vlan)
- return render(request, 'ipam/vlan.html', {
- 'vlan': vlan,
- 'prefixes': prefixes,
- })
- @permission_required('ipam.add_vlan')
- def vlan_add(request):
- if request.method == 'POST':
- form = VLANForm(request.POST)
- if form.is_valid():
- vlan = form.save()
- messages.success(request, "Added new VLAN: {0}".format(vlan))
- if '_addanother' in request.POST:
- base_url = reverse('ipam:vlan_add')
- params = urlencode({
- 'site': vlan.site.pk,
- })
- return HttpResponseRedirect('{}?{}'.format(base_url, params))
- else:
- return redirect('ipam:vlan', pk=vlan.pk)
- else:
- form = VLANForm()
- return render(request, 'ipam/vlan_edit.html', {
- 'form': form,
- 'cancel_url': reverse('ipam:vlan_list'),
- })
- @permission_required('ipam.change_vlan')
- def vlan_edit(request, pk):
- vlan = get_object_or_404(VLAN, pk=pk)
- if request.method == 'POST':
- form = VLANForm(request.POST, instance=vlan)
- if form.is_valid():
- vlan = form.save()
- messages.success(request, "Modified VLAN {0}".format(vlan))
- return redirect('ipam:vlan', pk=vlan.pk)
- else:
- form = VLANForm(instance=vlan)
- return render(request, 'ipam/vlan_edit.html', {
- 'vlan': vlan,
- 'form': form,
- 'cancel_url': reverse('ipam:vlan', kwargs={'pk': vlan.pk}),
- })
- @permission_required('ipam.delete_vlan')
- def vlan_delete(request, pk):
- vlan = get_object_or_404(VLAN, pk=pk)
- if request.method == 'POST':
- form = ConfirmationForm(request.POST)
- if form.is_valid():
- try:
- vlan.delete()
- messages.success(request, "VLAN {0} has been deleted".format(vlan))
- return redirect('ipam:vlan_list')
- except ProtectedError, e:
- handle_protectederror(vlan, request, e)
- return redirect('ipam:vlan', pk=vlan.pk)
- else:
- form = ConfirmationForm()
- return render(request, 'ipam/vlan_delete.html', {
- 'vlan': vlan,
- 'form': form,
- 'cancel_url': reverse('ipam:vlan', kwargs={'pk': vlan.pk})
- })
- class VLANBulkImportView(PermissionRequiredMixin, BulkImportView):
- permission_required = 'ipam.add_vlan'
- form = VLANImportForm
- table = VLANTable
- template_name = 'ipam/vlan_import.html'
- obj_list_url = 'ipam:vlan_list'
- class VLANBulkEditView(PermissionRequiredMixin, BulkEditView):
- permission_required = 'ipam.change_vlan'
- cls = VLAN
- form = VLANBulkEditForm
- template_name = 'ipam/vlan_bulk_edit.html'
- redirect_url = 'ipam:vlan_list'
- def update_objects(self, pk_list, form):
- fields_to_update = {}
- for field in ['site', 'status', 'role']:
- if form.cleaned_data[field]:
- fields_to_update[field] = form.cleaned_data[field]
- updated_count = self.cls.objects.filter(pk__in=pk_list).update(**fields_to_update)
- messages.success(self.request, "Updated {} VLANs".format(updated_count))
- class VLANBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
- permission_required = 'ipam.delete_vlan'
- cls = VLAN
- form = VLANBulkDeleteForm
- template_name = 'ipam/vlan_bulk_delete.html'
- redirect_url = 'ipam:vlan_list'
|