Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create DaemonBase class for all daemons #2570

Merged
merged 1 commit into from
Mar 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rules/docker-platform-monitor.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ $(DOCKER_PLATFORM_MONITOR)_PYTHON_DEBS += $(SONIC_LEDD) $(SONIC_XCVRD) $(SONIC_P
$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PLATFORM_COMMON_PY2)
$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SWSSSDK_PY2)
$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_PLATFORM_API_PY2)
$(DOCKER_PLATFORM_MONITOR)_PYTHON_WHEELS += $(SONIC_DAEMON_BASE_PY2)
$(DOCKER_PLATFORM_MONITOR)_LOAD_DOCKERS = $(DOCKER_CONFIG_ENGINE)

SONIC_DOCKER_IMAGES += $(DOCKER_PLATFORM_MONITOR)
Expand Down
7 changes: 7 additions & 0 deletions rules/sonic-daemon-base.mk
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)

30 changes: 30 additions & 0 deletions src/sonic-daemon-base/setup.py
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='[email protected]',
url='https://github.com/Azure/sonic-platform-daemons',
maintainer='Kevin Wang',
maintainer_email='[email protected]',
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.
136 changes: 136 additions & 0 deletions src/sonic-daemon-base/sonic_daemon_base/daemon_base.py
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