mirror of
https://github.com/drygdryg/netbox-plugin-interface-sync
synced 2025-02-17 21:22:21 +03:00
This plugin has been re-developed for Netbox 4. The sync button has been redesigned as well as the colors of the sync table.
115 lines
5.8 KiB
Python
115 lines
5.8 KiB
Python
from django.shortcuts import get_object_or_404, render, redirect
|
|
from django.views.generic import View
|
|
from dcim.models import Device, Interface, InterfaceTemplate
|
|
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
|
|
from django.conf import settings
|
|
from django.contrib import messages
|
|
|
|
from .utils import UnifiedInterface, natural_keys
|
|
from .forms import InterfaceComparisonForm
|
|
|
|
config = settings.PLUGINS_CONFIG['netbox_interface_sync']
|
|
|
|
|
|
class InterfaceComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View):
|
|
"""Comparison of interfaces between a device and a device type and beautiful visualization"""
|
|
permission_required = ("dcim.view_interface", "dcim.add_interface", "dcim.change_interface", "dcim.delete_interface")
|
|
|
|
def get(self, request, device_id):
|
|
device = get_object_or_404(Device.objects.filter(id=device_id))
|
|
interfaces = device.vc_interfaces()
|
|
if config["exclude_virtual_interfaces"]:
|
|
interfaces = list(filter(lambda i: not i.is_virtual, interfaces))
|
|
interface_templates = InterfaceTemplate.objects.filter(device_type=device.device_type)
|
|
|
|
unified_interfaces = [UnifiedInterface(i.id, i.name, i.type, i.get_type_display()) for i in interfaces]
|
|
unified_interface_templates = [
|
|
UnifiedInterface(i.id, i.name, i.type, i.get_type_display(), is_template=True) for i in interface_templates]
|
|
|
|
# List of interfaces and interface templates presented in the unified format
|
|
overall_interfaces = list(set(unified_interface_templates + unified_interfaces))
|
|
overall_interfaces.sort(key=lambda o: natural_keys(o.name))
|
|
|
|
comparison_templates = []
|
|
comparison_interfaces = []
|
|
for i in overall_interfaces:
|
|
try:
|
|
comparison_templates.append(unified_interface_templates[unified_interface_templates.index(i)])
|
|
except ValueError:
|
|
comparison_templates.append(None)
|
|
|
|
try:
|
|
comparison_interfaces.append(unified_interfaces[unified_interfaces.index(i)])
|
|
except ValueError:
|
|
comparison_interfaces.append(None)
|
|
|
|
comparison_items = list(zip(comparison_templates, comparison_interfaces))
|
|
return render(
|
|
request, "netbox_interface_sync/interface_comparison.html",
|
|
{
|
|
"comparison_items": comparison_items,
|
|
"templates_count": len(interface_templates),
|
|
"interfaces_count": len(interfaces),
|
|
"device": device
|
|
}
|
|
)
|
|
|
|
def post(self, request, device_id):
|
|
form = InterfaceComparisonForm(request.POST)
|
|
if form.is_valid():
|
|
device = get_object_or_404(Device.objects.filter(id=device_id))
|
|
interfaces = device.vc_interfaces()
|
|
if config["exclude_virtual_interfaces"]:
|
|
interfaces = interfaces.exclude(type__in=["virtual", "lag"])
|
|
interface_templates = InterfaceTemplate.objects.filter(device_type=device.device_type)
|
|
|
|
# Manually validating interfaces and interface templates lists
|
|
add_to_device = filter(
|
|
lambda i: i in interface_templates.values_list("id", flat=True),
|
|
map(int, filter(lambda x: x.isdigit(), request.POST.getlist("add_to_device")))
|
|
)
|
|
remove_from_device = filter(
|
|
lambda i: i in interfaces.values_list("id", flat=True),
|
|
map(int, filter(lambda x: x.isdigit(), request.POST.getlist("remove_from_device")))
|
|
)
|
|
|
|
# Remove selected interfaces from the device and count them
|
|
interfaces_deleted = Interface.objects.filter(id__in=remove_from_device).delete()[0]
|
|
|
|
# Add selected interfaces to the device and count them
|
|
add_to_device_interfaces = InterfaceTemplate.objects.filter(id__in=add_to_device)
|
|
interfaces_created = len(Interface.objects.bulk_create([
|
|
Interface(device=device, name=i.name, type=i.type) for i in add_to_device_interfaces
|
|
]))
|
|
|
|
# Getting and validating a list of interfaces to rename
|
|
fix_name_interfaces = filter(lambda i: str(i.id) in request.POST.getlist("fix_name"), interfaces)
|
|
# Casting interface templates into UnifiedInterface objects for proper comparison with interfaces for renaming
|
|
unified_interface_templates = [
|
|
UnifiedInterface(i.id, i.name, i.type, i.get_type_display()) for i in interface_templates]
|
|
|
|
# Rename selected interfaces
|
|
interfaces_fixed = 0
|
|
for interface in fix_name_interfaces:
|
|
unified_interface = UnifiedInterface(interface.id, interface.name, interface.type, interface.get_type_display())
|
|
try:
|
|
# Try to extract an interface template with the corresponding name
|
|
corresponding_template = unified_interface_templates[unified_interface_templates.index(unified_interface)]
|
|
interface.name = corresponding_template.name
|
|
interface.save()
|
|
interfaces_fixed += 1
|
|
except ValueError:
|
|
pass
|
|
|
|
# Generating result message
|
|
message = []
|
|
if interfaces_created > 0:
|
|
message.append(f"created {interfaces_created} interfaces")
|
|
if interfaces_deleted > 0:
|
|
message.append(f"deleted {interfaces_deleted} interfaces")
|
|
if interfaces_fixed > 0:
|
|
message.append(f"fixed {interfaces_fixed} interfaces")
|
|
messages.success(request, "; ".join(message).capitalize())
|
|
|
|
return redirect(request.path)
|