From 66e81bb119810da44857907310cee36c3c57bc5e Mon Sep 17 00:00:00 2001 From: fk410167 <51665572+fk410167@users.noreply.github.com> Date: Sat, 7 Dec 2019 02:48:40 +0530 Subject: [PATCH] Platform Driver Development Framework (PDDF): Adding PDDF CLI utils (#624) This change is related to Platform Driver Development Framework (PDDF) which is being added to sonic-buildimage repo. More details can be found here, Azure/SONiC#406 PDDF supports its own CLI utilities, which use generic PDDF component plugins. I added these PDDF CLI utilities. --- data/etc/bash_completion.d/pddf_fanutil | 8 + data/etc/bash_completion.d/pddf_ledutil | 8 + data/etc/bash_completion.d/pddf_psuutil | 8 + data/etc/bash_completion.d/pddf_thermalutil | 8 + pddf_fanutil/__init__.py | 0 pddf_fanutil/main.py | 193 +++++++++++++++++++ pddf_ledutil/__init__.py | 0 pddf_ledutil/main.py | 96 ++++++++++ pddf_psuutil/__init__.py | 0 pddf_psuutil/main.py | 194 ++++++++++++++++++++ pddf_thermalutil/__init__.py | 0 pddf_thermalutil/main.py | 119 ++++++++++++ setup.py | 8 + utilities_common/util_base.py | 153 +++++++++++++++ 14 files changed, 795 insertions(+) create mode 100644 data/etc/bash_completion.d/pddf_fanutil create mode 100644 data/etc/bash_completion.d/pddf_ledutil create mode 100644 data/etc/bash_completion.d/pddf_psuutil create mode 100644 data/etc/bash_completion.d/pddf_thermalutil create mode 100644 pddf_fanutil/__init__.py create mode 100644 pddf_fanutil/main.py create mode 100644 pddf_ledutil/__init__.py create mode 100644 pddf_ledutil/main.py create mode 100644 pddf_psuutil/__init__.py create mode 100644 pddf_psuutil/main.py create mode 100644 pddf_thermalutil/__init__.py create mode 100644 pddf_thermalutil/main.py create mode 100644 utilities_common/util_base.py diff --git a/data/etc/bash_completion.d/pddf_fanutil b/data/etc/bash_completion.d/pddf_fanutil new file mode 100644 index 0000000000..408c0f4cd4 --- /dev/null +++ b/data/etc/bash_completion.d/pddf_fanutil @@ -0,0 +1,8 @@ +_pddf_fanutil_completion() { + COMPREPLY=( $( env COMP_WORDS="${COMP_WORDS[*]}" \ + COMP_CWORD=$COMP_CWORD \ + _PDDF_FANUTIL_COMPLETE=complete $1 ) ) + return 0 +} + +complete -F _pddf_fanutil_completion -o default pddf_fanutil; diff --git a/data/etc/bash_completion.d/pddf_ledutil b/data/etc/bash_completion.d/pddf_ledutil new file mode 100644 index 0000000000..f39ceba823 --- /dev/null +++ b/data/etc/bash_completion.d/pddf_ledutil @@ -0,0 +1,8 @@ +_pddf_ledutil_completion() { + COMPREPLY=( $( env COMP_WORDS="${COMP_WORDS[*]}" \ + COMP_CWORD=$COMP_CWORD \ + _PDDF_LEDUTIL_COMPLETE=complete $1 ) ) + return 0 +} + +complete -F _pddf_ledutil_completion -o default pddf_ledutil; diff --git a/data/etc/bash_completion.d/pddf_psuutil b/data/etc/bash_completion.d/pddf_psuutil new file mode 100644 index 0000000000..afc6ab02d5 --- /dev/null +++ b/data/etc/bash_completion.d/pddf_psuutil @@ -0,0 +1,8 @@ +_pddf_psuutil_completion() { + COMPREPLY=( $( env COMP_WORDS="${COMP_WORDS[*]}" \ + COMP_CWORD=$COMP_CWORD \ + _PDDF_PSUUTIL_COMPLETE=complete $1 ) ) + return 0 +} + +complete -F _pddf_psuutil_completion -o default pddf_psuutil; diff --git a/data/etc/bash_completion.d/pddf_thermalutil b/data/etc/bash_completion.d/pddf_thermalutil new file mode 100644 index 0000000000..c536307594 --- /dev/null +++ b/data/etc/bash_completion.d/pddf_thermalutil @@ -0,0 +1,8 @@ +_pddf_thermalutil_completion() { + COMPREPLY=( $( env COMP_WORDS="${COMP_WORDS[*]}" \ + COMP_CWORD=$COMP_CWORD \ + _PDDF_THERMALUTIL_COMPLETE=complete $1 ) ) + return 0 +} + +complete -F _pddf_thermalutil_completion -o default pddf_thermalutil; diff --git a/pddf_fanutil/__init__.py b/pddf_fanutil/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pddf_fanutil/main.py b/pddf_fanutil/main.py new file mode 100644 index 0000000000..dee001603b --- /dev/null +++ b/pddf_fanutil/main.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python +# +# main.py +# +# Command-line utility for interacting with FAN Controller in PDDF mode in SONiC +# + +try: + import sys + import os + import subprocess + import click + import imp + import syslog + import types + import traceback + from tabulate import tabulate + from utilities_common import util_base + from utilities_common.util_base import UtilLogger + from utilities_common.util_base import UtilHelper +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +VERSION = '1.0' + +SYSLOG_IDENTIFIER = "fanutil" +PLATFORM_SPECIFIC_MODULE_NAME = "fanutil" +PLATFORM_SPECIFIC_CLASS_NAME = "FanUtil" + +# Global platform-specific fanutil class instance +platform_fanutil = None + +#logger = UtilLogger(SYSLOG_IDENTIFIER) + +# This is our main entrypoint - the main 'fanutil' command +@click.group() +def cli(): + """pddf_fanutil - Command line utility for providing FAN information""" + + if os.geteuid() != 0: + click.echo("Root privileges are required for this operation") + sys.exit(1) + + # Load the helper class + helper = UtilHelper() + + if not helper.check_pddf_mode(): + click.echo("PDDF mode should be supported and enabled for this platform for this operation") + sys.exit(1) + + # Load platform-specific fanutil class + global platform_fanutil + try: + platform_fanutil = helper.load_platform_util(PLATFORM_SPECIFIC_MODULE_NAME, PLATFORM_SPECIFIC_CLASS_NAME) + except Exception as e: + click.echo("Failed to load {}: {}".format(PLATFORM_SPECIFIC_MODULE_NAME, str(e))) + sys.exit(2) + +# 'version' subcommand +@cli.command() +def version(): + """Display version info""" + click.echo("PDDF fanutil version {0}".format(VERSION)) + +# 'numfans' subcommand +@cli.command() +def numfans(): + """Display number of FANs installed on device""" + click.echo(str(platform_fanutil.get_num_fans())) + +# 'status' subcommand +@cli.command() +@click.option('-i', '--index', default=-1, type=int, help="the index of FAN") +def status(index): + """Display FAN status""" + supported_fan = range(1, platform_fanutil.get_num_fans() + 1) + fan_ids = [] + if (index < 0): + fan_ids = supported_fan + else: + fan_ids = [index] + + header = ['FAN', 'Status'] + status_table = [] + + for fan in fan_ids: + msg = "" + fan_name = "FAN {}".format(fan) + if fan not in supported_fan: + click.echo("Error! The {} is not available on the platform.\n" \ + "Number of supported FAN - {}.".format(fan_name, platform_fanutil.get_num_fans())) + continue + presence = platform_fanutil.get_presence(fan) + if presence: + oper_status = platform_fanutil.get_status(fan) + msg = 'OK' if oper_status else "NOT OK" + else: + msg = 'NOT PRESENT' + status_table.append([fan_name, msg]) + + if status_table: + click.echo(tabulate(status_table, header, tablefmt="simple")) + +# 'direction' subcommand +@cli.command() +@click.option('-i', '--index', default=-1, type=int, help="the index of FAN") +def direction(index): + """Display FAN airflow direction""" + supported_fan = range(1, platform_fanutil.get_num_fans() + 1) + fan_ids = [] + if (index < 0): + fan_ids = supported_fan + else: + fan_ids = [index] + + header = ['FAN', 'Direction'] + status_table = [] + + for fan in fan_ids: + msg = "" + fan_name = "FAN {}".format(fan) + if fan not in supported_fan: + click.echo("Error! The {} is not available on the platform.\n" \ + "Number of supported FAN - {}.".format(fan_name, platform_fanutil.get_num_fans())) + continue + direction = platform_fanutil.get_direction(fan) + status_table.append([fan_name, direction]) + + if status_table: + click.echo(tabulate(status_table, header, tablefmt="simple")) + +# 'speed' subcommand +@cli.command() +@click.option('-i', '--index', default=-1, type=int, help="the index of FAN") +def getspeed(index): + """Display FAN speed in RPM""" + supported_fan = range(1, platform_fanutil.get_num_fans() + 1) + fan_ids = [] + if (index < 0): + fan_ids = supported_fan + else: + fan_ids = [index] + + header = ['FAN', 'Front Fan RPM', 'Rear Fan RPM'] + status_table = [] + + for fan in fan_ids: + msg = "" + fan_name = "FAN {}".format(fan) + if fan not in supported_fan: + click.echo("Error! The {} is not available on the platform.\n" \ + "Number of supported FAN - {}.".format(fan_name, platform_fanutil.get_num_fans())) + continue + front = platform_fanutil.get_speed(fan) + rear = platform_fanutil.get_speed_rear(fan) + status_table.append([fan_name, front, rear]) + + if status_table: + click.echo(tabulate(status_table, header, tablefmt="simple")) + +# 'setspeed' subcommand +@cli.command() +@click.argument('speed', type=int) +def setspeed(speed): + """Set FAN speed in percentage""" + if speed is None: + click.echo("speed value is required") + raise click.Abort() + + status = platform_fanutil.set_speed(speed) + if status: + click.echo("Successful") + else: + click.echo("Failed") + +@cli.group() +def debug(): + """pddf_fanutil debug commands""" + pass + +@debug.command() +def dump_sysfs(): + """Dump all Fan related SysFS paths""" + status = platform_fanutil.dump_sysfs() + + if status: + for i in status: + click.echo(i) + + + +if __name__ == '__main__': + cli() diff --git a/pddf_ledutil/__init__.py b/pddf_ledutil/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pddf_ledutil/main.py b/pddf_ledutil/main.py new file mode 100644 index 0000000000..df471ec8ef --- /dev/null +++ b/pddf_ledutil/main.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# +# main.py +# +# Command-line utility for interacting with FAN Controller in PDDF mode in SONiC +# + +try: + import sys + import os + import subprocess + import click + import imp + import syslog + import types + import traceback + from tabulate import tabulate + from utilities_common import util_base + from utilities_common.util_base import UtilLogger + from utilities_common.util_base import UtilHelper +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +VERSION = '1.0' + +SYSLOG_IDENTIFIER = "ledutil" +PLATFORM_SPECIFIC_MODULE_NAME = "ledutil" +PLATFORM_SPECIFIC_CLASS_NAME = "LedUtil" + +# Global platform-specific ledutil class instance +platform_ledutil = None + +#logger = UtilLogger(SYSLOG_IDENTIFIER) + +# ==================== CLI commands and groups ==================== + + +# This is our main entrypoint - the main 'ledutil' command +@click.group() +def cli(): + """pddf_ledutil - Command line utility for providing FAN information""" + + if os.geteuid() != 0: + click.echo("Root privileges are required for this operation") + sys.exit(1) + + # Load the helper class + helper = UtilHelper() + + if not helper.check_pddf_mode(): + click.echo("PDDF mode should be supported and enabled for this platform for this operation") + sys.exit(1) + + # Load platform-specific fanutil class + global platform_ledutil + try: + platform_ledutil = helper.load_platform_util(PLATFORM_SPECIFIC_MODULE_NAME, PLATFORM_SPECIFIC_CLASS_NAME) + except Exception as e: + click.echo("Failed to load {}: {}".format(PLATFORM_SPECIFIC_MODULE_NAME, str(e))) + sys.exit(2) + +# 'version' subcommand +@cli.command() +def version(): + """Display version info""" + click.echo("PDDF ledutil version {0}".format(VERSION)) + +# 'getstatusled' subcommand +@cli.command() +@click.argument('device_name', type=click.STRING) +@click.argument('index', type=click.STRING) +def getstatusled(device_name, index): + if device_name is None: + click.echo("device_name is required") + raise click.Abort() + + outputs = platform_ledutil.get_status_led(device_name, index) + click.echo(outputs) + + +# 'setstatusled' subcommand +@cli.command() +@click.argument('device_name', type=click.STRING) +@click.argument('index', type=click.STRING) +@click.argument('color', type=click.STRING) +@click.argument('color_state', type=click.STRING) +def setstatusled(device_name, index, color, color_state): + if device_name is None: + click.echo("device_name is required") + raise click.Abort() + + outputs = platform_ledutil.set_status_led(device_name, index, color, color_state) + click.echo(outputs) + +if __name__ == '__main__': + cli() diff --git a/pddf_psuutil/__init__.py b/pddf_psuutil/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pddf_psuutil/main.py b/pddf_psuutil/main.py new file mode 100644 index 0000000000..1a00a3b774 --- /dev/null +++ b/pddf_psuutil/main.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python +# +# main.py +# +# Command-line utility for interacting with PSU Controller in PDDF mode in SONiC +# + +try: + import sys + import os + import subprocess + import click + import imp + import syslog + import types + import traceback + from tabulate import tabulate + from utilities_common import util_base + from utilities_common.util_base import UtilLogger + from utilities_common.util_base import UtilHelper +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +VERSION = '1.0' + +SYSLOG_IDENTIFIER = "psuutil" +PLATFORM_SPECIFIC_MODULE_NAME = "psuutil" +PLATFORM_SPECIFIC_CLASS_NAME = "PsuUtil" + +# Global platform-specific psuutil class instance +platform_psuutil = None + +#logger = UtilLogger(SYSLOG_IDENTIFIER) + +# ==================== CLI commands and groups ==================== + + +# This is our main entrypoint - the main 'psuutil' command +@click.group() +def cli(): + """psuutil - Command line utility for providing PSU status""" + + if os.geteuid() != 0: + click.echo("Root privileges are required for this operation") + sys.exit(1) + + # Load the helper class + helper = UtilHelper() + + if not helper.check_pddf_mode(): + click.echo("PDDF mode should be supported and enabled for this platform for this operation") + sys.exit(1) + + # Load platform-specific fanutil class + global platform_psuutil + try: + platform_psuutil = helper.load_platform_util(PLATFORM_SPECIFIC_MODULE_NAME, PLATFORM_SPECIFIC_CLASS_NAME) + except Exception as e: + click.echo("Failed to load {}: {}".format(PLATFORM_SPECIFIC_MODULE_NAME, str(e))) + sys.exit(2) + +# 'version' subcommand +@cli.command() +def version(): + """Display version info""" + click.echo("psuutil version {0}".format(VERSION)) + +# 'numpsus' subcommand +@cli.command() +def numpsus(): + """Display number of supported PSUs on device""" + click.echo(str(platform_psuutil.get_num_psus())) + +# 'status' subcommand +@cli.command() +@click.option('-i', '--index', default=-1, type=int, help="the index of PSU") +def status(index): + """Display PSU status""" + supported_psu = range(1, platform_psuutil.get_num_psus() + 1) + psu_ids = [] + if (index < 0): + psu_ids = supported_psu + else: + psu_ids = [index] + + header = ['PSU', 'Status'] + status_table = [] + + for psu in psu_ids: + msg = "" + psu_name = "PSU {}".format(psu) + if psu not in supported_psu: + click.echo("Error! The {} is not available on the platform.\n" \ + "Number of supported PSU - {}.".format(psu_name, platform_psuutil.get_num_psus())) + continue + presence = platform_psuutil.get_psu_presence(psu) + if presence: + oper_status = platform_psuutil.get_psu_status(psu) + msg = 'OK' if oper_status else "NOT OK" + else: + msg = 'NOT PRESENT' + status_table.append([psu_name, msg]) + + if status_table: + click.echo(tabulate(status_table, header, tablefmt="simple")) + +# 'mfrinfo' subcommand +@cli.command() +@click.option('-i', '--index', default=-1, type=int, help="the index of PSU") +def mfrinfo(index): + """Display PSU manufacturer info""" + supported_psu = range(1, platform_psuutil.get_num_psus() + 1) + psu_ids = [] + info = "" + if (index < 0): + psu_ids = supported_psu + else: + psu_ids = [index] + + for psu in psu_ids: + msg = "" + psu_name = "PSU {}".format(psu) + if psu not in supported_psu: + click.echo("Error! The {} is not available on the platform.\n" \ + "Number of supported PSU - {}.".format(psu_name, platform_psuutil.get_num_psus())) + continue + status = platform_psuutil.get_psu_status(psu) + if not status: + click.echo("{} is Not OK\n".format(psu_name)) + continue + + model_name = platform_psuutil.get_model(psu) + mfr_id = platform_psuutil.get_mfr_id(psu) + serial_num = platform_psuutil.get_serial(psu) + airflow_dir = platform_psuutil.get_direction(psu) + + click.echo("{} is OK\nManufacture Id: {}\n" \ + "Model: {}\nSerial Number: {}\n" \ + "Fan Direction: {}\n".format(psu_name, mfr_id, model_name, serial_num, airflow_dir)) + + +# 'seninfo' subcommand +@cli.command() +@click.option('-i', '--index', default=-1, type=int, help="the index of PSU") +def seninfo(index): + """Display PSU sensor info""" + supported_psu = range(1, platform_psuutil.get_num_psus() + 1) + psu_ids = [] + if (index < 0): + psu_ids = supported_psu + else: + psu_ids = [index] + + for psu in psu_ids: + msg = "" + psu_name = "PSU {}".format(psu) + if psu not in supported_psu: + click.echo("Error! The {} is not available on the platform.\n" \ + "Number of supported PSU - {}.".format(psu_name, platform_psuutil.get_num_psus())) + continue + oper_status = platform_psuutil.get_psu_status(psu) + + if not oper_status: + click.echo("{} is Not OK\n".format(psu_name)) + continue + + v_out = platform_psuutil.get_output_voltage(psu) + i_out = platform_psuutil.get_output_current(psu) + p_out = platform_psuutil.get_output_power(psu) + # p_out would be in micro watts, convert it into milli watts + p_out = p_out/1000 + + fan1_rpm = platform_psuutil.get_fan_speed(psu, 1) + click.echo("{} is OK\nOutput Voltage: {} mv\n" \ + "Output Current: {} ma\nOutput Power: {} mw\n" \ + "Fan1 Speed: {} rpm\n".format(psu_name, v_out, i_out, p_out, fan1_rpm)) + +@cli.group() +def debug(): + """pddf_psuutil debug commands""" + pass + +@debug.command() +def dump_sysfs(): + """Dump all PSU related SysFS paths""" + status = platform_psuutil.dump_sysfs() + + if status: + for i in status: + click.echo(i) + + +if __name__ == '__main__': + cli() diff --git a/pddf_thermalutil/__init__.py b/pddf_thermalutil/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pddf_thermalutil/main.py b/pddf_thermalutil/main.py new file mode 100644 index 0000000000..c72e9d45dd --- /dev/null +++ b/pddf_thermalutil/main.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# +# main.py +# +# Command-line utility for interacting with Thermal sensors in PDDF mode in SONiC +# + +try: + import sys + import os + import subprocess + import click + import imp + import syslog + import types + import traceback + from tabulate import tabulate + from utilities_common import util_base + from utilities_common.util_base import UtilLogger + from utilities_common.util_base import UtilHelper +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +VERSION = '1.0' + +SYSLOG_IDENTIFIER = "thermalutil" +PLATFORM_SPECIFIC_MODULE_NAME = "thermalutil" +PLATFORM_SPECIFIC_CLASS_NAME = "ThermalUtil" + +# Global platform-specific thermalutil class instance +platform_thermalutil = None + +#logger = UtilLogger(SYSLOG_IDENTIFIER) + +# ==================== CLI commands and groups ==================== + + +# This is our main entrypoint - the main 'thermalutil' command +@click.group() +def cli(): + """pddf_thermalutil - Command line utility for providing Temp Sensors information""" + + if os.geteuid() != 0: + click.echo("Root privileges are required for this operation") + sys.exit(1) + + # Load the helper class + helper = UtilHelper() + + if not helper.check_pddf_mode(): + click.echo("PDDF mode should be supported and enabled for this platform for this operation") + sys.exit(1) + + # Load platform-specific fanutil class + global platform_thermalutil + try: + platform_thermalutil = helper.load_platform_util(PLATFORM_SPECIFIC_MODULE_NAME, PLATFORM_SPECIFIC_CLASS_NAME) + except Exception as e: + click.echo("Failed to load {}: {}".format(PLATFORM_SPECIFIC_MODULE_NAME, str(e))) + sys.exit(2) + + +# 'version' subcommand +@cli.command() +def version(): + """Display version info""" + click.echo("PDDF thermalutil version {0}".format(VERSION)) + +# 'numthermals' subcommand +@cli.command() +def numthermals(): + """Display number of Thermal Sensors installed """ + click.echo(str(platform_thermalutil.get_num_thermals())) + +# 'gettemp' subcommand +@cli.command() +@click.option('-i', '--index', default=-1, type=int, help="the index of Temp Sensor") +def gettemp(index): + """Display Temperature values of thermal sensors""" + supported_thermal = range(1, platform_thermalutil.get_num_thermals() + 1) + thermal_ids = [] + if (index < 0): + thermal_ids = supported_thermal + else: + thermal_ids = [index] + + header = ['Temp Sensor', 'Label', 'Value'] + status_table = [] + + for thermal in thermal_ids: + msg = "" + thermal_name = "TEMP{}".format(thermal) + if thermal not in supported_thermal: + click.echo("Error! The {} is not available on the platform.\n" \ + "Number of supported Temp - {}.".format(thermal_name, platform_thermalutil.get_num_thermals())) + ##continue + label, value = platform_thermalutil.show_thermal_temp_values(thermal) + status_table.append([thermal_name, label, value]) + + if status_table: + click.echo(tabulate(status_table, header, tablefmt="simple")) + +@cli.group() +def debug(): + """pddf_thermalutil debug commands""" + pass + +@debug.command() +def dump_sysfs(): + """Dump all Temp Sensor related SysFS paths""" + status = platform_thermalutil.dump_sysfs() + + if status: + for i in status: + click.echo(i) + + +if __name__ == '__main__': + cli() diff --git a/setup.py b/setup.py index 52a60c3d71..bbc59a753f 100644 --- a/setup.py +++ b/setup.py @@ -41,6 +41,10 @@ 'ssdutil', 'pfc', 'psuutil', + 'pddf_fanutil', + 'pddf_psuutil', + 'pddf_thermalutil', + 'pddf_ledutil', 'show', 'sonic_installer', 'sonic-utilities-tests', @@ -113,6 +117,10 @@ 'ssdutil = ssdutil.main:ssdutil', 'pfc = pfc.main:cli', 'psuutil = psuutil.main:cli', + 'pddf_fanutil = pddf_fanutil.main:cli', + 'pddf_psuutil = pddf_psuutil.main:cli', + 'pddf_thermalutil = pddf_thermalutil.main:cli', + 'pddf_ledutil = pddf_ledutil.main:cli', 'show = show.main:cli', 'sonic-clear = clear.main:cli', 'sonic_installer = sonic_installer.main:cli', diff --git a/utilities_common/util_base.py b/utilities_common/util_base.py new file mode 100644 index 0000000000..8ac7286391 --- /dev/null +++ b/utilities_common/util_base.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python2 + +try: + import imp + import signal + import subprocess + import os + import sys + import syslog +except ImportError, e: + raise ImportError (str(e) + " - required module not found") + +# +# Constants ==================================================================== +# +# Platform root directory inside docker +PLATFORM_ROOT_DOCKER = '/usr/share/sonic/platform' +SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen' +HWSKU_KEY = 'DEVICE_METADATA.localhost.hwsku' +PLATFORM_KEY = 'DEVICE_METADATA.localhost.platform' +PDDF_FILE_PATH = '/usr/share/sonic/platform/pddf_support' + +# Port config information +PORT_CONFIG = 'port_config.ini' +PORTMAP = 'portmap.ini' + + +EEPROM_MODULE_NAME = 'eeprom' +EEPROM_CLASS_NAME = 'board' + +class UtilLogger(object): + def __init__(self, syslog_identifier): + self.syslog = syslog + self.syslog.openlog(ident=syslog_identifier, logoption=self.syslog.LOG_NDELAY, facility=self.syslog.LOG_DAEMON) + + def __del__(self): + self.syslog.closelog() + + def log_error(self, msg, print_to_console=False): + self.syslog.syslog(self.syslog.LOG_ERR, msg) + + if print_to_console: + print msg + + def log_warning(self, msg, print_to_console=False): + self.syslog.syslog(self.syslog.LOG_WARNING, msg) + + if print_to_console: + print msg + + def log_notice(self, msg, print_to_console=False): + self.syslog.syslog(self.syslog.LOG_NOTICE, msg) + + if print_to_console: + print msg + + def log_info(self, msg, print_to_console=False): + self.syslog.syslog(self.syslog.LOG_INFO, msg) + + if print_to_console: + print msg + + def log_debug(self, msg, print_to_console=False): + self.syslog.syslog(self.syslog.LOG_DEBUG, msg) + + if print_to_console: + print msg + + +class UtilHelper(object): + def __init__(self): + pass + + # Returns platform and hwsku + def get_platform_and_hwsku(self): + try: + proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-H', '-v', PLATFORM_KEY], + stdout=subprocess.PIPE, + shell=False, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + platform = stdout.rstrip('\n') + + proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-d', '-v', HWSKU_KEY], + stdout=subprocess.PIPE, + shell=False, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + hwsku = stdout.rstrip('\n') + except OSError, e: + raise OSError("Failed to detect platform: %s" % (str(e))) + + return (platform, hwsku) + + # Returns path to platform and hwsku + def get_path_to_platform_and_hwsku(self): + # Get platform and hwsku + (platform, hwsku) = self.get_platform_and_hwsku() + + # Load platform module from source + platform_path = PLATFORM_ROOT_DOCKER + hwsku_path = "/".join([platform_path, hwsku]) + + return (platform_path, hwsku_path) + + # Returns path to port config file + def get_path_to_port_config_file(self): + # Get platform and hwsku path + (platform_path, hwsku_path) = self.get_path_to_platform_and_hwsku() + + # First check for the presence of the new 'port_config.ini' file + port_config_file_path = "/".join([hwsku_path, PORT_CONFIG]) + if not os.path.isfile(port_config_file_path): + # port_config.ini doesn't exist. Try loading the legacy 'portmap.ini' file + port_config_file_path = "/".join([hwsku_path, PORTMAP]) + if not os.path.isfile(port_config_file_path): + raise IOError("Failed to detect port config file: %s" % (port_config_file_path)) + + return port_config_file_path + + # Loads platform specific psuutil module from source + def load_platform_util(self, module_name, class_name): + platform_util = None + + # Get path to platform and hwsku + (platform_path, hwsku_path) = self.get_path_to_platform_and_hwsku() + + try: + module_file = "/".join([platform_path, "plugins", module_name + ".py"]) + module = imp.load_source(module_name, module_file) + except IOError, e: + raise IOError("Failed to load platform module '%s': %s" % (module_name, str(e))) + + try: + platform_util_class = getattr(module, class_name) + # board class of eeprom requires 4 paramerters, need special treatment here. + if module_name == EEPROM_MODULE_NAME and class_name == EEPROM_CLASS_NAME: + platform_util = platform_util_class('','','','') + else: + platform_util = platform_util_class() + except AttributeError, e: + raise AttributeError("Failed to instantiate '%s' class: %s" % (class_name, str(e))) + + return platform_util + + def check_pddf_mode(self): + if os.path.exists(PDDF_FILE_PATH): + return True + else: + return False +