Skip to content

Commit

Permalink
feat(disk-usage): add --list-fstypes and --fstype for specifying …
Browse files Browse the repository at this point in the history
…the file system type
  • Loading branch information
markuslf committed Dec 9, 2024
1 parent 23831aa commit 31745d3
Show file tree
Hide file tree
Showing 4 changed files with 241 additions and 74 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Monitoring Plugins:
* about-me: Add Moodle detection
* dhcp-scope-usage: Ignore PercentageInUse fractions
* disk-io: Re-add support for Windows after last rewrite
* disk-usage: Add `--list-fstypes` and `--fstype` for specifying the file system type
* fail2ban: More compact output (closes #141)
* fs-inodes: Check inode usage on real and different disks. `--mount` parameter is deprecated.
* librenms-alerts, librenms-health: Compact output is the new default and shows non-OK only
Expand Down
71 changes: 45 additions & 26 deletions check-plugins/disk-usage/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ Check disk-usage
Overview
--------

Measures the usage of all mounted disk *partitions* on physical disks only (e.g. hard disks, CD-ROM drives, USB keys) found. It does not check the usage on the raw disks, because for example in LVM more than one disk can be a member of a logical volume, and some of the disks might be full - which is ok as long as the LVM has some space available. The check also ignores all other partition types (e.g. memory partitions such as ``/dev/shm``).
Measures the usage of all mounted disk *partitions*. It does not check the usage on the raw disks, because in LVM for example, more than one disk can be a member of a logical volume, and some of the disks might be full - which is fine as long as LVM has some space available.

By default, this plugin only checks physical devices (e.g. hard disks, CD-ROM drives, USB keys) and ignores all others (e.g. pseudo, memory, duplicate, inaccessible file systems). You can override this behaviour by using the ``--fstype`` parameter and specifying which file system types should be checked explicitly.

To get a list of file system types you can specify, run ``disk-usage --list-fstype`` first (as file system types are machine dependent).

.. note::

UNIX usually reserves 5% of the total disk space for the root user. ``total`` and ``used`` fields on UNIX refer to the overall total and used space, whereas ``free`` represents the space available for the user and ``percent`` represents the user utilization. That is why percent value may look 5% bigger than what you would expect it to be (starting with psutil v4.3.0; quote from the `psutil documentation <https://psutil.readthedocs.io/en/latest/>`_).
UNIX usually reserves 5% of the total disk space for the root user. ``total`` and ``used`` fields on UNIX refer to the overall total and used space, whereas ``free`` represents the space available for the user and ``percent`` represents the user utilization. That is why ``percent`` value may look 5% bigger than what you would expect it to be (starting with psutil v4.3.0; quote from the `psutil documentation <https://psutil.readthedocs.io/en/latest/>`_).

Hints:

Expand Down Expand Up @@ -36,9 +40,9 @@ Help
usage: disk-usage [-h] [-V] [--always-ok] [-c CRIT]
[--exclude-pattern EXCLUDE_PATTERN]
[--exclude-regex EXCLUDE_REGEX]
[--exclude-regex EXCLUDE_REGEX] [--fstype FSTYPE]
[--include-pattern INCLUDE_PATTERN]
[--include-regex INCLUDE_REGEX]
[--include-regex INCLUDE_REGEX] [--list-fstypes]
[--perfdata-regex PERFDATA_REGEX] [-w WARN]
Checks the used disk space, for each partition.
Expand All @@ -59,31 +63,44 @@ Help
Other self-explanatory examples are `95%USED`,
`5%FREE`, `9.5GFREE`, `1400GUSED`. Default: 95%USED
--exclude-pattern EXCLUDE_PATTERN
Any line matching this pattern (case-insensitive) will
count as a exclude. The mountpoint is excluded if it
contains the specified value. Example: "boot" excludes
"/boot" as well as "/boot/efi". Can be specified
multiple times. On Windows, use drive letters without
backslash ("Y:" or "Y"). Includes are matched before
excludes.
Any mountpoint matching this pattern (case-
insensitive) will count as an exclude. The mountpoint
is excluded if it contains the specified value.
Example: "boot" excludes "/boot" as well as
"/boot/efi". Can be specified multiple times. On
Windows, use drive letters without backslash ("Y:" or
"Y"). Includes are matched before excludes.
--exclude-regex EXCLUDE_REGEX
Any line matching this python regex (case-insensitive)
will count as a exclude. Can be specified multiple
times. On Windows, use drive letters without backslash
("Y:" or "Y"). Includes are matched before excludes.
Any mountpoint matching this python regex (case-
insensitive) will count as an exclude. Can be
specified multiple times. On Windows, use drive
letters without backslash ("Y:" or "Y"). Includes are
matched before excludes.
--fstype FSTYPE By default, this plugin only checks physical devices
(e.g. hard disks, CD-ROM drives, USB keys) and ignores
all others (e.g. pseudo, memory, duplicate,
inaccessible file systems). You can override this
behaviour with this parameter by specifying which file
system types should be checked explicitly. Can be
specified multiple times. To get a list of file system
types you can specify, run `disk-usage --list-fstype`
first (as file system types are machine dependent).
--include-pattern INCLUDE_PATTERN
Any line matching this pattern (case-insensitive) will
count as a include. The mountpoint is included if it
contains the specified value. Example: "boot" includes
"/boot" as well as "/boot/efi". Can be specified
multiple times. On Windows, use drive letters without
backslash ("Y:" or "Y"). Includes are matched before
excludes.
Any mountpoint matching this pattern (case-
insensitive) will count as an include. The mountpoint
is included if it contains the specified value.
Example: "boot" includes "/boot" as well as
"/boot/efi". Can be specified multiple times. On
Windows, use drive letters without backslash ("Y:" or
"Y"). Includes are matched before excludes.
--include-regex INCLUDE_REGEX
Any line matching this python regex (case-insensitive)
will count as a include. Can be specified multiple
times. On Windows, use drive letters without backslash
("Y:" or "Y"). Includes are matched before excludes.
Any mountpoint matching this python regex (case-
insensitive) will count as an include. Can be
specified multiple times. On Windows, use drive
letters without backslash ("Y:" or "Y"). Includes are
matched before excludes.
--list-fstypes Show which file system types are available and which
are checked by default.
--perfdata-regex PERFDATA_REGEX
Only print perfdata keys matching this python regex.
For a list of perfdata keys, have a look at the README
Expand Down Expand Up @@ -165,6 +182,8 @@ Some other examples:
./disk-usage --exclude-pattern=/var/log --exclude-pattern=/tmp --warning=80%USED --critical=90%USED
./disk-usage --exclude-pattern=/var/log --exclude-pattern=/tmp --warning=80%USED --critical=3GFREE
./disk-usage --fstype=btrfs --fstype=vfat
./disk-usage --perfdata-pattern='/-usage'
./disk-usage --perfdata-pattern='var.*-usage'
Expand Down
111 changes: 90 additions & 21 deletions check-plugins/disk-usage/disk-usage
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ except ImportError:


__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
__version__ = '2023112901'
__version__ = '2024120901'

DESCRIPTION = 'Checks the used disk space, for each partition.'

Expand Down Expand Up @@ -75,7 +75,7 @@ def parse_args():

parser.add_argument(
'--exclude-pattern',
help='Any line matching this pattern (case-insensitive) will count as a exclude. '
help='Any mountpoint matching this pattern (case-insensitive) will count as an exclude. '
'The mountpoint is excluded if it contains the specified value. '
'Example: "boot" excludes "/boot" as well as "/boot/efi". '
'Can be specified multiple times. '
Expand All @@ -88,7 +88,8 @@ def parse_args():

parser.add_argument(
'--exclude-regex',
help='Any line matching this python regex (case-insensitive) will count as a exclude. '
help='Any mountpoint matching this python regex (case-insensitive) will count '
'as an exclude. '
'Can be specified multiple times. '
'On Windows, use drive letters without backslash ("Y:" or "Y"). '
'Includes are matched before excludes.',
Expand All @@ -97,9 +98,23 @@ def parse_args():
default=[],
)

parser.add_argument(
'--fstype',
help='By default, this plugin only checks physical devices (e.g. hard disks, '
'CD-ROM drives, USB keys) and ignores all others (e.g. pseudo, memory, duplicate, '
'inaccessible file systems). You can override this behaviour with this parameter by '
'specifying which file system types should be checked explicitly. '
'Can be specified multiple times. '
'To get a list of file system types you can specify, run `disk-usage --list-fstype` '
'first (as file system types are machine dependent).',
dest='FSTYPE',
action='append',
default=[],
)

parser.add_argument(
'--include-pattern',
help='Any line matching this pattern (case-insensitive) will count as a include. '
help='Any mountpoint matching this pattern (case-insensitive) will count as an include. '
'The mountpoint is included if it contains the specified value. '
'Example: "boot" includes "/boot" as well as "/boot/efi". '
'Can be specified multiple times. '
Expand All @@ -112,7 +127,8 @@ def parse_args():

parser.add_argument(
'--include-regex',
help='Any line matching this python regex (case-insensitive) will count as a include. '
help='Any mountpoint matching this python regex (case-insensitive) will count '
'as an include. '
'Can be specified multiple times. '
'On Windows, use drive letters without backslash ("Y:" or "Y"). '
'Includes are matched before excludes.',
Expand All @@ -121,6 +137,14 @@ def parse_args():
default=[],
)

parser.add_argument(
'--list-fstypes',
help='Show which file system types are available and which are checked by default.',
dest='LIST_FSTYPES',
action='store_true',
default=False,
)

parser.add_argument(
'--perfdata-regex',
help='Only print perfdata keys matching this python regex. '
Expand Down Expand Up @@ -169,6 +193,41 @@ def compile_regex(regex, what):
)


def list_fstypes():
"""Print a nice table showing which file system types exist and which are checked by default.
"""
# get all partitions, no matter which ones
parts = psutil.disk_partitions(all=True)
table_data = []
for part in parts:
table_data.append({
'fstype': part.fstype,
'mountpoint': part.mountpoint,
'device': part.device,
'checked': False,
})

# get which ones are checked by default
try:
parts = psutil.disk_partitions(all=False)
except AttributeError:
pass
for i, item in enumerate(table_data):
for part in parts:
if part.mountpoint == item['mountpoint']:
table_data[i]['checked'] = True
continue

# sort table by fstype, mountpoint
keys = [
'fstype',
'mountpoint',
'device',
'checked'
]
lib.base.oao(lib.base.get_table(table_data, keys, header=keys, sort_by_key='fstype'), STATE_OK)


def main():
"""The main function. Hier spielt die Musik.
"""
Expand All @@ -183,27 +242,31 @@ def main():
float(args.WARN[0])
float(args.CRIT[0])
except ValueError:
lib.base.oao(
'Invalid parameter value.',
STATE_UNKNOWN,
)
compiled_include_regex = compile_regex(args.INCLUDE_REGEX, 'include-regex')
compiled_exclude_regex = compile_regex(args.EXCLUDE_REGEX, 'exclude-regex')
compiled_perfdata_regex = compile_regex(args.PERFDATA_REGEX, 'perfdata-regex')
lib.base.cu('Invalid parameter value.')

# show partition information and exit
if args.LIST_FSTYPES:
list_fstypes()

# init some vars
state = STATE_OK
perfdata = ''
table_data = []
compiled_include_regex = compile_regex(args.INCLUDE_REGEX, 'include-regex')
compiled_exclude_regex = compile_regex(args.EXCLUDE_REGEX, 'exclude-regex')
compiled_perfdata_regex = compile_regex(args.PERFDATA_REGEX, 'perfdata-regex')

# analyze data
try:
parts = psutil.disk_partitions(all=False)
except AttributeError:
lib.base.oao(
'Did not find physical devices (e.g. hard disks, cd-rom drives, USB keys).',
STATE_UNKNOWN,
)
if args.FSTYPE:
# user wants to check file system types on his own
parts = psutil.disk_partitions(all=True)
else:
# default behaviour - check physical devices only (e.g. hard disks, cd-rom drives, USB keys)
# and ignore all others (e.g. pseudo, memory, duplicate, inaccessible filesystems)
try:
parts = psutil.disk_partitions(all=False)
except AttributeError:
lib.base.cu('Did not find physical devices (e.g. hard disks, cd-rom drives, USB keys).')

for part in parts:
# sdiskpart(device='/dev/vda2', mountpoint='/', fstype='ext4', opts='rw,relatime')
Expand All @@ -214,8 +277,14 @@ def main():
# opts='ro,nosuid,nodev,relatime,uid=0,gid=0,iocharset=utf8,mode=0400,dmode=0500'
# )
# ignore `/snap`, iso mountpoints and cdroms (UDF = universal disk format)
if part.fstype in ['CDFS', 'iso9660', 'squashfs', 'UDF'] or part.opts in ['cdrom']:
continue
if args.FSTYPE:
# user wants to check file system types on his own
if part.fstype not in args.FSTYPE:
continue
else:
# default behaviour - ignore read-only and some other filesystems
if part.fstype in ['CDFS', 'iso9660', 'squashfs', 'UDF'] or part.opts in ['cdrom']:
continue

# include (first) and exclude (second) specific partitions
# hint: we can't do `if not part or part.mountpoint in args.IGNORE:` because it is
Expand Down
Loading

0 comments on commit 31745d3

Please sign in to comment.