[BFN] Canceling PSU platform API calls on SIGTERM (#10720)

* [BFN] Canceling PSU platform API calls on SIGTERM

Signed-off-by: Andriy Kokhan <andriyx.kokhan@intel.com>

* [BFN] Fixed SONiC fwutil exec time (#31)

Signed-off-by: Taras Keryk <tarasx.keryk@intel.com>

Signed-off-by: Andriy Kokhan <andriyx.kokhan@intel.com>
Signed-off-by: Taras Keryk <tarasx.keryk@intel.com>
Co-authored-by: Taras Keryk <tarasx.keryk@intel.com>
This commit is contained in:
Andriy Kokhan 2022-09-30 01:18:43 +03:00 committed by GitHub
parent d08fcc971c
commit 9bb0a7f33c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 3 deletions

View File

@ -6,6 +6,7 @@ try:
import json
from collections import OrderedDict
from sonic_py_common import device_info
from platform_utils import limit_execution_time
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
@ -24,6 +25,7 @@ def get_bios_version():
except subprocess.CalledProcessError as e:
raise RuntimeError("Failed to get BIOS version")
@limit_execution_time(1)
def get_bmc_version():
"""
Retrieves the firmware version of the BMC

View File

@ -3,11 +3,19 @@
try:
import os
import subprocess
import signal
from functools import wraps
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
def file_create(path, mode=None):
"""
Ensure that file is created with the appropriate permissions
Args:
path: full path of a file
mode: file permission in octal representation
"""
def run_cmd(cmd):
if os.geteuid() != 0:
cmd.insert(0, 'sudo')
@ -18,5 +26,55 @@ def file_create(path, mode=None):
run_cmd(['mkdir', '-p', file_path])
if not os.path.isfile(path):
run_cmd(['touch', path])
if (mode is not None):
if (mode is not None):
run_cmd(['chmod', mode, path])
def cancel_on_sigterm(func):
"""
Wrapper for a function which has to be cancel on SIGTERM
"""
@wraps(func)
def wrapper(*args, **kwargs):
def handler(sig, frame):
if sigterm_handler:
sigterm_handler(sig, frame)
raise Exception("Canceling {}() execution...".format(func.__name__))
sigterm_handler = signal.getsignal(signal.SIGTERM)
signal.signal(signal.SIGTERM, handler)
result = None
try:
result = func(*args, **kwargs)
finally:
signal.signal(signal.SIGTERM, sigterm_handler)
return result
return wrapper
def limit_execution_time(execution_time_secs: int):
"""
Wrapper for a function whose execution time must be limited
Args:
execution_time_secs: maximum execution time in seconds,
after which the function execution will be stopped
"""
def wrapper(func):
@wraps(func)
def execution_func(*args, **kwargs):
def handler(sig, frame):
if sigalrm_handler:
sigalrm_handler(sig, frame)
raise Exception("Canceling {}() execution...".format(func.__name__))
sigalrm_handler = signal.getsignal(signal.SIGALRM)
signal.signal(signal.SIGALRM, handler)
signal.alarm(execution_time_secs)
result = None
try:
result = func(*args, **kwargs)
finally:
signal.alarm(0)
return result
return execution_func
return wrapper

View File

@ -4,18 +4,26 @@ try:
import os
import sys
import time
import signal
import syslog
sys.path.append(os.path.dirname(__file__))
from .platform_thrift_client import thrift_try
from sonic_platform_base.psu_base import PsuBase
from platform_utils import cancel_on_sigterm
except ImportError as e:
raise ImportError (str(e) + "- required module not found")
class Psu(PsuBase):
"""Platform-specific PSU class"""
sigterm = False
sigterm_default_handler = None
cls_inited = False
def __init__(self, index):
PsuBase.__init__(self)
self.__index = index
@ -24,6 +32,21 @@ class Psu(PsuBase):
# STUB IMPLEMENTATION
self.color = ""
syslog.syslog(syslog.LOG_INFO, "Created PSU #{} instance".format(self.__index))
if not Psu.cls_inited:
Psu.sigterm_default_handler = signal.getsignal(signal.SIGTERM)
signal.signal(signal.SIGTERM, Psu.signal_handler)
if Psu.sigterm_default_handler:
syslog.syslog(syslog.LOG_INFO, "Default SIGTERM handler overridden!!")
Psu.cls_inited = True
@classmethod
def signal_handler(cls, sig, frame):
if cls.sigterm_default_handler:
cls.sigterm_default_handler(sig, frame)
syslog.syslog(syslog.LOG_INFO, "Canceling PSU platform API calls...")
cls.sigterm = True
'''
Units of returned info object values:
vin - V
@ -33,20 +56,23 @@ class Psu(PsuBase):
fspeed - RPM
'''
def __info_get(self):
@cancel_on_sigterm
def psu_info_get(client):
return client.pltfm_mgr.pltfm_mgr_pwr_supply_info_get(self.__index)
# Update cache once per 2 seconds
if self.__ts + 2 < time.time():
if self.__ts + 2 < time.time() and not Psu.sigterm:
self.__info = None
try:
self.__info = thrift_try(psu_info_get, attempts=1)
except Exception as e:
if "Canceling" in str(e):
syslog.syslog(syslog.LOG_INFO, "{}".format(e))
finally:
self.__ts = time.time()
return self.__info
return self.__info
@staticmethod
def get_num_psus():
"""