Completed
Push — master ( 2b80fa...6ea077 )
by Nicolas
01:22
created

glances/plugins/glances_hddtemp.py (1 issue)

1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# Copyright (C) 2015 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 View Code Duplication
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
32
    """Glances HDD temperature sensors plugin.
33
34
    stats is a list
35
    """
36
37
    def __init__(self, args=None):
38
        """Init the plugin."""
39
        super(Plugin, self).__init__(args=args)
40
41
        # Init the sensor class
42
        self.glancesgrabhddtemp = GlancesGrabHDDTemp(args=args)
43
44
        # We do not want to display the stat in a dedicated area
45
        # The HDD temp is displayed within the sensors plugin
46
        self.display_curse = False
47
48
        # Init stats
49
        self.reset()
50
51
    def reset(self):
52
        """Reset/init the stats."""
53
        self.stats = []
54
55
    def update(self):
56
        """Update HDD stats using the input method."""
57
        # Reset stats
58
        self.reset()
59
60
        if self.input_method == 'local':
61
            # Update stats using the standard system lib
62
            self.stats = self.glancesgrabhddtemp.get()
63
64
        else:
65
            # Update stats using SNMP
66
            # Not available for the moment
67
            pass
68
69
        return self.stats
70
71
72
class GlancesGrabHDDTemp(object):
73
74
    """Get hddtemp stats using a socket connection."""
75
76
    def __init__(self, host='127.0.0.1', port=7634, args=None):
77
        """Init hddtemp stats."""
78
        self.args = args
79
        self.host = host
80
        self.port = port
81
        self.cache = ""
82
        self.reset()
83
84
    def reset(self):
85
        """Reset/init the stats."""
86
        self.hddtemp_list = []
87
88
    def __update__(self):
89
        """Update the stats."""
90
        # Reset the list
91
        self.reset()
92
93
        # Only update if --disable-hddtemp is not set
94
        if self.args is None or self.args.disable_hddtemp:
95
            return
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 = sck.recv(4096)
146
        except socket.error as e:
147
            logger.debug("Cannot connect to an HDDtemp server ({}:{} => {})".format(self.host, self.port, e))
148
            logger.debug("Disable the HDDtemp module. Use the --disable-hddtemp to hide the previous message.")
149
            self.args.disable_hddtemp = True
150
            data = ""
151
        finally:
152
            sck.close()
153
154
        return data
155
156
    def get(self):
157
        """Get HDDs list."""
158
        self.__update__()
159
        return self.hddtemp_list
160