hddtemp: correctly parse /disk/by-id + refactor
lgz committed
Jun 18, 2018 at 20:31 UTC
2f2ba9c85050abdddd65317663b7a5c63287ff99
1 file changed
+52
-58
python.d/hddtemp.chart.py
+52
-58
@@ -1,27 +1,16 @@
1
# -*- coding: utf-8 -*-
2
# Description: hddtemp netdata python.d module
3
# Author: Pawel Krupa (paulfantom)
4
+# Author: Ilya Mashchenko (l2isbad)
5
# SPDX-License-Identifier: GPL-3.0+
6
7
7
-import os
8
+import re
9
+
10
from copy import deepcopy
11
12
from bases.FrameworkServices.SocketService import SocketService
13
12
-# default module values (can be overridden per job in `config`)
13
-#update_every = 2
14
-priority = 60000
15
-retries = 60
16
-
17
-# default job configuration (overridden by python.d.plugin)
18
-# config = {'local': {
19
-# 'update_every': update_every,
20
-# 'retries': retries,
21
-# 'priority': priority,
22
-# 'host': 'localhost',
23
-# 'port': 7634
24
-# }}
14
15
ORDER = ['temperatures']
16
@@ -32,6 +21,18 @@ CHARTS = {
21
# lines are created dynamically in `check()` method
22
]}}
23
24
+RE = re.compile(r'\/([a-zA-Z_0-9-]+)\|([a-zA-Z0-9- ]+)\|([0-9]+|SLP|UNK)\|')
25
+
26
+
27
+class Disk:
28
+ def __init__(self, id_, name, temp):
29
+ self.id = id_.replace(' ', '_')
30
+ self.name = name.replace(' ', '_')
31
+ self.temp = temp if temp.isdigit() else 0
32
+
33
+ def __repr__(self):
34
+ return self.id
35
+
36
37
class Service(SocketService):
38
def __init__(self, configuration=None, name=None):
@@ -42,56 +43,43 @@ class Service(SocketService):
43
self.request = ""
44
self.host = "127.0.0.1"
45
self.port = 7634
45
- self.disks = list()
46
+ self.do_only = self.configuration.get('devices')
47
48
def get_disks(self):
48
- try:
49
- disks = self.configuration['devices']
50
- self.info("Using configured disks {0}".format(disks))
51
- except (KeyError, TypeError):
52
- self.info("Autodetecting disks")
53
- return ["/dev/" + f for f in os.listdir("/dev") if len(f) == 3 and f.startswith("sd")]
54
-
55
- ret = list()
56
- for disk in disks:
57
- if not disk.startswith('/dev/'):
58
- disk = "/dev/" + disk
59
- ret.append(disk)
60
- if not ret:
61
- self.error("Provided disks cannot be found in /dev directory.")
62
- return ret
63
-
64
- def _check_raw_data(self, data):
65
- if not data.endswith('|'):
66
- return False
49
+ r = self._get_raw_data()
50
+
51
+ if not r:
52
+ return None
53
68
- if all(disk in data for disk in self.disks):
69
- return True
70
- return False
54
+ m = RE.findall(r)
55
+
56
+ if not m:
57
+ self.error("received data doesn't have needed records")
58
+ return None
59
+
60
+ rv = [Disk(*d) for d in m]
61
+ self.debug('available disks: {0}'.format(rv))
62
+
63
+ if self.do_only:
64
+ return [v for v in rv if v.id in self.do_only]
65
+ return rv
66
67
def get_data(self):
68
"""
69
Get data from TCP/IP socket
70
:return: dict
71
"""
77
- try:
78
- raw = self._get_raw_data().split("|")[:-1]
79
- except AttributeError:
80
- self.error("no data received")
72
+
73
+ disks = self.get_disks()
74
+
75
+ if not disks:
76
return None
77
+
78
data = dict()
83
- for i in range(len(raw) // 5):
84
- if not raw[i*5+1] in self.disks:
85
- continue
86
- try:
87
- val = int(raw[i*5+3])
88
- except ValueError:
89
- val = 0
90
- data[raw[i*5+1].replace("/dev/", "")] = val
91
-
92
- if not data:
93
- self.error("received data doesn't have needed records")
94
- return None
79
+
80
+ for d in disks:
81
+ data[d.id] = d.temp
82
+
83
return data
84
85
def check(self):
@@ -100,12 +88,18 @@ class Service(SocketService):
88
:return: boolean
89
"""
90
self._parse_config()
103
- self.disks = self.get_disks()
91
+ disks = self.get_disks()
92
105
- data = self.get_data()
106
- if data is None:
93
+ if not disks:
94
return False
95
109
- for name in data:
110
- self.definitions['temperatures']['lines'].append([name])
96
+ for d in disks:
97
+ n = d.id if d.id.startswith('sd') else d.name
98
+ dim = [d.id, n]
99
+ self.definitions['temperatures']['lines'].append(dim)
100
+
101
return True
102
+
103
+ @staticmethod
104
+ def _check_raw_data(data):
105
+ return not bool(data)