Add netconf_get module (#39869)

* Add netconf_get module

Implements part-1 of proposal #104
https://github.com/ansible/proposals/issues/104

*  Add netconf_get module
*  Refactor `get`, `get_config`, `lock`, `unlock`
   and `discard_changes` netconf plugin api's
*  Add netconf module_utils file which netconf module
   related common functions
*  Refactor junos and iosxr netconf plugins

* Fix source option handling

* Fix review comments

* Update botmeta file

* Update review comments and add support for lock

* Lock update fix

* Fix CI issue

* Add integration test and minor fixes

* Fix review comments

* Fix CI failure

* Fix CI issues

* Fix CI issues

* Fix review comments and update integration test

* Fix review comments

* Fix review comments

* Fix review comments

Fix reveiw comments
This commit is contained in:
Ganesh Nalawade
2018-05-17 17:38:12 +05:30
committed by GitHub
parent 4c0ceaea3d
commit 30f992f260
16 changed files with 841 additions and 119 deletions

View File

@@ -110,22 +110,35 @@ class NetconfBase(with_metaclass(ABCMeta, object)):
raise Exception(to_xml(msg))
@ensure_connected
def get_config(self, *args, **kwargs):
"""Retrieve all or part of a specified configuration.
:source: name of the configuration datastore being queried
:filter: specifies the portion of the configuration to retrieve
(by default entire configuration is retrieved)"""
resp = self.m.get_config(*args, **kwargs)
def get_config(self, source=None, filter=None):
"""Retrieve all or part of a specified configuration
(by default entire configuration is retrieved).
:param source: Name of the configuration datastore being queried, defaults to running datastore
:param filter: This argument specifies the portion of the configuration data to retrieve
:return: Returns xml string containing the RPC response received from remote host
"""
if isinstance(filter, list):
filter = tuple(filter)
if not source:
source = 'running'
resp = self.m.get_config(source=source, filter=filter)
return resp.data_xml if hasattr(resp, 'data_xml') else resp.xml
@ensure_connected
def get(self, *args, **kwargs):
"""Retrieve running configuration and device state information.
*filter* specifies the portion of the configuration to retrieve
(by default entire configuration is retrieved)
def get(self, filter=None):
"""Retrieve device configuration and state information.
:param filter: This argument specifies the portion of the state data to retrieve
(by default entire state data is retrieved)
:return: Returns xml string containing the RPC response received from remote host
"""
resp = self.m.get(*args, **kwargs)
return resp.data_xml if hasattr(resp, 'data_xml') else resp.xml
if isinstance(filter, list):
filter = tuple(filter)
resp = self.m.get(filter=filter)
response = resp.data_xml if hasattr(resp, 'data_xml') else resp.xml
return response
@ensure_connected
def edit_config(self, *args, **kwargs):
@@ -162,26 +175,42 @@ class NetconfBase(with_metaclass(ABCMeta, object)):
return resp.data_xml if hasattr(resp, 'data_xml') else resp.xml
@ensure_connected
def lock(self, *args, **kwargs):
"""Allows the client to lock the configuration system of a device.
*target* is the name of the configuration datastore to lock
def lock(self, target=None):
"""
resp = self.m.lock(*args, **kwargs)
Allows the client to lock the configuration system of a device.
:param target: is the name of the configuration datastore to lock,
defaults to candidate datastore
:return: Returns xml string containing the RPC response received from remote host
"""
if not target:
target = 'candidate'
resp = self.m.lock(target=target)
return resp.data_xml if hasattr(resp, 'data_xml') else resp.xml
@ensure_connected
def unlock(self, *args, **kwargs):
def unlock(self, target=None):
"""
Release a configuration lock, previously obtained with the lock operation.
:param target: is the name of the configuration datastore to unlock,
defaults to candidate datastore
:return: Returns xml string containing the RPC response received from remote host
"""
"""Release a configuration lock, previously obtained with the lock operation.
:target: is the name of the configuration datastore to unlock
"""
resp = self.m.unlock(*args, **kwargs)
if not target:
target = 'candidate'
resp = self.m.unlock(target=target)
return resp.data_xml if hasattr(resp, 'data_xml') else resp.xml
@ensure_connected
def discard_changes(self, *args, **kwargs):
"""Revert the candidate configuration to the currently running configuration.
Any uncommitted changes are discarded."""
resp = self.m.discard_changes(*args, **kwargs)
def discard_changes(self):
"""
Revert the candidate configuration to the currently running configuration.
Any uncommitted changes are discarded.
:return: Returns xml string containing the RPC response received from remote host
"""
resp = self.m.discard_changes()
return resp.data_xml if hasattr(resp, 'data_xml') else resp.xml
@ensure_connected
@@ -245,4 +274,28 @@ class NetconfBase(with_metaclass(ABCMeta, object)):
"""Fetch file over scp from remote device"""
pass
def get_device_operations(self, server_capabilities):
operations = {}
capabilities = '\n'.join(server_capabilities)
operations['supports_commit'] = True if ':candidate' in capabilities else False
operations['supports_defaults'] = True if ':with-defaults' in capabilities else False
operations['supports_confirm_commit'] = True if ':confirmed-commit' in capabilities else False
operations['supports_startup'] = True if ':startup' in capabilities else False
operations['supports_xpath'] = True if ':xpath' in capabilities else False
operations['supports_writeable_running'] = True if ':writable-running' in capabilities else False
operations['lock_datastore'] = []
if operations['supports_writeable_running']:
operations['lock_datastore'].append('running')
if operations['supports_commit']:
operations['lock_datastore'].append('candidate')
if operations['supports_startup']:
operations['lock_datastore'].append('startup')
operations['supports_lock'] = True if len(operations['lock_datastore']) else False
return operations
# TODO Restore .xml, when ncclient supports it for all platforms