Update lm_sensors and catch specific errors. (#4667)
This updates our copy of the libsensors Python bindings to the most recent upstream copy, which provides proper errors instead of just raising bare Exceptions, and updates our code to catch those errors instead of catching bare exceptions.
Austin S. Hemmelgarn committed
Nov 15, 2018 at 14:19 UTC
9a071dea2d73f663d9d478703c8c2ae85b4096a3
2 files changed
+85
-18
collectors/python.d.plugin/python_modules/third_party/lm_sensors.py
+81
-12
@@ -17,11 +17,79 @@ import ctypes.util
17
_libc = cdll.LoadLibrary(ctypes.util.find_library("c"))
18
# see https://github.com/paroj/sensors.py/issues/1
19
_libc.free.argtypes = [c_void_p]
20
+
21
_hdl = cdll.LoadLibrary(ctypes.util.find_library("sensors"))
22
23
version = c_char_p.in_dll(_hdl, "libsensors_version").value.decode("ascii")
24
25
26
+class SensorsError(Exception):
27
+ pass
28
+
29
+
30
+class ErrorWildcards(SensorsError):
31
+ pass
32
+
33
+
34
+class ErrorNoEntry(SensorsError):
35
+ pass
36
+
37
+
38
+class ErrorAccessRead(SensorsError, PermissionError):
39
+ pass
40
+
41
+
42
+class ErrorKernel(SensorError, OSError):
43
+ pass
44
+
45
+
46
+class ErrorDivZero(SensorError, ZeroDivisionError):
47
+ pass
48
+
49
+
50
+class ErrorChipName(SensorError):
51
+ pass
52
+
53
+
54
+class ErrorBusName(SensorError):
55
+ pass
56
+
57
+
58
+class ErrorParse(SensorError):
59
+ pass
60
+
61
+
62
+class ErrorAccessWrite(SensorError, PermissionError):
63
+ pass
64
+
65
+
66
+class ErrorIO(SensorError, IOError):
67
+ pass
68
+
69
+
70
+class ErrorRecursion(SensorError):
71
+ pass
72
+
73
+
74
+_ERR_MAP = {
75
+ 1: ErrorWildcards,
76
+ 2: ErrorNoEntry,
77
+ 3: ErrorAccessRead,
78
+ 4: ErrorKernel,
79
+ 5: ErrorDivZero,
80
+ 6: ErrorChipName,
81
+ 7: ErrorBusName,
82
+ 8: ErrorParse,
83
+ 9: ErrorAccessWrite,
84
+ 10: ErrorIO,
85
+ 11: ErrorRecursion
86
+}
87
+
88
+
89
+def raise_sensor_error(errno, message=''):
90
+ raise _ERR_MAP[abs(errno)](message)
91
+
92
+
93
class bus_id(Structure):
94
_fields_ = [("type", c_short),
95
("nr", c_short)]
@@ -65,8 +133,8 @@ class subfeature(Structure):
133
_hdl.sensors_get_detected_chips.restype = POINTER(chip_name)
134
_hdl.sensors_get_features.restype = POINTER(feature)
135
_hdl.sensors_get_all_subfeatures.restype = POINTER(subfeature)
68
-_hdl.sensors_get_label.restype = c_void_p # return pointer instead of str so we can free it
69
-_hdl.sensors_get_adapter_name.restype = c_char_p # docs do not say whether to free this or not
136
+_hdl.sensors_get_label.restype = c_void_p # return pointer instead of str so we can free it
137
+_hdl.sensors_get_adapter_name.restype = c_char_p # docs do not say whether to free this or not
138
_hdl.sensors_strerror.restype = c_char_p
139
140
### RAW API ###
@@ -78,8 +146,9 @@ COMPUTE_MAPPING = 4
146
def init(cfg_file=None):
147
file = _libc.fopen(cfg_file.encode("utf-8"), "r") if cfg_file is not None else None
148
81
- if _hdl.sensors_init(file) != 0:
82
- raise Exception("sensors_init failed")
149
+ result = _hdl.sensors_init(file)
150
+ if result != 0:
151
+ raise_sensor_error(result, "sensors_init failed")
152
153
if file is not None:
154
_libc.fclose(file)
@@ -94,7 +163,7 @@ def parse_chip_name(orig_name):
163
err = _hdl.sensors_parse_chip_name(orig_name.encode("utf-8"), byref(ret))
164
165
if err < 0:
97
- raise Exception(strerror(err))
166
+ raise_sensor_error(err, strerror(err))
167
168
return ret
169
@@ -129,7 +198,7 @@ def chip_snprintf_name(chip, buffer_size=200):
198
err = _hdl.sensors_snprintf_chip_name(ret, buffer_size, byref(chip))
199
200
if err < 0:
132
- raise Exception(strerror(err))
201
+ raise_sensor_error(err, strerror(err))
202
203
return ret.value.decode("utf-8")
204
@@ -140,7 +209,7 @@ def do_chip_sets(chip):
209
"""
210
err = _hdl.sensors_do_chip_sets(byref(chip))
211
if err < 0:
143
- raise Exception(strerror(err))
212
+ raise_sensor_error(err, strerror(err))
213
214
215
def get_adapter_name(bus):
@@ -178,7 +247,7 @@ def get_value(chip, subfeature_nr):
247
val = c_double()
248
err = _hdl.sensors_get_value(byref(chip), subfeature_nr, byref(val))
249
if err < 0:
181
- raise Exception(strerror(err))
250
+ raise_sensor_error(err, strerror(err))
251
return val.value
252
253
@@ -189,7 +258,7 @@ def set_value(chip, subfeature_nr, value):
258
val = c_double(value)
259
err = _hdl.sensors_set_value(byref(chip), subfeature_nr, byref(val))
260
if err < 0:
192
- raise Exception(strerror(err))
261
+ raise_sensor_error(err, strerror(err))
262
263
264
### Convenience API ###
@@ -213,7 +282,7 @@ class ChipIterator:
282
if self.match is not None:
283
free_chip_name(self.match)
284
216
- def next(self): # python2 compability
285
+ def next(self): # python2 compability
286
return self.__next__()
287
288
@@ -233,7 +302,7 @@ class FeatureIterator:
302
303
return feature
304
236
- def next(self): # python2 compability
305
+ def next(self): # python2 compability
306
return self.__next__()
307
308
@@ -254,5 +323,5 @@ class SubFeatureIterator:
323
324
return subfeature
325
257
- def next(self): # python2 compability
326
+ def next(self): # python2 compability
327
return self.__next__()
collectors/python.d.plugin/sensors/sensors.chart.py
+4
-6
@@ -108,8 +108,7 @@ class Service(SimpleService):
108
try:
109
val = sensors.get_value(chip, sf.number)
110
break
111
- # TODO: use specific error after upstream is fixed
112
- except Exception:
111
+ except sensors.SensorsError:
112
continue
113
if val is None:
114
continue
@@ -119,7 +118,7 @@ class Service(SimpleService):
118
if val < limit[0] or val > limit[1]:
119
continue
120
data[prefix + '_' + str(feature.name.decode())] = int(val * 1000)
122
- except Exception as error:
121
+ except sensors.SensorsError as error:
122
self.error(error)
123
return None
124
@@ -137,8 +136,7 @@ class Service(SimpleService):
136
for sf in sfi:
137
try:
138
vals.append(sensors.get_value(chip, sf.number))
140
- # TODO: use specific error after upstream is fixed
141
- except Exception as error:
139
+ except sensors.SensorsError as error:
140
self.error('{0}: {1}'.format(sf.name, error))
141
continue
142
if not vals or vals[0] == 0:
@@ -160,7 +158,7 @@ class Service(SimpleService):
158
def check(self):
159
try:
160
sensors.init()
163
- except Exception as error:
161
+ except sensors.SensorsError as error:
162
self.error(error)
163
return False
164