-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[sonic-daemon-base] Create DaemonBase class for all daemons (#2570)
DaemonBase is to wrap the common function of daemons, such as logging, signal handling, db connector, load specific platform plugins. Signed-off-by: Kevin Wang <kevinw@mellanox.com>
- Loading branch information
1 parent
66f5202
commit fa84c42
Showing
5 changed files
with
174 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# SONIC_DAEMON_BASE_PY2 package | ||
|
||
SONIC_DAEMON_BASE_PY2 = sonic_daemon_base-1.0-py2-none-any.whl | ||
$(SONIC_DAEMON_BASE_PY2)_SRC_PATH = $(SRC_PATH)/sonic-daemon-base | ||
$(SONIC_DAEMON_BASE_PY2)_PYTHON_VERSION = 2 | ||
SONIC_PYTHON_WHEELS += $(SONIC_DAEMON_BASE_PY2) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
from setuptools import setup | ||
|
||
setup( | ||
name='sonic-daemon-base', | ||
version='1.0', | ||
description='Sonic daemon base package', | ||
license='Apache 2.0', | ||
author='SONiC Team', | ||
author_email='linuxnetdev@microsoft.com', | ||
url='https://github.com/Azure/sonic-platform-daemons', | ||
maintainer='Kevin Wang', | ||
maintainer_email='kevinw@mellanox.com', | ||
packages=[ | ||
'sonic_daemon_base', | ||
], | ||
classifiers=[ | ||
'Development Status :: 4 - Beta', | ||
'Environment :: No Input/Output (Daemon)', | ||
'Intended Audience :: Developers', | ||
'Intended Audience :: Information Technology', | ||
'Intended Audience :: System Administrators', | ||
'License :: OSI Approved :: Apache Software License', | ||
'Natural Language :: English', | ||
'Operating System :: POSIX :: Linux', | ||
'Programming Language :: Python :: 2.7', | ||
'Topic :: System :: Hardware', | ||
], | ||
keywords='SONiC sonic PLATFORM platform DAEMON daemon', | ||
) | ||
|
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
#!/usr/bin/env python2 | ||
|
||
try: | ||
import imp | ||
import signal | ||
import subprocess | ||
import sys | ||
import syslog | ||
from swsscommon import swsscommon | ||
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' | ||
|
||
class DaemonBase(object): | ||
# Redis DB information | ||
redis_hostname = "localhost" | ||
redis_port = 6379 | ||
redis_timeout_msecs = 0 | ||
|
||
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 ========================== | ||
def signal_handler(self, sig, frame): | ||
if sig == signal.SIGHUP: | ||
self.log_info("Caught SIGHUP - ignoring...") | ||
return | ||
elif sig == signal.SIGINT: | ||
self.log_info("Caught SIGINT - exiting...") | ||
sys.exit(128 + sig) | ||
elif sig == signal.SIGTERM: | ||
self.log_info("Caught SIGTERM - exiting...") | ||
sys.exit(128 + sig) | ||
else: | ||
self.log_warning("Caught unhandled signal '" + sig + "'") | ||
return | ||
|
||
#============ Functions to load platform-specific classes ============ | ||
# Returns platform and HW SKU | ||
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: | ||
self.log_error("Cannot to detect platform") | ||
raise OSError("Cannot detect platform") | ||
|
||
return (platform, hwsku) | ||
|
||
# Returns path to 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) | ||
|
||
# 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: | ||
self.log_error("Failed to load platform module '%s': %s" % (module_name, str(e))) | ||
return None | ||
|
||
try: | ||
platform_util_class = getattr(module, class_name) | ||
platform_util = platform_util_class() | ||
except AttributeError, e: | ||
self.log_error("Failed to instantiate '%s' class: %s" % (class_name, str(e))) | ||
return None | ||
|
||
return platform_util | ||
|