-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
SONiC Yang model support for LLDP #7191
Conversation
can you check the build issue? |
Can you please help to get this below issue fixed, this needs to be fixed outside of this PR. |
@@ -682,6 +682,24 @@ | |||
"nexthop_group_threshold_type": "percentage", | |||
"polling_interval": "0" | |||
} | |||
}, | |||
"LLDP": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added tests
which LLDP neighbor entry is deleted."; | ||
} | ||
|
||
leaf system_name { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ident issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
|
||
leaf supp_mgmt_address_tlv { | ||
type boolean; | ||
description |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we have config option to advertise v4/v6/both management capability.
can we check that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Abhishek, i checked the LLDPd implementation currently there is no support to control advertising mgmt capability TLV for v4 and v6 separately, once that support is available we can probably make the changes to YANG, let me know your thoughts.
|
||
container sonic-lldp { | ||
container LLDP { | ||
list LLDP_LIST { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
single value for key and only one entry ,...should be a container,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
"RX/TX mode for LLDP frames"; | ||
} | ||
|
||
//uses lldp_mode_config; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this from RFC 7950, can you plz point to the section. Thx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RFC7950 section -
7.13. The "uses" Statement
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason for commenting "//uses lldp_mode_config;"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The compilation fails with the usage of grouping (not related to this PR) hence its commented out, will uncomment once that issue is fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We dont see any outstanding issue on this, please mention the exact issue here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see below error when grouping is enabled -
Using /sonic/src/sonic-yang-models/.eggs/ijson-2.6.1-py3.7-linux-x86_64.egg
running egg_info
writing sonic_yang_models.egg-info/PKG-INFO
writing dependency_links to sonic_yang_models.egg-info/dependency_links.txt
writing top-level names to sonic_yang_models.egg-info/top_level.txt
reading manifest file 'sonic_yang_models.egg-info/SOURCES.txt'
writing manifest file 'sonic_yang_models.egg-info/SOURCES.txt'
running build_ext
============================= test session starts ==============================
platform linux -- Python 3.7.3, pytest-3.10.1, py-1.7.0, pluggy-0.8.0
rootdir: /sonic/src/sonic-yang-models, inifile:
plugins: cov-2.6.0
collected 3 items
tests/test_sonic_yang_models.py .F [ 66%]
tests/yang_model_tests/test_yang_model.py . [100%]
=================================== FAILURES ===================================
___________________________ test_generate_yang_tree ____________________________
def test_generate_yang_tree():
# Generate YANG Tree, see no error in it.
pyang_tree_cmd = "pyang -f tree ./yang-models/*.yang > ./yang-models/sonic_yang_tree"
if (system(pyang_tree_cmd)):
print("Failed: {}".format(pyang_tree_cmd))
exit(1)
E SystemExit: 1
tests/test_sonic_yang_models.py:30: SystemExit
----------------------------- Captured stdout call -----------------------------
Failed: pyang -f tree ./yang-models/*.yang > ./yang-models/sonic_yang_tree
----------------------------- Captured stderr call -----------------------------
./yang-models/sonic-acl.yang:8: error: module "ietf-inet-types" not found in search path
./yang-models/sonic-acl.yang:17: warning: imported module "sonic-extension" not used
./yang-models/sonic-breakout_cfg.yang:8: warning: imported module "sonic-extension" not used
./yang-models/sonic-device_metadata.yang:8: error: module "ietf-yang-types" not found in search path
./yang-models/sonic-device_neighbor.yang:12: warning: imported module "sonic-extension" not used
./yang-models/sonic-interface.yang:13: warning: imported module "sonic-extension" not used
./yang-models/sonic-lldp.yang:10: warning: imported module "sonic-extension" not used
./yang-models/sonic-loopback-interface.yang:13: warning: imported module "sonic-extension" not used
./yang-models/sonic-port.yang:13: warning: imported module "sonic-extension" not used
./yang-models/sonic-portchannel.yang:13: warning: imported module "sonic-extension" not used
./yang-models/sonic-vlan.yang:17: warning: imported module "sonic-extension" not used
./yang-models/sonic-vrf.yang:5: warning: imported module "sonic-extension" not used
====================== 1 failed, 2 passed in 1.11 seconds ======================
[ FAIL LOG END ] [ target/python-wheels/sonic_yang_models-1.0-py3-none-any.whl ]
make: *** [slave.mk:602: target/python-wheels/sonic_yang_models-1.0-py3-none-any.whl] Error 1
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality.
Makefile.work:287: recipe for target 'target/python-wheels/sonic_yang_mgmt-1.0-py3-none-any.whl' failed
make[1]: *** [target/python-wheels/sonic_yang_mgmt-1.0-py3-none-any.whl] Error 2
make[1]: Leaving directory '/projects/csg_sonic2/sk408012/SONiC/upstream/yang/sonic-buildimage'
Makefile:7: recipe for target 'target/python-wheels/sonic_yang_mgmt-1.0-py3-none-any.whl' failed
make: *** [target/python-wheels/sonic_yang_mgmt-1.0-py3-none-any.whl] Error 2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems you need to re-base, this doesn't have the latest fix in this PYANG test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Post rebase seeing below issue -
running build_ext
============================= test session starts ==============================
platform linux -- Python 3.7.3, pytest-3.10.1, py-1.7.0, pluggy-0.8.0
rootdir: /sonic/src/sonic-yang-mgmt, inifile:
plugins: cov-2.6.0
collected 26 items
tests/test_sonic_yang_mgmt.py . [ 3%]
tests/libyang-python-tests/test_sonic_yang.py ......................FF. [100%]
=================================== FAILURES ===================================
___________________ Test_SonicYang.test_validate_yang_models ___________________
self = <sonic_yang.SonicYang object at 0x7fc63bb549b0>
configdbJson = {'ACL_RULE': {'V4-ACL-TABLE|DEFAULT_DENY': {'IP_TYPE': 'IPv4ANY', 'PACKET_ACTION': 'DROP', 'PRIORITY': '0'}, 'V4-ACL-T...ter_low_threshold': '70', 'acl_counter_threshold_type': 'percentage', 'ipv6_neighbor_high_threshold': '67', ...}}, ...}
debug = False
def loadData(self, configdbJson, debug=False):
try:
# write Translated config in file if debug enabled
xlateFile = None
if debug:
xlateFile = "xlateConfig.json"
self.jIn = configdbJson
# reset xlate and tablesWithOutYang
self.xlateJson = dict()
self.tablesWithOutYang = dict()
# self.jIn will be cropped
self._cropConfigDB()
# xlated result will be in self.xlateJson
self._xlateConfigDB(xlateFile=xlateFile)
sonic_yang_ext.py:715:
self = <sonic_yang.SonicYang object at 0x7fc63bb549b0>, xlateFile = None
def _xlateConfigDB(self, xlateFile=None):
jIn= self.jIn
yangJ = self.xlateJson
# xlation is written in self.xlateJson
self._xlateConfigDBtoYang(jIn, yangJ)
sonic_yang_ext.py:432:
self = <sonic_yang.SonicYang object at 0x7fc63bb549b0>
jIn = {'ACL_RULE': {'V4-ACL-TABLE|DEFAULT_DENY': {'IP_TYPE': 'IPv4ANY', 'PACKET_ACTION': 'DROP', 'PRIORITY': '0'}, 'V4-ACL-T...ter_low_threshold': '70', 'acl_counter_threshold_type': 'percentage', 'ipv6_neighbor_high_threshold': '67', ...}}, ...}
yangJ = {'sonic-acl:sonic-acl': {'sonic-acl:ACL_RULE': {'ACL_RULE_LIST': [{'ACL_TABLE_NAME': 'V4-ACL-TABLE', 'IP_TYPE': 'IPv4A...TA': {'localhost': {'bgp_asn': '64850', 'buffer_model': 'dynamic', 'hostname': 'asw.dc', 'hwsku': 'Stone', ...}}}, ...}
def _xlateConfigDBtoYang(self, jIn, yangJ):
# find top level container for each table, and run the xlate_container.
for table in jIn.keys():
cmap = self.confDbYangMap[table]
# create top level containers
key = cmap['module']+":"+cmap['topLevelContainer']
subkey = cmap['topLevelContainer']+":"+cmap['container']['@name']
# Add new top level container for first table in this container
yangJ[key] = dict() if yangJ.get(key) is None else yangJ[key]
yangJ[key][subkey] = dict()
self.sysLog(msg="xlateConfigDBtoYang {}:{}".format(key, subkey))
self._xlateContainer(cmap['container'], yangJ[key][subkey], \
jIn[table], table)
sonic_yang_ext.py:420:
self = <sonic_yang.SonicYang object at 0x7fc63bb549b0>
model = OrderedDict([('@name', 'LLDP'), ('container', OrderedDict([('@name', 'GLOBAL'), ('leaf', [OrderedDict([('@name', 'hell...ities TLV in LLDP frames')])), ('__isleafList', False)])]), ('uses', OrderedDict([('@name', 'lldp_mode_config')]))]))])
yang = {'GLOBAL': {'hello_time': 12, 'multiplier': 5, 'supp_mgmt_address_tlv': 'true', 'supp_system_capabilities_tlv': 'false', ...}}
config = {'GLOBAL': {'enabled': 'true', 'hello_time': '12', 'mode': 'TRANSMIT', 'multiplier': '5', ...}}
table = 'LLDP'
def _xlateContainer(self, model, yang, config, table):
# To Handle multiple Lists, Make a copy of config, because we delete keys
# from config after each match. This is done to match one pkey with one list.
configC = config.copy()
exceptionList = list()
clist = model.get('list')
# If single list exists in container,
if clist and isinstance(clist, dict) and \
clist['@name'] == model['@name']+"_LIST" and bool(configC):
self._xlateListInContainer(clist, yang, configC, table, \
exceptionList)
# If multi-list exists in container,
elif clist and isinstance(clist, list) and bool(configC):
for modelList in clist:
self._xlateListInContainer(modelList, yang, configC, table, \
exceptionList)
# Handle container(s) in container
ccontainer = model.get('container')
# If single list exists in container,
if ccontainer and isinstance(ccontainer, dict) and bool(configC):
self._xlateContainerInContainer(ccontainer, yang, configC, table)
sonic_yang_ext.py:376:
self = <sonic_yang.SonicYang object at 0x7fc63bb549b0>
model = OrderedDict([('@name', 'GLOBAL'), ('leaf', [OrderedDict([('@name', 'hello_time'), ('type', OrderedDict([('@name', 'uin...bilities TLV in LLDP frames')])), ('__isleafList', False)])]), ('uses', OrderedDict([('@name', 'lldp_mode_config')]))])
yang = {'GLOBAL': {'hello_time': 12, 'multiplier': 5, 'supp_mgmt_address_tlv': 'true', 'supp_system_capabilities_tlv': 'false', ...}}
configC = {'GLOBAL': {'enabled': 'true', 'hello_time': '12', 'mode': 'TRANSMIT', 'multiplier': '5', ...}}
table = 'LLDP'
def _xlateContainerInContainer(self, model, yang, configC, table):
ccontainer = model
#print(ccontainer['@name'])
yang[ccontainer['@name']] = dict()
if not configC.get(ccontainer['@name']):
return
self.sysLog(msg="xlateProcessListOfContainer: {}".format(ccontainer['@name']))
self._xlateContainer(ccontainer, yang[ccontainer['@name']], \
configC[ccontainer['@name']], table)
sonic_yang_ext.py:340:
self = <sonic_yang.SonicYang object at 0x7fc63bb549b0>
model = OrderedDict([('@name', 'GLOBAL'), ('leaf', [OrderedDict([('@name', 'hello_time'), ('type', OrderedDict([('@name', 'uin...bilities TLV in LLDP frames')])), ('__isleafList', False)])]), ('uses', OrderedDict([('@name', 'lldp_mode_config')]))])
yang = {'hello_time': 12, 'multiplier': 5, 'supp_mgmt_address_tlv': 'true', 'supp_system_capabilities_tlv': 'false', ...}
config = {'enabled': 'true', 'hello_time': '12', 'mode': 'TRANSMIT', 'multiplier': '5', ...}
table = 'LLDP'
def _xlateContainer(self, model, yang, config, table):
# To Handle multiple Lists, Make a copy of config, because we delete keys
# from config after each match. This is done to match one pkey with one list.
configC = config.copy()
exceptionList = list()
clist = model.get('list')
# If single list exists in container,
if clist and isinstance(clist, dict) and \
clist['@name'] == model['@name']+"_LIST" and bool(configC):
self._xlateListInContainer(clist, yang, configC, table, \
exceptionList)
# If multi-list exists in container,
elif clist and isinstance(clist, list) and bool(configC):
for modelList in clist:
self._xlateListInContainer(modelList, yang, configC, table, \
exceptionList)
# Handle container(s) in container
ccontainer = model.get('container')
# If single list exists in container,
if ccontainer and isinstance(ccontainer, dict) and bool(configC):
self._xlateContainerInContainer(ccontainer, yang, configC, table)
# If multi-list exists in container,
elif ccontainer and isinstance(ccontainer, list) and bool(configC):
for modelContainer in ccontainer:
self._xlateContainerInContainer(modelContainer, yang, configC, table)
## Handle other leaves in container,
leafDict = self._createLeafDict(model)
vKeys = list(configC.keys())
for vKey in vKeys:
#vkey must be a leaf\leaf-list\choice in container
if leafDict.get(vKey):
self.sysLog(syslog.LOG_DEBUG, "xlateContainer vkey {}".format(vKey))
yang[vKey] = self._findYangTypedValue(vKey, configC[vKey], leafDict)
# delete entry from copy of config
del configC[vKey]
# All entries in copy of config must have been parsed.
if len(configC):
self.sysLog(msg="All Keys are not parsed in {}\n{}".format(table, \
configC.keys()), debug=syslog.LOG_ERR, doPrint=True)
self.sysLog(msg="exceptionList:{}".format(exceptionList), \
debug=syslog.LOG_ERR, doPrint=True)
raise(Exception("All Keys are not parsed in {}\n{}".format(table, \
configC.keys())))
E Exception: All Keys are not parsed in LLDP
E dict_keys(['mode', 'enabled'])
sonic_yang_ext.py:400: Exception
During handling of the above exception, another exception occurred:
self = <test_sonic_yang.Test_SonicYang object at 0x7fc63b710128>
sonic_yang_data = {'syc': <sonic_yang.SonicYang object at 0x7fc63bb549b0>, 'test_file': '../sonic-yang-models/tests/files/sample_config_db.json', 'yang_dir': '../sonic-yang-models/yang-models/'}
def test_validate_yang_models(self, sonic_yang_data):
'''
In this test, we validate yang models
a.) by converting the config as per RFC 7951 using YANG Models,
b.) by creating data tree using new YANG models and
c.) by validating config against YANG models.
Successful execution of these steps can be treated as
validation of new Yang models.
'''
test_file = sonic_yang_data['test_file']
syc = sonic_yang_data['syc']
# Currently only 2 YANG files are not directly related to config
# which are: sonic-extension.yang and sonic-types.yang. Hard coding
# it right now.
# If any more such helper yang files are added, we need to update here.
NON_CONFIG_YANG_FILES = 2
# read config
jIn = self.readIjsonInput(test_file, 'SAMPLE_CONFIG_DB_JSON')
jIn = json.loads(jIn)
numTables = len(jIn)
# load config and create Data tree
syc.loadData(jIn)
tests/libyang-python-tests/test_sonic_yang.py:305:
self = <sonic_yang.SonicYang object at 0x7fc63bb549b0>
configdbJson = {'ACL_RULE': {'V4-ACL-TABLE|DEFAULT_DENY': {'IP_TYPE': 'IPv4ANY', 'PACKET_ACTION': 'DROP', 'PRIORITY': '0'}, 'V4-ACL-T...ter_low_threshold': '70', 'acl_counter_threshold_type': 'percentage', 'ipv6_neighbor_high_threshold': '67', ...}}, ...}
debug = False
def loadData(self, configdbJson, debug=False):
try:
# write Translated config in file if debug enabled
xlateFile = None
if debug:
xlateFile = "xlateConfig.json"
self.jIn = configdbJson
# reset xlate and tablesWithOutYang
self.xlateJson = dict()
self.tablesWithOutYang = dict()
# self.jIn will be cropped
self._cropConfigDB()
# xlated result will be in self.xlateJson
self._xlateConfigDB(xlateFile=xlateFile)
#print("load data - {}".format(self.xlateJson))
self.sysLog(msg="Try to load Data in the tree")
self.root = self.ctx.parse_data_mem(dumps(self.xlateJson), \
ly.LYD_JSON, ly.LYD_OPT_CONFIG|ly.LYD_OPT_STRICT)
except Exception as e:
self.root = None
self.sysLog(msg="Data Loading Failed:{}".format(str(e)), \
debug=syslog.LOG_ERR, doPrint=True)
raise SonicYangException("Data Loading Failed\n{}".format(str(e)))
E sonic_yang_ext.SonicYangException: Data Loading Failed
E All Keys are not parsed in LLDP
E dict_keys(['mode', 'enabled'])
sonic_yang_ext.py:725: SonicYangException
----------------------------- Captured stdout call -----------------------------
Read JSON Section: SAMPLE_CONFIG_DB_JSON
sonic_yang(3):All Keys are not parsed in LLDP
dict_keys(['mode', 'enabled'])
sonic_yang(3):exceptionList:[]
sonic_yang(3):Data Loading Failed:All Keys are not parsed in LLDP
dict_keys(['mode', 'enabled'])
_____________________ Test_SonicYang.test_xlate_rev_xlate ______________________
self = <sonic_yang.SonicYang object at 0x7fc63bb549b0>
configdbJson = {'ACL_RULE': {'V4-ACL-TABLE|DEFAULT_DENY': {'IP_TYPE': 'IPv4ANY', 'PACKET_ACTION': 'DROP', 'PRIORITY': '0'}, 'V4-ACL-T...ter_low_threshold': '70', 'acl_counter_threshold_type': 'percentage', 'ipv6_neighbor_high_threshold': '67', ...}}, ...}
debug = False
def loadData(self, configdbJson, debug=False):
try:
# write Translated config in file if debug enabled
xlateFile = None
if debug:
xlateFile = "xlateConfig.json"
self.jIn = configdbJson
# reset xlate and tablesWithOutYang
self.xlateJson = dict()
self.tablesWithOutYang = dict()
# self.jIn will be cropped
self._cropConfigDB()
# xlated result will be in self.xlateJson
self._xlateConfigDB(xlateFile=xlateFile)
sonic_yang_ext.py:715:
self = <sonic_yang.SonicYang object at 0x7fc63bb549b0>, xlateFile = None
def _xlateConfigDB(self, xlateFile=None):
jIn= self.jIn
yangJ = self.xlateJson
# xlation is written in self.xlateJson
self._xlateConfigDBtoYang(jIn, yangJ)
sonic_yang_ext.py:432:
self = <sonic_yang.SonicYang object at 0x7fc63bb549b0>
jIn = {'ACL_RULE': {'V4-ACL-TABLE|DEFAULT_DENY': {'IP_TYPE': 'IPv4ANY', 'PACKET_ACTION': 'DROP', 'PRIORITY': '0'}, 'V4-ACL-T...ter_low_threshold': '70', 'acl_counter_threshold_type': 'percentage', 'ipv6_neighbor_high_threshold': '67', ...}}, ...}
yangJ = {'sonic-acl:sonic-acl': {'sonic-acl:ACL_RULE': {'ACL_RULE_LIST': [{'ACL_TABLE_NAME': 'V4-ACL-TABLE', 'IP_TYPE': 'IPv4A...TA': {'localhost': {'bgp_asn': '64850', 'buffer_model': 'dynamic', 'hostname': 'asw.dc', 'hwsku': 'Stone', ...}}}, ...}
def _xlateConfigDBtoYang(self, jIn, yangJ):
# find top level container for each table, and run the xlate_container.
for table in jIn.keys():
cmap = self.confDbYangMap[table]
# create top level containers
key = cmap['module']+":"+cmap['topLevelContainer']
subkey = cmap['topLevelContainer']+":"+cmap['container']['@name']
# Add new top level container for first table in this container
yangJ[key] = dict() if yangJ.get(key) is None else yangJ[key]
yangJ[key][subkey] = dict()
self.sysLog(msg="xlateConfigDBtoYang {}:{}".format(key, subkey))
self._xlateContainer(cmap['container'], yangJ[key][subkey], \
jIn[table], table)
sonic_yang_ext.py:420:
self = <sonic_yang.SonicYang object at 0x7fc63bb549b0>
model = OrderedDict([('@name', 'LLDP'), ('container', OrderedDict([('@name', 'GLOBAL'), ('leaf', [OrderedDict([('@name', 'hell...ities TLV in LLDP frames')])), ('__isleafList', False)])]), ('uses', OrderedDict([('@name', 'lldp_mode_config')]))]))])
yang = {'GLOBAL': {'hello_time': 12, 'multiplier': 5, 'supp_mgmt_address_tlv': 'true', 'supp_system_capabilities_tlv': 'false', ...}}
config = {'GLOBAL': {'enabled': 'true', 'hello_time': '12', 'mode': 'TRANSMIT', 'multiplier': '5', ...}}
table = 'LLDP'
def _xlateContainer(self, model, yang, config, table):
# To Handle multiple Lists, Make a copy of config, because we delete keys
# from config after each match. This is done to match one pkey with one list.
configC = config.copy()
exceptionList = list()
clist = model.get('list')
# If single list exists in container,
if clist and isinstance(clist, dict) and \
clist['@name'] == model['@name']+"_LIST" and bool(configC):
self._xlateListInContainer(clist, yang, configC, table, \
exceptionList)
# If multi-list exists in container,
elif clist and isinstance(clist, list) and bool(configC):
for modelList in clist:
self._xlateListInContainer(modelList, yang, configC, table, \
exceptionList)
# Handle container(s) in container
ccontainer = model.get('container')
# If single list exists in container,
if ccontainer and isinstance(ccontainer, dict) and bool(configC):
self._xlateContainerInContainer(ccontainer, yang, configC, table)
sonic_yang_ext.py:376:
self = <sonic_yang.SonicYang object at 0x7fc63bb549b0>
model = OrderedDict([('@name', 'GLOBAL'), ('leaf', [OrderedDict([('@name', 'hello_time'), ('type', OrderedDict([('@name', 'uin...bilities TLV in LLDP frames')])), ('__isleafList', False)])]), ('uses', OrderedDict([('@name', 'lldp_mode_config')]))])
yang = {'GLOBAL': {'hello_time': 12, 'multiplier': 5, 'supp_mgmt_address_tlv': 'true', 'supp_system_capabilities_tlv': 'false', ...}}
configC = {'GLOBAL': {'enabled': 'true', 'hello_time': '12', 'mode': 'TRANSMIT', 'multiplier': '5', ...}}
table = 'LLDP'
def _xlateContainerInContainer(self, model, yang, configC, table):
ccontainer = model
#print(ccontainer['@name'])
yang[ccontainer['@name']] = dict()
if not configC.get(ccontainer['@name']):
return
self.sysLog(msg="xlateProcessListOfContainer: {}".format(ccontainer['@name']))
self._xlateContainer(ccontainer, yang[ccontainer['@name']], \
configC[ccontainer['@name']], table)
sonic_yang_ext.py:340:
self = <sonic_yang.SonicYang object at 0x7fc63bb549b0>
model = OrderedDict([('@name', 'GLOBAL'), ('leaf', [OrderedDict([('@name', 'hello_time'), ('type', OrderedDict([('@name', 'uin...bilities TLV in LLDP frames')])), ('__isleafList', False)])]), ('uses', OrderedDict([('@name', 'lldp_mode_config')]))])
yang = {'hello_time': 12, 'multiplier': 5, 'supp_mgmt_address_tlv': 'true', 'supp_system_capabilities_tlv': 'false', ...}
config = {'enabled': 'true', 'hello_time': '12', 'mode': 'TRANSMIT', 'multiplier': '5', ...}
table = 'LLDP'
def _xlateContainer(self, model, yang, config, table):
# To Handle multiple Lists, Make a copy of config, because we delete keys
# from config after each match. This is done to match one pkey with one list.
configC = config.copy()
exceptionList = list()
clist = model.get('list')
# If single list exists in container,
if clist and isinstance(clist, dict) and \
clist['@name'] == model['@name']+"_LIST" and bool(configC):
self._xlateListInContainer(clist, yang, configC, table, \
exceptionList)
# If multi-list exists in container,
elif clist and isinstance(clist, list) and bool(configC):
for modelList in clist:
self._xlateListInContainer(modelList, yang, configC, table, \
exceptionList)
# Handle container(s) in container
ccontainer = model.get('container')
# If single list exists in container,
if ccontainer and isinstance(ccontainer, dict) and bool(configC):
self._xlateContainerInContainer(ccontainer, yang, configC, table)
# If multi-list exists in container,
elif ccontainer and isinstance(ccontainer, list) and bool(configC):
for modelContainer in ccontainer:
self._xlateContainerInContainer(modelContainer, yang, configC, table)
## Handle other leaves in container,
leafDict = self._createLeafDict(model)
vKeys = list(configC.keys())
for vKey in vKeys:
#vkey must be a leaf\leaf-list\choice in container
if leafDict.get(vKey):
self.sysLog(syslog.LOG_DEBUG, "xlateContainer vkey {}".format(vKey))
yang[vKey] = self._findYangTypedValue(vKey, configC[vKey], leafDict)
# delete entry from copy of config
del configC[vKey]
# All entries in copy of config must have been parsed.
if len(configC):
self.sysLog(msg="All Keys are not parsed in {}\n{}".format(table, \
configC.keys()), debug=syslog.LOG_ERR, doPrint=True)
self.sysLog(msg="exceptionList:{}".format(exceptionList), \
debug=syslog.LOG_ERR, doPrint=True)
raise(Exception("All Keys are not parsed in {}\n{}".format(table, \
configC.keys())))
E Exception: All Keys are not parsed in LLDP
E dict_keys(['mode', 'enabled'])
sonic_yang_ext.py:400: Exception
During handling of the above exception, another exception occurred:
self = <test_sonic_yang.Test_SonicYang object at 0x7fc63b694da0>
sonic_yang_data = {'syc': <sonic_yang.SonicYang object at 0x7fc63bb549b0>, 'test_file': '../sonic-yang-models/tests/files/sample_config_db.json', 'yang_dir': '../sonic-yang-models/yang-models/'}
def test_xlate_rev_xlate(self, sonic_yang_data):
# In this test, xlation and revXlation is tested with latest Sonic
# YANG model.
test_file = sonic_yang_data['test_file']
syc = sonic_yang_data['syc']
jIn = self.readIjsonInput(test_file, 'SAMPLE_CONFIG_DB_JSON')
jIn = json.loads(jIn)
numTables = len(jIn)
syc.loadData(jIn)
tests/libyang-python-tests/test_sonic_yang.py:332:
self = <sonic_yang.SonicYang object at 0x7fc63bb549b0>
configdbJson = {'ACL_RULE': {'V4-ACL-TABLE|DEFAULT_DENY': {'IP_TYPE': 'IPv4ANY', 'PACKET_ACTION': 'DROP', 'PRIORITY': '0'}, 'V4-ACL-T...ter_low_threshold': '70', 'acl_counter_threshold_type': 'percentage', 'ipv6_neighbor_high_threshold': '67', ...}}, ...}
debug = False
def loadData(self, configdbJson, debug=False):
try:
# write Translated config in file if debug enabled
xlateFile = None
if debug:
xlateFile = "xlateConfig.json"
self.jIn = configdbJson
# reset xlate and tablesWithOutYang
self.xlateJson = dict()
self.tablesWithOutYang = dict()
# self.jIn will be cropped
self._cropConfigDB()
# xlated result will be in self.xlateJson
self._xlateConfigDB(xlateFile=xlateFile)
#print("load data - {}".format(self.xlateJson))
self.sysLog(msg="Try to load Data in the tree")
self.root = self.ctx.parse_data_mem(dumps(self.xlateJson), \
ly.LYD_JSON, ly.LYD_OPT_CONFIG|ly.LYD_OPT_STRICT)
except Exception as e:
self.root = None
self.sysLog(msg="Data Loading Failed:{}".format(str(e)), \
debug=syslog.LOG_ERR, doPrint=True)
raise SonicYangException("Data Loading Failed\n{}".format(str(e)))
E sonic_yang_ext.SonicYangException: Data Loading Failed
E All Keys are not parsed in LLDP
E dict_keys(['mode', 'enabled'])
sonic_yang_ext.py:725: SonicYangException
----------------------------- Captured stdout call -----------------------------
Read JSON Section: SAMPLE_CONFIG_DB_JSON
sonic_yang(3):All Keys are not parsed in LLDP
dict_keys(['mode', 'enabled'])
sonic_yang(3):exceptionList:[]
sonic_yang(3):Data Loading Failed:All Keys are not parsed in LLDP
dict_keys(['mode', 'enabled'])
===================== 2 failed, 24 passed in 0.50 seconds ======================
[ FAIL LOG END ] [ target/python-wheels/sonic_yang_mgmt-1.0-py3-none-any.whl ]
make: *** [slave.mk:602: target/python-wheels/sonic_yang_mgmt-1.0-py3-none-any.whl] Error 1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@praveen-li @venkatmahalingam - can you please comment on the above failure?
Also there was another issue (see below) which is mentioned in PR description, this was also discussed in yang subgroup, is this addressed or still pending -
Compile sonic_yang_mgmt-1.0-py3-none-any.whl
tests/libyang-python-tests/test_sonic_yang.py - test_xlate_rev_xlate fails as the output generated in revXlateConfig.json has one of the field values "True" instead of "true" which causes failure in comparison.
yang subgroup reference mail dated Apr 9, 2021, subject - sonic_yang_mgmt-1.0-py3-none-any.whl build error when use leaf with type boolean in sample_config_db.json
8468a31
to
47b5494
Compare
description | ||
"RX/TX mode for LLDP frames"; | ||
} | ||
//uses lldp_mode_config; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use the grouping "lldp_mode_config", any reason for this comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The compilation fails with the usage of grouping (not related to this PR) hence its commented out, will uncomment once that issue is fixed. This was discussed in the PR review and the relevant information was also shared to yang sub-group over email.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please mention the exact issue.
|
||
leaf id { | ||
type enumeration { | ||
enum GLOBAL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make this list with one entry as container "GLOBAL" for review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
@sandeep-kulambi please provide input to Venkats review comments by 6/10. |
@anshuv-mfst |
Will be tracked in #8120 |
What I did
Created SONiC Yang model for LLDP
How I did it
Added LLDP and LLDP_PORT tables for global and port level configurations
How to verify it
Compile sonic_yang_mgmt-1.0-py3-none-any.whl
tests/libyang-python-tests/test_sonic_yang.py - test_xlate_rev_xlate fails as the output generated in revXlateConfig.json has one of the field values "True" instead of "true" which causes failure in comparison.