Test Failed
Push — develop ( 504450...f0e8ef )
by Nicolas
03:16
created

glances/plugins/glances_hddtemp.py (4 issues)

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
This line is too long as per the coding-style (82/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
44
                                                                   default="127.0.0.1"),
0 ignored issues
show
This line is too long as per the coding-style (88/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
45
                                          port=int(self.get_conf_value("hddtemp_port",
0 ignored issues
show
This line is too long as per the coding-style (86/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
46
                                                                       default="7634")))
0 ignored issues
show
This line is too long as per the coding-style (88/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
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