Repository: napalm-automation/napalm
Pull request #1842 (2023-02-10 13:32:53)

add get_network_instances for nxos_ssh, based mostly on nxos version
This change will implement get_network_instances for type nxos_ssh. It's based almost entirely on the version in nxos.py, returning the same fields.

Please let me know if it is acceptable in this way, whether it requires additional cleaning on the nxos_ssh file, or any other feedback


Patch:
diff --git a/napalm/nxos_ssh/nxos_ssh.py b/napalm/nxos_ssh/nxos_ssh.py
index 6c748901..51aa2c69 100644
--- a/napalm/nxos_ssh/nxos_ssh.py
+++ b/napalm/nxos_ssh/nxos_ssh.py
@@ -18,6 +18,7 @@ from builtins import super
 import ipaddress
 import re
 import socket
+from collections import defaultdict
 
 # import NAPALM Base
 from napalm.base import helpers
@@ -794,6 +795,61 @@ class NXOSSSHDriver(NXOSDriverBase):
             cli_output[str(command)] = output
         return cli_output
 
+    def get_network_instances(self, name=""):
+        """
+        get_network_instances implementation for NX-OS
+        """
+
+        # command 'show vrf detail | json' returns all VRFs with detailed information in JSON format
+        # format: list of dictionaries with keys such as 'vrf_name' and 'rd'
+        vrf_table_raw = self._get_command_table(
+            "show vrf detail | json", "TABLE_vrf", "ROW_vrf"
+        )
+
+        # command 'show vrf interface' returns all interfaces including their assigned VRF
+        # format: list of dictionaries with keys 'if_name', 'vrf_name', 'vrf_id' and 'soo'
+        intf_table_raw = self._get_command_table(
+            "show vrf interface | json", "TABLE_if", "ROW_if"
+        )
+
+        # create a dictionary with key = 'vrf_name' and value = list of interfaces
+        vrf_intfs = defaultdict(list)
+        for intf in intf_table_raw:
+            vrf_intfs[intf["vrf_name"]].append(str(intf["if_name"]))
+
+        vrfs = {}
+        for vrf in vrf_table_raw:
+            vrf_name = str(vrf.get("vrf_name"))
+            vrfs[vrf_name] = {}
+            vrfs[vrf_name]["name"] = vrf_name
+
+            # differentiate between VRF type 'DEFAULT_INSTANCE' and 'L3VRF'
+            if vrf_name == "default":
+                vrfs[vrf_name]["type"] = "DEFAULT_INSTANCE"
+            else:
+                vrfs[vrf_name]["type"] = "L3VRF"
+
+            vrfs[vrf_name]["state"] = {"route_distinguisher": str(vrf.get("rd"))}
+
+            # convert list of interfaces (vrf_intfs[vrf_name]) to expected format
+            # format = dict with key = interface name and empty values
+            vrfs[vrf_name]["interfaces"] = {}
+            vrfs[vrf_name]["interfaces"]["interface"] = dict.fromkeys(
+                vrf_intfs[vrf_name], {}
+            )
+
+        # if name of a specific VRF was passed as an argument
+        # only return results for this particular VRF
+
+        if name:
+            if name in vrfs.keys():
+                return {str(name): vrfs[name]}
+            else:
+                return {}
+        # else return results for all VRFs
+        else:
+            return vrfs
+
     def get_environment(self):
         """
         Get environment facts.


Test patch:
diff --git a/test/nxos_ssh/mocked_data/test_get_network_instances/normal/expected_result.json b/test/nxos_ssh/mocked_data/test_get_network_instances/normal/expected_result.json
new file mode 100644
index 00000000..ca3d2f11
--- /dev/null
+++ b/test/nxos_ssh/mocked_data/test_get_network_instances/normal/expected_result.json
@@ -0,0 +1,36 @@
+{
+    "management": {
+        "name": "management",
+        "type": "L3VRF",
+        "state": {
+            "route_distinguisher": "0:0"
+        },
+        "interfaces": {
+            "interface": {
+                "mgmt0": {}
+            }
+        }
+    },
+    "default": {
+        "name": "default",
+        "type": "DEFAULT_INSTANCE",
+        "state": {
+            "route_distinguisher": "0:0"
+        },
+        "interfaces": {
+            "interface": {
+                "Vlan1": {},
+                "Vlan100": {},
+                "Vlan101": {},
+                "Vlan102": {},
+                "Vlan103": {},
+                "Vlan104": {},
+                "Vlan105": {},
+                "loopback1": {},
+                "Null0": {},
+                "Ethernet1/5": {},
+                "Ethernet1/5.1": {}
+            }
+        }
+    }
+}
diff --git a/test/nxos_ssh/mocked_data/test_get_network_instances/normal/show_vrf_detail___json.txt b/test/nxos_ssh/mocked_data/test_get_network_instances/normal/show_vrf_detail___json.txt
new file mode 100644
index 00000000..637f6236
--- /dev/null
+++ b/test/nxos_ssh/mocked_data/test_get_network_instances/normal/show_vrf_detail___json.txt
@@ -0,0 +1,58 @@
+{
+  "TABLE_vrf": {
+    "ROW_vrf": [
+      {
+        "vrf_name": "default",
+        "vrf_id": 1,
+        "vrf_state": "Up",
+        "vpnid": "unknown",
+        "rd": "0:0",
+        "vni": 0,
+        "max_routes": 0,
+        "mid_threshold": 0,
+        "TABLE_tib": {
+          "ROW_tib": [
+            {
+              "tib_id": 80000001,
+              "tib_af": "IPv6",
+              "tib_nonce": 80000001,
+              "tib_state": "Up"
+            },
+            {
+              "tib_id": 1,
+              "tib_af": "IPv4",
+              "tib_nonce": 1,
+              "tib_state": "Up"
+            }
+          ]
+        }
+      },
+      {
+        "vrf_name": "management",
+        "vrf_id": 2,
+        "vrf_state": "Up",
+        "vpnid": "unknown",
+        "rd": "0:0",
+        "vni": 0,
+        "max_routes": 0,
+        "mid_threshold": 0,
+        "TABLE_tib": {
+          "ROW_tib": [
+            {
+              "tib_id": 80000002,
+              "tib_af": "IPv6",
+              "tib_nonce": 80000002,
+              "tib_state": "Up"
+            },
+            {
+              "tib_id": 2,
+              "tib_af": "IPv4",
+              "tib_nonce": 2,
+              "tib_state": "Up"
+            }
+          ]
+        }
+      }
+    ]
+  }
+}
diff --git a/test/nxos_ssh/mocked_data/test_get_network_instances/normal/show_vrf_interface___json.txt b/test/nxos_ssh/mocked_data/test_get_network_instances/normal/show_vrf_interface___json.txt
new file mode 100644
index 00000000..72a325a0
--- /dev/null
+++ b/test/nxos_ssh/mocked_data/test_get_network_instances/normal/show_vrf_interface___json.txt
@@ -0,0 +1,78 @@
+{
+  "TABLE_if": {
+    "ROW_if": [
+      {
+        "if_name": "Vlan1",
+        "vrf_name": "default",
+        "vrf_id": 1,
+        "soo": "--"
+      },
+      {
+        "if_name": "Vlan100",
+        "vrf_name": "default",
+        "vrf_id": 1,
+        "soo": "--"
+      },
+      {
+        "if_name": "Vlan101",
+        "vrf_name": "default",
+        "vrf_id": 1,
+        "soo": "--"
+      },
+      {
+        "if_name": "Vlan102",
+        "vrf_name": "default",
+        "vrf_id": 1,
+        "soo": "--"
+      },
+      {
+        "if_name": "Vlan103",
+        "vrf_name": "default",
+        "vrf_id": 1,
+        "soo": "--"
+      },
+      {
+        "if_name": "Vlan104",
+        "vrf_name": "default",
+        "vrf_id": 1,
+        "soo": "--"
+      },
+      {
+        "if_name": "Vlan105",
+        "vrf_name": "default",
+        "vrf_id": 1,
+        "soo": "--"
+      },
+      {
+        "if_name": "loopback1",
+        "vrf_name": "default",
+        "vrf_id": 1,
+        "soo": "--"
+      },
+      {
+        "if_name": "Null0",
+        "vrf_name": "default",
+        "vrf_id": 1,
+        "soo": "--"
+      },
+      {
+        "if_name": "Ethernet1/5",
+        "vrf_name": "default",
+        "vrf_id": 1,
+        "soo": "--"
+      },
+      {
+        "if_name": "Ethernet1/5.1",
+        "vrf_name": "default",
+        "vrf_id": 1,
+        "soo": "--"
+      },
+      {
+        "if_name": "mgmt0",
+        "vrf_name": "management",
+        "vrf_id": 2,
+        "soo": "--"
+      }
+    ]
+  }
+}