def find_mac_address_in_device_data(device_data: Dict[str, Any], mac_address: str, physical_ports_only: bool) -> List[Dict[str, Any]]: """ Find vlans and ports in switch mac table for spcified mac address """ findings = netcat.find_regex_ml(netcat.get_command_output(device_data, "show mac address-table"), rf"^\*?\s+(\d+)\s+{mac_address}\s+\S+\s+(?:\d+\s+\S+\s+\S+\s+)?(\S+) ?$", hint=mac_address) return [ { "mac_address": mac_address, "device_name": device_data.get("device_name"), "vlan": _, "port": __, "snapshot_timestamp": device_data.get("snapshot_timestamp"), } for _, __ in findings if re.search("Gi|Eth", __) or not physical_ports_only ]
def create_inventory_list(device_name_list: List[str]) -> List[Dict[str, Any]]: """ Create inventory list """ # Time process execution start_time = time.monotonic() # Setup logger to show process name if os.getpid() != netcat.MAIN_PROCESS_PID: netcat.bind_logger("SUB_PROC") inventory_list = [] for device_data in get_device_data_list(device_name_list): if device_data.get("device_type") == "cisco_switch": command_output = netcat.get_command_output(device_data, "show version") model_numbers = netcat.find_regex_ml(command_output, r"^Model number\s+: (\S+)$", hint="el n", optional=False) serial_numbers = netcat.find_regex_ml( command_output, r"^System serial number\s+: (\S+)$", hint="m s", optional=False) software_versions = netcat.find_regex_ml( command_output, r"^\*?\s+\d+\s+\d+\s+\S+\s+(\S+) .*$", hint=" W", optional=False) elif device_data.get("device_type") == "cisco_router": command_output = netcat.get_command_output(device_data, "show version") model_numbers = netcat.find_regex_ml( command_output, r"^[Cc]isco (\S+) .+ bytes of memory.$", hint="s of m", optional=False) serial_numbers = netcat.find_regex_ml( command_output, r"^Processor board ID (\S+)$", hint="d I", optional=False) software_versions = netcat.find_regex_ml( command_output, r"^Cisco IOS Software,? .+ Version ([^\s,]+), .+$", hint="o I", optional=False) elif device_data.get("device_type") == "cisco_nexus": command_output = netcat.get_command_output(device_data, "show version") model_numbers = netcat.find_regex_ml( command_output, r"^\s+cisco Nexus[^ ]* (\S+) .+$", hint="has", optional=False) serial_numbers = netcat.find_regex_ml( command_output, r"^\s+Processor Board ID (\S+)$", hint=" Pr", optional=False) software_versions = netcat.find_regex_ml( command_output, r"^\s+(?:system|NXOS):\s+version (\S+)$", hint="ver", optional=False) elif device_data.get("device_type") == "cisco_asa": command_output = netcat.get_command_output(device_data, "show version") model_numbers = netcat.find_regex_ml(command_output, r"^Hardware:\s+([^ ^,]+),.+$", hint="Har", optional=False) serial_numbers = netcat.find_regex_ml(command_output, r"^Serial Number: (\S+)$", hint="Ser", optional=False) software_versions = netcat.find_regex_ml( command_output, r"^Cisco .+ Software Version (\S+) .*$", hint="e S", optional=False) elif device_data.get("device_type") == "cisco_asa_mc": command_output = netcat.get_command_output(device_data, "show version") model_numbers = netcat.find_regex_ml(command_output, r"^Hardware:\s+([^ ^,]+),.+$", hint="Har", optional=False) serial_numbers = netcat.find_regex_ml(command_output, r"^Serial Number: (\S+)$", hint="Ser", optional=False) software_versions = netcat.find_regex_ml( command_output, r"^Cisco .+ Software Version (\S+) .*$", hint="e S", optional=False) elif device_data.get("device_type") == "paloalto": command_output = netcat.get_command_output(device_data, "show system info") model_numbers = netcat.find_regex_ml(command_output, r"^model: (\S+)$", hint="el:", optional=False) serial_numbers = netcat.find_regex_ml(command_output, r"^serial: (\S+)$", hint="ser", optional=False) software_versions = netcat.find_regex_ml(command_output, r"^sw-version: (\S+)$", hint="sw-", optional=False) elif device_data.get("device_type") == "f5": command_output = netcat.get_command_output(device_data, "show sys hardware") model_numbers = netcat.find_regex_ml(command_output, r"^ Name\s+(BIG-IP \S+).*$", hint="BIG", optional=False) serial_numbers = netcat.find_regex_ml( command_output, r"^\s+Host Board Serial\s+(\S+)$", hint=" Ho", optional=False) # Fix for vf2lb[12]mgmt that dont show serial numbers, can be removed after VF2 decom if serial_numbers == []: serial_numbers = ["UNKNOWN"] command_output = netcat.get_command_output(device_data, "show sys version") software_versions = netcat.find_regex_ml(command_output, r"^\s+Version\s+(\S+)$", hint=" V", optional=False) else: inventory_list.append( {"device_name": device_data.get("device_name")}) continue from uuid import uuid1 inventory_list.append({ "uuid": uuid1(), "snapshot_timestamp": device_data.get("snapshot_timestamp"), "device_name": device_data.get("device_name"), "device_type": device_data.get("device_type"), "chasis": [{ "model": _, "serial": __, "software": ___ } for _, __, ___ in zip(model_numbers, serial_numbers, software_versions)], }) # Time process execution end_time = time.monotonic() netcat.LOGGER.debug( f"Inventory data created for {len(device_name_list)} devices in {end_time - start_time:.2f}s" ) return inventory_list
def find_ip_address_in_device_data(device_data: Dict[str, Any], ip_address: str, use_arp: bool, use_dhcp: bool, use_dsnp: bool) -> List[Dict[str, Any]]: """ Find data line containing ip address in device data structure """ results: List[Tuple[Any, str, str]] = [] if device_data.get("device_type") == "cisco_switch": if use_dsnp: results += [ (_, "DSNP", f"[ l2_int: {___} ], [ vlan: {__} ]") for _, __, ___ in netcat.find_regex_ml( netcat.get_command_output(device_data, "show ip dhcp snooping binding"), rf"^(\S+)\s+{ip_address}\s+\d+\s+\S+\s+(\d+)\s+(\S+)\s*$", hint=ip_address) ] elif device_data.get("device_type") == "cisco_router": if use_arp: results += [( _, "ARP", f"[ l3_int: {__} ]" ) for _, __ in netcat.find_regex_ml( netcat.get_command_output(device_data, "show ip arp"), rf"^Internet\s+{ip_address}\s+\S+\s+(\S+)\s+ARPA\s+(\S+)\s*$", hint=ip_address)] if use_dhcp: results += [(_, "DHCP", f"") for _ in netcat.find_regex_ml( netcat.get_command_output(device_data, "show ip dhcp binding"), rf"^{ip_address}\s+(\S+)\s.+$", hint=ip_address)] elif device_data.get("device_type") == "paloalto": if use_arp: results += [ (__, "ARP", f"[ l3_int: {_} ]") for _, __ in netcat.find_regex_ml( netcat.get_command_output(device_data, "show arp all"), rf"^(\S+)\s+{ip_address}\s+(\S+)\s+\S+\s.*$", hint=ip_address) ] if use_dhcp: results += [ (_, "DHCP", f"[ name: {__} ]") for _, __ in netcat.find_regex_ml( netcat.get_command_output( device_data, "show dhcp server lease interface all"), rf"^{ip_address}\s+(\S+)\s+(\S+) .*$", hint=ip_address) ] else: netcat.LOGGER.warning( f"{netcat.fn()}: Unknown device data type value '{device_data.get('device_type')}'" ) return [] return [{ "snapshot_timestamp": device_data.get("snapshot_timestamp"), "mac_address": netcat.standardize_mac_address(_), "device_name": device_data.get("device_name"), "source": __, "other_info": ___, } for _, __, ___ in results]
break netcat.LOGGER.warning( f"Installation of version {requested_software_version} failed, will retry up to three times..." ) print("***", command_output, "***") else: raise netcat.CustomException( f"Failed three attempts to install version {requested_software_version}" ) # Wait till both of the firewalls have ha working properly and then reboot for _ in range(30): command_output = self.send_command("show high-availability all") ha_states = netcat.find_regex_ml(command_output, r"^\s+State:\s+(\S+).*$") if len(ha_states) < 2: raise netcat.CustomException( f"Cannot properly read firewalls HA state '{ha_states}'") if ha_states[0] in {"active", "passive" } and ha_states[1] in {"active", "passive"}: netcat.LOGGER.info( f"Firewalls HA states look okay: {ha_states}") break netcat.LOGGER.info( f"Firewalls HA states do not look okay yet: {ha_states}, waiting one more minute..." ) time.sleep(60)
def find_broken_links_per_device( device_data: Dict[str, Any]) -> List[Dict[str, Any]]: """ Search for any link that is down (but not admin down) on Cisco routers and Palo Alto firewalls """ # Time process execution start_time = time.monotonic() # Setup logger to show process name if os.getpid() != netcat.MAIN_PROCESS_PID: netcat.bind_logger("SUB_PROC") broken_links = [] if device_data.get("device_type") == "cisco_router": # Look for any broken link for interface_name, interface_ip_address in netcat.find_regex_ml( netcat.get_command_output(device_data, "show ip interface brief"), rf"^([^\s]*(?:Ethernet|Tunnel)\S+)\s+(\S+)\s+\S+\s+\S+\s+(?:up|down)\s+down\s*$" ): broken_link = { "uuid": uuid.uuid1(), "device_name": device_data.get("device_name"), "device_type": device_data.get("device_type"), "interface_name": interface_name, "interface_name_encoded": interface_name.replace("/", "_"), "interface_ip_address": interface_ip_address, } # Search for latest device_info structure that has broken link in UP state and record its timestamp device_data_list = db.get_device_data_list__c( device_data.get("device_name", ""), command_list=["show ip interface brief"]) for device_data in device_data_list: regex_interface_name = interface_name.replace("/", "\\/").replace( ".", "\.") if netcat.find_regex_sl( netcat.get_command_output(device_data, "show ip interface brief"), rf"(^[^\s]*{regex_interface_name}\s+\S+\s+\S+\s+\S+\s+up\s+up\s*$)", hint=interface_name, optional=False): broken_link["snapshot_timestamp"] = device_data.get( "snapshot_timestamp") break broken_links.append(broken_link) elif device_data.get("device_type") == "paloalto": # Skip device if its not in active ha state if netcat.find_regex_sl( netcat.get_command_output(device_data, "show high-availability all"), r"\s+State: (\S+) .*$") not in { "active", "active-primary", "active-secondary", "" }: return [] # Look for any broken link for interface_name, interface_mac_address in netcat.find_regex_ml( netcat.get_command_output(device_data, "show interface all"), r"^((?:ethernet|ae)\S+)\s+\d+\s+ukn\/ukn\/down\S+\s+(\S+)\s*$" ): broken_link = { "uuid": uuid.uuid1(), "device_name": device_data.get("device_name"), "device_type": device_data.get("device_type"), "interface_name": interface_name, "interface_name_encoded": interface_name.replace("/", "_"), "interface_ip_address": "N/A", "interface_mac_address": interface_mac_address, } # Search for latest device_info structure that has broken BGP session in UP state and record its timestamp device_data_list = db.get_device_data_list__c( device_data.get("device_name", ""), command_list=["show interface all"]) for device_data in device_data_list: regex_interface_name = interface_name.replace("/", "\\/").replace( ".", "\.") if netcat.find_regex_ml( netcat.get_command_output(device_data, "show interface all"), rf"(^{regex_interface_name}\s+\S+\s+\S+\/up\s+\S+\s*$)", hint=interface_name, optional=False): broken_link["snapshot_timestamp"] = device_data.get( "snapshot_timestamp") break broken_links.append(broken_link) else: netcat.LOGGER.warning( f"{netcat.fn()}: Unknown device data type value '{device_data.get('type')}'" ) # Time process execution end_time = time.monotonic() netcat.LOGGER.debug( f"Created broken links list of {len(broken_links)} links in {end_time - start_time:.2f}s" ) return broken_links
def find_broken_bgp_sessions_per_device( device_data: Dict[str, Any]) -> List[Dict[str, Any]]: """ Search for broken BGP sessions on Cisco routers and Palo Alto firewalls """ # Time process execution start_time = time.monotonic() # Setup logger to show process name if os.getpid() != netcat.MAIN_PROCESS_PID: netcat.bind_logger("SUB_PROC") broken_bgp_sessions = [] if device_data.get("device_type") == "cisco_router": # Look for any broken BGP sessions for bgp_session_peer_ip, bgp_session_peer_asn in netcat.find_regex_ml( netcat.get_command_output(device_data, "show ip bgp summary"), r"^(\S+)\s+\d\s+(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\S+\s+(?:Idle|Active)$" ): broken_bgp_session = { "uuid": uuid.uuid1(), "device_name": device_data.get("device_name"), "device_type": device_data.get("device_type"), "peer_ip": bgp_session_peer_ip, "peer_asn": bgp_session_peer_asn, } # Search for latest device_data document that has broken BGP session in UP state and record its timestamp device_data_list = db.get_device_data_list__c( device_data.get("device_name", ""), command_list=["show ip bgp summary"]) for device_data in device_data_list: if netcat.find_regex_ml( netcat.get_command_output(device_data, "show ip bgp summary"), rf"(^{bgp_session_peer_ip}\s+\d\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\S+\s+\d+$)", hint=bgp_session_peer_ip, optional=False): broken_bgp_session["snapshot_timestamp"] = device_data.get( "snapshot_timestamp") break broken_bgp_sessions.append(broken_bgp_session) elif device_data.get("device_type") == "paloalto": # Skip device if its not in active ha state if netcat.find_regex_sl( netcat.get_command_output(device_data, "show high-availability all"), r"\s+State: (\S+) .*$") not in { "active", "active-primary", "active-secondary", "" }: return [] # Look for any broken BGP sessions for bgp_session_peer_asn, bgp_session_peer_ip in netcat.find_regex_ml( netcat.get_command_output(device_data, "show routing protocol bgp summary"), r"^\s+peer \S+\s+ AS (\d+), (?:Connect|Active), IP (\S+)$"): broken_bgp_session = { "uuid": uuid.uuid1(), "device_name": device_data.get("device_name"), "device_type": device_data.get("device_type"), "peer_ip": bgp_session_peer_ip, "peer_asn": bgp_session_peer_asn, } # Search for latest device_data structure that has broken BGP session in UP state and record its timestamp device_data_list = db.get_device_data_list__c( device_data.get("device_name", ""), command_list=[ "show routing protocol bgp summary", "show high-availability all" ]) for device_data in device_data_list: if netcat.find_regex_sl( netcat.get_command_output( device_data, "show routing protocol bgp summary"), rf"(^\s+peer \S+\s+ AS \d+, Established, IP {bgp_session_peer_ip})$", hint=bgp_session_peer_ip, optional=False): broken_bgp_session["snapshot_timestamp"] = device_data.get( "snapshot_timestamp") break broken_bgp_sessions.append(broken_bgp_session) else: netcat.LOGGER.warning( f"{netcat.fn()}: Unknown device data type value '{device_data.get('type')}'" ) # Time process execution end_time = time.monotonic() netcat.LOGGER.debug( f"Created broken bgp session list of {len(broken_bgp_sessions)} sessions in {end_time - start_time:.2f}s" ) return broken_bgp_sessions