def Audit(): ## Parse the config parse = CiscoConfParse('conf.txt') for i in range(25): ## Add a new switchport at the bottom of the config... parse.append_line('interface FastEthernet0/' + str(i)) parse.append_line(' switchport') parse.append_line(' switchport mode access') parse.append_line('!') parse.commit() # commit() **must** be called before searching again ## Search and standardize the interfaces... standardize_intfs(parse) parse.commit() # commit() **must** be called before searching again ## I'm illustrating regular expression usage in has_line_with() if not parse.has_line_with(r'^service\stimestamp'): ## prepend_line() adds a line at the top of the configuration parse.prepend_line( 'service timestamps debug datetime msec localtime show-timezone') parse.prepend_line( 'service timestamps log datetime msec localtime show-timezone') ## Write the new configuration parse.save_as('conf3.txt')
# Script to find what interfaces have an "ip helper-address" # Uses ciscoconfparse library, make sure its installed #Importing the necessary modules. import os from ciscoconfparse import CiscoConfParse os.chdir("c:\\configs") for filename in os.listdir(os.getcwd()): parse = CiscoConfParse(filename, factory=True, syntax='ios') obj_list = parse.find_objects_dna(r'Hostname') inf_w_help = parse.find_parents_w_child(parentspec=r"^interface", childspec=r"ip helper-address") hostn = obj_list[0].hostname print hostn for interface in inf_w_help: print interface print("Write results to file...") newconfig = CiscoConfParse([]) newconfig.append_line(hostn) for interface in inf_w_help: newconfig.append_line(interface) newconfig.append_line('ip helper-address my.new.ip.add1') newconfig.commit() newconfig.save_as(hostn + '_newconfig.txt')
text = config_file re1 = '(ag)' rg = re.compile(re1, re.IGNORECASE | re.DOTALL) l2agg = rg.search(text) if l2agg: for intf in parse.find_objects(r'^interface.+?thernet'): has_qos_trust = intf.has_child_with(r' mls qos trust dscp') is_switchport_trunk = intf.has_child_with(r'switchport mode trunk') is_switchport_infra = intf.has_child_with(r'INFRA:TRUNK*.*') if (is_switchport_trunk and is_switchport_infra) and (not has_qos_trust): cfgdiff.append_line("!") cfgdiff.append_line(intf.text) cfgdiff.append_line("mls qos trust dscp") cfgdiff.save_as(config_file + '_new') print("Config Created with _new extension for L2AGG") else: for intf in parse.find_objects(r'^interface.+?thernet'): has_qos_trust = intf.has_child_with(r' mls qos trust dscp') is_switchport_trunk = intf.has_child_with(r'switchport mode trunk') is_switchport_infra = intf.has_child_with(r'INFRA:TRUNK*.*') is_switchport_access = intf.has_child_with(r'switchport mode access') is_switchport_shutdown = intf.has_child_with(r'shutdown') if (is_switchport_trunk and is_switchport_infra) and (not has_qos_trust): cfgdiff.append_line("!")
## Add missing commands if is_switchport_access and (not has_stormcontrol): intf.append_to_family(' storm-control action trap') intf.append_to_family(' storm-control broadcast level 0.4 0.3') ## remove dot1q trunk misconfiguration elif is_switchport_trunk: intf.delete_children_matching('port-security') ## Parse the config parse = CiscoConfParse('switch.conf') ## Add a new switchport at the bottom of the config... parse.append_line('interface GigabitEthernet1/0') parse.append_line(' switchport') parse.append_line(' switchport mode access') parse.append_line('!') parse.commit() ## Search and standardize the interfaces standardize_interfaces(parse) parse.commit() ## Add a line to the top of the config if not already there. if not parse.has_line_with(r'^service\stimestamp'): parse.prepend_line( 'service timestamps debug datetime msec localtime show-timezone') parse.prepend_line( 'service timestamps log datetime msec localtime show-timezone')
is_switchport_trunk = intf.has_child_with(r'switchport mode trunk') ## Add missing commands if is_switchport_access and (not has_stormcontrol): intf.append_to_family(' storm-control action trap') intf.append_to_family(' storm-control broadcast level 0.4 0.3') ## remove dot1q trunk misconfiguration elif is_switchport_trunk: intf.delete_children_matching('port-security') ## Parse the config parse = CiscoConfParse('switch.conf') ## Add a new switchport at the bottom of the config... parse.append_line('interface GigabitEthernet1/0') parse.append_line(' switchport') parse.append_line(' switchport mode access') parse.append_line('!') parse.commit () ## Search and standardize the interfaces standardize_interfaces(parse) parse.commit() ## Add a line to the top of the config if not already there. if not parse.has_line_with(r'^service\stimestamp'): parse.prepend_line('service timestamps debug datetime msec localtime show-timezone') parse.prepend_line('service timestamps log datetime msec localtime show-timezone') ## Wrtite the config file now...
# the current SVI address is used as a HSRP virtual IP virtual_ip = ipv4_addr.ip_object # at this point we need to determine the next addresses which are used for the primary and secondary switch # we will try, if the next two addresses are part of the network, otherwise we will use the previous two # addresses ipv4_network = IPv4Network(ipv4_addr.network) if (ipv4_addr.ip_object + 1) in ipv4_network.hosts(): primary_ip = ipv4_addr.ip_object + 1 secondary_ip = ipv4_addr.ip_object + 2 else: primary_ip = ipv4_addr.ip_object - 1 secondary_ip = ipv4_addr.ip_object - 2 # now add the configuration to the change scripts primary_config.append_line("interface %s" % vlan_interface_string) primary_config.append_line(" description *** VLAN SVI %s" % vlan_id) primary_config.append_line(" ip address %s %s" % (primary_ip, ipv4_addr.netmask)) primary_config.append_line(" standby version 2") primary_config.append_line(" standby 1 ip %s" % virtual_ip) primary_config.append_line(" standby 1 priority 255") primary_config.append_line(" standby 1 authentication md5 key-string vl%s" % vlan_id) primary_config.append_line("!") secondary_config.append_line("interface %s" % vlan_interface_string) secondary_config.append_line(" description *** VLAN SVI %s" % vlan_id) secondary_config.append_line(" ip address %s %s" % (secondary_ip, ipv4_addr.netmask)) secondary_config.append_line(" standby version 2") secondary_config.append_line(" standby 1 ip %s" % virtual_ip) secondary_config.append_line(" standby 1 priority 254") secondary_config.append_line(" standby 1 authentication md5 key-string vl%s" % vlan_id)
def main(): confparse = CiscoConfParse(config.USER_CONFIG) cfgdiffs = CiscoConfParse([]) for template in config.TEMPLATES: template_dict = load_template(template) template_name = template_dict["TEMPLATE_NAME"] template_type = template_dict["TEMPLATE_TYPE"] print(f'{Fore.BLUE}VERIFYING TEMPlATE: ' + template_name) print(f'**************************************{Style.RESET_ALL}') for template_section in template_dict["SECTIONS"]: regex_pattern = template_section["SECTION_REGEX"] sub_regex_patterns = template_section["LINES"] section_name = template_section["NAME"] #regex_pattern = template_dict["SECTION_REGEX"] #sub_regex_patterns = template_dict["LINES"] print(f'{Fore.GREEN}-VERIFYING SECTION: {Fore.CYAN}' + section_name + f'{Style.RESET_ALL}') ## Find all matching sections (multi line objects) objects = confparse.find_objects(regex_pattern) ## Verify first if the whole section is missing if len(objects) == 0: cfgdiffs.append_line(f'{Fore.RED} -> MISSING WHOLE SECTION:') cfgdiffs.append_line(f'{Fore.RED} ' + regex_pattern) for subregex in sub_regex_patterns: cfgdiffs.append_line(" " + subregex) is_valid = False if (is_valid == False): for line in cfgdiffs.ioscfg: print(f'{Fore.RED}' + line + f'{Style.RESET_ALL}') cfgdiffs = CiscoConfParse([]) ## If the section is there, verify if some parts are missing else: for object in objects: is_valid = True ## Mark that some lines are missing if we ever have to print that object cfgdiffs.append_line(f'{Fore.RED} -> MISSING OR DIFFERENTLY CONFIGURED LINES') cfgdiffs.append_line(f' ' + object.text + f'{Style.RESET_ALL}') ## Search children of the object for subregex in sub_regex_patterns: if not (object.re_search_children(subregex)): cfgdiffs.append_line(" " + subregex) is_valid = False if(is_valid==False): for line in cfgdiffs.ioscfg: print(f'{Fore.RED}' + line + f'{Style.RESET_ALL}') else: print(f'{Fore.GREEN} -> SUCCESS - CONFIG SECTION: ' + template_name + ' FOR OBJECT: ' + object.text + f'{Style.RESET_ALL}') #Reset cfgdiffs for next object cfgdiffs = CiscoConfParse([]) ## Find all single line objects if(template_type=='SINGLE_LINE_AND_MULTI_SECTION'): is_valid = True print(f'{Fore.GREEN}-VERIFYING GENERAL LINES: {Style.RESET_ALL}') regex_patterns = template_dict["SINGLE_LINE_REGEXES"] for line in regex_patterns: if not confparse.has_line_with(line): print(f'{Fore.RED} -> MISSING OR DIFFERENTLY CONFIGURED LINES: ' + line + f'{Style.RESET_ALL}') is_valid = False if (is_valid==True): print(f'{Fore.GREEN} -> SUCCESS - GENERAL CONFIG PARTS: ' + template_name + f'{Style.RESET_ALL}') print(f'{Fore.BLUE}*****************END*********************{Style.RESET_ALL}\n')
# now we create an IP address object from the ARP entry arp_ipv4_addr = IPv4Address(ipv4) # assign static arp entry to the VLAN SVI interface for vlan_svi in vlan_svis: svi_ipv4_network = IPv4Network(vlan_svi['ipv4_addr'] + "/" + vlan_svi['ipv4_netmask'], strict=False) if arp_ipv4_addr in svi_ipv4_network.hosts(): # extend the model if the correct IP network is found if "static_arps" not in vlan_svi.keys(): vlan_svi['static_arps'] = list() record = { 'ipv4_host': ipv4, 'mac': mac } vlan_svi['static_arps'].append(record) # a static ARP is only defined on a single interface break print("Write results to file...") cisco_nxos_template = CiscoConfParse(['!']) for vlan_svi in vlan_svis: cisco_nxos_template.append_line("interface Vlan%s" % vlan_svi['vlan_id']) for static_arp in vlan_svi['static_arps']: cisco_nxos_template.append_line(" ip arp %s %s" % (static_arp['ipv4_host'], static_arp['mac'])) cisco_nxos_template.append_line('!') cisco_nxos_template.save_as(os.path.join(output_dir, "cisco_nxos_config.txt"))
def convert_vrf(ios_conf_file, new_conf_file, vrf_name): xr_conf = CiscoConfParse(new_conf_file) vrf_attrib = IosVrfConfigParser.ios_get_vrf_attrib( ios_conf_file, vrf_name) if vrf_attrib['VRF_NAME']: print "create vrf config" xr_conf.append_line("vrf " + vrf_attrib['VRF_NAME']) xr_conf.append_line(" address-family ipv4 unicast") if vrf_attrib['EX_MAP']: print "create EXPORT Route-policy" for ex_map in vrf_attrib['EX_MAP']: xr_conf.append_line(" export route-policy " + ex_map) if vrf_attrib['IM_MAP']: print "create IMPORT Route-policy" for im_map in vrf_attrib['IM_MAP']: xr_conf.append_line(" export route-policy " + im_map) if vrf_attrib['RT_EXPORT']: print "create Export Route-Target " for rt_export in vrf_attrib['RT_EXPORT']: xr_conf.append_line(" export route-target " + rt_export) if vrf_attrib['RT_IMPORT']: print "create Import Route-Target " for rt_import in vrf_attrib['RT_IMPORT']: xr_conf.append_line(" export route-target " + rt_import) xr_conf.commit() xr_conf.save_as(new_conf_file)
def convert_cfg_file(config, device_type, out_path, conversion_matrix): """Convert cfg file to other cfg file""" import os import re from ciscoconfparse import CiscoConfParse # Check if device type exist in conversion matrix if device_type in conversion_matrix: # Determine new filename new_filename = os.path.join(out_path, os.path.basename(config)) if os.path.isfile(new_filename): # Remove CFG if it exist os.remove(new_filename) # Parse cisco configuration with Ciscoconfparse parse = CiscoConfParse(config) # DELETE for item in conversion_matrix[device_type]["delete"]: if item[1] == None: # Check required fields continue elif item[0] != None: # Parent cmd is mentionned parent_object = parse.find_objects(item[0]) for parent in parent_object: # Delete child object in parent object parent.delete_children_matching(item[1]) else: # parent cmd is not mentionned cli_objects = parse.find_objects(item[1]) for cli_object in cli_objects: # Delete object and all child objects if exist cli_object.delete() # ADD for item in conversion_matrix[device_type]["add"]: if item[2] == None: # Check required fields continue elif item[0] != None: # parent cmd is mentionned parent_object = parse.find_objects(item[0]) parent_object_done = list( ) # This is to avoid duplicate added entries for parent in parent_object: parent_re = re.compile(parent.text) if parent.has_children == True: # Add space to child if they are child if parent.text not in parent_object_done: # Avoid duplicates entries nb_space = len(parent.text) - len( parent.text.lstrip()) + 1 parse.insert_after(parent_re, insertstr=" " * nb_space + item[2]) parent_object_done.append(parent.text) else: # Entry is at the root of cfg, no space added parse.insert_after(parent_re, insertstr=item[2]) else: # parent cmd is not mentionned parse.append_line(item[2]) # Write line at the end of the file # REPLACE for item in conversion_matrix[device_type]["replace"]: if item[1] == None or item[2] == None: # Check required fields continue if item[0] != None: # parent cmd is mentionned initial_cmd = re.compile(item[1]) parse.replace_children(item[0], initial_cmd, item[2]) else: # parent cmd is not mentionned initial_cmd = re.compile(item[1]) parse.replace_lines(initial_cmd, item[2]) # Write output to out_file parse.save_as(new_filename) else: new_filename = "Skipped (model unknown)" return new_filename
arp_ipv4_addr = IPv4Address(ipv4) # assign static arp entry to the VLAN SVI interface for vlan_svi in vlan_svis: svi_ipv4_network = IPv4Network(vlan_svi['ipv4_addr'] + "/" + vlan_svi['ipv4_netmask'], strict=False) if arp_ipv4_addr in svi_ipv4_network.hosts(): # extend the model if the correct IP network is found if "static_arps" not in vlan_svi.keys(): vlan_svi['static_arps'] = list() record = {'ipv4_host': ipv4, 'mac': mac} vlan_svi['static_arps'].append(record) # a static ARP is only defined on a single interface break print("Write results to file...") cisco_nxos_template = CiscoConfParse(['!']) for vlan_svi in vlan_svis: cisco_nxos_template.append_line("interface Vlan%s" % vlan_svi['vlan_id']) for static_arp in vlan_svi['static_arps']: cisco_nxos_template.append_line( " ip arp %s %s" % (static_arp['ipv4_host'], static_arp['mac'])) cisco_nxos_template.append_line('!') cisco_nxos_template.save_as( os.path.join(output_dir, "cisco_nxos_config.txt"))
## Add missing features if is_switchport_access and (not has_stormcontrol): intf.append_to_family(' storm-control action trap') intf.append_to_family(' storm-control broadcast level 0.4 0.3') ## Remove dot1q trunk misconfiguration... elif is_switchport_trunk: intf.delete_children_matching('port-security') ## Parse the config parse = CiscoConfParse('short.conf') ## Add a new switchport at the bottom of the config... parse.append_line('interface FastEthernet0/4') parse.append_line(' switchport') parse.append_line(' switchport mode access') parse.append_line('!') parse.commit() # commit() **must** be called before searching again ## Search and standardize the interfaces... standardize_intfs(parse) parse.commit() # commit() **must** be called before searching again ## I'm illustrating regular expression usage in has_line_with() if not parse.has_line_with(r'^service\stimestamp'): ## prepend_line() adds a line at the top of the configuration parse.prepend_line( 'service timestamps debug datetime msec localtime show-timezone') parse.prepend_line(
add_ip_addresses = [] secondary_ipv4_address_lines = vlan_interface.re_search_children(r"^ ip address .* secondary$") for sec_ipv4_cmd in secondary_ipv4_address_lines: # another way to convert the ip address command sec_ipv4_addr = sec_ipv4_cmd.text[len(" ip address "):] sec_ipv4_addr = sec_ipv4_addr.rstrip(" secondary") sec_ipv4_addr = sec_ipv4_addr.replace(" ", "/") # convert it to an IPv4Interface object from the ipaddresss module ip_address = IPv4Interface(sec_ipv4_addr) # store it for later processing add_ip_addresses.append(ip_address) # now add the configuration to the change scripts primary_config.append_line("interface %s" % vlan_interface_string) primary_config.append_line(" description *** VLAN SVI %s" % vlan_id) primary_config.append_line(" ip address %s %s" % (primary_ip, ipv4_addr.netmask)) for ipv4_address in add_ip_addresses: # determine primary IP address if IPv4Address(ipv4_address.ip + 1) in ipv4_address.network.hosts(): primary_ip = ipv4_address + 1 else: primary_ip = ipv4_address - 1 primary_config.append_line(" ip address %s %s secondary" % (primary_ip.ip, ipv4_address.netmask)) primary_config.append_line(" standby version 2") primary_config.append_line(" standby 1 ip %s" % virtual_ip) for ipv4_address in add_ip_addresses: primary_config.append_line(" standby 1 ip %s secondary" % ipv4_address.ip)
cfgdiff = CiscoConfParse([]) text = config_file re1='(ag)' rg = re.compile(re1,re.IGNORECASE|re.DOTALL) l2agg = rg.search(text) if l2agg: for intf in parse.find_objects(r'^interface.+?thernet'): has_qos_trust = intf.has_child_with(r' mls qos trust dscp') is_switchport_trunk = intf.has_child_with(r'switchport mode trunk') is_switchport_infra = intf.has_child_with(r'INFRA:TRUNK*.*') if (is_switchport_trunk and is_switchport_infra) and (not has_qos_trust): cfgdiff.append_line("!") cfgdiff.append_line(intf.text) cfgdiff.append_line("mls qos trust dscp") cfgdiff.save_as(config_file+'_new') print ("Config Created with _new extension for L2AGG") else: for intf in parse.find_objects(r'^interface.+?thernet'): has_qos_trust = intf.has_child_with(r' mls qos trust dscp') is_switchport_trunk = intf.has_child_with(r'switchport mode trunk') is_switchport_infra = intf.has_child_with(r'INFRA:TRUNK*.*') is_switchport_access = intf.has_child_with(r'switchport mode access') is_switchport_shutdown = intf.has_child_with(r'shutdown') if (is_switchport_trunk and is_switchport_infra) and (not has_qos_trust): cfgdiff.append_line("!") cfgdiff.append_line(intf.text)