Repository: napalm-automation/napalm

Issue:
Split for rollback command output causes exception when generating diffs
https://github.com/napalm-automation/napalm/blob/0a2a5425e59e939efdc162a841281f01f4bc308a/napalm/nxos/nxos.py#L261

So the `#` in this split statement causes exception in NXOS 7.0(3)I7(2) on NX9300s I was testing today since there's no # in the CLI output.    I came across it when I noticed that "diffs: true" on a napalm_ansible playbook crashed, but disabling diffs pass for the platform.  

I don't have older releases on-hand to compare and determine if simply altering the split statement is adequate (that's what I've done for my local copy for now), or if we need to instead support both options with and without the `#` for various versions/platforms.  I'm happy to submit a PR for the fix, just looking for guidance on how you'd prefer it be tackled.   I'd assume a simple try-block around the split to try the old way and fall-back to the new way would suffice, like so:
```
try:
    diff_out = diff_out.split(
        '#Generating Rollback Patch')[1].replace(
            'Rollback Patch is Empty', '').strip()
except IndexError:
    # newer NXOS releases do not include the # sign in the rollback patch
     diff_out = diff_out.split(
         'Generating Rollback Patch')[1].replace(
             'Rollback Patch is Empty', '').strip()
```

Example failure using napalm-cli and extra print to STDOUT of the diff before split with resulting traceback is here: 
```
2018-01-10 20:56:40,744 - napalm - DEBUG - load_replace_candidate - Successful
2018-01-10 20:56:40,744 - napalm - DEBUG - compare_config - Calling with args: (<napalm.nxos.nxos.NXOSDriver object at 0x7fb85eb55e10>,), {}
/home/netmagus/.pyenv/versions/2.7.14/envs/ansible/lib/python2.7/site-packages/urllib3/connectionpool.py:858: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
/home/netmagus/.pyenv/versions/2.7.14/envs/ansible/lib/python2.7/site-packages/urllib3/connectionpool.py:858: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
Generating Rollback Patch

!!

no logging console

no logging module

no logging monitor

no logging logfile messages 5 size 4194304

priority-flow-control override-interface mode off

no xml server timeout 1200

no router bgp 65100

no router ospf UNDERLAY

no boot nxos bootflash:/nxos.7.0.3.I7.2.bin

***REST OF DIFF REMOVED FOR BREVITY***

2018-01-10 20:56:42,534 - napalm - ERROR - compare_config - Failed: list index out of range

================= Traceback =================

Traceback (most recent call last):
  File "/home/netmagus/.pyenv/versions/ansible/bin/napalm", line 11, in <module>
    sys.exit(main())
  File "/home/netmagus/.pyenv/versions/2.7.14/envs/ansible/lib/python2.7/site-packages/napalm/base/clitools/cl_napalm.py", line 285, in main
    run_tests(args)
  File "/home/netmagus/.pyenv/versions/2.7.14/envs/ansible/lib/python2.7/site-packages/napalm/base/clitools/cl_napalm.py", line 270, in run_tests
    configuration_change(device, args.config_file, args.strategy, args.dry_run)
  File "/home/netmagus/.pyenv/versions/2.7.14/envs/ansible/lib/python2.7/site-packages/napalm/base/clitools/cl_napalm.py", line 226, in configuration_change
    diff = call_compare_config(device)
  File "/home/netmagus/.pyenv/versions/2.7.14/envs/ansible/lib/python2.7/site-packages/napalm/base/clitools/cl_napalm.py", line 27, in wrapper
    r = func(*args, **kwargs)
  File "/home/netmagus/.pyenv/versions/2.7.14/envs/ansible/lib/python2.7/site-packages/napalm/base/clitools/cl_napalm.py", line 207, in call_compare_config
    diff = device.compare_config(*args, **kwargs)
  File "/home/netmagus/.pyenv/versions/2.7.14/envs/ansible/lib/python2.7/site-packages/napalm/nxos/nxos.py", line 296, in compare_config
    diff = self._get_diff(self.fc.dst)
  File "/home/netmagus/.pyenv/versions/2.7.14/envs/ansible/lib/python2.7/site-packages/napalm/nxos/nxos.py", line 262, in _get_diff
    '#Generating Rollback Patch')[1].replace(
IndexError: list index out of range
``` 

Here is the result with `#` removed in the newer release/platforms and also showing an added print to STDOUT of the diff prior to the split being performed to show the change in behavior:
```
2018-01-10 20:58:38,326 - napalm - DEBUG - load_replace_candidate - Successful
2018-01-10 20:58:38,326 - napalm - DEBUG - compare_config - Calling with args: (<napalm.nxos.nxos.NXOSDriver object at 0x7f6feb54de10>,), {}
/home/netmagus/.pyenv/versions/2.7.14/envs/ansible/lib/python2.7/site-packages/urllib3/connectionpool.py:858: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
/home/netmagus/.pyenv/versions/2.7.14/envs/ansible/lib/python2.7/site-packages/urllib3/connectionpool.py:858: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
Generating Rollback Patch

!!

no logging console

no logging module

no logging monitor

no logging logfile messages 5 size 4194304

***REST OF DIFF REMOVED FOR BREVITY***

2018-01-10 20:58:40,147 - napalm - DEBUG - Gathered diff:
no logging console
no logging module
no logging monitor
no logging logfile messages 5 size 4194304
priority-flow-control override-interface mode off
***REST OF DIFF REMOVED FOR BREVITY***

2018-01-10 20:58:40,148 - napalm - DEBUG - compare_config - Successful
2018-01-10 20:58:40,148 - napalm - DEBUG - close - Calling with args: (<napalm.nxos.nxos.NXOSDriver object at 0x7f6feb54de10>,), {}
2018-01-10 20:58:40,148 - napalm - DEBUG - close - Successful
2018-01-10 20:58:40,148 - napalm - DEBUG - post_connection_tests - Calling with args: (<napalm.nxos.nxos.NXOSDriver object at 0x7f6feb54de10>,), {}
```

Here's direct device CLI output with same command nxos.py sends also showing the new output:
```
chc-spine-1# show diff rollback-patch file bootflash:///chc-spine-1.cfg running-config
Collecting Running-Config
Generating Rollback Patch

!!

interface Ethernet1/9

  shutdown

  no switchport
```


Discussion:
For reference here is what it looks like on NX-OSv 7.3(1)D1(1):

```
nxos1# show diff rollback-patch file bootflash:sot_file running-config 
Collecting Running-Config
#Generating Rollback Patch
Rollback Patch is Empty
```

Resolving patch:
diff --git a/napalm/nxos/nxos.py b/napalm/nxos/nxos.py
--- a/napalm/nxos/nxos.py
+++ b/napalm/nxos/nxos.py
@@ -258,7 +258,7 @@ def _get_diff(self, cp_file):
                 'sot_file', self.replace_file.split('/')[-1]), raw_text=True)
         try:
             diff_out = diff_out.split(
-                '#Generating Rollback Patch')[1].replace(
+                'Generating Rollback Patch')[1].replace(
                     'Rollback Patch is Empty', '').strip()
             for line in diff_out.splitlines():
                 if line:
diff --git a/napalm/nxos_ssh/nxos_ssh.py b/napalm/nxos_ssh/nxos_ssh.py
--- a/napalm/nxos_ssh/nxos_ssh.py
+++ b/napalm/nxos_ssh/nxos_ssh.py
@@ -601,7 +601,7 @@ def _get_diff(self):
         diff_out = self.device.send_command(command)
         try:
             diff_out = diff_out.split(
-                '#Generating Rollback Patch')[1].replace(
+                'Generating Rollback Patch')[1].replace(
                     'Rollback Patch is Empty', '').strip()
             for line in diff_out.splitlines():
                 if line:


Test patch: