Esempio n. 1
0
 def load(self):
     return Inventory(
         hosts=Hosts({
             "h1": Host("h1"),
             "h2": Host("h2"),
             "h3": Host("h3")
         }),
         groups=Groups({"g1": Group("g1")}),
         defaults=Defaults(),
     )
Esempio n. 2
0
def process_dc_data(group: Group, group_data: Dict[str, Dict[str,
                                                             str]]) -> Hosts:
    """
    Arguments:
        group: Current group we are processing
        group_data: the data for the entire group as returned by the backend
    """
    # we create a placeholder for the hosts
    hosts = Hosts()

    # inside each datacenter we had a dictionary where the key was the hostname
    # and the data inside had some data about it, we iterate over the hosts
    for hostname, host_data in group_data.items():
        # for each host we create a Host object mapping it's required parameters
        # with the data we got
        hosts[hostname] = Host(
            name=hostname,
            hostname=hostname,
            platform=host_data.pop("platform"),
            groups=ParentGroups([group
                                 ]),  # we add the DC group as a parent group
            data={
                "site": group.name,
                **host_data
            },  # extra data
        )
    return hosts
 def _process_special_reset_device(self, device: Host) -> None:
     device.data["special_reset"] = True
     pod_mgmt_interface = self.deployment.device_to_pod_mgmt_port[
         device.name]
     device_name = pod_mgmt_interface.device_name
     pod_mgmt_interfaces = self.get_device(
         device_name=device_name).get("interfaces")
     pod_mgmt_interfaces[pod_mgmt_interface.num]["shutdown"] = True
Esempio n. 4
0
def load_credentials(host: Host,
                     username: Optional[str] = None,
                     password: Optional[str] = None) -> None:
    """
    load_credentials is an transform_functions to add credentials to every host.
    Environment variables `NORNIR_USERNAME` and `NORNIR_PASSWORD` or arguments can be used.

    Args:

        username: Device username
        password: Device password
    """
    username = username if username is not None else os.getenv(
        "NORNIR_USERNAME")
    if username is not None:
        host.username = username
    password = password if password is not None else os.getenv(
        "NORNIR_PASSWORD")
    if password is not None:
        host.password = password
Esempio n. 5
0
def create_result(
    result_content: Any,
    host: str = "",
    destination: Optional[str] = None,
    failed: bool = False,
    exception: Optional[BaseException] = None,
    **kwargs: Any
) -> Result:
    result = Result(host=Host(name=host), destination=destination, **kwargs)
    result.result = result_content
    result.failed = failed
    result.exception = exception
    return result
    def subtask_instance_completed(self, task: Task, host: Host,
                                   result: MultiResult) -> None:
        """For each host, check if the results returned by the task is valid and cleanup results as needed.

        Args:
            task (Task): Nornir Task
            host (Host): Nornir Host
            result (MultiResult): Nornir Results
        """
        if task.name != self.task_name:
            return

        if result[0].failed:
            LOGGER.warning(
                "%s | Something went wrong while trying to pull the neighbor information",
                host.name)
            host.status = "fail-other"
            return

        if not isinstance(result[0].result,
                          dict) or "neighbors" not in result[0].result:
            LOGGER.warning("%s | No neighbor information returned", host.name)
            result[0].failed = True
            return

        interfaces = list(result[0].result["neighbors"].keys())
        for interface in interfaces:

            neighbors = result[0].result["neighbors"][interface]

            if len(neighbors) > 1:
                LOGGER.warning(
                    "%s | More than 1 neighbor found on interface %s, SKIPPING",
                    host.name, interface)
                del result[0].result["neighbors"][interface]
                continue

            if is_mac_address(neighbors[0]["hostname"]):
                del result[0].result["neighbors"][interface]
                continue

            # Clean up hostname to remove full FQDN
            result[0].result["neighbors"][interface][0][
                "hostname"] = self.clean_neighbor_name(
                    neighbors[0]["hostname"])

            # Clean up the portname if genie incorrectly capitalized it
            result[0].result["neighbors"][interface][0][
                "port"] = self.clean_neighbor_port_name(neighbors[0]["port"])
Esempio n. 7
0
def patch_inventory_delegate(inv: Inventory) -> Inventory:
    """
    Patch nornir inventory configurations per cli arguments.

    Arguments:
        inv: nornir.core.inventory.Inventory object; Initialized Nornir Inventory object

    Returns:
        inv: nornir.core.inventory.Inventory object; Updated Nornir Inventory object

    Raises:
        N/A  # noqa

    """
    inv.hosts["delegate"] = Host(name="delegate")

    return inv
def _set_host(data: Dict[str, Any], name: str, groups, host, defaults) -> Host:
    connection_option = {}
    for key, value in data.get("connection_options", {}).items():
        connection_option[key] = ConnectionOptions(
            hostname=value.get("hostname"),
            port=value.get("port"),
            username=value.get("username"),
            password=value.get("password"),
            platform=value.get("platform"),
            extras=value.get("extras"),
        )
    return Host(
        name=name,
        hostname=host["hostname"],
        username=host["username"],
        password=host["password"],
        platform=host["platform"],
        data=data,
        groups=groups,
        defaults=defaults,
        connection_options=connection_option,
    )
Esempio n. 9
0
from nornir import InitNornir
from nornir.core.inventory import Host
import json

my_nornir = InitNornir(config_file="config.yaml")

# this displays the default schema for the inventory
# hosts and groups file. Defaults is same without repetition
# for individual devices.
print(json.dumps(Host.schema(), indent=4))

# my_nornir
# now has an inventory with dict-like attributes hosts and groups
print(my_nornir.inventory.hosts)
print(my_nornir.inventory.groups)
# you can access the like regular dictionaries
print(my_nornir.inventory.hosts.keys())
print(my_nornir.inventory.hosts['R1'])

# Showing inheritance hosts --> groups --> defaults
router1 = my_nornir.inventory.hosts['R1']
rtr_priority = router1['priority']
print("Router1 priority is: " + str(rtr_priority))

router2 = my_nornir.inventory.hosts['R2']
print("Router2 priority is: {}".format(router2['priority']))

router4 = my_nornir.inventory.hosts['R4']
print("Router4 priority is: {}".format(router4['priority']))

# filters can be based on key: value pairs from the inventory yaml files
Esempio n. 10
0
    def subtask_instance_completed(self, task: Task, host: Host,
                                   result: MultiResult) -> None:
        """Verify the configuration returned and store it to disk.

        After collecting the configuration for each host.
        - Inspect the result and ensure the configuration is valid
        - If the configuration is valid, check the md5
        - if the MD5 is different, write the new configuration to disk

        Args:
            task (Task): Nornir Task
            host (Host): Nornir Host
            result (MultiResult): Nornir MultiResult
        """
        if task.name != self.task_name:
            return

        if result[0].failed:
            if result[0].exception:
                LOGGER.warning("%s | %s", task.host.name, result[0].exception)
            else:
                LOGGER.warning(
                    "%s | Something went wrong while trying to update the configuration ",
                    task.host.name)
            host.status = "fail-other"
            return

        conf = result[0].result.get("config", None)

        if not conf:
            LOGGER.warning("%s | No configuration return ", task.host.name)
            host.status = "fail-other"
            return

        # Count the number of lines in the config file, if less than 10 report an error
        # mostlikely something went wrong while pulling the config
        if conf.count("\n") < 10:
            LOGGER.warning("%s | Less than 10 configuration lines returned",
                           task.host.name)
            host.status = "fail-other"
            return

        if host.name in self.existing_config_hostnames:
            self.existing_config_hostnames.remove(host.name)

        # Save configuration to file and verify the new MD5
        with open(self.config_filename[host.name], "w") as config_:
            config_.write(conf)

        host.has_config = True

        self.current_md5[host.name] = hashlib.md5(
            conf.encode("utf-8")).hexdigest()
        # changed = False

        if host.name in self.previous_md5 and self.previous_md5[
                host.name] == self.current_md5[host.name]:
            LOGGER.info("%s | Latest config file already present ...",
                        task.host.name)
        else:
            LOGGER.info("%s | Configuration file updated", task.host.name)
Esempio n. 11
0
    def test_hosts(self):
        defaults = {"var4": "ALL"}
        g1 = Group(name="g1", var1="1", var2="2", var3="3")
        g2 = Group(name="g2", var1="a", var2="b")
        g3 = Group(name="g3", var1="A", var4="Z")
        g4 = Group(name="g4", groups=[g2, g1], var3="q")

        h1 = Host(name="host1", groups=[g1, g2], defaults=defaults)
        assert h1["var1"] == "1"
        assert h1["var2"] == "2"
        assert h1["var3"] == "3"
        assert h1["var4"] == "ALL"
        assert compare_lists(
            list(h1.keys()), ["name", "groups", "var1", "var2", "var3", "var4"]
        )
        assert compare_lists(
            list(h1.values()), ["host1", ["g1", "g2"], "1", "2", "3", "ALL"]
        )
        assert compare_lists(
            list(h1.items()),
            [
                ("name", "host1"),
                ("groups", ["g1", "g2"]),
                ("var1", "1"),
                ("var2", "2"),
                ("var3", "3"),
                ("var4", "ALL"),
            ],
        )

        h2 = Host(name="host2", groups=[g2, g1], defaults=defaults)
        assert h2["var1"] == "a"
        assert h2["var2"] == "b"
        assert h2["var3"] == "3"
        assert h2["var4"] == "ALL"
        assert compare_lists(
            list(h2.keys()), ["name", "groups", "var1", "var2", "var3", "var4"]
        )
        assert compare_lists(
            list(h2.values()), ["host2", ["g2", "g1"], "a", "b", "3", "ALL"]
        )
        assert compare_lists(
            list(h2.items()),
            [
                ("name", "host2"),
                ("groups", ["g2", "g1"]),
                ("var1", "a"),
                ("var2", "b"),
                ("var3", "3"),
                ("var4", "ALL"),
            ],
        )

        h3 = Host(name="host3", groups=[g4, g3], defaults=defaults)
        assert h3["var1"] == "a"
        assert h3["var2"] == "b"
        assert h3["var3"] == "q"
        assert h3["var4"] == "Z"
        assert compare_lists(
            list(h3.keys()), ["name", "groups", "var3", "var1", "var2", "var4"]
        )
        assert compare_lists(
            list(h3.values()), ["host3", ["g4", "g3"], "q", "a", "b", "Z"]
        )
        assert compare_lists(
            list(h3.items()),
            [
                ("name", "host3"),
                ("groups", ["g4", "g3"]),
                ("var3", "q"),
                ("var1", "a"),
                ("var2", "b"),
                ("var4", "Z"),
            ],
        )

        h4 = Host(name="host4", groups=[g3, g4], defaults=defaults)
        assert h4["var1"] == "A"
        assert h4["var2"] == "b"
        assert h4["var3"] == "q"
        assert h4["var4"] == "Z"
        assert compare_lists(
            list(h4.keys()), ["name", "groups", "var1", "var4", "var3", "var2"]
        )
        assert compare_lists(
            list(h4.values()), ["host4", ["g3", "g4"], "A", "Z", "q", "b"]
        )
        assert compare_lists(
            list(h4.items()),
            [
                ("name", "host4"),
                ("groups", ["g3", "g4"]),
                ("var1", "A"),
                ("var4", "Z"),
                ("var3", "q"),
                ("var2", "b"),
            ],
        )

        with pytest.raises(KeyError):
            assert h2["asdasd"]
Esempio n. 12
0
C        10.0.0.0/24 is directly connected, GigabitEthernet1
L        10.0.0.15/32 is directly connected, GigabitEthernet1"""

RAW_RESULT = "\n".join([IOSXE_SHOW_VERSION, IOSXE_SHOW_IP_ROUTE])

TEST_SCRAPLI_RESPONSE_ONE = Response(host="sea-ios-1",
                                     channel_input="show version",
                                     textfsm_platform="cisco_iosxe")
TEST_SCRAPLI_RESPONSE_ONE._record_response(result=IOSXE_SHOW_VERSION)
TEST_SCRAPLI_RESPONSE_TWO = Response(host="sea-ios-1",
                                     channel_input="show ip route",
                                     textfsm_platform="cisco_iosxe")
TEST_SCRAPLI_RESPONSE_TWO._record_response(result=IOSXE_SHOW_IP_ROUTE)
TEST_SCRAPLI_RESPONSE = [TEST_SCRAPLI_RESPONSE_ONE, TEST_SCRAPLI_RESPONSE_TWO]

TEST_HOST = Host(name="sea-ios-1")
TEST_AGG_RESULT = AggregatedResult("send_commands")
TEST_MULTI_RESULT = MultiResult("send_commands")
TEST_RESULT = Result(host=TEST_HOST, result=RAW_RESULT, name="send_commands")
setattr(TEST_RESULT, "scrapli_response", TEST_SCRAPLI_RESPONSE)

TEST_MULTI_RESULT.append(TEST_RESULT)

TEST_AGG_RESULT[TEST_HOST.name] = TEST_MULTI_RESULT


@pytest.mark.parametrize(
    "to_dict",
    [
        (
            True,
Esempio n. 13
0
    def load(self) -> Inventory:
        defaults = Defaults(
            connection_options={
                "napalm": ConnectionOptions(extras={
                    "optional_args": {
                        # args to eAPI HttpsEapiConnection for EOS
                        "enforce_verification": True,
                        "context": ssl_context
                    }
                })
            }
        )
        insecure_device_states = [
            DeviceState.INIT,
            DeviceState.DHCP_BOOT,
            DeviceState.PRE_CONFIGURED,
            DeviceState.DISCOVERED
        ]
        insecure_connection_options = {
            "napalm": ConnectionOptions(extras={
                "optional_args": {"enforce_verification": False}
            })
        }

        groups = Groups()
        for device_type in list(DeviceType.__members__):
            group_name = 'T_'+device_type
            groups[group_name] = Group(name=group_name, defaults=defaults)
        for device_state in list(DeviceState.__members__):
            username, password = self._get_credentials(device_state)
            group_name = 'S_'+device_state
            groups[group_name] = Group(
                name=group_name, username=username, password=password, defaults=defaults)
        for group_name in get_groups():
            groups[group_name] = Group(name=group_name, defaults=defaults)

        hosts = Hosts()
        with cnaas_nms.db.session.sqla_session() as session:
            instance: Device
            for instance in session.query(Device):
                hostname = self._get_management_ip(instance.management_ip,
                                                   instance.dhcp_ip)
                port = None
                if instance.port and isinstance(instance.port, int):
                    port = instance.port
                host_groups = [
                    'T_' + instance.device_type.name,
                    'S_' + instance.state.name
                ]
                for member_group in get_groups(instance.hostname):
                    host_groups.append(member_group)

                if instance.state in insecure_device_states:
                    host_connection_options = insecure_connection_options
                else:
                    host_connection_options = None
                hosts[instance.hostname] = Host(
                    name=instance.hostname,
                    hostname=hostname,
                    platform=instance.platform,
                    groups=ParentGroups(groups[g] for g in host_groups),
                    port=port,
                    data={
                        'synchronized': instance.synchronized,
                        'managed': (True if instance.state == DeviceState.MANAGED else False)
                    },
                    connection_options=host_connection_options,
                    defaults=defaults
                )

        return Inventory(hosts=hosts, groups=groups, defaults=defaults)