From ff7e2cd622cf3679cd9265b2cb766395a1830f50 Mon Sep 17 00:00:00 2001 From: John Estabrook Date: Fri, 25 Feb 2022 16:05:03 -0600 Subject: configtree: T4235: add utility get_subtree --- python/vyos/configtree.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/python/vyos/configtree.py b/python/vyos/configtree.py index 866f24e47..0ec15cf40 100644 --- a/python/vyos/configtree.py +++ b/python/vyos/configtree.py @@ -126,6 +126,10 @@ class ConfigTree(object): self.__set_tag.argtypes = [c_void_p, c_char_p] self.__set_tag.restype = c_int + self.__get_subtree = self.__lib.get_subtree + self.__get_subtree.argtypes = [c_void_p, c_char_p] + self.__get_subtree.restype = c_void_p + self.__destroy = self.__lib.destroy self.__destroy.argtypes = [c_void_p] @@ -291,6 +295,14 @@ class ConfigTree(object): else: raise ConfigTreeError("Path [{}] doesn't exist".format(path_str)) + def get_subtree(self, path, with_node=False): + check_path(path) + path_str = " ".join(map(str, path)).encode() + + res = self.__get_subtree(self.__config, path_str, with_node) + subt = ConfigTree(address=res) + return subt + class Diff: def __init__(self, left, right, path=[], libpath=LIBPATH): if not (isinstance(left, ConfigTree) and isinstance(right, ConfigTree)): -- cgit v1.2.3 From 3d28528ff84b4e874faf80028709bd08b2956933 Mon Sep 17 00:00:00 2001 From: John Estabrook Date: Fri, 25 Feb 2022 16:10:12 -0600 Subject: configtree: T4235: simplification of diff_tree class The return value of diff_tree is now a single config_tree, with initial children of names: ["add", "delete", "inter"] containing the config sub-trees of added paths; deleted paths; and intersection, respectively. The simplifies dumping to json, and checking existence of paths, hence, of node changes. --- python/vyos/configtree.py | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/python/vyos/configtree.py b/python/vyos/configtree.py index 0ec15cf40..f5e697137 100644 --- a/python/vyos/configtree.py +++ b/python/vyos/configtree.py @@ -15,7 +15,7 @@ import re import json -from ctypes import cdll, c_char_p, c_void_p, c_int, POINTER +from ctypes import cdll, c_char_p, c_void_p, c_int LIBPATH = '/usr/lib/libvyosconfig.so.0' @@ -303,7 +303,7 @@ class ConfigTree(object): subt = ConfigTree(address=res) return subt -class Diff: +class DiffTree: def __init__(self, left, right, path=[], libpath=LIBPATH): if not (isinstance(left, ConfigTree) and isinstance(right, ConfigTree)): raise TypeError("Arguments must be instances of ConfigTree") @@ -312,21 +312,28 @@ class Diff: raise ConfigTreeError(f"Path {path} doesn't exist in lhs tree") if not right.exists(path): raise ConfigTreeError(f"Path {path} doesn't exist in rhs tree") + self.left = left self.right = right + self.__lib = cdll.LoadLibrary(libpath) + + self.__diff_tree = self.__lib.diff_tree + self.__diff_tree.argtypes = [c_char_p, c_void_p, c_void_p] + self.__diff_tree.restype = c_void_p + check_path(path) path_str = " ".join(map(str, path)).encode() - df = cdll.LoadLibrary(libpath).diffs - df.restype = POINTER(c_void_p * 3) - res = list(df(path_str, left._get_config(), right._get_config()).contents) - self._diff = {'add': ConfigTree(address=res[0]), - 'del': ConfigTree(address=res[1]), - 'int': ConfigTree(address=res[2]) } - - self.add = self._diff['add'] - self.delete = self._diff['del'] - self.inter = self._diff['int'] + res = self.__diff_tree(path_str, left._get_config(), right._get_config()) + + # full diff config_tree and python dict representation + self.full = ConfigTree(address=res) + self.dict = json.loads(self.full.to_json()) + + # config_tree sub-trees + self.add = self.full.get_subtree(['add']) + self.delete = self.full.get_subtree(['delete']) + self.inter = self.full.get_subtree(['inter']) def to_commands(self): add = self.add.to_commands() -- cgit v1.2.3 From 4625fd41f99ddf77c104a657cd90a1ddf5449dd8 Mon Sep 17 00:00:00 2001 From: John Estabrook Date: Fri, 25 Feb 2022 16:12:29 -0600 Subject: configtree: T4235: allow empty arguments --- python/vyos/configtree.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/vyos/configtree.py b/python/vyos/configtree.py index f5e697137..5ba829a4c 100644 --- a/python/vyos/configtree.py +++ b/python/vyos/configtree.py @@ -305,6 +305,10 @@ class ConfigTree(object): class DiffTree: def __init__(self, left, right, path=[], libpath=LIBPATH): + if left is None: + left = ConfigTree(config_string='\n') + if right is None: + right = ConfigTree(config_string='\n') if not (isinstance(left, ConfigTree) and isinstance(right, ConfigTree)): raise TypeError("Arguments must be instances of ConfigTree") if path: -- cgit v1.2.3 From 193cbd15ba39a41614c63b997e6a62254589158a Mon Sep 17 00:00:00 2001 From: John Estabrook Date: Sun, 27 Feb 2022 10:05:40 -0600 Subject: configtree: T4235: distinguish sub(-tract) tree from delete tree The DiffTree class maintains both the 'sub'(-tract) configtree, containing all paths in the LHS of the comparison that are not in the RHS, and the 'delete' configtree: the delete tree is the minimal subtree containing only the first node of a path not present in the RHS. It is the delete tree that is needed to produce 'delete' commands for config mode, whereas the 'sub' tree contains full information, needed for recursively detecting changes to a node. --- python/vyos/configtree.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/python/vyos/configtree.py b/python/vyos/configtree.py index 5ba829a4c..e9cdb69e4 100644 --- a/python/vyos/configtree.py +++ b/python/vyos/configtree.py @@ -326,8 +326,13 @@ class DiffTree: self.__diff_tree.argtypes = [c_char_p, c_void_p, c_void_p] self.__diff_tree.restype = c_void_p + self.__trim_tree = self.__lib.trim_tree + self.__trim_tree.argtypes = [c_void_p, c_void_p] + self.__trim_tree.restype = c_void_p + check_path(path) path_str = " ".join(map(str, path)).encode() + res = self.__diff_tree(path_str, left._get_config(), right._get_config()) # full diff config_tree and python dict representation @@ -336,9 +341,14 @@ class DiffTree: # config_tree sub-trees self.add = self.full.get_subtree(['add']) - self.delete = self.full.get_subtree(['delete']) + self.sub = self.full.get_subtree(['sub']) self.inter = self.full.get_subtree(['inter']) + # trim sub(-tract) tree to get delete tree for commands + ref = self.right.get_subtree(path, with_node=True) if path else self.right + res = self.__trim_tree(self.sub._get_config(), ref._get_config()) + self.delete = ConfigTree(address=res) + def to_commands(self): add = self.add.to_commands() delete = self.delete.to_commands(op="delete") -- cgit v1.2.3