def testValues_IOSIntfLine_find_objects_factory_02(self):
        """test whether find_objects() returns correct IOSIntfLine objects and tests IOSIntfLine methods"""
        with patch('__main__.IOSIntfLine') as mock:
            # the mock pretends to be an IOSCfgLine so we can test against it
            result_correct01 = mock
            result_correct01.linenum = 12
            result_correct01.text = 'interface Serial 2/0'
            result_correct01.classname = 'IOSIntfLine'
            result_correct01.ipv4_addr_object = IPv4Network('1.1.1.1/30')

            result_correct02 = self.c01_insert_serial_replace

            cfg = CiscoConfParse(self.c01, factory=True)
            # Insert a line above the IOSIntfLine object
            cfg.insert_before('interface Serial 1/0', 'default interface Serial 1/0')
            # Replace text in the IOSIntfLine object
            cfg.replace_lines('interface Serial 1/0', 'interface Serial 2/0', exactmatch=False)

            test_result01 = cfg.find_objects('^interface Serial 2/0')[0]
            test_result02 = cfg.ioscfg

            # Check attributes of the IOSIntfLine object
            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.ipv4_addr_object, 
                test_result01.ipv4_addr_object)

            # Ensure the text configs are exactly what we wanted
            self.assertEqual(result_correct02, test_result02)
 def testValues_replace_lines_03(self):
     for config, args, result_correct in self.replace_lines_Values03:
         cfg = CiscoConfParse(config)
         test_result = cfg.replace_lines(**args)
         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 testValues_replace_lines_01(self):
     # We have to parse multiple times because of replacements
     for config, args, result_correct in self.replace_lines_Values01:
         cfg = CiscoConfParse(config)
         test_result = cfg.replace_lines(**args)
         self.assertEqual(result_correct, test_result)
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