Refactoring: Moved check parameters from unsorted.py to dedicated modules (CMK-1393)
[check_mk.git] / checks / oracle_rman
blobc1210f5bfbb37106cff417b5aa102771f3457fbe
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 # actual format
28 # <<<oracle_rman>>>
29 # TUX2|COMPLETED|2015-01-02_07:05:59|2015-01-02_07:05:59|DB_INCR|2|335|8485138
31 # old format
32 # <<<oracle_rman>>>
33 # TUX2 COMPLETED 2014-07-08_17:27:59 2014-07-08_17:29:35 DB_INCR 32
34 # TUX2 COMPLETED 2014-07-08_17:30:02 2014-07-08_17:30:06 ARCHIVELOG 121
36 # Columns: SID STATUS START END BACKUPTYPE BACKUPAGE
38 # Create DB_INCR_<Level> checks when parameter is True
39 # Set this to False for old behavior. This is required for the service
40 # discovery and can't be set as a inventory parameter.
41 # This will be removed in a later version of Check_MK. Don't use it for new installations!
42 inventory_oracle_rman_incremental_details = True
45 def parse_oracle_rman(info):
46 parsed = {}
47 error_sids = {}
49 for line in info:
50 line = line[1:]
52 # Check for query errors
53 err = oracle_handle_ora_errors(line)
54 if err is False:
55 continue # ignore ancient agent outputs
56 elif isinstance(err, tuple):
57 sid = line[0]
58 error_sids[sid] = err
60 # we leave the llop with break when item is found except for DB_INCR_0
61 # later we need to restore the values for DB_INCR_0 due to possivle
62 # overwrite with new line from info
64 backupscn = -1
65 item = ''
67 if len(line) == 6:
68 sid, status, _start, _end, backuptype, backupage = line
69 item = "%s.%s" % (sid, backuptype)
71 backupscn = int(-1)
72 backuplevel = -1
74 elif len(line) == 8:
75 sid, status, _not_used_1, _end, backuptype, backuplevel, backupage, backupscn = line
76 if backupscn == '':
77 backupscn = int(-1)
78 else:
79 backupscn = int(backupscn)
81 if backuptype == 'DB_INCR':
83 if inventory_oracle_rman_incremental_details:
84 item = "%s.%s_%s" % (sid, backuptype, backuplevel)
85 else:
86 # This is for really old plugins without an information for the backuplevel
87 item = "%s.%s" % (sid, backuptype)
88 else:
89 item = "%s.%s" % (sid, backuptype)
91 else:
92 continue
94 try:
95 backupage = int(backupage)
97 except (ValueError, TypeError):
98 backupage = None
100 parsed.setdefault(
101 item,
103 "sid": sid,
104 "backuptype": backuptype,
105 "backuplevel": backuplevel,
106 "backupage": backupage,
107 "status": status,
108 "backupscn": backupscn,
109 "used_incr_0": False, # True when last incr0 is newer then incr1
112 # take the most current backupage in clustered environments
113 if parsed[item]['backupage'] is None or parsed[item]['backupage'] > backupage:
114 parsed[item].update({"backupage": backupage})
116 # some tweaks in aprsed for change in behavior of oracle
117 # correct backupage for INCR_1 when newer INCR_0 is existing
118 for line in parsed:
120 # search DB_INCR_1 in parsed
121 if line.rsplit('.', 1)[1] == 'DB_INCR_1':
123 # check backupage
124 sid_level0 = "%s0" % (line[0:-1])
126 if sid_level0 in parsed and parsed[sid_level0]['backupage'] < parsed[line]['backupage']:
128 parsed[line].update({
129 "backupage": backupage,
130 "used_incr_0": True,
133 return parsed
136 def inventory_oracle_rman(parsed):
137 inventory = []
138 for line in parsed:
140 sid = parsed[line]['sid']
141 backuptype = parsed[line]['backuptype']
142 backuplevel = parsed[line]['backuplevel']
144 if backuptype in ('ARCHIVELOG', 'DB_FULL', 'DB_INCR', 'CONTROLFILE'):
146 if inventory_oracle_rman_incremental_details and backuptype == 'DB_INCR':
147 inventory.append(("%s.%s_%s" % (sid, backuptype, backuplevel), {}))
148 continue
150 else:
151 inventory.append(("%s.%s" % (sid, backuptype), {}))
153 return inventory
156 # Cannot use generic decorator @get_parsed_item_data because this check function
157 # needs special treatment
158 def check_oracle_rman(item, params, parsed):
160 rman_backup = parsed.get(item)
162 sid_level0 = ''
164 if not rman_backup:
166 # some versions of Oracle removes the last Level 1 after a new Level 0
167 # => we have no Level 1 in agent output. level 1 is shown as level 0
169 sid_level0 = "%s0" % (item[0:-1])
171 if item[-1] == '1' and sid_level0 in parsed:
173 # => INCR_1 in item and INCR_0 found
174 # => Switch to INCR_0 + used_incr_0
175 rman_backup = parsed.get(sid_level0)
176 rman_backup.update({"used_incr_0": True})
178 else:
180 # In case of missing information we assume that the login into
181 # the database has failed and we simply skip this check. It won't
182 # switch to UNKNOWN, but will get stale.
183 raise MKCounterWrapped("Login into database failed. Working on %s" % item)
185 status = rman_backup['status']
186 backupage = rman_backup['backupage']
187 backupscn = rman_backup['backupscn']
189 perfdata = []
190 state = 2
192 if status in ('COMPLETED', 'COMPLETED WITH WARNINGS'):
194 if backupage is None:
195 # backupage in agent was empty. That's only possible with really old agents.
196 return 3, "Unknown backupage in check found. Please update agent."
198 # backupage is time in minutes from agent!
199 backupage = backupage * 60
200 infotext = "Last backup %s ago" % get_age_human_readable(backupage)
202 state = 0
203 if "levels" in params:
204 warn, crit = params.get("levels")
205 if backupage >= crit:
206 state = 2
207 elif backupage >= warn:
208 state = 1
209 infotext += " (warn/crit at %s/%s)" % (get_age_human_readable(warn),
210 get_age_human_readable(crit))
212 perfdata = [("age", backupage, warn, crit)]
213 else:
214 perfdata = [("age", backupage)]
216 if backupscn > 0:
217 infotext += ", incremental SCN %i" % backupscn
219 if rman_backup['used_incr_0']:
220 infotext += ', Last DB_INCR_0 used'
221 else:
222 infotext = "no COMPLETED backup found in last 14 days (very old plugin in use?)"
224 return state, infotext, perfdata
227 check_info['oracle_rman'] = {
228 "check_function": check_oracle_rman,
229 "parse_function": parse_oracle_rman,
230 "inventory_function": inventory_oracle_rman,
231 "service_description": "ORA %s RMAN Backup",
232 "has_perfdata": True,
233 "node_info": True,
234 "group": "oracle_rman",
235 "includes": ["oracle.include", "db.include"]