GUI CSS: Deployed view styles for layouts (CMK-1171)
[check_mk.git] / checks / md
blobceae28ee7a096a084e70cd4764b236d974fcdbaf
1 #!/usr/bin/python
2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
9 # | |
10 # | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
11 # +------------------------------------------------------------------+
13 # This file is part of Check_MK.
14 # The official homepage is at http://mathias-kettner.de/check_mk.
16 # check_mk is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation in version 2. check_mk is distributed
19 # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
20 # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 # PARTICULAR PURPOSE. See the GNU General Public License for more de-
22 # tails. You should have received a copy of the GNU General Public
23 # License along with GNU Make; see the file COPYING. If not, write
24 # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 # Boston, MA 02110-1301 USA.
27 # Example for output from agent (contents of /proc/mdstat):
28 # ---------------------------------------------------------
29 # Personalities : [raid1]
30 # md1 : active raid1 dm-19[0] dm-9[1]
31 # 20971456 blocks [2/2] [UU]
32 # 20971456 blocks super 1.2 [2/2] [UU]
34 # md2 : active (auto-read-only) raid1 sda6[0] sdb6[1]
35 # 4200952 blocks super 1.0 [2/2] [UU]
36 # bitmap: 0/9 pages [0KB], 256KB chunk
38 # unused devices: <none>
39 # ---------------------------------------------------------
41 # Another example (with RAID 5 and spare disk (md2) and a RAID-0
42 # device (md3)
43 # ---------------------------------------------------------
44 # Personalities : [raid1] [raid6] [raid5] [raid4]
45 # md2 : active raid5 sde1[3](S) sdd1[0] sdg1[2] sdf1[1]
46 # 976767872 blocks level 5, 64k chunk, algorithm 2 [3/3] [UUU]
48 # md0 : active raid1 sdb1[1] sda1[0]
49 # 104320 blocks [2/2] [UU]
51 # md1 : active raid1 sdb3[1] sda3[0]
52 # 486239232 blocks [2/2] [UU]
54 # md4 : active (auto-read-only) raid1 sda6[0] sdb6[1]
55 # 4200952 blocks super 1.0 [2/2] [UU]
56 # resync=PENDING
57 # bitmap: 9/9 pages [36KB], 256KB chunk
59 # md3 : active raid0 sdb3[0] sda3[1]
60 # 16386048 blocks 64k chunks
62 # unused devices: <none>
63 # ---------------------------------------------------------
65 # Another example with RAID1 replacement gone wrong
66 # ---------------------------------------------------------
67 # Personalities : [raid1]
68 # md0 : active raid1 sdc3[3] sda3[2](F) sdb3[1]
69 # 48837528 blocks super 1.0 [2/2] [UU]
71 # md1 : active raid1 sdc4[3] sda4[2](F) sdb4[1]
72 # 193277940 blocks super 1.0 [2/2] [UU]
74 # unused devices: <none>
75 # ----------------------------------------------------------
77 # Another example with RAID5 being recovered
78 # ---------------------------------------------------------
79 # Personalities : [raid1] [raid6] [raid5] [raid4]
80 # md1 : active raid1 sdd1[1] sdc1[0]
81 # 10484668 blocks super 1.1 [2/2] [UU]
82 # bitmap: 1/1 pages [4KB], 65536KB chunk
84 # md127 : active raid5 sda3[0] sdb3[1] sdd3[4] sdc3[2]
85 # 11686055424 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/3] [UUU_]
86 # [======>..............] recovery = 31.8% (1241578496/3895351808) finish=746.8min speed=59224K/sec
88 # md0 : active raid1 sdb1[1] sda1[0]
89 # 10485688 blocks super 1.0 [2/2] [UU]
90 # bitmap: 0/1 pages [0KB], 65536KB chunk
92 # unused devices: <none>
93 # ----------------------------------------------------------
95 # And now for something completely different:
96 # ---------------------------------------------------------
97 # Personalities : [raid1] [raid10]
98 # md1 : active raid10 sdd6[3] sdb6[1] sda6[0]
99 # 1463055360 blocks 64K chunks 2 near-copies [4/3] [UU_U]
101 # md0 : active raid1 sdd1[3] sdb1[1] sda1[0]
102 # 104320 blocks [4/3] [UU_U]
104 # unused devices: <none>
105 # ---------------------------------------------------------
108 def parse_md(info):
109 parsed = {}
110 instance = {}
111 for line in info:
112 if line[0].startswith("md") and line[1] == ':':
113 if line[3].startswith("(") and line[3].endswith(")"):
114 raid_state = line[2] + line[3]
115 raid_name = line[4]
116 disk_list = line[5:]
117 else:
118 raid_state = line[2]
119 raid_name = line[3]
120 disk_list = line[4:]
122 spare_disks = len([x for x in disk_list if x.endswith("(S)")])
123 failed_disks = len([x for x in disk_list if x.endswith("(F)")])
125 instance = parsed.setdefault(
126 line[0], {
127 'raid_name': raid_name,
128 'raid_state': raid_state,
129 'spare_disks': spare_disks,
130 'failed_disks': failed_disks,
131 'active_disks': len(disk_list) - spare_disks - failed_disks,
134 elif instance:
135 if line[0].startswith("resync="):
136 k, v = line[0].split("=")
137 instance["%s_state" % k] = v
138 continue
140 if line[0].startswith("[") and line[0].endswith("]"):
141 for idx, e in enumerate(line[1:]):
142 if e.startswith("finish=") or e.startswith("speed="):
143 k, v = e.split("=")
144 instance[k] = v
145 elif e in ["recovery", "resync"]:
146 instance["%s_values" % e] = line[idx + 3]
147 continue
149 if line[-1].startswith("[") and line[-1].endswith("]"):
150 instance["working_disks"] = line[-1][1:-1]
152 if len(line) >= 2 and line[-2].startswith("[") and line[-2].endswith("]"):
153 for key, value in zip(["num_disks", "expected_disks"], line[-2][1:-1].split('/')):
154 try:
155 instance[key] = int(value)
156 except ValueError:
157 pass
159 return parsed
162 def inventory_md(parsed):
163 for device, attrs in parsed.iteritems():
164 if attrs["raid_name"] != "raid0":
165 yield device, None
168 def check_md(item, _no_params, parsed):
169 data = parsed.get(item)
170 if data is None:
171 return
173 raid_state = data["raid_state"]
174 infotext = "Status: %s" % raid_state
175 if raid_state == "active" or raid_state == "active(auto-read-only)":
176 state = 0
177 else:
178 infotext += " (should be 'active')"
179 state = 2
180 yield state, infotext
182 spare_disks = data["spare_disks"]
183 failed_disks = data["failed_disks"]
184 active_disks = data["active_disks"]
185 yield 0, "Spare: %s, Failed: %s, Active: %s" % (spare_disks, failed_disks, active_disks)
187 num_disks = data["num_disks"]
188 expected_disks = data["expected_disks"]
189 working_disks = data["working_disks"]
191 infotext = "Status: %s/%s, %s" % (num_disks, expected_disks, working_disks)
192 if num_disks == expected_disks and active_disks == working_disks.count("U"):
193 yield 0, infotext
194 else:
195 yield 2, infotext
197 header = "[Resync/Recovery]"
198 infotexts = []
199 if "resync_state" in data:
200 header = "[Resync]"
201 infotexts.append("Status: %s" % data["resync_state"])
203 if "resync_values" in data:
204 header = "[Resync]"
205 infotexts.append(data["resync_values"])
207 if "recovery_values" in data:
208 header = "[Recovery]"
209 infotexts.append(data["recovery_values"])
211 if "finish" in data:
212 infotexts.append("Finish: %s" % data["finish"])
214 if "speed" in data:
215 infotexts.append("Speed: %s" % data["speed"])
217 if infotexts:
218 yield 1, "%s %s" % (header, ", ".join(infotexts))
221 check_info["md"] = {
222 'parse_function': parse_md,
223 'inventory_function': inventory_md,
224 'check_function': check_md,
225 'service_description': 'MD Softraid %s',
226 'group': 'raid',