diff options
author | Xu Yuandong <yuandongdeyouxiang@gmail.com> | 2019-10-12 23:48:33 +0800 |
---|---|---|
committer | Toshio Kuratomi <a.badger@gmail.com> | 2019-10-12 09:17:10 -0700 |
commit | 8c05339cb7af113811dd54decbd6aa26461348b3 (patch) | |
tree | eb755640d1f3501153c44e05f6eae407d847d10e | |
parent | 2a3ce4d6ec0a339e42bcf246801f6765e40be836 (diff) | |
download | ansible-8c05339cb7af113811dd54decbd6aa26461348b3.tar.gz |
Backport/2.9/62587 module_utils/network/cloudengine:fix get_nc_next. (#62752)
* fix plugins/netconf/ce.py for netconf/capability/exchange (#60569)
(cherry picked from commit 037401b6e0d5c500774e2a259909e6fa7e3f16e2)
* for capability/exchange/1.0 (#60630)
* for capability/exchange/1.0
* for capability/exchange/1.0
* update for shippable
* Update ce.py
* Update ce.py
(cherry picked from commit 28227c95a468b26a2bbd3d6d4338565f1cb84e34)
* module_utils-network-cloudengine: fix get_nc_next. (#62587)
* fix get_nc_next.
* add a changelog fragment.
* upadte for changelgo fragment.
* merge two prs, one depens another.
* merge two prs, one depens another.
* update changelog.
(cherry picked from commit d6ef7c8530ca1f45cc1a0b41a97919fa4d98e1f1)
-rw-r--r-- | changelogs/fragments/60569-plugins-netconf-ce.yml | 2 | ||||
-rw-r--r-- | changelogs/fragments/62587-module_utils-network-cloudengine.yml | 3 | ||||
-rw-r--r-- | lib/ansible/module_utils/network/cloudengine/ce.py | 32 | ||||
-rw-r--r-- | lib/ansible/plugins/netconf/ce.py | 24 |
4 files changed, 59 insertions, 2 deletions
diff --git a/changelogs/fragments/60569-plugins-netconf-ce.yml b/changelogs/fragments/60569-plugins-netconf-ce.yml new file mode 100644 index 0000000000..9d6ce19417 --- /dev/null +++ b/changelogs/fragments/60569-plugins-netconf-ce.yml @@ -0,0 +1,2 @@ +bugfixes: + - plugins-netconf-ce - to get attribute 'set-id' from rpc-reply. diff --git a/changelogs/fragments/62587-module_utils-network-cloudengine.yml b/changelogs/fragments/62587-module_utils-network-cloudengine.yml new file mode 100644 index 0000000000..708128caf3 --- /dev/null +++ b/changelogs/fragments/62587-module_utils-network-cloudengine.yml @@ -0,0 +1,3 @@ +bugfixes: + - "Cloudengine module_utils - the ``set-id`` (RPC-REPLY XML attribute) may change over the time althougth ``set-id`` is the identity of the next RPC packet." + - "Cloudengine netconf plugin - add a dispatch RPC function,just return original RPC-REPLY, the function is used by ``Cloudengine module_utils``." diff --git a/lib/ansible/module_utils/network/cloudengine/ce.py b/lib/ansible/module_utils/network/cloudengine/ce.py index 168c790683..01df0e795d 100644 --- a/lib/ansible/module_utils/network/cloudengine/ce.py +++ b/lib/ansible/module_utils/network/cloudengine/ce.py @@ -35,19 +35,24 @@ import traceback from ansible.module_utils.basic import env_fallback from ansible.module_utils.network.common.utils import to_list, ComplexList -from ansible.module_utils.connection import exec_command +from ansible.module_utils.connection import exec_command, ConnectionError from ansible.module_utils.six import iteritems from ansible.module_utils._text import to_native from ansible.module_utils.network.common.netconf import NetconfConnection try: - from ncclient.xml_ import to_xml + from ncclient.xml_ import to_xml, new_ele_ns HAS_NCCLIENT = True except ImportError: HAS_NCCLIENT = False +try: + from lxml import etree +except ImportError: + from xml.etree import ElementTree as etree + _DEVICE_CLI_CONNECTION = None _DEVICE_NC_CONNECTION = None @@ -343,6 +348,29 @@ def set_nc_config(module, xml_str): return to_string(to_xml(out)) +def get_nc_next(module, xml_str): + """ get_nc_next for exchange capability """ + + conn = get_nc_connection(module) + result = None + if xml_str is not None: + response = conn.get(xml_str, if_rpc_reply=True) + result = response.find('./*') + set_id = response.get('set-id') + while True and set_id is not None: + try: + fetch_node = new_ele_ns('get-next', 'http://www.huawei.com/netconf/capability/base/1.0', {'set-id': set_id}) + next_xml = conn.dispatch_rpc(etree.tostring(fetch_node)) + if next_xml is not None: + result.extend(next_xml.find('./*')) + set_id = next_xml.get('set-id') + except ConnectionError: + break + if result is not None: + return etree.tostring(result) + return result + + def get_nc_config(module, xml_str): """ get_config """ diff --git a/lib/ansible/plugins/netconf/ce.py b/lib/ansible/plugins/netconf/ce.py index 24066b13e0..784e283d57 100644 --- a/lib/ansible/plugins/netconf/ce.py +++ b/lib/ansible/plugins/netconf/ce.py @@ -36,6 +36,11 @@ try: except (ImportError, AttributeError): # paramiko and gssapi are incompatible and raise AttributeError not ImportError HAS_NCCLIENT = False +try: + from lxml.etree import fromstring +except ImportError: + from xml.etree.ElementTree import fromstring + class Netconf(NetconfBase): @@ -167,6 +172,9 @@ class Netconf(NetconfBase): @ensure_connected def get(self, *args, **kwargs): try: + if_rpc_reply = kwargs.pop('if_rpc_reply', False) + if if_rpc_reply: + return self.m.get(*args, **kwargs).xml return self.m.get(*args, **kwargs).data_xml except RPCError as exc: raise Exception(to_xml(exc.xml)) @@ -210,3 +218,19 @@ class Netconf(NetconfBase): @ensure_connected def discard_changes(self, *args, **kwargs): return self.m.discard_changes(*args, **kwargs).data_xml + + @ensure_ncclient + @ensure_connected + def dispatch_rpc(self, rpc_command=None, source=None, filter=None): + """ + Execute rpc on the remote device eg. dispatch('get-next') + :param rpc_command: specifies rpc command to be dispatched either in plain text or in xml element format (depending on command) + :param source: name of the configuration datastore being queried + :param filter: specifies the portion of the configuration to retrieve (by default entire configuration is retrieved) + :return: Returns xml string containing the rpc-reply response received from remote host + """ + if rpc_command is None: + raise ValueError('rpc_command value must be provided') + resp = self.m.dispatch(fromstring(rpc_command), source=source, filter=filter) + # just return rpc-reply xml + return resp.xml |