diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f2a98b..c1e78a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ CHANGELOG.md +2026/03/11 +Fix SSH reconnection and improve interface description parsing in CiscoMacTableParser + 2026/02/09 Refactor Cisco MAC Monitor: Implement HTTPS service and restructure code diff --git a/src/cisco_mac_monitor.py b/src/cisco_mac_monitor.py index 7d08bfb..ef6cabb 100755 --- a/src/cisco_mac_monitor.py +++ b/src/cisco_mac_monitor.py @@ -260,17 +260,18 @@ class CiscoMacTableParser: def _get_interface_descriptions(self, ssh_connector: CiscoSSHConnector): """Obtiene las descripciones de las interfaces""" try: + # Reconectar la sesión SSH para evitar errores de sesión inactiva + ssh_connector.disconnect() + if not ssh_connector.connect(): + self.logger.warning("No se pudo reconectar para obtener descripciones de interfaces") + return command = "show interface description" output = ssh_connector.execute_command(command) - # Si el comando no es válido, intentar alternativa if "Invalid input" in output or not output.strip(): - # Intentar obtener descripciones una por una (más lento pero funciona en IOS antiguos) self.logger.debug("show interface description no disponible, usando método alternativo") return - self._parse_interface_descriptions(output) - except Exception as e: self.logger.warning(f"Error obteniendo descripciones de interfaces: {str(e)}") @@ -281,22 +282,25 @@ class CiscoMacTableParser: line_stripped = line.strip() if not line_stripped or line_stripped.startswith('-') or 'Interface' in line_stripped: continue - - # Format: Interface Status Protocol Description - # Fa0/1 up up User Port - # Usamos split con máximo 3 splits para preservar la descripción completa - parts = line.split(None, 3) # Split en whitespace, máximo 4 partes - - if len(parts) >= 1: - interface = parts[0] - description = "" - - if len(parts) >= 4: - description = parts[3].strip() - - # Si esta interfaz ya existe en nuestro diccionario, actualizar descripción + # El formato Cisco es: Interface Status Protocol Description (Description puede tener espacios o estar vacía) + match = re.match(r'^(\S+)\s+(\S+)\s+(\S+)\s*(.*)$', line_stripped) + if match: + interface = match.group(1) + status_raw = match.group(2) + protocol_raw = match.group(3) + description = match.group(4).strip() if match.group(4) else "" + # Normalizar status (up/down/disabled/unknown) + status = self._normalize_status(status_raw) + # Actualizar o crear la interfaz en el diccionario if interface in self.interface_info: + self.interface_info[interface].status = status self.interface_info[interface].description = description + else: + self.interface_info[interface] = InterfaceInfo( + name=interface, + status=status, + description=description + ) def _normalize_status(self, status_raw: str) -> str: """Normaliza el estado de la interfaz a up/down/disabled/unknown"""