from typing import Dict from ruamel.yaml import YAML import constants from constants import ( NORMALIZED_INTERFACES, INTERFACE_NAME_RE, NEIGHBOR_SPLIT_RE, CDP_NEIGHBOR_RE, HOSTS_FILE, DEVICE_USERNAME, DEVICE_PASSWORD, DEVICE_TYPE, CONNECTION_TIMEOUT, ) def normalize_interface_type(interface_type: str) -> str: """Normalizes interface type For example, G is converted to GigabitEthernet, Te is converted to TenGigabitEthernet """ int_type = interface_type.strip().lower() for norm_int_type in NORMALIZED_INTERFACES: if norm_int_type.lower().startswith(int_type): return norm_int_type return int_type def normalize_interface_name(interface_name: str) -> str: """Normalizes interface name For example, Gi0/1 is converted to GigabitEthernet1, Te1/1 is converted to TenGigabitEthernet1/1 """ match = INTERFACE_NAME_RE.search(interface_name) if match: int_type = match.group("interface_type") normalized_int_type = normalize_interface_type(int_type) int_num = match.group("interface_num") return normalized_int_type + int_num raise ValueError(f"Does not recognize {interface_name} as an interface name") def extract_hostname_from_fqdn(fqdn: str) -> str: """Extracts hostname from fqdn-like string For example, R1.cisco.com -> R1, sw1 -> sw1" """ return fqdn.split(".")[0] def parse_show_cdp_neighbors(cli_output: str) -> Dict[str, Dict[str, str]]: """Parses `show cdp neighbors` and returns a dictionary of neighbors and connected interfaces""" result: Dict[str, Dict[str, str]] = {} for neighbor_output in NEIGHBOR_SPLIT_RE.split(cli_output): match = CDP_NEIGHBOR_RE.search(neighbor_output) if match: remote_fqdn = match.group("remote_fqdn") local_interface = normalize_interface_name(match.group("local_interface")) remote_interface = normalize_interface_name(match.group("remote_interface")) remote_hostname = extract_hostname_from_fqdn(remote_fqdn) result[local_interface] = { "connected_device": { "name": remote_hostname, "port": remote_interface, } } return dict(sorted(result.items())) def get_devices_conn_params() -> Dict[str, Dict[str, str]]: """Creates a dictionary of connection parameters for SSH""" result: Dict[str, Dict[str, str]] = {} yaml = YAML() with open(HOSTS_FILE, 'r') as f: hosts = yaml.load(f) for device, device_details in hosts["devices"]["routers"].items(): device_params = { "host": device_details["host"], "username": DEVICE_USERNAME, "password": DEVICE_PASSWORD, "device_type": DEVICE_TYPE, "timeout": CONNECTION_TIMEOUT, "global_delay_factor": constants.NETMIKO_GLOBAL_DELAY_FACTOR, } result[device] = device_params return result