Completed
Pull Request — develop (#804)
by Floran
01:03
created

glances.plugins.Plugin.msg_curse()   B

Complexity

Conditions 3

Size

Total Lines 40

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 3
dl 0
loc 40
rs 8.8571
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
"""Swap memory plugin."""
21
22
from glances.compat import iterkeys
23
from glances.plugins.glances_plugin import GlancesPlugin
24
25
import psutil
26
27
# SNMP OID
28
# Total Swap Size: .1.3.6.1.4.1.2021.4.3.0
29
# Available Swap Space: .1.3.6.1.4.1.2021.4.4.0
30
snmp_oid = {'default': {'total': '1.3.6.1.4.1.2021.4.3.0',
31
                        'free': '1.3.6.1.4.1.2021.4.4.0'},
32
            'windows': {'mnt_point': '1.3.6.1.2.1.25.2.3.1.3',
33
                        'alloc_unit': '1.3.6.1.2.1.25.2.3.1.4',
34
                        'size': '1.3.6.1.2.1.25.2.3.1.5',
35
                        'used': '1.3.6.1.2.1.25.2.3.1.6'}}
36
37
# Define the history items list
38
# All items in this list will be historised if the --enable-history tag is set
39
# 'color' define the graph color in #RGB format
40
items_history_list = [{'name': 'percent', 'color': '#00FF00', 'y_unit': '%'}]
41
42
43
class Plugin(GlancesPlugin):
44
45
    """Glances swap memory plugin.
46
47
    stats is a dict
48
    """
49
50
    def __init__(self, args=None):
51
        """Init the plugin."""
52
        super(Plugin, self).__init__(args=args, items_history_list=items_history_list)
53
54
        # We want to display the stat in the curse interface
55
        self.display_curse = True
56
57
        # Init the stats
58
        self.reset()
59
60
    def reset(self):
61
        """Reset/init the stats."""
62
        self.stats = {}
63
64
    @GlancesPlugin._log_result_decorator
65
    def update(self):
66
        """Update swap memory stats using the input method."""
67
        # Reset stats
68
        self.reset()
69
70
        if self.input_method == 'local':
71
            # Update stats using the standard system lib
72
            # Grab SWAP using the PSUtil swap_memory method
73
            sm_stats = psutil.swap_memory()
74
75
            # Get all the swap stats (copy/paste of the PsUtil documentation)
76
            # total: total swap memory in bytes
77
            # used: used swap memory in bytes
78
            # free: free swap memory in bytes
79
            # percent: the percentage usage
80
            # sin: the number of bytes the system has swapped in from disk (cumulative)
81
            # sout: the number of bytes the system has swapped out from disk
82
            # (cumulative)
83
            for swap in ['total', 'used', 'free', 'percent',
84
                         'sin', 'sout']:
85
                if hasattr(sm_stats, swap):
86
                    self.stats[swap] = getattr(sm_stats, swap)
87
        elif self.input_method == 'snmp':
88
            # Update stats using SNMP
89
            if self.short_system_name == 'windows':
90
                # Mem stats for Windows OS are stored in the FS table
91
                try:
92
                    fs_stat = self.get_stats_snmp(snmp_oid=snmp_oid[self.short_system_name],
93
                                                  bulk=True)
94
                except KeyError:
95
                    self.reset()
96
                else:
97
                    for fs in fs_stat:
98
                        # The virtual memory concept is used by the operating
99
                        # system to extend (virtually) the physical memory and
100
                        # thus to run more programs by swapping unused memory
101
                        # zone (page) to a disk file.
102
                        if fs == 'Virtual Memory':
103
                            self.stats['total'] = int(
104
                                fs_stat[fs]['size']) * int(fs_stat[fs]['alloc_unit'])
105
                            self.stats['used'] = int(
106
                                fs_stat[fs]['used']) * int(fs_stat[fs]['alloc_unit'])
107
                            self.stats['percent'] = float(
108
                                self.stats['used'] * 100 / self.stats['total'])
109
                            self.stats['free'] = self.stats[
110
                                'total'] - self.stats['used']
111
                            break
112
            else:
113
                self.stats = self.get_stats_snmp(snmp_oid=snmp_oid['default'])
114
115
                if self.stats['total'] == '':
116
                    self.reset()
117
                    return self.stats
118
119
                for key in iterkeys(self.stats):
120
                    if self.stats[key] != '':
121
                        self.stats[key] = float(self.stats[key]) * 1024
122
123
                # used=total-free
124
                self.stats['used'] = self.stats['total'] - self.stats['free']
125
126
                # percent: the percentage usage calculated as (total -
127
                # available) / total * 100.
128
                self.stats['percent'] = float(
129
                    (self.stats['total'] - self.stats['free']) / self.stats['total'] * 100)
130
131
        # Update the history list
132
        self.update_stats_history()
133
134
        # Update the view
135
        self.update_views()
136
137
        return self.stats
138
139
    def update_views(self):
140
        """Update stats views."""
141
        # Call the father's method
142
        super(Plugin, self).update_views()
143
144
        # Add specifics informations
145
        # Alert and log
146
        self.views['used']['decoration'] = self.get_alert_log(self.stats['used'], maximum=self.stats['total'])
147
148
    def msg_curse(self, args=None):
149
        """Return the dict to display in the curse interface."""
150
        # Init the return message
151
        ret = []
152
153
        # Only process if stats exist and plugin not disabled
154
        if not self.stats or args.disable_swap:
155
            return ret
156
157
        # Build the string message
158
        # Header
159
        msg = '{0:7} '.format('SWAP')
160
        ret.append(self.curse_add_line(msg, "TITLE"))
161
        # Percent memory usage
162
        msg = '{0:>6.1%}'.format(self.stats['percent'] / 100)
163
        ret.append(self.curse_add_line(msg))
164
        # New line
165
        ret.append(self.curse_new_line())
166
        # Total memory usage
167
        msg = '{0:8}'.format('total:')
168
        ret.append(self.curse_add_line(msg))
169
        msg = '{0:>6}'.format(self.auto_unit(self.stats['total']))
170
        ret.append(self.curse_add_line(msg))
171
        # New line
172
        ret.append(self.curse_new_line())
173
        # Used memory usage
174
        msg = '{0:8}'.format('used:')
175
        ret.append(self.curse_add_line(msg))
176
        msg = '{0:>6}'.format(self.auto_unit(self.stats['used']))
177
        ret.append(self.curse_add_line(
178
            msg, self.get_views(key='used', option='decoration')))
179
        # New line
180
        ret.append(self.curse_new_line())
181
        # Free memory usage
182
        msg = '{0:8}'.format('free:')
183
        ret.append(self.curse_add_line(msg))
184
        msg = '{0:>6}'.format(self.auto_unit(self.stats['free']))
185
        ret.append(self.curse_add_line(msg))
186
187
        return ret
188