/usr/share/check_mk/checks/zfsget is in check-mk-server 1.2.6p12-1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | #!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# | ____ _ _ __ __ _ __ |
# | / ___| |__ ___ ___| | __ | \/ | |/ / |
# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
# | | |___| | | | __/ (__| < | | | | . \ |
# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
# | |
# | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at http://mathias-kettner.de/check_mk.
#
# check_mk is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation in version 2. check_mk is distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
# out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU General Public License for more de-
# ails. You should have received a copy of the GNU General Public
# License along with GNU Make; see the file COPYING. If not, write
# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301 USA.
# Example output from agent (sizes are in bytes). Note: the part
# [df] in this check is duplicated. We need this information because
# zfsget does not show pass-through filesystems like '/'. :-(
# <<<zfsget>>>
# bpool name bpool -
# bpool quota 0 default
# bpool used 21947036798826 -
# bpool available 11329512075414 -
# bpool mountpoint /bpool default
# bpool type filesystem -
# bpool/acs_fs name bpool/acs_fs -
# bpool/acs_fs quota 0 default
# bpool/acs_fs used 4829131610 -
# bpool/acs_fs available 11329512075414 -
# bpool/acs_fs mountpoint /backup/acs local
# bpool/acs_fs type filesystem -
# [df]
# / 10255636 1836517 8419119 18% /
# /dev 10255636 1836517 8419119 18% /dev
# proc 0 0 0 0% /proc
# ctfs 0 0 0 0% /system/contract
# mnttab 0 0 0 0% /etc/mnttab
# objfs 0 0 0 0% /system/object
# swap 153480592 232 153480360 1% /etc/svc/volatile
# /usr/lib/libc/libc_hwcap1.so.1 10255636 1836517 8419119 18% /lib/libc.so.1
# fd 0 0 0 0% /dev/fd
# swap 2097152 11064 2086088 1% /tmp
# swap 153480384 24 153480360 1% /var/run
# tsrdb10exp/export 5128704 21 4982717 1% /export
# tsrdb10exp/export/home 5128704 55 4982717 1% /home
# tsrdb10exp/export/opt 5128704 145743 4982717 3% /opt
# tsrdb10exp 5128704 21 4982717 1% /tsrdb10exp
# tsrdb10dat 30707712 19914358 10789464 65% /u01
def parse_zfs_entry(info):
def mb(x):
return saveint(x) / (1024.0 * 1024)
entry = {}
for name, what, value in info:
if what in ["used", "available"]:
entry[what] = mb(value)
elif what == "quota":
if value not in [ '0', '-' ]:
entry[what] = mb(value)
elif what in [ 'mountpoint', 'type', 'name' ]:
entry[what] = value
return entry
def parse_zfsget(info):
run_zfs = True
run_df = False
last_name = None
zfs_agent_data = []
zfs_converted = []
df_parsed = {}
for line in info:
if line == ['[zfs]']:
run_zfs = True
run_df = False
continue
if line == ['[df]']:
run_df = True
run_zfs = False
continue
if run_zfs:
name = line[0]
# New block so parse everthing and go on collecting more blocks
if last_name != name:
last_name = name
if zfs_agent_data:
new_entry = parse_zfs_entry(zfs_agent_data)
if new_entry:
zfs_converted.append(new_entry)
zfs_agent_data = []
zfs_agent_data.append(line[:3])
if run_df:
if len(line) == 6:
device, kbytes, used, avail, percent, mountpoint = line
else:
device, fs_type, kbytes, used, avail, percent, mountpoint = line
if mountpoint.startswith("/"):
entry = {}
total = int(kbytes) / 1024.0
entry["name"] = device
entry["total"] = total
entry["used"] = int(used) / 1024.0
entry["available"] = total - entry["used"]
entry["mountpoint"] = mountpoint
df_parsed[mountpoint] = entry
# Now remove duplicate entries for the root filesystem, such
# as /dev/ or /lib/libc.so.1. We do this if size, used and
# avail is equal. I hope that it will not happen too often
# that this is per chance the case for different passed-through
# filesystems
root_entry = df_parsed.get("/")
if root_entry:
t_u_a = (root_entry["total"], root_entry["used"], root_entry["available"])
drop = []
for mountpoint, entry in df_parsed.items():
if mountpoint != "/" and \
t_u_a == (entry["total"], entry["used"], entry["available"]):
drop.append(mountpoint)
for mp in drop:
del df_parsed[mp]
# parsed has the device name as key, because there may exist
# several device names per mount point, and we know only
# later which one to take
zfs_parsed = {}
for entry in zfs_converted:
if entry["mountpoint"].startswith("/"):
entry["is_pool"] = '/' not in entry["name"]
if entry['available'] !=0 and entry['type'] == 'filesystem':
zfs_parsed[entry["name"]] = entry
# parsed_df and parsed_final have the mount point as key
parsed_final = {}
for mountpoint, entry_df in df_parsed.items():
found = False
# for every mount point in the df section, if the device name
# is also present in the "parsed" variable, we take those data
for name, entry in zfs_parsed.items():
if entry_df["name"] == name:
parsed_final[mountpoint] = entry
found = True
# if a mount point in the df section is not present in the
# parsed variable, we take the data from the df section
if not found:
parsed_final[mountpoint] = entry_df
return parsed_final
def inventory_zfsget(info):
mplist = []
parsed = parse_zfsget(info)
for mountpoint, properties in parsed.items():
if mountpoint not in inventory_df_exclude_mountpoints:
mplist.append(mountpoint)
return df_inventory(mplist)
# def convert_zfssize(txt):
# units_to_mb = {
# 'K' : 1/1024.0,
# 'M' : 1.0,
# 'G' : 1024.0,
# 'T' : 1024 * 1024.0,
# 'P' : 1024 * 1024 * 1024.0,
# }
# return float(txt[:-1]) * units_to_mb[txt[-1]]
def check_zfsget(item, params, info):
entries = parse_zfsget(info)
# ist item drin -> OK, ansonsten gleich hier
fslist = []
for mountpoint, entry in entries.items():
if "patterns" in params or item == mountpoint:
# 1. Filesystems with a quota
if "quota" in entry:
used_mb = entry["used"]
total_mb = entry["quota"]
avail_mb = total_mb - used_mb
# 2. Normal filesystems.
else:
used_mb = entry["used"]
avail_mb = entry["available"]
total_mb = used_mb + avail_mb
fslist.append((mountpoint, total_mb, avail_mb))
return df_check_filesystem_list(item, params, fslist)
check_info['zfsget'] = {
"check_function" : check_zfsget,
"inventory_function" : inventory_zfsget,
"service_description" : "Filesystem %s",
"has_perfdata" : True,
"group" : "filesystem",
"default_levels_variable" : "filesystem_default_levels",
"includes" : [ "df.include" ],
}
|