glances_memswap.py 6.1 KB
Newer Older
A
Alessio Sergi 已提交
1 2
# -*- coding: utf-8 -*-
#
3
# This file is part of Glances.
A
Alessio Sergi 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#
# Copyright (C) 2014 Nicolargo <nicolas@nicolargo.com>
#
# 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.plugins.glances_plugin import GlancesPlugin
A
Alessio Sergi 已提交
23

A
Alessio Sergi 已提交
24 25
import psutil

N
Nicolargo 已提交
26 27 28
# 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
29 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',
                        'used': '1.3.6.1.2.1.25.2.3.1.6'}}            
N
Nicolargo 已提交
35

A
Alessio Sergi 已提交
36 37

class Plugin(GlancesPlugin):
A
PEP 257  
Alessio Sergi 已提交
38 39

    """Glances' swap memory plugin.
A
Alessio Sergi 已提交
40 41 42 43

    stats is a dict
    """

44
    def __init__(self, args=None):
A
PEP 257  
Alessio Sergi 已提交
45
        """Init the plugin."""
46
        GlancesPlugin.__init__(self, args=args)
A
Alessio Sergi 已提交
47 48 49 50

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

51
        # Init the stats
A
Alessio Sergi 已提交
52
        self.reset()
53 54

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

A
Alessio Sergi 已提交
58
    def update(self):
A
PEP 257  
Alessio Sergi 已提交
59
        """Update swap memory stats using the input method."""
60 61 62
        # Reset stats
        self.reset()

63
        if self.get_input() == 'local':
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
            # Update stats using the standard system lib
            # Grab SWAP using the PSUtil swap_memory method
            sm_stats = psutil.swap_memory()

            # Get all the swap stats (copy/paste of the PsUtil documentation)
            # 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)
            # sout: the number of bytes the system has swapped out from disk (cumulative)
            for swap in ['total', 'used', 'free', 'percent',
                         'sin', 'sout']:
                if hasattr(sm_stats, swap):
                    self.stats[swap] = getattr(sm_stats, swap)
79
        elif self.get_input() == 'snmp':
80
            # Update stats using SNMP
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
            if self.get_short_system_name() == 'windows':
                # Mem stats for Windows OS are stored in the FS table
                try:
                    fs_stat = self.set_stats_snmp(snmp_oid=snmp_oid[self.get_short_system_name()], 
                                                  bulk=True)
                except KeyError:
                    self.reset()
                else:
                    for fs in fs_stat:                        
                        # 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. 
                        if fs == 'Virtual Memory':
                            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'] 
                            break
            else:            
N
Nicolargo 已提交
99
                self.stats = self.set_stats_snmp(snmp_oid=snmp_oid['default'])
100 101 102 103 104

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

105
                for key in list(self.stats.keys()):
106 107 108 109 110 111 112 113
                    if self.stats[key] != '':
                        self.stats[key] = float(self.stats[key]) * 1024

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

                # percent: the percentage usage calculated as (total - available) / total * 100.
                self.stats['percent'] = float((self.stats['total'] - self.stats['free']) / self.stats['total'] * 100)
114 115

        return self.stats
A
Alessio Sergi 已提交
116 117

    def msg_curse(self, args=None):
A
PEP 257  
Alessio Sergi 已提交
118
        """Return the dict to display in the curse interface."""
A
Alessio Sergi 已提交
119 120 121
        # Init the return message
        ret = []

122
        # Only process if stats exist...
123
        if self.stats == {}:
124 125
            return ret

A
Alessio Sergi 已提交
126 127
        # Build the string message
        # Header
A
Alessio Sergi 已提交
128
        msg = '{0:7} '.format(_("SWAP"))
A
Alessio Sergi 已提交
129 130
        ret.append(self.curse_add_line(msg, "TITLE"))
        # Percent memory usage
A
Alessio Sergi 已提交
131
        msg = '{0:>6.1%}'.format(self.stats['percent'] / 100)
A
Alessio Sergi 已提交
132 133 134 135
        ret.append(self.curse_add_line(msg))
        # New line
        ret.append(self.curse_new_line())
        # Total memory usage
A
Alessio Sergi 已提交
136
        msg = '{0:8}'.format(_("total:"))
A
Alessio Sergi 已提交
137
        ret.append(self.curse_add_line(msg))
A
Alessio Sergi 已提交
138
        msg = '{0:>6}'.format(self.auto_unit(self.stats['total']))
A
Alessio Sergi 已提交
139 140 141 142
        ret.append(self.curse_add_line(msg))
        # New line
        ret.append(self.curse_new_line())
        # Used memory usage
A
Alessio Sergi 已提交
143
        msg = '{0:8}'.format(_("used:"))
A
Alessio Sergi 已提交
144
        ret.append(self.curse_add_line(msg))
A
Alessio Sergi 已提交
145
        msg = '{0:>6}'.format(self.auto_unit(self.stats['used']))
A
Alessio Sergi 已提交
146
        ret.append(self.curse_add_line(
147
            msg, self.get_alert_log(self.stats['used'], max=self.stats['total'])))
A
Alessio Sergi 已提交
148 149 150
        # New line
        ret.append(self.curse_new_line())
        # Free memory usage
A
Alessio Sergi 已提交
151
        msg = '{0:8}'.format(_("free:"))
A
Alessio Sergi 已提交
152
        ret.append(self.curse_add_line(msg))
A
Alessio Sergi 已提交
153
        msg = '{0:>6}'.format(self.auto_unit(self.stats['free']))
A
Alessio Sergi 已提交
154 155 156
        ret.append(self.curse_add_line(msg))

        return ret