Fix interface comparison. Modified global post

This commit is contained in:
rizlas 2021-12-28 20:29:37 +01:00
parent 80112869e0
commit d1b2b82d13
3 changed files with 234 additions and 176 deletions

View File

@ -59,6 +59,10 @@ class InterfaceComparison(ParentTypedComparison):
and (self.mgmt_only == other.mgmt_only) and (self.mgmt_only == other.mgmt_only)
) )
def __hash__(self):
# Ignore some fields when hashing; ignore interface name case and whitespaces
return hash((self.name.lower().replace(" ", ""), self.type))
@dataclass(frozen=True) @dataclass(frozen=True)
class FrontPortComparison(ParentTypedComparison): class FrontPortComparison(ParentTypedComparison):
@ -143,24 +147,3 @@ class DeviceBayComparison(ParentComparison):
"""A unified way to represent the interface and interface template""" """A unified way to represent the interface and interface template"""
is_template: bool = False is_template: bool = False
@dataclass(frozen=True)
class UnifiedInterface:
"""A unified way to represent the interface and interface template"""
id: int
name: str
type: str = ""
type_display: str = ""
is_template: bool = False
def __eq__(self, other):
# Ignore some fields when comparing; ignore interface name case and whitespaces
return (
self.name.lower().replace(" ", "") == other.name.lower().replace(" ", "")
) and (self.type == other.type)
def __hash__(self):
# Ignore some fields when hashing; ignore interface name case and whitespaces
return hash((self.name.lower().replace(" ", ""), self.type))

View File

@ -2,7 +2,7 @@ import re
from typing import Iterable from typing import Iterable
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.contrib import messages from django.contrib import messages
from .comparison import UnifiedInterface from django.core.exceptions import ObjectDoesNotExist
def split(s): def split(s):
@ -20,18 +20,6 @@ def human_sorted(iterable: Iterable):
def get_components(request, device, components, unified_components, unified_component_templates): def get_components(request, device, components, unified_components, unified_component_templates):
# try:
# unified_components = [UnifiedInterface(i.id, i.name, i.type, i.get_type_display()) for i in components]
# except AttributeError:
# unified_components = [UnifiedInterface(i.id, i.name) for i in components]
# try:
# unified_component_templates = [
# UnifiedInterface(i.id, i.name, i.type, i.get_type_display(), is_template=True) for i in component_templates]
# except AttributeError:
# unified_component_templates = [
# UnifiedInterface(i.id, i.name, is_template=True) for i in component_templates]
# List of interfaces and interface templates presented in the unified format # List of interfaces and interface templates presented in the unified format
overall_powers = list(set(unified_component_templates + unified_components)) overall_powers = list(set(unified_component_templates + unified_components))
overall_powers.sort(key=lambda o: natural_keys(o.name)) overall_powers.sort(key=lambda o: natural_keys(o.name))
@ -67,7 +55,7 @@ def get_components(request, device, components, unified_components, unified_comp
def post_components( def post_components(
request, device, components, component_templates, ObjectType, ObjectTemplateType request, device, components, component_templates, ObjectType, ObjectTemplateType, unified_component, unified_component_templates
): ):
# Manually validating interfaces and interface templates lists # Manually validating interfaces and interface templates lists
add_to_device = filter( add_to_device = filter(
@ -89,50 +77,38 @@ def post_components(
add_to_device_component = ObjectTemplateType.objects.filter(id__in=add_to_device) add_to_device_component = ObjectTemplateType.objects.filter(id__in=add_to_device)
bulk_create = [] bulk_create = []
updated = 0
keys_to_avoid = ["id"] keys_to_avoid = ["id"]
for i in add_to_device_component.values(): for i in add_to_device_component.values():
to_create = False
try:
tmp = components.get(name=i["name"])
except ObjectDoesNotExist:
tmp = ObjectType() tmp = ObjectType()
tmp.device = device tmp.device = device
to_create = True
for k in i.keys(): for k in i.keys():
if k not in keys_to_avoid: if k not in keys_to_avoid:
setattr(tmp, k, i[k]) setattr(tmp, k, i[k])
if to_create:
bulk_create.append(tmp) bulk_create.append(tmp)
else:
tmp.save()
updated += 1
created = len(ObjectType.objects.bulk_create(bulk_create)) created = len(ObjectType.objects.bulk_create(bulk_create))
# Getting and validating a list of interfaces to rename
fix_name_components = filter(
lambda i: str(i.id) in request.POST.getlist("fix_name"), components
)
# Casting interface templates into UnifiedInterface objects for proper comparison with interfaces for renaming
try:
unified_component_templates = [
UnifiedInterface(i.id, i.name, i.type, i.get_type_display())
for i in component_templates
]
except AttributeError:
unified_component_templates = [
UnifiedInterface(i.id, i.name) for i in component_templates
]
# Rename selected interfaces # Rename selected interfaces
fixed = 0 fixed = 0
for component in fix_name_components: for component, component_comparison in unified_component:
try:
unified_component = UnifiedInterface(
component.id,
component.name,
component.type,
component.get_type_display(),
)
except AttributeError:
unified_component = UnifiedInterface(component.id, component.name)
try: try:
# Try to extract an interface template with the corresponding name # Try to extract an interface template with the corresponding name
corresponding_template = unified_component_templates[ corresponding_template = unified_component_templates[
unified_component_templates.index(unified_component) unified_component_templates.index(component_comparison)
] ]
component.name = corresponding_template.name component.name = corresponding_template.name
component.save() component.save()
@ -144,6 +120,8 @@ def post_components(
message = [] message = []
if created > 0: if created > 0:
message.append(f"created {created} interfaces") message.append(f"created {created} interfaces")
if updated > 0:
message.append(f"updated {updated} interfaces")
if deleted > 0: if deleted > 0:
message.append(f"deleted {deleted} interfaces") message.append(f"deleted {deleted} interfaces")
if fixed > 0: if fixed > 0:

View File

@ -40,7 +40,27 @@ class InterfaceComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View)
interfaces = interfaces.exclude(type__in=["virtual", "lag"]) interfaces = interfaces.exclude(type__in=["virtual", "lag"])
interface_templates = InterfaceTemplate.objects.filter(device_type=device.device_type) interface_templates = InterfaceTemplate.objects.filter(device_type=device.device_type)
return post_components(request, device, interfaces, interface_templates, Interface, InterfaceTemplate) # Getting and validating a list of interfaces to rename
fix_name_components = filter(
lambda i: str(i.id) in request.POST.getlist("fix_name"), interfaces
)
unified_interface_templates = [
InterfaceComparison(i.id, i.name, i.label, i.description, i.type, i.get_type_display(), i.mgmt_only, is_template=True) for i in interface_templates]
unified_interfaces = []
for component in fix_name_components:
unified_interfaces.append((component, InterfaceComparison(
component.id,
component.name,
component.label,
component.description,
component.type,
component.get_type_display(),
component.mgmt_only)))
return post_components(request, device, interfaces, interface_templates, Interface, InterfaceTemplate, unified_interfaces, unified_interface_templates)
class PowerPortComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View): class PowerPortComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View):
"""Comparison of interfaces between a device and a device type and beautiful visualization""" """Comparison of interfaces between a device and a device type and beautiful visualization"""
@ -66,7 +86,28 @@ class PowerPortComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View)
powerports = device.powerports.all() powerports = device.powerports.all()
powerports_templates = PowerPortTemplate.objects.filter(device_type=device.device_type) powerports_templates = PowerPortTemplate.objects.filter(device_type=device.device_type)
return post_components(request, device, powerports, powerports_templates, PowerPort, PowerPortTemplate) # Getting and validating a list of interfaces to rename
fix_name_components = filter(
lambda i: str(i.id) in request.POST.getlist("fix_name"), powerports
)
unified_powerport_templates = [
PowerPortComparison(i.id, i.name, i.label, i.description, i.type, i.get_type_display(), i.maximum_draw, i.allocated_draw, is_template=True) for i in powerports_templates]
unified_powerports = []
for component in fix_name_components:
unified_powerports.append((component, PowerPortComparison(
component.id,
component.name,
component.label,
component.description,
component.type,
component.get_type_display(),
component.maximum_draw,
component.allocated_draw)))
return post_components(request, device, powerports, powerports_templates, PowerPort, PowerPortTemplate, unified_powerports, unified_powerport_templates)
class ConsolePortComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View): class ConsolePortComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View):
"""Comparison of interfaces between a device and a device type and beautiful visualization""" """Comparison of interfaces between a device and a device type and beautiful visualization"""
@ -92,7 +133,26 @@ class ConsolePortComparisonView(LoginRequiredMixin, PermissionRequiredMixin, Vie
consoleports = device.consoleports.all() consoleports = device.consoleports.all()
consoleports_templates = ConsolePortTemplate.objects.filter(device_type=device.device_type) consoleports_templates = ConsolePortTemplate.objects.filter(device_type=device.device_type)
return post_components(request, device, consoleports, consoleports_templates, ConsolePort, ConsolePortTemplate) # Getting and validating a list of interfaces to rename
fix_name_components = filter(
lambda i: str(i.id) in request.POST.getlist("fix_name"), consoleports
)
unified_consoleport_templates = [
ConsolePortComparison(i.id, i.name, i.label, i.description, i.type, i.get_type_display(), is_template=True) for i in consoleports_templates]
unified_consoleports = []
for component in fix_name_components:
unified_consoleports.append((component, ConsolePortComparison(
component.id,
component.name,
component.label,
component.description,
component.type,
component.get_type_display())))
return post_components(request, device, consoleports, consoleports_templates, ConsolePort, ConsolePortTemplate, unified_consoleports, unified_consoleport_templates)
class ConsoleServerPortComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View): class ConsoleServerPortComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View):
"""Comparison of interfaces between a device and a device type and beautiful visualization""" """Comparison of interfaces between a device and a device type and beautiful visualization"""
@ -118,7 +178,26 @@ class ConsoleServerPortComparisonView(LoginRequiredMixin, PermissionRequiredMixi
consoleserverports = device.consoleserverports.all() consoleserverports = device.consoleserverports.all()
consoleserverports_templates = ConsoleServerPortTemplate.objects.filter(device_type=device.device_type) consoleserverports_templates = ConsoleServerPortTemplate.objects.filter(device_type=device.device_type)
return post_components(request, device, consoleserverports, consoleserverports_templates, ConsoleServerPort, ConsoleServerPortTemplate) # Getting and validating a list of interfaces to rename
fix_name_components = filter(
lambda i: str(i.id) in request.POST.getlist("fix_name"), consoleserverports
)
unified_consoleserverport_templates = [
ConsoleServerPortComparison(i.id, i.name, i.label, i.description, i.type, i.get_type_display(), is_template=True) for i in consoleserverports_templates]
unified_consoleserverports = []
for component in fix_name_components:
unified_consoleserverports.append((component, ConsoleServerPortComparison(
component.id,
component.name,
component.label,
component.description,
component.type,
component.get_type_display())))
return post_components(request, device, consoleserverports, consoleserverports_templates, ConsoleServerPort, ConsoleServerPortTemplate, unified_consoleserverports, unified_consoleserverport_templates)
class PowerOutletComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View): class PowerOutletComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View):
"""Comparison of interfaces between a device and a device type and beautiful visualization""" """Comparison of interfaces between a device and a device type and beautiful visualization"""
@ -322,4 +401,22 @@ class DeviceBayComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View)
devicebays = device.devicebays.all() devicebays = device.devicebays.all()
devicebays_templates = DeviceBayTemplate.objects.filter(device_type=device.device_type) devicebays_templates = DeviceBayTemplate.objects.filter(device_type=device.device_type)
return post_components(request, device, devicebays, devicebays_templates, DeviceBay, DeviceBayTemplate) # Getting and validating a list of devicebays to rename
fix_name_components = filter(
lambda i: str(i.id) in request.POST.getlist("fix_name"), devicebays
)
unified_devicebay_templates = [
DeviceBayComparison(i.id, i.name, i.label, i.description, is_template=True) for i in devicebays_templates]
unified_devicebays = []
for component in fix_name_components:
unified_devicebays.append((component, DeviceBayComparison(
component.id,
component.name,
component.label,
component.description
)))
return post_components(request, device, devicebays, devicebays_templates, DeviceBay, DeviceBayTemplate, unified_devicebays, unified_devicebay_templates)