1515 'MAP_PFC_PRIORITY_TO_QUEUE_LIST' ,
1616 'PFC_PRIORITY_TO_PRIORITY_GROUP_MAP_LIST' ]
1717
18+ # Workaround for those fields who is defined as leaf-list in YANG model but have string value in config DB.
19+ # Dictinary structure key = (<table_name>, <field_name>), value = seperator
20+ LEAF_LIST_WITH_STRING_VALUE_DICT = {
21+ ('MIRROR_SESSION' , 'src_ip' ): ',' ,
22+ ('NTP' , 'src_intf' ): ';' ,
23+ ('BGP_ALLOWED_PREFIXES' , 'prefixes_v4' ): ',' ,
24+ ('BGP_ALLOWED_PREFIXES' , 'prefixes_v6' ): ',' ,
25+ ('BUFFER_PORT_EGRESS_PROFILE_LIST' , 'profile_list' ): ',' ,
26+ ('BUFFER_PORT_INGRESS_PROFILE_LIST' , 'profile_list' ): ',' ,
27+ ('PORT' , 'adv_speeds' ): ',' ,
28+ ('PORT' , 'adv_interface_types' ): ',' ,
29+ }
30+
1831"""
1932This is the Exception thrown out of all public function of this class.
2033"""
@@ -402,6 +415,11 @@ def _yangConvert(val):
402415 # if it is a leaf-list do it for each element
403416 if leafDict [key ]['__isleafList' ]:
404417 vValue = list ()
418+ if isinstance (value , str ) and (self .elementPath [0 ], self .elementPath [- 1 ]) in LEAF_LIST_WITH_STRING_VALUE_DICT :
419+ # For field defined as leaf-list but has string value in CONFIG DB, need do special handling here. For exampe:
420+ # port.adv_speeds in CONFIG DB has value "100,1000,10000", it shall be transferred to [100,1000,10000] as YANG value here to
421+ # make it align with its YANG definition.
422+ value = (x .strip () for x in value .split (LEAF_LIST_WITH_STRING_VALUE_DICT [(self .elementPath [0 ], self .elementPath [- 1 ])]))
405423 for v in value :
406424 vValue .append (_yangConvert (v ))
407425 else :
@@ -540,16 +558,21 @@ def _xlateList(self, model, yang, config, table, exceptionList):
540558 primaryKeys = list (config .keys ())
541559 for pkey in primaryKeys :
542560 try :
561+ self .elementPath .append (pkey )
543562 vKey = None
544563 self .sysLog (syslog .LOG_DEBUG , "xlateList Extract pkey:{}" .\
545564 format (pkey ))
546565 # Find and extracts key from each dict in config
547566 keyDict = self ._extractKey (pkey , listKeys )
548567 # fill rest of the values in keyDict
549568 for vKey in config [pkey ]:
569+ self .elementPath .append (vKey )
550570 self .sysLog (syslog .LOG_DEBUG , "xlateList vkey {}" .format (vKey ))
551- keyDict [vKey ] = self ._findYangTypedValue (vKey , \
552- config [pkey ][vKey ], leafDict )
571+ try :
572+ keyDict [vKey ] = self ._findYangTypedValue (vKey , \
573+ config [pkey ][vKey ], leafDict )
574+ finally :
575+ self .elementPath .pop ()
553576 yang .append (keyDict )
554577 # delete pkey from config, done to match one key with one list
555578 del config [pkey ]
@@ -561,6 +584,8 @@ def _xlateList(self, model, yang, config, table, exceptionList):
561584 exceptionList .append (str (e ))
562585 # with multilist, we continue matching other keys.
563586 continue
587+ finally :
588+ self .elementPath .pop ()
564589
565590 return
566591
@@ -591,8 +616,10 @@ def _xlateContainerInContainer(self, model, yang, configC, table):
591616 if not configC .get (ccontainer ['@name' ]):
592617 return
593618 self .sysLog (msg = "xlateProcessListOfContainer: {}" .format (ccontainer ['@name' ]))
619+ self .elementPath .append (ccontainer ['@name' ])
594620 self ._xlateContainer (ccontainer , yang [ccontainer ['@name' ]], \
595621 configC [ccontainer ['@name' ]], table )
622+ self .elementPath .pop ()
596623 # clean empty container
597624 if len (yang [ccontainer ['@name' ]]) == 0 :
598625 del yang [ccontainer ['@name' ]]
@@ -640,8 +667,10 @@ def _xlateContainer(self, model, yang, config, table):
640667 for vKey in vKeys :
641668 #vkey must be a leaf\leaf-list\choice in container
642669 if leafDict .get (vKey ):
670+ self .elementPath .append (vKey )
643671 self .sysLog (syslog .LOG_DEBUG , "xlateContainer vkey {}" .format (vKey ))
644672 yang [vKey ] = self ._findYangTypedValue (vKey , configC [vKey ], leafDict )
673+ self .elementPath .pop ()
645674 # delete entry from copy of config
646675 del configC [vKey ]
647676
@@ -671,8 +700,10 @@ def _xlateConfigDBtoYang(self, jIn, yangJ):
671700 yangJ [key ] = dict () if yangJ .get (key ) is None else yangJ [key ]
672701 yangJ [key ][subkey ] = dict ()
673702 self .sysLog (msg = "xlateConfigDBtoYang {}:{}" .format (key , subkey ))
703+ self .elementPath .append (table )
674704 self ._xlateContainer (cmap ['container' ], yangJ [key ][subkey ], \
675705 jIn [table ], table )
706+ self .elementPath = []
676707
677708 return
678709
@@ -729,9 +760,14 @@ def _revYangConvert(val):
729760
730761 # if it is a leaf-list do it for each element
731762 if leafDict [key ]['__isleafList' ]:
732- vValue = list ()
733- for v in value :
734- vValue .append (_revYangConvert (v ))
763+ if isinstance (value , list ) and (self .elementPath [0 ], self .elementPath [- 1 ]) in LEAF_LIST_WITH_STRING_VALUE_DICT :
764+ # For field defined as leaf-list but has string value in CONFIG DB, we need do special handling here:
765+ # e.g. port.adv_speeds is [10,100,1000] in YANG, need to convert it into a string for CONFIG DB: "10,100,1000"
766+ vValue = LEAF_LIST_WITH_STRING_VALUE_DICT [(self .elementPath [0 ], self .elementPath [- 1 ])].join ((_revYangConvert (x ) for x in value ))
767+ else :
768+ vValue = list ()
769+ for v in value :
770+ vValue .append (_revYangConvert (v ))
735771 elif leafDict [key ]['type' ]['@name' ] == 'boolean' :
736772 vValue = 'true' if value else 'false'
737773 else :
@@ -840,12 +876,16 @@ def _revXlateList(self, model, yang, config, table):
840876 # create key of config DB table
841877 pkey , pkeydict = self ._createKey (entry , listKeys )
842878 self .sysLog (syslog .LOG_DEBUG , "revXlateList pkey:{}" .format (pkey ))
879+ self .elementPath .append (pkey )
843880 config [pkey ]= dict ()
844881 # fill rest of the entries
845882 for key in entry :
846883 if key not in pkeydict :
884+ self .elementPath .append (key )
847885 config [pkey ][key ] = self ._revFindYangTypedValue (key , \
848886 entry [key ], leafDict )
887+ self .elementPath .pop ()
888+ self .elementPath .pop ()
849889
850890 return
851891
@@ -869,8 +909,10 @@ def _revXlateContainerInContainer(self, model, yang, config, table):
869909 if yang .get (modelContainer ['@name' ]):
870910 config [modelContainer ['@name' ]] = dict ()
871911 self .sysLog (msg = "revXlateContainerInContainer {}" .format (modelContainer ['@name' ]))
912+ self .elementPath .append (modelContainer ['@name' ])
872913 self ._revXlateContainer (modelContainer , yang [modelContainer ['@name' ]], \
873914 config [modelContainer ['@name' ]], table )
915+ self .elementPath .pop ()
874916 return
875917
876918 """
@@ -902,7 +944,9 @@ def _revXlateContainer(self, model, yang, config, table):
902944 #vkey must be a leaf\leaf-list\choice in container
903945 if leafDict .get (vKey ):
904946 self .sysLog (syslog .LOG_DEBUG , "revXlateContainer vkey {}" .format (vKey ))
947+ self .elementPath .append (vKey )
905948 config [vKey ] = self ._revFindYangTypedValue (vKey , yang [vKey ], leafDict )
949+ self .elementPath .pop ()
906950
907951 return
908952
@@ -930,8 +974,10 @@ def _revXlateYangtoConfigDB(self, yangJ, cDbJson):
930974 cDbJson [table ] = dict ()
931975 #print(key + "--" + subkey)
932976 self .sysLog (msg = "revXlateYangtoConfigDB {}" .format (table ))
977+ self .elementPath .append (table )
933978 self ._revXlateContainer (cmap ['container' ], yangJ [module_top ][container ], \
934979 cDbJson [table ], table )
980+ self .elementPath = []
935981
936982 return
937983
0 commit comments