From ab2c42ea8ad2aa646626ffb597fb52b6742d6251 Mon Sep 17 00:00:00 2001 From: Nazarii Hnydyn Date: Thu, 4 Apr 2019 16:12:59 +0300 Subject: [PATCH] Refactored daemon base API: added Logger. (#2672) * Refactored daemon base API: added Logger. Signed-off-by: Nazarii Hnydyn --- .../sonic_daemon_base/daemon_base.py | 150 +++++++++++------- 1 file changed, 97 insertions(+), 53 deletions(-) diff --git a/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py b/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py index abed352c68..4f26806f4f 100644 --- a/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py +++ b/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py @@ -4,82 +4,111 @@ try: import imp import signal import subprocess + import os import sys import syslog from swsscommon import swsscommon except ImportError, e: raise ImportError (str(e) + " - required module not found") -#============================= Constants ============================= +# +# Constants ==================================================================== +# + +# Redis DB information +REDIS_HOSTNAME = 'localhost' +REDIS_PORT = 6379 +REDIS_TIMEOUT_MSECS = 0 # Platform root directory inside docker -PLATFORM_ROOT_DOCKER = "/usr/share/sonic/platform" +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' +# Port config information +PORT_CONFIG = 'port_config.ini' +PORTMAP = 'portmap.ini' + EEPROM_MODULE_NAME = 'eeprom' EEPROM_CLASS_NAME = 'board' -class DaemonBase(object): - # Redis DB information - redis_hostname = "localhost" - redis_port = 6379 - redis_timeout_msecs = 0 +# +# Helper functions ============================================================= +# +def db_connect(db): + return swsscommon.DBConnector(db, + REDIS_HOSTNAME, + REDIS_PORT, + REDIS_TIMEOUT_MSECS) + +# +# Helper classes =============================================================== +# + +class Logger(object): + def __init__(self, syslog_identifier): + syslog.openlog(ident=syslog_identifier, logoption=syslog.LOG_NDELAY, facility=syslog.LOG_DAEMON) + + def __del__(self): + syslog.closelog() + + def log_error(self, msg, also_print_to_console=False): + syslog.syslog(syslog.LOG_ERR, msg) + + if also_print_to_console: + print msg + + def log_warning(self, msg, also_print_to_console=False): + syslog.syslog(syslog.LOG_WARNING, msg) + + if also_print_to_console: + print msg + + def log_notice(self, msg, also_print_to_console=False): + syslog.syslog(syslog.LOG_NOTICE, msg) + + if also_print_to_console: + print msg + + def log_info(self, msg, also_print_to_console=False): + syslog.syslog(syslog.LOG_INFO, msg) + + if also_print_to_console: + print msg + + def log_debug(self, msg, also_print_to_console=False): + syslog.syslog(syslog.LOG_DEBUG, msg) + + if also_print_to_console: + print msg + +# +# Daemon ======================================================================= +# + +class DaemonBase(object): def __init__(self): - self.log_info("Starting up...") # Register our signal handlers signal.signal(signal.SIGHUP, self.signal_handler) signal.signal(signal.SIGINT, self.signal_handler) signal.signal(signal.SIGTERM, self.signal_handler) - def __del__(self): - self.log_error("Return from daemon, exiting...") - - def run(self): - raise NotImplementedError() - - # ========================== Connect to DB ============================ - def db_connect(self, db): - return swsscommon.DBConnector(db, - self.redis_hostname, - self.redis_port, - self.redis_timeout_msecs) - - # ========================== Syslog wrappers ========================== - def log_info(self, msg): - syslog.openlog() - syslog.syslog(syslog.LOG_INFO, msg) - syslog.closelog() - - def log_warning(self, msg): - syslog.openlog() - syslog.syslog(syslog.LOG_WARNING, msg) - syslog.closelog() - - def log_error(self, msg): - syslog.openlog() - syslog.syslog(syslog.LOG_ERR, msg) - syslog.closelog() - - #========================== Signal Handling ========================== + # Signal handler def signal_handler(self, sig, frame): if sig == signal.SIGHUP: - self.log_info("Caught SIGHUP - ignoring...") - return + syslog.syslog(syslog.LOG_INFO, "Caught SIGHUP - ignoring...") elif sig == signal.SIGINT: - self.log_info("Caught SIGINT - exiting...") + syslog.syslog(syslog.LOG_INFO, "Caught SIGINT - exiting...") sys.exit(128 + sig) elif sig == signal.SIGTERM: - self.log_info("Caught SIGTERM - exiting...") + syslog.syslog(syslog.LOG_INFO, "Caught SIGTERM - exiting...") sys.exit(128 + sig) else: - self.log_warning("Caught unhandled signal '" + sig + "'") - return + syslog.syslog(syslog.LOG_WARNING, "Caught unhandled signal '" + sig + "'") - #============ Functions to load platform-specific classes ============ - # Returns platform and HW SKU + # Returns platform and hwsku def get_platform_and_hwsku(self): try: proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-H', '-v', PLATFORM_KEY], @@ -98,12 +127,11 @@ class DaemonBase(object): proc.wait() hwsku = stdout.rstrip('\n') except OSError, e: - self.log_error("Cannot to detect platform") - raise OSError("Cannot detect platform") + raise OSError("Failed to detect platform: %s" % (str(e))) return (platform, hwsku) - # Returns path to 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() @@ -114,6 +142,21 @@ class DaemonBase(object): 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 @@ -125,8 +168,7 @@ class DaemonBase(object): module_file = "/".join([platform_path, "plugins", module_name + ".py"]) module = imp.load_source(module_name, module_file) except IOError, e: - self.log_error("Failed to load platform module '%s': %s" % (module_name, str(e))) - return None + raise IOError("Failed to load platform module '%s': %s" % (module_name, str(e))) try: platform_util_class = getattr(module, class_name) @@ -136,8 +178,10 @@ class DaemonBase(object): else: platform_util = platform_util_class() except AttributeError, e: - self.log_error("Failed to instantiate '%s' class: %s" % (class_name, str(e))) - return None + raise AttributeError("Failed to instantiate '%s' class: %s" % (class_name, str(e))) return platform_util + # Runs daemon + def run(self): + raise NotImplementedError()