Repository: napalm-automation/napalm (python)

Issue:
Bug Report: NAPALM get_facts() incorrect os_version parsing on Nexus 9K with NXOS 10.3(5)
## Description
The NAPALM `get_facts()` method is not correctly parsing the os_version for Cisco Nexus switches running NXOS 10.3(5). Instead of returning the actual version number, it returns the literal string "version".

## Environment
- Device Model: Cisco Nexus9000 C93180YC-FX3 chassis
- NXOS Version: 10.3(5) [Maintenance Release]
- NAPALM Version: 5.0.0

## Current Behavior
`get_facts()` returns:
```python
{
    'uptime': 123456.0,
    'vendor': 'Cisco',
    'os_version': 'version',  # This is incorrect
    'serial_number': 'FAKESERIAL',
    'model': 'Nexus9000 C93180YC-FX3 Chassis',
    'hostname': 'SWITCH1',
    ...
}
```

## Expected Behavior
`get_facts()` should return:
```python
{
    ...
    'os_version': '10.3(5)',  # This is the expected value
    ...
}
```

## Raw Device Output
```
Cisco Nexus Operating System (NX-OS) Software
TAC support: http://www.cisco.com/tac
Copyright (C) 2002-2024, Cisco and/or its affiliates.
[...]
Software
  BIOS: version 01.09
  NXOS: version 10.3(5) [Maintenance Release]
  Host NXOS: version 10.3(5)
  BIOS compile time: 10/08/2023
  NXOS image file is: bootflash:///nxos64-cs.10.3.5.M.bin
  NXOS compile time: 4/30/2024 12:00:00 [05/08/2024 05:39:13]
  NXOS boot mode: LXC
```

## Steps to Reproduce
1. Connect to a Cisco Nexus switch running NXOS 10.3(5) using NAPALM
2. Call the `get_facts()` method
3. Observe that the 'os_version' field contains "version" instead of "10.3(5)"

## Additional Notes
- The issue appears to be in the regex parsing of the 'show version' output
- The version string includes "[Maintenance Release]" suffix which might be affecting the parsing
- This might affect other NXOS versions with similar output format

## Possible Fix Direction
The current regex pattern in the NX-OS driver may need to be updated to handle the version string format "X.X(X) [Maintenance Release]" correctly.

Pull request:
Improve nxos_ssh version handling
Closes #2151

Patch:
diff --git a/napalm/nxos_ssh/nxos_ssh.py b/napalm/nxos_ssh/nxos_ssh.py
index 7206756d..5a71662a 100644
--- a/napalm/nxos_ssh/nxos_ssh.py
+++ b/napalm/nxos_ssh/nxos_ssh.py
@@ -621,7 +621,7 @@ class NXOSSSHDriver(NXOSDriverBase):
                 _, uptime_str = line.split(" uptime is ")
                 uptime = self.parse_uptime(uptime_str)
 
-            if "system: " in line or "NXOS: " in line:
+            if "system: " in line or line.strip().startswith("NXOS: version"):
                 line = line.strip()
                 os_version = line.split()[2]
                 os_version = os_version.strip()


Test patch:
diff --git a/test/nxos_ssh/mocked_data/test_get_facts/issue2151/expected_result.json b/test/nxos_ssh/mocked_data/test_get_facts/issue2151/expected_result.json
new file mode 100644
index 00000000..4f2b4860
--- /dev/null
+++ b/test/nxos_ssh/mocked_data/test_get_facts/issue2151/expected_result.json
@@ -0,0 +1,76 @@
+{
+  "os_version": "10.3(5)",
+  "uptime": 4338547,
+  "interface_list": [
+    "Management0",
+    "Ethernet1/1",
+    "Ethernet1/2",
+    "Ethernet1/3",
+    "Ethernet1/4",
+    "Ethernet1/5",
+    "Ethernet1/6",
+    "Ethernet1/7",
+    "Ethernet1/8",
+    "Ethernet1/9",
+    "Ethernet1/10",
+    "Ethernet1/11",
+    "Ethernet1/12",
+    "Ethernet1/13",
+    "Ethernet1/14",
+    "Ethernet1/15",
+    "Ethernet1/16",
+    "Ethernet1/17",
+    "Ethernet1/18",
+    "Ethernet1/19",
+    "Ethernet1/20",
+    "Ethernet1/21",
+    "Ethernet1/22",
+    "Ethernet1/23",
+    "Ethernet1/24",
+    "Ethernet1/25",
+    "Ethernet1/26",
+    "Ethernet1/27",
+    "Ethernet1/28",
+    "Ethernet1/29",
+    "Ethernet1/30",
+    "Ethernet1/31",
+    "Ethernet1/32",
+    "Ethernet1/33",
+    "Ethernet1/34",
+    "Ethernet1/35",
+    "Ethernet1/36",
+    "Ethernet1/37",
+    "Ethernet1/38",
+    "Ethernet1/39",
+    "Ethernet1/40",
+    "Ethernet1/41",
+    "Ethernet1/42",
+    "Ethernet1/43",
+    "Ethernet1/44",
+    "Ethernet1/45",
+    "Ethernet1/46",
+    "Ethernet1/47",
+    "Ethernet1/48",
+    "Ethernet1/49",
+    "Ethernet1/50",
+    "Ethernet1/51",
+    "Ethernet1/52",
+    "Port-channel1",
+    "Port-channel16",
+    "Port-channel17",
+    "Port-channel32",
+    "Port-channel33",
+    "Port-channel34",
+    "Port-channel35",
+    "Port-channel50",
+    "Port-channel51",
+    "Port-channel360",
+    "Vlan1",
+    "Vlan351"
+  ],
+  "vendor": "Cisco",
+  "serial_number": "TM6012EC74B",
+  "model": "Nexus 3048 Chassis",
+  "hostname": "SWITCH_NXOSv",
+  "fqdn": "SWITCH_NXOSv.y.z.a.com"
+}
diff --git a/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_hostname.txt b/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_hostname.txt
new file mode 100644
index 00000000..c82c8bda
--- /dev/null
+++ b/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_hostname.txt
@@ -0,0 +1,1 @@
+SWITCH_NXOSv.y.z.a.com 
\ No newline at end of file
diff --git a/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_hosts.txt b/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_hosts.txt
new file mode 100644
index 00000000..303a24bf
--- /dev/null
+++ b/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_hosts.txt
@@ -0,0 +1,7 @@
+DNS lookup enabled
+Vrf Name: default Default domain is y.z.a.com
+Name servers are   8.8.8.4 8.8.8.8
+
+
+
+Host            Address
diff --git a/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_interface_status.txt b/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_interface_status.txt
new file mode 100644
index 00000000..105efd98
--- /dev/null
+++ b/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_interface_status.txt
@@ -0,0 +1,69 @@
+
+--------------------------------------------------------------------------------
+Port          Name               Status    Vlan      Duplex  Speed   Type
+--------------------------------------------------------------------------------
+mgmt0         --                 connected routed    full    1000    --         
+Eth1/1        --                 connected 353       full    100     10/100/1g  
+Eth1/2        --                 notconnec 353       auto    auto    10/100/1g  
+Eth1/3        --                 disabled  366       auto    auto    10/100/1g  
+Eth1/4        --                 connected 351       full    1000    10/100/1g  
+Eth1/5        --                 connected 351       full    1000    10/100/1g  
+Eth1/6        --                 connected 351       full    1000    10/100/1g  
+Eth1/7        --                 connected 351       full    1000    10/100/1g  
+Eth1/8        --                 connected 351       full    1000    10/100/1g  
+Eth1/9        --                 connected 351       full    1000    10/100/1g  
+Eth1/10       --                 connected 351       full    1000    10/100/1g  
+Eth1/11       --                 connected 351       full    1000    10/100/1g  
+Eth1/12       --                 connected 351       full    1000    10/100/1g  
+Eth1/13       --                 connected 351       full    1000    10/100/1g  
+Eth1/14       --                 connected 351       full    1000    10/100/1g  
+Eth1/15       --                 connected 351       full    1000    10/100/1g  
+Eth1/16       --                 connected trunk     full    1000    10/100/1g  
+Eth1/17       --                 connected trunk     full    1000    10/100/1g  
+Eth1/18       --                 connected 369       full    1000    10/100/1g  
+Eth1/19       --                 notconnec 351       auto    auto    10/100/1g  
+Eth1/20       --                 connected 351       full    100     10/100/1g  
+Eth1/21       --                 connected 351       half    100     10/100/1g  
+Eth1/22       --                 connected 351       half    100     10/100/1g  
+Eth1/23       --                 disabled  366       auto    auto    10/100/1g  
+Eth1/24       --                 connected 352       full    1000    10/100/1g  
+Eth1/25       --                 connected 352       half    100     10/100/1g  
+Eth1/26       --                 connected 352       full    1000    10/100/1g  
+Eth1/27       --                 connected 352       half    100     10/100/1g  
+Eth1/28       --                 connected 352       full    100     10/100/1g  
+Eth1/29       --                 connected 352       full    100     10/100/1g  
+Eth1/30       --                 connected 352       full    100     10/100/1g  
+Eth1/31       --                 disabled  366       auto    auto    10/100/1g  
+Eth1/32       --                 connected trunk     full    1000    10/100/1g  
+Eth1/33       --                 connected trunk     full    1000    10/100/1g  
+Eth1/34       --                 connected trunk     full    1000    10/100/1g  
+Eth1/35       --                 connected trunk     full    1000    10/100/1g  
+Eth1/36       --                 connected 351       full    1000    10/100/1g  
+Eth1/37       --                 connected 351       full    1000    10/100/1g  
+Eth1/38       --                 connected 351       full    1000    10/100/1g  
+Eth1/39       --                 connected 351       full    1000    10/100/1g  
+Eth1/40       --                 connected 351       full    1000    10/100/1g  
+Eth1/41       --                 disabled  350       auto    auto    10/100/1g  
+Eth1/42       --                 connected 351       full    1000    10/100/1g  
+Eth1/43       --                 connected 351       full    1000    10/100/1g  
+Eth1/44       --                 connected 351       full    1000    10/100/1g  
+Eth1/45       --                 connected 351       full    1000    10/100/1g  
+Eth1/46       --                 disabled  366       auto    auto    10/100/1g  
+Eth1/47       --                 connected trunk     full    1000    10/100/1g  
+Eth1/48       --                 connected trunk     full    1000    10/100/1g  
+Eth1/49       --                 xcvrAbsen 366       full    10G     --         
+Eth1/50       --                 connected trunk     full    1000    1000base-SX
+Eth1/51       --                 connected trunk     full    1000    1000base-SX
+Eth1/52       --                 connected trunk     full    1000    1000base-SX
+Po1           --                 connected trunk     full    1000    --         
+Po16          --                 connected trunk     full    1000    --         
+Po17          --                 connected trunk     full    1000    --         
+Po32          --                 connected trunk     full    1000    --         
+Po33          --                 connected trunk     full    1000    --         
+Po34          --                 connected trunk     full    1000    --         
+Po35          --                 connected trunk     full    1000    --         
+Po50          --                 connected trunk     full    1000    --         
+Po51          --                 connected trunk     full    1000    --         
+Po360         --                 connected trunk     full    1000    --         
+Vlan1         --                 down      routed    auto    auto    --
+Vlan351       --                 connected routed    auto    auto    --
\ No newline at end of file
diff --git a/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_inventory___json.txt b/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_inventory___json.txt
new file mode 100644
index 00000000..15cbe724
--- /dev/null
+++ b/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_inventory___json.txt
@@ -0,0 +1,34 @@
+{
+  "TABLE_inv": {
+    "ROW_inv": [
+      {
+        "name": "Chassis",
+        "desc": "Nexus 6001 Chassis",
+        "productid": "N6K-C6001-64P",
+        "vendorid": "V01",
+        "serialnum": "TM6012EC74B"
+      },
+      {
+        "name": "Module 1",
+        "desc": "Nexus 64 Supervisor",
+        "productid": "N6K-C6001-64P",
+        "vendorid": "V01",
+        "serialnum": "FOC11111111"
+      },
+      {
+        "name": "Module 2",
+        "desc": "Nexus 4xQSFP Ethernet Module",
+        "productid": "N6K-C6001-M4Q",
+        "vendorid": "V01",
+        "serialnum": "FOC11111111"
+      },
+      {
+        "name": "Fan 1",
+        "desc": "Chassis fan module",
+        "productid": "N6K-C6001-FAN-B",
+        "vendorid": "N/A",
+        "serialnum": "N/A"
+      }
+    ]
+  }
+}
diff --git a/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_version.txt b/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_version.txt
new file mode 100644
index 00000000..cafe1098
--- /dev/null
+++ b/test/nxos_ssh/mocked_data/test_get_facts/issue2151/show_version.txt
@@ -0,0 +1,50 @@
+Cisco Nexus Operating System (NX-OS) Software
+TAC support: http://www.cisco.com/tac
+Copyright (C) 2002-2017, Cisco and/or its affiliates.
+All rights reserved.
+The copyrights to certain works contained in this software are
+owned by other third parties and used and distributed under their own
+licenses, such as open source.  This software is provided "as is," and unless
+otherwise stated, there is no warranty, express or implied, including but not
+limited to warranties of merchantability and fitness for a particular purpose.
+Certain components of this software are licensed under
+the GNU General Public License (GPL) version 2.0 or
+GNU General Public License (GPL) version 3.0  or the GNU
+Lesser General Public License (LGPL) Version 2.1 or
+Lesser General Public License (LGPL) Version 2.0.
+A copy of each such license is available at
+http://www.opensource.org/licenses/gpl-2.0.php and
+http://opensource.org/licenses/gpl-3.0.html and
+http://www.opensource.org/licenses/lgpl-2.1.php and
+http://www.gnu.org/licenses/old-licenses/library.txt.
+
+Software
+  BIOS: version 01.09
+  NXOS: version 10.3(5) [Maintenance Release]
+  Host NXOS: version 10.3(5)
+  BIOS compile time: 10/08/2023
+  NXOS image file is: bootflash:///nxos64-cs.10.3.5.M.bin
+  NXOS compile time: 4/30/2024 12:00:00 [05/08/2024 05:39:13]
+  NXOS boot mode: LXC
+
+Hardware
+  cisco Nexus 3048 Chassis
+  Intel(R) Celeron(R) CPU        P4505  @ 1.87GHz with 3903332 kB of memory.
+  Processor Board ID TM6012EC74B
+
+  Device name: SWITCH_NXOSv
+  bootflash:    1848240 kB
+  usb1:               0 kB (expansion flash)
+
+Kernel uptime is 50 day(s), 5 hour(s), 9 minute(s), 7 second(s)
+
+Last reset at 829281 usecs after  Thu Oct 26 20:25:34 2017
+
+  Reason: Reset Requested by CLI command reload
+  System version: 7.0(3)I4(7)
+  Service:
+
+plugin
+  Core Plugin, Ethernet Plugin
+
+Active Package(s):