def testVal_object_group_network_01(): """Test object group network results""" conf = [ '!', 'name 1.1.2.20 loghost01', '!', 'object-group network INSIDE_addrs', ' network-object host loghost01', ' network-object host 1.1.2.1', ' network-object 1.1.2.2 255.255.255.255', ' network-object 1.1.2.0 255.255.255.0', '!', ] cfg_factory = CiscoConfParse(conf, factory=True, syntax='asa') obj = cfg_factory.find_objects(r'object-group\snetwork')[0] result_correct_01 = [ IPv4Obj('1.1.2.20/32'), IPv4Obj('1.1.2.1/32'), IPv4Obj('1.1.2.2/32'), IPv4Obj('1.1.2.0/24') ] result_correct_02 = [ '1.1.2.20', '1.1.2.1', '1.1.2.2', '1.1.2.0/255.255.255.0' ] # Ensure obj.name is set correctly assert obj.name == "INSIDE_addrs" assert obj.networks == result_correct_01 assert obj.network_strings == result_correct_02 ## Test obj.networks again to test the result_cache assert obj.networks == result_correct_01
def testValues_sync_diff_07(): """Test diffs with remove_lines=False""" ## config_01 is the starting point config_01 = [ '!', 'vlan 51', ' state active', 'vlan 53', '!', 'vtp mode transparent', ] required_config = [ '!', 'vlan 51', ' name SOME-VLAN', ' state active', 'vlan 52', ' name BLAH', ' state active', '!', ] result_correct = [ 'vlan 51', ' name SOME-VLAN', 'vlan 52', ' name BLAH', ' state active' ] linespec = r'vlan\s+\S+|name\s+\S+|state.+' parse = CiscoConfParse(config_01) test_result = parse.sync_diff(required_config, linespec, linespec, remove_lines=False) assert result_correct == test_result
def testValues_find_objects_replace_01(): """test whether find_objects we can correctly replace object values using native IOSCfgLine object methods""" config01 = [ '!', 'boot system flash slot0:c2600-adventerprisek9-mz.124-21a.bin', 'boot system flash bootflash:c2600-adventerprisek9-mz.124-21a.bin', '!', 'interface Ethernet0/0', ' ip address 172.16.1.253 255.255.255.0', '!', 'ip route 0.0.0.0 0.0.0.0 172.16.1.254', '!', 'end', ] result_correct = [ '!', '! old boot image flash slot0:c2600-adventerprisek9-mz.124-21a.bin', '! old boot image flash bootflash:c2600-adventerprisek9-mz.124-21a.bin', '!', 'interface Ethernet0/0', ' ip address 172.16.1.253 255.255.255.0', '!', 'ip route 0.0.0.0 0.0.0.0 172.16.1.254', '!', 'end', ] cfg = CiscoConfParse(config01) for obj in cfg.find_objects('boot system'): obj.replace('boot system', '! old boot image') test_result = cfg.ioscfg assert result_correct == test_result
def testValues_sync_diff_06(): """Test diffs against double-spacing for children (such as NXOS)""" ## config_01 is the starting point config_01 = [ '!', 'vlan 51', ' state active', 'vlan 53', '!', ] required_config = [ '!', 'vlan 51', ' name SOME-VLAN', ' state active', 'vlan 52', ' name BLAH', ' state active', '!', ] result_correct = [ 'no vlan 53', 'vlan 51', ' name SOME-VLAN', 'vlan 52', ' name BLAH', ' state active' ] linespec = r'vlan\s+\S+|name\s+\S+|state.+' parse = CiscoConfParse(config_01) test_result = parse.sync_diff(required_config, linespec, linespec) assert result_correct == test_result
def testValues_find_all_chidren02(): """Ensure we don't need a comment at the end of a """ """ parent / child block to identify the end of the family""" CONFIG = [ 'thing1', ' foo', ' bar', ' 100', ' 200', ' 300', ' 400', 'thing2', ] RESULT_CORRECT = [ 'thing1', ' foo', ' bar', ' 100', ' 200', ' 300', ' 400', ] cfg = CiscoConfParse(CONFIG) test_result = cfg.find_all_children('^thing1') assert RESULT_CORRECT == test_result
def testValues_ignore_ws(): ## test find_lines with ignore_ws flag config = ['set snmp community read-only myreadonlystring'] result_correct = config cfg = CiscoConfParse(config) test_result = cfg.find_lines( 'set snmp community read-only myreadonlystring', ignore_ws=True) assert result_correct == test_result
def testValues_negative_ignore_ws(): """test find_lines WITHOUT ignore_ws""" config = ['set snmp community read-only myreadonlystring'] result_correct = list() cfg = CiscoConfParse(config) test_result = cfg.find_lines( 'set snmp community read-only myreadonlystring', ignore_ws=False) assert result_correct == test_result
def testValues_banner_delimiter_04(): # Test multiple banner delimiters on different lines CONFIG = ['!', 'banner motd ^', ' trivial banner here ^^', 'end'] parse = CiscoConfParse(CONFIG) bannerobj = parse.find_objects('^banner')[0] BANNER_LINE_NUMBER = 1 assert bannerobj.linenum == BANNER_LINE_NUMBER for obj in bannerobj.children: assert obj.parent.linenum == BANNER_LINE_NUMBER
def testValues_sync_diff_04(): """Test diffs against double-spacing for children (such as NXOS)""" ## config_01 is the starting point config_01 = [ '!', 'interface GigabitEthernet 1/5', ' ip address 1.1.1.2 255.255.255.0', ' standby 5 ip 1.1.1.1', ' standby 5 preempt', '!' ] required_config = [ '!', 'interface GigabitEthernet 1/5', ' switchport', ' switchport mode access', ' switchport access vlan 5', ' switchport nonegotiate', '!', 'interface Vlan5', ' no shutdown', ' ip address 1.1.1.2 255.255.255.0', ' standby 5 ip 1.1.1.1', ' standby 5 preempt', '!', ] result_correct = [ 'interface GigabitEthernet 1/5', ' no ip address 1.1.1.2 255.255.255.0', ' no standby 5 ip 1.1.1.1', ' no standby 5 preempt', 'interface GigabitEthernet 1/5', ' switchport', ' switchport mode access', ' switchport access vlan 5', ' switchport nonegotiate', 'interface Vlan5', ' no shutdown', ' ip address 1.1.1.2 255.255.255.0', ' standby 5 ip 1.1.1.1', ' standby 5 preempt', ] linespec = r'' parse = CiscoConfParse(config_01) test_result = parse.sync_diff(required_config, linespec, linespec) assert result_correct == test_result
def parse_j01_factory(request): """Preparsed j01 with factory option""" parse_j01_factory = CiscoConfParse(j01, syntax='junos', comment='#!', factory=True) yield parse_j01_factory
def parse_j01(request): """Preparsed j01""" parse_j01 = CiscoConfParse(j01, syntax='junos', comment='#!', factory=False) yield parse_j01
def testValues_banner_delimiter_05(): # Test multiple banners CONFIG = [ '!', 'banner motd ^', ' trivial banner1 here ^', 'banner exec ^', ' trivial banner2 here ^', 'end' ] parse = CiscoConfParse(CONFIG) bannerobj = parse.find_objects('^banner\smotd')[0] BANNER_LINE_NUMBER = 1 assert bannerobj.linenum == BANNER_LINE_NUMBER for obj in bannerobj.children: assert obj.parent.linenum == BANNER_LINE_NUMBER bannerobj = parse.find_objects('^banner\sexec')[0] BANNER_LINE_NUMBER = 3 assert bannerobj.linenum == BANNER_LINE_NUMBER for obj in bannerobj.children: assert obj.parent.linenum == BANNER_LINE_NUMBER
def testVal_object_group_service_01(): ## This can only be configured as protocol object-group conf = [ '!', 'object-group service APP01_svc', ' service-object tcp destination smtp', ' service-object tcp destination https', '!', ] cfg_factory = CiscoConfParse(conf, factory=True, syntax='asa') obj = cfg_factory.find_objects(r'object-group\sservice')[0] result_correct = [ L4Object(protocol='tcp', port_spec='eq 25', syntax='asa'), L4Object(protocol='tcp', port_spec='eq 443', syntax='asa') ] assert (obj.name == 'APP01_svc') assert (obj.ports == result_correct) assert (obj.L4Objects_are_directional is True) assert (obj.protocol_type == '')
def testVal_object_group_service_03(): ## This can only be configured as an object group after a host / network conf = [ '!', 'object-group service APP03_svc tcp-udp', ' port-object eq domain', '!', ] cfg_factory = CiscoConfParse(conf, factory=True, syntax='asa') obj = cfg_factory.find_objects(r'object-group\sservice')[0] ## Test whether the proper port objects are returned results_correct = [ L4Object(port_spec='eq 53', protocol='tcp', syntax='asa'), L4Object(port_spec='eq 53', protocol='udp', syntax='asa') ] assert (obj.name == 'APP03_svc') assert (obj.ports == results_correct) assert (obj.L4Objects_are_directional is False) assert (obj.protocol_type == 'tcp-udp')
def testVal_ipv4_addr(): conf = [ '!', 'interface Ethernet0/0', ' nameif OUTSIDE', ' ip address 198.101.172.106 255.255.255.128 standby 198.101.172.107', '!', 'interface Ethernet0/1', ' nameif INSIDE', ' ip address 192.0.2.254 255.255.255.0', '!', ] cfg_factory = CiscoConfParse(conf, factory=True, syntax='asa') obj = cfg_factory.find_objects(r'^interface\sEthernet0\/0$')[0] # Ensure obj.ipv4_addr is set correctly assert obj.ipv4_addr == '198.101.172.106' assert obj.ipv4_standby_addr == '198.101.172.107' obj = cfg_factory.find_objects(r'^interface\sEthernet0\/1$')[0] assert obj.ipv4_addr == '192.0.2.254'
def testValues_find_objects_delete_01(): """Test whether IOSCfgLine.delete() recurses through children correctly""" config = [ '!', 'interface Serial1/0', ' encapsulation ppp', ' ip address 1.1.1.1 255.255.255.252', ' no ip proxy-arp', '!', 'interface Serial1/1', ' encapsulation ppp', ' ip address 1.1.1.5 255.255.255.252', '!', ] result_correct = ['!', '!', '!'] cfg = CiscoConfParse(config) for intf in cfg.find_objects(r'^interface'): # Delete all the interface objects intf.delete(recurse=True) # recurse=True is the default test_result = cfg.ioscfg assert result_correct == test_result
def testVal_object_group_service_02(): ## This can only be configured as an object group after a host / network conf = [ '!', 'object-group service APP02_svc tcp', ' port-object eq smtp', ' port-object eq https', ' port-object range 8080 8081', '!', ] cfg_factory = CiscoConfParse(conf, factory=True, syntax='asa') obj = cfg_factory.find_objects(r'object-group\sservice')[0] result_correct = [ L4Object(protocol='tcp', port_spec='eq 25', syntax='asa'), L4Object(protocol='tcp', port_spec='eq 443', syntax='asa'), L4Object(protocol='tcp', port_spec='range 8080 8081', syntax='asa') ] assert (obj.name == 'APP02_svc') assert (obj.ports == result_correct) assert (obj.L4Objects_are_directional is False) assert (obj.protocol_type == 'tcp')
def testValues_sync_diff_09(): """Test diffs with explicit ignore_order=True""" ## config_01 is the starting point config_01 = [ '!', 'vlan 51', ' state active', 'vlan 53', '!', 'vtp mode transparent', ] required_config = [ '!', 'vtp mode transparent', 'vlan 51', ' name SOME-VLAN', ' state active', 'vlan 52', ' name BLAH', ' state active', '!', ] result_correct = [ 'no vlan 53', 'vlan 51', ' name SOME-VLAN', 'vlan 52', ' name BLAH', ' state active', ] linespec = r'vlan\s+\S+|name\s+\S+|state.+|vtp' parse = CiscoConfParse(config_01) test_result = parse.sync_diff(required_config, linespec, linespec, ignore_order=True) assert result_correct == test_result
def testValues_sync_diff_05(): ## config_01 is the starting point config_01 = ['!', 'vlan 51', ' state active', 'vlan 53', '!'] required_config = [ '!', 'vlan 51', ' name SOME-VLAN', ' state active', 'vlan 52', ' name BLAH', ' state active', '!', ] result_correct = [ 'no vlan 53', 'vlan 51', ' name SOME-VLAN', 'vlan 52', ' name BLAH', ' state active' ] linespec = r'vlan\s+\S+|name\s+\S+|state.+' parse = CiscoConfParse(config_01) test_result = parse.sync_diff(required_config, linespec, linespec) assert result_correct == test_result
def testValues_banner_delete_01(): # Ensure multiline banners are correctly deleted CONFIG = [ '!', 'banner motd ^', ' trivial banner1 here ^', 'interface GigabitEthernet0/0', ' ip address 192.0.2.1 255.255.255.0', 'banner exec ^', ' trivial banner2 here ^', 'end' ] parse = CiscoConfParse(CONFIG) for obj in parse.find_objects('^banner'): obj.delete() parse.commit() assert parse.find_objects('^banner') == []
def testValues_banner_delete_02(): # Ensure multiline banners are correctly deleted # # Check for Github issue #37 CONFIG = [ '!', 'interface GigabitEthernet0/0', ' ip address 192.0.2.1 255.255.255.0', 'banner motd ^', ' trivial banner1 here ^', 'interface GigabitEthernet0/1', ' ip address 192.0.2.1 255.255.255.0', 'banner exec ^', ' trivial banner2 here ^', 'end' ] parse = CiscoConfParse(CONFIG) for obj in parse.find_objects('^banner'): obj.delete() parse.commit() assert parse.find_objects('^banner') == [] # Github issue #37 assigned Gi0/1's child to Gi0/0 after deleting # the banner motd line... for obj in parse.find_objects('^interface'): assert len(obj.children) == 1
def parse_a02(request): """Preparsed a02""" parse_a02_factory = CiscoConfParse(a02, syntax='asa', factory=False) yield parse_a02_factory
def parse_c03_factory(request): """Preparsed c01 with factory option""" parse_c03_factory = CiscoConfParse(c03, factory=True) yield parse_c03_factory
interface Vlan16 ip address 10.0.16.1 255.255.255.0 no ip proxy-arp ! interface Vlan20 ip address 10.0.20.1 255.255.255.0 no ip proxy-arp ! """ ## Note, I don't pretend that this will be useful, it's a conceptual demo ## ## OUTPUT: ## ## GigabitEthernet 0/1 10.0.20.1 255.255.255.0 ## GigabitEthernet 0/2.12 10.0.12.1 255.255.255.0 ## GigabitEthernet 0/2.16 10.0.16.1 255.255.255.0 parse = CiscoConfParse(CONFIG.splitlines()) vlans = vlan_intf_dict(parse) intfs, access = switchport_vlans(parse) for intf in sorted(intfs): vlan_list = intfs.get(intf) for vlan in vlan_list: addr = vlans.get(vlan, 'ERROR') if access.get(intf, False): print(("{0} {1}".format(intf, addr))) else: print(("{0}.{1} {2}".format(intf, vlan, addr)))
def parse_a02_factory(request): """Preparsed a02 with factory option""" parse_a02_factory = CiscoConfParse(a02, syntax='asa', factory=True) yield parse_a02_factory
import sys import os THIS_DIR = os.path.dirname(__file__) sys.path.insert(0, os.path.join(os.path.abspath(THIS_DIR), "../nety/")) from nety import CiscoConfParse if sys.argv[1]=="1": parse = CiscoConfParse('../configs/sample_01.ios', syntax='ios', factory=False) for line in parse.objs: print(line) elif sys.argv[1]=="2": parse = CiscoConfParse('../configs/sample_01.ios', syntax='ios', factory=True) for line in parse.objs: print(line) elif sys.argv[1]=="3": parse = CiscoConfParse('../configs/sample_01.iosxr', syntax='ios', factory=True) for line in parse.objs: print(line)
#!/usr/bin/env python from nety import CiscoConfParse parse = CiscoConfParse("../configs/sample_01.ios") # Return a list of all ATM interfaces and subinterfaces atm_intfs = parse.find_lines("^interface\sATM") # Return a list of all interfaces with a certain QOS policy qos_intfs = parse.find_parents_w_child("^interf", "service-policy") # Return a list of all active interfaces (i.e. not shutdown) active_intfs = parse.find_parents_wo_child("^interf", "shutdown")
from nety import CiscoConfParse ## this is not a valid test yet, because we don't detect parents of a line ## that is missing (i.e. 'no passive-interface Vlan500' below) config = [ '!', 'router ospf 102', ' ispf', ' passive-interface default', ' no passive-interface TenGigabitEthernet1/49', ' auto-cost reference-bandwidth 100000', '!', ] p = CiscoConfParse(config) required_lines = [ 'router ospf 102', ' ispf', ' passive-interface default', ' no passive-interface TenGigabitEthernet1/49', ' no passive-interface Vlan500', ' auto-cost reference-bandwidth 1000000' ] # lines matching linespec are enforced linespec = "router ospf 102|ispf|passive-interface.+?|auto-cost\sreference.+?" unconfspec = linespec diffs = p.req_cfgspec_excl_diff(linespec, unconfspec, required_lines) print(diffs)
def testParse_asa_as_ios(config_a02): """Test for Github issue #42 parse asa banner with ios syntax""" parse = CiscoConfParse(config_a02, syntax='ios', factory=False) assert not (parse is None)
def testParse_asa_as_asa(config_a02): parse = CiscoConfParse(config_a02, syntax='asa', factory=False) assert not (parse is None)