diff --git a/netbox_interface_sync/comparison.py b/netbox_interface_sync/comparison.py index ec0ce61..af12877 100644 --- a/netbox_interface_sync/comparison.py +++ b/netbox_interface_sync/comparison.py @@ -20,6 +20,9 @@ class ParentComparison: def __hash__(self): return hash(self.name.lower().replace(" ", "")) + def __str__(self): + return f"Label: {self.label}\nDescription: {self.description}" + @dataclass(frozen=True) class ParentTypedComparison(ParentComparison): @@ -41,6 +44,9 @@ class ParentTypedComparison(ParentComparison): # Ignore some fields when hashing; ignore interface name case and whitespaces return hash((self.name.lower().replace(" ", ""), self.type)) + def __str__(self): + return f"{super().__str__()}\nType: {self.type_display}" + @dataclass(frozen=True) class InterfaceComparison(ParentTypedComparison): @@ -63,6 +69,9 @@ class InterfaceComparison(ParentTypedComparison): # Ignore some fields when hashing; ignore interface name case and whitespaces return hash((self.name.lower().replace(" ", ""), self.type)) + def __str__(self): + return f"{super().__str__()}\nManagement only: {self.mgmt_only}" + @dataclass(frozen=True) class FrontPortComparison(ParentTypedComparison): @@ -88,6 +97,9 @@ class FrontPortComparison(ParentTypedComparison): # Ignore some fields when hashing; ignore interface name case and whitespaces return hash((self.name.lower().replace(" ", ""), self.type)) + def __str__(self): + return f"{super().__str__()}\nColor: {self.color}\nPosition: {self.rear_port_position}" + @dataclass(frozen=True) class RearPortComparison(ParentTypedComparison): @@ -112,6 +124,9 @@ class RearPortComparison(ParentTypedComparison): # Ignore some fields when hashing; ignore interface name case and whitespaces return hash((self.name.lower().replace(" ", ""), self.type)) + def __str__(self): + return f"{super().__str__()}\nColor: {self.color}\nPositions: {self.positions}" + @dataclass(frozen=True, eq=False) class ConsolePortComparison(ParentTypedComparison): @@ -150,6 +165,9 @@ class PowerPortComparison(ParentTypedComparison): # Ignore some fields when hashing; ignore interface name case and whitespaces return hash((self.name.lower().replace(" ", ""), self.type)) + def __str__(self): + return f"{super().__str__()}\nMaximum draw: {self.maximum_draw}\nAllocated draw: {self.allocated_draw}" + @dataclass(frozen=True) class PowerOutletComparison(ParentTypedComparison): @@ -176,6 +194,9 @@ class PowerOutletComparison(ParentTypedComparison): (self.name.lower().replace(" ", ""), self.type, self.power_port_name) ) + def __str__(self): + return f"{super().__str__()}\nPower port name: {self.power_port_name}\nFeed leg: {self.feed_leg}" + @dataclass(frozen=True, eq=False) class DeviceBayComparison(ParentComparison): diff --git a/netbox_interface_sync/template_content.py b/netbox_interface_sync/template_content.py index be5c5a4..8bda0d7 100644 --- a/netbox_interface_sync/template_content.py +++ b/netbox_interface_sync/template_content.py @@ -8,7 +8,7 @@ class DeviceViewExtension(PluginTemplateExtension): def buttons(self): """Implements a compare interfaces button at the top of the page""" obj = self.context['object'] - return self.render("netbox_interface_sync/compare_interfaces_button.html", extra_context={ + return self.render("netbox_interface_sync/compare_components_button.html", extra_context={ "device": obj }) diff --git a/netbox_interface_sync/templates/netbox_interface_sync/compare_interfaces_button.html b/netbox_interface_sync/templates/netbox_interface_sync/compare_components_button.html similarity index 100% rename from netbox_interface_sync/templates/netbox_interface_sync/compare_interfaces_button.html rename to netbox_interface_sync/templates/netbox_interface_sync/compare_components_button.html diff --git a/netbox_interface_sync/templates/netbox_interface_sync/components_comparison.html b/netbox_interface_sync/templates/netbox_interface_sync/components_comparison.html new file mode 100644 index 0000000..f7668ae --- /dev/null +++ b/netbox_interface_sync/templates/netbox_interface_sync/components_comparison.html @@ -0,0 +1,159 @@ +{% extends 'base/layout.html' %} + +{% block title %}{{ device }} - {{ component_type }} comparison{% endblock %} +{% block header %} + + {{ block.super }} +{% endblock %} + +{% block content %} + + + +
+ + {% csrf_token %} +
+ + {% if templates_count == components_count %} + + {% else %} + + {% endif %} + + + + + + + + + + + + + + + + + + + {% for component_template, component in comparison_items %} + + {% if component_template %} + + + + {% else %} + + + + {% endif %} + + {% if component %} + + + + + {% else %} + + + + + {% endif %} + + {% endfor %} + +
+ The device and device type have the same number of {{ component_type }}. + + The device and device type have different number of {{ component_type|lower }}.
+ Device: {{ components_count }}
+ Device type: {{ templates_count }} +
Device typeActionsDeviceActions
NameAttributes + + NameAttributes + + + +
+ {% if component and component_template.name != component.name %} + {{ component_template.name }} + {% else %} + {{ component_template.name }} + {% endif %} + {{ component_template }} + {% if not component %} + + {% endif %} +     + {% if component_template and component_template.name != component.name %} + {{ component.name }} + {% else %} + {{ component.name }} + {% endif %} + {{ component }} + {% if not component_template %} + + {% endif %} + + {% if component_template and component_template.name != component.name %} + + {% endif %} +     
+
+
+ +
+
+ +{% endblock %} diff --git a/netbox_interface_sync/templates/netbox_interface_sync/interface_comparison.html b/netbox_interface_sync/templates/netbox_interface_sync/interface_comparison.html deleted file mode 100644 index 4befb9d..0000000 --- a/netbox_interface_sync/templates/netbox_interface_sync/interface_comparison.html +++ /dev/null @@ -1,161 +0,0 @@ -{% extends 'base/layout.html' %} - -{% block title %}{{ device }} - Interface comparison{% endblock %} -{% block header %} - - {{ block.super }} -{% endblock %} - -{% block content %} - - - -

-{% if templates_count == interfaces_count %} - The device and device type have the same number of interfaces. -{% else %} - The device and device type have different number of interfaces.
- Device: {{ interfaces_count }}
- Device type: {{ templates_count }} -{% endif %} -

- -
- - {% csrf_token %} - - - - - - - - - - - {% for template, interface in comparison_items %} - {% if template %} - - - - - - {% else %} - - - - - - {% endif %} - {% endfor %} -
Device typeActions
NameType - -
- {% if interface and template.name != interface.name %} - {{ template.name }} - {% else %} - {{ template.name }} - {% endif %} - {{ template.type_display }} - {% if not interface %} - - {% endif %} -
   
- - - - - - - - - - - - - - {% for template, interface in comparison_items %} - {% if interface %} - - - - - - - {% else %} - - - - - - - {% endif %} - {% endfor %} -
DeviceActions
NameType - - - -
- {% if template and template.name != interface.name %} - {{ interface.name }} - {% else %} - {{ interface.name }} - {% endif %} - {{ interface.type_display }} - {% if not template %} - - {% endif %} - - {% if template and template.name != interface.name %} - - {% endif %} -
    
-
- -
-
- -{% endblock %} diff --git a/netbox_interface_sync/utils.py b/netbox_interface_sync/utils.py index 0d4186e..739a40c 100644 --- a/netbox_interface_sync/utils.py +++ b/netbox_interface_sync/utils.py @@ -19,13 +19,13 @@ def human_sorted(iterable: Iterable): return sorted(iterable, key=natural_keys) -def get_components(request, device, components, unified_components, unified_component_templates): - # List of interfaces and interface templates presented in the unified format +def get_components(request, device, components, unified_components, unified_component_templates, component_type): + # List of components and components 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)) comparison_templates = [] - comparison_interfaces = [] + comparison_components = [] for i in overall_powers: try: comparison_templates.append( @@ -35,20 +35,21 @@ def get_components(request, device, components, unified_components, unified_comp comparison_templates.append(None) try: - comparison_interfaces.append( + comparison_components.append( unified_components[unified_components.index(i)] ) except ValueError: - comparison_interfaces.append(None) + comparison_components.append(None) - comparison_items = list(zip(comparison_templates, comparison_interfaces)) + comparison_items = list(zip(comparison_templates, comparison_components)) return render( request, - "netbox_interface_sync/interface_comparison.html", + "netbox_interface_sync/components_comparison.html", { + "component_type": component_type, "comparison_items": comparison_items, "templates_count": len(unified_component_templates), - "interfaces_count": len(components), + "components_count": len(components), "device": device, }, ) diff --git a/netbox_interface_sync/views.py b/netbox_interface_sync/views.py index 6c0b03a..f2256e6 100644 --- a/netbox_interface_sync/views.py +++ b/netbox_interface_sync/views.py @@ -29,7 +29,7 @@ class InterfaceComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View) 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] - return get_components(request, device, interfaces, unified_interfaces, unified_interface_templates) + return get_components(request, device, interfaces, unified_interfaces, unified_interface_templates, "Interfaces") def post(self, request, device_id): form = InterfaceComparisonForm(request.POST) @@ -76,7 +76,7 @@ class PowerPortComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View) 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] - return get_components(request, device, powerports, unified_powerports, unified_powerport_templates) + return get_components(request, device, powerports, unified_powerports, unified_powerport_templates, "Power ports") def post(self, request, device_id): form = InterfaceComparisonForm(request.POST) @@ -123,7 +123,7 @@ class ConsolePortComparisonView(LoginRequiredMixin, PermissionRequiredMixin, Vie 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] - return get_components(request, device, consoleports, unified_consoleports, unified_consoleport_templates) + return get_components(request, device, consoleports, unified_consoleports, unified_consoleport_templates, "Console ports") def post(self, request, device_id): form = InterfaceComparisonForm(request.POST) @@ -168,7 +168,7 @@ class ConsoleServerPortComparisonView(LoginRequiredMixin, PermissionRequiredMixi 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] - return get_components(request, device, consoleserverports, unified_consoleserverports, unified_consoleserverport_templates) + return get_components(request, device, consoleserverports, unified_consoleserverports, unified_consoleserverport_templates, "Console server ports") def post(self, request, device_id): form = InterfaceComparisonForm(request.POST) @@ -213,7 +213,7 @@ class PowerOutletComparisonView(LoginRequiredMixin, PermissionRequiredMixin, Vie unified_poweroutlet_templates = [ PowerOutletComparison(i.id, i.name, i.label, i.description, i.type, i.get_type_display(), power_port_name=PowerPortTemplate.objects.get(id=i.power_port_id).name if i.power_port_id is not None else "", feed_leg=i.feed_leg, is_template=True) for i in poweroutlets_templates] - return get_components(request, device, poweroutlets, unified_poweroutlets, unified_poweroutlet_templates) + return get_components(request, device, poweroutlets, unified_poweroutlets, unified_poweroutlet_templates, "Power outlets") def post(self, request, device_id): form = InterfaceComparisonForm(request.POST) @@ -347,7 +347,7 @@ class FrontPortComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View) unified_frontports_templates = [ FrontPortComparison(i.id, i.name, i.label, i.description, i.type, i.get_type_display(), i.color, i.rear_port_position, is_template=True) for i in frontports_templates] - return get_components(request, device, frontports, unified_frontports, unified_frontports_templates) + return get_components(request, device, frontports, unified_frontports, unified_frontports_templates, "Front ports") def post(self, request, device_id): form = InterfaceComparisonForm(request.POST) @@ -479,7 +479,7 @@ class RearPortComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View): unified_rearports_templates = [ RearPortComparison(i.id, i.name, i.label, i.description, i.type, i.get_type_display(), i.color, i.positions, is_template=True) for i in rearports_templates] - return get_components(request, device, rearports, unified_rearports, unified_rearports_templates) + return get_components(request, device, rearports, unified_rearports, unified_rearports_templates, "Rear ports") def post(self, request, device_id): form = InterfaceComparisonForm(request.POST) @@ -536,7 +536,7 @@ class DeviceBayComparisonView(LoginRequiredMixin, PermissionRequiredMixin, View) unified_devicebay_templates = [ DeviceBayComparison(i.id, i.name, i.label, i.description, is_template=True) for i in devicebays_templates] - return get_components(request, device, devicebays, unified_devicebays, unified_devicebay_templates) + return get_components(request, device, devicebays, unified_devicebays, unified_devicebay_templates, "Device bays") def post(self, request, device_id): form = InterfaceComparisonForm(request.POST)