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, config=None): |
||
37 | """Init the plugin.""" |
||
38 | super(Plugin, self).__init__(args=args, |
||
39 | config=config, |
||
40 | stats_init_value=[]) |
||
41 | |||
42 | # Init the sensor class |
||
43 | hddtemp_host = self.get_conf_value("host", |
||
44 | default=["127.0.0.1"])[0] |
||
45 | hddtemp_port = int(self.get_conf_value("port", |
||
46 | default="7634")) |
||
47 | self.hddtemp = GlancesGrabHDDTemp(args=args, |
||
48 | host=hddtemp_host, |
||
49 | port=hddtemp_port) |
||
50 | |||
51 | # We do not want to display the stat in a dedicated area |
||
52 | # The HDD temp is displayed within the sensors plugin |
||
53 | self.display_curse = False |
||
54 | |||
55 | @GlancesPlugin._check_decorator |
||
56 | @GlancesPlugin._log_result_decorator |
||
57 | def update(self): |
||
58 | """Update HDD stats using the input method.""" |
||
59 | # Init new stats |
||
60 | stats = self.get_init_value() |
||
61 | |||
62 | if self.input_method == 'local': |
||
63 | # Update stats using the standard system lib |
||
64 | stats = self.hddtemp.get() |
||
65 | |||
66 | else: |
||
67 | # Update stats using SNMP |
||
68 | # Not available for the moment |
||
69 | pass |
||
70 | |||
71 | # Update the stats |
||
72 | self.stats = stats |
||
73 | |||
74 | return self.stats |
||
75 | |||
76 | |||
77 | class GlancesGrabHDDTemp(object): |
||
78 | """Get hddtemp stats using a socket connection.""" |
||
79 | |||
80 | def __init__(self, host='127.0.0.1', port=7634, args=None): |
||
81 | """Init hddtemp stats.""" |
||
82 | self.args = args |
||
83 | self.host = host |
||
84 | self.port = port |
||
85 | self.cache = "" |
||
86 | self.reset() |
||
87 | |||
88 | def reset(self): |
||
89 | """Reset/init the stats.""" |
||
90 | self.hddtemp_list = [] |
||
91 | |||
92 | def __update__(self): |
||
93 | """Update the stats.""" |
||
94 | # Reset the list |
||
95 | self.reset() |
||
96 | |||
97 | # Fetch the data |
||
98 | # data = ("|/dev/sda|WDC WD2500JS-75MHB0|44|C|" |
||
99 | # "|/dev/sdb|WDC WD2500JS-75MHB0|35|C|" |
||
100 | # "|/dev/sdc|WDC WD3200AAKS-75B3A0|45|C|" |
||
101 | # "|/dev/sdd|WDC WD3200AAKS-75B3A0|45|C|" |
||
102 | # "|/dev/sde|WDC WD3200AAKS-75B3A0|43|C|" |
||
103 | # "|/dev/sdf|???|ERR|*|" |
||
104 | # "|/dev/sdg|HGST HTS541010A9E680|SLP|*|" |
||
105 | # "|/dev/sdh|HGST HTS541010A9E680|UNK|*|") |
||
106 | data = self.fetch() |
||
107 | |||
108 | # Exit if no data |
||
109 | if data == "": |
||
110 | return |
||
111 | |||
112 | # Safety check to avoid malformed data |
||
113 | # Considering the size of "|/dev/sda||0||" as the minimum |
||
114 | if len(data) < 14: |
||
115 | data = self.cache if len(self.cache) > 0 else self.fetch() |
||
116 | self.cache = data |
||
117 | |||
118 | try: |
||
119 | fields = data.split(b'|') |
||
120 | except TypeError: |
||
121 | fields = "" |
||
122 | devices = (len(fields) - 1) // 5 |
||
123 | for item in range(devices): |
||
124 | offset = item * 5 |
||
125 | hddtemp_current = {} |
||
126 | device = os.path.basename(nativestr(fields[offset + 1])) |
||
127 | temperature = fields[offset + 3] |
||
128 | unit = nativestr(fields[offset + 4]) |
||
129 | hddtemp_current['label'] = device |
||
130 | try: |
||
131 | hddtemp_current['value'] = float(temperature) |
||
132 | except ValueError: |
||
133 | # Temperature could be 'ERR', 'SLP' or 'UNK' (see issue #824) |
||
134 | # Improper bytes/unicode in glances_hddtemp.py (see issue #887) |
||
135 | hddtemp_current['value'] = nativestr(temperature) |
||
136 | hddtemp_current['unit'] = unit |
||
137 | self.hddtemp_list.append(hddtemp_current) |
||
138 | |||
139 | def fetch(self): |
||
140 | """Fetch the data from hddtemp daemon.""" |
||
141 | # Taking care of sudden deaths/stops of hddtemp daemon |
||
142 | try: |
||
143 | sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
||
144 | sck.connect((self.host, self.port)) |
||
145 | data = b'' |
||
146 | while True: |
||
147 | received = sck.recv(4096) |
||
148 | if not received: |
||
149 | break |
||
150 | data += received |
||
151 | except Exception as e: |
||
152 | logger.debug("Cannot connect to an HDDtemp server ({}:{} => {})".format(self.host, self.port, e)) |
||
153 | logger.debug("Disable the HDDtemp module. Use the --disable-hddtemp to hide the previous message.") |
||
154 | if self.args is not None: |
||
155 | self.args.disable_hddtemp = True |
||
156 | data = "" |
||
157 | finally: |
||
158 | sck.close() |
||
159 | if data != "": |
||
160 | logger.debug("Received data from the HDDtemp server: {}".format(data)) |
||
0 ignored issues
–
show
|
|||
161 | |||
162 | return data |
||
163 | |||
164 | def get(self): |
||
165 | """Get HDDs list.""" |
||
166 | self.__update__() |
||
167 | return self.hddtemp_list |
||
168 |
This check looks for lines that are too long. You can specify the maximum line length.