Exemplo n.º 1
0
    def parse_running_config(self, devices):
        """ Parsing running config """

        output = devices.execute('show running-config')
        config = Config(output)
        config.tree()

        #  Storing running configuration to use later
        self.config_output = config.config
Exemplo n.º 2
0
 def get_current_config(self):
     #print("Getting Current Config")
     testbed_filename = "testbeds/" + self.options.testbed
     testbed = load(testbed_filename)
     TR = testbed.devices[self.options.hostname]
     TR.connect(log_stdout=False)
     output = TR.execute('show running-config')
     self.current_config = Config(output)
     self.current_config.tree()
Exemplo n.º 3
0
def get_config_dict(config):
    """ Cast config to Configuration dict

        Args:
            config ('str'): config string
        Returns:
            Configuration dict
    """
    cfg = Config(config)
    cfg.tree()
    return cfg.config
def main():
    argument_spec = dict(
        compare=dict(type='dict', required=False),
        sendonly=dict(type='bool', default=False, required=False),
    )
    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    if not PY3:
        module.fail_json(msg="pyATS/Genie requires Python 3")

    if not HAS_GENIE:
        module.fail_json(msg="Genie not found Run 'pip install genie'")

    if not HAS_PYATS:
        module.fail_json(msg="pyATS not found. Run 'pip install pyats'")

    if module.check_mode and not module.params['command'].startswith('show'):
        module.fail_json(
            msg='Only show commands are supported when using check_mode, not '
            'executing %s' % module.params['command'])

    warnings = list()
    result = {'changed': False, 'warnings': warnings}

    connection = Connection(module._socket_path)

    response = ''
    try:
        response = connection.get(command='show run')
    except ConnectionError as exc:
        module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))

    config = Config(response)
    config.tree()

    if module.params['compare']:
        diff = Diff(config.config, module.params['compare'])
        diff.findDiff()
    else:
        diff = None

    try:
        result['json'] = module.from_json(response)
    except ValueError:
        pass

    result.update({
        'stdout': response,
        'structured': config.config,
        'diff': "{0}".format(diff)
    })

    module.exit_json(**result)
Exemplo n.º 5
0
    def genie_config_diff(self, output1, output2, mode=None, exclude=None):
        if not PY3:
            raise AnsibleFilterError("Genie requires Python 3")

        if not HAS_GENIE:
            raise AnsibleFilterError(
                "Genie not found. Run 'pip install genie'")

        if not HAS_PYATS:
            raise AnsibleFilterError(
                "pyATS not found. Run 'pip install pyats'")

        supported_mode = ['add', 'remove', 'modified', None]
        if mode not in supported_mode:
            raise AnsibleFilterError(
                "Mode '%s' is not supported. Specify %s." %
                (mode, supported_mode))

        config1 = Config(output1)
        config1.tree()
        dict1 = config1.config

        config2 = Config(output2)
        config2.tree()
        dict2 = config2.config

        dd = Diff(dict1, dict2, mode=mode, exclude=exclude)
        dd.findDiff()
        diff = str(dd)
        diff_list = diff.split('\n')

        return diff_list
Exemplo n.º 6
0
def main():
    nr = InitNornir(config_file="config.yaml")
    #Filter devices to run against
    nr = nr.filter(F(groups__contains="iosv"))
    print('Running postvalidaiton.py against the following Nornir inventory hosts:', nr.inventory.hosts.keys())
    # Ask for credentials at runtime instead of storing.
    nornir_set_creds(nr)

    print("Collecting running configurations and operational values\n")
    resultconf = nr.run(task=collect_configs)
    resultgetters = nr.run(task=collect_getters)
    #import ipdb; ipdb.set_trace()

    #Loop through napalm getters and output current running version.
    prYellow('Current IOS Running Versions:')
    for host in resultgetters:
        print(host, '>>', resultgetters[host][1].result['facts']['os_version'])

    #Perform a Diff between the pre and post nornir getter files we saved.
    for host in nr.inventory.hosts:
        #dont try to open files or compare if a host failed collection
        if host in resultconf.failed_hosts or host in resultgetters.failed_hosts:
            print('!', host, 'failed collection and Op State will not be compared\n')
            #TODO: log netmiko/nornir error to file. otherwise it should exist in nornir.log.
            continue
        else:
            #load facts in hosts pre and post folder and store to var. since were not using pyats native learn objects we must loop through files
            prGreen("vvv --- " + host + " --- Begin Comparison between Pre Upgrade and Post Upgrade operational values vvv")
            for filename in os.listdir(initial_facts_dir+host):
                with open(initial_facts_dir+host+'/'+filename, 'r') as f:
                    initialstate = json.load(f)
                with open(facts_dir+host+'/'+filename, 'r') as f:
                    poststate = json.load(f)
                compare = Diff(initialstate, poststate)
                compare.findDiff()
                print('#', filename, '#\n', compare)
            prGreen("^^^ --- " + host + " --- End Comparison between Pre Upgrade and Post Upgrade operational values ^^^\n")


            prGreen("vvv --- " + host + " --- Begin Comparison between Pre Upgrade and Post Upgrade configurations vvv")
            with open(initial_config_dir+host+'-running.cfg', 'r') as f:
                cfg = f.read()
            initialconfig = Config(cfg)
            initialconfig.tree()
            with open(config_dir+host+'-running.cfg', 'r') as f:
                cfg = f.read()
            postconfig = Config(cfg)
            postconfig.tree()
            compare = Diff(initialconfig, postconfig)
            compare.findDiff()
            prCyan("# " + os.path.basename(f.name) + " #")
            print(compare)
            #ipdb.set_trace()
            prGreen("^^^ --- " + host + " --- End Comparison between Pre Upgrade and Post Upgrade configurations ^^^\n")
Exemplo n.º 7
0
    def get_golden_config(self):
        #print("Reading Golden Config")
        golden_config_filename = "configs/" + self.options.hostname + "-golden.conf"

        if not os.path.isfile(golden_config_filename):
            testbed_filename = "testbeds/" + self.options.testbed
            testbed = load(testbed_filename)
            TR = testbed.devices[self.options.hostname]
            TR.connect(log_stdout=False)
            output = TR.execute('show running-config')
            with open(golden_config_filename, 'w') as f:
                f.write(output)
            self.status = self.STATUS_WARNING
            self.set_message("Golden Config did not exist. Created for : {}".format(self.options.hostname))
        else:
            with open(golden_config_filename, 'r') as f:
                output=f.read()
            self.golden_config=Config(output)
            self.golden_config.tree()

        return()
Exemplo n.º 8
0
 def setup(self, testbed):
     """Parse config archive from the testbed devices."""
     self.configs = {}
     for device_name, device in testbed.devices.items():
         # Only attempt to learn details on supported network operation systems
         if device.os in ("ios", "iosxe", "iosxr", "nxos"):
             logger.info(
                 f"{device_name} connected status: {device.connected}")
             logger.info(f"Learning configs for {device_name}")
             startup = device.execute("show startup")
             startup_config = Config(startup)
             startup_config.tree()
             self.configs[device_name] = {}
             self.configs[device_name]['startup'] = startup_config.config
             running = device.execute("show running")
             running_config = Config(running)
             running_config.tree()
             self.configs[device_name]['running'] = running_config.config
Exemplo n.º 9
0
def diff_configuration(device, config1, config2):
    """ Show difference between two configurations
        Args:
            config1 ('str'): Configuration one
            config2 ('str'): Configuration two
        Raise:
            None
        Returns:
            Diff
    """
    configObject1 = Config(config1)
    configObject2 = Config(config2)
    configObject1.tree()
    configObject2.tree()

    diff = Diff(configObject1.config, configObject2.config)

    diff.findDiff()

    return diff
Exemplo n.º 10
0
#!/usr/local/bin/python3

from genie.utils.config import Config
from genie.utils.diff import Diff
from genie.testbed import load

tb = load('my_testbed.yaml')

for device_name, device in tb.devices.items():
    device.connect()
    startup = device.execute("show startup")
    startup_config = Config(startup)
    startup_config.tree()

    running = device.execute("show running")
    running_config = Config(running)
    running_config.tree()

    diff = Diff(running_config, startup_config)
    diff.findDiff()
    print(diff)
Exemplo n.º 11
0
 def _profile_config(self, device):
     device_handle = self._search_device(device)
     config = Config(device_handle.execute('show running-config'))
     config.tree()
     return config
Exemplo n.º 12
0
class ConfigChecker:
    STATUS_OK = 0
    STATUS_WARNING = 1
    STATUS_CRITICAL = 2
    STATUS_UNKNOWN = 3

    def __init__(self):
        self.status = None
        self.messages = []
        self.perfdata = []
        self.options = None
        self.golden_config = None
        self.current_config = None

    def run(self):
        self.parse_options()

        self.get_golden_config()

        if self.status == None:
            self.get_current_config()
            self.compare_configs()

        self.print_output()

        return self.status

    def parse_options(self):
        parser = argparse.ArgumentParser(
            description="Monitoring check plugin to check network configs for differences against golden configs."
                        "The code uses Cisco PyATS to connect to the device and check for differences."
                        "In order for the plugin to be used than a golden config file is necessary."
                        "You can do this using the script create-golden-config.py in the same repository."
                        "Future versions of this plugin will create the golden configs if they are not found on disk."
                        "If the current config found to be the same as the golden config, an OK status is returned"
                        "If the current config found to be different than the golden config, a CRITICAL status is returned."
                        "If the golden config is not present on disk, the current config is saved as the golden config and a WARNING status is returned. That status will surely return to OK when the plugin is run again as the golden config will be found and probably no differences will be found."
                        "UNKNOWN is returned if there is a failure."
        )

        parser.add_argument("-H", "--hostname",
                            type=str, help="Hostname defined in the testbed")
        parser.add_argument("-t", "--testbed",
                            type=str, help="PyATS Testbed file")

        self.options = parser.parse_args()

        if not self.are_options_valid():
            print("Run with --help for usage information")
            print("")
            exit(0)

        if (not os.path.isdir("testbeds")) or (not os.path.isdir("configs")):
            print("directories testbeds or configs not present under current dir")
            print("")
            exit(0)


    def are_options_valid(self):
        if not self.options.hostname:
            print("You must specify a hostname")
            return False
        if not self.options.testbed:
            print("You must specify a testbed")
            return False
        return True

    def print_output(self):
        """ Prints the final output (in Nagios plugin format if self.status is set)
        :return:
        """
        output = ""
        if self.status == self.STATUS_OK:
            output = "OK"
        elif self.status == self.STATUS_WARNING:
            output = "Warning"
        elif self.status == self.STATUS_CRITICAL:
            output = "Critical"
        elif self.status == self.STATUS_UNKNOWN:
            output = "Unknown"

        if self.messages:
            if len(output):
                output += " - "
            # Join messages like sentences. Correct those messages which already ended with a period or a newline.
            output += ". ".join(self.messages).replace(".. ", ".").replace("\n. ", "\n")

        if self.perfdata:
            if len(output):
                output += " | "
            output += " ".join(self.perfdata)

        print(output)

    def get_golden_config(self):
        #print("Reading Golden Config")
        golden_config_filename = "configs/" + self.options.hostname + "-golden.conf"

        if not os.path.isfile(golden_config_filename):
            testbed_filename = "testbeds/" + self.options.testbed
            testbed = load(testbed_filename)
            TR = testbed.devices[self.options.hostname]
            TR.connect(log_stdout=False)
            output = TR.execute('show running-config')
            with open(golden_config_filename, 'w') as f:
                f.write(output)
            self.status = self.STATUS_WARNING
            self.set_message("Golden Config did not exist. Created for : {}".format(self.options.hostname))
        else:
            with open(golden_config_filename, 'r') as f:
                output=f.read()
            self.golden_config=Config(output)
            self.golden_config.tree()

        return()

    def get_current_config(self):
        #print("Getting Current Config")
        testbed_filename = "testbeds/" + self.options.testbed
        testbed = load(testbed_filename)
        TR = testbed.devices[self.options.hostname]
        TR.connect(log_stdout=False)
        output = TR.execute('show running-config')
        self.current_config = Config(output)
        self.current_config.tree()

    def compare_configs(self):
        dd = Diff(self.golden_config, self.current_config)
        dd.findDiff()
        #import ipdb; ipdb.set_trace()

        if len(str(dd)) == 0 :
            self.status = self.STATUS_OK
            self.set_message("No changes in Running Config")
        else:
            self.status = self.STATUS_CRITICAL
            self.set_message("Running Config has changed: {}".format(dd))

    def add_status(self, status):
        """ Set the status only if it is more severe than the present status
        The order of severity being OK, WARNING, CRITICAL, UNKNOWN
        :param status: Status to set, one of the self.STATUS_xxx constants
        :return: The current status
        """
        if self.status is None or status > self.status:
            self.status = status

    def set_message(self, message):
        self.messages = [message]

    def add_message(self, message):
        self.messages.append(message)

    def add_perfdata(self, perfitem):
        self.perfdata.append(perfitem)
Exemplo n.º 13
0
    def learn(self, vrf='all', interface=''):
        '''Learn Nd object'''

        # new Nd structure
        # Place holder to make it more readable
        #  interfaces
        #     interface
        #     router_advertisement
        #         interval
        #         lifetime
        #         suppress
        #     neighbors
        #         neighbor
        #             ip
        #             link_layer_address
        #             neighbor_state
        #             age
        #             origin
        #             is_router             N/A

        if interface:
            src_nd = '[interfaces][{}]'.format(interface)
        else:
            src_nd = '[interfaces][(?P<interface>.*)]'

        dest_nd = 'info' + src_nd

        self.add_leaf(cmd=ShowIpv6Neighbors,
                      src=src_nd + '[interface]',
                      dest=dest_nd + '[interface]',
                      interface=interface,
                      vrf=vrf)
        self.make()

        if interface:
            src_rd = '[{}][ipv6]'.format(interface)
        else:
            src_rd = '[(?P<interface>.*)][ipv6]'

        dest_rd = dest_nd + '[router_advertisement]'
        req_dict = {'nd_adv_duration': 'interval', 'nd_router_adv': 'lifetime'}

        for src, dest in req_dict.items():
            self.add_leaf(cmd=ShowIpv6VrfAllInterface,
                          src=src_rd + '[{}]'.format(src),
                          dest=dest_rd + '[{}]'.format(dest),
                          interface=interface,
                          vrf=vrf)

        src_nd_neighbor = src_nd + '[neighbors][(?P<neighbor>.*)]'
        dest_nd_neighbor = 'info' + src_nd_neighbor
        req_key = [
            'ip', 'link_layer_address', 'neighbor_state', 'age', 'origin'
        ]
        for key in req_key:
            self.add_leaf(cmd=ShowIpv6NeighborsDetail,
                          src=src_nd_neighbor + '[{}]'.format(key),
                          dest=dest_nd_neighbor + '[{}]'.format(key))
        self.make()

        # Get nd suppress by executing 'show running-config interface'
        if interface:
            show_run_cmd = 'show running-config interface {}'.format(interface)
        else:
            show_run_cmd = 'show running-config interface'

        show_run = self.device.execute(show_run_cmd)
        cfg = Config(show_run)
        cfg.tree()
        config_dict = cfg.config

        if config_dict and hasattr(self, 'info'):
            for intf, intf_dict in self.info['interfaces'].items():
                key = 'interface {}'.format(intf)
                if key in config_dict and 'ipv6 nd suppress-ra' in config_dict[
                        key]:
                    intf_dict.setdefault('router_advertisement',
                                         {}).update({'suppress': True})

        self.make(final_call=True)