Refactored snapin server_time to new snapin API
[check_mk.git] / checks / ucs_bladecenter_if
blob3b1715d9fb46b5dd6cee8cfe4933f51d16a9b867
1 #!/usr/bin/python
2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
9 # | |
10 # | Copyright Mathias Kettner 2013 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 # <<ucs_bladecenter_if:sep(9)>>>
28 # fcStats Dn sys/switch-A/slot-1/switch-fc/port-37/stats BytesRx 2411057759048 BytesTx 1350394110752 Suspect no
29 # fcStats Dn sys/switch-A/slot-1/switch-fc/port-40/stats BytesRx 0 BytesTx 0 Suspect no
30 # fcErrStats Dn sys/switch-B/slot-1/switch-fc/port-47/err-stats CrcRx 0 DiscardRx 0 DiscardTx 0
31 # fcErrStats Dn sys/switch-B/slot-1/switch-fc/port-48/err-stats CrcRx 0 DiscardRx 0 DiscardTx 0
32 # fabricFcSanEp Dn fabric/san/A/phys-slot-1-port-40 EpDn sys/switch-A/slot-1/switch-fc/port-40 AdminState disabled OperState up
33 # fabricFcSanEp Dn fabric/san/A/phys-slot-1-port-41 EpDn sys/switch-A/slot-1/switch-fc/port-41 AdminState disabled OperState up
35 # Example interfaces
36 # fibrechannel:
37 # 'sys/switch-A/slot-1/switch-fc/port-38':
38 # {'AdminState': 'enabled',
39 # 'BytesRx': '51789849113704',
40 # 'BytesTx': '15914991789936',
41 # 'CrcRx': '1',
42 # 'DiscardRx': '0',
43 # 'DiscardTx': '0',
44 # 'EpDn': 'sys/switch-A/slot-1/switch-fc/port-38',
45 # 'OperState': 'up',
46 # 'PacketsRx': '26771306796',
47 # 'PacketsTx': '8735571946',
48 # 'PortId': '38',
49 # 'Rx': '1',
50 # 'SlotId': '1',
51 # 'Suspect': 'no',
52 # 'SwitchId': 'A',
53 # 'Tx': '0'},
54 # ethernet:
55 # 'sys/switch-A/slot-1/switch-ether/port-18':
56 # {'AdminState': 'enabled',
57 # 'Dn': 'fabric/lan/A/pc-1/ep-slot-1-port-18',
58 # 'EpDn': 'sys/switch-A/slot-1/switch-ether/port-18',
59 # 'OperState': 'up',
60 # 'PortId': '18',
61 # 'SlotId': '1',
62 # 'SwitchId': 'A',
63 # 'etherRxStats': {'BroadcastPackets': '116544272',
64 # 'Dn': 'sys/switch-A/slot-1/switch-ether/port-18/rx-stats',
65 # 'MulticastPackets': '560456841',
66 # 'TotalBytes': '53066141169147',
67 # 'UnicastPackets': '138412352259'},
68 # 'etherTxStats': {'BroadcastPackets': '4922247',
69 # 'Dn': 'sys/switch-A/slot-1/switch-ether/port-18/tx-stats',
70 # 'MulticastPackets': '82743790',
71 # 'TotalBytes': '79420242621595',
72 # 'UnicastPackets': '135007642584'},
73 # interconnect:
74 # 'sys/switch-A/slot-1/switch-ether/port-2':
75 # {'AdminState': 'enabled',
76 # 'Dn': 'fabric/server/sw-A/pc-1025/ep-slot-1-port-2',
77 # 'EpDn': 'sys/switch-A/slot-1/switch-ether/port-2',
78 # 'OperState': 'up',
79 # 'PortId': '2',
80 # 'SlotId': '1',
81 # 'SwitchId': 'A',
82 # 'etherErrStats': {'Dn': 'sys/switch-A/slot-1/switch-ether/port-2/err-stats',
83 # 'OutDiscard': '0',
84 # 'Rcv': '0'},
85 # 'etherRxStats': {'BroadcastPackets': '50432549',
86 # 'Dn': 'sys/switch-A/slot-1/switch-ether/port-2/rx-stats',
87 # 'MulticastPackets': '80349542',
88 # 'TotalBytes': '50633308808192',
89 # 'UnicastPackets': '53535107978'},
90 # 'etherTxStats': {'BroadcastPackets': '4892153',
91 # 'Dn': 'sys/switch-A/slot-1/switch-ether/port-2/tx-stats',
92 # 'MulticastPackets': '328878878',
93 # 'TotalBytes': '97004901202254',
94 # 'UnicastPackets': '79555260499'},
95 # 'portchannel': {'AdminState': 'enabled',
96 # 'Dn': 'fabric/server/sw-A/pc-1025',
97 # 'OperSpeed': '10gbps',
98 # 'OperState': 'up',
99 # 'PortId': '1025',
100 # 'members': 4}},
103 # We need to fill this structure
104 # converted = [
105 # [], # 0 ifIndex 0
106 # [], # 1 ifDescr 1
107 # [], # 2 ifType 2
108 # [], # 3 ifHighSpeed .. 1000 means 1Gbit
109 # [], # 4 ifOperStatus 4
110 # [], # 5 ifHCInOctets 5
111 # [], # 6 ifHCInUcastPkts 6
112 # [], # 7 ifHCInMulticastPkts 7
113 # [], # 8 ifHCInBroadcastPkts 8
114 # [], # 9 ifInDiscards 9
115 # [], # 10 ifInErrors 10
116 # [], # 11 ifHCOutOctets 11
117 # [], # 12 ifHCOutUcastPkts 12
118 # [], # 13 ifHCOutMulticastPkts 13
119 # [], # 14 ifHCOutBroadcastPkts 14
120 # [], # 15 ifOutDiscards 15
121 # [], # 16 ifOutErrors 16
122 # [], # 17 ifOutQLen 17
123 # [], # 18 ifAlias 18
124 # [], # 19 ifPhysAddress 19
127 # Specify which values are to put into the resulting interface
128 tableindex = {
129 "fibrechannel": {
130 # a list of class and field
131 2: "6", # This means Ethernet. We should set the real type here
132 # if.include does not support the interface type 56
133 5: [ ("fcStats", "BytesRx") ],
134 6: [ ("fcStats", "PacketsRx") ],
135 9: [ ("fcErrStats", "DiscardRx") ],
136 10: [ ("fcErrStats", "Rx"), ("fcErrStats", "CrcRx") ],
138 11: [ ("fcStats", "BytesTx") ],
139 12: [ ("fcStats", "PacketsTx") ],
140 15: [ ("fcErrStats", "DiscardTx") ],
141 16: [ ("fcErrStats", "Tx") ]
143 "ethernet": {
144 2: "6",
145 5: [ ("etherRxStats", "TotalBytes") ],
146 6: [ ("etherRxStats", "UnicastPackets") ],
147 7: [ ("etherRxStats", "MulticastPackets") ],
148 8: [ ("etherRxStats", "BroadcastPackets") ],
149 10: [ ("etherErrStats", "Rcv") ],
151 11: [ ("etherTxStats", "TotalBytes") ],
152 12: [ ("etherTxStats", "UnicastPackets") ],
153 13: [ ("etherTxStats", "MulticastPackets") ],
154 14: [ ("etherTxStats", "BroadcastPackets") ],
155 15: [ ("etherErrStats", "OutDiscard") ],
157 "interconnect": {
158 2: "6",
159 5: [ ("etherRxStats", "TotalBytes") ],
160 6: [ ("etherRxStats", "UnicastPackets") ],
161 7: [ ("etherRxStats", "MulticastPackets") ],
162 8: [ ("etherRxStats", "BroadcastPackets") ],
163 10: [ ("etherErrStats", "Rcv") ],
165 11: [ ("etherTxStats", "TotalBytes") ],
166 12: [ ("etherTxStats", "UnicastPackets") ],
167 13: [ ("etherTxStats", "MulticastPackets") ],
168 14: [ ("etherTxStats", "BroadcastPackets") ],
169 15: [ ("etherErrStats", "OutDiscard") ],
173 def parse_ucs_bladecenter_if(info):
174 data = ucs_bladecenter_convert_info(info)
176 fc_interfaces = _parse_fc_interfaces(data)
177 eth_interfaces = _parse_eth_interfaces(data)
178 icnt_interfaces = _parse_icnt_interfaces(data)
180 converted = []
181 last_index = 0
182 for what, group_prefix, interfaces, item_template in [
183 ("fibrechannel", "Fibrechannel-Group", fc_interfaces, "Slot %s FC-Switch %s Port %s"),
184 ("ethernet", "Ethernet-Group", eth_interfaces, "Slot %s Switch %s Port %s"),
185 ("interconnect", "Interconnect-Group", icnt_interfaces, "Slot %s IC-Switch %s Port %s"),
187 index = 0
188 for index, (_name, values) in enumerate(interfaces.iteritems()):
189 item = item_template % ( values.get("SlotId"),
190 values.get("SwitchId"),
191 values.get("PortId") )
192 entry = ['0'] * 20
193 converted.append(entry)
195 # Interfaces in portchannels are automatically grouped by within if.include
196 # Grouped interfaces are identified when the type of the ifIndex field is a tuple
197 # Speed and OperState
198 if "portchannel" in values:
199 entry[0] = (group_prefix + " " + values["portchannel"].get("Name", values["portchannel"].get("PortId", "")),\
200 str(last_index + index))
201 speed = values["portchannel"].get("AdminSpeed") or values["portchannel"].get("OperSpeed")
202 # It looks like that the AdminSpeed of a portchannel is the speed of one member
203 # speed = str(int(float(speed.replace("gbps", "000000000")) / values["portchannel"]["members"]))
204 entry[3] = speed.replace("gbps", "000000000")
205 operStatus = values["portchannel"].get("AdminState", "disabled") == "enabled" and \
206 values["portchannel"].get("OperState", "down") == "up"
207 else:
208 entry[0] = str(last_index + index)
209 entry[3] = values.get("AdminSpeed", "").replace("gbps", "000000000")
210 operStatus = values.get("AdminState", "disabled") == "enabled" and \
211 values.get("OperState", "down") == "up"
213 entry[1] = item
214 entry[4] = "1" if operStatus else "2"
215 entry[18] = item # ifAlias
216 entry[19] = '' # MAC address not known here
217 for table_index , ctr_keys in tableindex.get(what).items():
218 ctr_value = 0
219 # On summing keys there is a possiblility to overlook some counter wraps.
220 # Right now, it's only Recv-Errors (therefore unlikely). We can live with that
221 if type(ctr_keys) != list: # fixed value
222 ctr_value = ctr_keys
223 else:
224 for ctr_class, ctr_key in ctr_keys: # compute value from data
225 if ctr_class:
226 ctr_value += int(values[ctr_class].get(ctr_key, "0"))
227 else:
228 ctr_value += int(values.get(ctr_key, "0"))
229 entry[table_index] = str(ctr_value)
231 last_index += index + 1
233 return converted
236 def _parse_fc_interfaces(data):
237 """Fibrechannels"""
238 fc_interfaces = {}
239 for key, values in data.get("fabricFcSanEp", {}).items():
240 fc_interfaces.setdefault(values["EpDn"], {}).update(values)
242 # TODO: fabricFcSanPc
243 # TODO: fabricFcSanPcEp
244 for what, cut in [ ("fcStats", 6),
245 ("fcErrStats", 10) ]:
246 if what in data:
247 for key, values in data[what].items():
248 fc_name = key[:-cut]
249 if fc_name in fc_interfaces:
250 fc_interfaces[fc_name].setdefault(what, {})
251 fc_interfaces[key[:-cut]][what].update(values)
253 return fc_interfaces
256 def _parse_eth_interfaces(data):
257 eth_interfaces = {}
258 for key, values in data.get("fabricEthLanEp", {}).items():
259 eth_interfaces.setdefault(values["EpDn"], {}).update(values)
261 # Get info for each portchannel
262 eth_pc_info = {}
263 for key, values in data.get("fabricEthLanPc", {}).items():
264 eth_pc_info[key] = values
266 # Ethernet-Portchannel Members
267 for key, values in data.get("fabricEthLanPcEp", {}).items():
268 pc_name = "/".join(values.get("Dn").split("/")[:-1])
269 values["portchannel"] = eth_pc_info[pc_name]
270 eth_pc_info[pc_name].setdefault("members", 0)
271 eth_pc_info[pc_name]["members"] += 1
272 eth_interfaces.setdefault(values["EpDn"], {}).update(values)
274 for what, cut in [ ("etherRxStats", 9),
275 ("etherTxStats", 9),
276 ("etherErrStats", 10) ]:
277 if what in data:
278 for key, values in data[what].items():
279 eth_name = key[:-cut]
280 if eth_name in eth_interfaces:
281 eth_interfaces[eth_name].setdefault(what, {})
282 eth_interfaces[key[:-cut]][what].update(values)
284 return eth_interfaces
287 def _parse_icnt_interfaces(data):
288 icnt_interfaces = {}
289 for key, values in data.get("fabricDceSwEp", {}).items():
290 icnt_interfaces.setdefault(values["EpDn"], {}).update(values)
292 for key, values in data.get("fabricDceSwSrvEp", {}).items():
293 icnt_interfaces.setdefault(values["EpDn"], {}).update(values)
295 # Get info for each portchannel
296 icnt_pc_info = {}
297 for key, values in data.get("fabricDceSwSrvPc", {}).items():
298 icnt_pc_info[key] = values
300 # Interconnect-Portchannel Members
301 for key, values in data.get("fabricDceSwSrvPcEp", {}).items():
302 if len(values.get("Dn").split("/")[:-1]) == 4:
303 pc_name = "/".join(values.get("Dn").split("/")[:-1])
304 else:
305 pc_name = "/".join(values.get("Dn").split("/")[:-2])
306 values["portchannel"] = icnt_pc_info[pc_name]
307 icnt_pc_info[pc_name].setdefault("members", 0)
308 icnt_pc_info[pc_name]["members"] += 1
309 icnt_interfaces.setdefault(values["EpDn"], {}).update(values)
312 for what, cut in [ ("etherRxStats", 9),
313 ("etherTxStats", 9),
314 ("etherErrStats", 10) ]:
315 if what in data:
316 for key, values in data[what].items():
317 eth_name = key[:-cut]
318 if eth_name in icnt_interfaces:
319 icnt_interfaces[eth_name].setdefault(what, {})
320 icnt_interfaces[key[:-cut]][what].update(values)
322 return icnt_interfaces
326 def inventory_ucs_bladecenter_if(info):
327 return inventory_if_common(info)
330 check_info["ucs_bladecenter_if"] = {
331 'parse_function' : parse_ucs_bladecenter_if,
332 'inventory_function' : inventory_ucs_bladecenter_if,
333 'check_function' : check_if_common,
334 'service_description' : 'Interface %s',
335 'has_perfdata' : True,
336 'group' : 'if',
337 'includes' : [ 'ucs_bladecenter.include', 'if.include' ],
338 'default_levels_variable' : 'if_default_levels',