1 | # -*- coding: utf-8 -*- |
||
2 | # |
||
3 | # This file is part of Glances. |
||
4 | # |
||
5 | # Copyright (C) 2019 Nicolargo <[email protected]> |
||
6 | # |
||
7 | # Glances is free software; you can redistribute it and/or modify |
||
8 | # it under the terms of the GNU Lesser General Public License as published by |
||
9 | # the Free Software Foundation, either version 3 of the License, or |
||
10 | # (at your option) any later version. |
||
11 | # |
||
12 | # Glances is distributed in the hope that it will be useful, |
||
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
15 | # GNU Lesser General Public License for more details. |
||
16 | # |
||
17 | # You should have received a copy of the GNU Lesser General Public License |
||
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
19 | |||
20 | """HDD temperature plugin.""" |
||
21 | |||
22 | import os |
||
23 | import socket |
||
24 | |||
25 | from glances.compat import nativestr, range |
||
26 | from glances.logger import logger |
||
27 | from glances.plugins.glances_plugin import GlancesPlugin |
||
28 | |||
29 | |||
30 | class Plugin(GlancesPlugin): |
||
31 | """Glances HDD temperature sensors plugin. |
||
32 | |||
33 | stats is a list |
||
34 | """ |
||
35 | |||
36 | def __init__(self, args=None): |
||
37 | """Init the plugin.""" |
||
38 | super(Plugin, self).__init__(args=args, |
||
39 | stats_init_value=[]) |
||
40 | |||
41 | # Init the sensor class |
||
42 | self.hddtemp = GlancesGrabHDDTemp(args=args, |
||
43 | host=self.get_conf_value("hddtemp_host", |
||
0 ignored issues
–
show
|
|||
44 | default="127.0.0.1"), |
||
0 ignored issues
–
show
|
|||
45 | port=int(self.get_conf_value("hddtemp_port", |
||
0 ignored issues
–
show
|
|||
46 | default="7634"))) |
||
0 ignored issues
–
show
|
|||
47 | |||
48 | # We do not want to display the stat in a dedicated area |
||
49 | # The HDD temp is displayed within the sensors plugin |
||
50 | self.display_curse = False |
||
51 | |||
52 | @GlancesPlugin._check_decorator |
||
53 | @GlancesPlugin._log_result_decorator |
||
54 | def update(self): |
||
55 | """Update HDD stats using the input method.""" |
||
56 | # Init new stats |
||
57 | stats = self.get_init_value() |
||
58 | |||
59 | if self.input_method == 'local': |
||
60 | # Update stats using the standard system lib |
||
61 | stats = self.hddtemp.get() |
||
62 | |||
63 | else: |
||
64 | # Update stats using SNMP |
||
65 | # Not available for the moment |
||
66 | pass |
||
67 | |||
68 | # Update the stats |
||
69 | self.stats = stats |
||
70 | |||
71 | return self.stats |
||
72 | |||
73 | |||
74 | class GlancesGrabHDDTemp(object): |
||
75 | """Get hddtemp stats using a socket connection.""" |
||
76 | |||
77 | def __init__(self, host='127.0.0.1', port=7634, args=None): |
||
78 | """Init hddtemp stats.""" |
||
79 | self.args = args |
||
80 | self.host = host |
||
81 | self.port = port |
||
82 | self.cache = "" |
||
83 | self.reset() |
||
84 | |||
85 | def reset(self): |
||
86 | """Reset/init the stats.""" |
||
87 | self.hddtemp_list = [] |
||
88 | |||
89 | def __update__(self): |
||
90 | """Update the stats.""" |
||
91 | # Reset the list |
||
92 | self.reset() |
||
93 | |||
94 | # Fetch the data |
||
95 | # data = ("|/dev/sda|WDC WD2500JS-75MHB0|44|C|" |
||
96 | # "|/dev/sdb|WDC WD2500JS-75MHB0|35|C|" |
||
97 | # "|/dev/sdc|WDC WD3200AAKS-75B3A0|45|C|" |
||
98 | # "|/dev/sdd|WDC WD3200AAKS-75B3A0|45|C|" |
||
99 | # "|/dev/sde|WDC WD3200AAKS-75B3A0|43|C|" |
||
100 | # "|/dev/sdf|???|ERR|*|" |
||
101 | # "|/dev/sdg|HGST HTS541010A9E680|SLP|*|" |
||
102 | # "|/dev/sdh|HGST HTS541010A9E680|UNK|*|") |
||
103 | data = self.fetch() |
||
104 | |||
105 | # Exit if no data |
||
106 | if data == "": |
||
107 | return |
||
108 | |||
109 | # Safety check to avoid malformed data |
||
110 | # Considering the size of "|/dev/sda||0||" as the minimum |
||
111 | if len(data) < 14: |
||
112 | data = self.cache if len(self.cache) > 0 else self.fetch() |
||
113 | self.cache = data |
||
114 | |||
115 | try: |
||
116 | fields = data.split(b'|') |
||
117 | except TypeError: |
||
118 | fields = "" |
||
119 | devices = (len(fields) - 1) // 5 |
||
120 | for item in range(devices): |
||
121 | offset = item * 5 |
||
122 | hddtemp_current = {} |
||
123 | device = os.path.basename(nativestr(fields[offset + 1])) |
||
124 | temperature = fields[offset + 3] |
||
125 | unit = nativestr(fields[offset + 4]) |
||
126 | hddtemp_current['label'] = device |
||
127 | try: |
||
128 | hddtemp_current['value'] = float(temperature) |
||
129 | except ValueError: |
||
130 | # Temperature could be 'ERR', 'SLP' or 'UNK' (see issue #824) |
||
131 | # Improper bytes/unicode in glances_hddtemp.py (see issue #887) |
||
132 | hddtemp_current['value'] = nativestr(temperature) |
||
133 | hddtemp_current['unit'] = unit |
||
134 | self.hddtemp_list.append(hddtemp_current) |
||
135 | |||
136 | def fetch(self): |
||
137 | """Fetch the data from hddtemp daemon.""" |
||
138 | # Taking care of sudden deaths/stops of hddtemp daemon |
||
139 | try: |
||
140 | sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
||
141 | sck.connect((self.host, self.port)) |
||
142 | data = b'' |
||
143 | while True: |
||
144 | received = sck.recv(4096) |
||
145 | if not received: |
||
146 | break |
||
147 | data += received |
||
148 | except Exception as e: |
||
149 | logger.debug("Cannot connect to an HDDtemp server ({}:{} => {})".format(self.host, self.port, e)) |
||
150 | logger.debug("Disable the HDDtemp module. Use the --disable-hddtemp to hide the previous message.") |
||
151 | if self.args is not None: |
||
152 | self.args.disable_hddtemp = True |
||
153 | data = "" |
||
154 | finally: |
||
155 | sck.close() |
||
156 | if data != "": |
||
157 | logger.debug("Received data from the HDDtemp server: {}".format(data)) |
||
158 | |||
159 | return data |
||
160 | |||
161 | def get(self): |
||
162 | """Get HDDs list.""" |
||
163 | self.__update__() |
||
164 | return self.hddtemp_list |
||
165 |
This check looks for lines that are too long. You can specify the maximum line length.