|
1
|
|
|
# -*- coding: utf-8 -*- |
|
2
|
|
|
"""Disk usage metrics reader from /proc on Linux.""" |
|
3
|
|
|
import re |
|
4
|
|
|
import os |
|
5
|
|
|
import sys |
|
6
|
|
|
import plumd |
|
7
|
|
|
from plumd.util import get_file_list |
|
8
|
|
|
|
|
9
|
|
|
PY3 = sys.version_info > (3,) |
|
10
|
|
|
|
|
11
|
|
|
__author__ = 'Kenny Freeman' |
|
12
|
|
|
__email__ = '[email protected]' |
|
13
|
|
|
__license__ = "ISCL" |
|
14
|
|
|
__docformat__ = 'reStructuredText' |
|
15
|
|
|
|
|
16
|
|
|
|
|
17
|
|
|
class DiskSpace(plumd.Reader): |
|
18
|
|
|
"""Plugin to measure disk usage.""" |
|
19
|
|
|
|
|
20
|
|
|
# default config values |
|
21
|
|
|
defaults = { |
|
22
|
|
|
'poll.interval': 60, |
|
23
|
|
|
'fs_types': ['xfs', 'ext2', 'ext3', 'ext4'], |
|
24
|
|
|
'mnt_exclude_re': "^\/mnt\/.*", |
|
|
|
|
|
|
25
|
|
|
'chrs_keep': 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-' |
|
26
|
|
|
} |
|
27
|
|
|
|
|
28
|
|
|
def __init__(self, log, config): |
|
29
|
|
|
"""Plugin to measure disk usage. |
|
30
|
|
|
|
|
31
|
|
|
:param log: A logger |
|
32
|
|
|
:type log: logging.RootLogger |
|
33
|
|
|
:param config: a plumd.config.Conf configuration helper instance. |
|
34
|
|
|
:type config: plumd.config.Conf |
|
35
|
|
|
""" |
|
36
|
|
|
super(DiskSpace, self).__init__(log, config) |
|
37
|
|
|
self.config.defaults(DiskSpace.defaults) |
|
38
|
|
|
# skip mounts for devices matching this re |
|
39
|
|
|
self.mnt_re = re.compile(config.get('mnt_exclude_re')) |
|
40
|
|
|
|
|
41
|
|
|
# characters to remove from device names |
|
42
|
|
|
self.filter_chars = "".join(char for char in map(chr, range(256)) |
|
43
|
|
|
if char not in self.config.get('chrs_keep')) |
|
44
|
|
|
# args for str.translate() calls |
|
45
|
|
|
self.tlate_args = [None, self.filter_chars] |
|
46
|
|
|
if PY3: |
|
47
|
|
|
self.tlate_args = [dict.fromkeys( |
|
48
|
|
|
map(ord, self.filter_chars)), None] |
|
49
|
|
|
# get a list of mount points - only on init |
|
50
|
|
|
self.mounts = self.proc_mounts() |
|
51
|
|
|
|
|
52
|
|
|
def proc_mounts(self): |
|
53
|
|
|
"""Return a list of mounted file systems. |
|
54
|
|
|
|
|
55
|
|
|
:rtype: list |
|
56
|
|
|
""" |
|
57
|
|
|
fs_types = self.config.get('fs_types') |
|
58
|
|
|
ret = [] |
|
59
|
|
|
mounts = get_file_list("/proc/mounts") |
|
60
|
|
|
mnt_re = self.mnt_re |
|
61
|
|
|
tlate_args = self.tlate_args |
|
62
|
|
|
for entry in mounts: |
|
63
|
|
|
dev, path, f_sys, _, _, _ = entry.split() |
|
64
|
|
|
if mnt_re.match(path) or f_sys not in fs_types: |
|
65
|
|
|
continue |
|
66
|
|
|
dev = re.sub("^/dev/", "", dev) |
|
67
|
|
|
dev = dev.translate(*tlate_args) |
|
|
|
|
|
|
68
|
|
|
ret.append((dev, path)) |
|
69
|
|
|
return ret |
|
70
|
|
|
|
|
71
|
|
|
def poll(self): |
|
72
|
|
|
"""Poll for disk space usage. |
|
73
|
|
|
|
|
74
|
|
|
:rtype: ResultSet |
|
75
|
|
|
""" |
|
76
|
|
|
result = plumd.Result("diskusage") |
|
77
|
|
|
for dev, mpoint in self.mounts: |
|
78
|
|
|
mp_stat = os.statvfs(mpoint) |
|
79
|
|
|
free = (mp_stat.f_bavail * mp_stat.f_frsize) |
|
80
|
|
|
total = (mp_stat.f_blocks * mp_stat.f_frsize) |
|
81
|
|
|
used = (mp_stat.f_blocks - mp_stat.f_bfree) * mp_stat.f_frsize |
|
82
|
|
|
total_inodes = mp_stat.f_files |
|
83
|
|
|
free_inodes = mp_stat.f_favail |
|
84
|
|
|
used_inodes = total_inodes - free_inodes |
|
85
|
|
|
result.add(plumd.Int("{0}.free".format(dev), free)) |
|
86
|
|
|
result.add(plumd.Int("{0}.total".format(dev), total)) |
|
87
|
|
|
result.add(plumd.Int("{0}.used".format(dev), used)) |
|
88
|
|
|
result.add(plumd.Int("{0}.total_inodes".format(dev), total_inodes)) |
|
89
|
|
|
result.add(plumd.Int("{0}.free_inodes".format(dev), free_inodes)) |
|
90
|
|
|
result.add(plumd.Int("{0}.used_inodes".format(dev), used_inodes)) |
|
91
|
|
|
return plumd.ResultSet([result]) |
|
92
|
|
|
|
Escape sequences in Python are generally interpreted according to rules similar to standard C. Only if strings are prefixed with
rorRare they interpreted as regular expressions.The escape sequence that was used indicates that you might have intended to write a regular expression.
Learn more about the available escape sequences. in the Python documentation.