netbox-plugin-interface-sync/netbox_interface_sync/views.py

310 lines
16 KiB
Python
Raw Normal View History

from django.db.models.fields.related import ForeignKey
2021-04-20 10:22:26 +03:00
from django.shortcuts import get_object_or_404, render, redirect
from django.views.generic import View
from dcim.choices import PortTypeChoices
from dcim.models import Device, Interface, InterfaceTemplate, PowerPort, PowerPortTemplate, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, DeviceBay, DeviceBayTemplate, FrontPort, FrontPortTemplate,PowerOutlet, PowerOutletTemplate, RearPort, RearPortTemplate
2021-04-20 10:22:26 +03:00
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.conf import settings
from django.contrib import messages
from .utils import ComparisonPowerOutlet, UnifiedInterface, natural_keys, get_components, post_components
2021-04-20 10:22:26 +03:00
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))
2021-08-25 16:16:56 +03:00
interfaces = device.vc_interfaces()
2021-04-20 10:22:26 +03:00
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)
return get_components(request, device, interfaces, interface_templates)
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)
return post_components(request, device, interfaces, interface_templates, Interface, InterfaceTemplate)
class PowerPortComparisonView(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))
powerports = device.powerports.all()
powerports_templates = PowerPortTemplate.objects.filter(device_type=device.device_type)
return get_components(request, device, powerports, powerports_templates)
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))
powerports = device.powerports.all()
powerports_templates = PowerPortTemplate.objects.filter(device_type=device.device_type)
return post_components(request, device, powerports, powerports_templates, PowerPort, PowerPortTemplate)
class ConsolePortComparisonView(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))
consoleports = device.consoleports.all()
consoleports_templates = ConsolePortTemplate.objects.filter(device_type=device.device_type)
return get_components(request, device, consoleports, consoleports_templates)
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))
consoleports = device.consoleports.all()
consoleports_templates = ConsolePortTemplate.objects.filter(device_type=device.device_type)
return post_components(request, device, consoleports, consoleports_templates, ConsolePort, ConsolePortTemplate)
class ConsoleServerPortComparisonView(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))
consoleserverports = device.consoleserverports.all()
consoleserverports_templates = ConsoleServerPortTemplate.objects.filter(device_type=device.device_type)
return get_components(request, device, consoleserverports, consoleserverports_templates)
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))
consoleserverports = device.consoleserverports.all()
consoleserverports_templates = ConsoleServerPortTemplate.objects.filter(device_type=device.device_type)
return post_components(request, device, consoleserverports, consoleserverports_templates, ConsoleServerPort, ConsoleServerPortTemplate)
class PowerOutletComparisonView(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))
poweroutlets = device.poweroutlets.all()
poweroutlets_templates = PowerOutletTemplate.objects.filter(device_type=device.device_type)
unified_components = [ComparisonPowerOutlet(i.id, i.name, i.type, i.get_type_display(), power_port_name=PowerPort.objects.get(id=i.power_port_id).name if i.power_port_id is not None else "") for i in poweroutlets]
unified_component_templates = [
ComparisonPowerOutlet(i.id, i.name, i.type, i.get_type_display(), is_template=True, power_port_name=PowerPortTemplate.objects.get(id=i.power_port_id).name if i.power_port_id is not None else "") for i in poweroutlets_templates]
2021-04-20 10:22:26 +03:00
# List of interfaces and interface templates presented in the unified format
overall_powers = list(set(unified_component_templates + unified_components))
overall_powers.sort(key=lambda o: natural_keys(o.name))
2021-04-20 10:22:26 +03:00
comparison_templates = []
comparison_interfaces = []
for i in overall_powers:
2021-04-20 10:22:26 +03:00
try:
comparison_templates.append(unified_component_templates[unified_component_templates.index(i)])
2021-04-20 10:22:26 +03:00
except ValueError:
comparison_templates.append(None)
try:
comparison_interfaces.append(unified_components[unified_components.index(i)])
2021-04-20 10:22:26 +03:00
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(unified_component_templates),
"interfaces_count": len(poweroutlets),
2021-04-20 10:22:26 +03:00
"device": device
}
2021-04-20 10:22:26 +03:00
)
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))
poweroutlets = device.poweroutlets.all()
poweroutlets_templates = PowerOutletTemplate.objects.filter(device_type=device.device_type)
#se il template ha una power port che non ho nel device fisico stop
device_pp = PowerPort.objects.filter(device_id=device.id)
matching = {}
mismatch = False
for i in poweroutlets_templates:
found = False
if i.power_port_id is not None:
ppt = PowerPortTemplate.objects.get(id=i.power_port_id)
for pp in device_pp:
if pp.name == ppt.name:
matching[i.id] = pp.id
found = True
if not found:
mismatch = True
break
if not mismatch:
2021-04-20 10:22:26 +03:00
# Manually validating interfaces and interface templates lists
with open("/tmp/ciccio.log", "w") as f:
f.write(str(request.POST.getlist("add_to_device")))
2021-04-20 10:22:26 +03:00
add_to_device = filter(
lambda i: i in poweroutlets_templates.values_list("id", flat=True),
2021-04-20 10:22:26 +03:00
map(int, filter(lambda x: x.isdigit(), request.POST.getlist("add_to_device")))
)
remove_from_device = filter(
lambda i: i in poweroutlets.values_list("id", flat=True),
2021-04-20 10:22:26 +03:00
map(int, filter(lambda x: x.isdigit(), request.POST.getlist("remove_from_device")))
)
# Remove selected interfaces from the device and count them
deleted = PowerOutlet.objects.filter(id__in=remove_from_device).delete()[0]
2021-04-20 10:22:26 +03:00
# Add selected interfaces to the device and count them
add_to_device_component = PowerOutletTemplate.objects.filter(id__in=add_to_device)
bulk_create = []
keys_to_avoid = ["id"]
for i in add_to_device_component.values():
tmp = PowerOutlet()
tmp.device = device
for k in i.keys():
if k not in keys_to_avoid:
setattr(tmp, k, i[k])
tmp.power_port_id = matching.get(i["id"], None)
bulk_create.append(tmp)
created = len(PowerOutlet.objects.bulk_create(bulk_create))
2021-04-20 10:22:26 +03:00
# Getting and validating a list of interfaces to rename
fix_name_components = filter(lambda i: str(i.id) in request.POST.getlist("fix_name"), poweroutlets)
2021-04-20 10:22:26 +03:00
# Casting interface templates into UnifiedInterface objects for proper comparison with interfaces for renaming
unified_component_templates = [
ComparisonPowerOutlet(i.id, i.name, i.type, i.get_type_display(), is_template=True, power_port_name=PowerPortTemplate.objects.get(id=i.power_port_id).name if i.power_port_id is not None else "") for i in poweroutlets_templates]
2021-04-20 10:22:26 +03:00
# Rename selected interfaces
fixed = 0
for component in fix_name_components:
unified_component = [ComparisonPowerOutlet(i.id, i.name, i.type, i.get_type_display(), power_port_name=PowerPort.objects.get(id=i.power_port_id).name if i.power_port_id is not None else "") for i in poweroutlets]
2021-04-20 10:22:26 +03:00
try:
# Try to extract an interface template with the corresponding name
corresponding_template = unified_component_templates[unified_component_templates.index(unified_component)]
component.name = corresponding_template.name
component.save()
fixed += 1
2021-04-20 10:22:26 +03:00
except ValueError:
pass
# Generating result message
message = []
if created > 0:
message.append(f"created {created} interfaces")
if deleted > 0:
message.append(f"deleted {deleted} interfaces")
if fixed > 0:
message.append(f"fixed {fixed} interfaces")
2021-04-20 10:22:26 +03:00
messages.success(request, "; ".join(message).capitalize())
return redirect(request.path)
else:
messages.error(request, "Fai prima le power ports")
return redirect(request.path)
class FrontPortComparisonView(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))
frontports = device.frontports.all()
frontports_templates = FrontPortTemplate.objects.filter(device_type=device.device_type)
return get_components(request, device, frontports, frontports_templates)
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))
frontports = device.frontports.all()
frontports_templates = FrontPortTemplate.objects.filter(device_type=device.device_type)
return post_components(request, device, frontports, frontports_templates, FrontPort, FrontPortTemplate)
class RearPortComparisonView(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))
rearports = device.rearports.all()
rearports_templates = RearPortTemplate.objects.filter(device_type=device.device_type)
return get_components(request, device, rearports, rearports_templates)
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))
rearports = device.rearports.all()
rearports_templates = RearPortTemplate.objects.filter(device_type=device.device_type)
return post_components(request, device, rearports, rearports_templates, RearPort, RearPortTemplate)
class DeviceBayComparisonView(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))
devicebays = device.devicebays.all()
devicebays_templates = DeviceBayTemplate.objects.filter(device_type=device.device_type)
return get_components(request, device, devicebays, devicebays_templates)
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))
devicebays = device.devicebays.all()
devicebays_templates = DeviceBayTemplate.objects.filter(device_type=device.device_type)
return post_components(request, device, devicebays, devicebays_templates, DeviceBay, DeviceBayTemplate)