Skip to content

Commit

Permalink
[GCU] Supporting Groupings during path-xpath translation
Browse files Browse the repository at this point in the history
  • Loading branch information
ghooo committed Feb 17, 2022
1 parent 9789bfb commit 6a374e3
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 1 deletion.
51 changes: 50 additions & 1 deletion generic_config_updater/gu_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,9 @@ def create_xpath(self, tokens):

return f"{PathAddressing.XPATH_SEPARATOR}{PathAddressing.XPATH_SEPARATOR.join(str(t) for t in tokens)}"

def _create_sonic_yang_with_loaded_models(self):
return self.config_wrapper.create_sonic_yang_with_loaded_models()

def find_ref_paths(self, path, config):
"""
Finds the paths referencing any line under the given 'path' within the given 'config'.
Expand Down Expand Up @@ -401,7 +404,7 @@ def find_ref_paths(self, path, config):
return self._find_leafref_paths(path, config)

def _find_leafref_paths(self, path, config):
sy = self.config_wrapper.create_sonic_yang_with_loaded_models()
sy = self._create_sonic_yang_with_loaded_models()

tmp_config = copy.deepcopy(config)

Expand Down Expand Up @@ -547,6 +550,13 @@ def _get_xpath_tokens_from_leaf(self, model, token_index, path_tokens, config):
# /module-name:container/leaf-list[.='val']
# Source: Check examples in https://netopeer.liberouter.org/doc/libyang/master/html/howto_x_path.html
return [f"{token}[.='{value}']"]

# checking 'uses' statement
if not isinstance(config[token], list): # leaf-list under uses is not supported yet in sonic_yang
table = path_tokens[0]
uses_leaf_model = self._get_uses_leaf_model(model, table, token)
if uses_leaf_model:
return [token]

raise ValueError("Token not found")

Expand Down Expand Up @@ -712,6 +722,13 @@ def _get_path_tokens_from_leaf(self, model, token_index, xpath_tokens, config):
list_idx = list_config.index(leaf_list_value)
return [leaf_list_name, list_idx]

# checking 'uses' statement
if not isinstance(config[leaf_list_name], list): # leaf-list under uses is not supported yet in sonic_yang
table = xpath_tokens[1]
uses_leaf_model = self._get_uses_leaf_model(model, table, token)
if uses_leaf_model:
return [token]

raise Exception("no leaf")

def _extract_key_dict(self, list_token):
Expand Down Expand Up @@ -746,6 +763,38 @@ def _get_model(self, model, name):

return None

def _get_uses_leaf_model(self, model, table, token):
"""
Getting leaf model in uses model matching the given token.
"""
uses_s = model.get('uses')
if not uses_s:
return None

# a model can be a single dict or a list of dictionaries, unify to a list of dictionaries
if isinstance(uses_s, dict):
uses_s = [uses_s]

sy = self._create_sonic_yang_with_loaded_models()
# find yang module for current table
table_module = sy.confDbYangMap[table]['yangModule']
# uses Example: "@name": "bgpcmn:sonic-bgp-cmn"
for uses in uses_s:
# Assume ':' means reference to another module
if ':' in uses['@name']:
prefix = uses['@name'].split(':')[0].strip()
uses_module = sy._findYangModuleFromPrefix(prefix, table_module)
else:
uses_module = table_module
grouping = uses['@name'].split(':')[-1].strip()
leafs = sy.preProcessedYang['grouping'][uses_module][grouping]

leaf_model = self._get_model(leafs, token)
if leaf_model:
return leaf_model

return None

class TitledLogger(logger.Logger):
def __init__(self, syslog_identifier, title, verbose, print_all_to_console):
super().__init__(syslog_identifier)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"BGP_NEIGHBOR": {
"1.2.3.4": {
"admin_status": "up",
"asn": "65000",
"holdtime": "10",
"keepalive": "3",
"local_addr": "10.0.0.10",
"name": "ARISTA03T1",
"nhopself": "0",
"rrclient": "0"
},
"default|1.2.3.4": {
"local_asn": "65200",
"asn": "65100",
"name": "bgp peer 65100",
"ebgp_multihop_ttl": "3"
}
}
}
12 changes: 12 additions & 0 deletions tests/generic_config_updater/gu_common_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,12 @@ def check(path, xpath, config=None):
check(path="/PORTCHANNEL_INTERFACE/PortChannel0001|1.1.1.1~124",
xpath="/sonic-portchannel:sonic-portchannel/PORTCHANNEL_INTERFACE/PORTCHANNEL_INTERFACE_IPPREFIX_LIST[name='PortChannel0001'][ip_prefix='1.1.1.1/24']",
config=Files.CONFIG_DB_WITH_PORTCHANNEL_INTERFACE)
check(path="/BGP_NEIGHBOR/1.2.3.4/holdtime",
xpath="/sonic-bgp-neighbor:sonic-bgp-neighbor/BGP_NEIGHBOR/BGP_NEIGHBOR_TEMPLATE_LIST[neighbor='1.2.3.4']/holdtime",
config=Files.CONFIG_DB_WITH_BGP_NEIGHBOR)
check(path="/BGP_NEIGHBOR/default|1.2.3.4/asn",
xpath="/sonic-bgp-neighbor:sonic-bgp-neighbor/BGP_NEIGHBOR/BGP_NEIGHBOR_LIST[vrf_name='default'][neighbor='1.2.3.4']/asn",
config=Files.CONFIG_DB_WITH_BGP_NEIGHBOR)

def test_convert_xpath_to_path(self):
def check(xpath, path, config=None):
Expand Down Expand Up @@ -798,6 +804,12 @@ def check(xpath, path, config=None):
check(xpath="/sonic-portchannel:sonic-portchannel/PORTCHANNEL_INTERFACE/PORTCHANNEL_INTERFACE_IPPREFIX_LIST[name='PortChannel0001'][ip_prefix='1.1.1.1/24']",
path="/PORTCHANNEL_INTERFACE/PortChannel0001|1.1.1.1~124",
config=Files.CONFIG_DB_WITH_PORTCHANNEL_INTERFACE)
check(xpath="/sonic-bgp-neighbor:sonic-bgp-neighbor/BGP_NEIGHBOR/BGP_NEIGHBOR_TEMPLATE_LIST[neighbor='1.2.3.4']/holdtime",
path="/BGP_NEIGHBOR/1.2.3.4/holdtime",
config=Files.CONFIG_DB_WITH_BGP_NEIGHBOR)
check(xpath="/sonic-bgp-neighbor:sonic-bgp-neighbor/BGP_NEIGHBOR/BGP_NEIGHBOR_LIST[vrf_name='default'][neighbor='1.2.3.4']/asn",
path="/BGP_NEIGHBOR/default|1.2.3.4/asn",
config=Files.CONFIG_DB_WITH_BGP_NEIGHBOR)

def test_has_path(self):
def check(config, path, expected):
Expand Down

0 comments on commit 6a374e3

Please sign in to comment.