glances_memswap.py 7.1 KB
Newer Older
A
Alessio Sergi 已提交
1 2
# -*- coding: utf-8 -*-
#
3
# This file is part of Glances.
A
Alessio Sergi 已提交
4
#
A
Alessio Sergi 已提交
5
# Copyright (C) 2017 Nicolargo <nicolas@nicolargo.com>
A
Alessio Sergi 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18
#
# Glances is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Glances is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
A
PEP 257  
Alessio Sergi 已提交
19 20

"""Swap memory plugin."""
A
Alessio Sergi 已提交
21

22
from glances.compat import iterkeys
23 24
from glances.plugins.glances_plugin import GlancesPlugin

A
flake8  
Alessio Sergi 已提交
25 26
import psutil

N
Nicolargo 已提交
27 28 29
# SNMP OID
# Total Swap Size: .1.3.6.1.4.1.2021.4.3.0
# Available Swap Space: .1.3.6.1.4.1.2021.4.4.0
30 31 32 33 34
snmp_oid = {'default': {'total': '1.3.6.1.4.1.2021.4.3.0',
                        'free': '1.3.6.1.4.1.2021.4.4.0'},
            'windows': {'mnt_point': '1.3.6.1.2.1.25.2.3.1.3',
                        'alloc_unit': '1.3.6.1.2.1.25.2.3.1.4',
                        'size': '1.3.6.1.2.1.25.2.3.1.5',
35 36 37 38
                        'used': '1.3.6.1.2.1.25.2.3.1.6'}}

# Define the history items list
# All items in this list will be historised if the --enable-history tag is set
39 40 41
items_history_list = [{'name': 'percent',
                       'description': 'Swap memory usage',
                       'y_unit': '%'}]
N
Nicolargo 已提交
42

A
Alessio Sergi 已提交
43 44

class Plugin(GlancesPlugin):
A
PEP 257  
Alessio Sergi 已提交
45
    """Glances swap memory plugin.
A
Alessio Sergi 已提交
46 47 48 49

    stats is a dict
    """

50
    def __init__(self, args=None):
A
PEP 257  
Alessio Sergi 已提交
51
        """Init the plugin."""
A
Alessio Sergi 已提交
52
        super(Plugin, self).__init__(args=args, items_history_list=items_history_list)
A
Alessio Sergi 已提交
53 54 55 56

        # We want to display the stat in the curse interface
        self.display_curse = True

57
        # Init the stats
A
Alessio Sergi 已提交
58
        self.reset()
59 60

    def reset(self):
A
PEP 257  
Alessio Sergi 已提交
61
        """Reset/init the stats."""
62 63
        self.stats = {}

64
    @GlancesPlugin._check_decorator
65
    @GlancesPlugin._log_result_decorator
A
Alessio Sergi 已提交
66
    def update(self):
A
PEP 257  
Alessio Sergi 已提交
67
        """Update swap memory stats using the input method."""
68 69 70
        # Reset stats
        self.reset()

71
        if self.input_method == 'local':
72
            # Update stats using the standard system lib
A
Alessio Sergi 已提交
73
            # Grab SWAP using the psutil swap_memory method
74 75
            sm_stats = psutil.swap_memory()

A
Alessio Sergi 已提交
76
            # Get all the swap stats (copy/paste of the psutil documentation)
77 78 79 80 81
            # total: total swap memory in bytes
            # used: used swap memory in bytes
            # free: free swap memory in bytes
            # percent: the percentage usage
            # sin: the number of bytes the system has swapped in from disk (cumulative)
82 83
            # sout: the number of bytes the system has swapped out from disk
            # (cumulative)
84 85 86 87
            for swap in ['total', 'used', 'free', 'percent',
                         'sin', 'sout']:
                if hasattr(sm_stats, swap):
                    self.stats[swap] = getattr(sm_stats, swap)
88
        elif self.input_method == 'snmp':
89
            # Update stats using SNMP
90
            if self.short_system_name == 'windows':
91 92
                # Mem stats for Windows OS are stored in the FS table
                try:
93
                    fs_stat = self.get_stats_snmp(snmp_oid=snmp_oid[self.short_system_name],
94 95 96 97
                                                  bulk=True)
                except KeyError:
                    self.reset()
                else:
98
                    for fs in fs_stat:
A
flake8  
Alessio Sergi 已提交
99 100 101 102
                        # The virtual memory concept is used by the operating
                        # system to extend (virtually) the physical memory and
                        # thus to run more programs by swapping unused memory
                        # zone (page) to a disk file.
103
                        if fs == 'Virtual Memory':
104 105 106 107 108 109 110 111
                            self.stats['total'] = int(
                                fs_stat[fs]['size']) * int(fs_stat[fs]['alloc_unit'])
                            self.stats['used'] = int(
                                fs_stat[fs]['used']) * int(fs_stat[fs]['alloc_unit'])
                            self.stats['percent'] = float(
                                self.stats['used'] * 100 / self.stats['total'])
                            self.stats['free'] = self.stats[
                                'total'] - self.stats['used']
112
                            break
113
            else:
114
                self.stats = self.get_stats_snmp(snmp_oid=snmp_oid['default'])
115 116 117 118 119

                if self.stats['total'] == '':
                    self.reset()
                    return self.stats

A
Alessio Sergi 已提交
120
                for key in iterkeys(self.stats):
121 122 123 124 125 126
                    if self.stats[key] != '':
                        self.stats[key] = float(self.stats[key]) * 1024

                # used=total-free
                self.stats['used'] = self.stats['total'] - self.stats['free']

127 128 129 130 131
                # percent: the percentage usage calculated as (total -
                # available) / total * 100.
                self.stats['percent'] = float(
                    (self.stats['total'] - self.stats['free']) / self.stats['total'] * 100)

132
        return self.stats
A
Alessio Sergi 已提交
133

134
    def update_views(self):
A
PEP 257  
Alessio Sergi 已提交
135
        """Update stats views."""
136
        # Call the father's method
A
Alessio Sergi 已提交
137
        super(Plugin, self).update_views()
138 139 140

        # Add specifics informations
        # Alert and log
141
        self.views['used']['decoration'] = self.get_alert_log(self.stats['used'], maximum=self.stats['total'])
142

143
    def msg_curse(self, args=None, max_width=None):
A
PEP 257  
Alessio Sergi 已提交
144
        """Return the dict to display in the curse interface."""
A
Alessio Sergi 已提交
145 146 147
        # Init the return message
        ret = []

148
        # Only process if stats exist and plugin not disabled
N
nicolargo 已提交
149
        if not self.stats or self.is_disable():
150 151
            return ret

A
Alessio Sergi 已提交
152 153
        # Build the string message
        # Header
154
        msg = '{}'.format('SWAP')
A
Alessio Sergi 已提交
155
        ret.append(self.curse_add_line(msg, "TITLE"))
156
        msg = ' {:3}'.format(self.trend_msg(self.get_trend('percent')))
157
        ret.append(self.curse_add_line(msg))
A
Alessio Sergi 已提交
158
        # Percent memory usage
159
        msg = '{:>6.1%}'.format(self.stats['percent'] / 100)
A
Alessio Sergi 已提交
160 161 162 163
        ret.append(self.curse_add_line(msg))
        # New line
        ret.append(self.curse_new_line())
        # Total memory usage
164
        msg = '{:8}'.format('total:')
A
Alessio Sergi 已提交
165
        ret.append(self.curse_add_line(msg))
166
        msg = '{:>6}'.format(self.auto_unit(self.stats['total']))
A
Alessio Sergi 已提交
167 168 169 170
        ret.append(self.curse_add_line(msg))
        # New line
        ret.append(self.curse_new_line())
        # Used memory usage
171
        msg = '{:8}'.format('used:')
A
Alessio Sergi 已提交
172
        ret.append(self.curse_add_line(msg))
173
        msg = '{:>6}'.format(self.auto_unit(self.stats['used']))
A
Alessio Sergi 已提交
174
        ret.append(self.curse_add_line(
175
            msg, self.get_views(key='used', option='decoration')))
A
Alessio Sergi 已提交
176 177 178
        # New line
        ret.append(self.curse_new_line())
        # Free memory usage
179
        msg = '{:8}'.format('free:')
A
Alessio Sergi 已提交
180
        ret.append(self.curse_add_line(msg))
181
        msg = '{:>6}'.format(self.auto_unit(self.stats['free']))
A
Alessio Sergi 已提交
182 183 184
        ret.append(self.curse_add_line(msg))

        return ret