Refactoring: Changed all check parameters starting with an 'o' to the new rulespec...
[check_mk.git] / checks / emcvnx_storage_pools
blobf992caf409507c948f14d88924c9d24ce4542fd4
1 #!/usr/bin/python
2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
9 # | |
10 # | Copyright Mathias Kettner 2017 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.
28 def parse_emcvnx_storage_pools(info):
29 parsed = {}
30 section = None
31 pool_name = None
32 tier_name = None
33 for line in info:
34 line = [x.strip() for x in line]
36 if line[0].startswith("[[[") and line[0].endswith("]]]"):
37 section = line[0][3:-3]
39 elif (section == "storage_pools" and line[0] == "Pool Name") or \
40 (section == "auto_tiering" and line[0] == "Storage Pool Name"):
41 pool_name = line[1]
42 parsed.setdefault(pool_name, {})
44 elif pool_name is not None and len(line) == 2:
45 if line[0] == "Tier Name":
46 tier_name = line[1]
47 parsed[pool_name].setdefault("tier_names", [])
48 parsed[pool_name]["tier_names"].append(tier_name)
50 elif line[0] == "Disks (Type)":
51 tier_name = None
53 elif tier_name is not None:
54 parsed[pool_name].setdefault("%s_%s" % (tier_name, line[0]), line[1])
56 else:
57 parsed[pool_name].setdefault(line[0], line[1])
59 return parsed
62 def inventory_emcvnx_storage_pools(parsed):
63 for pool_name in parsed:
64 yield pool_name, {}
67 # .--general-------------------------------------------------------------.
68 # | _ |
69 # | __ _ ___ _ __ ___ _ __ __ _| | |
70 # | / _` |/ _ \ '_ \ / _ \ '__/ _` | | |
71 # | | (_| | __/ | | | __/ | | (_| | | |
72 # | \__, |\___|_| |_|\___|_| \__,_|_| |
73 # | |___/ |
74 # '----------------------------------------------------------------------'
76 # Suggested by customer
77 factory_settings["emcvnx_storage_pools_default_levels"] = {"percent_full": (70.0, 90.0)}
80 def check_emcvnx_storage_pools(item, params, parsed):
81 # Better readable names in web GUI of device:
82 # "User Capacity (GBs)" : "Physical Capacity: Total",
83 # "Consumed Capacity (GBs)" : "Physical Capacity: Total Allocation",
84 # "Available Capacity (GBs)" : "Physical Capacity: Free",
85 # "Percent Full" : "Physical Capacity: Percent Full",
86 # "Percent Subscribed" : "Virtual Capacity: Percent Subscribed",
87 # "Oversubscribed by (GBs)" : "Virtual Capacity: Oversubscribed by",
88 # "Total Subscribed Capacity (GBs)" : "Virtual Capacity: Total Subscription",
90 if item in parsed:
91 data = parsed[item]
92 state = data["State"]
93 status = data["Status"]
94 user_capacity = float(data["User Capacity (GBs)"]) * 1024**3
95 consumed_capacity = float(data["Consumed Capacity (GBs)"]) * 1024**3
96 avail_capacity = float(data["Available Capacity (GBs)"]) * 1024**3
97 percent_full = float(data["Percent Full"])
98 percent_subscribed = float(data["Percent Subscribed"])
99 over_subscribed = float(data["Oversubscribed by (GBs)"]) * 1024**3
100 total_subscribed_capacity = float(data["Total Subscribed Capacity (GBs)"]) * 1024**3
102 yield 0, ("State: %s, Status: %s, [Phys. capacity] User capacity: %s, " +\
103 "Consumed capacity: %s, Available capacity: %s") %\
104 (state, status, get_bytes_human_readable(user_capacity),
105 get_bytes_human_readable(consumed_capacity),
106 get_bytes_human_readable(avail_capacity))
108 state = 0
109 infotext = "Percent full: %s" % get_percent_human_readable(percent_full)
110 if "percent_full" in params:
111 perc_full_warn, perc_full_crit = params["percent_full"]
112 if percent_full >= perc_full_crit:
113 state = 2
114 elif percent_full >= perc_full_warn:
115 state = 1
116 if state:
117 infotext += " (warn/crit at %s/%s)" % \
118 (get_bytes_human_readable(perc_full_warn),
119 get_bytes_human_readable(perc_full_crit))
121 yield state, infotext
122 yield 0, ("[Virt. capacity] Percent subscribed: %s, Oversubscribed by: %s, " +\
123 "Total subscribed capacity: %s") %\
124 (get_percent_human_readable(percent_subscribed),
125 get_bytes_human_readable(over_subscribed),
126 get_bytes_human_readable(total_subscribed_capacity)), [
127 ("emcvnx_consumed_capacity", consumed_capacity),
128 ("emcvnx_avail_capacity", avail_capacity),
129 ("emcvnx_perc_full", percent_full),
130 ("emcvnx_perc_subscribed", percent_subscribed),
131 ("emcvnx_over_subscribed", over_subscribed),
132 ("emcvnx_total_subscribed_capacity", total_subscribed_capacity),
136 check_info['emcvnx_storage_pools'] = {
137 'parse_function': parse_emcvnx_storage_pools,
138 'inventory_function': inventory_emcvnx_storage_pools,
139 'check_function': check_emcvnx_storage_pools,
140 'service_description': 'Pool %s General',
141 'group': 'emcvnx_storage_pools',
142 'has_perfdata': True,
143 'default_levels_variable': 'emcvnx_storage_pools_default_levels',
147 # .--tiering-------------------------------------------------------------.
148 # | _ _ |
149 # | | |_ ___ __ _ _ __(_)_ __ __ _ |
150 # | | __/ _ \/ _` | '__| | '_ \ / _` | |
151 # | | || __/ (_| | | | | | | | (_| | |
152 # | \__\___|\__,_|_| |_|_| |_|\__, | |
153 # | |___/ |
154 # '----------------------------------------------------------------------'
156 # Suggested by customer
157 factory_settings['emcvnx_storage_pools_tiering_default_levels'] = {
158 "time_to_complete": (21 * 60 * 60 * 24, 28 * 60 * 60 * 24),
162 def parse_emcvnx_time_to_complete(time_to_complete):
163 map_units = {
164 "day": 24 * 60 * 60,
165 "hour": 60 * 60,
166 "minute": 60,
168 # 11 days, 17 hours, 24 minutes
169 # 17 hours, 24 minutes
170 # 1 hour, 43 minutes
171 # ...
172 try:
173 seconds = 0
174 for value, unit in [x.strip().split() for x in time_to_complete.split(",")]:
175 if unit.endswith("s"):
176 unit = unit[:-1]
177 seconds += int(value) * map_units[unit]
178 return seconds
179 except:
180 return
183 def inventory_emcvnx_storage_pools_tiering(parsed):
184 for pool_name in parsed.iterkeys():
185 yield pool_name, {}
188 def check_emcvnx_storage_pools_tiering(item, params, parsed):
189 if item in parsed:
190 data = parsed[item]
191 fast_cache = data["FAST Cache"]
192 relocation_status = data["Relocation Status"]
193 relocation_rate = data["Relocation Rate"]
194 move_up = float(data["Data to Move Up (GBs)"]) * 1024**3
195 move_down = float(data["Data to Move Down (GBs)"]) * 1024**3
196 move_within = float(data["Data to Move Within Tiers (GBs)"]) * 1024**3
197 move_completed = float(data["Data Movement Completed (GBs)"]) * 1024**3
198 time_to_complete = data["Estimated Time to Complete"]
199 age = parse_emcvnx_time_to_complete(time_to_complete)
201 infotext = ("Fast cache: %s, Relocation status: %s, Relocation rate: %s, " +\
202 "Move up: %s, Move down: %s, Move within: %s, " +\
203 "Movement completed: %s") %\
204 (fast_cache, relocation_status, relocation_rate,
205 get_bytes_human_readable(move_up),
206 get_bytes_human_readable(move_down),
207 get_bytes_human_readable(move_within),
208 get_bytes_human_readable(move_completed))
210 yield 0, infotext, [
211 ("emcvnx_move_up", move_up),
212 ("emcvnx_move_down", move_down),
213 ("emcvnx_move_within", move_within),
214 ("emcvnx_move_completed", move_completed),
217 if age is not None:
218 infotext = "Estimated time to complete: %s" % time_to_complete
219 warn, crit = params["time_to_complete"]
220 state = 0
221 if age > crit:
222 state = 2
223 elif age > warn:
224 state = 1
225 if state:
226 infotext += " (warn/crit at %s/%s)" % (get_age_human_readable(warn),
227 get_age_human_readable(crit))
228 yield state, infotext, [("emcvnx_time_to_complete", age)]
231 check_info['emcvnx_storage_pools.tiering'] = {
232 'inventory_function': inventory_emcvnx_storage_pools_tiering,
233 'check_function': check_emcvnx_storage_pools_tiering,
234 'service_description': 'Pool %s Tiering Status',
235 'has_perfdata': True,
236 'group': 'emcvnx_storage_pools_tiering',
237 'default_levels_variable': 'emcvnx_storage_pools_tiering_default_levels',
241 def inventory_emcvnx_storage_pools_tieringtypes(parsed):
242 for pool_name, data in parsed.items():
243 for tier_name in data.get("tier_names", []):
244 yield "%s %s" % (pool_name, tier_name), {}
247 def check_emcvnx_storage_pools_tieringtypes(item, params, parsed):
248 for pool_name, data in parsed.items():
249 for tier_name in data.get("tier_names", []):
250 if item == "%s %s" % (pool_name, tier_name):
251 user_capacity = float(data["%s_User Capacity (GBs)" % tier_name]) * 1024**3
252 consumed_capacity = float(data["%s_Consumed Capacity (GBs)" % tier_name]) * 1024**3
253 avail_capacity = float(data["%s_Available Capacity (GBs)" % tier_name]) * 1024**3
254 percent_subscribed = float(data["%s_Percent Subscribed" % tier_name].replace(
255 "%", ""))
256 targeted_higher = float(
257 data["%s_Data Targeted for Higher Tier (GBs)" % tier_name]) * 1024**3
258 targeted_lower = float(
259 data["%s_Data Targeted for Lower Tier (GBs)" % tier_name]) * 1024**3
260 targeted_within = float(
261 data["%s_Data Targeted Within Tier (GBs)" % tier_name]) * 1024**3
263 infotext = ("User capacity: %s, Consumed capacity: %s, Available capacity: %s, " +\
264 "Percent subscribed: %s, Move up: %s, Move down: %s, Move within: %s") %\
265 (get_bytes_human_readable(user_capacity),
266 get_bytes_human_readable(consumed_capacity),
267 get_bytes_human_readable(avail_capacity),
268 get_percent_human_readable(percent_subscribed),
269 get_bytes_human_readable(targeted_higher),
270 get_bytes_human_readable(targeted_lower),
271 get_bytes_human_readable(targeted_within))
273 return 0, infotext, [
274 ("emcvnx_consumed_capacity", consumed_capacity),
275 ("emcvnx_avail_capacity", avail_capacity),
276 ("emcvnx_perc_subscribed", percent_subscribed),
277 ("emcvnx_targeted_higher", targeted_higher),
278 ("emcvnx_targeted_lower", targeted_lower),
279 ("emcvnx_targeted_within", targeted_within),
283 check_info['emcvnx_storage_pools.tieringtypes'] = {
284 'inventory_function': inventory_emcvnx_storage_pools_tieringtypes,
285 'check_function': check_emcvnx_storage_pools_tieringtypes,
286 'service_description': 'Pool %s tiering',
287 'has_perfdata': True,
291 # .--deduplication-------------------------------------------------------.
292 # | _ _ _ _ _ _ |
293 # | __| | ___ __| |_ _ _ __ | (_) ___ __ _| |_(_) ___ _ __ |
294 # | / _` |/ _ \/ _` | | | | '_ \| | |/ __/ _` | __| |/ _ \| '_ \ |
295 # | | (_| | __/ (_| | |_| | |_) | | | (_| (_| | |_| | (_) | | | | |
296 # | \__,_|\___|\__,_|\__,_| .__/|_|_|\___\__,_|\__|_|\___/|_| |_| |
297 # | |_| |
298 # '----------------------------------------------------------------------'
301 def _emcvnx_get_text_perf(data, key, perfname, format_func=get_bytes_human_readable, factor=1024
302 **3):
303 field = data.get(key, "unknown")
304 try:
305 value = float(field) * factor
306 return format_func(value), [(perfname, value)]
307 except ValueError:
308 return str(field), []
311 @get_parsed_item_data
312 def check_emcvnx_storage_pools_deduplication(_no_item, _no_params, data):
314 yield 0, "State: %s" % data.get("Deduplication State", "unknown")
315 yield 0, "Status: %s" % data.get("Deduplication Status", "unknown").split("(")[0]
316 yield 0, "Rate: %s" % data.get("Deduplication Rate", "unknown")
318 txt, perf = _emcvnx_get_text_perf(data, "Efficiency Savings (GBs)",
319 "emcvnx_dedupl_efficiency_savings")
320 yield 0, "Efficiency savings: %s" % txt, perf
322 txt, perf = _emcvnx_get_text_perf(
323 data,
324 "Deduplication Percent Completed",
325 "emcvnx_dedupl_perc_completed",
326 format_func=get_percent_human_readable,
327 factor=1.0)
328 yield 0, "Percent completed: %s" % txt, perf
330 txt, perf = _emcvnx_get_text_perf(data, "Deduplication Remaining Size (GBs)",
331 "emcvnx_dedupl_remaining_size")
332 yield 0, "Remaining size: %s" % txt, perf
334 txt, perf = _emcvnx_get_text_perf(data, "Deduplication Shared Capacity (GBs)",
335 "emcvnx_dedupl_shared_capacity")
336 yield 0, "Shared capacity: %s" % txt, perf
339 check_info['emcvnx_storage_pools.deduplication'] = {
340 'inventory_function': inventory_emcvnx_storage_pools,
341 'check_function': check_emcvnx_storage_pools_deduplication,
342 'service_description': 'Pool %s Deduplication',
343 'has_perfdata': True,