Skip to content

Commit

Permalink
[config/config_mgmt.py]: Address latest review comments.
Browse files Browse the repository at this point in the history
Signed-off-by: Praveen Chaudhary [email protected]
  • Loading branch information
Praveen Chaudhary committed Jun 26, 2020
1 parent eb870d5 commit 2a8d16c
Showing 1 changed file with 60 additions and 82 deletions.
142 changes: 60 additions & 82 deletions config/config_mgmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from time import sleep as tsleep
from imp import load_source
from jsondiff import diff
from sys import flags

# SONiC specific imports
import sonic_yang
Expand All @@ -28,7 +29,7 @@
YANG_DIR = "/usr/local/yang-models"
CONFIG_DB_JSON_FILE = '/etc/sonic/confib_db.json'
# TODO: Find a place for it on sonic switch.
DEFAULT_CONFIG_DB_JSON_FILE = '/etc/sonic/default_config_db.json'
DEFAULT_CONFIG_DB_JSON_FILE = '/etc/sonic/port_breakout_config_db.json'

class ConfigMgmt():
'''
Expand Down Expand Up @@ -75,7 +76,7 @@ def __init__(self, source="configDB", debug=False, allowTablesWithoutYang=True):
raise Exception('Config has tables without YANG models')

except Exception as e:
print(e)
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, msg=str(e))
raise(Exception('ConfigMgmt Class creation failed'))

return
Expand Down Expand Up @@ -128,11 +129,10 @@ def validateConfigData(self):
self.sysLog(msg='Data Validation Failed')
return False

print('Data Validation successful')
self.sysLog(msg='Data Validation successful')
self.sysLog(msg='Data Validation successful', doPrint=True)
return True

def sysLog(self, debug=syslog.LOG_INFO, msg=None):
def sysLog(self, logLevel=syslog.LOG_INFO, msg=None, doPrint=False):
'''
Log the msg in syslog file.
Expand All @@ -144,10 +144,12 @@ def sysLog(self, debug=syslog.LOG_INFO, msg=None):
void
'''
# log debug only if enabled
if self.DEBUG == False and debug == syslog.LOG_DEBUG:
if self.DEBUG == False and logLevel == syslog.LOG_DEBUG:
return
if flgas.interactive !=0 and doPrint == True:
print("{}".format(msg))
syslog.openlog(self.SYSLOG_IDENTIFIER)
syslog.syslog(debug, msg)
syslog.syslog(logLevel, msg)
syslog.closelog()

return
Expand All @@ -162,9 +164,9 @@ def readConfigDBJson(self, source=CONFIG_DB_JSON_FILE):
Returns:
(void)
'''
print('Reading data from {}'.format(source))
self.sysLog(msg='Reading data from {}'.format(source))
self.configdbJsonIn = readJsonFile(source)
#print(type(self.configdbJsonIn))
#self.sysLog(msg=type(self.configdbJsonIn))
if not self.configdbJsonIn:
raise(Exception("Can not load config from config DB json file"))
self.sysLog(msg='Reading Input {}'.format(self.configdbJsonIn))
Expand All @@ -184,7 +186,7 @@ def readConfigDB(self):
Returns:
(void)
'''
print('Reading data from Redis configDb')
self.sysLog(doPrint=True, msg='Reading data from Redis configDb')
# Read from config DB on sonic switch
db_kwargs = dict(); data = dict()
configdb = ConfigDBConnector(**db_kwargs)
Expand All @@ -206,7 +208,7 @@ def writeConfigDB(self, jDiff):
Returns:
void
'''
print('Writing in Config DB')
self.sysLog(doPrint=True, msg='Writing in Config DB')
db_kwargs = dict(); data = dict()
configdb = ConfigDBConnector(**db_kwargs)
configdb.connect(False)
Expand Down Expand Up @@ -244,7 +246,7 @@ def __init__(self, source="configDB", debug=False, allowTablesWithoutYang=True):
self.oidKey = 'ASIC_STATE:SAI_OBJECT_TYPE_PORT:oid:0x'

except Exception as e:
print(e)
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, msg=str(e))
raise(Exception('ConfigMgmtDPB Class creation failed'))

return
Expand All @@ -258,7 +260,7 @@ def _checkKeyinAsicDB(self, key, db):
Parameters:
db (SonicV2Connector): database.
key (str): key in config DB, with table Seperator if applicable.
key (str): key in ASIC DB, with table Seperator if applicable.
Returns:
(bool): True, if given key is present.
Expand All @@ -269,31 +271,11 @@ def _checkKeyinAsicDB(self, key, db):
if db.exists('ASIC_DB', key):
return True
except Exception as e:
print(e)
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, msg=str(e))
raise(e)

return False

def _testRedisCli(self, key):
'''
Additional test funtion for _verifyAsicDB(). This funtions will fetch
ports information from Asic DB, using redis-cli. This is done only when
debugging is on.
Parameters:
key (str): key in config DB, with table Seperator if applicable.
Returns:
void
'''
# To Debug
if self.DEBUG:
cmd = 'sudo redis-cli -n 1 hgetall "{}"'.format(key)
self.sysLog(syslog.LOG_DEBUG, "Running {}".format(cmd))
print(cmd)
system(cmd)
return

def _checkNoPortsInAsicDb(self, db, ports, portMap):
'''
Check ASIC DB for PORTs in port List
Expand All @@ -311,14 +293,11 @@ def _checkNoPortsInAsicDb(self, db, ports, portMap):
db.connect(db.ASIC_DB)
for port in ports:
key = self.oidKey + portMap[port]
if self._checkKeyinAsicDB(key, db) == False:
# Test again via redis-cli
self._testRedisCli(key)
else:
if self._checkKeyinAsicDB(key, db) == True:
return False

except Exception as e:
print(e)
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, msg=str(e))
return False

return True
Expand All @@ -337,11 +316,11 @@ def _verifyAsicDB(self, db, ports, portMap, timeout):
Returns:
(bool)
'''
print("Verify Port Deletion from Asic DB, Wait...")
self.sysLog(msg="Verify Port Deletion from Asic DB, Wait...")
self.sysLog(doPrint=True, msg="Verify Port Deletion from Asic DB, Wait...")
try:
for waitTime in range(timeout):
self.sysLog(msg='Check Asic DB: {} try'.format(waitTime+1))
self.sysLog(logLevel=syslog.LOG_DEBUG, msg='Check Asic DB: {} \
try'.format(waitTime+1))
# checkNoPortsInAsicDb will return True if all ports are not
# present in ASIC DB
if self._checkNoPortsInAsicDb(db, ports, portMap):
Expand All @@ -350,19 +329,18 @@ def _verifyAsicDB(self, db, ports, portMap, timeout):

# raise if timer expired
if waitTime + 1 == timeout:
print("!!! Critical Failure, Ports are not Deleted from \
ASIC DB, Bail Out !!!")
self.sysLog(syslog.LOG_CRIT, "!!! Critical Failure, Ports \
are not Deleted from ASIC DB, Bail Out !!!")
raise(Exception("Ports are present in ASIC DB after timeout"))
are not Deleted from ASIC DB, Bail Out !!!", doPrint=True)
raise(Exception("Ports are present in ASIC DB after {} secs".\
format(timeout)))

except Exception as e:
print(e)
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, msg=str(e))
raise e

return True

def breakOutPort(self, delPorts=list(), addPorts= list(), portJson=dict(), \
def breakOutPort(self, delPorts=list(), addPorts=list(), portJson=dict(), \
force=False, loadDefConfig=True):
'''
This is the main function for port breakout. Exposed to caller.
Expand Down Expand Up @@ -409,7 +387,7 @@ def breakOutPort(self, delPorts=list(), addPorts= list(), portJson=dict(), \
self.writeConfigDB(addConfigtoLoad)

except Exception as e:
print(e)
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, msg=str(e))
return None, False

return None, True
Expand All @@ -431,15 +409,14 @@ def _deletePorts(self, ports=list(), force=False):
try:
self.sysLog(msg="delPorts ports:{} force:{}".format(ports, force))

print('\nStart Port Deletion')
self.sysLog(doPrint=True, msg='Start Port Deletion')
deps = list()

# Get all dependecies for ports
for port in ports:
xPathPort = self.sy.findXpathPortLeaf(port)
print('Find dependecies for port {}'.format(port))
self.sysLog(msg='Find dependecies for port {}'.format(port))
# print("Generated Xpath:" + xPathPort)
self.sysLog(doPrint=True, msg='Find dependecies for port {}'.\
format(port))
dep = self.sy.find_data_dependencies(str(xPathPort))
if dep:
deps.extend(dep)
Expand All @@ -450,7 +427,7 @@ def _deletePorts(self, ports=list(), force=False):

# delets all deps, No topological sort is needed as of now, if deletion
# of deps fails, return immediately
elif deps and force:
elif deps:
for dep in deps:
self.sysLog(msg='Deleting {}'.format(dep))
self.sy.deleteNode(str(dep))
Expand All @@ -460,8 +437,7 @@ def _deletePorts(self, ports=list(), force=False):
# all deps are deleted now, delete all ports now
for port in ports:
xPathPort = self.sy.findXpathPort(port)
print("Deleting Port: " + port)
self.sysLog(msg='Deleting Port:{}'.format(port))
self.sysLog(doPrint=True, msg="Deleting Port: " + port)
self.sy.deleteNode(str(xPathPort))

# Let`s Validate the tree now
Expand All @@ -474,19 +450,19 @@ def _deletePorts(self, ports=list(), force=False):
configToLoad = self._updateDiffConfigDB()

except Exception as e:
print(e)
print("Port Deletion Failed")
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, msg=str(e))
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, \
msg="Port Deletion Failed")
return configToLoad, deps, False

return configToLoad, deps, True

def _addPorts(self, ports=list(), portJson=dict(), loadDefConfig=True):
def _addPorts(self, portJson=dict(), loadDefConfig=True):
'''
Add ports and default confug in data tree, validate and return resultant
config.
Parameters:
ports (list): list of ports
portJson (dict): Config DB json Part of all Ports, generated from
platform.json.
loadDefConfig: If loadDefConfig, add default config for ports as well.
Expand All @@ -495,13 +471,11 @@ def _addPorts(self, ports=list(), portJson=dict(), loadDefConfig=True):
(configToLoad, ret) (tuple)[dict, bool]
'''
configToLoad = None
ports = portJson['PORT'].keys()
try:
self.sysLog(msg='Start Port Addition')
self.sysLog(msg="addPorts ports:{} loadDefConfig:{}".\
format(ports, loadDefConfig))
self.sysLog(msg="addPorts Args portjson {}".format(portJson))

print('\nStart Port Addition')
self.sysLog(doPrint=True, msg='Start Port Addition')
self.sysLog(msg="addPorts Args portjson: {} loadDefConfig: {}".\
format(portJson, loadDefConfig))

if loadDefConfig:
defConfig = self._getDefaultConfig(ports)
Expand All @@ -520,8 +494,8 @@ def _addPorts(self, ports=list(), portJson=dict(), loadDefConfig=True):
# merge new config with data tree, this is json level merge.
# We do not allow new table merge while adding default config.
if loadDefConfig:
print("Merge Default Config for {}".format(ports))
self.sysLog(msg="Merge Default Config for {}".format(ports))
self.sysLog(doPrint=True, msg="Merge Default Config for {}".\
format(ports))
self._mergeConfigs(self.configdbJsonOut, defConfig, True)

# create a tree with merged config and validate, if validation is
Expand All @@ -534,8 +508,9 @@ def _addPorts(self, ports=list(), portJson=dict(), loadDefConfig=True):
configToLoad = self._updateDiffConfigDB()

except Exception as e:
print(e)
print("Port Addition Failed")
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, msg=str(e))
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, \
msg="Port Addition Failed")
return configToLoad, False

return configToLoad, True
Expand Down Expand Up @@ -582,8 +557,9 @@ def _mergeItems(it1, it2):
if uniqueKeys:
D1.update(D2)
except Exce as e:
print("Merge Config failed")
print(e)
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, \
msg="Merge Config failed")
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, msg=str(e))
raise e

return D1
Expand Down Expand Up @@ -629,7 +605,6 @@ def _searchKeysInConfig(self, In, Out, skeys):
if skey in In:
found = True
Out.append(skey)
#print("Added in list:" + port)

else:
# nothing for other keys
Expand All @@ -654,7 +629,8 @@ def configWithKeys(self, configIn=dict(), keys=list()):
if len(configIn) and len(keys):
self._searchKeysInConfig(configIn, configOut, skeys=keys)
except Exception as e:
print("configWithKeys Failed, Error: {}".format(str(e)))
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, \
msg="configWithKeys Failed, Error: {}".format(str(e)))
raise e

return configOut
Expand All @@ -672,13 +648,13 @@ def _getDefaultConfig(self, ports=list()):
'''
# function code
try:
print("Generating default config for {}".format(ports))
self.sysLog(doPrint=True, msg="Generating default config for {}".format(ports))
defConfigIn = readJsonFile(DEFAULT_CONFIG_DB_JSON_FILE)
#print(defConfigIn)
defConfigOut = dict()
self._searchKeysInConfig(defConfigIn, defConfigOut, skeys=ports)
except Exception as e:
print("getDefaultConfig Failed, Error: {}".format(str(e)))
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, \
msg="getDefaultConfig Failed, Error: {}".format(str(e)))
raise e

return defConfigOut
Expand All @@ -695,15 +671,16 @@ def _updateDiffConfigDB(self):
'''
try:
# Get the Diff
print('Generate Final Config to write in DB')
self.sysLog(msg='Generate Final Config to write in DB')
configDBdiff = self._diffJson()
# Process diff and create Config which can be updated in Config DB
configToLoad = self._createConfigToLoad(configDBdiff, \
self.configdbJsonIn, self.configdbJsonOut)

except Exception as e:
print("Config Diff Generation failed")
print(e)
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, \
msg="Config Diff Generation failed")
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, msg=str(e))
raise e

return configToLoad
Expand Down Expand Up @@ -819,8 +796,9 @@ def _recurCreateConfig(diff, inp, outp, config):
_recurCreateConfig(diff, inp, outp, configToLoad)

except Exception as e:
print("Create Config to load in DB, Failed")
print(e)
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, \
msg="Create Config to load in DB, Failed")
self.sysLog(doPrint=True, logLevel=syslog.LOG_ERR, msg=str(e))
raise e

return configToLoad
Expand Down

0 comments on commit 2a8d16c

Please sign in to comment.