8
8
#
9
9
#############################################################################
10
10
11
- import os .path
12
-
13
11
try :
12
+ import os .path
14
13
from sonic_platform_base .psu_base import PsuBase
14
+ from sonic_daemon_base .daemon_base import Logger
15
15
from sonic_platform .fan import Fan
16
16
except ImportError as e :
17
17
raise ImportError (str (e ) + "- required module not found" )
18
18
19
+ # Global logger class instance
20
+ SYSLOG_IDENTIFIER = "mlnx-psu-api"
21
+ logger = Logger (SYSLOG_IDENTIFIER )
22
+
19
23
psu_list = []
20
24
25
+ PSU_CURRENT = "current"
26
+ PSU_VOLTAGE = "voltage"
27
+ PSU_POWER = "power"
28
+
29
+ # SKUs with unplugable PSUs:
30
+ # 1. don't have psuX_status and should be treated as always present
31
+ # 2. don't have voltage, current and power values
32
+ hwsku_dict_with_unplugable_psu = ['ACS-MSN2010' , 'ACS-MSN2100' ]
33
+
34
+ # in most SKUs the file psuX_curr, psuX_volt and psuX_power contain current, voltage and power data respectively.
35
+ # but there are exceptions which will be handled by the following dictionary
36
+ hwsku_dict_psu = {'ACS-MSN3700' : 1 , 'ACS-MSN3700C' : 1 , 'ACS-MSN3800' : 1 }
37
+ psu_profile_list = [
38
+ # default filename convention
39
+ {
40
+ PSU_CURRENT : "power/psu{}_curr" ,
41
+ PSU_VOLTAGE : "power/psu{}_volt" ,
42
+ PSU_POWER : "power/psu{}_power"
43
+ },
44
+ # for 3700, 3700c, 3800
45
+ {
46
+ PSU_CURRENT : "power/psu{}_curr" ,
47
+ PSU_VOLTAGE : "power/psu{}_volt_out2" ,
48
+ PSU_POWER : "power/psu{}_power"
49
+ }
50
+ ]
51
+
21
52
class Psu (PsuBase ):
22
53
"""Platform-specific Psu class"""
23
- def __init__ (self , psu_index ):
54
+ def __init__ (self , psu_index , sku ):
24
55
global psu_list
25
56
PsuBase .__init__ (self )
26
57
# PSU is 1-based on Mellanox platform
27
58
self .index = psu_index + 1
28
59
psu_list .append (self .index )
29
- self .psu_path = "/var/run/hw-management/thermal/"
30
- self .psu_oper_status = "psu{}_pwr_status" .format (self .index )
31
- self .psu_presence = "psu{}_status" .format (self .index )
32
- if os .path .exists (os .path .join (self .psu_path , self .psu_presence )):
33
- self .presence_file_exists = True
60
+ self .psu_path = "/var/run/hw-management/"
61
+ psu_oper_status = "thermal/psu{}_pwr_status" .format (self .index )
62
+ #psu_oper_status should always be present for all SKUs
63
+ self .psu_oper_status = os .path .join (self .psu_path , psu_oper_status )
64
+
65
+ if sku in hwsku_dict_psu :
66
+ filemap = psu_profile_list [hwsku_dict_psu [sku ]]
67
+ else :
68
+ filemap = psu_profile_list [0 ]
69
+
70
+ if sku in hwsku_dict_with_unplugable_psu :
71
+ self .always_presence = True
72
+ self .psu_voltage = None
73
+ self .psu_current = None
74
+ self .psu_power = None
75
+ self .psu_presence = None
34
76
else :
35
- self .presence_file_exists = False
77
+ self .always_presence = False
78
+ psu_voltage = filemap [PSU_VOLTAGE ].format (self .index )
79
+ psu_voltage = os .path .join (self .psu_path , psu_voltage )
80
+ self .psu_voltage = psu_voltage
81
+
82
+ psu_current = filemap [PSU_CURRENT ].format (self .index )
83
+ psu_current = os .path .join (self .psu_path , psu_current )
84
+ self .psu_current = psu_current
85
+
86
+ psu_power = filemap [PSU_POWER ].format (self .index )
87
+ psu_power = os .path .join (self .psu_path , psu_power )
88
+ self .psu_power = psu_power
89
+
90
+ psu_presence = "thermal/psu{}_status" .format (self .index )
91
+ psu_presence = os .path .join (self .psu_path , psu_presence )
92
+ self .psu_presence = psu_presence
93
+
36
94
fan = Fan (psu_index , psu_index , True )
37
95
if fan .get_presence ():
38
96
self ._fan = fan
39
97
40
- def get_status (self ):
98
+ def _read_generic_file (self , filename , len ):
99
+ """
100
+ Read a generic file, returns the contents of the file
101
+ """
102
+ result = 0
103
+ try :
104
+ with open (filename , 'r' ) as fileobj :
105
+ result = int (fileobj .read ())
106
+ except Exception as e :
107
+ logger .log_info ("Fail to read file {} due to {}" .format (filename , repr (e )))
108
+ return result
109
+
110
+ def get_powergood_status (self ):
41
111
"""
42
112
Retrieves the operational status of power supply unit (PSU) defined
43
113
44
114
Returns:
45
115
bool: True if PSU is operating properly, False if not
46
116
"""
47
- status = 0
48
- try :
49
- with open (os .path .join (self .psu_path , self .psu_oper_status ), 'r' ) as power_status :
50
- status = int (power_status .read ())
51
- except (ValueError , IOError ):
52
- status = 0
117
+ status = self ._read_generic_file (os .path .join (self .psu_path , self .psu_oper_status ), 0 )
53
118
54
119
return status == 1
55
120
@@ -60,15 +125,48 @@ def get_presence(self):
60
125
Returns:
61
126
bool: True if PSU is present, False if not
62
127
"""
63
- status = 0
64
- if self .presence_file_exists :
65
- try :
66
- with open (os .path .join (self .psu_path , self .psu_presence ), 'r' ) as presence_status :
67
- status = int (presence_status .read ())
68
- except (ValueError , IOError ):
69
- status = 0
128
+ if self .always_presence :
129
+ return self .always_presence
70
130
else :
71
- status = self .index in psu_list
131
+ status = self ._read_generic_file (self .psu_presence , 0 )
132
+ return status == 1
72
133
73
- return status == 1
134
+ def get_voltage (self ):
135
+ """
136
+ Retrieves current PSU voltage output
74
137
138
+ Returns:
139
+ A float number, the output voltage in volts,
140
+ e.g. 12.1
141
+ """
142
+ if self .psu_voltage is not None and self .get_powergood_status ():
143
+ voltage = self ._read_generic_file (self .psu_voltage , 0 )
144
+ return float (voltage ) / 1000
145
+ else :
146
+ return None
147
+
148
+ def get_current (self ):
149
+ """
150
+ Retrieves present electric current supplied by PSU
151
+
152
+ Returns:
153
+ A float number, the electric current in amperes, e.g 15.4
154
+ """
155
+ if self .psu_current is not None and self .get_powergood_status ():
156
+ amperes = self ._read_generic_file (self .psu_current , 0 )
157
+ return float (amperes ) / 1000
158
+ else :
159
+ return None
160
+
161
+ def get_power (self ):
162
+ """
163
+ Retrieves current energy supplied by PSU
164
+
165
+ Returns:
166
+ A float number, the power in watts, e.g. 302.6
167
+ """
168
+ if self .psu_power is not None and self .get_powergood_status ():
169
+ power = self ._read_generic_file (self .psu_power , 0 )
170
+ return float (power ) / 1000000
171
+ else :
172
+ return None
0 commit comments