diff --git a/test/infamy/netconf.py b/test/infamy/netconf.py
index 14353767..56303d96 100644
--- a/test/infamy/netconf.py
+++ b/test/infamy/netconf.py
@@ -6,6 +6,7 @@ import logging
import socket
import sys
import time
+import uuid # For _ncc_get_data() extension
import libyang
import lxml
@@ -45,6 +46,13 @@ class Manager(netconf_client.ncclient.Manager):
self.set_logger_level(logging.DEBUG)
self.logger().addHandler(logging.StreamHandler(sys.stderr))
+class NccGetDataReply:
+ """Fold in to DataReply class when upstreaming"""
+ def __init__(self, raw, ele):
+ self.data_ele = ele.find("{urn:ietf:params:xml:ns:yang:ietf-netconf-nmda}data")
+ self.data_xml = lxml.etree.tostring(self.data_ele)
+ self.raw_reply = raw
+
@dataclass
class Location:
host: str
@@ -120,6 +128,25 @@ class Device(object):
return list(filter(lambda m: m["name"] in modnames,
self.modules.values()))
+ def _ncc_make_rpc(self, guts, msg_id=None):
+ if not msg_id:
+ msg_id = uuid.uuid4()
+
+ return '{guts}' \
+ .format(guts=guts, id=msg_id).encode("utf-8")
+
+ def _ncc_get_data_rpc(self, datastore="operational", filter=None, msg_id=None):
+ pieces = []
+ pieces.append('')
+ pieces.append(f''
+ f'ds:{datastore}'
+ f'')
+ if filter:
+ xmlns = " ".join([f"xmlns:{m['name']}=\"{m['namespace']}\"" for m in self._modules_in_xpath(filter)])
+ pieces.append(f'{filter}')
+ pieces.append("")
+ return self._ncc_make_rpc("".join(pieces), msg_id=msg_id)
+
def _get(self, xpath, getter):
# Figure out which modules we are referencing
mods = self._modules_in_xpath(xpath)
@@ -127,16 +154,32 @@ class Device(object):
# Fetch the data
xmlns = " ".join([f"xmlns:{m['name']}=\"{m['namespace']}\"" for m in mods])
filt = f""
+ # pylint: disable=c-extension-no-member
cfg = lxml.etree.tostring(getter(filter=filt).data_ele[0])
return self.ly.parse_data_mem(cfg, "xml", parse_only=True)
+ def _get_data(self, xpath):
+ """Local member wrapper for netconf-client RPC"""
+ # pylint: disable=protected-access
+ (raw, ele) = self.ncc._send_rpc(self._ncc_get_data_rpc(filter=xpath))
+ data = NccGetDataReply(raw, ele)
+ # pylint: disable=c-extension-no-member
+ cfg = lxml.etree.tostring(data.data_ele[0])
+ return self.ly.parse_data_mem(cfg, "xml", parse_only=True)
+
def get(self, xpath):
+ """RPC (legacy NETCONF) fetches config:false data"""
return self._get(xpath, self.ncc.get)
def get_dict(self, xpath):
+ """Return Python dictionary of RPC data"""
return self.get(xpath).print_dict()
+ def get_data(self, xpath):
+ """RPC to fetch operational data"""
+ return self._get_data(xpath).print_dict()
+
def get_config(self, xpath):
return self._get(xpath, self.ncc.get_config)