From e4f6b8c6258ae2dcfb286098b30652c7a31ecf30 Mon Sep 17 00:00:00 2001 From: David Barroso Date: Tue, 2 Mar 2021 09:03:37 +0100 Subject: [PATCH 1/5] address UTF-8 error on windows (#654) --- nornir/plugins/inventory/simple.py | 9 ++++++--- tests/plugins/inventory/data/hosts.yaml | 3 ++- tests/plugins/inventory/test_simple_inventory.py | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/nornir/plugins/inventory/simple.py b/nornir/plugins/inventory/simple.py index e34b0a077..db1d74b8f 100644 --- a/nornir/plugins/inventory/simple.py +++ b/nornir/plugins/inventory/simple.py @@ -70,6 +70,7 @@ def __init__( host_file: str = "hosts.yaml", group_file: str = "groups.yaml", defaults_file: str = "defaults.yaml", + encoding: str = "utf-8", ) -> None: """ SimpleInventory is an inventory plugin that loads data from YAML files. @@ -82,24 +83,26 @@ def __init__( it doesn't exist it will be skipped defaults_file: path to file with defaults definition. If it doesn't exist it will be skipped + encoding: Encoding used to save inventory files. Defaults to utf-8 """ self.host_file = pathlib.Path(host_file).expanduser() self.group_file = pathlib.Path(group_file).expanduser() self.defaults_file = pathlib.Path(defaults_file).expanduser() + self.encoding = encoding def load(self) -> Inventory: yml = ruamel.yaml.YAML(typ="safe") if self.defaults_file.exists(): - with open(self.defaults_file, "r") as f: + with open(self.defaults_file, "r", encoding=self.encoding) as f: defaults_dict = yml.load(f) or {} defaults = _get_defaults(defaults_dict) else: defaults = Defaults() hosts = Hosts() - with open(self.host_file, "r") as f: + with open(self.host_file, "r", encoding=self.encoding) as f: hosts_dict = yml.load(f) for n, h in hosts_dict.items(): @@ -107,7 +110,7 @@ def load(self) -> Inventory: groups = Groups() if self.group_file.exists(): - with open(self.group_file, "r") as f: + with open(self.group_file, "r", encoding=self.encoding) as f: groups_dict = yml.load(f) or {} for n, g in groups_dict.items(): diff --git a/tests/plugins/inventory/data/hosts.yaml b/tests/plugins/inventory/data/hosts.yaml index 8f11e4790..38d32fb2d 100644 --- a/tests/plugins/inventory/data/hosts.yaml +++ b/tests/plugins/inventory/data/hosts.yaml @@ -116,6 +116,7 @@ dev5.no_group: username: password: platform: linux - data: {} + data: + smiley: 😜 groups: [] connection_options: {} diff --git a/tests/plugins/inventory/test_simple_inventory.py b/tests/plugins/inventory/test_simple_inventory.py index 27040dd29..8eae3d698 100644 --- a/tests/plugins/inventory/test_simple_inventory.py +++ b/tests/plugins/inventory/test_simple_inventory.py @@ -220,7 +220,7 @@ def test(self): }, "dev5.no_group": { "connection_options": {}, - "data": {}, + "data": {"smiley": "😜"}, "groups": [], "hostname": "localhost", "name": "dev5.no_group", From 2e0c9f4e8997f05ac60e94956faa6443302133d4 Mon Sep 17 00:00:00 2001 From: Brandon Donohoe Date: Fri, 2 Apr 2021 06:52:09 -0500 Subject: [PATCH 2/5] remove state property from Nornir class (#669) --- nornir/core/__init__.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/nornir/core/__init__.py b/nornir/core/__init__.py index dd5d192d7..bc086addb 100644 --- a/nornir/core/__init__.py +++ b/nornir/core/__init__.py @@ -171,7 +171,3 @@ def validate(cls, v): if not isinstance(v, cls): raise ValueError(f"Nornir: Nornir expected not {type(v)}") return v - - @property - def state(self): - return GlobalState From 9d308cb7d4ccb10d5c7d559e053aa6012b019892 Mon Sep 17 00:00:00 2001 From: bytinbit Date: Sat, 24 Apr 2021 19:17:56 +0200 Subject: [PATCH 3/5] Evaluate a host's group outside groups evaluation (#677) --- nornir/plugins/inventory/simple.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nornir/plugins/inventory/simple.py b/nornir/plugins/inventory/simple.py index db1d74b8f..d453073e8 100644 --- a/nornir/plugins/inventory/simple.py +++ b/nornir/plugins/inventory/simple.py @@ -116,10 +116,10 @@ def load(self) -> Inventory: for n, g in groups_dict.items(): groups[n] = _get_inventory_element(Group, g, n, defaults) - for h in hosts.values(): - h.groups = ParentGroups([groups[g] for g in h.groups]) - for g in groups.values(): g.groups = ParentGroups([groups[g] for g in g.groups]) + for h in hosts.values(): + h.groups = ParentGroups([groups[g] for g in h.groups]) + return Inventory(hosts=hosts, groups=groups, defaults=defaults) From 0f03a1dc5738116ac954897108720383e297c67e Mon Sep 17 00:00:00 2001 From: Daniel Teycheney Date: Sun, 25 Apr 2021 03:26:57 +1000 Subject: [PATCH 4/5] Nornir Filtering Deep Dive How To (#674) --- docs/howto/filtering_deep_dive.ipynb | 2195 +++++++++++++++++ docs/howto/filtering_deep_dive/config.yaml | 10 + .../filtering_deep_dive/inventory/groups.yaml | 79 + .../inventory/groups_extract.yaml | 8 + .../inventory/groups_extract_alternate.yaml | 12 + .../filtering_deep_dive/inventory/hosts.yaml | 351 +++ .../inventory/hosts_extract.yaml | 13 + .../inventory/hosts_extract_alternate.yaml | 14 + 8 files changed, 2682 insertions(+) create mode 100644 docs/howto/filtering_deep_dive.ipynb create mode 100644 docs/howto/filtering_deep_dive/config.yaml create mode 100644 docs/howto/filtering_deep_dive/inventory/groups.yaml create mode 100644 docs/howto/filtering_deep_dive/inventory/groups_extract.yaml create mode 100644 docs/howto/filtering_deep_dive/inventory/groups_extract_alternate.yaml create mode 100644 docs/howto/filtering_deep_dive/inventory/hosts.yaml create mode 100644 docs/howto/filtering_deep_dive/inventory/hosts_extract.yaml create mode 100644 docs/howto/filtering_deep_dive/inventory/hosts_extract_alternate.yaml diff --git a/docs/howto/filtering_deep_dive.ipynb b/docs/howto/filtering_deep_dive.ipynb new file mode 100644 index 000000000..7c888aa4e --- /dev/null +++ b/docs/howto/filtering_deep_dive.ipynb @@ -0,0 +1,2195 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "economic-description", + "metadata": {}, + "source": [ + "# Filtering Deep Dive\n", + "\n", + "In this tutorial, we will explore the power of nornir filtering and demonstrate why nornir is a first-class inventory management framework.\n", + "\n", + "This tutorial will demonstrate some common network use-cases and how nornir filtering can be target to target hosts or groups with precision." + ] + }, + { + "cell_type": "markdown", + "id": "unauthorized-integral", + "metadata": {}, + "source": [ + "## Tutorial Inventory\n", + "\n", + "Firstly, let's start with initialising our nornir inventory." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "checked-standing", + "metadata": {}, + "outputs": [], + "source": [ + "# Import modules\n", + "from nornir import InitNornir\n", + "from nornir.core.filter import F\n", + "\n", + "# Initialise nornir\n", + "nr = InitNornir(config_file=\"filtering_deep_dive/config.yaml\")" + ] + }, + { + "cell_type": "markdown", + "id": "challenging-specialist", + "metadata": {}, + "source": [ + "Next, let's look at our tutorial `hosts.yaml` file. Don't be overwhelmed by the size of the inventory or the content within as we will explore this in further detail later in the tutorial:" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "certified-clothing", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---\r\n", + "lab-csr-011.lab.norn.local:\r\n", + " hostname: lab-csr-011.lab.norn.local\r\n", + " groups:\r\n", + " - ios\r\n", + " - lab\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.0.16\r\n", + " vendor: cisco\r\n", + " device_type: router\r\n", + " os_version: 16.6.4\r\n", + " site_code: mel\r\n", + "\r\n", + "dfjt-r001.lab.norn.local:\r\n", + " hostname: dfjt-r001.lab.norn.local\r\n", + " groups:\r\n", + " - ios\r\n", + " - lab\r\n", + " - bcn\r\n", + " data:\r\n", + " mgmt_ip: 10.0.0.1\r\n", + " vendor: cisco\r\n", + " device_type: router\r\n", + " os_version: 16.6.3\r\n", + " site_code: bcn\r\n", + "\r\n", + "lab-arista-01.lab.norn.local:\r\n", + " hostname: lab-arista-01.lab.norn.local\r\n", + " groups:\r\n", + " - eos\r\n", + " - lab\r\n", + " - mtl\r\n", + " data:\r\n", + " mgmt_ip: 10.0.0.11\r\n", + " vendor: arista\r\n", + " device_type: switch\r\n", + " os_version: 4.22.0F\r\n", + " site_code: mtl\r\n", + "\r\n", + "lab-arista-02.lab.norn.local:\r\n", + " hostname: lab-arista-02.lab.norn.local\r\n", + " groups:\r\n", + " - eos\r\n", + " - lab\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.0.18\r\n", + " vendor: arista\r\n", + " device_type: switch\r\n", + " os_version: 4.23.2F\r\n", + " site_code: mel\r\n", + "\r\n", + "lab-junos-01.lab.norn.local:\r\n", + " hostname: lab-junos-01.lab.norn.local\r\n", + " groups:\r\n", + " - junos\r\n", + " - lab\r\n", + " - mtl\r\n", + " data:\r\n", + " mgmt_ip: 10.0.0.15\r\n", + " vendor: juniper\r\n", + " device_type: router\r\n", + " os_version: 18.4R2-S5\r\n", + " site_code: mtl\r\n", + "\r\n", + "lab-nxos-01.lab.norn.local:\r\n", + " hostname: lab-nxos-01.lab.norn.local\r\n", + " groups:\r\n", + " - nxos\r\n", + " - lab\r\n", + " - mtl\r\n", + " data:\r\n", + " mgmt_ip: 10.0.0.14\r\n", + " vendor: cisco\r\n", + " device_type: switch\r\n", + " os_version: 9.3(6)\r\n", + " site_code: mtl\r\n", + "\r\n", + "lab-paloalto-01.lab.djft.local:\r\n", + " hostname: lab-paloalto-01.lab.djft.local\r\n", + " groups:\r\n", + " - panos\r\n", + " - lab\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.0.21\r\n", + " vendor: palo alto\r\n", + " device_type: firewall\r\n", + " os_version: 10.0.3\r\n", + " site_code: mel\r\n", + "\r\n", + "lab-paloalto-02.lab.norn.local:\r\n", + " hostname: lab-paloalto-02.lab.norn.local\r\n", + " groups:\r\n", + " - panos\r\n", + " - lab\r\n", + " - bcn\r\n", + " data:\r\n", + " mgmt_ip: 10.0.0.22\r\n", + " vendor: palo alto\r\n", + " device_type: firewall\r\n", + " os_version: 9.1.3-h1\r\n", + " site_code: bcn\r\n", + "\r\n", + "lab-junos-06.lab.norn.local:\r\n", + " hostname: lab-junos-06.lab.norn.local\r\n", + " groups:\r\n", + " - junos\r\n", + " - lab\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.0.23\r\n", + " vendor: juniper\r\n", + " device_type: switch\r\n", + " os_version: 18.4R2-S5\r\n", + " site_code: mel\r\n", + "\r\n", + "prd-csr-01.prd.norn.local:\r\n", + " hostname: prd-csr-01.prd.norn.local\r\n", + " groups:\r\n", + " - ios\r\n", + " - prod\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.16.16\r\n", + " vendor: cisco\r\n", + " device_type: router\r\n", + " os_version: 16.6.4\r\n", + " site_code: mel\r\n", + "\r\n", + "dfjt-r001.prd.norn.local:\r\n", + " hostname: dfjt-r001.prd.norn.local\r\n", + " groups:\r\n", + " - ios\r\n", + " - prod\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.16.1\r\n", + " vendor: cisco\r\n", + " device_type: router\r\n", + " os_version: 16.6.3\r\n", + " site_code: mel\r\n", + "\r\n", + "prd-arista-01.prd.norn.local:\r\n", + " hostname: prd-arista-01.prd.norn.local\r\n", + " groups:\r\n", + " - eos\r\n", + " - prod\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.16.11\r\n", + " vendor: arista\r\n", + " device_type: switch\r\n", + " os_version: 4.21.1F\r\n", + " site_code: mel\r\n", + "\r\n", + "prd-arista-02.prd.nron.local:\r\n", + " hostname: prd-arista-02.prd.norn.local\r\n", + " groups:\r\n", + " - eos\r\n", + " - prod\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.16.18\r\n", + " vendor: arista\r\n", + " device_type: switch\r\n", + " os_version: 4.23.1F\r\n", + " site_code: mel\r\n", + "\r\n", + "prd-junos-01.prd.norn.local:\r\n", + " hostname: prd-junos-01.prd.norn.local\r\n", + " groups:\r\n", + " - junos\r\n", + " - prod\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.16.15\r\n", + " vendor: juniper\r\n", + " device_type: router\r\n", + " os_version: 15.1R7-S6\r\n", + " site_code: mel\r\n", + "\r\n", + "prd-nxos-01.prd.norn.local:\r\n", + " hostname: prd-nxos-01.prd.norn.local\r\n", + " groups:\r\n", + " - nxos_ssh\r\n", + " - prod\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.16.14\r\n", + " vendor: cisco\r\n", + " device_type: switch\r\n", + " os_version: 7.0(3)\r\n", + " site_code: mel\r\n", + "\r\n", + "prd-paloalto-01.prd.norn.local:\r\n", + " hostname: prd-paloalto-01.prd.norn.local\r\n", + " groups:\r\n", + " - panos\r\n", + " - prod\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.16.21\r\n", + " vendor: palo alto\r\n", + " device_type: firewall\r\n", + " os_version: 10.0.3\r\n", + " site_code: mel\r\n", + "\r\n", + "prd-paloalto-02.prd.norn.local:\r\n", + " hostname: prd-paloalto-02.prd.norn.local\r\n", + " groups:\r\n", + " - panos\r\n", + " - prod\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.16.22\r\n", + " vendor: palo alto\r\n", + " device_type: firewall\r\n", + " os_version: 9.1.6\r\n", + " site_code: mel\r\n", + "\r\n", + "prd-junos-06.prd.norn.local:\r\n", + " hostname: prd-junos-06.prd.norn.local\r\n", + " groups:\r\n", + " - junos\r\n", + " - prod\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.16.23\r\n", + " vendor: juniper\r\n", + " device_type: switch\r\n", + " os_version: 12.1R3-S4\r\n", + " site_code: mel\r\n", + "\r\n", + "tst-csr-01.tst.norn.local:\r\n", + " hostname: tst-csr-01.tst.norn.local\r\n", + " groups:\r\n", + " - ios\r\n", + " - test\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.32.16\r\n", + " vendor: cisco\r\n", + " device_type: router\r\n", + " os_version: 16.6.4\r\n", + " site_code: mel\r\n", + "\r\n", + "dfjt-r001.tst.norn.local:\r\n", + " hostname: dfjt-r001.tst.norn.local\r\n", + " groups:\r\n", + " - ios\r\n", + " - test\r\n", + " - mel\r\n", + " data:\r\n", + " mgmt_ip: 10.0.32.1\r\n", + " vendor: cisco\r\n", + " device_type: router\r\n", + " os_version: 15.1.4\r\n", + " site_code: mel\r\n", + "\r\n", + "tst-arista-01.tst.norn.local:\r\n", + " hostname: tst-arista-01.tst.norn.local\r\n", + " groups:\r\n", + " - eos\r\n", + " - test\r\n", + " - ptl\r\n", + " data:\r\n", + " mgmt_ip: 10.0.32.11\r\n", + " vendor: arista\r\n", + " device_type: switch\r\n", + " os_version: 4.21.1F\r\n", + " site_code: ptl\r\n", + "\r\n", + "tstt-arista-02.tst.norn.local:\r\n", + " hostname: tstt-arista-02.tst.norn.local\r\n", + " groups:\r\n", + " - eos\r\n", + " - test\r\n", + " - ptl\r\n", + " data:\r\n", + " mgmt_ip: 10.0.32.18\r\n", + " vendor: arista\r\n", + " device_type: switch\r\n", + " os_version: 4.21.1F\r\n", + " site_code: ptl\r\n", + "\r\n", + "tst-junos-01.tst.norn.local:\r\n", + " hostname: tst-junos-01.tst.norn.local\r\n", + " groups:\r\n", + " - junos\r\n", + " - test\r\n", + " - ptl\r\n", + " data:\r\n", + " mgmt_ip: 10.0.32.15\r\n", + " vendor: juniper\r\n", + " device_type: router\r\n", + " os_version: 15.1R7-S6\r\n", + " site_code: ptl\r\n", + "\r\n", + "tst-nxos-01.tst.norn.local:\r\n", + " hostname: tst-nxos-01.tst.norn.local\r\n", + " groups:\r\n", + " - nxos\r\n", + " - test\r\n", + " - chc\r\n", + " data:\r\n", + " mgmt_ip: 10.0.32.14\r\n", + " vendor: cisco\r\n", + " device_type: switch\r\n", + " os_version: 7.0(4)\r\n", + " site_code: chc\r\n", + "\r\n", + "tst-paloalto-01.tst.norn.local:\r\n", + " hostname: tst-paloalto-01.tst.norn.local\r\n", + " groups:\r\n", + " - panos\r\n", + " - test\r\n", + " - chc\r\n", + " data:\r\n", + " mgmt_ip: 10.0.32.21\r\n", + " vendor: palo alto\r\n", + " device_type: firewall\r\n", + " os_version: 10.0.3\r\n", + " site_code: chc\r\n", + "\r\n", + "tst-paloalto-02.tst.norn.local:\r\n", + " hostname: tst-paloalto-02.tst.norn.local\r\n", + " groups:\r\n", + " - panos\r\n", + " - test\r\n", + " - chc\r\n", + " data:\r\n", + " mgmt_ip: 10.0.32.22\r\n", + " vendor: palo alto\r\n", + " device_type: firewall\r\n", + " os_version: 8.0.8\r\n", + " site_code: chc\r\n", + "\r\n", + "tst-junos-06.tst.norn.local:\r\n", + " hostname: tst-junos-06.tst.norn.local\r\n", + " groups:\r\n", + " - junos\r\n", + " - test\r\n", + " - chc\r\n", + " data:\r\n", + " mgmt_ip: 10.0.32.23\r\n", + " vendor: juniper\r\n", + " device_type: switch\r\n", + " os_version: 12.1R3-S4\r\n", + " site_code: chc\r\n" + ] + } + ], + "source": [ + "%cat filtering_deep_dive/inventory/hosts.yaml" + ] + }, + { + "cell_type": "markdown", + "id": "baking-mercury", + "metadata": {}, + "source": [ + "Next, let's look at our tutorial `groups.yaml` file. There are a mixture of group types in here.\n", + "\n", + "Some appear to be based on network operating systems, some on operating environments and others based on physical location. \n", + "\n", + "nornir has no pre-conceived ideas or limits on group composition or structures:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "dirty-spain", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---\r\n", + "ios:\r\n", + " platform: ios\r\n", + " data:\r\n", + " vendor: cisco\r\n", + "junos:\r\n", + " platform: junos\r\n", + " data:\r\n", + " vendor: juniper\r\n", + "eos:\r\n", + " platform: eos\r\n", + " data:\r\n", + " vendor: arista\r\n", + "nxos:\r\n", + " platform: nxos\r\n", + " data:\r\n", + " vendor: cisco\r\n", + "nxos_ssh:\r\n", + " platform: nxos_ssh\r\n", + " data:\r\n", + " vendor: cisco\r\n", + "panos:\r\n", + " platform: paloalto_panos\r\n", + " data:\r\n", + " vendor: palo alto\r\n", + "lab:\r\n", + " data:\r\n", + " sla: 70\r\n", + " production: false\r\n", + "prod:\r\n", + " data:\r\n", + " sla: 90\r\n", + " production: true\r\n", + "test:\r\n", + " data:\r\n", + " sla: 80\r\n", + " production: false\r\n", + "mel:\r\n", + " data:\r\n", + " full_name: Melbourne\r\n", + " country: Australia\r\n", + " region: apac\r\n", + " hemisphere: southern\r\n", + " site_type: primary\r\n", + "hbt:\r\n", + " data:\r\n", + " full_name: Hobart\r\n", + " country: Australia\r\n", + " region: apac\r\n", + " hemisphere: southern\r\n", + " site_type: tertiary\r\n", + "chc:\r\n", + " data:\r\n", + " full_name: Christchurch\r\n", + " country: New Zealand\r\n", + " region: apac\r\n", + " hemisphere: southern\r\n", + " site_type: secondary\r\n", + "ptl:\r\n", + " data:\r\n", + " full_name: Port Louis\r\n", + " country: Mauritius\r\n", + " region: amea\r\n", + " hemisphere: southern\r\n", + " site_type: primary\r\n", + "mtl:\r\n", + " data:\r\n", + " full_name: Montreal\r\n", + " country: Canada\r\n", + " region: amer\r\n", + " hemisphere: northern\r\n", + " site_type: primary\r\n", + "bcn:\r\n", + " data:\r\n", + " full_name: Barcelona\r\n", + " country: Spain\r\n", + " region: amea\r\n", + " hemisphere: northern\r\n", + " site_type: primary\r\n" + ] + } + ], + "source": [ + "%cat filtering_deep_dive/inventory/groups.yaml" + ] + }, + { + "cell_type": "markdown", + "id": "appointed-broadway", + "metadata": {}, + "source": [ + "## Custom inventory data\n", + "\n", + "Before we dive into filtering, it's important to introduce some core concepts regarding custom data.\n", + "\n", + "nornir allows you to populate custom data on `hosts` or `groups` objects under the `data` key, in whatever key/value data structure you choose. You can name these keys whatever you like to suit your business needs.\n", + "\n", + "Firstly, let's explore an extract of one host and one group in the initial inventory introduced `hosts.yaml` and `groups.yaml` file. \n", + "\n", + "**NOTE: These files have been cut down to only contain one entry each, and also have some comments dispersed for readability**" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "varied-guarantee", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---\r\n", + "lab-csr-011.lab.norn.local:\r\n", + " hostname: lab-csr-011.lab.norn.local\r\n", + " groups:\r\n", + " - ios\r\n", + " - lab\r\n", + " - mel\r\n", + " data: # Anything under this key is custom data\r\n", + " mgmt_ip: 10.0.0.16 # This is custom data\r\n", + " vendor: cisco # So is this\r\n", + " device_type: router # Same as this\r\n", + " os_version: 16.6.4 # Also this too\r\n", + " site_code: mel # Yes, and also this\r\n" + ] + } + ], + "source": [ + "%cat filtering_deep_dive/inventory/hosts_extract.yaml" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "fuzzy-conclusion", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---\r\n", + "mel:\r\n", + " data: # Anything under this key is custom data\r\n", + " full_name: Melbourne # This is custom data\r\n", + " country: Australia # So is this\r\n", + " region: apac # Same as this\r\n", + " hemisphere: southern # Also this too\r\n", + " site_type: primary # Yes, and also this\r\n" + ] + } + ], + "source": [ + "%cat filtering_deep_dive/inventory/groups_extract.yaml" + ] + }, + { + "cell_type": "markdown", + "id": "dressed-johnson", + "metadata": {}, + "source": [ + "As you can see in the two examples above, you can use custom data in any manner you like to record any information you please. The examples above are a \"flat\" data structure under the `data` key, but you can nest your data structure in any key/value structure to suit your needs. \n", + "\n", + "In the below example, we take the `mgmt_ip` value of `10.0.0.16`, and reorient it under an alternate data structure to the key `mgmt` which could allow for future expansion:" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "affected-principle", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---\r\n", + "lab-csr-011.lab.norn.local:\r\n", + " hostname: lab-csr-011.lab.norn.local\r\n", + " groups:\r\n", + " - ios\r\n", + " - lab\r\n", + " - mel\r\n", + " data: # Anything under this key is custom data\r\n", + " ip_addresses:\r\n", + " mgmt: 10.0.0.16 # Alternate way of managing mgmt_ip data\r\n", + " vendor: cisco\r\n", + " device_type: router\r\n", + " os_version: 16.6.4\r\n", + " site_code: mel\r\n" + ] + } + ], + "source": [ + "%cat filtering_deep_dive/inventory/hosts_extract_alternate.yaml" + ] + }, + { + "cell_type": "markdown", + "id": "foster-timing", + "metadata": {}, + "source": [ + "Naturally over time, you needs to store custom data might change and ideally you enrich your custom data with as much business information as possible. \n", + "\n", + "In the example below, a new set of key/value pairs related to the location of the site are now stored under the `location` key. This means that any existing code leveraging the existing data structure doesn't need to be refactored:" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "numeric-musician", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---\r\n", + "mel:\r\n", + " data: # Anything under this key is custom data\r\n", + " full_name: Melbourne\r\n", + " country: Australia\r\n", + " region: apac\r\n", + " hemisphere: southern\r\n", + " site_type: primary\r\n", + " location: # New location data is stored about the site\r\n", + " address: 1 Wurundjeri Street\r\n", + " suburb: Northcote\r\n", + " zip_code: 3070\r\n" + ] + } + ], + "source": [ + "%cat filtering_deep_dive/inventory/groups_extract_alternate.yaml" + ] + }, + { + "cell_type": "markdown", + "id": "passing-swimming", + "metadata": {}, + "source": [ + "### Viewing host/group data\n", + "\n", + "Before we revert back to filtering, we will show you how to access all data which is accessible or attributed to a `host` or `group`.\n", + "\n", + "First, we will initialise nornir and filter the inventory on a single host `\n", + "lab-csr-011.lab.norn.local`: " + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "spare-sandwich", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of hosts in entire inventory: 27\n", + "Single host: lab-csr-011.lab.norn.local\n" + ] + } + ], + "source": [ + "# Import modules\n", + "from nornir import InitNornir\n", + "from nornir.core.filter import F\n", + "\n", + "# Initialise nornir\n", + "nr = InitNornir(config_file=\"filtering_deep_dive/config.yaml\")\n", + "# Print the number of hosts in the inventory\n", + "print(f\"Number of hosts in entire inventory: {len(nr.inventory.hosts)}\")\n", + "# Access the host lab-csr-011.lab.norn.local using standard python key methods\n", + "single_host = nr.inventory.hosts['lab-csr-011.lab.norn.local']\n", + "# Print out the host\n", + "print(f\"Single host: {single_host}\")" + ] + }, + { + "cell_type": "markdown", + "id": "streaming-republican", + "metadata": {}, + "source": [ + "We can now print out all the data associated to the host `lab-csr-011.lab.norn.local` by dumping the dictionary structure:" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "informal-greece", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "==================================================\n", + "Displaying information for host: lab-csr-011.lab.norn.local\n", + "{\n", + " \"name\": \"lab-csr-011.lab.norn.local\",\n", + " \"connection_options\": {},\n", + " \"groups\": [\n", + " \"ios\",\n", + " \"lab\",\n", + " \"mel\"\n", + " ],\n", + " \"data\": {\n", + " \"mgmt_ip\": \"10.0.0.16\",\n", + " \"vendor\": \"cisco\",\n", + " \"device_type\": \"router\",\n", + " \"os_version\": \"16.6.4\",\n", + " \"site_code\": \"mel\"\n", + " },\n", + " \"hostname\": \"lab-csr-011.lab.norn.local\",\n", + " \"port\": null,\n", + " \"username\": null,\n", + " \"password\": null,\n", + " \"platform\": null\n", + "}\n", + "==================================================\n" + ] + } + ], + "source": [ + "# Import the JSON module\n", + "import json\n", + "# Dump the dictionary, assign to variable\n", + "single_host_data = json.dumps(single_host.dict(), indent=2)\n", + "# Print seperator\n", + "print(\"=\" * 50)\n", + "# Print header and host data structure\n", + "print(f\"Displaying information for host: {single_host}\")\n", + "print(f\"{single_host_data}\")\n", + "# Print seperator\n", + "print(\"=\" * 50)" + ] + }, + { + "cell_type": "markdown", + "id": "delayed-dressing", + "metadata": {}, + "source": [ + "As you can see above, all our data related to the host is available for viewing and usage in any subsequent code. Whether we are using JSON or YAML, the data structure remains the same.\n", + "\n", + "Below are some examples for displaying the values of some of the keys:" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "racial-patio", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Displaying data for host: lab-csr-011.lab.norn.local\n", + "Site code is: mel\n", + "Platform is: None\n", + "OS Version is: 16.6.4\n" + ] + } + ], + "source": [ + "print(f\"Displaying data for host: {single_host}\")\n", + "# Access the site_code value, nested under the data key\n", + "single_host_site_code = single_host.dict()[\"data\"][\"site_code\"]\n", + "print(f\"Site code is: {single_host_site_code}\")\n", + "# Access the platform value\n", + "single_host_platform = single_host.dict()[\"platform\"]\n", + "print(f\"Platform is: {single_host_platform}\")\n", + "# Access the os_version value, nested under the data key\n", + "single_host_os_version = single_host.dict()[\"data\"][\"os_version\"]\n", + "print(f\"OS Version is: {single_host_os_version}\")" + ] + }, + { + "cell_type": "markdown", + "id": "mathematical-vacation", + "metadata": {}, + "source": [ + "The same concept shown above with a `host`, also applies to a `group`. \n", + "\n", + "As we have described how this works, we will show the same concepts as they apply to groups below, with comments:" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "technical-currency", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Number of groups in entire inventory: 15\n", + "Single group: ptl\n", + "==================================================\n", + "Displaying information for group: ptl\n", + "{\n", + " \"name\": \"ptl\",\n", + " \"connection_options\": {},\n", + " \"groups\": [],\n", + " \"data\": {\n", + " \"full_name\": \"Port Louis\",\n", + " \"country\": \"Mauritius\",\n", + " \"region\": \"amea\",\n", + " \"hemisphere\": \"southern\",\n", + " \"site_type\": \"primary\"\n", + " },\n", + " \"hostname\": null,\n", + " \"port\": null,\n", + " \"username\": null,\n", + " \"password\": null,\n", + " \"platform\": null\n", + "}\n", + "==================================================\n", + "Displaying data for group: ptl\n", + "Full Name is: Port Louis\n", + "Platform is: None\n", + "Region is: amea\n" + ] + } + ], + "source": [ + "# Import modules\n", + "from nornir import InitNornir\n", + "from nornir.core.filter import F\n", + "import json\n", + "\n", + "# Initialise nornir\n", + "nr = InitNornir(config_file=\"filtering_deep_dive/config.yaml\")\n", + "# Print the number of groups in the inventory\n", + "print(f\"Number of groups in entire inventory: {len(nr.inventory.groups)}\")\n", + "# Filter the entire group inventory on one group\n", + "single_group = nr.inventory.groups['ptl']\n", + "# Print out the group\n", + "print(f\"Single group: {single_group}\")\n", + "\n", + "# Dump the dictionary, assign to variable\n", + "single_group_data = json.dumps(single_group.dict(), indent=2)\n", + "# Print seperator\n", + "print(\"=\" * 50)\n", + "# Print header and host data structure\n", + "print(f\"Displaying information for group: {single_group}\")\n", + "print(f\"{single_group_data}\")\n", + "# Print seperator\n", + "print(\"=\" * 50)\n", + "\n", + "print(f\"Displaying data for group: {single_group}\")\n", + "# Access the full_name value, nested under the data key\n", + "single_group_site_code = single_group.dict()[\"data\"][\"full_name\"]\n", + "print(f\"Full Name is: {single_group_site_code}\")\n", + "# Access the platform value\n", + "single_group_platform = single_group.dict()[\"platform\"]\n", + "print(f\"Platform is: {single_group_platform}\")\n", + "# Access the os_version value, nested under the data key\n", + "single_group_region = single_group.dict()[\"data\"][\"region\"]\n", + "print(f\"Region is: {single_group_region}\")" + ] + }, + { + "cell_type": "markdown", + "id": "creative-hearts", + "metadata": {}, + "source": [ + "By now, you should have an understanding of the following regarding inventory custom data: \n", + " - *What is nornir custom data?* \n", + " - *How can it be stored?* \n", + " - *How can I access it?* \n", + " - *How can I view and troubleshoot it?* \n", + " \n", + "In the next section, we will now revert back to nornir filtering, which will build off your understanding of these concepts." + ] + }, + { + "cell_type": "markdown", + "id": "korean-suffering", + "metadata": {}, + "source": [ + "## Filtering Types\n", + "\n", + "nornir offers three types of filtering capabilities:\n", + "\n", + "- basic/intermediate filtering using the `filter` method\n", + "- advanced filtering using the `F` object\n", + "- advanced filtering using filter functions\n", + "\n", + "It should be noted that the `F` object filtering method can address all filtering requirements of the `filter` method, but the `filter` method cannot address all the filtering requirements of the `F` object. This tutorial will explore both filtering methods, so you can understand their potential use-cases, limitations and trade-offs.\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "narrow-ranking", + "metadata": {}, + "source": [ + "## Basic Filtering\n", + "\n", + "Let's explore the `filter` method, which can used for straight forward filtering requirements. We will reinitialise the same nornir inventory introduced in the top of this tutorial:" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "surprising-aircraft", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "There are 27 hosts in this tutorial inventory.\n", + "There are 15 groups in this tutorial inventory.\n" + ] + } + ], + "source": [ + "# Import modules\n", + "from nornir import InitNornir\n", + "from nornir.core.filter import F\n", + "\n", + "# Initialise nornir\n", + "nr = InitNornir(config_file=\"filtering_deep_dive/config.yaml\")\n", + "# Informational printouts\n", + "print(f\"There are {len(nr.inventory.hosts)} hosts in this tutorial inventory.\")\n", + "print(f\"There are {len(nr.inventory.groups)} groups in this tutorial inventory.\")" + ] + }, + { + "cell_type": "markdown", + "id": "aboriginal-disability", + "metadata": {}, + "source": [ + "The basic `filter` method allows to filter on any key attributable to a `host` or a `group`. In the example below, we will filter the inventory on a single host:" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "czech-country", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Filtering entire inventory on lab-arista-02.lab.norn.local ...\n", + "Total results found: 1\n", + "Host: lab-arista-02.lab.norn.local - Hostname: lab-arista-02.lab.norn.local\n" + ] + } + ], + "source": [ + "# Assign filter value to a variable for usage\n", + "filter_query = \"lab-arista-02.lab.norn.local\"\n", + "# Filter inventory for all hostnames which equal the filter value\n", + "target_hosts = nr.filter(hostname=filter_query)\n", + "print(f\"Filtering entire inventory on {filter_query} ...\")\n", + "print(f\"Total results found: {len(target_hosts.inventory.hosts)}\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in target_hosts.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Hostname: {data.hostname}\"\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "spectacular-forwarding", + "metadata": {}, + "source": [ + "### Host-based basic filters\n", + "\n", + "Let's look at some more useful examples below whereby we filter on properties directly attributed to a host, such as: \n", + "\n", + "- filter hosts by vendor\n", + "- filter hosts by device_type\n", + "- filter hosts by mgmt_ip\n" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "pursuant-sculpture", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "==================================================\n", + "The hosts which have vendor palo alto are:\n", + "Host: lab-paloalto-01.lab.djft.local - Vendor: palo alto\n", + "Host: lab-paloalto-02.lab.norn.local - Vendor: palo alto\n", + "Host: prd-paloalto-01.prd.norn.local - Vendor: palo alto\n", + "Host: prd-paloalto-02.prd.norn.local - Vendor: palo alto\n", + "Host: tst-paloalto-01.tst.norn.local - Vendor: palo alto\n", + "Host: tst-paloalto-02.tst.norn.local - Vendor: palo alto\n", + "Total: 6\n", + "==================================================\n", + "==================================================\n", + "The hosts which have device type switch are:\n", + "Host: lab-arista-01.lab.norn.local - Device Type: switch\n", + "Host: lab-arista-02.lab.norn.local - Device Type: switch\n", + "Host: lab-nxos-01.lab.norn.local - Device Type: switch\n", + "Host: lab-junos-06.lab.norn.local - Device Type: switch\n", + "Host: prd-arista-01.prd.norn.local - Device Type: switch\n", + "Host: prd-arista-02.prd.nron.local - Device Type: switch\n", + "Host: prd-nxos-01.prd.norn.local - Device Type: switch\n", + "Host: prd-junos-06.prd.norn.local - Device Type: switch\n", + "Host: tst-arista-01.tst.norn.local - Device Type: switch\n", + "Host: tstt-arista-02.tst.norn.local - Device Type: switch\n", + "Host: tst-nxos-01.tst.norn.local - Device Type: switch\n", + "Host: tst-junos-06.tst.norn.local - Device Type: switch\n", + "Total: 12\n", + "==================================================\n", + "==================================================\n", + "The hosts which have management IP address 10.0.0.16 are:\n", + "Host: lab-csr-011.lab.norn.local - Management IP Address: 10.0.0.16\n", + "Total: 1\n", + "==================================================\n" + ] + } + ], + "source": [ + "# Import modules\n", + "from nornir import InitNornir\n", + "# Initialise nornir\n", + "nr = InitNornir(config_file=\"filtering_deep_dive/config.yaml\")\n", + "\n", + "# Use Case 1 - filter hosts by vendor\n", + "# Assign vendor to variable for later usage\n", + "vendor=\"palo alto\"\n", + "# Execute filter based on vendor\n", + "target_hosts = nr.filter(vendor=vendor)\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(f\"The hosts which have vendor {vendor} are:\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in target_hosts.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Vendor: {data['vendor']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(target_hosts.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "\n", + "# Use Case 2 - filter hosts by device_type\n", + "# Assign device_type to variable for later usage\n", + "device_type=\"switch\"\n", + "# Execute filter based on device_type\n", + "target_hosts = nr.filter(device_type=device_type)\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(f\"The hosts which have device type {device_type} are:\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in target_hosts.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Device Type: {data['device_type']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(target_hosts.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "\n", + "\n", + "# Use Case 3 - filter hosts by mgmt_ip\n", + "# Assign mgmt_ip to variable for later usage\n", + "mgmt_ip=\"10.0.0.16\"\n", + "# Execute filter based on mgmt_ip\n", + "target_hosts = nr.filter(mgmt_ip=mgmt_ip)\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(f\"The hosts which have management IP address {mgmt_ip} are:\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in target_hosts.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Management IP Address: {data['mgmt_ip']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(target_hosts.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)" + ] + }, + { + "cell_type": "markdown", + "id": "acceptable-palace", + "metadata": {}, + "source": [ + "### Host-based basic filters (from group inheritance)\n", + "\n", + "As nornir uses an [inheritance model](https://nornir.readthedocs.io/en/latest/tutorial/inventory.html?#Inheritance-model), we filter on group-based attributes which are inherited down to the host.\n", + "\n", + "In the examples below, we will filter the inventory based on some group-based attributes which inherited from their group values: \n", + "\n", + "- filter hosts by platform\n", + "- filter hosts by production equals false\n", + "- filter hosts by site_type of secondary\n" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "confirmed-february", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "==================================================\n", + "The hosts which have platform junos are:\n", + "Host: lab-junos-01.lab.norn.local - Platform: junos\n", + "Host: lab-junos-06.lab.norn.local - Platform: junos\n", + "Host: prd-junos-01.prd.norn.local - Platform: junos\n", + "Host: prd-junos-06.prd.norn.local - Platform: junos\n", + "Host: tst-junos-01.tst.norn.local - Platform: junos\n", + "Host: tst-junos-06.tst.norn.local - Platform: junos\n", + "Total: 6\n", + "==================================================\n", + "==================================================\n", + "The hosts which have production boolean value of False are:\n", + "Host: lab-csr-011.lab.norn.local - Production: False\n", + "Host: dfjt-r001.lab.norn.local - Production: False\n", + "Host: lab-arista-01.lab.norn.local - Production: False\n", + "Host: lab-arista-02.lab.norn.local - Production: False\n", + "Host: lab-junos-01.lab.norn.local - Production: False\n", + "Host: lab-nxos-01.lab.norn.local - Production: False\n", + "Host: lab-paloalto-01.lab.djft.local - Production: False\n", + "Host: lab-paloalto-02.lab.norn.local - Production: False\n", + "Host: lab-junos-06.lab.norn.local - Production: False\n", + "Host: tst-csr-01.tst.norn.local - Production: False\n", + "Host: dfjt-r001.tst.norn.local - Production: False\n", + "Host: tst-arista-01.tst.norn.local - Production: False\n", + "Host: tstt-arista-02.tst.norn.local - Production: False\n", + "Host: tst-junos-01.tst.norn.local - Production: False\n", + "Host: tst-nxos-01.tst.norn.local - Production: False\n", + "Host: tst-paloalto-01.tst.norn.local - Production: False\n", + "Host: tst-paloalto-02.tst.norn.local - Production: False\n", + "Host: tst-junos-06.tst.norn.local - Production: False\n", + "Total: 18\n", + "==================================================\n", + "==================================================\n", + "The hosts which have site_type of secondary are:\n", + "Host: tst-nxos-01.tst.norn.local - Site Type: secondary\n", + "Host: tst-paloalto-01.tst.norn.local - Site Type: secondary\n", + "Host: tst-paloalto-02.tst.norn.local - Site Type: secondary\n", + "Host: tst-junos-06.tst.norn.local - Site Type: secondary\n", + "Total: 4\n", + "==================================================\n" + ] + } + ], + "source": [ + "# Import modules\n", + "from nornir import InitNornir\n", + "# Initialise nornir\n", + "nr = InitNornir(config_file=\"filtering_deep_dive/config.yaml\")\n", + "\n", + "# Use Case 1 - filter hosts by platform\n", + "# Assign platform to variable for later usage\n", + "platform=\"junos\"\n", + "# Execute filter based on platform\n", + "target_hosts = nr.filter(platform=platform)\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(f\"The hosts which have platform {platform} are:\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in target_hosts.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Platform: {data.platform}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(target_hosts.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "\n", + "# Use Case 2 - filter hosts by production equals false\n", + "# Assign production equals false to variable for later usage\n", + "production = False\n", + "# Execute filter based on production\n", + "target_hosts = nr.filter(production=production)\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(f\"The hosts which have production boolean value of {production} are:\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in target_hosts.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Production: {data['production']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(target_hosts.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "\n", + "\n", + "# Use Case 3 - filter hosts by site_type of tertiary\n", + "# Assign site_type of secondary to variable for later usage\n", + "site_type=\"secondary\"\n", + "# Execute filter based on site_type\n", + "target_hosts = nr.filter(site_type=site_type)\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(f\"The hosts which have site_type of {site_type} are:\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in target_hosts.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Site Type: {data['site_type']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(target_hosts.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)" + ] + }, + { + "cell_type": "markdown", + "id": "human-accreditation", + "metadata": {}, + "source": [ + "## Intermediate filtering\n", + "\n", + "We can chain or join filters together using the `filter` method to be narrow down results and end up with specific devices.\n", + "\n", + "In the examples below, we will use output of a filter result and feed that into the next filter and filter incrementally to end up with a specific result of the Christchurch Cisco Switch." + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "compact-intent", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "==================================================\n", + "All cisco devices\n", + "Host: lab-csr-011.lab.norn.local - Vendor: cisco\n", + "Host: dfjt-r001.lab.norn.local - Vendor: cisco\n", + "Host: lab-nxos-01.lab.norn.local - Vendor: cisco\n", + "Host: prd-csr-01.prd.norn.local - Vendor: cisco\n", + "Host: dfjt-r001.prd.norn.local - Vendor: cisco\n", + "Host: prd-nxos-01.prd.norn.local - Vendor: cisco\n", + "Host: tst-csr-01.tst.norn.local - Vendor: cisco\n", + "Host: dfjt-r001.tst.norn.local - Vendor: cisco\n", + "Host: tst-nxos-01.tst.norn.local - Vendor: cisco\n", + "Total: 9\n", + "==================================================\n", + "==================================================\n", + "All cisco switches\n", + "Host: lab-nxos-01.lab.norn.local - Device Type: switch\n", + "Host: prd-nxos-01.prd.norn.local - Device Type: switch\n", + "Host: tst-nxos-01.tst.norn.local - Device Type: switch\n", + "Total: 3\n", + "==================================================\n", + "==================================================\n", + "All Christchuch cisco switches\n", + "Host: tst-nxos-01.tst.norn.local \n", + " - Vendor: cisco\n", + " - Device Type: switch\n", + " - Site Name: Christchurch\n", + "Total: 1\n", + "==================================================\n" + ] + } + ], + "source": [ + "# Import modules\n", + "from nornir import InitNornir\n", + "# Initialise nornir\n", + "nr = InitNornir(config_file=\"filtering_deep_dive/config.yaml\")\n", + "# Filter all devices for Cisco devices\n", + "cisco_devices = nr.filter(vendor=\"cisco\")\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(\"All cisco devices\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in cisco_devices.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Vendor: {data['vendor']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(cisco_devices.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "# Filter all Cisco devices for Cisco switches\n", + "cisco_switches = cisco_devices.filter(device_type=\"switch\")\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(\"All cisco switches\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in cisco_switches.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Device Type: {data['device_type']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(cisco_switches.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "# Filter all Cisco switches for Christchurch switches\n", + "chc_cisco_switches = cisco_switches.filter(full_name=\"Christchurch\")\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(\"All Christchuch cisco switches\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in chc_cisco_switches.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \\n\"\n", + " + \" \" * 8 + f\"- Vendor: {data['vendor']}\\n\"\n", + " + \" \" * 8 + f\"- Device Type: {data['device_type']}\\n\"\n", + " + \" \" * 8 + f\"- Site Name: {data['full_name']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(chc_cisco_switches.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)" + ] + }, + { + "cell_type": "markdown", + "id": "favorite-technical", + "metadata": {}, + "source": [ + "## Advanced filtering\n", + "\n", + "The final and most powerful method of filtering is using the `F` object. As mentioned in sections above, the `F` object can perform all forms of filtering.\n", + "\n", + "In this section we will cover: \n", + " - `F` object filter operators \n", + " - `F` object filter operations \n", + " - filter functions using `filter_func`\n" + ] + }, + { + "cell_type": "markdown", + "id": "arabic-gabriel", + "metadata": {}, + "source": [ + "### F object filter operators\n", + "\n", + "There are three `F` filter operators which are described below:\n", + "\n", + "| Character Pattern | Description |\n", + "| ---------- | ------------ |\n", + "|`~` | NOT |\n", + "|`&` | AND |\n", + "|`\\|` | OR |\n", + "\n", + "In the proceeding code, we will show examples of these in use:" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "headed-commission", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "==================================================\n", + "All non-junos devices - using NOT operator\n", + "Host: lab-csr-011.lab.norn.local - Platform: ios\n", + "Host: dfjt-r001.lab.norn.local - Platform: ios\n", + "Host: lab-arista-01.lab.norn.local - Platform: eos\n", + "Host: lab-arista-02.lab.norn.local - Platform: eos\n", + "Host: lab-nxos-01.lab.norn.local - Platform: nxos\n", + "Host: lab-paloalto-01.lab.djft.local - Platform: paloalto_panos\n", + "Host: lab-paloalto-02.lab.norn.local - Platform: paloalto_panos\n", + "Host: prd-csr-01.prd.norn.local - Platform: ios\n", + "Host: dfjt-r001.prd.norn.local - Platform: ios\n", + "Host: prd-arista-01.prd.norn.local - Platform: eos\n", + "Host: prd-arista-02.prd.nron.local - Platform: eos\n", + "Host: prd-nxos-01.prd.norn.local - Platform: nxos_ssh\n", + "Host: prd-paloalto-01.prd.norn.local - Platform: paloalto_panos\n", + "Host: prd-paloalto-02.prd.norn.local - Platform: paloalto_panos\n", + "Host: tst-csr-01.tst.norn.local - Platform: ios\n", + "Host: dfjt-r001.tst.norn.local - Platform: ios\n", + "Host: tst-arista-01.tst.norn.local - Platform: eos\n", + "Host: tstt-arista-02.tst.norn.local - Platform: eos\n", + "Host: tst-nxos-01.tst.norn.local - Platform: nxos\n", + "Host: tst-paloalto-01.tst.norn.local - Platform: paloalto_panos\n", + "Host: tst-paloalto-02.tst.norn.local - Platform: paloalto_panos\n", + "Total: 21\n", + "==================================================\n", + "==================================================\n", + "All nxos switches - using AND operator\n", + "Host: lab-nxos-01.lab.norn.local - Platform: nxos - Device Type: switch\n", + "Host: tst-nxos-01.tst.norn.local - Platform: nxos - Device Type: switch\n", + "Total: 2\n", + "==================================================\n", + "==================================================\n", + "All ptl or chc site code devices - using OR operator\n", + "Host: tst-arista-01.tst.norn.local - Site Code: ptl\n", + "Host: tstt-arista-02.tst.norn.local - Site Code: ptl\n", + "Host: tst-junos-01.tst.norn.local - Site Code: ptl\n", + "Host: tst-nxos-01.tst.norn.local - Site Code: chc\n", + "Host: tst-paloalto-01.tst.norn.local - Site Code: chc\n", + "Host: tst-paloalto-02.tst.norn.local - Site Code: chc\n", + "Host: tst-junos-06.tst.norn.local - Site Code: chc\n", + "Total: 7\n", + "==================================================\n" + ] + } + ], + "source": [ + "# Import modules\n", + "from nornir import InitNornir\n", + "from nornir.core.filter import F\n", + "# Initialise nornir\n", + "nr = InitNornir(config_file=\"filtering_deep_dive/config.yaml\")\n", + "# Use Case 1 - NOT operator\n", + "# Filter for NOT equals platform of \"junos\"\n", + "not_junos = nr.filter(~F(platform__eq=\"junos\"))\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(\"All non-junos devices - using NOT operator\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in not_junos.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Platform: {data.platform}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(not_junos.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "# Use Case 2 - AND operator\n", + "# Filter for platform equals \"nxos\" AND device_type equals \"switch\" \n", + "nxos_switches = nr.filter(F(platform__eq=\"nxos\") & F(device_type__eq=\"switch\"))\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(\"All nxos switches - using AND operator\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in nxos_switches.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Platform: {data.platform} \"\n", + " + f\"- Device Type: {data['device_type']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(nxos_switches.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "# Use Case 3 - OR operator\n", + "# Filter for site code equals \"ptl\" OR site code equals \"chc\"\n", + "ptl_or_chc_devices = nr.filter(\n", + " F(site_code__eq=\"ptl\") | F(site_code__eq=\"chc\")\n", + ")\n", + "print(\"=\" * 50)\n", + "print(\"All ptl or chc site code devices - using OR operator\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in ptl_or_chc_devices.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Site Code: {data['site_code']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(ptl_or_chc_devices.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)" + ] + }, + { + "cell_type": "markdown", + "id": "coordinate-headline", + "metadata": {}, + "source": [ + "### F object operations\n", + "\n", + "There are eleven F filter operations which are described below:\n", + "\n", + "| Character Pattern | Description | Type Usage |\n", + "| ---------- | ------------ |------ |\n", + "|`eq` | Equals | string, integer |\n", + "|`ge` | Greater than or equal to | integer |\n", + "|`gt`| Greater than | integer |\n", + "|`le` | Less than or equal to | integer |\n", + "|`lt`| Less than | integer |\n", + "|`contains` | Contains | string |\n", + "|`startswith` | Starts with | string |\n", + "|`endswith` | ends with | string |\n", + "|`any` | Any of the following | string |\n", + "|`has_parent_group`| Host has a parent group | string |\n", + "|`in`| In | string |\n", + "|`all`| All of | list |\n", + "\n", + "In the proceeding code, we will show examples of these in use. \n", + "**NOTE: These are spread out over multiple snippets of code to cut down the amount of interpreting you need to perform at once**" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "authentic-opposition", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "==================================================\n", + "All junos devices - using eq operation\n", + "Host: lab-junos-01.lab.norn.local - Platform: junos\n", + "Host: lab-junos-06.lab.norn.local - Platform: junos\n", + "Host: prd-junos-01.prd.norn.local - Platform: junos\n", + "Host: prd-junos-06.prd.norn.local - Platform: junos\n", + "Host: tst-junos-01.tst.norn.local - Platform: junos\n", + "Host: tst-junos-06.tst.norn.local - Platform: junos\n", + "Total: 6\n", + "==================================================\n", + "==================================================\n", + "All devices with SLA greater than or equal to 80 - using gt operation\n", + "Host: prd-csr-01.prd.norn.local - SLA: 90\n", + "Host: dfjt-r001.prd.norn.local - SLA: 90\n", + "Host: prd-arista-01.prd.norn.local - SLA: 90\n", + "Host: prd-arista-02.prd.nron.local - SLA: 90\n", + "Host: prd-junos-01.prd.norn.local - SLA: 90\n", + "Host: prd-nxos-01.prd.norn.local - SLA: 90\n", + "Host: prd-paloalto-01.prd.norn.local - SLA: 90\n", + "Host: prd-paloalto-02.prd.norn.local - SLA: 90\n", + "Host: prd-junos-06.prd.norn.local - SLA: 90\n", + "Host: tst-csr-01.tst.norn.local - SLA: 80\n", + "Host: dfjt-r001.tst.norn.local - SLA: 80\n", + "Host: tst-arista-01.tst.norn.local - SLA: 80\n", + "Host: tstt-arista-02.tst.norn.local - SLA: 80\n", + "Host: tst-junos-01.tst.norn.local - SLA: 80\n", + "Host: tst-nxos-01.tst.norn.local - SLA: 80\n", + "Host: tst-paloalto-01.tst.norn.local - SLA: 80\n", + "Host: tst-paloalto-02.tst.norn.local - SLA: 80\n", + "Host: tst-junos-06.tst.norn.local - SLA: 80\n", + "Total: 18\n", + "==================================================\n", + "==================================================\n", + "All devices with SLA greater than 79 - using gt operation\n", + "Host: prd-csr-01.prd.norn.local - SLA: 90\n", + "Host: dfjt-r001.prd.norn.local - SLA: 90\n", + "Host: prd-arista-01.prd.norn.local - SLA: 90\n", + "Host: prd-arista-02.prd.nron.local - SLA: 90\n", + "Host: prd-junos-01.prd.norn.local - SLA: 90\n", + "Host: prd-nxos-01.prd.norn.local - SLA: 90\n", + "Host: prd-paloalto-01.prd.norn.local - SLA: 90\n", + "Host: prd-paloalto-02.prd.norn.local - SLA: 90\n", + "Host: prd-junos-06.prd.norn.local - SLA: 90\n", + "Host: tst-csr-01.tst.norn.local - SLA: 80\n", + "Host: dfjt-r001.tst.norn.local - SLA: 80\n", + "Host: tst-arista-01.tst.norn.local - SLA: 80\n", + "Host: tstt-arista-02.tst.norn.local - SLA: 80\n", + "Host: tst-junos-01.tst.norn.local - SLA: 80\n", + "Host: tst-nxos-01.tst.norn.local - SLA: 80\n", + "Host: tst-paloalto-01.tst.norn.local - SLA: 80\n", + "Host: tst-paloalto-02.tst.norn.local - SLA: 80\n", + "Host: tst-junos-06.tst.norn.local - SLA: 80\n", + "Total: 18\n", + "==================================================\n", + "==================================================\n", + "All devices with SLA less than or equal to 80 - using le operation\n", + "Host: lab-csr-011.lab.norn.local - SLA: 70\n", + "Host: dfjt-r001.lab.norn.local - SLA: 70\n", + "Host: lab-arista-01.lab.norn.local - SLA: 70\n", + "Host: lab-arista-02.lab.norn.local - SLA: 70\n", + "Host: lab-junos-01.lab.norn.local - SLA: 70\n", + "Host: lab-nxos-01.lab.norn.local - SLA: 70\n", + "Host: lab-paloalto-01.lab.djft.local - SLA: 70\n", + "Host: lab-paloalto-02.lab.norn.local - SLA: 70\n", + "Host: lab-junos-06.lab.norn.local - SLA: 70\n", + "Host: tst-csr-01.tst.norn.local - SLA: 80\n", + "Host: dfjt-r001.tst.norn.local - SLA: 80\n", + "Host: tst-arista-01.tst.norn.local - SLA: 80\n", + "Host: tstt-arista-02.tst.norn.local - SLA: 80\n", + "Host: tst-junos-01.tst.norn.local - SLA: 80\n", + "Host: tst-nxos-01.tst.norn.local - SLA: 80\n", + "Host: tst-paloalto-01.tst.norn.local - SLA: 80\n", + "Host: tst-paloalto-02.tst.norn.local - SLA: 80\n", + "Host: tst-junos-06.tst.norn.local - SLA: 80\n", + "Total: 18\n", + "==================================================\n", + "==================================================\n", + "All devices with SLA less than 80 - using lt operation\n", + "Host: lab-csr-011.lab.norn.local - SLA: 70\n", + "Host: dfjt-r001.lab.norn.local - SLA: 70\n", + "Host: lab-arista-01.lab.norn.local - SLA: 70\n", + "Host: lab-arista-02.lab.norn.local - SLA: 70\n", + "Host: lab-junos-01.lab.norn.local - SLA: 70\n", + "Host: lab-nxos-01.lab.norn.local - SLA: 70\n", + "Host: lab-paloalto-01.lab.djft.local - SLA: 70\n", + "Host: lab-paloalto-02.lab.norn.local - SLA: 70\n", + "Host: lab-junos-06.lab.norn.local - SLA: 70\n", + "Total: 9\n", + "==================================================\n" + ] + } + ], + "source": [ + "# Import modules\n", + "from nornir import InitNornir\n", + "from nornir.core.filter import F\n", + "# Initialise nornir\n", + "nr = InitNornir(config_file=\"filtering_deep_dive/config.yaml\")\n", + "# Use Case 1 - eq operation\n", + "# Filter for equals platform of \"junos\"\n", + "junos_devices = nr.filter(F(platform__eq=\"junos\"))\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(\"All junos devices - using eq operation\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in junos_devices.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Platform: {data.platform}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(junos_devices.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "# Use Case 2 - ge operation\n", + "# Filter for sla greater than or equal to 80\n", + "sla_eighty_or_greater = nr.filter(F(sla__ge=80))\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(\"All devices with SLA greater than or equal to 80 - using gt operation\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in sla_eighty_or_greater.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- SLA: {data['sla']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(sla_eighty_or_greater.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "# Use Case 3 - gt operation\n", + "# Filter for sla greater than 79\n", + "sla_more_than_seventy_nine = nr.filter(F(sla__gt=79))\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(\"All devices with SLA greater than 79 - using gt operation\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in sla_more_than_seventy_nine.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- SLA: {data['sla']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(sla_more_than_seventy_nine.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "# Use Case 4 - le operation\n", + "# Filter for sla lesser than or equal to 80\n", + "sla_eighty_or_lesser = nr.filter(F(sla__le=80))\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(\"All devices with SLA less than or equal to 80 - using le operation\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in sla_eighty_or_lesser.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- SLA: {data['sla']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(sla_eighty_or_lesser.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "# Use Case 4 - lt operation\n", + "# Filter for sla lesser than 80\n", + "sla_less_than_eighty = nr.filter(F(sla__lt=80))\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(\"All devices with SLA less than 80 - using lt operation\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in sla_less_than_eighty.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- SLA: {data['sla']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(sla_less_than_eighty.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "thrown-greene", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "==================================================\n", + "All devices contain 'nos' in platform - using contain operation\n", + "Host: lab-junos-01.lab.norn.local - Platform: junos\n", + "Host: lab-paloalto-01.lab.djft.local - Platform: paloalto_panos\n", + "Host: lab-paloalto-02.lab.norn.local - Platform: paloalto_panos\n", + "Host: lab-junos-06.lab.norn.local - Platform: junos\n", + "Host: prd-junos-01.prd.norn.local - Platform: junos\n", + "Host: prd-paloalto-01.prd.norn.local - Platform: paloalto_panos\n", + "Host: prd-paloalto-02.prd.norn.local - Platform: paloalto_panos\n", + "Host: prd-junos-06.prd.norn.local - Platform: junos\n", + "Host: tst-junos-01.tst.norn.local - Platform: junos\n", + "Host: tst-paloalto-01.tst.norn.local - Platform: paloalto_panos\n", + "Host: tst-paloalto-02.tst.norn.local - Platform: paloalto_panos\n", + "Host: tst-junos-06.tst.norn.local - Platform: junos\n", + "Total: 12\n", + "==================================================\n", + "==================================================\n", + "All devices starts with 'am' in region - using startswith operation\n", + "Host: dfjt-r001.lab.norn.local - Platform: amea\n", + "Host: lab-arista-01.lab.norn.local - Platform: amer\n", + "Host: lab-junos-01.lab.norn.local - Platform: amer\n", + "Host: lab-nxos-01.lab.norn.local - Platform: amer\n", + "Host: lab-paloalto-02.lab.norn.local - Platform: amea\n", + "Host: tst-arista-01.tst.norn.local - Platform: amea\n", + "Host: tstt-arista-02.tst.norn.local - Platform: amea\n", + "Host: tst-junos-01.tst.norn.local - Platform: amea\n", + "Total: 8\n", + "==================================================\n", + "==================================================\n", + "All devices ends with 'l' in site code - using endswith operation\n", + "Host: lab-csr-011.lab.norn.local - Platform: mel\n", + "Host: lab-arista-01.lab.norn.local - Platform: mtl\n", + "Host: lab-arista-02.lab.norn.local - Platform: mel\n", + "Host: lab-junos-01.lab.norn.local - Platform: mtl\n", + "Host: lab-nxos-01.lab.norn.local - Platform: mtl\n", + "Host: lab-paloalto-01.lab.djft.local - Platform: mel\n", + "Host: lab-junos-06.lab.norn.local - Platform: mel\n", + "Host: prd-csr-01.prd.norn.local - Platform: mel\n", + "Host: dfjt-r001.prd.norn.local - Platform: mel\n", + "Host: prd-arista-01.prd.norn.local - Platform: mel\n", + "Host: prd-arista-02.prd.nron.local - Platform: mel\n", + "Host: prd-junos-01.prd.norn.local - Platform: mel\n", + "Host: prd-nxos-01.prd.norn.local - Platform: mel\n", + "Host: prd-paloalto-01.prd.norn.local - Platform: mel\n", + "Host: prd-paloalto-02.prd.norn.local - Platform: mel\n", + "Host: prd-junos-06.prd.norn.local - Platform: mel\n", + "Host: tst-csr-01.tst.norn.local - Platform: mel\n", + "Host: dfjt-r001.tst.norn.local - Platform: mel\n", + "Host: tst-arista-01.tst.norn.local - Platform: ptl\n", + "Host: tstt-arista-02.tst.norn.local - Platform: ptl\n", + "Host: tst-junos-01.tst.norn.local - Platform: ptl\n", + "Total: 21\n", + "==================================================\n", + "==================================================\n", + "All devices which contains ['catos', 'ios', 'iosxe', 'iosxr', 'nxos'] - using contains operation\n", + "Host: lab-csr-011.lab.norn.local - Platform: ios\n", + "Host: dfjt-r001.lab.norn.local - Platform: ios\n", + "Host: lab-nxos-01.lab.norn.local - Platform: nxos\n", + "Host: prd-csr-01.prd.norn.local - Platform: ios\n", + "Host: dfjt-r001.prd.norn.local - Platform: ios\n", + "Host: tst-csr-01.tst.norn.local - Platform: ios\n", + "Host: dfjt-r001.tst.norn.local - Platform: ios\n", + "Host: tst-nxos-01.tst.norn.local - Platform: nxos\n", + "Total: 8\n", + "==================================================\n", + "==================================================\n", + "All devices which has parent group of test - using has_parent_group operation\n", + "Host: tst-csr-01.tst.norn.local - Production: False\n", + "Host: dfjt-r001.tst.norn.local - Production: False\n", + "Host: tst-arista-01.tst.norn.local - Production: False\n", + "Host: tstt-arista-02.tst.norn.local - Production: False\n", + "Host: tst-junos-01.tst.norn.local - Production: False\n", + "Host: tst-nxos-01.tst.norn.local - Production: False\n", + "Host: tst-paloalto-01.tst.norn.local - Production: False\n", + "Host: tst-paloalto-02.tst.norn.local - Production: False\n", + "Host: tst-junos-06.tst.norn.local - Production: False\n", + "Total: 9\n", + "==================================================\n", + "==================================================\n", + "All devices which are in the list ['eos', 'paloalto_panos', 'junos'] - using in operation\n", + "Host: lab-arista-01.lab.norn.local - Platform: eos\n", + "Host: lab-arista-02.lab.norn.local - Platform: eos\n", + "Host: lab-junos-01.lab.norn.local - Platform: junos\n", + "Host: lab-paloalto-01.lab.djft.local - Platform: paloalto_panos\n", + "Host: lab-paloalto-02.lab.norn.local - Platform: paloalto_panos\n", + "Host: lab-junos-06.lab.norn.local - Platform: junos\n", + "Host: prd-arista-01.prd.norn.local - Platform: eos\n", + "Host: prd-arista-02.prd.nron.local - Platform: eos\n", + "Host: prd-junos-01.prd.norn.local - Platform: junos\n", + "Host: prd-paloalto-01.prd.norn.local - Platform: paloalto_panos\n", + "Host: prd-paloalto-02.prd.norn.local - Platform: paloalto_panos\n", + "Host: prd-junos-06.prd.norn.local - Platform: junos\n", + "Host: tst-arista-01.tst.norn.local - Platform: eos\n", + "Host: tstt-arista-02.tst.norn.local - Platform: eos\n", + "Host: tst-junos-01.tst.norn.local - Platform: junos\n", + "Host: tst-paloalto-01.tst.norn.local - Platform: paloalto_panos\n", + "Host: tst-paloalto-02.tst.norn.local - Platform: paloalto_panos\n", + "Host: tst-junos-06.tst.norn.local - Platform: junos\n", + "Total: 18\n", + "==================================================\n", + "==================================================\n", + "All devices which all the groups ['eos', 'prod', 'mel'] - using all operation\n", + "Host: prd-arista-01.prd.norn.local - Groups: [Group: eos, Group: prod, Group: mel]\n", + "Host: prd-arista-02.prd.nron.local - Groups: [Group: eos, Group: prod, Group: mel]\n", + "Total: 2\n", + "==================================================\n" + ] + } + ], + "source": [ + "# Use Case 5 - contains operation\n", + "# Filter for a platform that contains \"nos\" in it.\n", + "# i.e match \"paloalto_panos\" or \"junos\" but not \"nxos\"\n", + "network_nos = nr.filter(F(platform__contains=\"nos\"))\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(\"All devices contain 'nos' in platform - using contain operation\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in network_nos.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Platform: {data.platform}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(network_nos.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "# Use Case 6 - startswith operation\n", + "# Filter for a platform that starts with \"am\".\n", + "# i.e match \"amer\", \"amea\" but not \"apac\"\n", + "am_devs = nr.filter(F(region__startswith=\"am\"))\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(\"All devices starts with 'am' in region - using startswith operation\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in am_devs.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Platform: {data['region']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(am_devs.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "# Use Case 7 - startswith operation\n", + "# Filter for a platform that ends with \"l\".\n", + "# i.e match \"mtl\", \"mel\" or \"ptl\", but not \"chc\", \"hbt\" or \"bcn\"\n", + "l_site_code_devs = nr.filter(F(site_code__endswith=\"l\"))\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(\"All devices ends with 'l' in site code - using endswith operation\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in l_site_code_devs.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Platform: {data['site_code']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(l_site_code_devs.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "# Use Case 8 - startswith operation\n", + "# Filter for a platform that is any of elements in our cisco_platforms\n", + "# list\n", + "cisco_platforms = [\"catos\", \"ios\", \"iosxe\", \"iosxr\", \"nxos\"]\n", + "cisco_devs = nr.filter(F(platform__any=cisco_platforms))\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(f\"All devices which contains {cisco_platforms} - using contains operation\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in cisco_devs.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Platform: {data.platform}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(cisco_devs.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "# Use Case 9 - has_parent_group operation\n", + "# Filter for any hosts which have the parent group of test\n", + "test_devs = nr.filter(F(has_parent_group=\"test\"))\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(f\"All devices which has parent group of test - using has_parent_group operation\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in test_devs.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Production: {data['production']}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(test_devs.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "# Use Case 10 - in operation\n", + "# Filter for a platform that is in one of elements in our non_cisco_platforms\n", + "# list\n", + "# NOTE: Not sure how different this is to the \"any\" operation in case you\n", + "# were wondering too.\n", + "non_cisco_platforms = [\"eos\", \"paloalto_panos\", \"junos\"]\n", + "non_cisco_devs = nr.filter(F(platform__in=non_cisco_platforms))\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(f\"All devices which are in the list {non_cisco_platforms} - using in operation\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in non_cisco_devs.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Platform: {data.platform}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(non_cisco_devs.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)\n", + "# Use Case 11 - all operation\n", + "# Filter for a device which has all groups\n", + "all_groups = [\"eos\",\"prod\", \"mel\"]\n", + "eos_prod_mel = nr.filter(F(groups__all=all_groups))\n", + "# Print seperator and header\n", + "print(\"=\" * 50)\n", + "print(f\"All devices which all the groups {all_groups} - using all operation\")\n", + "# Iterate over filtered results and printout information\n", + "for host, data in eos_prod_mel.inventory.hosts.items():\n", + " print(\n", + " f\"Host: {host} \"\n", + " + f\"- Groups: {data.groups}\"\n", + " )\n", + "# Print total and seperator\n", + "print(f\"Total: {len(eos_prod_mel.inventory.hosts.items())}\")\n", + "print(\"=\" * 50)" + ] + }, + { + "cell_type": "markdown", + "id": "geological-eating", + "metadata": {}, + "source": [ + "### Filter functions\n", + "\n", + "Filter functions are a powerful method of filtering your nornir inventory through another python function. \n", + "\n", + "Using this method, you can write complex filtering logic and manage that in another function, then simply call them as needed. \n", + "\n", + "In this example, we will introduce a few examples using regex to perform some analysis based on the hostnames, then call those from another function. This is just one idea of many that this can be used for so hopefully it helps spark your imagination." + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "forward-salon", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "==================================================\n", + "The hosts which match the even device naming convention are:\n", + "Host: lab-arista-02.lab.norn.local \n", + "Host: lab-paloalto-02.lab.norn.local \n", + "Host: lab-junos-06.lab.norn.local \n", + "Host: prd-arista-02.prd.nron.local \n", + "Host: prd-paloalto-02.prd.norn.local \n", + "Host: prd-junos-06.prd.norn.local \n", + "Host: tstt-arista-02.tst.norn.local \n", + "Host: tst-paloalto-02.tst.norn.local \n", + "Host: tst-junos-06.tst.norn.local \n", + "Total: 9\n", + "==================================================\n", + "==================================================\n", + "The hosts which match the device naming convention are:\n", + "Host: lab-arista-01.lab.norn.local \n", + "Host: lab-arista-02.lab.norn.local \n", + "Host: lab-junos-01.lab.norn.local \n", + "Host: lab-nxos-01.lab.norn.local \n", + "Host: lab-paloalto-02.lab.norn.local \n", + "Host: lab-junos-06.lab.norn.local \n", + "Host: prd-csr-01.prd.norn.local \n", + "Host: prd-arista-01.prd.norn.local \n", + "Host: prd-junos-01.prd.norn.local \n", + "Host: prd-nxos-01.prd.norn.local \n", + "Host: prd-paloalto-01.prd.norn.local \n", + "Host: prd-paloalto-02.prd.norn.local \n", + "Host: prd-junos-06.prd.norn.local \n", + "Host: tst-csr-01.tst.norn.local \n", + "Host: tst-arista-01.tst.norn.local \n", + "Host: tst-junos-01.tst.norn.local \n", + "Host: tst-nxos-01.tst.norn.local \n", + "Host: tst-paloalto-01.tst.norn.local \n", + "Host: tst-paloalto-02.tst.norn.local \n", + "Host: tst-junos-06.tst.norn.local \n", + "Total: 20\n", + "==================================================\n", + "==================================================\n", + "The hosts which DO NOT match the device naming convention are:\n", + "Host: lab-csr-011.lab.norn.local \n", + "Host: dfjt-r001.lab.norn.local \n", + "Host: lab-paloalto-01.lab.djft.local \n", + "Host: dfjt-r001.prd.norn.local \n", + "Host: prd-arista-02.prd.nron.local \n", + "Host: dfjt-r001.tst.norn.local \n", + "Host: tstt-arista-02.tst.norn.local \n", + "Total: 7\n", + "==================================================\n" + ] + } + ], + "source": [ + "# Import modules\n", + "from nornir import InitNornir\n", + "from nornir.core.filter import F\n", + "import re\n", + "# Initialise nornir\n", + "nr = InitNornir(config_file=\"filtering_deep_dive/config.yaml\")\n", + "\"\"\"\n", + "Below are some example filter functions, which we will call in later functions\n", + "\"\"\"\n", + "\n", + "def even_device_naming_convention(host):\n", + " \"\"\"\n", + " Helper filter function to filter hosts based targeting\n", + " host names which have even number names.\n", + " Examples:\n", + " - lab-junos-08.prd.norn.local\n", + " - lab-arista-22.tst.norn.local\n", + " - lab-nxos-64.lab.norn.local\n", + " :param host: The host you want to filter on\n", + " :return bool: True if it matches, False if it doesn't match\n", + " \"\"\"\n", + " # Perform regex match on host name and return boolean\n", + " if re.match(\".+\\-[0-9][2,4,6,8,0].+\", host.name):\n", + " return True\n", + " else:\n", + " return False\n", + " \n", + " \n", + "def device_name_convention(host):\n", + " \"\"\"\n", + " Helper filter function to filter hosts based targeting\n", + " host names which a specified naming convention\n", + " Examples:\n", + " - lab-junos-08.tst.norn.local\n", + " - lab-arista-22.prd.norn.local\n", + " - lab-nxos-01.lab.norn.local\n", + " :param host: The host you want to filter on\n", + " :return bool: True if it matches, False if it doesn't match\n", + " \"\"\"\n", + " # Perform regex match on host name and return boolean\n", + " if re.match(\"\\w{3}\\-\\w+\\-\\d{2}.\\w{3}.norn.local\", host.name):\n", + " return True\n", + " else:\n", + " return False\n", + "\n", + "\n", + "def non_device_name_convention(host):\n", + " \"\"\"\n", + " Helper filter function to filter hosts based targeting\n", + " host names which do NOT match a specified naming convention\n", + " Examples:\n", + " - lab-junos-08.tstt.norn.local\n", + " - dfjt-arista-22.prd.norn.local\n", + " - lab-nxos-001.lab.nron.local\n", + " :param host: The host you want to filter on\n", + " :return bool: True if does not match, False if it matches the convention\n", + " \"\"\"\n", + " # Perform regex match on host name and return boolean\n", + " if re.match(\"\\w{3}\\-\\w+\\-\\d{2}.\\w{3}.norn.local\", host.name):\n", + " return False\n", + " else:\n", + " return True\n", + "\n", + " \n", + "def filter_functions(nr):\n", + " \"\"\"\n", + " An example of wrapping filter functions to retrieve some more complex\n", + " filtering queries.\n", + " \n", + " Three use cases are shown:\n", + " - Use Case 1 - Filter inventory for \"even\" numbered devices.\n", + " - Use Case 2 - Filter inventory for device which meet\n", + " the naming convention.\n", + " - Use Case 3 - Filter inventory for device which DO NOT meet\n", + " the naming convention.\n", + " \n", + " :param nr: An initialised Nornir inventory, used for processing.\n", + " \"\"\"\n", + " # We use the 'filter_func' option to run our entire inventory through the python\n", + " # function called 'even_device_naming_convention'\n", + " even_device_name_hosts = nr.filter(filter_func=even_device_naming_convention)\n", + " # Print seperator and header\n", + " print(\"=\" * 50)\n", + " print(\"The hosts which match the even device naming convention are:\")\n", + " # Iterate over filtered results and printout information\n", + " for host, data in even_device_name_hosts.inventory.hosts.items():\n", + " print(f\"Host: {host} \")\n", + " # Print total and seperator\n", + " print(f\"Total: {len(even_device_name_hosts.inventory.hosts.items())}\")\n", + " print(\"=\" * 50)\n", + " # Use Case 2 - Devices which match the naming convention\n", + " # We use the 'filter_func' option to run our entire inventory through the python\n", + " # function called 'device_name_convention'\n", + " compliant_naming_convention_hosts = nr.filter(filter_func=device_name_convention)\n", + " # Print seperator and header\n", + " print(\"=\" * 50)\n", + " print(\"The hosts which match the device naming convention are:\")\n", + " # Iterate over filtered results and printout information\n", + " for host, data in compliant_naming_convention_hosts.inventory.hosts.items():\n", + " print(f\"Host: {host} \")\n", + " # Print total and seperator\n", + " print(f\"Total: {len(compliant_naming_convention_hosts.inventory.hosts.items())}\")\n", + " print(\"=\" * 50)\n", + " # Use Case 2 - Devices which DO NOT match the naming convention\n", + " # We use the 'filter_func' option to run our entire inventory through the python\n", + " # function called 'non_device_name_convention'\n", + " non_compliant_naming_convention_hosts = nr.filter(filter_func=non_device_name_convention)\n", + " # Print seperator and header\n", + " print(\"=\" * 50)\n", + " print(\"The hosts which DO NOT match the device naming convention are:\")\n", + " # Iterate over filtered results and printout information\n", + " for host, data in non_compliant_naming_convention_hosts.inventory.hosts.items():\n", + " print(f\"Host: {host} \")\n", + " # Print total and seperator\n", + " print(f\"Total: {len(non_compliant_naming_convention_hosts.inventory.hosts.items())}\")\n", + " print(\"=\" * 50)\n", + "\n", + " \n", + "# Call wrapper function\n", + "filter_functions(nr)" + ] + }, + { + "cell_type": "markdown", + "id": "duplicate-cathedral", + "metadata": {}, + "source": [ + "## Conclusion\n", + "\n", + "Thanks for following along with this tutorial. If you have got to this point, I'm sure you would agree that nornir filtering is powerful and limitless in it's possibilities.\n", + "\n", + "We have covered basic, intermediate and advanced filtering using network-automation specific use-cases. Hopefully this will give you some ideas and insipiration on how to leverage this feature. \n", + "\n", + "There is also a helpful [filtering cheatsheet](https://github.com/nornir-automation/nornir/discussions/647) which has been created for your reference." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/howto/filtering_deep_dive/config.yaml b/docs/howto/filtering_deep_dive/config.yaml new file mode 100644 index 000000000..fbc39df11 --- /dev/null +++ b/docs/howto/filtering_deep_dive/config.yaml @@ -0,0 +1,10 @@ +--- +inventory: + plugin: SimpleInventory + options: + host_file: "filtering_deep_dive/inventory/hosts.yaml" + group_file: "filtering_deep_dive/inventory/groups.yaml" +runner: + plugin: threaded + options: + num_workers: 20 diff --git a/docs/howto/filtering_deep_dive/inventory/groups.yaml b/docs/howto/filtering_deep_dive/inventory/groups.yaml new file mode 100644 index 000000000..8c6bd24d0 --- /dev/null +++ b/docs/howto/filtering_deep_dive/inventory/groups.yaml @@ -0,0 +1,79 @@ +--- +ios: + platform: ios + data: + vendor: cisco +junos: + platform: junos + data: + vendor: juniper +eos: + platform: eos + data: + vendor: arista +nxos: + platform: nxos + data: + vendor: cisco +nxos_ssh: + platform: nxos_ssh + data: + vendor: cisco +panos: + platform: paloalto_panos + data: + vendor: palo alto +lab: + data: + sla: 70 + production: false +prod: + data: + sla: 90 + production: true +test: + data: + sla: 80 + production: false +mel: + data: + full_name: Melbourne + country: Australia + region: apac + hemisphere: southern + site_type: primary +hbt: + data: + full_name: Hobart + country: Australia + region: apac + hemisphere: southern + site_type: tertiary +chc: + data: + full_name: Christchurch + country: New Zealand + region: apac + hemisphere: southern + site_type: secondary +ptl: + data: + full_name: Port Louis + country: Mauritius + region: amea + hemisphere: southern + site_type: primary +mtl: + data: + full_name: Montreal + country: Canada + region: amer + hemisphere: northern + site_type: primary +bcn: + data: + full_name: Barcelona + country: Spain + region: amea + hemisphere: northern + site_type: primary diff --git a/docs/howto/filtering_deep_dive/inventory/groups_extract.yaml b/docs/howto/filtering_deep_dive/inventory/groups_extract.yaml new file mode 100644 index 000000000..ac595eb8f --- /dev/null +++ b/docs/howto/filtering_deep_dive/inventory/groups_extract.yaml @@ -0,0 +1,8 @@ +--- +mel: + data: # Anything under this key is custom data + full_name: Melbourne # This is custom data + country: Australia # So is this + region: apac # Same as this + hemisphere: southern # Also this too + site_type: primary # Yes, and also this diff --git a/docs/howto/filtering_deep_dive/inventory/groups_extract_alternate.yaml b/docs/howto/filtering_deep_dive/inventory/groups_extract_alternate.yaml new file mode 100644 index 000000000..205a3a289 --- /dev/null +++ b/docs/howto/filtering_deep_dive/inventory/groups_extract_alternate.yaml @@ -0,0 +1,12 @@ +--- +mel: + data: # Anything under this key is custom data + full_name: Melbourne + country: Australia + region: apac + hemisphere: southern + site_type: primary + location: # New location data is stored about the site + address: 1 Wurundjeri Street + suburb: Northcote + zip_code: 3070 diff --git a/docs/howto/filtering_deep_dive/inventory/hosts.yaml b/docs/howto/filtering_deep_dive/inventory/hosts.yaml new file mode 100644 index 000000000..f75062de6 --- /dev/null +++ b/docs/howto/filtering_deep_dive/inventory/hosts.yaml @@ -0,0 +1,351 @@ +--- +lab-csr-011.lab.norn.local: + hostname: lab-csr-011.lab.norn.local + groups: + - ios + - lab + - mel + data: + mgmt_ip: 10.0.0.16 + vendor: cisco + device_type: router + os_version: 16.6.4 + site_code: mel + +dfjt-r001.lab.norn.local: + hostname: dfjt-r001.lab.norn.local + groups: + - ios + - lab + - bcn + data: + mgmt_ip: 10.0.0.1 + vendor: cisco + device_type: router + os_version: 16.6.3 + site_code: bcn + +lab-arista-01.lab.norn.local: + hostname: lab-arista-01.lab.norn.local + groups: + - eos + - lab + - mtl + data: + mgmt_ip: 10.0.0.11 + vendor: arista + device_type: switch + os_version: 4.22.0F + site_code: mtl + +lab-arista-02.lab.norn.local: + hostname: lab-arista-02.lab.norn.local + groups: + - eos + - lab + - mel + data: + mgmt_ip: 10.0.0.18 + vendor: arista + device_type: switch + os_version: 4.23.2F + site_code: mel + +lab-junos-01.lab.norn.local: + hostname: lab-junos-01.lab.norn.local + groups: + - junos + - lab + - mtl + data: + mgmt_ip: 10.0.0.15 + vendor: juniper + device_type: router + os_version: 18.4R2-S5 + site_code: mtl + +lab-nxos-01.lab.norn.local: + hostname: lab-nxos-01.lab.norn.local + groups: + - nxos + - lab + - mtl + data: + mgmt_ip: 10.0.0.14 + vendor: cisco + device_type: switch + os_version: 9.3(6) + site_code: mtl + +lab-paloalto-01.lab.djft.local: + hostname: lab-paloalto-01.lab.djft.local + groups: + - panos + - lab + - mel + data: + mgmt_ip: 10.0.0.21 + vendor: palo alto + device_type: firewall + os_version: 10.0.3 + site_code: mel + +lab-paloalto-02.lab.norn.local: + hostname: lab-paloalto-02.lab.norn.local + groups: + - panos + - lab + - bcn + data: + mgmt_ip: 10.0.0.22 + vendor: palo alto + device_type: firewall + os_version: 9.1.3-h1 + site_code: bcn + +lab-junos-06.lab.norn.local: + hostname: lab-junos-06.lab.norn.local + groups: + - junos + - lab + - mel + data: + mgmt_ip: 10.0.0.23 + vendor: juniper + device_type: switch + os_version: 18.4R2-S5 + site_code: mel + +prd-csr-01.prd.norn.local: + hostname: prd-csr-01.prd.norn.local + groups: + - ios + - prod + - mel + data: + mgmt_ip: 10.0.16.16 + vendor: cisco + device_type: router + os_version: 16.6.4 + site_code: mel + +dfjt-r001.prd.norn.local: + hostname: dfjt-r001.prd.norn.local + groups: + - ios + - prod + - mel + data: + mgmt_ip: 10.0.16.1 + vendor: cisco + device_type: router + os_version: 16.6.3 + site_code: mel + +prd-arista-01.prd.norn.local: + hostname: prd-arista-01.prd.norn.local + groups: + - eos + - prod + - mel + data: + mgmt_ip: 10.0.16.11 + vendor: arista + device_type: switch + os_version: 4.21.1F + site_code: mel + +prd-arista-02.prd.nron.local: + hostname: prd-arista-02.prd.norn.local + groups: + - eos + - prod + - mel + data: + mgmt_ip: 10.0.16.18 + vendor: arista + device_type: switch + os_version: 4.23.1F + site_code: mel + +prd-junos-01.prd.norn.local: + hostname: prd-junos-01.prd.norn.local + groups: + - junos + - prod + - mel + data: + mgmt_ip: 10.0.16.15 + vendor: juniper + device_type: router + os_version: 15.1R7-S6 + site_code: mel + +prd-nxos-01.prd.norn.local: + hostname: prd-nxos-01.prd.norn.local + groups: + - nxos_ssh + - prod + - mel + data: + mgmt_ip: 10.0.16.14 + vendor: cisco + device_type: switch + os_version: 7.0(3) + site_code: mel + +prd-paloalto-01.prd.norn.local: + hostname: prd-paloalto-01.prd.norn.local + groups: + - panos + - prod + - mel + data: + mgmt_ip: 10.0.16.21 + vendor: palo alto + device_type: firewall + os_version: 10.0.3 + site_code: mel + +prd-paloalto-02.prd.norn.local: + hostname: prd-paloalto-02.prd.norn.local + groups: + - panos + - prod + - mel + data: + mgmt_ip: 10.0.16.22 + vendor: palo alto + device_type: firewall + os_version: 9.1.6 + site_code: mel + +prd-junos-06.prd.norn.local: + hostname: prd-junos-06.prd.norn.local + groups: + - junos + - prod + - mel + data: + mgmt_ip: 10.0.16.23 + vendor: juniper + device_type: switch + os_version: 12.1R3-S4 + site_code: mel + +tst-csr-01.tst.norn.local: + hostname: tst-csr-01.tst.norn.local + groups: + - ios + - test + - mel + data: + mgmt_ip: 10.0.32.16 + vendor: cisco + device_type: router + os_version: 16.6.4 + site_code: mel + +dfjt-r001.tst.norn.local: + hostname: dfjt-r001.tst.norn.local + groups: + - ios + - test + - mel + data: + mgmt_ip: 10.0.32.1 + vendor: cisco + device_type: router + os_version: 15.1.4 + site_code: mel + +tst-arista-01.tst.norn.local: + hostname: tst-arista-01.tst.norn.local + groups: + - eos + - test + - ptl + data: + mgmt_ip: 10.0.32.11 + vendor: arista + device_type: switch + os_version: 4.21.1F + site_code: ptl + +tstt-arista-02.tst.norn.local: + hostname: tstt-arista-02.tst.norn.local + groups: + - eos + - test + - ptl + data: + mgmt_ip: 10.0.32.18 + vendor: arista + device_type: switch + os_version: 4.21.1F + site_code: ptl + +tst-junos-01.tst.norn.local: + hostname: tst-junos-01.tst.norn.local + groups: + - junos + - test + - ptl + data: + mgmt_ip: 10.0.32.15 + vendor: juniper + device_type: router + os_version: 15.1R7-S6 + site_code: ptl + +tst-nxos-01.tst.norn.local: + hostname: tst-nxos-01.tst.norn.local + groups: + - nxos + - test + - chc + data: + mgmt_ip: 10.0.32.14 + vendor: cisco + device_type: switch + os_version: 7.0(4) + site_code: chc + +tst-paloalto-01.tst.norn.local: + hostname: tst-paloalto-01.tst.norn.local + groups: + - panos + - test + - chc + data: + mgmt_ip: 10.0.32.21 + vendor: palo alto + device_type: firewall + os_version: 10.0.3 + site_code: chc + +tst-paloalto-02.tst.norn.local: + hostname: tst-paloalto-02.tst.norn.local + groups: + - panos + - test + - chc + data: + mgmt_ip: 10.0.32.22 + vendor: palo alto + device_type: firewall + os_version: 8.0.8 + site_code: chc + +tst-junos-06.tst.norn.local: + hostname: tst-junos-06.tst.norn.local + groups: + - junos + - test + - chc + data: + mgmt_ip: 10.0.32.23 + vendor: juniper + device_type: switch + os_version: 12.1R3-S4 + site_code: chc diff --git a/docs/howto/filtering_deep_dive/inventory/hosts_extract.yaml b/docs/howto/filtering_deep_dive/inventory/hosts_extract.yaml new file mode 100644 index 000000000..1f758faa1 --- /dev/null +++ b/docs/howto/filtering_deep_dive/inventory/hosts_extract.yaml @@ -0,0 +1,13 @@ +--- +lab-csr-011.lab.norn.local: + hostname: lab-csr-011.lab.norn.local + groups: + - ios + - lab + - mel + data: # Anything under this key is custom data + mgmt_ip: 10.0.0.16 # This is custom data + vendor: cisco # So is this + device_type: router # Same as this + os_version: 16.6.4 # Also this too + site_code: mel # Yes, and also this diff --git a/docs/howto/filtering_deep_dive/inventory/hosts_extract_alternate.yaml b/docs/howto/filtering_deep_dive/inventory/hosts_extract_alternate.yaml new file mode 100644 index 000000000..cbd4b05cc --- /dev/null +++ b/docs/howto/filtering_deep_dive/inventory/hosts_extract_alternate.yaml @@ -0,0 +1,14 @@ +--- +lab-csr-011.lab.norn.local: + hostname: lab-csr-011.lab.norn.local + groups: + - ios + - lab + - mel + data: # Anything under this key is custom data + ip_addresses: + mgmt: 10.0.0.16 # Alternate way of managing mgmt_ip data + vendor: cisco + device_type: router + os_version: 16.6.4 + site_code: mel From 5f90a385c14a331d75399e10e978b95b8cd24d72 Mon Sep 17 00:00:00 2001 From: David Barroso Date: Mon, 26 Apr 2021 10:19:52 +0200 Subject: [PATCH 5/5] prepare nornir 3.1.1 (#680) --- CHANGELOG.rst | 8 ++++++++ pyproject.toml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index becdcd2d7..75fea29a6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ Changelog ========== +3.1.1 - April 26 2021 +--------------------- + +- address UTF-8 error on windows (#654) @dbarrosop +- remove state property from Nornir class (#669) @brandomando +- Evaluate a host's group outside groups evaluation (#677) @bytinbit +- Nornir Filtering Deep Dive How To (#674) @writememe + 3.1.0 - February 27 2021 ------------------------ diff --git a/pyproject.toml b/pyproject.toml index 20e892ed2..5cd1041ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ build-backend = "poetry.masonry.api" [tool.poetry] name = "nornir" -version = "3.1.0" +version = "3.1.1" description = "Pluggable multi-threaded framework with inventory management to help operate collections of devices" authors = ["David Barroso "] license = "Apache 2.0"