diff options
Diffstat (limited to 'python/vyos/configtree.py')
-rw-r--r-- | python/vyos/configtree.py | 71 |
1 files changed, 56 insertions, 15 deletions
diff --git a/python/vyos/configtree.py b/python/vyos/configtree.py index 4b46a1fb3..a812b62ec 100644 --- a/python/vyos/configtree.py +++ b/python/vyos/configtree.py @@ -24,6 +24,7 @@ def strip_comments(s): IN_COMMENT = 1 i = len(s) - 1 + state = INITIAL config_end = 0 @@ -40,20 +41,19 @@ def strip_comments(s): else: config_end = 0 break - elif (state == INITIAL) and (c == '/'): - # A comment begins, or it's a stray slash - try: - if (s[i-1] == '*'): - state = IN_COMMENT - i -= 2 - else: - raise ValueError("Invalid syntax") - except: - raise ValueError("Invalid syntax") - elif (state == INITIAL) and (c == '}'): - # We are not inside a comment, that's the end of the last node + elif (state == INITIAL) and not re.match(r'(\s|\/)', c): + # Assume there are no (more) trailing comments, + # this is an end of a node: either a brace of the last character + # of a leaf node value config_end = i + 1 break + elif (state == INITIAL) and (c == '/'): + # A comment begins, or it's a stray slash + if (s[i-1] == '*'): + state = IN_COMMENT + i -= 2 + else: + raise ValueError("Invalid syntax: stray slash at character {0}".format(i + 1)) elif (state == IN_COMMENT) and (c == '*'): # A comment ends here try: @@ -61,12 +61,13 @@ def strip_comments(s): state = INITIAL i -= 2 except: - raise ValueError("Invalid syntax") + raise ValueError("Invalid syntax: malformed commend end at character {0}".format(i + 1)) elif (state == IN_COMMENT) and (c != '*'): # Ignore everything inside comments, including braces i -= 1 else: - raise ValueError("Invalid syntax") + # Shouldn't happen + raise ValueError("Invalid syntax at character {0}: invalid character {1}".format(i + 1, c)) return (s[0:config_end], s[config_end+1:]) @@ -92,6 +93,10 @@ class ConfigTree(object): self.__from_string.argtypes = [c_char_p] self.__from_string.restype = c_void_p + self.__get_error = self.__lib.get_error + self.__get_error.argtypes = [] + self.__get_error.restype = c_char_p + self.__to_string = self.__lib.to_string self.__to_string.argtypes = [c_void_p] self.__to_string.restype = c_char_p @@ -112,6 +117,14 @@ class ConfigTree(object): self.__delete.argtypes = [c_void_p, c_char_p] self.__delete.restype = c_int + self.__rename = self.__lib.rename_node + self.__rename.argtypes = [c_void_p, c_char_p, c_char_p] + self.__rename.restype = c_int + + self.__copy = self.__lib.copy_node + self.__copy.argtypes = [c_void_p, c_char_p, c_char_p] + self.__copy.restype = c_int + self.__set_replace_value = self.__lib.set_replace_value self.__set_replace_value.argtypes = [c_void_p, c_char_p, c_char_p] self.__set_replace_value.restype = c_int @@ -150,10 +163,12 @@ class ConfigTree(object): config_section, comments_section = strip_comments(config_string) config = self.__from_string(config_section.encode()) if config is None: - raise ValueError("Parse error") + msg = self.__get_error().decode() + raise ValueError("Failed to parse config: {0}".format(msg)) else: self.__config = config self.__comments = comments_section + def __del__(self): if self.__config is not None: self.__destroy(self.__config) @@ -193,6 +208,32 @@ class ConfigTree(object): self.__delete_value(self.__config, path_str, value.encode()) + def rename(self, path, new_name): + check_path(path) + path_str = " ".join(map(str, path)).encode() + newname_str = new_name.encode() + + # Check if a node with intended new name already exists + new_path = path[:-1] + [new_name] + if self.exists(new_path): + raise ConfigTreeError() + res = self.__rename(self.__config, path_str, newname_str) + if (res != 0): + raise ConfigTreeError("Path [{}] doesn't exist".format(oldpath)) + + def copy(self, old_path, new_path): + check_path(old_path) + check_path(new_path) + oldpath_str = " ".join(map(str, old_path)).encode() + newpath_str = " ".join(map(str, new_path)).encode() + + # Check if a node with intended new name already exists + if self.exists(new_path): + raise ConfigTreeError() + res = self.__copy(self.__config, oldpath_str, newpath_str) + if (res != 0): + raise ConfigTreeError("Path [{}] doesn't exist".format(oldpath)) + def exists(self, path): check_path(path) path_str = " ".join(map(str, path)).encode() |