|
1 | 1 | #!/usr/bin/env python2 |
2 | 2 |
|
3 | 3 | """ |
4 | | - Psud |
| 4 | + psud |
5 | 5 | PSU information update daemon for SONiC |
6 | 6 | This daemon will loop to collect PSU related information and then write the information to state DB. |
7 | 7 | Currently it is implemented based on old plugins rather than new platform APIs. So the PSU information just |
|
10 | 10 | """ |
11 | 11 |
|
12 | 12 | try: |
13 | | - import getopt |
14 | | - import os |
15 | | - import imp |
16 | | - import signal |
17 | | - import subprocess |
18 | 13 | import sys |
19 | | - import syslog |
20 | 14 | import time |
21 | 15 | from swsscommon import swsscommon |
| 16 | + from sonic_daemon_base.daemon_base import DaemonBase |
22 | 17 | except ImportError, e: |
23 | 18 | raise ImportError (str(e) + " - required module not found") |
24 | 19 |
|
25 | 20 | #============================= Constants ============================= |
26 | 21 |
|
27 | | -VERSION = '1.0' |
28 | | - |
29 | | -SYSLOG_IDENTIFIER = os.path.basename(__file__) |
30 | 22 | PLATFORM_SPECIFIC_MODULE_NAME = "psuutil" |
31 | 23 | PLATFORM_SPECIFIC_CLASS_NAME = "PsuUtil" |
32 | 24 |
|
33 | | -# Platform root directory inside docker |
34 | | -PLATFORM_ROOT_DOCKER = "/usr/share/sonic/platform" |
35 | | -SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen' |
36 | | -HWSKU_KEY = 'DEVICE_METADATA.localhost.hwsku' |
37 | | -PLATFORM_KEY = 'DEVICE_METADATA.localhost.platform' |
38 | | - |
39 | | -# Global platform-specific psuutil class instance |
40 | | -platform_psuutil = None |
41 | | - |
42 | | -REDIS_HOSTNAME = "localhost" |
43 | | -REDIS_PORT = 6379 |
44 | | -REDIS_TIMEOUT_MSECS = 0 |
45 | | - |
46 | 25 | PSU_INFO_UPDATE_PERIOD_SECS = 3 |
47 | 26 |
|
48 | | -#========================== Syslog wrappers ========================== |
49 | | - |
50 | | -def log_info(msg, also_print_to_console=False): |
51 | | - syslog.openlog(SYSLOG_IDENTIFIER) |
52 | | - syslog.syslog(syslog.LOG_INFO, msg) |
53 | | - syslog.closelog() |
54 | | - |
55 | | - if also_print_to_console: |
56 | | - print msg |
57 | | - |
58 | | -def log_warning(msg, also_print_to_console=False): |
59 | | - syslog.openlog(SYSLOG_IDENTIFIER) |
60 | | - syslog.syslog(syslog.LOG_WARNING, msg) |
61 | | - syslog.closelog() |
62 | | - |
63 | | - if also_print_to_console: |
64 | | - print msg |
65 | | - |
66 | | -def log_error(msg, also_print_to_console=False): |
67 | | - syslog.openlog(SYSLOG_IDENTIFIER) |
68 | | - syslog.syslog(syslog.LOG_ERR, msg) |
69 | | - syslog.closelog() |
70 | | - |
71 | | - if also_print_to_console: |
72 | | - print msg |
73 | | - |
74 | | -#========================== Signal Handling ========================== |
75 | | - |
76 | | -def signal_handler(sig, frame): |
77 | | - if sig == signal.SIGHUP: |
78 | | - log_info("Caught SIGHUP - ignoring...") |
79 | | - return |
80 | | - elif sig == signal.SIGINT: |
81 | | - log_info("Caught SIGINT - exiting...") |
82 | | - sys.exit(128 + sig) |
83 | | - elif sig == signal.SIGTERM: |
84 | | - log_info("Caught SIGTERM - exiting...") |
85 | | - sys.exit(128 + sig) |
86 | | - else: |
87 | | - log_warning("Caught unhandled signal '" + sig + "'") |
88 | | - return |
89 | | - |
90 | 27 | #============ Functions to load platform-specific classes ============ |
91 | 28 |
|
92 | | -# Returns platform and HW SKU |
93 | | -def get_platform_and_hwsku(): |
94 | | - try: |
95 | | - proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-H', '-v', PLATFORM_KEY], |
96 | | - stdout=subprocess.PIPE, |
97 | | - shell=False, |
98 | | - stderr=subprocess.STDOUT) |
99 | | - stdout = proc.communicate()[0] |
100 | | - proc.wait() |
101 | | - platform = stdout.rstrip('\n') |
102 | | - |
103 | | - proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-d', '-v', HWSKU_KEY], |
104 | | - stdout=subprocess.PIPE, |
105 | | - shell=False, |
106 | | - stderr=subprocess.STDOUT) |
107 | | - stdout = proc.communicate()[0] |
108 | | - proc.wait() |
109 | | - hwsku = stdout.rstrip('\n') |
110 | | - except OSError, e: |
111 | | - raise OSError("Cannot detect platform") |
112 | | - |
113 | | - return (platform, hwsku) |
114 | | - |
115 | | -# Loads platform specific psuutil module from source |
116 | | -def load_platform_psuutil(): |
117 | | - global platform_psuutil |
118 | | - |
119 | | - # Get platform and hwsku |
120 | | - (platform, hwsku) = get_platform_and_hwsku() |
121 | | - |
122 | | - # Load platform module from source |
123 | | - platform_path = PLATFORM_ROOT_DOCKER |
124 | | - hwsku_path = "/".join([platform_path, hwsku]) |
125 | | - |
126 | | - try: |
127 | | - module_file = "/".join([platform_path, "plugins", PLATFORM_SPECIFIC_MODULE_NAME + ".py"]) |
128 | | - module = imp.load_source(PLATFORM_SPECIFIC_MODULE_NAME, module_file) |
129 | | - except IOError, e: |
130 | | - log_error("Failed to load platform module '%s': %s" % (PLATFORM_SPECIFIC_MODULE_NAME, str(e)), True) |
131 | | - return -1 |
132 | | - |
133 | | - try: |
134 | | - platform_psuutil_class = getattr(module, PLATFORM_SPECIFIC_CLASS_NAME) |
135 | | - platform_psuutil = platform_psuutil_class() |
136 | | - except AttributeError, e: |
137 | | - log_error("Failed to instantiate '%s' class: %s" % (PLATFORM_SPECIFIC_CLASS_NAME, str(e)), True) |
138 | | - return -2 |
139 | | - |
140 | | - return 0 |
141 | | - |
142 | | -def psu_db_update(psu_tbl, num_psus): |
| 29 | +def psu_db_update(psuutil, psu_tbl, num_psus): |
143 | 30 | for psu_index in range(1, num_psus + 1): |
144 | 31 | fvs = swsscommon.FieldValuePairs([('presence', |
145 | | - 'true' if platform_psuutil.get_psu_presence(psu_index) else 'false'), |
| 32 | + 'true' if psuutil.get_psu_presence(psu_index) else 'false'), |
146 | 33 | ('status', |
147 | | - 'true' if platform_psuutil.get_psu_status(psu_index) else 'false')]) |
| 34 | + 'true' if psuutil.get_psu_status(psu_index) else 'false')]) |
148 | 35 | psu_tbl.set("PSU {}".format(psu_index), fvs) |
149 | 36 |
|
150 | 37 | #=============================== Main ================================ |
151 | 38 |
|
152 | 39 | def main(): |
153 | | - log_info("Starting up...") |
154 | | - |
155 | | - # Register our signal handlers |
156 | | - signal.signal(signal.SIGHUP, signal_handler) |
157 | | - signal.signal(signal.SIGINT, signal_handler) |
158 | | - signal.signal(signal.SIGTERM, signal_handler) |
| 40 | + psud_util = DaemonBase() |
| 41 | + if not psud_util: |
| 42 | + print "Failed to load psu daemon utilities" |
| 43 | + sys.exit(1) |
159 | 44 |
|
160 | 45 | # Load platform-specific psuutil class |
161 | | - err = load_platform_psuutil() |
162 | | - if err != 0: |
163 | | - log_error("failed to load psuutil") |
| 46 | + platform_psuutil = psud_util.load_platform_util(PLATFORM_SPECIFIC_MODULE_NAME, PLATFORM_SPECIFIC_CLASS_NAME) |
| 47 | + if not platform_psuutil: |
| 48 | + psud_util.log_error("failed to load psuutil") |
164 | 49 | sys.exit(1) |
165 | 50 |
|
166 | 51 | state_db = swsscommon.DBConnector(swsscommon.STATE_DB, |
167 | | - REDIS_HOSTNAME, |
168 | | - REDIS_PORT, |
169 | | - REDIS_TIMEOUT_MSECS) |
| 52 | + psud_util.redis_hostname, |
| 53 | + psud_util.redis_port, |
| 54 | + psud_util.redis_timeout_msecs) |
170 | 55 | psu_tbl = swsscommon.Table(state_db, "PSU_INFO") |
171 | 56 | chassis_tbl = swsscommon.Table(state_db, "CHASSIS_INFO") |
172 | 57 | num_psus = platform_psuutil.get_num_psus() |
173 | 58 | fvs = swsscommon.FieldValuePairs([('num_psus', str(num_psus))]) |
174 | 59 | chassis_tbl.set('chassis 1', fvs) |
175 | 60 |
|
176 | 61 | # Start main loop to listen to the PSU change event. |
177 | | - log_info("Start main loop") |
| 62 | + psud_util.log_info("Start main loop") |
178 | 63 | while True: |
179 | | - psu_db_update(psu_tbl, num_psus) |
| 64 | + psu_db_update(platform_psuutil, psu_tbl, num_psus) |
180 | 65 | time.sleep(PSU_INFO_UPDATE_PERIOD_SECS) |
181 | 66 |
|
182 | 67 | # Clean all the information from DB and then exit |
183 | 68 | for psu_index in range(1, num_psus + 1): |
184 | 69 | psu_tbl._del("PSU {}".format(psu_index)) |
185 | 70 | chassis_tbl._del('chassis 1') |
186 | | - log_error("Error: return error from psu daemon, exiting...") |
187 | 71 | return 1 |
188 | 72 |
|
189 | 73 | if __name__ == '__main__': |
|
0 commit comments