Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add following APIs and test cases: #44

Merged
merged 2 commits into from
Feb 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions src/sonic-yang-mgmt/sonic_yang.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Ping

Actually, This prefix is not the one which is used in leafref. This is the prefix defined for each module, where as we need the prefix which is used in import statement. Import statement can use a name which is different then module prefix.
For example in sonic-acl, we can have port leafref.

 path "/port:sonic-port/port:PORT/port:PORT_LIST/port:port_name;"

Here port prefix comes from import statement:

	import sonic-port {
		prefix port;<<<<<<<
		revision-date 2019-07-01;
	}

Whereas, this API will return below prefix:

module sonic-port{
	namespace "http://github.com/Azure/sonic-port";
	prefix sonic-port;<<<<<<<<< [We can write any name here]


"""
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):
li-pingmao marked this conversation as resolved.
Show resolved Hide resolved
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()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gives value of leafref, right?


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
Original file line number Diff line number Diff line change
Expand Up @@ -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":[
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really useful, good.

{"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"}
]
}
40 changes: 40 additions & 0 deletions src/sonic-yang-mgmt/tests/libyang-python-tests/test_sonic_yang.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down