From ba4d4caeb35801ba416381eebc30d6a63ca279a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Tue, 11 Jun 2024 21:37:55 +0200 Subject: [PATCH] infamy: netconf: Implement deletion by xpath This is the only way to delete with restconf so it it must also be implemented in netconf. This replace the put_diff_dict function. Also: how the xpath looks is different in restconf/netconf therefore each protocl has a get_xpath() function as well. --- test/infamy/netconf.py | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/test/infamy/netconf.py b/test/infamy/netconf.py index 991bea1c..870c8973 100644 --- a/test/infamy/netconf.py +++ b/test/infamy/netconf.py @@ -8,6 +8,8 @@ import sys import time import uuid # For _ncc_get_data() extension import os +import copy +import re import libyang import lxml @@ -344,13 +346,6 @@ class Device(object): lyd = mod.parse_data_dict(edit, no_state=True, validate=False) return self.put_config(lyd.print_mem("xml", with_siblings=True, pretty=False)) - def put_diff_dicts(self, modname, old, new): - mod = self.ly.get_module(modname) - oldd = mod.parse_data_dict(old, no_state=True) - newd = mod.parse_data_dict(new, no_state=True) - lyd = oldd.diff(newd) - return self.put_config(lyd.print_mem("xml", with_siblings=True, pretty=False)) - def call(self, call): """Call RPC, XML version""" return self.ncc.dispatch(call) @@ -402,3 +397,32 @@ class Device(object): with open(outdir+"/"+schema["filename"], "w") as f: f.write(data.schema) + + def get_xpath(self, xpath, key, value, path=None): + """Compose complete XPath to a YANG node in /ietf-interfaces""" + xpath = f"{xpath}[{key}='{value}']" + if not path is None: + xpath=f"{xpath}/{path}" + return xpath + + def get_iface_xpath(self, iface, path=None): + """Compose complete XPath to a YANG node in /ietf-interfaces""" + xpath = f"/ietf-interfaces:interfaces/interface" + return self.get_xpath(xpath, "name", iface, path) + + def delete_xpath(self, xpath): + # Split out the model and the container from xpath + pattern = r"^/(?P[^:]+):(?P[^/]+)" + match = re.search(pattern, xpath) + module = match.group('module') + modpath = f"/{match.group('module')}:{match.group('path')}" + + old = self.get_config_dict(modpath) + new = copy.deepcopy(old) + libyang.xpath_del(new, xpath) + mod = self.ly.get_module(module) + oldd = mod.parse_data_dict(old, no_state=True) + newd = mod.parse_data_dict(new, no_state=True) + lyd = oldd.diff(newd) + + return self.put_config(lyd.print_mem("xml", with_siblings=True, pretty=False))