From e367361d45c39cf0b85547c2947575ed0f6f9fe1 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Tue, 4 Feb 2025 15:17:21 +0100 Subject: [PATCH] Add huge_tree support for RPC calls When retrieving large XML responses over Netconf we need to use lxml with huge_trees, because the default XML parser bails out. Fixes: #255 --- changelogs/fragments/add_rpc_huge_tree_support.yaml | 3 +++ plugins/module_utils/network/common/netconf.py | 13 ++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/add_rpc_huge_tree_support.yaml diff --git a/changelogs/fragments/add_rpc_huge_tree_support.yaml b/changelogs/fragments/add_rpc_huge_tree_support.yaml new file mode 100644 index 000000000..df98aae86 --- /dev/null +++ b/changelogs/fragments/add_rpc_huge_tree_support.yaml @@ -0,0 +1,3 @@ +--- +minor_changes: + - "Add `huge_tree` support for RPC calls to support large RPC responses with lxml." diff --git a/plugins/module_utils/network/common/netconf.py b/plugins/module_utils/network/common/netconf.py index a12fbe226..ad56fb262 100644 --- a/plugins/module_utils/network/common/netconf.py +++ b/plugins/module_utils/network/common/netconf.py @@ -27,7 +27,7 @@ HAS_NCCLIENT = False try: - from lxml.etree import Element, XMLSyntaxError, fromstring + from lxml.etree import Element, XMLParser, XMLSyntaxError, fromstring except ImportError: from xml.etree.ElementTree import Element, fromstring @@ -59,12 +59,23 @@ def __rpc__(self, name, *args, **kwargs): """ self.check_rc = kwargs.pop("check_rc", True) self.ignore_warning = kwargs.pop("ignore_warning", True) + self.huge_tree = kwargs.pop("huge_tree", False) response = self._exec_jsonrpc(name, *args, **kwargs) if "error" in response: rpc_error = response["error"].get("data") return self.parse_rpc_error(to_bytes(rpc_error, errors="surrogate_then_replace")) + if self.huge_tree: + try: + _parser = XMLParser(encoding="utf-8", recover=True, huge_tree=True) + except NameError as exc: + raise RuntimeError("XML huge_tree requires lxml.") from exc + return fromstring( + to_bytes(response["result"], errors="surrogate_then_replace"), + _parser, + ) + return fromstring(to_bytes(response["result"], errors="surrogate_then_replace")) def parse_rpc_error(self, rpc_error):