sonic-buildimage/platform/pddf/i2c/utils/pddf_util.py
FuzailBrcm fa361f164c
[pddf]: Update PDDF utils and common platform APIs for Debian Bullseye (#9585)
- Why I did it
PDDF utils were python2 compliant and they needed to be migrated to Python3 (as per Bullseye)
PDDF common platform APIs file name changed as the name was already in use
Indentation issues
Dead/redundant code needed to be removed

- How I did it
Made files Python3 compliant
Indentation corrected
Redundant code removed

- How to verify it
AS7326 Accton platform uses PDDF. PDDF utils were run on this platform to verify.
2022-01-02 22:27:01 -08:00

605 lines
23 KiB
Python
Executable File

#!/usr/bin/env python
"""
Usage: %(scriptName)s [options] command object
options:
-h | --help : this help message
-d | --debug : run with debug mode
-f | --force : ignore error during installation or clean
command:
install : install drivers and generate related sysfs nodes
clean : uninstall drivers and remove related sysfs nodes
switch-pddf : switch to pddf mode, installing pddf drivers and generating sysfs nodes
switch-nonpddf : switch to per platform, non-pddf mode
"""
import logging
import getopt
import os
import shutil
import subprocess
import sys
import pddfparse
PLATFORM_ROOT_PATH = '/usr/share/sonic/device'
SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen'
HWSKU_KEY = 'DEVICE_METADATA.localhost.hwsku'
PLATFORM_KEY = 'DEVICE_METADATA.localhost.platform'
PROJECT_NAME = 'PDDF'
version = '1.1'
verbose = False
DEBUG = False
args = []
ALL_DEVICE = {}
FORCE = 0
kos = []
perm_kos = []
devs = []
# Instantiate the class pddf_obj
try:
pddf_obj = pddfparse.PddfParse()
except Exception as e:
print("%s" % str(e))
sys.exit()
if DEBUG == True:
print(sys.argv[0])
print('ARGV :', sys.argv[1:])
def main():
global DEBUG
global args
global FORCE
global kos
if len(sys.argv)<2:
show_help()
options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help',
'debug',
'force',
])
if DEBUG == True:
print(options)
print(args)
print(len(sys.argv))
# generate the KOS list from pddf device JSON file
if 'std_perm_kos' in pddf_obj.data['PLATFORM'].keys():
kos.extend(pddf_obj.data['PLATFORM']['std_perm_kos'])
perm_kos.extend(pddf_obj.data['PLATFORM']['std_perm_kos'])
kos.extend(pddf_obj.data['PLATFORM']['std_kos'])
kos.extend(pddf_obj.data['PLATFORM']['pddf_kos'])
kos = ['modprobe '+i for i in kos]
if 'custom_kos' in pddf_obj.data['PLATFORM']:
custom_kos = pddf_obj.data['PLATFORM']['custom_kos']
kos.extend(['modprobe -f '+i for i in custom_kos])
for opt, arg in options:
if opt in ('-h', '--help'):
show_help()
elif opt in ('-d', '--debug'):
DEBUG = True
logging.basicConfig(level=logging.INFO)
elif opt in ('-f', '--force'):
FORCE = 1
else:
logging.info('no option')
for arg in args:
if arg == 'install':
do_install()
elif arg == 'clean':
do_uninstall()
elif arg == 'switch-pddf':
do_switch_pddf()
elif arg == 'switch-nonpddf':
do_switch_nonpddf()
else:
show_help()
return 0
def show_help():
print(__doc__ % {'scriptName' : sys.argv[0].split("/")[-1]})
sys.exit(0)
def my_log(txt):
if DEBUG == True:
print("[PDDF]"+txt)
return
def log_os_system(cmd, show):
logging.info('Run :'+cmd)
status, output = subprocess.getstatusoutput(cmd)
my_log (cmd +"with result:" + str(status))
my_log (" output:"+output)
if status:
logging.info('Failed :'+cmd)
if show:
print('Failed :'+cmd)
return status, output
def driver_check():
ret, lsmod = log_os_system("lsmod| grep pddf", 0)
if ret:
return False
logging.info('mods:'+lsmod)
if len(lsmod) ==0:
return False
return True
def get_path_to_device():
# Get platform and hwsku
(platform, hwsku) = pddf_obj.get_platform_and_hwsku()
# Load platform module from source
platform_path = "/".join([PLATFORM_ROOT_PATH, platform])
return platform_path
def get_path_to_pddf_plugin():
pddf_path = "/".join([PLATFORM_ROOT_PATH, "pddf/plugins"])
return pddf_path
def config_pddf_utils():
device_path = get_path_to_device()
pddf_path = get_path_to_pddf_plugin()
# ##########################################################################
SONIC_PLATFORM_BSP_WHL_PKG = "/".join([device_path, 'sonic_platform-1.0-py3-none-any.whl'])
SONIC_PLATFORM_PDDF_WHL_PKG = "/".join([device_path, 'pddf', 'sonic_platform-1.0-py3-none-any.whl'])
SONIC_PLATFORM_BSP_WHL_PKG_BK = "/".join([device_path, 'sonic_platform-1.0-py3-none-any.whl.orig'])
status, output = log_os_system("pip3 show sonic-platform > /dev/null 2>&1", 1)
if status:
if os.path.exists(SONIC_PLATFORM_PDDF_WHL_PKG):
# Platform API 2.0 is supported
if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG):
# bsp whl pkg is present but not installed on host <special case>
if not os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_BK):
log_os_system('mv '+SONIC_PLATFORM_BSP_WHL_PKG+' '+SONIC_PLATFORM_BSP_WHL_PKG_BK, 1)
# PDDF whl package exist ... this must be the whl package created from
# PDDF 2.0 ref API classes and some changes on top of it ... install it
log_os_system('sync', 1)
shutil.copy(SONIC_PLATFORM_PDDF_WHL_PKG, SONIC_PLATFORM_BSP_WHL_PKG)
log_os_system('sync', 1)
print("Attemting to install the PDDF sonic_platform wheel package ...")
if os.path.getsize(SONIC_PLATFORM_BSP_WHL_PKG) != 0:
status, output = log_os_system("pip3 install "+ SONIC_PLATFORM_BSP_WHL_PKG, 1)
if status:
print("Error: Failed to install {}".format(SONIC_PLATFORM_BSP_WHL_PKG))
return status
else:
print("Successfully installed {} package".format(SONIC_PLATFORM_BSP_WHL_PKG))
else:
print("Error: Failed to copy {} properly. Exiting ...".format(SONIC_PLATFORM_PDDF_WHL_PKG))
return -1
else:
# PDDF with platform APIs 1.5 must be supported
device_plugin_path = "/".join([device_path, "plugins"])
backup_path = "/".join([device_plugin_path, "orig"])
print("Loading PDDF generic plugins (1.0)")
if os.path.exists(backup_path) is False:
os.mkdir(backup_path)
log_os_system("mv "+device_plugin_path+"/*.*"+" "+backup_path, 0)
for item in os.listdir(pddf_path):
shutil.copy(pddf_path+"/"+item, device_plugin_path+"/"+item)
shutil.copy('/usr/local/bin/pddfparse.py', device_plugin_path+"/pddfparse.py")
else:
# sonic_platform whl pkg is installed 2 possibilities, 1) bsp 2.0 classes
# are installed, 2) system rebooted and either pddf/bsp 2.0 classes are already installed
if os.path.exists(SONIC_PLATFORM_PDDF_WHL_PKG):
if not os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_BK):
# bsp 2.0 classes are installed. Take a backup and copy pddf 2.0 whl pkg
log_os_system('mv '+SONIC_PLATFORM_BSP_WHL_PKG+' '+SONIC_PLATFORM_BSP_WHL_PKG_BK, 1)
shutil.copy(SONIC_PLATFORM_PDDF_WHL_PKG, SONIC_PLATFORM_BSP_WHL_PKG)
# uninstall the existing bsp whl pkg
status, output = log_os_system("pip3 uninstall sonic-platform -y &> /dev/null", 1)
if status:
print("Error: Unable to uninstall BSP sonic-platform whl package")
return status
print("Attempting to install the PDDF sonic_platform wheel package ...")
if os.path.getsize(SONIC_PLATFORM_BSP_WHL_PKG) != 0:
status, output = log_os_system("pip3 install "+ SONIC_PLATFORM_BSP_WHL_PKG, 1)
if status:
print("Error: Failed to install {}".format(SONIC_PLATFORM_BSP_WHL_PKG))
return status
else:
print("Successfully installed {} package".format(SONIC_PLATFORM_BSP_WHL_PKG))
else:
print("Error: Failed to copy {} properly. Exiting ...".format(SONIC_PLATFORM_PDDF_WHL_PKG))
return -1
else:
# system rebooted in pddf mode
print("System rebooted in PDDF mode, hence keeping the PDDF 2.0 classes")
else:
# pddf whl package doesnt exist
print("Error: PDDF 2.0 classes doesnt exist. PDDF mode can not be enabled")
sys.exit(1)
# ##########################################################################
# Take a backup of orig fancontrol
if os.path.exists(device_path+"/fancontrol"):
log_os_system("mv "+device_path+"/fancontrol"+" "+device_path+"/fancontrol.bak", 0)
# Create a link to fancontrol of PDDF
if os.path.exists(device_path+"/pddf/fancontrol") and not os.path.exists(device_path+"/fancontrol"):
shutil.copy(device_path+"/pddf/fancontrol",device_path+"/fancontrol")
# BMC support
f_sensors="/usr/bin/sensors"
f_sensors_org="/usr/bin/sensors.org"
f_pddf_sensors="/usr/local/bin/pddf_sensors"
if os.path.exists(f_pddf_sensors) is True:
if os.path.exists(f_sensors_org) is False:
shutil.copy(f_sensors, f_sensors_org)
shutil.copy(f_pddf_sensors, f_sensors)
return 0
def cleanup_pddf_utils():
device_path = get_path_to_device()
SONIC_PLATFORM_BSP_WHL_PKG = "/".join([device_path, 'sonic_platform-1.0-py3-none-any.whl'])
SONIC_PLATFORM_PDDF_WHL_PKG = "/".join([device_path, 'pddf', 'sonic_platform-1.0-py3-none-any.whl'])
SONIC_PLATFORM_BSP_WHL_PKG_BK = "/".join([device_path, 'sonic_platform-1.0-py3-none-any.whl.orig'])
# ##########################################################################
status, output = log_os_system("pip3 show sonic-platform > /dev/null 2>&1", 1)
if status:
# PDDF Platform API 2.0 is not supported but system is in PDDF mode, hence PDDF 1.0 plugins are present
device_plugin_path = "/".join([device_path, "plugins"])
backup_path = "/".join([device_plugin_path, "orig"])
if os.path.exists(backup_path) is True:
for item in os.listdir(device_plugin_path):
if os.path.isdir(device_plugin_path+"/"+item) is False:
os.remove(device_plugin_path+"/"+item)
log_os_system("mv "+backup_path+"/*"+" "+device_plugin_path, 1)
os.rmdir(backup_path)
else:
print("\nERR: Unable to locate original device files...\n")
else:
# PDDF 2.0 apis are supported and PDDF whl package is installed
if os.path.exists(SONIC_PLATFORM_PDDF_WHL_PKG):
if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_BK):
# platform is 2.0 compliant and original bsp 2.0 whl package exist
log_os_system('mv '+SONIC_PLATFORM_BSP_WHL_PKG_BK+' '+SONIC_PLATFORM_BSP_WHL_PKG, 1)
status, output = log_os_system("pip3 uninstall sonic-platform -y &> /dev/null", 1)
if status:
print("Error: Unable to uninstall PDDF sonic-platform whl package")
return status
print("Attemting to install the BSP sonic_platform wheel package ...")
status, output = log_os_system("pip3 install "+ SONIC_PLATFORM_BSP_WHL_PKG, 1)
if status:
print("Error: Failed to install {}".format(SONIC_PLATFORM_BSP_WHL_PKG))
return status
else:
print("Successfully installed {} package".format(SONIC_PLATFORM_BSP_WHL_PKG))
else:
# platform doesnt support 2.0 APIs but PDDF is 2.0 based
# remove and uninstall the PDDF whl package
if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG):
os.remove(SONIC_PLATFORM_BSP_WHL_PKG)
status, output = log_os_system("pip3 uninstall sonic-platform -y &> /dev/null", 1)
if status:
print("Error: Unable to uninstall PDDF sonic-platform whl package")
return status
else:
# something seriously wrong. System is in PDDF mode but pddf whl pkg is not present
print("Error: Fatal error as the system is in PDDF mode but the pddf .whl original is not present")
# ################################################################################################################
if os.path.exists(device_path+"/fancontrol"):
os.remove(device_path+"/fancontrol")
if os.path.exists(device_path+"/fancontrol.bak"):
log_os_system("mv "+device_path+"/fancontrol.bak"+" "+device_path+"/fancontrol", 0)
# BMC support
f_sensors="/usr/bin/sensors"
f_sensors_org="/usr/bin/sensors.org"
if os.path.exists(f_sensors_org) is True:
shutil.copy(f_sensors_org, f_sensors)
return 0
def create_pddf_log_files():
if not os.path.exists('/var/log/pddf'):
log_os_system("sudo mkdir /var/log/pddf", 1)
log_os_system("sudo touch /var/log/pddf/led.txt", 1)
log_os_system("sudo touch /var/log/pddf/psu.txt", 1)
log_os_system("sudo touch /var/log/pddf/fan.txt", 1)
log_os_system("sudo touch /var/log/pddf/xcvr.txt", 1)
log_os_system("sudo touch /var/log/pddf/sysstatus.txt", 1)
log_os_system("sudo touch /var/log/pddf/cpld.txt", 1)
log_os_system("sudo touch /var/log/pddf/cpldmux.txt", 1)
log_os_system("sudo touch /var/log/pddf/client.txt", 1)
log_os_system("sudo touch /var/log/pddf/mux.txt", 1)
def driver_install():
global FORCE
# check for pre_driver_install script
if os.path.exists('/usr/local/bin/pddf_pre_driver_install.sh'):
status, output = log_os_system('/usr/local/bin/pddf_pre_driver_install.sh', 1)
if status:
print("Error: pddf_pre_driver_install script failed with error %d"%status)
return status
# For debug
print(output)
# Removes the perm_kos first, then reload them in a proper sequence
for mod in perm_kos:
cmd = "modprobe -rq " + mod
status, output = log_os_system(cmd, 1)
if status:
print("driver_install: Unable to unload {}".format(mod))
# Don't exit but continue
log_os_system("depmod", 1)
for i in range(0,len(kos)):
status, output = log_os_system(kos[i], 1)
if status:
print("driver_install() failed with error %d"%status)
if FORCE == 0:
return status
output = config_pddf_utils()
if output:
print("config_pddf_utils() failed with error %d"%output)
# check for post_driver_install script
if os.path.exists('/usr/local/bin/pddf_post_driver_install.sh'):
status, output = log_os_system('/usr/local/bin/pddf_post_driver_install.sh', 1)
if status:
print("Error: pddf_post_driver_install script failed with error %d"%status)
return status
# Useful for debugging
print(output)
return 0
def driver_uninstall():
global FORCE
status = cleanup_pddf_utils()
if status:
print("cleanup_pddf_utils() failed with error %d"%status)
for i in range(0,len(kos)):
# if it is in perm_kos, do not remove
if (kos[-(i+1)].split())[-1] in perm_kos or 'i2c-i801' in kos[-(i+1)]:
continue
rm = kos[-(i+1)].replace("modprobe", "modprobe -rq")
rm = rm.replace("insmod", "rmmod")
status, output = log_os_system(rm, 1)
if status:
print("driver_uninstall() failed with error %d"%status)
if FORCE == 0:
return status
return 0
def device_install():
global FORCE
# check for pre_device_creation script
if os.path.exists('/usr/local/bin/pddf_pre_device_create.sh'):
status, output = log_os_system('/usr/local/bin/pddf_pre_device_create.sh', 1)
if status:
print("Error: pddf_pre_device_create script failed with error %d"%status)
return status
# trigger the pddf_obj script for FAN, PSU, CPLD, MUX, etc
status = pddf_obj.create_pddf_devices()
if status:
print("Error: create_pddf_devices() failed with error %d"%status)
if FORCE == 0:
return status
# check for post_device_create script
if os.path.exists('/usr/local/bin/pddf_post_device_create.sh'):
status, output = log_os_system('/usr/local/bin/pddf_post_device_create.sh', 1)
if status:
print("Error: pddf_post_device_create script failed with error %d"%status)
return status
# Useful for debugging
print(output)
return
def device_uninstall():
global FORCE
# Trigger the paloparse script for deletion of FAN, PSU, OPTICS, CPLD clients
status = pddf_obj.delete_pddf_devices()
if status:
print("Error: delete_pddf_devices() failed with error %d"%status)
if FORCE == 0:
return status
return
def do_install():
print("Checking system....")
if not os.path.exists('/usr/share/sonic/platform/pddf_support'):
print(PROJECT_NAME.upper() +" mode is not enabled")
return
if driver_check()== False :
print(PROJECT_NAME.upper() +" has no PDDF driver installed....")
create_pddf_log_files()
print("Installing ...")
status = driver_install()
if status:
return status
else:
print(PROJECT_NAME.upper() +" drivers detected....")
print("Creating devices ...")
status = device_install()
if status:
return status
return
def do_uninstall():
print("Checking system....")
if not os.path.exists('/usr/share/sonic/platform/pddf_support'):
print(PROJECT_NAME.upper() +" mode is not enabled")
return
if os.path.exists('/var/log/pddf'):
print("Remove pddf log files.....")
log_os_system("sudo rm -rf /var/log/pddf", 1)
print("Remove all the devices...")
status = device_uninstall()
if status:
return status
if driver_check()== False :
print(PROJECT_NAME.upper() +" has no PDDF driver installed....")
else:
print("Removing installed driver....")
status = driver_uninstall()
if status:
if FORCE == 0:
return status
return
def do_switch_pddf():
try:
import pddf_switch_svc
except ImportError:
print("Unable to find pddf_switch_svc.py. PDDF might not be supported on this platform")
sys.exit()
print("Check the pddf support...")
status = pddf_switch_svc.check_pddf_support()
if not status:
print("PDDF is not supported on this platform")
return status
print("Checking system....")
if os.path.exists('/usr/share/sonic/platform/pddf_support'):
print(PROJECT_NAME.upper() +" system is already in pddf mode....")
else:
print("Check if the native sonic-platform whl package is installed in the pmon docker")
status, output = log_os_system("docker exec -it pmon pip3 show sonic-platform", 1)
if not status:
# Need to remove this whl module
status, output = log_os_system("docker exec -it pmon pip3 uninstall sonic-platform -y", 1)
if not status:
print("Successfully uninstalled the native sonic-platform whl pkg from pmon container")
else:
print("Error: Unable to uninstall the sonic-platform whl pkg from pmon container."
" Do it manually before moving to nonpddf mode")
return status
print("Stopping the pmon service ...")
status, output = log_os_system("systemctl stop pmon.service", 1)
if status:
print("Pmon stop failed")
if FORCE==0:
return status
print("Stopping the platform services..")
status = pddf_switch_svc.stop_platform_svc()
if not status:
if FORCE==0:
return status
print("Creating the pddf_support file...")
if os.path.exists('/usr/share/sonic/platform'):
log_os_system("touch /usr/share/sonic/platform/pddf_support", 1)
else:
print("/usr/share/sonic/platform path doesn't exist. Unable to set pddf mode")
return -1
print("Starting the PDDF platform service...")
status = pddf_switch_svc.start_platform_pddf()
if not status:
if FORCE==0:
return status
print("Restart the pmon service ...")
status, output = log_os_system("systemctl start pmon.service", 1)
if status:
print("Pmon restart failed")
if FORCE==0:
return status
return
def do_switch_nonpddf():
try:
import pddf_switch_svc
except ImportError:
print("Unable to find pddf_switch_svc.py. PDDF might not be supported on this platform")
sys.exit()
print("Checking system....")
if not os.path.exists('/usr/share/sonic/platform/pddf_support'):
print(PROJECT_NAME.upper() +" system is already in non-pddf mode....")
else:
print("Check if the sonic-platform whl package is installed in the pmon docker")
status, output = log_os_system("docker exec -it pmon pip3 show sonic-platform", 1)
if not status:
# Need to remove this whl module
status, output = log_os_system("docker exec -it pmon pip3 uninstall sonic-platform -y", 1)
if not status:
print("Successfully uninstalled the sonic-platform whl pkg from pmon container")
else:
print("Error: Unable to uninstall the sonic-platform whl pkg from pmon container."
" Do it manually before moving to nonpddf mode")
return status
print("Stopping the pmon service ...")
status, output = log_os_system("systemctl stop pmon.service", 1)
if status:
print("Stopping pmon service failed")
if FORCE==0:
return status
print("Stopping the PDDF platform service...")
status = pddf_switch_svc.stop_platform_pddf()
if not status:
if FORCE==0:
return status
print("Removing the pddf_support file...")
if os.path.exists('/usr/share/sonic/platform'):
log_os_system("rm -f /usr/share/sonic/platform/pddf_support", 1)
else:
print("/usr/share/sonic/platform path doesnt exist. Unable to set non-pddf mode")
return -1
print("Starting the platform services...")
status = pddf_switch_svc.start_platform_svc()
if not status:
if FORCE==0:
return status
print("Restart the pmon service ...")
status, output = log_os_system("systemctl start pmon.service", 1)
if status:
print("Restarting pmon service failed")
if FORCE==0:
return status
return
if __name__ == "__main__":
main()