def testValues_insert_after_atomic_factory_01(self): """Ensure that comments which are added, assert is_comment""" with patch('__main__.IOSCfgLine') as mock: # the mock pretends to be an IOSCfgLine so we can test against it result_correct01 = mock result_correct01.linenum = 16 result_correct01.text = ' ! TODO: some note to self' result_correct01.classname = 'IOSCfgLine' result_correct01.is_comment = True result_correct02 = [ 'interface GigabitEthernet4/1', ' ! TODO: some note to self', ' switchport', ' switchport access vlan 100', ' switchport voice vlan 150', ' power inline static max 7000', ] linespec = 'interface GigabitEthernet4/1' cfg = CiscoConfParse(self.c01, factory=True) cfg.insert_after(linespec, ' ! TODO: some note to self', exactmatch=True, atomic=True) test_result01 = cfg.find_objects('TODO')[0] self.assertEqual(result_correct01.linenum, test_result01.linenum) self.assertEqual(result_correct01.text, test_result01.text) self.assertEqual(result_correct01.classname, test_result01.classname) self.assertEqual(result_correct01.is_comment, test_result01.is_comment) # FIXME: this fails... maybe because I don't parse comments as children correctly??? test_result02 = cfg.find_children(linespec) self.assertEqual(result_correct02, test_result02)
def Modify_Conf(): parse = CiscoConfParse('cat.txt') #特定のI/FのVLAN番号を変更する #例:10、12番ポートのVLAN番号を変更する for i in range(25): if (i == 10): for intf in parse.find_objects(r'^interface GigabitEthernet0/' + str(i)): if (intf.has_child_with(r' switchport access vlan')): intf.delete_children_matching(r' switchport access vlan') parse.insert_after(r'^interface GigabitEthernet0/' + str(i), insertstr=' switchport access vlan 999', exactmatch=False, ignore_ws=False, atomic=False) parse.commit() elif (i == 12): for intf in parse.find_objects(r'^interface GigabitEthernet0/' + str(i)): if (intf.has_child_with(r' switchport access vlan')): intf.delete_children_matching(r' switchport access vlan') parse.insert_after(r'^interface GigabitEthernet0/' + str(i), insertstr=' switchport access vlan 999', exactmatch=False, ignore_ws=False, atomic=False) parse.commit() #新規ファイルに書き込み parse.save_as('cat2.txt')
def testValues_insert_after_nonatomic_02(self): """Negative test. We expect insert_after(atomic=False) to miss any children added like this at some point in the future I might fix insert_after so it knows how to correctly parse children""" result_correct = ['interface GigabitEthernet4/1', #' shutdown', <--- Intentionally commented out ' switchport', ' switchport access vlan 100', ' switchport voice vlan 150', ' power inline static max 7000', ] linespec = 'interface GigabitEthernet4/1' cfg = CiscoConfParse(self.c01, factory=False) cfg.insert_after(linespec, ' shutdown', exactmatch=True, atomic=False) test_result = cfg.find_children(linespec) self.assertEqual(result_correct, test_result)
def testValues_insert_after_atomic_01(self): """We expect insert_after(atomic=True) to correctly parse children""" ## See also -> testValues_insert_after_nonatomic_02() result_correct = [ 'interface GigabitEthernet4/1', ' shutdown', ' switchport', ' switchport access vlan 100', ' switchport voice vlan 150', ' power inline static max 7000', ] linespec = 'interface GigabitEthernet4/1' cfg = CiscoConfParse(self.c01, factory=False) cfg.insert_after(linespec, ' shutdown', exactmatch=True, atomic=True) test_result = cfg.find_children(linespec) self.assertEqual(result_correct, test_result)
def testValues_insert_after_nonatomic_01(self): inputs = ['interface GigabitEthernet4/1', 'interface GigabitEthernet4/2', 'interface GigabitEthernet4/3', 'interface GigabitEthernet4/4', 'interface GigabitEthernet4/5', 'interface GigabitEthernet4/6', 'interface GigabitEthernet4/7', 'interface GigabitEthernet4/8', ] cfg = CiscoConfParse(self.c01, factory=False) for idx, linespec in enumerate(inputs): test_result = cfg.insert_after(linespec, ' shutdown', exactmatch=True, atomic=False) result_correct = [inputs[idx]] self.assertEqual(result_correct, test_result)
def standardize_configs(ip, chan): print "Downloading running configuration" output = send_command("enable", "!Tmgmt", "skip", "sh run", read=True, chan=chan) # Captures running config capture = re.findall(r"!\r\nver.*end", output, re.S).pop() # Parses running config print "Parsing configuraion" output = CiscoConfParse(capture.splitlines()) # Corrects DNS Setting dns = output.find_lines(r"ip dns server-address.*") output.replace_lines(r"ip dns server-address.*", r"ip dns server-address 10.210.1.214 10.220.1.200") print ("Correcting dns entry") send_command( "no {0}".format(dns.pop()), "ip dns server-address 10.210.1.214 10.220.1.200", configure=True, chan=chan ) # Enables IGMP Snooping globally output.insert_after(r"hostname", r"ip multicast active") print ('Enabling "ip multicast"') send_command("ip multicast active", configure=True, chan=chan) # print 'Searching for interfaces with dhcp helper' # virtual_interfaces = output.find_objects_w_child(r'interface ve.*', r'\s+ip\s+helper.*',) # for intf in virtual_interfaces: # interface = intf.text # print interface # has_dhcp_helper = intf.has_child_with(r'ip helper.*') # for line in intf.all_children: # if 'ip address' in line.text: # address = line.text # print address # if 'helper-address' in line.text: # dhcp = line.text # print dhcp # if has_dhcp_helper: # writer.writerow((ip, interface, address, dhcp)) # # Iterates through interfaces and cleans up misconfigurations for interface in output.find_objects(r"^interface.+"): has_loop_detection = interface.has_child_with(r"loop-detection") has_bpdu_guard = interface.has_child_with(r"stp-bpdu-guard") has_root_protection = interface.has_child_with(r"spanning-tree\sroot-protect") has_no_flow_control = interface.has_child_with(r"no\sflow-control") is_layer3_intf = (interface.has_child_with(r"ip\s+add")) or ("interface ve.*" in interface.text) # Temporarily disabled # Remove loop-detection misconfiguration if has_loop_detection and has_bpdu_guard: interface.delete_children_matching("loop-detection") print ('Removing "loop-detection" from {0}'.format(interface.text)) send_command(interface.text, "no loop-detection", configure=True) # Remove spanning-tree root-protect misconfiguration if has_root_protection: interface.delete_children_matching(r"spanning-tree\sroot-protect") print ('Removing "spanning-tree root-protect" from {0}'.format(interface.text)) send_command(interface.text, "no spanning-tree root", configure=True) # Adds IGMP snooping and QoS to Layer 3 interfaces if is_layer3_intf and not ("loopback" in interface.text or "management" in interface.text): interface.append_to_family(r" trust dscp") print ('Adding "trust dscp" to {0}'.format(interface.text)) send_command(interface.text, "trust dscp", configure=True, chan=chan) interface.append_to_family(r" ip igmp version 2") print ('Adding "ip igmp version 2" to {0}'.format(interface.text)) send_command(interface.text, "ip igmp version 2", configure=True, chan=chan) # enables flow-control if has_no_flow_control: interface.delete_children_matching(r"no\sflow-control.+") print ('Enabling "flow-control" on {0}'.format(interface.text)) send_command(interface.text, "flow-control", configure=True, chan=chan) return output
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