Repository: ansible/ansible

Issue:
Ansible 2.3 nxos_rollback ShellError
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report
 
##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
nxos_rollback

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.3.0.0
  config file = /home/user/sdi-nw-fabric/ansible.cfg
  configured module search path = Default w/o overrides
  python version = 2.7.5 (default, Nov  6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
[defaults]
retry_files_save_path = ~/retry-files
record_host_keys = False
host_key_checking = False
##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->
Centos 7
##### SUMMARY
<!--- Explain the problem briefly -->
nsox_rollback throws an error

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
---
- name: Get backup
  set_fact: BKUPFILE="{{lookup('pipe', 'cat ~/.BKUPFILE')}}"

- name: DEBUG
  debug: msg="{{BKUPFILE}}"

- name: Set Checkpoint
  nxos_rollback:
    checkpoint_file: "{{BKUPFILE}}"
    provider: "{{ cli }}"
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Successful run

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
Vault password:

PLAY [DRF_vxlan] ***********************************************************************************************************************************************************************************

TASK [checkpoint : Get backup] *********************************************************************************************************************************************************************
ok: [s-leaf]

TASK [checkpoint : DEBUG] **************************************************************************************************************************************************************************
ok: [s-leaf] => {
    "changed": false,
    "msg": "user.2017.04.12.13.57.03"
}

TASK [checkpoint : Set Checkpoint] *****************************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: NameError: global name 'ShellError' is not defined
fatal: [s-leaf]: FAILED! => {"changed": false, "failed": true, "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_aK1Nz9/ansible_module_nxos_rollback.py\", line 186, in <module>\n    main()\n  File \"/tmp/ansible_aK1Nz9/ansible_module_nxos_rollback.py\", line 178, in main\n    except ShellError:\nNameError: global name 'ShellError' is not defined\n", "module_stdout": "", "msg": "MODULE FAILURE", "rc": 0}
	to retry, use: --limit @/home/user/retry-files/site.retry

PLAY RECAP *****************************************************************************************************************************************************************************************
s-leaf : ok=2    changed=0    unreachable=0    failed=1

```



Discussion:
cc @jedelman8 @GGabriele @privateip @rcarrillocruz
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
@dgjustice Thanks for the bug report.

This is something that needs fixing for 2.3.1

Resolving patch:
diff --git a/lib/ansible/modules/network/nxos/nxos_rollback.py b/lib/ansible/modules/network/nxos/nxos_rollback.py
--- a/lib/ansible/modules/network/nxos/nxos_rollback.py
+++ b/lib/ansible/modules/network/nxos/nxos_rollback.py
@@ -78,70 +78,18 @@
 '''
 
 
-import re
-from ansible.module_utils.nxos import get_config, load_config, run_commands
-from ansible.module_utils.nxos import nxos_argument_spec, check_args
+from ansible.module_utils.nxos import nxos_argument_spec, run_commands
 from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.netcfg import CustomNetworkConfig
-
-import re
-
-
-def execute_commands(cmds, module, command_type=None):
-    command_type_map = {
-        'cli_show': 'json',
-        'cli_show_ascii': 'text'
-    }
-
-    try:
-        if command_type:
-            response = module.execute(cmds, command_type=command_type)
-        else:
-            response = module.execute(cmds)
-    except ShellError:
-        clie = get_exception()
-        module.fail_json(msg='Error sending {0}'.format(cmds),
-                         error=str(clie))
-    except AttributeError:
-        try:
-            if command_type:
-                command_type = command_type_map.get(command_type)
-                module.cli.add_commands(cmds, output=command_type)
-                response = module.cli.run_commands()
-            else:
-                module.cli.add_commands(cmds, output=command_type)
-                response = module.cli.run_commands()
-        except ShellError:
-            clie = get_exception()
-            module.fail_json(msg='Error sending {0}'.format(cmds),
-                             error=str(clie))
-    return response
-
-
-def prepare_show_command(command, module):
-    if module.params['transport'] == 'cli':
-        execute_commands(command, module)
-    elif module.params['transport'] == 'nxapi':
-        execute_commands(command, module, command_type='cli_show_ascii')
 
 
 def checkpoint(filename, module):
     commands = ['terminal dont-ask', 'checkpoint file %s' % filename]
-    prepare_show_command(commands, module)
+    run_commands(module, commands)
 
 
 def rollback(filename, module):
     commands = ['rollback running-config file %s' % filename]
-    try:
-        module.configure(commands)
-    except AttributeError:
-        try:
-            module.cli.add_commands(commands, output='config')
-            module.cli.run_commands()
-        except ShellError:
-            clie = get_exception()
-            module.fail_json(msg='Error sending CLI commands',
-                             error=str(clie), commands=commands)
+    run_commands(module, commands)
 
 
 def main():
@@ -156,9 +104,9 @@ def main():
     argument_spec.update(nxos_argument_spec)
 
     module = AnsibleModule(argument_spec=argument_spec,
-                        mutually_exclusive=[['checkpoint_file',
-                                             'rollback_to']],
-                        supports_check_mode=False)
+                           mutually_exclusive=[['checkpoint_file',
+                                                'rollback_to']],
+                           supports_check_mode=False)
 
     checkpoint_file = module.params['checkpoint_file']
     rollback_to = module.params['rollback_to']
@@ -166,22 +114,18 @@ def main():
     status = None
     filename = None
     changed = False
-    try:
-        if checkpoint_file:
-            checkpoint(checkpoint_file, module)
-            status = 'checkpoint file created'
-        elif rollback_to:
-            rollback(rollback_to, module)
-            status = 'rollback executed'
-        changed = True
-        filename = rollback_to or checkpoint_file
-    except ShellError:
-        clie = get_exception()
-        module.fail_json(msg=str(clie))
+
+    if checkpoint_file:
+        checkpoint(checkpoint_file, module)
+        status = 'checkpoint file created'
+    elif rollback_to:
+        rollback(rollback_to, module)
+        status = 'rollback executed'
+    changed = True
+    filename = rollback_to or checkpoint_file
 
     module.exit_json(changed=changed, status=status, filename=filename)
 
 
 if __name__ == '__main__':
     main()
-


Test patch:
diff --git a/test/sanity/pep8/legacy-files.txt b/test/sanity/pep8/legacy-files.txt
--- a/test/sanity/pep8/legacy-files.txt
+++ b/test/sanity/pep8/legacy-files.txt
@@ -588,7 +588,6 @@ lib/ansible/modules/network/nxos/nxos_pim_rp_address.py
 lib/ansible/modules/network/nxos/nxos_ping.py
 lib/ansible/modules/network/nxos/nxos_portchannel.py
 lib/ansible/modules/network/nxos/nxos_reboot.py
-lib/ansible/modules/network/nxos/nxos_rollback.py
 lib/ansible/modules/network/nxos/nxos_smu.py
 lib/ansible/modules/network/nxos/nxos_snapshot.py
 lib/ansible/modules/network/nxos/nxos_snmp_community.py