blob: e92385912b2cc9d4d433fd841abf041c59a970b4 [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:
114 self.Emergency()
115
116 self.Set(iface, 'threshold_state', current_state)
117 worst = self.properties[iface]['worst_threshold_state']
118 if (current_state == "CRITICAL" or
119 (current_state == "WARNING" and worst != "CRITICAL")):
120 self.Set(iface, 'worst_threshold_state', current_state)
121
122 return rtn
123
124 @dbus.service.signal(IFACE_NAME, signature='')
125 def Emergency(self):
126 pass
127
128
129class VirtualSensor(SensorValue):
130 def __init__(self, bus, name):
131 DbusProperties.__init__(self)
132 SensorValue.__init__(self, bus, name)
133 dbus.service.Object.__init__(self, bus, name)
134
135
136class HwmonSensor(SensorValue, SensorThresholds):
137 IFACE_NAME = 'org.openbmc.HwmonSensor'
138
139 def __init__(self, bus, name):
140 DbusProperties.__init__(self)
141 SensorValue.__init__(self, bus, name)
142 SensorThresholds.__init__(self, bus, name)
143 self.Set(HwmonSensor.IFACE_NAME, 'scale', 1)
144 self.Set(HwmonSensor.IFACE_NAME, 'offset', 0)
145 self.Set(HwmonSensor.IFACE_NAME, 'filename', '')
146 self.value_dirty = False
147
148 # need to cache value to know if changed
149 self.value = None
150 dbus.service.Object.__init__(self, bus, name)
151
152 @dbus.service.method(
153 SensorValue.IFACE_NAME, in_signature='v', out_signature='')
154 def setValue(self, value):
155 self.value_dirty = True
156 SensorValue.setValue(self, value)
157
158 ## Called by sensor process to update value from polling
159 ## if returns not None, then sensor process will update hwmon value
160 @dbus.service.method(
161 IFACE_NAME, in_signature='v', out_signature='(bv)')
162 def setByPoll(self, value):
163 scale = self.properties[HwmonSensor.IFACE_NAME]['scale']
164 offset = self.properties[HwmonSensor.IFACE_NAME]['offset']
165 if self.value_dirty:
166 ## new value externally set, so just return to hwmon
167 ## process to write value
168 self.value_dirty = False
169 val = (
170 self.properties[SensorValue.IFACE_NAME]['value']
171 - offset) * scale
172 return [True, val]
173 else:
174 # Keep the val as integer. scale may be floating point
175 val = int(value/scale + offset)
176 if (val != self.value):
177 SensorValue.setValue(self, val)
178 self.check_thresholds(val)
179 self.value = val
180
181 return [False, 0]
182
183
184CONTROL_IFACE = 'org.openbmc.Control'
185
186
187class PowerCap(VirtualSensor):
188 def __init__(self, bus, name):
189 VirtualSensor.__init__(self, bus, name)
190 SensorValue.setValue(self, 0)
191 self.sysfs_attr = "/sys/class/hwmon/hwmon3/user_powercap"
192
193 ##override setValue method
194 @dbus.service.method(
195 SensorValue.IFACE_NAME, in_signature='v', out_signature='')
196 def setValue(self, value):
197 try:
198 cmd_str = "echo "+str(value)+" > "+self.sysfs_attr
199 ret = subprocess.check_output(cmd_str, shell=True)
200 except subprocess.CalledProcessError as powerexc:
201 print "Set PowerCap Error", powerexc.returncode,
202 powerexc.output
203 return
204 print "Set PowerCap: ", value
205 SensorValue.setValue(self, value)
206
207
208class BootProgressSensor(VirtualSensor):
209 def __init__(self, bus, name):
210 VirtualSensor.__init__(self, bus, name)
211 self.setValue("Off")
212 bus.add_signal_receiver(
213 self.SystemStateHandler, signal_name="GotoSystemState")
214
215 def SystemStateHandler(self, state):
216 if (state == "HOST_POWERED_OFF"):
217 self.setValue("Off")
218
219 ##override setValue method
220 @dbus.service.method(
221 SensorValue.IFACE_NAME,
222 in_signature='v', out_signature='')
223 def setValue(self, value):
224 SensorValue.setValue(self, value)
225 if (value == "FW Progress, Starting OS"):
226 self.GotoSystemState("HOST_BOOTED")
227
228 @dbus.service.signal(CONTROL_IFACE, signature='s')
229 def GotoSystemState(self, state):
230 pass
231
232
233class OccStatusSensor(VirtualSensor):
234 def __init__(self, bus, name, sysfs=None):
235 ## default path. can be override
236 if sysfs is None:
237 self.sysfs_attr = "/sys/class/i2c-adapter/i2c-3/3-0050/online"
238 else:
239 self.sysfs_attr = sysfs
240 VirtualSensor.__init__(self, bus, name)
241 self.setValue("Disabled")
242 bus.add_signal_receiver(
243 self.SystemStateHandler, signal_name="GotoSystemState")
244
245 def SystemStateHandler(self, state):
246 if (state == "HOST_POWERED_OFF"):
247 self.setValue("Disabled")
248
249 ##override setValue method
250 @dbus.service.method(
251 SensorValue.IFACE_NAME, in_signature='v', out_signature='')
252 def setValue(self, value):
253 if (value == "Enabled"):
254 print "Installing OCC device"
255 os.system("echo 1 > " + self.sysfs_attr)
256 else:
257 print "Deleting OCC device"
258 os.system("echo 0 > " + self.sysfs_attr)
259 SensorValue.setValue(self, value)
260
261 @dbus.service.signal(CONTROL_IFACE, signature='s')
262 def GotoSystemState(self, state):
263 pass
264
265
266class BootCountSensor(VirtualSensor):
267 def __init__(self, bus, name):
268 VirtualSensor.__init__(self, bus, name)
269 self.setValue(2)
270
271
272class OperatingSystemStatusSensor(VirtualSensor):
273 def __init__(self, bus, name):
274 VirtualSensor.__init__(self, bus, name)
275 self.setValue("Off")
276 bus.add_signal_receiver(
277 self.SystemStateHandler, signal_name="GotoSystemState")
278
279 def SystemStateHandler(self, state):
280 if (state == "HOST_POWERED_OFF"):
281 self.setValue("Off")