/usr/share/check_mk/checks/md 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 | #!/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 for output from agent (contents of /proc/mdstat):
# ---------------------------------------------------------
# Personalities : [raid1]
# md1 : active raid1 dm-19[0] dm-9[1]
# 20971456 blocks [2/2] [UU]
# 20971456 blocks super 1.2 [2/2] [UU]
#
# md2 : active (auto-read-only) raid1 sda6[0] sdb6[1]
# 4200952 blocks super 1.0 [2/2] [UU]
# bitmap: 0/9 pages [0KB], 256KB chunk
#
# unused devices: <none>
# ---------------------------------------------------------
# Another example (with RAID 5 and spare disk (md2) and a RAID-0
# device (md3)
# ---------------------------------------------------------
# Personalities : [raid1] [raid6] [raid5] [raid4]
# md2 : active raid5 sde1[3](S) sdd1[0] sdg1[2] sdf1[1]
# 976767872 blocks level 5, 64k chunk, algorithm 2 [3/3] [UUU]
#
# md0 : active raid1 sdb1[1] sda1[0]
# 104320 blocks [2/2] [UU]
#
# md1 : active raid1 sdb3[1] sda3[0]
# 486239232 blocks [2/2] [UU]
#
# md4 : active (auto-read-only) raid1 sda6[0] sdb6[1]
# 4200952 blocks super 1.0 [2/2] [UU]
# resync=PENDING
# bitmap: 9/9 pages [36KB], 256KB chunk
#
# md3 : active raid0 sdb3[0] sda3[1]
# 16386048 blocks 64k chunks
#
# unused devices: <none>
# ---------------------------------------------------------
# Another example with RAID1 replacement gone wrong
# ---------------------------------------------------------
# Personalities : [raid1]
# md0 : active raid1 sdc3[3] sda3[2](F) sdb3[1]
# 48837528 blocks super 1.0 [2/2] [UU]
#
# md1 : active raid1 sdc4[3] sda4[2](F) sdb4[1]
# 193277940 blocks super 1.0 [2/2] [UU]
#
# unused devices: <none>
# ----------------------------------------------------------
# Another example with RAID5 being recovered
# ---------------------------------------------------------
# Personalities : [raid1] [raid6] [raid5] [raid4]
# md1 : active raid1 sdd1[1] sdc1[0]
# 10484668 blocks super 1.1 [2/2] [UU]
# bitmap: 1/1 pages [4KB], 65536KB chunk
#
# md127 : active raid5 sda3[0] sdb3[1] sdd3[4] sdc3[2]
# 11686055424 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/3] [UUU_]
# [======>..............] recovery = 31.8% (1241578496/3895351808) finish=746.8min speed=59224K/sec
#
# md0 : active raid1 sdb1[1] sda1[0]
# 10485688 blocks super 1.0 [2/2] [UU]
# bitmap: 0/1 pages [0KB], 65536KB chunk
#
# unused devices: <none>
# ----------------------------------------------------------
# And now for something completely different:
# ---------------------------------------------------------
# Personalities : [raid1] [raid10]
# md1 : active raid10 sdd6[3] sdb6[1] sda6[0]
# 1463055360 blocks 64K chunks 2 near-copies [4/3] [UU_U]
#
# md0 : active raid1 sdd1[3] sdb1[1] sda1[0]
# 104320 blocks [4/3] [UU_U]
#
# unused devices: <none>
# ---------------------------------------------------------
# TODO: Write a parse function!
def inventory_md(info):
inventory = []
for line in info:
if len(line) < 3:
continue
if line[0].startswith("md") and line[1] == ':':
device = line[0]
raid_state = line[2]
elif line[1] == 'blocks':
if line[-1] != "chunks": # ignore RAID 0 devices
disk_state = line[-1][1:-1]
inventory.append( (device, None) )
return inventory
def check_md(item, _no_params, info):
raid_state = ''
its_next = False
state_next = False
for line in info:
if line[0] == item and line[1] == ':':
raid_state = line[2]
if raid_state != 'active' and raid_state != 'active(auto-read-only)':
return (2, "raid state is '%s' (should be 'active')" % (raid_state,))
# Usually (auto-read-only) sticks to active without a space.
# But on some kernels it appears separated by a space
if line[3] == '(auto-read-only)':
del line[3]
all_disks = len([x for x in line[4:]]) # all disks
spare_disks = len([x for x in line[4:] if x.endswith("(S)") ]) # spare disks
failed_disks = len([x for x in line[4:] if x.endswith("(F)") ]) # failed disks
active_disks = all_disks - spare_disks - failed_disks
its_next = True
elif its_next:
disk_state_1 = line[-2]
(num_disks, expected_disks) = map(int,disk_state_1[1:-1].split('/'))
disk_state_2 = line[-1]
working_disks = disk_state_2.count('U')
state_next = True
its_next = False
elif state_next:
if num_disks == expected_disks and active_disks == working_disks:
return (0, 'raid active, disk state is %s %s' % (disk_state_1, disk_state_2))
if len(line) > 6 and line[-6] != '' and "speed=" in line[-1]:
build_state_1 = line[-6]
build_state_2 = line[-4]
build_est = line[-2].partition('=')[2]
build_speed = float(line[-1].partition('=')[2][:-5]) / 1024
return (1, 'disk state is %s %s (expected %d disks to be up) - %s %s @ %.1fMB/s (%s)' %
(disk_state_1, disk_state_2, expected_disks, build_state_1, build_state_2, build_speed, build_est))
return (2, 'disk state is %s %s (expected %d disks to be up)' %
(disk_state_1, disk_state_2, expected_disks))
return (2, 'no RAID device %s' % item)
check_info["md"] = {
'check_function': check_md,
'inventory_function': inventory_md,
'service_description': 'MD Softraid %s',
'group': 'raid',
}
|