blob: dc747336a2b7cb8534d9e9f1dc1e0f0c6ff9d5d1 [file] [log] [blame]
Brad Bishop179b39b2016-05-12 16:45:57 -04001# Contributors Listed Below - COPYRIGHT 2016
2# [+] International Business Machines Corp.
3#
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14# implied. See the License for the specific language governing
15# permissions and limitations under the License.
16
17import os
18import subprocess
19import dbus
20import dbus.service
21from obmc.dbuslib.bindings import DbusProperties
22
23
24## Abstract class, must subclass
25class SensorValue(DbusProperties):
26 IFACE_NAME = 'org.openbmc.SensorValue'
27
28 def __init__(self, bus, name):
29 self.Set(SensorValue.IFACE_NAME, 'units', "")
30 self.Set(SensorValue.IFACE_NAME, 'error', False)
31
32 @dbus.service.method(
33 IFACE_NAME, in_signature='v', out_signature='')
34 def setValue(self, value):
35 self.Set(SensorValue.IFACE_NAME, 'value', value)
36
37 @dbus.service.method(
38 IFACE_NAME, in_signature='', out_signature='v')
39 def getValue(self):
40 return self.Get(SensorValue.IFACE_NAME, 'value')
41
42
43class SensorThresholds(DbusProperties):
44 IFACE_NAME = 'org.openbmc.SensorThresholds'
45
46 def __init__(self, bus, name):
47 self.Set(
48 SensorThresholds.IFACE_NAME,
49 'thresholds_enabled',
50 False)
51 self.Set(
52 SensorThresholds.IFACE_NAME,
53 'emergency_enabled',
54 False)
55 self.Set(
56 SensorThresholds.IFACE_NAME,
57 'warning_upper',
58 0)
59 self.Set(
60 SensorThresholds.IFACE_NAME,
61 'warning_lower',
62 0)
63 self.Set(
64 SensorThresholds.IFACE_NAME,
65 'critical_upper',
66 0)
67 self.Set(
68 SensorThresholds.IFACE_NAME,
69 'critical_lower',
70 0)
71 self.Set(
72 SensorThresholds.IFACE_NAME,
73 'critical_lower',
74 0)
75 self.Set(
76 SensorThresholds.IFACE_NAME,
77 'threshold_state',
78 "NORMAL")
79 self.Set(
80 SensorThresholds.IFACE_NAME,
81 'worst_threshold_state',
82 "NORMAL")
83
84 @dbus.service.method(
85 IFACE_NAME, in_signature='', out_signature='')
86 def resetThresholdState(self):
87 self.Set(
88 SensorThresholds.IFACE_NAME,
89 'worst_threshold_state',
90 "NORMAL")
91
92 def check_thresholds(self, value):
93 iface = SensorThresholds.IFACE_NAME
94 if (self.Get(iface, 'thresholds_enabled') is False):
95 return False
96 rtn = False
97 current_state = "NORMAL"
98 if (value >= self.properties[iface]['critical_upper']):
99 current_state = "CRITICAL"
100 rtn = True
101 elif (value <= self.properties[iface]['critical_lower']):
102 current_state = "CRITICAL"
103 rtn = True
104 elif (value >= self.properties[iface]['warning_upper']):
105 current_state = "WARNING"
106 rtn = True
107 elif (value <= self.properties[iface]['warning_lower']):
108 current_state = "WARNING"
109 rtn = True
110
111 if self.Get(iface, 'threshold_state') != current_state and \
112 current_state == "CRITICAL" and \
113 self.Get(iface, 'emergency_enabled') is True:
Yi Li3cb85e92016-07-01 16:47:16 +0800114 message = type(self).__name__ + \
115 ' SensorThresholds.check_thresholds(): trigger emergency' + \
116 ' signal, sensor value: ' + str(value)
117 self.Emergency(message)
Brad Bishop179b39b2016-05-12 16:45:57 -0400118
119 self.Set(iface, 'threshold_state', current_state)
120 worst = self.properties[iface]['worst_threshold_state']
121 if (current_state == "CRITICAL" or
122 (current_state == "WARNING" and worst != "CRITICAL")):
123 self.Set(iface, 'worst_threshold_state', current_state)
124
125 return rtn
126
Yi Li3cb85e92016-07-01 16:47:16 +0800127 @dbus.service.signal(IFACE_NAME, signature='s')
128 def Emergency(self, message):
Brad Bishop179b39b2016-05-12 16:45:57 -0400129 pass
130
131
132class VirtualSensor(SensorValue):
133 def __init__(self, bus, name):
134 DbusProperties.__init__(self)
135 SensorValue.__init__(self, bus, name)
136 dbus.service.Object.__init__(self, bus, name)
137
138
139class HwmonSensor(SensorValue, SensorThresholds):
140 IFACE_NAME = 'org.openbmc.HwmonSensor'
141
142 def __init__(self, bus, name):
143 DbusProperties.__init__(self)
144 SensorValue.__init__(self, bus, name)
145 SensorThresholds.__init__(self, bus, name)
146 self.Set(HwmonSensor.IFACE_NAME, 'scale', 1)
147 self.Set(HwmonSensor.IFACE_NAME, 'offset', 0)
148 self.Set(HwmonSensor.IFACE_NAME, 'filename', '')
149 self.value_dirty = False
150
151 # need to cache value to know if changed
152 self.value = None
153 dbus.service.Object.__init__(self, bus, name)
154
155 @dbus.service.method(
156 SensorValue.IFACE_NAME, in_signature='v', out_signature='')
157 def setValue(self, value):
158 self.value_dirty = True
159 SensorValue.setValue(self, value)
160
161 ## Called by sensor process to update value from polling
162 ## if returns not None, then sensor process will update hwmon value
163 @dbus.service.method(
164 IFACE_NAME, in_signature='v', out_signature='(bv)')
165 def setByPoll(self, value):
166 scale = self.properties[HwmonSensor.IFACE_NAME]['scale']
167 offset = self.properties[HwmonSensor.IFACE_NAME]['offset']
Edward A. Jamesecf8bd82016-08-15 16:22:25 -0500168 try:
169 adjust = self.properties[HwmonSensor.IFACE_NAME]['adjust']
170 if adjust == 0:
171 adjust = 1
172 except:
173 adjust = 1
174
Brad Bishop179b39b2016-05-12 16:45:57 -0400175 if self.value_dirty:
176 ## new value externally set, so just return to hwmon
177 ## process to write value
178 self.value_dirty = False
Edward A. Jamesecf8bd82016-08-15 16:22:25 -0500179 val = int((
Brad Bishop179b39b2016-05-12 16:45:57 -0400180 self.properties[SensorValue.IFACE_NAME]['value']
Edward A. Jamesecf8bd82016-08-15 16:22:25 -0500181 - offset) * adjust)
Brad Bishop179b39b2016-05-12 16:45:57 -0400182 return [True, val]
183 else:
Edward A. Jamesecf8bd82016-08-15 16:22:25 -0500184 # Keep the val as integer. adjust may be floating point
185 val = int(value/adjust + offset)
Brad Bishop179b39b2016-05-12 16:45:57 -0400186 if (val != self.value):
187 SensorValue.setValue(self, val)
Edward A. Jamesecf8bd82016-08-15 16:22:25 -0500188 # scale the value to check threshold
189 self.check_thresholds(val * (10 ** scale))
Brad Bishop179b39b2016-05-12 16:45:57 -0400190 self.value = val
191
192 return [False, 0]
193
194
195CONTROL_IFACE = 'org.openbmc.Control'
196
197
198class PowerCap(VirtualSensor):
199 def __init__(self, bus, name):
200 VirtualSensor.__init__(self, bus, name)
201 SensorValue.setValue(self, 0)
202 self.sysfs_attr = "/sys/class/hwmon/hwmon3/user_powercap"
203
204 ##override setValue method
205 @dbus.service.method(
206 SensorValue.IFACE_NAME, in_signature='v', out_signature='')
207 def setValue(self, value):
208 try:
209 cmd_str = "echo "+str(value)+" > "+self.sysfs_attr
210 ret = subprocess.check_output(cmd_str, shell=True)
211 except subprocess.CalledProcessError as powerexc:
212 print "Set PowerCap Error", powerexc.returncode,
213 powerexc.output
214 return
215 print "Set PowerCap: ", value
216 SensorValue.setValue(self, value)
217
218
219class BootProgressSensor(VirtualSensor):
220 def __init__(self, bus, name):
221 VirtualSensor.__init__(self, bus, name)
222 self.setValue("Off")
223 bus.add_signal_receiver(
224 self.SystemStateHandler, signal_name="GotoSystemState")
225
226 def SystemStateHandler(self, state):
227 if (state == "HOST_POWERED_OFF"):
228 self.setValue("Off")
229
230 ##override setValue method
231 @dbus.service.method(
232 SensorValue.IFACE_NAME,
233 in_signature='v', out_signature='')
234 def setValue(self, value):
235 SensorValue.setValue(self, value)
236 if (value == "FW Progress, Starting OS"):
237 self.GotoSystemState("HOST_BOOTED")
Yi Li57e3bf92016-09-08 17:58:00 +0800238 self.BootProgress(value)
Brad Bishop179b39b2016-05-12 16:45:57 -0400239
240 @dbus.service.signal(CONTROL_IFACE, signature='s')
241 def GotoSystemState(self, state):
242 pass
243
Yi Li57e3bf92016-09-08 17:58:00 +0800244 @dbus.service.signal(CONTROL_IFACE, signature='s')
245 def BootProgress(self, state):
246 pass
247
Brad Bishop179b39b2016-05-12 16:45:57 -0400248
249class OccStatusSensor(VirtualSensor):
250 def __init__(self, bus, name, sysfs=None):
251 ## default path. can be override
252 if sysfs is None:
253 self.sysfs_attr = "/sys/class/i2c-adapter/i2c-3/3-0050/online"
254 else:
255 self.sysfs_attr = sysfs
256 VirtualSensor.__init__(self, bus, name)
257 self.setValue("Disabled")
258 bus.add_signal_receiver(
259 self.SystemStateHandler, signal_name="GotoSystemState")
260
261 def SystemStateHandler(self, state):
262 if (state == "HOST_POWERED_OFF"):
263 self.setValue("Disabled")
264
265 ##override setValue method
266 @dbus.service.method(
267 SensorValue.IFACE_NAME, in_signature='v', out_signature='')
268 def setValue(self, value):
269 if (value == "Enabled"):
270 print "Installing OCC device"
271 os.system("echo 1 > " + self.sysfs_attr)
272 else:
273 print "Deleting OCC device"
274 os.system("echo 0 > " + self.sysfs_attr)
275 SensorValue.setValue(self, value)
276
277 @dbus.service.signal(CONTROL_IFACE, signature='s')
278 def GotoSystemState(self, state):
279 pass
280
281
282class BootCountSensor(VirtualSensor):
283 def __init__(self, bus, name):
284 VirtualSensor.__init__(self, bus, name)
285 self.setValue(2)
286
287
288class OperatingSystemStatusSensor(VirtualSensor):
289 def __init__(self, bus, name):
290 VirtualSensor.__init__(self, bus, name)
291 self.setValue("Off")
292 bus.add_signal_receiver(
293 self.SystemStateHandler, signal_name="GotoSystemState")
294
295 def SystemStateHandler(self, state):
296 if (state == "HOST_POWERED_OFF"):
297 self.setValue("Off")