def connect(): """ Here we will user connArgs gathered from get_conn_args \n""" \ """ and establish connection to WLC \n""" global conn global connArgs global savedCredentials global connIsAlive attempts = 0 expPrompt = False while connIsAlive is False: try: connArgs = get_conn_args() conn = ConnectHandler(ip=connArgs["ip"], username=connArgs["user"], password=connArgs["pass"], device_type="cisco_ios", session_log="ssh_session_logfile.txt", session_log_file_mode="write", session_log_record_writes="True") except nm.NetMikoTimeoutException: print("-------------------------------------------\n" \ "Error: Timeout Error Occured Attempting to \n" \ "connect. Check IP/Hostname and try Again \n" \ "-------------------------------------------\n") except nm.NetMikoAuthenticationException: print("-------------------------------------------\n" \ "Error: Authentication Error Occured. \n" \ "Check Credentials and try Again \n" \ "-------------------------------------------\n") ## except: ## print("Unexpected error:", sys.exc_info()[0]) ## raise else: connIsAlive = conn.is_alive() if connIsAlive is True: print("Connection Successful!") getPrompt = conn.find_prompt() print("-------------------------------------------\n" \ "CONNECTED via SSH- \n" \ f"Device returned : {getPrompt} \n" \ "-------------------------------------------\n") while expPrompt is False: choice = 0 choice = int(input("Is the above CLI prompt the prompt you were\n" \ "expecting from the correct WLC in exec mode? \n" \ "1= Yes | 2=No or Ctrl-C to quit : ")) if choice == 1: conn.disable_paging() expPrompt = True return conn elif choice == 2: savedCredentials = False print(f"Disconnecting Current SSH Session...") conn.disconnect() connIsAlive = conn.is_alive() main2() else: print("Failure: Unknown Error. Sorry")
def connect(): """ Here we will user connArgs gathered from get_conn_args \n""" \ """ and establish connection to WLC \n""" global conn global connArgs global savedCredentials global connIsAlive attempts = 0 expPrompt = False while connIsAlive is False: try: connArgs = get_conn_args() conn = ConnectHandler(ip=connArgs["ip"], username=connArgs["user"], password=connArgs["pass"], device_type="cisco_ios", session_log="ssh_session_logfile.txt", session_log_file_mode="write", session_log_record_writes="True") except nm.NetMikoTimeoutException: print("*********************************************************\n" \ "* Error: Timeout Error Occured Attempting to *\n" \ "* connect. Check IP/Hostname and try Again *\n" \ "*********************************************************\n") except nm.NetMikoAuthenticationException: print("*********************************************************\n" \ "* Error: Authentication Error Occured. *\n" \ "* Check Credentials and try Again *\n" \ "*********************************************************\n") ## except: ## print("Unexpected error:", sys.exc_info()[0]) ## raise else: connIsAlive = conn.is_alive() if connIsAlive is True: print( "*********************************************************" ) print( "* Dino | SSH ConneX *" ) print( "*********************************************************" ) print( "* SSH Connection Successful! *" ) getPrompt = conn.find_prompt() print( "* We need to validate if this is the intended device *" ) print( "* *" ) print( f"* Device CLI prompt : {getPrompt} \n" ) print( "* *" ) while expPrompt is False: choice = 0 print( "* [1] Yes | [2] No or Ctrl-C to quit *" ) print( "*********************************************************" ) choice = int(input(" Is the above CLI prompt the prompt you were *\n" \ " expecting from the correct WLC in PRIV EXEC mode? : \n")) if choice == 1: conn.disable_paging() expPrompt = True return conn elif choice == 2: savedCredentials = False print(f"Disconnecting Current SSH Session...") conn.disconnect() connIsAlive = conn.is_alive() main2() else: print("Failure: Unknown Error. Sorry")
#!usr/bin/python #coding: utf-8 import sys import csv from netmiko import ConnectHandler ip = '192.168.73.137' un = 'cisco' pw = 'cisco' platform = 'cisco_ios' device = ConnectHandler(device_type=platform, ip=ip, username=un, password=pw) disable_paging = device.disable_paging() #fo = open ("show_version.txt","a") output = device.send_command('show version', delay_factor=20) print output #fo.write(output) #fo.close close_ssh = device.disconnect()
class DLDriver(NetworkDriver): """NAPALM D-Link Handler.""" def __init__(self, hostname, username, password, timeout=60, optional_args=None): """NAPALM D-Link Handler.""" self.device = None self.hostname = hostname self.username = username self.password = password self.timeout = timeout self.disable_paging = True self.platform = "dlink" self.profile = [self.platform] self.default_clipaging_status = 'enable' # Get optional arguments if optional_args is None: optional_args = {} self.inline_transfer = optional_args.get("inline_transfer", False) self.transport = optional_args.get("transport", "ssh") if self.transport == "telnet": # Telnet only supports inline_transfer self.inline_transfer = True self.port = optional_args.get('port', 22) default_port = {"ssh": 22, "telnet": 23} # Netmiko possible arguments netmiko_argument_map = { 'port': default_port[self.transport], 'verbose': False, 'timeout': self.timeout, 'global_delay_factor': 1, 'use_keys': False, 'key_file': None, 'ssh_strict': False, 'system_host_keys': False, 'alt_host_keys': False, 'alt_key_file': '', 'ssh_config_file': None, 'allow_agent': False } # Build dict of any optional Netmiko args self.netmiko_optional_args = { k: optional_args.get(k, v) for k, v in netmiko_argument_map.items() } def _parse_output(self, output, parser_regexp): result_list = [] for line in output.split("\n"): search_result = re.search(parser_regexp, line) if search_result: result_list.append(search_result.groupdict()) return result_list @staticmethod def _parse_uptime(uptime_str): """Return the uptime in seconds as an integer.""" (years, weeks, days, hours, minutes, seconds) = (0, 0, 0, 0, 0, 0) years_regx = re.search(r"(?P<year>\d+)\syear", uptime_str) if years_regx is not None: years = int(years_regx.group(1)) weeks_regx = re.search(r"(?P<week>\d+)\sweek", uptime_str) if weeks_regx is not None: weeks = int(weeks_regx.group(1)) days_regx = re.search(r"(?P<day>\d+)\sday", uptime_str) if days_regx is not None: days = int(days_regx.group(1)) hours_regx = re.search(r"(?P<hour>\d+)\shour", uptime_str) if hours_regx is not None: hours = int(hours_regx.group(1)) minutes_regx = re.search(r"(?P<minute>\d+)\sminute", uptime_str) if minutes_regx is not None: minutes = int(minutes_regx.group(1)) seconds_regx = re.search(r"(?P<second>\d+)\ssecond", uptime_str) if seconds_regx is not None: seconds = int(seconds_regx.group(1)) uptime_sec = (years * YEAR_SECONDS) + (weeks * WEEK_SECONDS) + (days * DAY_SECONDS) + \ (hours * 3600) + (minutes * 60) + seconds return uptime_sec def _get_clipaging_status(self): try: self.device.send_command("show switch", 'Next Page') self.device.send_command("q") # For exit return 'enable' except IOError: return 'disable' def open(self): """Open a connection to the device.""" try: device_type = 'cisco_ios' if self.transport == "telnet": device_type = "cisco_ios_telnet" self.device = ConnectHandler(device_type=device_type, host=self.hostname, username=self.username, password=self.password, **self.netmiko_optional_args) self.default_clipaging_status = self._get_clipaging_status() if self.disable_paging and self.default_clipaging_status == 'enable': self.device.disable_paging(command="disable clipaging") except NetMikoTimeoutException: raise ConnectionException('Cannot connect to {}'.format(self.hostname)) def close(self): """Close the connection to the device.""" if self.disable_paging and self.default_clipaging_status == 'enable': self.device.disable_paging(command="enable clipaging") self.device.disconnect() self.device = None def is_alive(self): """Returns a flag with the state of the connection.""" null = chr(0) if self.device is None: return {"is_alive": False} if self.transport == "telnet": try: # Try sending IAC + NOP (IAC is telnet way of sending command # IAC = Interpret as Command (it comes before the NOP) self.device.write_channel(telnetlib.IAC + telnetlib.NOP) return {"is_alive": True} except UnicodeDecodeError: # Netmiko logging bug (remove after Netmiko >= 1.4.3) return {"is_alive": True} except AttributeError: return {"is_alive": False} else: # SSH try: # Try sending ASCII null byte to maintain the connection alive self.device.write_channel(null) return {"is_alive": self.device.remote_conn.transport.is_active()} except (socket.error, EOFError): # If unable to send, we can tell for sure that the connection is unusable return {"is_alive": False} def cli(self, commands): """ Execute a list of commands and return the output in a dictionary format using the command as the key. """ cli_output = dict() if type(commands) is not list: raise TypeError("Please enter a valid list of commands!") for command in commands: output = self.device.send_command(command) cli_output.setdefault(command, {}) cli_output[command] = output return cli_output def get_facts(self): """Return a set of facts from the devices.""" show_switch = self.device.send_command("show switch") switch_facts = {} for line in show_switch.splitlines(): if line: name, value = line.split(":") switch_facts[name.strip()] = value.strip() if switch_facts.get("Device Uptime"): switch_facts['Device Uptime'] = self._parse_uptime(switch_facts['Device Uptime']) return switch_facts def get_config(self, retrieve='all'): """ Get config from device. """ config = { 'startup': '', 'running': '', 'candidate': '' } if retrieve.lower() in ('running', 'all'): command = 'show config current_config' config['running'] = py23_compat.text_type(self.device.send_command(command)) # Some D-link switch need run other command if "Configuration" not in config['running']: command = 'show config active' config['running'] = py23_compat.text_type(self.device.send_command(command)) if retrieve.lower() in ('candidate', 'all'): command = 'show config config_in_nvram' config['candidate'] = py23_compat.text_type(self.device.send_command(command)) return config def get_arp_table(self): """ Get arp table information. Sample output: [ {u'interface': u'System', u'ip': u'10.12.16.0', u'mac': u'FF-FF-FF-FF-FF-FF', u'type': u'Local/Broadcast'}, {u'interface': u'System', u'ip': u'10.12.16.1', u'mac': u'00-1F-9D-48-72-51', u'type': u'Dynamic'}, ] """ output = self.device.send_command('show arpentry') parser_regexp = ("(?P<interface>^\w+)\s+" "(?P<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+" "(?P<mac>([0-9A-F]{2}[:-]){5}([0-9A-F]{2}))\s+" "(?P<type>(\w+(/\w+)*))") return self._parse_output(output, parser_regexp) def get_mac_address_table(self): """ Return the MAC address table. Sample output: [ {'status': 'Forward', 'vid': '1', 'vlan_name': 'default', 'mac': '00-0F-E2-21-35-20', 'type': 'Dynamic', 'port': '9'}, {'status': 'Forward', 'vid': '1', 'vlan_name': 'default', 'mac': '00-0F-E2-21-35-2A', 'type': 'Dynamic', 'port': '9'}, {'status': 'Forward', 'vid': '1', 'vlan_name': 'default', 'mac': '00-1D-E5-48-34-81', 'type': 'Dynamic', 'port': '9'}, ] """ output = self.device.send_command('show fdb') parser_regexp = ("(?P<vid>\d+)\s+" "(?P<vlan_name>\w+)\s+" "(?P<mac>([0-9A-F]{2}[:-]){5}([0-9A-F]{2}))\s+" "(?P<port>\d+)\s+" "(?P<type>\w+)\s+" "(?P<status>\w+)\s+") return self._parse_output(output, parser_regexp)
def body(session, apic, username, password): leaf_array = [] leaf_dict = {} vlans = [] vlan_vxlan_array = [] vxlan_array = [] wrong_dict = {} correct_dict = {} vlan_pool = collections.defaultdict(list) phys_doms = collections.defaultdict(list) aaeps = collections.defaultdict(list) location = collections.defaultdict(list) path = collections.defaultdict(list) time.sleep(1) clear() # Clear terminal print("\n") print("|-Target Leafs--------------------|") print("|-CTRL + C When Complete----------|") print("\n") while True: try: leaf = input("Leaf: ") # Input target leafs ipaddress.IPv4Address(leaf) # Check for valid IP leaf_array.append(leaf) # If valid IP, store to array except (ipaddress.AddressValueError, ValueError): # Exception for invalid IP print("Invalid IP Address\n") continue # Continue loop, prompt again except KeyboardInterrupt: # Break the loop using CTRL-C print("\n") break clear() print("Gathering VLAN to VXLAN Mappings...") time.sleep(2) clear() module_mode = "vsh_lc" # Command used by netmiko ti access module smode show_infra_mappings = "show system internal eltmc info vlan brief" # Command used to get vlan to vxlan mappings try: for leaf in leaf_array: # Iterate through leaf array/fabric leafs vlan_vxlan_array = [] vxlan_array = [] vlans_array = [] wrong_vlans = [] credentials = { # Netmiko credential dictionary 'device_type': 'cisco_ios', 'host': leaf, 'username': username, 'password': password, 'session_log': 'my_file.out' } try: device_connect = ConnectHandler( **credentials ) # Connect to device/leaf using crdential dictionary except (ValueError, ssh_exception.AuthenticationException, ssh_exception.NetmikoTimeoutException) as error: print(error) # Print error pass switch_to_hardware = device_connect.send_command( module_mode, expect_string="module-1#" ) # Send command store in variable to device device_connect.disable_paging( command='terminal length 0') # Disable paging on device CLI get_infra_mappings = device_connect.send_command( show_infra_mappings ) # Send command store in variable to device with open(get_file_1, "w") as report: # Write ouput to file report.write(get_infra_mappings ) # Variable create during netmiko session with open(get_file_1, "r") as report: for line in report: # Read file as report if "802.1q" in line: # Check if 802.1q in line L2_info = (re.findall(r"q\b.*\s\b", line) ) # Grab text borded by q and whitespace cleanup = L2_info[0].replace( "q", "") # Remove q from string cleanup = cleanup.replace( "VXLAN", "") # Remove VXLAN from string final_L2 = ( re.findall(r"\b[0-9].*?[0-9]\b", cleanup) ) # Grab vlan - bordered by anything [0-9] ending in [0-9] if len( final_L2 ) == 1: # Since final_2 cariable creates a list, see if the list length == 1 vlan = (re.findall(r"\b[0-9]\b", final_L2[0]) ) # Find the vlan in final_2 index 0 vxlan = (re.findall(r"\b[0-9][0-9].*?[0-9]\b", final_L2[0]) ) # Find the vxlan in final_2 index 0 vlan_vxlan = str(vlan[0] + " " + vxlan[0]) # Concatinate the two vlan_split = vlan_vxlan.split( " ") # Create list of two using split. vlans_array.append( vlan_split[0]) # Index vlan, store to array vxlan_array.append( vlan_split[1]) # Index vxlan, store to array vlan_vxlan_array.append( vlan_split) # Grab whole list, store to array else: vlans_array.append( final_L2[0] ) # If final_2 len != 1 index vlan, store to array vxlan_array.append( final_L2[1] ) # If final_2 len != 1 index vxlan, store to array vlan_vxlan_array.append( final_L2) # Grab whole list, store to array else: pass leaf_dict[ leaf] = vlan_vxlan_array # Store list in dictionaries. Keys being leaf IPs remove_duplicates_vlans = list( dict.fromkeys(vlans_array) ) # Clear of duplicates in list. This allows us to have all assigned vlans across the fabric remove_duplicates_vxlans = list( dict.fromkeys(vxlan_array) ) # Clear of duplicates in list. This allows us to have all assigned vxlans across the fabric clear() print("\n") for k, v in leaf_dict.items( ): # Iterate through key/value pairs wrong_array = [] # List will be reset every k interation correct_array = [] # List will be reset every k interation for v in v: for vlan, vxlan in zip(remove_duplicates_vlans, remove_duplicates_vxlans): if vlan == v[0] and vxlan == v[1]: correct_array.append( " Leaf IP: " + k + " | VLAN: {:7} | VXLAN ID: {:15} " .format(vlan, vxlan)) if vlan == v[0] and vxlan != v[1]: wrong_vlans.append(vlan) wrong_array.append( " Leaf IP: " + k + " | VLAN: {:7} | VXLAN ID: {:15} " .format(v[0], v[1])) else: pass if len(wrong_array) == 0: correct_dict[k] = correct_array else: wrong_dict[k] = wrong_array remove_dups = list(dict.fromkeys(wrong_vlans)) for vlan in remove_dups: pools = vlanPool.aci_gets.find_duplicatee_vlan(session, apic, vlan) vlan_pool[vlan].append(pools[0]) phys_doms[vlan].append(pools[1]) aaeps[vlan].append(pools[2]) location[vlan].append(pools[3]) path[vlan].append(pools[4]) for key_1, v in wrong_dict.items(): # unpack k, v pairs if not v: # If the key has no value, continue at the top of the loop continue else: for string in v: vlan_1 = re.search(r'(?<=VLAN:\s).*?[0-9]\b', string) print( " Fabric VLAN to VXLAN Mapping *Leaf Perspective" ) print( "--------------------------------------------------------------------------------\n" ) print(" *" + string) for key_2, v in correct_dict.items(): for string_2 in v: vlan_2 = re.search(r'(?<=VLAN:\s).*?[0-9]\b', string_2) try: if vlan_1.group(0) == vlan_2.group(0): if string == string_2: pass else: print(" " + string_2) else: pass except AttributeError: pass unpacked_vlan_pools = [ v for k, v in vlan_pool.items() if vlan_1.group(0) == k for v in v for v in v ] unpacked_phys_doms = [ v for k, v in phys_doms.items() if vlan_1.group(0) == k for v in v for v in v ] unpacked_aaep = [ v for k, v in aaeps.items() if vlan_1.group(0) == k for v in v for v in v ] unpacked_location = [ v for k, v in location.items() if vlan_1.group(0) == k for v in v for v in v ] unpacked_path = [ v for k, v in path.items() if vlan_1.group(0) == k for v in v for v in v ] print("\n") print(" Access Policy Details:\n") print(" VLAN Pool(s): " + "\n ".join(unpacked_vlan_pools)) print("\n") print(" Phys Dom(s): " + "\n ".join(unpacked_phys_doms)) print("\n") print(" AAEP(s): " + "\n ".join(unpacked_aaep)) print("\n") print(" Encap Loc.: " + "\n ".join(unpacked_location)) print("\n") print(" Path Attach: " + "\n ".join(unpacked_path)) print("\n") except (UnboundLocalError, OSError): print( "Something Went Wrong. Please Verify Connectivity and Credentials\n" ) pass stop = input("Program Ended")
def device_login(username, password): clear() print("|-Target Layer--------------------|") print("|---------------------------------|") print("\n") # Commands sent to the CLI depend on the layer you want to capture at. As seen under the if staement, CLI code is different layer_selection = " " while layer_selection == "1" or "2": layer_selection = input( " 1. L3 capture\n 2. L2 Capture\n\n Selection: ") if layer_selection == "1": src_dst_iter = [ip for ip in EPCollect.endpoint_array] set_layer = "set outer ipv4 src_ip {} dst_ip {}".format( src_dst_iter[0], src_dst_iter[1]) get_report_1 = "show platform internal hal ep l3 all | grep %s" % src_dst_iter[ 1] get_report_2 = "show platform internal hal ep l3 all | grep %s" % src_dst_iter[ 0] dst_ep = " show endpoint ip %s" % src_dst_iter[1] src_ep = " show endpoint ip %s" % src_dst_iter[0] break elif layer_selection == "2": src_dst_iter = [mac for mac in EPCollect.ep_mac_array] set_layer = "set outer l2 src_mac {} dst_mac {}".format( src_dst_iter[0], src_dst_iter[1]) dst_ep = " show endpoint mac %s" % src_dst_iter[1] src_ep = " show endpoint mac %s" % src_dst_iter[0] break else: print("\n") print("Invalid Input\n") clear() if layer_selection == "1": print("|-Target Port--------------------|") print("|--------------------------------|") print("\n") # If layer 1 is selected above, you will be asked to put in either a source or destination port port_selection = " " while port_selection == "1" or "2": port_selection = input( " 1. Source port\n 2. Destionation port:\n\n Selection: ") if port_selection == "1": target_port = input(" Port: ") set_inner_l4_1 = "set outer l4 src-port %s" % target_port break elif port_selection == "2": target_port = input(" Port: ") set_inner_l4_1 = "set outer l4 dst-port %s" % target_port break else: print("\n") print("Invalid Input\n") else: pass clear() print("Capture Configuration:\n") print(set_layer) try: print(set_inner_l4_1) except UnboundLocalError: pass print("\n") print("|-Target Leafs--------------------|") print("|-CTRL + C When Complete----------|") print("\n") while True: try: leaf = input("Leaf: ") leaf_array.append(leaf) except KeyboardInterrupt: break time.sleep(1) clear() # Start the ELAM capture setup using the leaf array created on line 153 print("\n") print("|-Configuring Triggers------------|") print("|---------------------------------|\n") loop_count = 0 for i in leaf_array: device_dict = {} source_dict = {} # Netmiko login credentials dictionary. Uses variables carried over from the EPCollect module credentials = { 'device_type': 'cisco_ios', 'host': i, 'username': username, 'password': password, 'session_log': 'my_file.out' } # If login fails continue the loop at the next variable, or leaf try: credentials_array.append(credentials) try: device_connect = ConnectHandler(**credentials) except (ValueError, ssh_exception.AuthenticationException, ssh_exception.NetmikoTimeoutException) as error: print(error) continue ################################################################################################### # Gather the destination fabric VLAN, Endpoint VRF, and where the Endpoint was learned from # Send command to CLI which gets all endpoint information for with EP IP or MAC ep_fabric_vl_1 = device_connect.send_command(dst_ep) #Save string to file with open(get_file_1, "w") as report: report.write(ep_fabric_vl_1) # Open file and search lines for infrastructure vlans. Not all leafs will have a vlan # In this case store v to key as N/A. # If there is a vlan in a line, the regex will seach for the vlan at the begining of the line # to the next white space. with open(get_file_1, "r") as report: for line in report: if re.findall(r'^[0-9].*?\s', line): if EPCollect.ep_encap_array[1] in line: vlan = re.findall(r'^[0-9].*?\s', line) device_dict["Infra_vl"] = vlan[0] break elif re.findall(r'^[0-9].*?\s', line): vlan = re.findall(r'^[0-9].*?\s', line) device_dict["Infra_vl"] = vlan[0] break else: device_dict["Infra_vl"] = "N/A" #Open file and search of the vrf in line. Leafs may have vlans but no vrf. In this case it will use a tunnel # to forward to the reporting leaf. Search begingin of line for lower case chars until the chars end with # either upper or lowercase chars. Write vrf to dictionary with open(get_file_1, "r") as report: for line in report: if re.findall(r'^[a-z].*?[a-zA-Z].*?', line): vrf = re.findall(r'^[a-z].*?:[a-zA-Z].*?\s', line) device_dict["vrf"] = vrf[0] break else: device_dict["vrf"] = "N/A" # Find where the endpoint was learned from. Could be ethernet, port-channel, or tunnel # search regex \b = border, starting with the interface type, ending in a number 0-9, or \b # Write to dictionary with open(get_file_1, "r") as report: for line in report: if re.findall(r'\bpo.*?', line): learnedFrom = re.findall(r'\bpo.*?[0-9]\b', line) device_dict["LearnedFrom"] = learnedFrom[0] elif re.findall(r'\beth.*?[0-9]', line): learnedFrom = re.findall(r'\beth.*?[0-9]\b', line) device_dict["LearnedFrom"] = learnedFrom[0] elif re.findall(r'\btun.*?[0-9]', line): learnedFrom = re.findall(r'\btun.*?[0-9]\b', line) device_dict["LearnedFrom"] = learnedFrom[0] report.close() ############################################################################################## # Gather the source fabric VLAN, Endpoint VRF, and where the Endpoint was learned from # We are going to repeat the above lines, but write to a source dictionary ep_fabric_vl_2 = device_connect.send_command(src_ep) with open(get_file_1, "w") as report: report.write(ep_fabric_vl_2) with open(get_file_1, "r") as report: for line in report: if re.findall(r'^[0-9].*?\s', line): if EPCollect.ep_encap_array[0] in line: vlan = re.findall(r'^[0-9].*?\s', line) source_dict["Infra_vl"] = vlan[0] break elif re.findall(r'^[0-9].*?\s', line): vlan = re.findall(r'^[0-9].*?\s', line) source_dict["Infra_vl"] = vlan[0] break else: source_dict["Infra_vl"] = "N/A" with open(get_file_1, "r") as report: for line in report: if re.findall(r'^[a-z].*?[a-zA-Z].*?', line): vrf = re.findall(r'^[a-z].*?:[a-zA-Z].*?\s', line) source_dict["vrf"] = vrf[0] break else: source_dict["vrf"] = "N/A" with open(get_file_1, "r") as report: for line in report: if re.findall(r'\bpo.*?', line): learnedFrom = re.findall(r'\bpo.*?[0-9]\b', line) source_dict["LearnedFrom"] = learnedFrom[0] elif re.findall(r'\beth.*?[0-9]', line): learnedFrom = re.findall(r'\beth[0-9].*?[0-9]\b', line) source_dict["LearnedFrom"] = learnedFrom[0] elif re.findall(r'\btun.*?[0-9]', line): learnedFrom = re.findall(r'\btun.*?[0-9]\b', line) source_dict["LearnedFrom"] = learnedFrom[0] report.close() commands = device_connect.send_command(module_mode, expect_string="module-1#") device_connect.disable_paging(command='terminal length 0') ################################################################################################## # Gather Destination Endpoint Information Endpoint DB port, Hardware BD. This information is all # about hardware, or how the fabric see the path. # First we need to decide which commands we need to send to CLI. If an IP is the endpooint we will # will validate with the ipaddress module. If not a valid ip, we will use the excpetion as the # condition try: ipaddress.IPv4Address(src_dst_iter[0]) get_report_1 = "show platform internal hal ep l3 all | grep %s" % src_dst_iter[ 1] get_report_2 = "show platform internal hal ep l3 all | grep %s" % src_dst_iter[ 0] network_report_1 = device_connect.send_command(get_report_1) network_report_2 = device_connect.send_command(get_report_2) ep_dest = src_dst_iter[0] ep_src = src_dst_iter[0] except ipaddress.AddressValueError: get_l2_src = "show platform internal hal ep l2 mac %s" % src_dst_iter[ 0] get_l2_dst = "show platform internal hal ep l2 mac %s" % src_dst_iter[ 1] network_report_1 = device_connect.send_command(get_l2_dst) network_report_2 = device_connect.send_command(get_l2_src) ep_dest = src_dst_iter[0].swapcase() ep_src = src_dst_iter[0].swapcase() pass with open(get_file_1, "w") as report: report.write(network_report_1) with open(get_file_1, "r") as report: for line in report: bd = re.findall(r'\bBD-.*?\s', line) if re.findall(r'\bEth.*?[0-9]\s', line): learned_ep_1 = re.findall(r'\bEth[0-9].*?[0-9]\b', line) device_dict["EP DB Port"] = learned_ep_1[0] device_dict["EP Hw BD"] = bd[0] elif re.findall(r'\bPo.*?[0-9]\s', line): learned_ep_1 = re.findall(r'\bPo.*?[0-9]\b', line) dst_interface = learned_ep_1[0] device_dict["EP DB Port"] = learned_ep_1[0] device_dict["EP Hw BD"] = bd[0] elif re.findall(r'\bTun.*?[0-9]', line): learned_ep_1 = re.findall(r'\bTun.*?[0-9]\b', line) bd = re.findall(r'\bBD-.*?\s', line) device_dict["EP DB Port"] = learned_ep_1[0] device_dict["EP Hw BD"] = bd[0] device_dict["Sw Port"] = "N/A" report.close() ############################################################################################### # Gather Source Endpoint Information Endpoint DB port, Hardware BD with open(get_file_1, "w") as report: report.write(network_report_2) with open(get_file_1, "r") as report: for line in report: bd = re.findall(r'\bBD-.*?\s', line) if re.findall(r'\bEth.*?[0-9]\b', line): learned_ep_1 = re.findall(r'\bEth[0-9].*?[0-9]\b', line) src_interface = learned_ep_1[0] source_dict["EP DB Port"] = learned_ep_1[0] source_dict["EP Hw BD"] = bd[0] elif re.findall(r'\bPo.*?[0-9]\s', line): learned_ep_1 = re.findall(r'\bPo.*?[0-9]\b', line) src_interface = learned_ep_1[0] source_dict["EP DB Port"] = learned_ep_1[0] source_dict["EP Hw BD"] = bd[0] elif re.findall(r'\bTun.*?[0-9]\s', line): learned_ep_1 = re.findall(r'\bTun.*?[0-9]\b', line) source_dict["EP DB Port"] = learned_ep_1[0] source_dict["EP Hw BD"] = bd[0] source_dict["Sw Port"] = "N/A" exit_module = device_connect.send_command(exit, expect_string="") ############################################################################################### # Gather Source Endpoint Information Endpoint Software port. port_channel = device_connect.send_command(get_port_channel) with open(get_file_1, "w") as report: report.write(port_channel) try: if "Tunnel" not in learned_ep_1[0]: with open(get_file_1, "r") as report: for line in report: try: if dst_interface in line: learned_phy_ports = re.findall( r'\bEth[0-9].*?[0-9]\b', line) if len(learned_phy_ports) > 1: join_ints = ", ".join( learned_phy_ports) device_dict["Sw Port"] = join_ints break else: device_dict[ "Sw Port"] = learned_phy_ports[0] break else: device_dict["Sw Port"] = dst_interface except UnboundLocalError: pass with open(get_file_1, "r") as report: for line in report: try: if src_interface in line: learned_phy_ports = re.findall( r'\bEth[0-9].*?[0-9]\b', line) if len(learned_phy_ports) > 1: join_ints = ", ".join( learned_phy_ports) source_dict["Sw Port"] = join_ints break else: source_dict[ "Sw Port"] = learned_phy_ports[0] break else: source_dict["Sw Port"] = src_interface except UnboundLocalError: pass else: device_dict["Sw Port"] = "N/A" source_dict["Sw Port"] = "N/A" except UnboundLocalError: pass ############################################################################################### # Setup ELAM capture perameters and intialize the capture commands = device_connect.send_command(module_mode, expect_string="") device_connect.disable_paging(command='terminal length 0') debug = device_connect.send_command(debug_mode, expect_string="") reset_trigger = device_connect.send_command(trigger_reset, expect_string="") init_trigger = device_connect.send_command(initializer, expect_string="") layer_three = device_connect.send_command(set_layer, expect_string="") try: layer_four = device_connect.send_command(set_inner_l4_1, expect_string="") except UnboundLocalError: pass init = device_connect.send_command(start, expect_string="") stat = device_connect.send_command(status, expect_string="ed") print(" IP (Leaf): {} Status: {}".format(i, "Armed")) device_dict_nested_2.update({i: source_dict}) device_dict_nested.update({i: device_dict}) loop_count = loop_count + 1 except (OSError, UnboundLocalError, TypeError) as error: print("Failed to initialize ELAM capture for leaf: %s") % i print("Error: " + error) continue print("\n") holder = input("Hit enter to check status: ") print("\n") print("Checking Trigger...") clear() ############################################################################################### # Present Endpoint ACI confiurations with external vlan tags print("Endpoints:\n") for endpoint_1, endpoint_2 in zip(EPCollect.query_array_1, EPCollect.query_array_2): print("{:54}{}".format(endpoint_1, endpoint_2)) print("\n") ############################################################################################### # Present Endpoint hardware configuration create by the internal fabric try: print(" Source Endpoint Fabric Information:\n") for k, v in device_dict_nested_2.items(): print(" {:1} {:<25} {:<20} {:<30} {:<20} {:<20} {:<27} {}".format( " ", "Leaf : " + k, "Infra_vl : " + v["Infra_vl"], "vrf: " + v["vrf"], "EP DB Port: " + v["EP DB Port"], "EP hw BD: " + v["EP Hw BD"], "LearningPort: " + v["LearnedFrom"], "Phys Port: " + v["Sw Port"])) print("\n") except KeyError as error: print(error) pass ############################################################################################### # Check to see if any of our ELAM traps have been triggered. If so crab the ovec hex, gther the report, # and find which port is associated the the hex. for leaf in leaf_array: try: credentials = { 'device_type': 'cisco_ios', 'host': leaf, 'username': username, 'password': password, 'session_log': 'my_file.out' } try: device_connect = ConnectHandler(**credentials) except (ValueError, ssh_exception.AuthenticationException, ssh_exception.NetmikoTimeoutException) as error: continue commands = device_connect.send_command(module_mode, expect_string="") device_connect.disable_paging(command='terminal length 0') debug = device_connect.send_command(debug_mode, expect_string="") init_trigger = device_connect.send_command(initializer, expect_string="") stat = device_connect.send_command(status, expect_string="ed") if "Triggered" in stat: print(" IP (Leaf): {} Status: {}\n".format( leaf, "Triggered ####")) ############################################################################################### # Request the ovec report from CLI and use regex to get the hex. Since the right of the x # is the the important char, we will create a variable with only those chars. Here we # are searching directly from string. ovec_report = device_connect.send_command(get_ovec) if re.compile(r'\b0x.\b').findall(ovec_report): hex = re.compile(r'\b0x.').findall(ovec_report) hex_strip = str(hex[0].replace("0x", "")).swapcase() elif re.compile(r'\b0x..\b').findall(ovec_report): hex = re.compile(r'\b0x..').findall(ovec_report) hex_strip = str(hex[0].replace("0x", "")).swapcase() ############################################################################################### # Get full report, open it and scan for the port associated with the hex string. get_port = "show platform internal hal l2 port gpd" report_filtered = device_connect.send_command(get_port) with open("C:\\Python\ELAM_Report.txt", "w") as report: report.write(report_filtered) try: with open("C:\\Python\ELAM_Report.txt", "r") as report: print("\n") for line in report: if re.findall( r'\b' + hex_strip + '.' + hex_strip + '\s', line): ovec_port = re.findall(r'\bEth[0-9].*?[0-9]\b', line) device_dict_nested[leaf]["ovec"] = ovec_port[0] elif re.findall( r'\b' + hex_strip + '..' + hex_strip + '\s', line): ovec_port = re.findall(r'\bEth[0-9].*?[0-9]\b', line) device_dict_nested[leaf]["ovec"] = ovec_port[0] ############################################################################################### # Present the destination Endpoints fabric forwarding information with ovec. If the final 3 # values show association then the forwarding path is correct. print( " Infra_vl: {} vrf: {} EP hw BD: {} EP DB Fw: {} [LearningPort: {} Phys Port: {} Ovec Port: {}]" .format(device_dict_nested[leaf]["Infra_vl"], device_dict_nested[leaf]["vrf"], device_dict_nested[leaf]["EP Hw BD"], device_dict_nested[leaf]["EP DB Port"], device_dict_nested[leaf]["LearnedFrom"], device_dict_nested[leaf]["Sw Port"], device_dict_nested[leaf]["ovec"])) print("\n") except (NameError) as error: continue else: continue except (UnboundLocalError, OSError) as error: print("Failed to initialize ELAM capture for leaf: %s") % leaf print("Error: " + error) continue complete = input("Capture Complete")
def body(): leaf_array = [ ] leaf_dict = { } vlans = [ ] vlan_vxlan_array = [ ] vxlan_array = [ ] wrong_dict = { } correct_dict = { } wrong_array = [ ] correct_array = [ ] print("Fabric Credentials:\n.") username = input("Username: "******"Password: "******"\n") print("|-Target Leafs--------------------|") print("|-CTRL + C When Complete----------|") print("\n") while True: try: leaf = input("Leaf: ") # Input target leafs ipaddress.IPv4Address(leaf) # Check for valid IP leaf_array.append(leaf) # If valid IP, store to array except (ipaddress.AddressValueError, ValueError): # Exception for invalid IP print("Invalid IP Address\n") continue # Continue loop, prompt again except KeyboardInterrupt: # Break the loop using CTRL-C print("\n") break clear() print("Gathering VLAN to VXLAN Mappings...") time.sleep(2) clear() module_mode = "vsh_lc" # Command used by netmiko ti access module smode show_infra_mappings = "show system internal eltmc info vlan brief" # Command used to get vlan to vxlan mappings try: for leaf in leaf_array: # Iterate through leaf array/fabric leafs vlan_vxlan_array = [ ] vxlan_array = [ ] vlans_array = [ ] credentials = { # Netmiko credential dictionary 'device_type': 'cisco_ios', 'host': leaf, 'username': username, 'password': password, 'session_log': 'my_file.out'} try: device_connect = ConnectHandler(**credentials) # Connect to device/leaf using crdential dictionary except (ValueError, ssh_exception.AuthenticationException, # Catch netmiko exceptions ssh_exception.NetmikoTimeoutException) as error: print(error) # Print error pass switch_to_hardware = device_connect.send_command(module_mode, expect_string="module-1#") # Send command store in variable to device device_connect.disable_paging(command='terminal length 0') # Disable paging on device CLI get_infra_mappings = device_connect.send_command(show_infra_mappings) # Send command store in variable to device with open(get_file_1, "w") as report: # Write ouput to file report.write(get_infra_mappings) # Variable create during netmiko session with open(get_file_1, "r") as report: for line in report: # Read file as report if "802.1q" in line: # Check if 802.1q in line L2_info = (re.findall(r"q\b.*\s\b", line)) # Grab text borded by q and whitespace cleanup = L2_info[0].replace("q", "") # Remove q from string cleanup = cleanup.replace("VXLAN", "") # Remove VXLAN from string final_L2 = (re.findall(r"\b[0-9].*?[0-9]\b", cleanup)) # Grab vlan - bordered by anything [0-9] ending in [0-9] if len(final_L2) == 1: # Since final_2 cariable creates a list, see if the list length == 1 vlan = (re.findall(r"\b[0-9]\b", final_L2[0])) # Find the vlan in final_2 index 0 vxlan = (re.findall(r"\b[0-9][0-9].*?[0-9]\b", final_L2[0])) # Find the vxlan in final_2 index 0 vlan_vxlan = str(vlan[0] + " " + vxlan[0]) # Concatinate the two vlan_split = vlan_vxlan.split(" ") # Create list of two using split. vlans_array.append(vlan_split[0]) # Index vlan, store to array vxlan_array.append(vlan_split[1]) # Index vxlan, store to array vlan_vxlan_array.append(vlan_split) # Grab whole list, store to array else: vlans_array.append(final_L2[0]) # If final_2 len != 1 index vlan, store to array vxlan_array.append(final_L2[1]) # If final_2 len != 1 index vxlan, store to array vlan_vxlan_array.append(final_L2) # Grab whole list, store to array else: pass leaf_dict[leaf] = vlan_vxlan_array # Store list in dictionaries. Keys being leaf IPs # The following variables will be used for conditional statements by gathering vlans/vxlans in the fabric, not where there are assigned currently. That wil be checked later remove_duplicates_vlans = list(dict.fromkeys(vlans_array)) # Clear of duplicates in list. This allows us to have all assigned vlans across the fabric remove_duplicates_vxlans = list(dict.fromkeys(vxlan_array)) # Clear of duplicates in list. This allows us to have all assigned vxlans across the fabric clear() print("\n") for k, v in leaf_dict.items(): # Iterate through key/value pairs wrong_array = [] # List will be reset every k interation correct_array = [] # List will be reset every k interation for v in v: for vlan, vxlan in zip(remove_duplicates_vlans, remove_duplicates_vxlans): # Iterate through both list we create on line 133, 134 if vlan == v[0] and vxlan == v[1]: # Check see if the variables vlan/vxlan are == to values in the dictionary correct_array.append(" Leaf IP: " + k + " | VLAN: {:7} | VXLAN ID: {:15} |".format(vlan, vxlan)) # Store value if true if vlan == v[0] and vxlan != v[1]: # Check see if the variables vlan is == to value but vxlan is not wrong_array.append(" Leaf IP: " + k + " | VLAN: {:7} | VXLAN ID: {:15} |".format(v[0], v[1])) # Store value if false else: pass if len(wrong_array) == 0: # If list length == to 0, or if mapping are correct store to dictionary correct_dict[k] = correct_array else: # if list > 1 then a mapping wasnt correct, store to dictionary wrong_dict[k] = wrong_array for k, v in wrong_dict.items(): # unpack k, v pairs if not v: # If the key has no value, continue at the top of the loop continue else: for string in v: # Else, unpack v (string) from v. This is needed because the v is a list of v(vlan, to vxlan mappings vlan_1 = re.search(r'\bVL.*?[0-9]\b', string) # Grab the first occurnece of and int, whihc would be the vlan print("Fabric VLAN to VXLAN Mapping *Leaf Perspective") print("---------------------------------------------------------------------------------") print(" *" + string) # Print the value stored in wrong array, or incorrect mapping for k, v in correct_dict.items(): # Next unpack the correct mappings for string_2 in v: # Get the value in the value, or list in the list vlan_2 = re.search(r'\bVL.*?[0-9]\b', string_2) # Store the value try: if vlan_1.group(0) == vlan_2.group(0): # Compare the to variables for correct and incorrect if string == string_2: # If they're equal each other, check if the string in each dict == each other. pass # If they are, dont print since it was printed in the first unpacking else: print(" " + string_2) # ELSE, print the string else: pass except AttributeError: pass print("---------------------------------------------------------------------------------") print("\n") except (UnboundLocalError,OSError): print("Something Went Wrong. Please Verify Connectivity and Credentials\n") pass stop = input("Program Ended")