diff --git a/config/config_mgmt.py b/config/config_mgmt.py index d6e25afc1192..772ddd8ee8b0 100644 --- a/config/config_mgmt.py +++ b/config/config_mgmt.py @@ -126,7 +126,8 @@ def validateConfigData(self): try: self.sy.validate_data_tree() except Exception as e: - self.sysLog(msg='Data Validation Failed') + self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, + msg='Data Validation Failed') return False self.sysLog(msg='Data Validation successful', doPrint=True) @@ -146,7 +147,8 @@ def sysLog(self, logLevel=syslog.LOG_INFO, msg=None, doPrint=False): # log debug only if enabled if self.DEBUG == False and logLevel == syslog.LOG_DEBUG: return - if flags.interactive !=0 and doPrint == True: + # always print < Info level msg with doPrint flag + if doPrint == True and (logLevel < syslog.LOG_INFO or flags.interactive != 0): print("{}".format(msg)) syslog.openlog(self.SYSLOG_IDENTIFIER) syslog.syslog(logLevel, msg) @@ -712,18 +714,31 @@ def _deleteHandler(diff, inp, outp, config): ''' if isinstance(inp, dict): # Example Case: diff = PORT': {delete: {u'Ethernet1': {...}}}} + self.sysLog(logLevel=syslog.LOG_DEBUG, \ + msg="Delete Dict diff:{}".format(diff)) for key in diff: # make sure keys from diff are present in inp but not in outp if key in inp and key not in outp: - # assign key to None(null), redis will delete entire key - config[key] = None + if type(inp[key]) == list: + self.sysLog(logLevel=syslog.LOG_DEBUG, \ + msg="Delete List key:{}".format(key)) + # assign current lists as empty. + config[key] = [] + else: + self.sysLog(logLevel=syslog.LOG_DEBUG, \ + msg="Delete Dict key:{}".format(key)) + # assign key to None(null), redis will delete entire key + config[key] = None else: # should not happen raise Exception('Invalid deletion of {} in diff'.format(key)) elif isinstance(inp, list): - # Example case: {u'VLAN': {u'Vlan100': {'members': {delete: [(95, 'Ethernet1')]}} - # just take list from outputs + # Example case: diff: [(3, 'Ethernet10'), (2, 'Ethernet8')] + # inp:['Ethernet0', 'Ethernet4', 'Ethernet8', 'Ethernet10'] + # outp:['Ethernet0', 'Ethernet4'] + self.sysLog(logLevel=syslog.LOG_DEBUG, \ + msg="Delete List diff: {} inp:{} outp:{}".format(diff, inp, outp)) config.extend(outp) return @@ -733,9 +748,13 @@ def _insertHandler(diff, inp, outp, config): ''' if isinstance(outp, dict): # Example Case: diff = PORT': {insert: {u'Ethernet1': {...}}}} + self.sysLog(logLevel=syslog.LOG_DEBUG, \ + msg="Insert Dict diff:{}".format(diff)) for key in diff: # make sure keys are only in outp if key not in inp and key in outp: + self.sysLog(logLevel=syslog.LOG_DEBUG, \ + msg="Insert Dict key:{}".format(key)) # assign key in config same as outp config[key] = outp[key] else: @@ -743,9 +762,17 @@ def _insertHandler(diff, inp, outp, config): raise Exception('Invalid insertion of {} in diff'.format(key)) elif isinstance(outp, list): - # just take list from output - # Example case: {u'VLAN': {u'Vlan100': {'members': {insert: [(95, 'Ethernet1')]}} + # Example diff:[(2, 'Ethernet8'), (3, 'Ethernet10')] + # in:['Ethernet0', 'Ethernet4'] + # out:['Ethernet0', 'Ethernet4', 'Ethernet8', 'Ethernet10'] + self.sysLog(logLevel=syslog.LOG_DEBUG, \ + msg="Insert list diff:{} inp:{} outp:{}".format(diff, inp, outp)) config.extend(outp) + # configDb stores []->[""], i.e. empty list as list of empty + # string. While adding default config for newly created ports, + # inp can be [""], in that case remove it from delta config. + if inp == ['']: + config.remove(''); return def _recurCreateConfig(diff, inp, outp, config): diff --git a/tests/config_mgmt_test.py b/tests/config_mgmt_test.py index 24a2ad07accc..b1c794faf114 100644 --- a/tests/config_mgmt_test.py +++ b/tests/config_mgmt_test.py @@ -10,6 +10,7 @@ from unittest import TestCase from mock import MagicMock, call from json import dump +from copy import deepcopy class TestConfigMgmt(TestCase): ''' @@ -22,14 +23,14 @@ def setUp(self): return def test_config_validation(self): - curConfig = dict(configDbJson) + curConfig = deepcopy(configDbJson) self.writeJson(curConfig, config_mgmt.CONFIG_DB_JSON_FILE) cm = config_mgmt.ConfigMgmt(source=config_mgmt.CONFIG_DB_JSON_FILE) assert cm.validateConfigData() == True return def test_table_without_yang(self): - curConfig = dict(configDbJson) + curConfig = deepcopy(configDbJson) unknown = {"unknown_table": {"ukey": "uvalue"}} self.updateConfig(curConfig, unknown) self.writeJson(curConfig, config_mgmt.CONFIG_DB_JSON_FILE) @@ -38,7 +39,7 @@ def test_table_without_yang(self): return def test_search_keys(self): - curConfig = dict(configDbJson) + curConfig = deepcopy(configDbJson) self.writeJson(curConfig, config_mgmt.CONFIG_DB_JSON_FILE) cmdpb = config_mgmt.ConfigMgmtDPB(source=config_mgmt.CONFIG_DB_JSON_FILE) out = cmdpb.configWithKeys(portBreakOutConfigDbJson, \ @@ -61,7 +62,7 @@ def test_break_out(self): self.writeJson(portBreakOutConfigDbJson, \ config_mgmt.DEFAULT_CONFIG_DB_JSON_FILE) # prepare config dj json to start with - curConfig = dict(configDbJson) + curConfig = deepcopy(configDbJson) #Ethernet8: start from 4x25G-->2x50G with -f -l self.dpb_port8_4x25G_2x50G_f_l(curConfig) #Ethernet8: move from 2x50G-->1x100G without force, list deps @@ -182,6 +183,13 @@ def updateConfig(self, conf, uconf): else: if isinstance(conf[it], list) and isinstance(uconf[it], list): conf[it] = list(uconf[it]) + ''' + configDb stores []->[""], i.e. empty list as + list of empty string. So we need to replicate + same behaviour here. + ''' + if len(conf[it]) == 0: + conf[it] = [""] elif isinstance(conf[it], dict) and isinstance(uconf[it], dict): self.updateConfig(conf[it], uconf[it]) else: @@ -442,7 +450,7 @@ def dpb_port8_4x25G_2x50G_f_l(self, curConfig): 'ports': ['Ethernet0', 'Ethernet4'] }, 'NO-NSW-PACL-TEST': { - 'ports': None + 'ports': [] } }, 'INTERFACE': None,