diff --git a/src/sonic-yang-mgmt/sonic_yang.py b/src/sonic-yang-mgmt/sonic_yang.py index d867072fb57e..82de2a00ecd0 100644 --- a/src/sonic-yang-mgmt/sonic_yang.py +++ b/src/sonic-yang-mgmt/sonic_yang.py @@ -540,3 +540,122 @@ def find_data_dependencies (self, data_xpath): self.fail(e) return ref_list + + """ + get_module_prefix: get the prefix of a Yang module + input: name of the Yang module + output: prefix of the Yang module + """ + def get_module_prefix(self, module_name): + prefix = "" + try: + module = self.get_module(module_name) + except Exception as e: + self.fail(e) + return prefix + else: + return module.prefix() + + """ + str_to_type: map string to type of node + input: string + output: type + """ + def str_to_type (self, type_str): + mapped_type = { + "LY_TYPE_DER":ly.LY_TYPE_DER, + "LY_TYPE_BINARY":ly.LY_TYPE_BINARY, + "LY_TYPE_BITS":ly.LY_TYPE_BITS, + "LY_TYPE_BOOL":ly.LY_TYPE_BOOL, + "LY_TYPE_DEC64":ly.LY_TYPE_DEC64, + "LY_TYPE_EMPTY":ly.LY_TYPE_EMPTY, + "LY_TYPE_ENUM":ly.LY_TYPE_ENUM, + "LY_TYPE_IDENT":ly.LY_TYPE_IDENT, + "LY_TYPE_INST":ly.LY_TYPE_INST, + "LY_TYPE_LEAFREF":ly.LY_TYPE_LEAFREF, + "LY_TYPE_STRING":ly.LY_TYPE_STRING, + "LY_TYPE_UNION":ly.LY_TYPE_UNION, + "LY_TYPE_INT8":ly.LY_TYPE_INT8, + "LY_TYPE_UINT8":ly.LY_TYPE_UINT8, + "LY_TYPE_INT16":ly.LY_TYPE_INT16, + "LY_TYPE_UINT16":ly.LY_TYPE_UINT16, + "LY_TYPE_INT32":ly.LY_TYPE_INT32, + "LY_TYPE_UINT32":ly.LY_TYPE_UINT32, + "LY_TYPE_INT64":ly.LY_TYPE_INT64, + "LY_TYPE_UINT64":ly.LY_TYPE_UINT64, + "LY_TYPE_UNKNOWN":ly.LY_TYPE_UNKNOWN + } + + if type_str not in mapped_type: + return ly.LY_TYPE_UNKNOWN + + return mapped_type[type_str] + + def get_data_type (self, schema_xpath): + try: + schema_node = self.find_schema_node(schema_xpath) + except Exception as e: + print("get_data_type(): Failed to find schema node from xpath: {}".format(schema_xpath)) + self.fail(e) + return None + + if (schema_node is not None): + return schema_node.subtype().type().base() + + return ly.LY_TYPE_UNKNOWN + + """ + get_leafref_type: find the type of node that leafref references to + input: data_xpath - xpath of a data node + output: type of the node this leafref references to + """ + def get_leafref_type (self, data_xpath): + data_node = self.find_data_node(data_xpath) + if (data_node is not None): + subtype = data_node.subtype() + if (subtype is not None): + if data_node.schema().subtype().type().base() != ly.LY_TYPE_LEAFREF: + print("get_leafref_type() node type for data xpath: {} is not LEAFREF".format(data_xpath)) + return ly.LY_TYPE_UNKNOWN + else: + return subtype.value_type() + + return ly.LY_TYPE_UNKNOWN + + """ + get_leafref_path(): find the leafref path + input: schema_xpath - xpath of a schema node + output: path value of the leafref node + """ + def get_leafref_path (self, schema_xpath): + schema_node = self.find_schema_node(schema_xpath) + if (schema_node is not None): + subtype = schema_node.subtype() + if (subtype is not None): + if subtype.type().base() != ly.LY_TYPE_LEAFREF: + return None + else: + return subtype.type().info().lref().path() + + return None + + """ + get_leafref_type_schema: find the type of node that leafref references to + input: schema_xpath - xpath of a schema node + output: type of the node this leafref references to + """ + def get_leafref_type_schema (self, schema_xpath): + schema_node = self.find_schema_node(schema_xpath) + if (schema_node is not None): + subtype = schema_node.subtype() + if (subtype is not None): + if subtype.type().base() != ly.LY_TYPE_LEAFREF: + return None + else: + leafref_path = subtype.type().info().lref().path() + target = subtype.type().info().lref().target() + target_path = target.path() + target_type = self.get_data_type(target_path) + return target_type + + return None diff --git a/src/sonic-yang-mgmt/tests/libyang-python-tests/test_SonicYang.json b/src/sonic-yang-mgmt/tests/libyang-python-tests/test_SonicYang.json index fb13168a466c..b023ba57860e 100644 --- a/src/sonic-yang-mgmt/tests/libyang-python-tests/test_SonicYang.json +++ b/src/sonic-yang-mgmt/tests/libyang-python-tests/test_SonicYang.json @@ -99,5 +99,43 @@ "parent":"/sonic-vlan:sonic-vlan/VLAN_INTERFACE/VLAN_INTERFACE_LIST[vlanid='111'][ip-prefix='10.1.1.64/26']"}, {"xpath":"/sonic-port:sonic-port/PORT/PORT_LIST[port_name='Ethernet9']/speed", "parent":"/sonic-port:sonic-port/PORT/PORT_LIST[port_name='Ethernet9']"} - ] + ], + "prefix":[ + {"module_name":"sonic-head", "module_prefix":"sonic-head"}, + {"module_name":"sonic-port", "module_prefix":"port"}, + {"module_name":"sonic-acl", "module_prefix":"acl"}, + {"module_name":"sonic-interface", "module_prefix":"intf"}, + {"module_name":"sonic-portchannel", "module_prefix":"lag"}, + {"module_name":"sonic-vlan", "module_prefix":"vlan"} + ], + "data_type":[ + {"xpath":"/sonic-port:sonic-port/sonic-port:PORT/sonic-port:PORT_LIST/sonic-port:port_name", "data_type":"LY_TYPE_STRING"}, + {"xpath":"/sonic-vlan:sonic-vlan/sonic-vlan:VLAN_INTERFACE/sonic-vlan:VLAN_INTERFACE_LIST/sonic-vlan:vlanid", "data_type":"LY_TYPE_LEAFREF"} + ], + "leafref_type":[ + {"xpath":"/sonic-vlan:sonic-vlan/VLAN_INTERFACE/VLAN_INTERFACE_LIST[vlanid='111'][ip-prefix='2000:f500:45:6709::/64']/vlanid", "data_type":"LY_TYPE_UINT16"}, + {"xpath":"/sonic-interface:sonic-interface/INTERFACE/INTERFACE_LIST[interface='Ethernet8'][ip-prefix='2000:f500:40:a749::/126']/interface", "data_type":"LY_TYPE_STRING"}, + {"xpath":"/sonic-vlan:sonic-vlan/VLAN_MEMBER/VLAN_MEMBER_LIST[vlanid='111'][port='Ethernet0']/port", "data_type":"LY_TYPE_STRING"}, + {"xpath":"/sonic-vlan:sonic-vlan/VLAN_MEMBER/VLAN_MEMBER_LIST[vlanid='111'][port='Ethernet0']/vlanid", "data_type":"LY_TYPE_UINT16"} + ], + "leafref_type_schema":[ + {"xpath":"/sonic-vlan:sonic-vlan/sonic-vlan:VLAN_INTERFACE/sonic-vlan:VLAN_INTERFACE_LIST/sonic-vlan:vlanid", + "data_type":"LY_TYPE_UINT16"}, + {"xpath":"/sonic-interface:sonic-interface/sonic-interface:INTERFACE/sonic-interface:INTERFACE_LIST/sonic-interface:interface", + "data_type":"LY_TYPE_STRING"}, + {"xpath":"/sonic-vlan:sonic-vlan/sonic-vlan:VLAN_MEMBER/sonic-vlan:VLAN_MEMBER_LIST/sonic-vlan:port", + "data_type":"LY_TYPE_STRING"}, + {"xpath":"/sonic-vlan:sonic-vlan/sonic-vlan:VLAN_MEMBER/sonic-vlan:VLAN_MEMBER_LIST/sonic-vlan:vlanid", + "data_type":"LY_TYPE_UINT16"} + ], + "leafref_path":[ + {"xpath":"/sonic-vlan:sonic-vlan/sonic-vlan:VLAN_INTERFACE/sonic-vlan:VLAN_INTERFACE_LIST/sonic-vlan:vlanid", + "leafref_path":"../../../VLAN/VLAN_LIST/vlanid"}, + {"xpath":"/sonic-interface:sonic-interface/sonic-interface:INTERFACE/sonic-interface:INTERFACE_LIST/sonic-interface:interface", + "leafref_path":"/sonic-port:sonic-port/sonic-port:PORT/sonic-port:PORT_LIST/sonic-port:port_name"}, + {"xpath":"/sonic-vlan:sonic-vlan/sonic-vlan:VLAN_MEMBER/sonic-vlan:VLAN_MEMBER_LIST/sonic-vlan:port", + "leafref_path":"/sonic-port:sonic-port/sonic-port:PORT/sonic-port:PORT_LIST/sonic-port:port_name"}, + {"xpath":"/sonic-vlan:sonic-vlan/sonic-vlan:VLAN_MEMBER/sonic-vlan:VLAN_MEMBER_LIST/sonic-vlan:vlanid", + "leafref_path":"../../../VLAN/VLAN_LIST/vlanid"} + ] } diff --git a/src/sonic-yang-mgmt/tests/libyang-python-tests/test_sonic_yang.py b/src/sonic-yang-mgmt/tests/libyang-python-tests/test_sonic_yang.py index dc7fc268179a..7db42aad8153 100644 --- a/src/sonic-yang-mgmt/tests/libyang-python-tests/test_sonic_yang.py +++ b/src/sonic-yang-mgmt/tests/libyang-python-tests/test_sonic_yang.py @@ -214,6 +214,46 @@ def test_merge_data_tree(self, data, yang_s): yang_s.merge_data(data_merge_file, yang_dir) #yang_s.root.print_mem(ly.LYD_JSON, ly.LYP_FORMAT) + #test get module prefix + def test_get_module_prefix(self, yang_s, data): + for node in data['prefix']: + xpath = str(node['module_name']) + expected = node['module_prefix'] + prefix = yang_s.get_module_prefix(xpath) + assert expected == prefix + + #test get data type + def test_get_data_type(self, yang_s, data): + for node in data['data_type']: + xpath = str(node['xpath']) + expected = node['data_type'] + expected_type = yang_s.str_to_type(expected) + data_type = yang_s.get_data_type(xpath) + assert expected_type == data_type + + def test_get_leafref_type(self, yang_s, data): + for node in data['leafref_type']: + xpath = str(node['xpath']) + expected = node['data_type'] + expected_type = yang_s.str_to_type(expected) + data_type = yang_s.get_leafref_type(xpath) + assert expected_type == data_type + + def test_get_leafref_path(self, yang_s, data): + for node in data['leafref_path']: + xpath = str(node['xpath']) + expected_path = node['leafref_path'] + path = yang_s.get_leafref_path(xpath) + assert expected_path == path + + def test_get_leafref_type_schema(self, yang_s, data): + for node in data['leafref_type_schema']: + xpath = str(node['xpath']) + expected = node['data_type'] + expected_type = yang_s.str_to_type(expected) + data_type = yang_s.get_leafref_type_schema(xpath) + assert expected_type == data_type + def test_xlate_rev_xlate(self): # This Test is with Sonic YANG model, so create class from start # read the config