2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
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
):
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"):
42 parsed
.setdefault(pool_name
, {})
44 elif pool_name
is not None and len(line
) == 2:
45 if line
[0] == "Tier Name":
47 parsed
[pool_name
].setdefault("tier_names", [])
48 parsed
[pool_name
]["tier_names"].append(tier_name
)
50 elif line
[0] == "Disks (Type)":
53 elif tier_name
is not None:
54 parsed
[pool_name
].setdefault("%s_%s" % (tier_name
, line
[0]), line
[1])
57 parsed
[pool_name
].setdefault(line
[0], line
[1])
62 def inventory_emcvnx_storage_pools(parsed
):
63 for pool_name
in parsed
:
67 # .--general-------------------------------------------------------------.
69 # | __ _ ___ _ __ ___ _ __ __ _| | |
70 # | / _` |/ _ \ '_ \ / _ \ '__/ _` | | |
71 # | | (_| | __/ | | | __/ | | (_| | | |
72 # | \__, |\___|_| |_|\___|_| \__,_|_| |
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",
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
))
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
:
114 elif percent_full
>= perc_full_warn
:
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-------------------------------------------------------------.
149 # | | |_ ___ __ _ _ __(_)_ __ __ _ |
150 # | | __/ _ \/ _` | '__| | '_ \ / _` | |
151 # | | || __/ (_| | | | | | | | (_| | |
152 # | \__\___|\__,_|_| |_|_| |_|\__, | |
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
):
168 # 11 days, 17 hours, 24 minutes
169 # 17 hours, 24 minutes
174 for value
, unit
in [x
.strip().split() for x
in time_to_complete
.split(",")]:
175 if unit
.endswith("s"):
177 seconds
+= int(value
) * map_units
[unit
]
183 def inventory_emcvnx_storage_pools_tiering(parsed
):
184 for pool_name
in parsed
.iterkeys():
188 def check_emcvnx_storage_pools_tiering(item
, params
, parsed
):
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
))
211 ("emcvnx_move_up", move_up
),
212 ("emcvnx_move_down", move_down
),
213 ("emcvnx_move_within", move_within
),
214 ("emcvnx_move_completed", move_completed
),
218 infotext
= "Estimated time to complete: %s" % time_to_complete
219 warn
, crit
= params
["time_to_complete"]
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(
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-------------------------------------------------------.
293 # | __| | ___ __| |_ _ _ __ | (_) ___ __ _| |_(_) ___ _ __ |
294 # | / _` |/ _ \/ _` | | | | '_ \| | |/ __/ _` | __| |/ _ \| '_ \ |
295 # | | (_| | __/ (_| | |_| | |_) | | | (_| (_| | |_| | (_) | | | | |
296 # | \__,_|\___|\__,_|\__,_| .__/|_|_|\___\__,_|\__|_|\___/|_| |_| |
298 # '----------------------------------------------------------------------'
301 def _emcvnx_get_text_perf(data
, key
, perfname
, format_func
=get_bytes_human_readable
, factor
=1024
303 field
= data
.get(key
, "unknown")
305 value
= float(field
) * factor
306 return format_func(value
), [(perfname
, value
)]
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(
324 "Deduplication Percent Completed",
325 "emcvnx_dedupl_perc_completed",
326 format_func
=get_percent_human_readable
,
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,