def fetch_interfaces(device_id=None): device = Device.objects.get(id=device_id) if device.environment == "LAB": return { "interfaces_fetched": False, "reason": "can only fetch production interfaces" } try: options = { "style": device.os_type, "sectional_overwrite": [], "sectional_overwrite_no_negate": [], "indent_adjust": [], "parent_allows_duplicate_child": [], "sectional_exiting": [], "full_text_sub": [], "per_line_sub": [], "idempotent_commands_blacklist": [], "idempotent_commands": [], "negation_default_when": [], "negation_negate_with": [], "ordering": [] } device_config = RouteSwitchConfig.objects.get(device=device) host = Host(hostname=device.name, os=device.os_type, hconfig_options=options) host.load_config_from(name=device_config.text, config_type="running", load_file=False) interfaces = host.running_config.get_children('startswith', 'interface') for item in interfaces: try: DeviceInterface.objects.get( device=device, name=f"{item.text.strip('interface ')}") except DeviceInterface.DoesNotExist: DeviceInterface.objects.create( device=device, name=f"{item.text.strip('interface ')}") return {"interfaces_fetched": True, "reason": "interfaces fetched"} except RouteSwitchConfig.DoesNotExist: return { "interfaces_fetched": False, "reason": "must fetch production config first" }
def test_unified_diff(options_ios): host = Host(hostname="test_host", os="ios", hconfig_options=options_ios) config_a = HConfig(host=host) config_b = HConfig(host=host) # deep differences config_a.add_children_deep(["a", "aa", "aaa", "aaaa"]) config_b.add_children_deep(["a", "aa", "aab", "aaba"]) # these children will be the same and should not appear in the diff config_a.add_children_deep(["b", "ba", "baa"]) config_b.add_children_deep(["b", "ba", "baa"]) # root level differences config_a.add_children_deep(["c", "ca"]) config_b.add_child("d") diff = list(config_a.unified_diff(config_b)) assert diff == [ "a", " aa", " - aaa", " - aaaa", " + aab", " + aaba", "- c", " - ca", "+ d", ]
def test_difference3(options_ios): host = Host(hostname="test_host", os="ios", hconfig_options=options_ios) rc = ["ip access-list extended test", " 10 a", " 20 b"] step = ["ip access-list extended test", " 10 a", " 20 b", " 30 c"] rc_hier = HConfig(host=host) rc_hier.load_from_string("\n".join(rc)) step_hier = HConfig(host=host) step_hier.load_from_string("\n".join(step)) difference = step_hier.difference(rc_hier) difference_children = list( c.cisco_style_text() for c in difference.all_children_sorted() ) assert difference_children == ["ip access-list extended test", " 30 c"]
def test_difference2(options_ios): host = Host(hostname="test_host", os="ios", hconfig_options=options_ios) rc = ["a", " a1", " a2", " a3", "b"] step = ["a", " a1", " a2", " a3", " a4", " a5", "b", "c", "d", " d1"] rc_hier = HConfig(host=host) rc_hier.load_from_string("\n".join(rc)) step_hier = HConfig(host=host) step_hier.load_from_string("\n".join(step)) difference = step_hier.difference(rc_hier) difference_children = list( c.cisco_style_text() for c in difference.all_children_sorted() ) assert len(difference_children) == 6
def test_issue104() -> None: running_config_raw = ("tacacs-server deadtime 3\n" "tacacs-server host 192.168.1.99 key 7 Test12345\n") generated_config_raw = ( "tacacs-server host 192.168.1.98 key 0 Test135 timeout 3\n" "tacacs-server host 192.168.100.98 key 0 test135 timeout 3\n") host = Host(hostname="test", os="nxos") running_config = HConfig(host=host) running_config.load_from_string(running_config_raw) generated_config = HConfig(host=host) generated_config.load_from_string(generated_config_raw) rem = running_config.config_to_get_to(generated_config) expected_rem_lines = { "no tacacs-server deadtime 3", "no tacacs-server host 192.168.1.99 key 7 Test12345", "tacacs-server host 192.168.1.98 key 0 Test135 timeout 3", "tacacs-server host 192.168.100.98 key 0 test135 timeout 3", } rem_lines = {line.cisco_style_text() for line in rem.all_children()} assert expected_rem_lines == rem_lines
def setup(self, options_ios): self.os = "ios" self.host_a = Host("example1.rtr", self.os, options_ios) self.host_b = Host("example2.rtr", self.os, options_ios)
def hier_host( task: Task, include_tags: list = None, exclude_tags: list = None, running_config: str = None, compiled_config: str = None, config_path: str = None, load_file: bool = False, **kwargs: Any, ) -> Result: """ hier_config task for nornir :param task: type object :param incude_tags: type list :param exclude_tags: type list :param running_config: type str :param compiled_config: type str :param config_path: type str :param load_file: type bool :returns: hier remediation object """ from netnir.constants import HIER_DIR from hier_config import Host import logging import os import yaml operating_system = task.host.data["os"] hier_options_file = "/".join([HIER_DIR, operating_system, "options.yml"]) hier_tags_file = "/".join([HIER_DIR, operating_system, "tags.yml"]) running_config = "/".join([config_path, task.host.name, running_config]) compiled_config = "/".join([config_path, task.host.name, compiled_config]) logging = logging.getLogger("nornir") if os.path.isfile(hier_options_file): hier_options = yaml.load(open(hier_options_file), Loader=yaml.SafeLoader) else: return Result( host=task.host, result=f"{hier_options_file} does not exist", failed=True, severity_level=logging.WARN, ) host = Host(hostname=task.host.name, os=operating_system, hconfig_options=hier_options) host.load_config_from(config_type="running", name=running_config, load_file=load_file) host.load_config_from(config_type="compiled", name=compiled_config, load_file=load_file) if os.path.isfile(hier_tags_file): host.load_tags(hier_tags_file) else: return Result( host=task.host, result=f"{hier_tags_file} does not exist", failed=True, severity_level=logging.WARN, ) host.load_remediation() results = host.filter_remediation(include_tags=include_tags, exclude_tags=exclude_tags) return Result(host=task.host, result=results)
def fetch_lab_config(device_id): device = Device.objects.get(id=device_id) device_pair = DevicePair.objects.get(lab_device=device) other_device = device_pair.prod_device interfaces = DeviceInterface.objects.filter(device=device) interface_maps = list() for interface in interfaces: interface_maps.append( InterfaceMapper.objects.get(lab_device=interface)) interface_replace_maps = list() lab_interface_names = list() for item in interface_maps: interface_replace_maps.append({ "search": f"{item.prod_device.name}$", "replace": item.lab_device.name }) lab_interface_names.append(item.lab_device.name) replace_maps = interface_replace_maps options = { "style": device.os_type, "sectional_overwrite": [], "sectional_overwrite_no_negate": [], "indent_adjust": [], "parent_allows_duplicate_child": [], "sectional_exiting": [], "full_text_sub": [], "per_line_sub": replace_maps, "idempotent_commands_blacklist": [], "idempotent_commands": [], "negation_default_when": [], "negation_negate_with": [], "ordering": [] } prod_config = RouteSwitchConfig.objects.get(device=other_device) host = Host(device.name, os=device.os_type, hconfig_options=options) host.load_config_from(name="", config_type="running", load_file=False) host.load_config_from(name=prod_config.text, config_type="compiled", load_file=False) tags = HierSerializer(os=device.os_type) for item in host.compiled_config.get_children("startswith", "interface"): if item.text.startswith("interface Loopback"): pass elif item.text.strip("interface ") in lab_interface_names: pass else: tags.add_lineage({ "lineage": [{ "startswith": [item.text] }], "add_tags": "ignore" }) host.load_tags(tags.fetch_lineage(), load_file=False) host.load_remediation() result = host.filter_remediation(exclude_tags="ignore") fetch_or_update(device, result) return tags