Skip to content

Commit 9bb0a7f

Browse files
Andriy KokhanTaras Keryk
Andriy Kokhan
and
Taras Keryk
authored
[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 (edge-core#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>
1 parent d08fcc9 commit 9bb0a7f

File tree

3 files changed

+89
-3
lines changed

3 files changed

+89
-3
lines changed

platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/component.py

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import json
77
from collections import OrderedDict
88
from sonic_py_common import device_info
9+
from platform_utils import limit_execution_time
910

1011
except ImportError as e:
1112
raise ImportError(str(e) + "- required module not found")
@@ -24,6 +25,7 @@ def get_bios_version():
2425
except subprocess.CalledProcessError as e:
2526
raise RuntimeError("Failed to get BIOS version")
2627

28+
@limit_execution_time(1)
2729
def get_bmc_version():
2830
"""
2931
Retrieves the firmware version of the BMC

platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/platform_utils.py

+59-1
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@
33
try:
44
import os
55
import subprocess
6+
import signal
7+
from functools import wraps
68

79
except ImportError as e:
810
raise ImportError(str(e) + "- required module not found")
911

1012
def file_create(path, mode=None):
13+
"""
14+
Ensure that file is created with the appropriate permissions
15+
Args:
16+
path: full path of a file
17+
mode: file permission in octal representation
18+
"""
1119
def run_cmd(cmd):
1220
if os.geteuid() != 0:
1321
cmd.insert(0, 'sudo')
@@ -18,5 +26,55 @@ def run_cmd(cmd):
1826
run_cmd(['mkdir', '-p', file_path])
1927
if not os.path.isfile(path):
2028
run_cmd(['touch', path])
21-
if (mode is not None):
29+
if (mode is not None):
2230
run_cmd(['chmod', mode, path])
31+
32+
def cancel_on_sigterm(func):
33+
"""
34+
Wrapper for a function which has to be cancel on SIGTERM
35+
"""
36+
@wraps(func)
37+
def wrapper(*args, **kwargs):
38+
def handler(sig, frame):
39+
if sigterm_handler:
40+
sigterm_handler(sig, frame)
41+
raise Exception("Canceling {}() execution...".format(func.__name__))
42+
43+
sigterm_handler = signal.getsignal(signal.SIGTERM)
44+
signal.signal(signal.SIGTERM, handler)
45+
result = None
46+
try:
47+
result = func(*args, **kwargs)
48+
finally:
49+
signal.signal(signal.SIGTERM, sigterm_handler)
50+
return result
51+
return wrapper
52+
53+
def limit_execution_time(execution_time_secs: int):
54+
"""
55+
Wrapper for a function whose execution time must be limited
56+
Args:
57+
execution_time_secs: maximum execution time in seconds,
58+
after which the function execution will be stopped
59+
"""
60+
def wrapper(func):
61+
@wraps(func)
62+
def execution_func(*args, **kwargs):
63+
def handler(sig, frame):
64+
if sigalrm_handler:
65+
sigalrm_handler(sig, frame)
66+
raise Exception("Canceling {}() execution...".format(func.__name__))
67+
68+
sigalrm_handler = signal.getsignal(signal.SIGALRM)
69+
signal.signal(signal.SIGALRM, handler)
70+
signal.alarm(execution_time_secs)
71+
result = None
72+
try:
73+
result = func(*args, **kwargs)
74+
finally:
75+
signal.alarm(0)
76+
77+
return result
78+
return execution_func
79+
return wrapper
80+

platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/psu.py

+28-2
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,26 @@
44
import os
55
import sys
66
import time
7+
import signal
8+
import syslog
79

810
sys.path.append(os.path.dirname(__file__))
911

1012
from .platform_thrift_client import thrift_try
1113

1214
from sonic_platform_base.psu_base import PsuBase
15+
from platform_utils import cancel_on_sigterm
16+
1317
except ImportError as e:
1418
raise ImportError (str(e) + "- required module not found")
1519

1620
class Psu(PsuBase):
1721
"""Platform-specific PSU class"""
1822

23+
sigterm = False
24+
sigterm_default_handler = None
25+
cls_inited = False
26+
1927
def __init__(self, index):
2028
PsuBase.__init__(self)
2129
self.__index = index
@@ -24,6 +32,21 @@ def __init__(self, index):
2432
# STUB IMPLEMENTATION
2533
self.color = ""
2634

35+
syslog.syslog(syslog.LOG_INFO, "Created PSU #{} instance".format(self.__index))
36+
if not Psu.cls_inited:
37+
Psu.sigterm_default_handler = signal.getsignal(signal.SIGTERM)
38+
signal.signal(signal.SIGTERM, Psu.signal_handler)
39+
if Psu.sigterm_default_handler:
40+
syslog.syslog(syslog.LOG_INFO, "Default SIGTERM handler overridden!!")
41+
Psu.cls_inited = True
42+
43+
@classmethod
44+
def signal_handler(cls, sig, frame):
45+
if cls.sigterm_default_handler:
46+
cls.sigterm_default_handler(sig, frame)
47+
syslog.syslog(syslog.LOG_INFO, "Canceling PSU platform API calls...")
48+
cls.sigterm = True
49+
2750
'''
2851
Units of returned info object values:
2952
vin - V
@@ -33,20 +56,23 @@ def __init__(self, index):
3356
fspeed - RPM
3457
'''
3558
def __info_get(self):
59+
@cancel_on_sigterm
3660
def psu_info_get(client):
3761
return client.pltfm_mgr.pltfm_mgr_pwr_supply_info_get(self.__index)
3862

3963
# Update cache once per 2 seconds
40-
if self.__ts + 2 < time.time():
64+
if self.__ts + 2 < time.time() and not Psu.sigterm:
4165
self.__info = None
4266
try:
4367
self.__info = thrift_try(psu_info_get, attempts=1)
68+
except Exception as e:
69+
if "Canceling" in str(e):
70+
syslog.syslog(syslog.LOG_INFO, "{}".format(e))
4471
finally:
4572
self.__ts = time.time()
4673
return self.__info
4774
return self.__info
4875

49-
5076
@staticmethod
5177
def get_num_psus():
5278
"""

0 commit comments

Comments
 (0)