2
0
Эх сурвалжийг харах

Fixes #7300: Fix incorrect Device LLDP interface row coloring & improve related JS

thatmattlove 4 жил өмнө
parent
commit
84c14aadc7

+ 1 - 0
docs/release-notes/version-3.0.md

@@ -4,6 +4,7 @@
 
 ### Bug Fixes
 
+* [#7300](https://github.com/netbox-community/netbox/issues/7300) - Fix incorrect Device LLDP interface row coloring
 * [#7495](https://github.com/netbox-community/netbox/issues/7495) - Fix navigation UI issue that caused improper element overlap
 * [#7529](https://github.com/netbox-community/netbox/issues/7529) - Restore horizontal scrolling for tables in narrow viewports
 * [#7534](https://github.com/netbox-community/netbox/issues/7534) - Avoid exception when utilizing "create and add another" twice in succession

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
netbox/project-static/dist/lldp.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
netbox/project-static/dist/lldp.js.map


+ 73 - 25
netbox/project-static/src/device/lldp.ts

@@ -1,6 +1,17 @@
 import { createToast } from '../bs';
 import { getNetboxData, apiGetBase, hasError, isTruthy, toggleLoader } from '../util';
 
+// Match an interface name that begins with a capital letter and is followed by at least one other
+// alphabetic character, and ends with a forward-slash-separated numeric sequence such as 0/1/2.
+const CISCO_IOS_PATTERN = new RegExp(/^([A-Z][A-Za-z]+)[^0-9]*([0-9/]+)$/);
+
+// Mapping of overrides to default Cisco IOS interface alias behavior (default behavior is to use
+// the first two characters).
+const CISCO_IOS_OVERRIDES = new Map<string, string>([
+  // Cisco IOS abbreviates 25G (TwentyFiveGigE) interfaces as 'Twe'.
+  ['TwentyFiveGigE', 'Twe'],
+]);
+
 /**
  * Get an attribute from a row's cell.
  *
@@ -12,6 +23,40 @@ function getData(row: HTMLTableRowElement, query: string, attr: string): string
   return row.querySelector(query)?.getAttribute(attr) ?? null;
 }
 
+/**
+ * Get preconfigured alias for given interface. Primarily for matching long-form Cisco IOS
+ * interface names with short-form Cisco IOS interface names. For example, `GigabitEthernet0/1/2`
+ * would become `Gi0/1/2`.
+ *
+ * This should probably be replaced with something in the primary application (Django), such as
+ * a database field attached to given interface types. However, this is a temporary measure to
+ * replace the functionality of this one-liner:
+ *
+ * @see https://github.com/netbox-community/netbox/blob/9cc4992fad2fe04ef0211d998c517414e8871d8c/netbox/templates/dcim/device/lldp_neighbors.html#L69
+ *
+ * @param name Long-form/original interface name.
+ */
+function getInterfaceAlias(name: string | null): string | null {
+  if (name === null) {
+    return name;
+  }
+  if (name.match(CISCO_IOS_PATTERN)) {
+    // Extract the base name and numeric portions of the interface. For example, an input interface
+    // of `GigabitEthernet0/0/1` would result in an array of `['GigabitEthernet', '0/0/1']`.
+    const [base, numeric] = (name.match(CISCO_IOS_PATTERN) ?? []).slice(1, 3);
+
+    if (isTruthy(base) && isTruthy(numeric)) {
+      // Check the override map and use its value if the base name is present in the map.
+      // Otherwise, use the first two characters of the base name. For example,
+      // `GigabitEthernet0/0/1` would become `Gi0/0/1`, but `TwentyFiveGigE0/0/1` would become
+      // `Twe0/0/1`.
+      const aliasBase = CISCO_IOS_OVERRIDES.get(base) || base.slice(0, 2);
+      return `${aliasBase}${numeric}`;
+    }
+  }
+  return name;
+}
+
 /**
  * Update row styles based on LLDP neighbor data.
  */
@@ -23,38 +68,41 @@ function updateRowStyle(data: LLDPNeighborDetail) {
 
     if (row !== null) {
       for (const neighbor of neighbors) {
-        const cellDevice = row.querySelector<HTMLTableCellElement>('td.device');
-        const cellInterface = row.querySelector<HTMLTableCellElement>('td.interface');
-        const cDevice = getData(row, 'td.configured_device', 'data');
-        const cChassis = getData(row, 'td.configured_chassis', 'data-chassis');
-        const cInterface = getData(row, 'td.configured_interface', 'data');
-
-        let cInterfaceShort = null;
-        if (isTruthy(cInterface)) {
-          cInterfaceShort = cInterface.replace(/^([A-Z][a-z])[^0-9]*([0-9/]+)$/, '$1$2');
-        }
+        const deviceCell = row.querySelector<HTMLTableCellElement>('td.device');
+        const interfaceCell = row.querySelector<HTMLTableCellElement>('td.interface');
+        const configuredDevice = getData(row, 'td.configured_device', 'data');
+        const configuredChassis = getData(row, 'td.configured_chassis', 'data-chassis');
+        const configuredIface = getData(row, 'td.configured_interface', 'data');
+
+        const interfaceAlias = getInterfaceAlias(configuredIface);
 
-        const nHost = neighbor.remote_system_name ?? '';
-        const nPort = neighbor.remote_port ?? '';
-        const [nDevice] = nHost.split('.');
-        const [nInterface] = nPort.split('.');
+        const remoteName = neighbor.remote_system_name ?? '';
+        const remotePort = neighbor.remote_port ?? '';
+        const [neighborDevice] = remoteName.split('.');
+        const [neighborIface] = remotePort.split('.');
 
-        if (cellDevice !== null) {
-          cellDevice.innerText = nDevice;
+        if (deviceCell !== null) {
+          deviceCell.innerText = neighborDevice;
         }
 
-        if (cellInterface !== null) {
-          cellInterface.innerText = nInterface;
+        if (interfaceCell !== null) {
+          interfaceCell.innerText = neighborIface;
         }
 
-        if (!isTruthy(cDevice) && isTruthy(nDevice)) {
+        // Interface has an LLDP neighbor, but the neighbor is not configured in NetBox.
+        const nonConfiguredDevice = !isTruthy(configuredDevice) && isTruthy(neighborDevice);
+
+        // NetBox device or chassis matches LLDP neighbor.
+        const validNode =
+          configuredDevice === neighborDevice || configuredChassis === neighborDevice;
+
+        // NetBox configured interface matches LLDP neighbor interface.
+        const validInterface =
+          configuredIface === neighborIface || interfaceAlias === neighborIface;
+
+        if (nonConfiguredDevice) {
           row.classList.add('info');
-        } else if (
-          (cDevice === nDevice || cChassis === nDevice) &&
-          cInterfaceShort === nInterface
-        ) {
-          row.classList.add('success');
-        } else if (cDevice === nDevice || cChassis === nDevice) {
+        } else if (validNode && validInterface) {
           row.classList.add('success');
         } else {
           row.classList.add('danger');

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно