Cleanup config.nodes_of
[check_mk.git] / checks / mssql_backup
blob516487ef199e061ae2a518dd31d89e0a356f32e7
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 # <<<mssql_backup>>>
28 # MSSQL_SQLEXPRESS1 test123 1331207325
30 # <<<mssql_backup>>>
31 # MSSQL_SQL0x2 master 2016-07-08 20:20:27
32 # MSSQL_SQL0x2 model 2016-07-08 20:20:28
33 # MSSQL_SQL0x2 model 2016-07-12 09:09:42
34 # MSSQL_SQL0x2 model 2016-07-11 20:20:07
35 # MSSQL_SQL0x2 msdb 2016-07-08 20:20:43
36 # MSSQL_SQL0x2 msdb 2016-07-11 20:20:07
38 # <<<mssql_backup>>>
39 # MSSQL_SQL0x3 master 2016-07-08 20:20:27 D
40 # MSSQL_SQL0x3 model 2016-07-08 20:20:28 D
41 # MSSQL_SQL0x3 model 2016-07-12 09:09:42 L
42 # MSSQL_SQL0x3 model 2016-07-11 20:20:07 I
43 # MSSQL_SQL0x3 msdb 2016-07-08 20:20:43 D
44 # MSSQL_SQL0x3 msdb 2016-07-11 20:20:07 I
46 # <<<mssql_backup:sep(124)>>>
47 # MSSQL_SQL0x4|master|2016-07-08 20:20:27|D
48 # MSSQL_SQL0x4|model|2016-07-08 20:20:28|D
49 # MSSQL_SQL0x4|model|2016-07-12 09:09:42|L
50 # MSSQL_SQL0x4|model|2016-07-11 20:20:07|I
51 # MSSQL_SQL0x4|msdb|2016-07-08 20:20:43|D
52 # MSSQL_SQL0x4|msdb|2016-07-11 20:20:07|I
54 discovery_mssql_backup = []
56 factory_settings["mssql_backup_default_levels"] = {
57 "database": (None, None),
58 "database_diff": (None, None),
59 "log": (None, None),
60 "file_or_filegroup": (None, None),
61 "file_diff": (None, None),
62 "partial": (None, None),
63 "partial_diff": (None, None),
64 "unspecific": (None, None),
68 def parse_mssql_backup(info):
69 def _parse_date_and_time(b_date, b_time):
70 try:
71 if b_time is None:
72 return int(b_date)
73 return time.mktime(time.strptime("%s %s" % (b_date, b_time), '%Y-%m-%d %H:%M:%S'))
74 except ValueError:
75 return None
77 map_backup_types = {
78 "D": "database",
79 "I": "database diff",
80 "L": "log",
81 "F": "file or filegroup",
82 "G": "file diff",
83 "P": "partial",
84 "Q": "partial diff",
85 "-": "unspecific",
88 parsed = {}
89 Backup = collections.namedtuple("Backup", ["timestamp", "type", "state"])
90 for line in info:
91 if len(line) <= 2:
92 continue
93 # handle one special case where spaces are in date/time:
94 if len(line) == 4 and " " in line[2]:
95 line = line[:2] + line[2].split(" ") + line[3:]
97 # fill up with Nones:
98 line += [None] * (6 - len(line))
100 inst, tablespace, b_date, b_time, b_type, b_state = line
101 timestamp = _parse_date_and_time(b_date, b_time)
103 item = "%s %s" % (inst, tablespace)
104 backup = Backup(timestamp, map_backup_types.get(b_type), b_state or "")
105 parsed.setdefault(item, []).append(backup)
107 return parsed
110 def inventory_mssql_backup(parsed):
111 discovery_mode = _mssql_backup_discovery_mode()
112 if discovery_mode != "summary":
113 return
114 for db_name in parsed:
115 yield db_name, {}
118 def _mssql_backup_discovery_mode():
119 rules = host_extra_conf(host_name(), discovery_mssql_backup)
120 try:
121 return rules[0]['mode']
122 except (IndexError, KeyError):
123 return "summary" # default, comp. to older versions
126 def check_mssql_backup(item, params, parsed):
127 data = parsed.get(item)
128 if data is None:
129 # Assume general connection problem to the database, which is reported
130 # by the "X Instance" service and skip this check.
131 raise MKCounterWrapped("Failed to connect to database")
133 if not isinstance(params, dict):
134 params = {"database": params}
136 for backup in data:
137 if backup.state == "no backup found":
138 yield params.get("not_found", 1), "No backup found"
139 continue
140 if backup.state.startswith("ERROR: "):
141 yield 2, backup.state[7:]
142 continue
143 if backup.type is None:
144 backup_type_var = "database"
145 perfkey = "seconds"
146 backup_type_info = "[database]"
147 else:
148 backup_type_var = backup.type.strip().replace(" ", "_")
149 perfkey = "backup_age_%s" % backup_type_var
150 backup_type_info = "[%s]" % backup.type
151 state, infotext, perfdata =\
152 _check_mssql_backup(backup, params.get(backup_type_var, (None, None)), perfkey)
153 yield state, "%s %s" % (backup_type_info, infotext), perfdata
156 def _check_mssql_backup(backup, levels, perfkey):
157 state = 0
158 age_warn, age_crit = levels
159 sec_ago = time.time() - backup.timestamp
160 if age_crit is not None and sec_ago >= age_crit:
161 state = 2
162 elif age_warn is not None and sec_ago >= age_warn:
163 state = 1
165 infotext = 'Last backup was at %s (%s ago)' % (time.strftime(
166 '%Y-%m-%d %H:%M:%S', time.localtime(backup.timestamp)), get_age_human_readable(sec_ago))
168 if state:
169 infotext += " (warn/crit at %s/%s)" % (get_age_human_readable(age_warn),
170 get_age_human_readable(age_crit))
172 return state, infotext, [(perfkey, sec_ago, age_warn, age_crit)]
175 check_info['mssql_backup'] = {
176 'parse_function': parse_mssql_backup,
177 'check_function': check_mssql_backup,
178 'inventory_function': inventory_mssql_backup,
179 'service_description': 'MSSQL %s Backup',
180 'has_perfdata': True,
181 'group': 'mssql_backup',
182 'default_levels_variable': 'mssql_backup_default_levels',
186 # .--single--------------------------------------------------------------.
187 # | _ _ |
188 # | ___(_)_ __ __ _| | ___ |
189 # | / __| | '_ \ / _` | |/ _ \ |
190 # | \__ \ | | | | (_| | | __/ |
191 # | |___/_|_| |_|\__, |_|\___| |
192 # | |___/ |
193 # '----------------------------------------------------------------------'
196 def _mssql_backup_per_type_item(db_name, backup):
197 if backup.type is None:
198 return "%s UNKNOWN" % db_name
199 return "%s %s" % (db_name, backup.type.title())
202 def inventory_mssql_backup_per_type(parsed):
203 discovery_mode = _mssql_backup_discovery_mode()
204 if discovery_mode != "per_type":
205 return
206 for db_name, attrs in parsed.iteritems():
207 for backup in attrs:
208 yield _mssql_backup_per_type_item(db_name, backup), {}
211 def check_mssql_backup_per_type(item, params, parsed):
212 for db_name, attrs in parsed.iteritems():
213 for backup in attrs:
214 if item == _mssql_backup_per_type_item(db_name, backup):
215 return _check_mssql_backup(backup, params.get("levels", (None, None)), "backup_age")
216 # Assume general connection problem to the database, which is reported
217 # by the "X Instance" service and skip this check.
218 raise MKCounterWrapped("Failed to connect to database")
221 check_info['mssql_backup.per_type'] = {
222 'check_function': check_mssql_backup_per_type,
223 'inventory_function': inventory_mssql_backup_per_type,
224 'service_description': 'MSSQL %s Backup',
225 'has_perfdata': True,
226 'group': 'mssql_backup_per_type',