Repository: ansible/ansible

Issue:
netconf_config problem with ncclient 
<!---
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 ncclient -->
netconf_config

##### ANSIBLE VERSION
```
$ command ansible --version
ansible 2.2.0.0
  config file = /home/steve/ansible-test/ansible.cfg
  configured module search path = Default w/o overrides
```

##### CONFIGURATION
<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

##### OS / ENVIRONMENT
$  lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.1 LTS
Release:        16.04
Codename:       xenial

##### SUMMARY
Ansible not seeing ncclient module

##### STEPS TO REPRODUCE
<!---
run attached sites.yml playbook 
-->

<!--- Paste example playbooks or commands between quotes below -->
```
steve@gitsum:~/ansible-automation$ ansible-playbook site.yml --v
Usage: ansible-playbook playbook.yml

ansible-playbook: error: ambiguous option: --v (--vault-password-file, --verbose, --version?)
steve@gitsum:~/ansible-automation$ ansible-playbook site.yml -vvvv
Using /home/steve/ansible-automation/ansible.cfg as config file
Loading callback plugin default of type stdout, v2.0 from /usr/local/lib/python2.7/dist-packages/ansible/plugins/callback/__init__.pyc

PLAYBOOK: site.yml *************************************************************
1 plays in site.yml

PLAY [hp5900] ******************************************************************

TASK [motd : Configure MOTD banner] ********************************************
task path: /home/steve/ansible-automation/roles/motd/tasks/main.yml:2
Using module file /usr/local/lib/python2.7/dist-packages/ansible/modules/extras/network/netconf/netconf_config.py
<192.168.11.15> ESTABLISH LOCAL CONNECTION FOR USER: steve
<192.168.11.15> EXEC /bin/sh -c '/usr/bin/python && sleep 0'
An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_9TGtyr/ansible_module_netconf_config.py", line 221, in <module>
    main()
  File "/tmp/ansible_9TGtyr/ansible_module_netconf_config.py", line 210, in main
    retkwargs=retkwargs,
  File "/tmp/ansible_9TGtyr/ansible_module_netconf_config.py", line 135, in netconf_edit_config
    m.discard_changes()
  File "/usr/local/lib/python2.7/dist-packages/ncclient/manager.py", line 161, in wrapper
    return self.execute(op_cls, *args, **kwds)
  File "/usr/local/lib/python2.7/dist-packages/ncclient/manager.py", line 231, in execute
    raise_mode=self._raise_mode).request(*args, **kwds)
  File "/usr/local/lib/python2.7/dist-packages/ncclient/operations/rpc.py", line 282, in __init__
    self._assert(cap)
  File "/usr/local/lib/python2.7/dist-packages/ncclient/operations/rpc.py", line 356, in _assert
    raise MissingCapabilityError('Server does not support [%s]' % capability)
ncclient.operations.errors.MissingCapabilityError: Server does not support [:candidate]
fatal: [192.168.11.15]: FAILED! => {
    "changed": false, 
    "failed": true, 
    "invocation": {
        "module_name": "netconf_config"
    }, 
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_9TGtyr/ansible_module_netconf_config.py\", line 221, in <module>\n    main()\n  File \"/tmp/ansible_9TGtyr/ansible_module_netconf_config.py\", line 210, in main\n    retkwargs=retkwargs,\n  File \"/tmp/ansible_9TGtyr/ansible_module_netconf_config.py\", line 135, in netconf_edit_config\n    m.discard_changes()\n  File \"/usr/local/lib/python2.7/dist-packages/ncclient/manager.py\", line 161, in wrapper\n    return self.execute(op_cls, *args, **kwds)\n  File \"/usr/local/lib/python2.7/dist-packages/ncclient/manager.py\", line 231, in execute\n    raise_mode=self._raise_mode).request(*args, **kwds)\n  File \"/usr/local/lib/python2.7/dist-packages/ncclient/operations/rpc.py\", line 282, in __init__\n    self._assert(cap)\n  File \"/usr/local/lib/python2.7/dist-packages/ncclient/operations/rpc.py\", line 356, in _assert\n    raise MissingCapabilityError('Server does not support [%s]' % capability)\nncclient.operations.errors.MissingCapabilityError: Server does not support [:candidate]\n", 
    "module_stdout": "", 
    "msg": "MODULE FAILURE"
}
        to retry, use: --limit @/home/steve/ansible-automation/site.retry

PLAY RECAP *********************************************************************
192.168.11.15              : ok=0    changed=0    unreachable=0    failed=1   

```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- Update HP5900 with new MOTD babber? -->

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
steve@gitsum:~/ansible-automation$ ansible-playbook site.yml --v
Usage: ansible-playbook playbook.yml

ansible-playbook: error: ambiguous option: --v (--vault-password-file, --verbose, --version?)
steve@gitsum:~/ansible-automation$ ansible-playbook site.yml -vvvv
Using /home/steve/ansible-automation/ansible.cfg as config file
Loading callback plugin default of type stdout, v2.0 from /usr/local/lib/python2.7/dist-packages/ansible/plugins/callback/__init__.pyc

PLAYBOOK: site.yml *************************************************************
1 plays in site.yml

PLAY [hp5900] ******************************************************************

TASK [motd : Configure MOTD banner] ********************************************
task path: /home/steve/ansible-automation/roles/motd/tasks/main.yml:2
Using module file /usr/local/lib/python2.7/dist-packages/ansible/modules/extras/network/netconf/netconf_config.py
<192.168.11.15> ESTABLISH LOCAL CONNECTION FOR USER: steve
<192.168.11.15> EXEC /bin/sh -c '/usr/bin/python && sleep 0'
An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_9TGtyr/ansible_module_netconf_config.py", line 221, in <module>
    main()
  File "/tmp/ansible_9TGtyr/ansible_module_netconf_config.py", line 210, in main
    retkwargs=retkwargs,
  File "/tmp/ansible_9TGtyr/ansible_module_netconf_config.py", line 135, in netconf_edit_config
    m.discard_changes()
  File "/usr/local/lib/python2.7/dist-packages/ncclient/manager.py", line 161, in wrapper
    return self.execute(op_cls, *args, **kwds)
  File "/usr/local/lib/python2.7/dist-packages/ncclient/manager.py", line 231, in execute
    raise_mode=self._raise_mode).request(*args, **kwds)
  File "/usr/local/lib/python2.7/dist-packages/ncclient/operations/rpc.py", line 282, in __init__
    self._assert(cap)
  File "/usr/local/lib/python2.7/dist-packages/ncclient/operations/rpc.py", line 356, in _assert
    raise MissingCapabilityError('Server does not support [%s]' % capability)
ncclient.operations.errors.MissingCapabilityError: Server does not support [:candidate]
fatal: [192.168.11.15]: FAILED! => {
    "changed": false, 
    "failed": true, 
    "invocation": {
        "module_name": "netconf_config"
    }, 
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_9TGtyr/ansible_module_netconf_config.py\", line 221, in <module>\n    main()\n  File \"/tmp/ansible_9TGtyr/ansible_module_netconf_config.py\", line 210, in main\n    retkwargs=retkwargs,\n  File \"/tmp/ansible_9TGtyr/ansible_module_netconf_config.py\", line 135, in netconf_edit_config\n    m.discard_changes()\n  File \"/usr/local/lib/python2.7/dist-packages/ncclient/manager.py\", line 161, in wrapper\n    return self.execute(op_cls, *args, **kwds)\n  File \"/usr/local/lib/python2.7/dist-packages/ncclient/manager.py\", line 231, in execute\n    raise_mode=self._raise_mode).request(*args, **kwds)\n  File \"/usr/local/lib/python2.7/dist-packages/ncclient/operations/rpc.py\", line 282, in __init__\n    self._assert(cap)\n  File \"/usr/local/lib/python2.7/dist-packages/ncclient/operations/rpc.py\", line 356, in _assert\n    raise MissingCapabilityError('Server does not support [%s]' % capability)\nncclient.operations.errors.MissingCapabilityError: Server does not support [:candidate]\n", 
    "module_stdout": "", 
    "msg": "MODULE FAILURE"
}
        to retry, use: --limit @/home/steve/ansible-automation/site.retry

PLAY RECAP *********************************************************************
192.168.11.15              : ok=0    changed=0    unreachable=0    failed=1   

```



Discussion:
cc @lpenz
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
[ansible-automation-master.zip](https://github.com/ansible/ansible/files/663938/ansible-automation-master.zip)


Resolving patch:
diff --git a/lib/ansible/modules/network/netconf/netconf_config.py b/lib/ansible/modules/network/netconf/netconf_config.py
--- a/lib/ansible/modules/network/netconf/netconf_config.py
+++ b/lib/ansible/modules/network/netconf/netconf_config.py
@@ -136,7 +136,8 @@ def netconf_edit_config(m, xml, commit, retkwargs):
         datastore = 'running'
     m.lock(target=datastore)
     try:
-        m.discard_changes()
+        if ":candidate" in m.server_capabilities:
+            m.discard_changes()
         config_before = m.get_config(source=datastore)
         m.edit_config(target=datastore, config=xml)
         config_after = m.get_config(source=datastore)


Test patch: