glances_diskio.py 4.8 KB
Newer Older
A
Alessio Sergi 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Glances - An eye on your system
#
# 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/>.
20 21 22
"""
Glances CPU plugin
"""
A
Alessio Sergi 已提交
23 24 25 26

# Import system lib
from psutil import disk_io_counters

27 28
# Import Glances libs
from glances.plugins.glances_plugin import GlancesPlugin
A
Alessio Sergi 已提交
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
from glances.core.glances_timer import getTimeSinceLastUpdate


class Plugin(GlancesPlugin):
    """
    Glances's disks IO Plugin

    stats is a list
    """

    def __init__(self):
        GlancesPlugin.__init__(self)

        # We want to display the stat in the curse interface
        self.display_curse = True
        # Set the message position
        # It is NOT the curse position but the Glances column/line
        # Enter -1 to right align
        self.column_curse = 0
        # Enter -1 to diplay bottom
        self.line_curse = 3

51 52 53
        # Init stats
        self.diskio_old = []

A
Alessio Sergi 已提交
54 55 56 57 58
    def update(self):
        """
        Update disk IO stats
        """

59 60 61 62 63 64 65 66 67 68 69 70 71
        # Grab the stat using the PsUtil disk_io_counters method
        # read_count: number of reads
        # write_count: number of writes
        # read_bytes: number of bytes read
        # write_bytes: number of bytes written
        # read_time: time spent reading from disk (in milliseconds)
        # write_time: time spent writing to disk (in milliseconds)
        diskiocounters = disk_io_counters(perdisk=True)

        # Previous disk IO stats are stored in the diskio_old variable
        diskio = []
        if (self.diskio_old == []):
            # First call, we init the network_old var
A
Alessio Sergi 已提交
72
            try:
73 74 75
                self.diskio_old = diskiocounters
            except (IOError, UnboundLocalError):
                pass
A
Alessio Sergi 已提交
76
        else:
77 78 79 80 81 82 83
            # By storing time data we enable Rx/s and Tx/s calculations in the
            # XML/RPC API, which would otherwise be overly difficult work
            # for users of the API
            time_since_update = getTimeSinceLastUpdate('disk')

            diskio_new = diskiocounters
            for disk in diskio_new:
A
Alessio Sergi 已提交
84 85 86 87 88 89
                try:
                    # Try necessary to manage dynamic disk creation/del
                    diskstat = {}
                    diskstat['time_since_update'] = time_since_update
                    diskstat['disk_name'] = disk
                    diskstat['read_bytes'] = (
90
                        diskio_new[disk].read_bytes -
A
Alessio Sergi 已提交
91 92
                        self.diskio_old[disk].read_bytes)
                    diskstat['write_bytes'] = (
93
                        diskio_new[disk].write_bytes -
A
Alessio Sergi 已提交
94
                        self.diskio_old[disk].write_bytes)
95
                except KeyError:
A
Alessio Sergi 已提交
96 97
                    continue
                else:
98 99 100 101
                    diskio.append(diskstat)
            self.diskio_old = diskio_new

        self.stats = diskio
A
Alessio Sergi 已提交
102

103
        return self.stats
A
Alessio Sergi 已提交
104 105 106 107 108

    def msg_curse(self, args=None):
        """
        Return the dict to display in the curse interface
        """
109

A
Alessio Sergi 已提交
110 111 112
        # Init the return message
        ret = []

113 114
        # Only process if stats exist and display plugin enable...
        if ((self.stats == []) or (args.disable_diskio)):
115 116
            return ret

A
Alessio Sergi 已提交
117 118
        # Build the string message
        # Header
119
        msg = "{0:9}".format(_("DISK I/O"))
A
Alessio Sergi 已提交
120
        ret.append(self.curse_add_line(msg, "TITLE"))
121
        msg = "{0:>7}".format(_("R/s"))
A
Alessio Sergi 已提交
122
        ret.append(self.curse_add_line(msg))
123
        msg = "{0:>7}".format(_("W/s"))
A
Alessio Sergi 已提交
124 125 126
        ret.append(self.curse_add_line(msg))
        # Disk list (sorted by name)
        for i in sorted(self.stats, key=lambda diskio: diskio['disk_name']):
127 128 129
            # Do not display hidden interfaces
            if (self.is_hide(i['disk_name'])):
                continue
A
Alessio Sergi 已提交
130 131
            # New line
            ret.append(self.curse_new_line())
132
            msg = "{0:9}".format(i['disk_name'])
A
Alessio Sergi 已提交
133 134
            ret.append(self.curse_add_line(msg))
            txps = self.auto_unit(int(i['read_bytes'] // i['time_since_update']))
135
            rxps = self.auto_unit(int(i['write_bytes'] // i['time_since_update']))
136
            msg = "{0:>7}".format(txps)
A
Alessio Sergi 已提交
137
            ret.append(self.curse_add_line(msg))
138
            msg = "{0:>7}".format(rxps)
139
            ret.append(self.curse_add_line(msg))
A
Alessio Sergi 已提交
140 141

        return ret