def _display_device_inventory_web_page() -> str: """ Display device inventory on the web page """ # Time process execution start_time = time.monotonic() netcat.LOGGER.debug("Creating device inventory list") # Create list of all devices for latest command snapshot device_name_list = list( next( iter( db.get_command_status_list(search_depth=1, field_list=["device_info_dict"])), {}).get("device_info_dict", {})) # type: ignore # Randomize list so we have even spread of device types per batch from random import shuffle shuffle(device_name_list) # Start child processes to perform search operation for each batch inventory_list = sorted(netcat.execute_data_processing_function( netcat.split_list(device_name_list, MAX_WORKERS), create_inventory_list), key=lambda _: _.get("device_name")) # Time process execution end_time = time.monotonic() if netcat.SINGLE_PROCESS_MODE: generated_info = ( f"Witchcraft performed by {socket.gethostname()} on {datetime.datetime.now().strftime('%Y-%m-%d at %H:%M:%S EDT')} " + f"in {end_time - start_time:.2f}s by casting single spell for {len(device_name_list)} " + f"devices. NetCAT {netcat.VERSION} ({netcat.DB_TYPE}) - {netcat.YEAR}, Sebastian Majewski" ) else: generated_info = ( f"Witchcraft performed by {socket.gethostname()} on {datetime.datetime.now().strftime('%Y-%m-%d at %H:%M:%S EDT')} " + f"in {end_time - start_time:.2f}s by casting {MAX_WORKERS} concurrent spells for {len(device_name_list)} " + f"devices. NetCAT {netcat.VERSION} ({netcat.DB_TYPE}) - {netcat.YEAR}, Sebastian Majewski" ) netcat.LOGGER.info( f"Created device inventory list for {len(inventory_list)} devices in {end_time - start_time :.2f}s" ) return flask.render_template("inventory_results.html", inventory_list=inventory_list, generated_info=generated_info)
def lookup_mac_address(mac_address: str, search_depth: int, physical_ports_only: bool) -> str: """ Main search function """ # Time process execution start_time = time.monotonic() timestamp_list = [_.get("snapshot_timestamp") for _ in db.get_command_status_list(search_depth) if type(_) is dict] netcat.LOGGER.debug(f"Starting search for '{mac_address}' using {len(timestamp_list)} search processes") # Start child processes to perform search operation findings = sorted(netcat.execute_data_processing_function(timestamp_list, find_mac_address_in_snapshot, mac_address, physical_ports_only, max_workers=MAX_WORKERS), key=lambda _: _.get("snapshot_timestamp"), reverse=True) # Add UUIDs to be used as HTML IDs for JavaScript from uuid import uuid1 for finding in findings: finding["uuid"] = uuid1() # Time process execution end_time = time.monotonic() netcat.LOGGER.info(f"Finished search for '{mac_address}' in {end_time - start_time:.2f}s, number of findings: {len(findings)}") if netcat.SINGLE_PROCESS_MODE: generated_info = ( f"Witchcraft performed by {socket.gethostname()} on {datetime.datetime.now().strftime('%Y-%m-%d at %H:%M:%S EDT')} " + f"in {end_time - start_time:.2f}s by casting single spell. " + f"NetCAT {netcat.VERSION} ({netcat.DB_TYPE}) - {netcat.YEAR}, Sebastian Majewski" ) else: generated_info = ( f"Witchcraft performed by {socket.gethostname()} on {datetime.datetime.now().strftime('%Y-%m-%d at %H:%M:%S EDT')} " + f"in {end_time - start_time:.2f}s by casting {MAX_WORKERS} concurrent spells. " + f"NetCAT {netcat.VERSION} ({netcat.DB_TYPE}) - {netcat.YEAR}, Sebastian Majewski" ) return flask.render_template( "maclookup_results.html", mac_address=netcat.standardize_mac_address(mac_address), findings=findings, snapshot_number=len(timestamp_list), generated_info=generated_info, )
def find_inaccessible_devices( latest_command_status: Dict[str, Any]) -> List[Dict[str, Any]]: """ Search for devices that have missing latest device_info structures """ # Time process execution start_time = time.monotonic() # Create failed device name list from latest snapshot failed_device_list = [ (_[0], _[1].get("device_type")) for _ in latest_command_status.get("device_info_dict", {}).items() if _[1].get("failed") ] # Start child processes to perform search operation for each batch device_data_list = sorted(netcat.execute_data_processing_function( netcat.split_list(failed_device_list, MAX_WORKERS), get_failed_device_data_list), key=lambda _: _.get("device_name")) inaccessible_devices = sorted(device_data_list, key=lambda _: _.get("device_name")) # Add UUIDs to be used as HTML IDs for JavaScript for device in inaccessible_devices: device["uuid"] = uuid.uuid1() # Remove all the BS switches inaccessible_devices = [ _ for _ in inaccessible_devices if not re.match(r"^\S+bs\d+$", _.get("device_name")) ] # Time process execution end_time = time.monotonic() netcat.LOGGER.debug( f"Assembled inaccessible device list for {len(device_data_list)} devices in {end_time - start_time:.2f}s" ) return inaccessible_devices
def find_broken_links( latest_command_status: Dict[str, Any]) -> List[Dict[str, Any]]: """ Search for broken links in list of device_data structures """ # Time process execution start_time = time.monotonic() device_data_list = db.get_device_data_list__a( latest_command_status.get("snapshot_timestamp", ""), ["paloalto", "cisco_router"], command_list=[ "show ip interface brief", "show interface all", "show high-availability all" ]) # Filter out routers that have single link device_data_list = [ _ for _ in device_data_list if _.get("device_name")[-3:] not in {"ts1", "ts2"} ] # Start child processes to perform search operation for each device broken_links = sorted(netcat.execute_data_processing_function( device_data_list, find_broken_links_per_device, max_workers=MAX_WORKERS), key=lambda _: _.get("device_name")) # Time process execution end_time = time.monotonic() netcat.LOGGER.debug( f"Assembled broken links list for {len(broken_links)} links in {end_time - start_time:.2f}s" ) return broken_links
sys.exit() # If required confirm validity of snippet and device list with user, quit program if not confirmed if not arguments.non_interactive: if not confirm_deployment_validity(snippet, requested_device_name_list): sys.exit() # Run CLI processes netcat.LOGGER.info(f"Executing backup for {len(requested_device_name_list)} device(s): {', '.join(requested_device_name_list)}") # Time deployment execution start_time = time.time() # Execute separate process per device or continue as the same process if SINGLE_PROCESS_MODE flag is set successful_device_name_list = sorted( netcat.execute_data_processing_function([_ for _ in device_info_list if _["device_name"] in requested_device_name_list], cli_process, snippet, site_id_check, inet_gw_check, arguments.no_commit) ) # Create failed device info list failed_device_name_list = sorted(set(requested_device_name_list) - set(successful_device_name_list)) # Time backup execution end_time = time.time() netcat.LOGGER.info(f"Deployment ended, execution time: '{end_time - start_time:.2f}s'") # Report processe's finish status netcat.report_final_status(requested_device_name_list, successful_device_name_list, failed_device_name_list) return 0
arguments))): netcat.LOGGER.error(f"No valid device names requested, exiting...") sys.exit() # Run CLI processes netcat.LOGGER.info( f"Executing upgrade for {len(requested_device_name_list)} device(s): {', '.join(requested_device_name_list)}" ) # Time backup execution start_time = time.time() # Execute separate process per device or continue as the same process if SINGLE_PROCESS_MODE flag is set successful_device_name_list = sorted( netcat.execute_data_processing_function([ _ for _ in device_info_list if _["device_name"] in requested_device_name_list ], cli_process, timestamp, arguments.upgrade)) # Create failed device info list failed_device_name_list = sorted( set(requested_device_name_list) - set(successful_device_name_list)) # Time backup execution end_time = time.time() netcat.LOGGER.info( f"Upgrade ended, execution time: '{end_time - start_time:.2f}s'") # Report processe's finish status netcat.report_final_status(requested_device_name_list, successful_device_name_list,