Repository: ansible/ansible

Issue:
(P1)nxos_file_copy: file copy fails for nxapi
<!---
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_file_copy

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.4.0 (devel b93b9e68d7) last updated 2017/07/26 14:19:36 (GMT -400)
  config file = None
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /root/agents-ci/ansible/lib/ansible
  executable location = /root/agents-ci/ansible/bin/ansible
  python version = 2.7.6 (default, Oct 26 2016, 20:30:19) [GCC 4.8.4]
```

##### 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.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->
Ubuntu 14.04

##### SUMMARY
<!--- Explain the problem briefly -->
File copy fails for transport `nxapi`. Looks like while checking to see if directory already present on device the command used is not structured output compliant and hence the module fails.

##### 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
---
- hosts: nxos
  connection: local
  gather_facts: no

  tasks:
  - name: "Radius Server Basic settings"
    nxos_file_copy:
      local_file: "./nxos.yaml"
      file_system: "bootflash:"
      provider: "{{ nxapi }}"
      username: "{{ nxos_nxapi_user | default('admin') }}"
      password: "{{ nxos_nxapi_pass | default('admin') }}"
      host: "{{ inventory_hostname }}"
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Expected file to copy cleanly to device.

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
TASK [nxos_file_copy : Copy nxos.yaml to bootflash] *******************************************************************************************************
task path: /root/agents-ci/ansible/test/integration/targets/nxos_file_copy/tests/nxapi/sanity.yaml:21
<camden-nx-xxx.example.com> connection transport is nxapi
Using module file /root/agents-ci/ansible/lib/ansible/modules/network/nxos/nxos_file_copy.py
<camden-nx-xxx.example.com> ESTABLISH LOCAL CONNECTION FOR USER: root
<camden-nx-xxx.example.com> EXEC /bin/sh -c 'echo ~ && sleep 0'
<camden-nx-xxx.example.com> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1501099012.78-269753565282518 `" && echo ansible-tmp-1501099012.78-269753565282518="` echo /root/.ansible/tmp/ansible-tmp-1501099012.78-269753565282518 `" ) && sleep 0'
<camden-nx-xxx.example.com> PUT /tmp/tmplT6tse TO /root/.ansible/tmp/ansible-tmp-1501099012.78-269753565282518/nxos_file_copy.py
<camden-nx-xxx.example.com> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1501099012.78-269753565282518/ /root/.ansible/tmp/ansible-tmp-1501099012.78-269753565282518/nxos_file_copy.py && sleep 0'
<camden-nx-xxx.example.com> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1501099012.78-269753565282518/nxos_file_copy.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1501099012.78-269753565282518/" > /dev/null 2>&1 && sleep 0'
FAILED! => {
    "changed": false, 
    "clierror": "No such file or directory\n", 
    "code": "501", 
    "failed": true, 
    "input": "dir bootflash:/nxos.yaml",     
    "invocation": {
        "module_args": {
            "config": null, 
            "file_system": "bootflash:",             
            "host": "camden-nx-xxx.example.com",         
            "include_defaults": "True",   
            "local_file": "./nxos.yaml",             
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", 
            "port": 80, 
            "provider": {
                "host": "camden-nx-xxx.example.com",         
                "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", 
                "port": 80, 
                "ssh_keyfile": null, 
                "timeout": 10, 
                "transport": "nxapi", 
                "use_ssl": false, 
                "username": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", 
                "validate_certs": true
            }, 
            "remote_file": null, 
            "save": false,  
            "ssh_keyfile": null, 
            "timeout": 10,  
            "transport": "nxapi", 
            "url_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", 
            "url_username": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", 
            "use_ssl": false, 
            "username": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", 
            "validate_certs": true
        }
    }, 
    "msg": "Structured output unsupported",  
    "output": {
        "clierror": "No such file or directory\n", 
        "code": "501", 
        "input": "dir bootflash:/nxos.yaml",     
        "msg": "Structured output unsupported"   
    }, 
    "url": "http://camden-nx-xxx.example.com:80/ins"
}
```



Discussion:
cc @GGabriele @jedelman8 @mikewiebe @privateip @rcarrillocruz @trishnaguha
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/network/nxos/nxos_file_copy.py b/lib/ansible/modules/network/nxos/nxos_file_copy.py
--- a/lib/ansible/modules/network/nxos/nxos_file_copy.py
+++ b/lib/ansible/modules/network/nxos/nxos_file_copy.py
@@ -102,7 +102,7 @@
 
 def remote_file_exists(module, dst, file_system='bootflash:'):
     command = 'dir {0}/{1}'.format(file_system, dst)
-    body = run_commands(module, [command])[0]
+    body = run_commands(module, {'command': command, 'output': 'text'})[0]
     if 'No such file' in body:
         return False
     return True
@@ -110,7 +110,7 @@ def remote_file_exists(module, dst, file_system='bootflash:'):
 
 def verify_remote_file_exists(module, dst, file_system='bootflash:'):
     command = 'dir {0}/{1}'.format(file_system, dst)
-    body = run_commands(module, [command])[0]
+    body = run_commands(module, {'command': command, 'output': 'text'})[0]
     if 'No such file' in body:
         return 0
     return body.split()[0].strip()
@@ -122,7 +122,7 @@ def local_file_exists(module):
 
 def get_flash_size(module):
     command = 'dir {}'.format(module.params['file_system'])
-    body = run_commands(module, [command])[0]
+    body = run_commands(module, {'command': command, 'output': 'text'})[0]
 
     match = re.search(r'(\d+) bytes free', body)
     bytes_free = match.group(1)
@@ -181,9 +181,6 @@ def main():
         local_file=dict(required=True),
         remote_file=dict(required=False),
         file_system=dict(required=False, default='bootflash:'),
-        include_defaults=dict(default=True),
-        config=dict(),
-        save=dict(type='bool', default=False)
     )
 
     argument_spec.update(nxos_argument_spec)


Test patch: