Cleanup config.nodes_of
[check_mk.git] / checks / oracle_instance
blobc9e70cb4b298511902c18c185110d693d5514cd4
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 # In cooperation with Thorsten Bruhns
29 # <<<oracle_instance:sep(124)>>>
30 # TUX2|12.1.0.1.0|OPEN|ALLOWED|STARTED|6735|1297771692|ARCHIVELOG|PRIMARY|NO|TUX2
31 # TUX5|12.1.0.1.1|MOUNTED|ALLOWED|STARTED|82883|1297771692|NOARCHIVELOG|PRIMARY|NO|0|TUX5
33 # <<<oracle_instance:sep(124)>>>$
34 # +ASM|FAILURE|ORA-99999 tnsping failed for +ASM $
35 # ERROR:$
36 # ORA-28002: the password will expire within 1 days$
38 factory_settings["oracle_instance_defaults"] = {
39 "logins": 2,
40 "noforcelogging": 1,
41 "noarchivelog": 1,
42 "primarynotopen": 2,
46 def inventory_oracle_instance(info):
48 inv_list = []
50 for line in info:
52 # Skip ORA- error messages from broken old oracle agent
53 # <<<oracle_instance:sep(124)>>>
54 # ORA-99999 tnsping failed for +ASM1
55 if not (line[0].startswith('ORA-') and line[0][4].isdigit() and len(line[0]) < 16):
57 # possible multitenant entry?
58 if len(line) > 12:
60 # every pdb has a con_id <> 0
61 # Multitenant use DB_NAME.PDB_NAME as Service
62 if line[12] == ('TRUE') and line[13] <> '0':
63 inv_list.append((("%s.%s" % (line[0], line[14])), {}))
64 continue
66 inv_list.append((line[0], {}))
68 return inv_list
71 def _transform_oracle_instance_params(p):
72 if "ignore_noarchivelog" in p:
73 if p["ignore_noarchivelog"]:
74 p["noarchivelog"] = 0
75 del p["ignore_noarchivelog"]
76 return p
79 def check_oracle_instance(item, params, info):
80 params = _transform_oracle_instance_params(params)
82 def state_marker(state, infotext, param, column, data):
83 value = params.get(param)
84 if value is not None and column == data:
85 state = max(state, value)
86 if value == 1:
87 infotext += '(!)'
88 elif value == 2:
89 infotext += '(!!)'
90 return state, infotext
92 state = 0
94 for line in info:
96 itemname = line[0]
97 pdb = False
98 pluggable = "false"
100 if len(line) > 12:
101 # Multitenant!
102 if line[12] == ('TRUE') and line[13] <> '0':
103 itemname = ("%s.%s" % (line[0], line[14]))
104 pdb = True
106 if itemname == item:
107 # In case of a general error (e.g. authentication failed), the second
108 # column contains the word "FAILURE"
109 if line[1] == 'FAILURE':
110 return 2, " ".join(line[2:])
112 state = 0
114 # Be compatible to old oracle agent plugin output
115 if len(line) == 6:
116 sid, version, openmode, logins, _unused, _unused2 = line
118 infotext = 'Status %s, Version %s, Logins %s' % (openmode, version, logins.lower())
119 state, infotext = state_marker(state, infotext, 'logins', logins, 'RESTRICTED')
120 return state, infotext
122 elif len(line) == 11:
123 sid, version, openmode, logins, archiver, up_seconds, _dbid, \
124 log_mode, database_role, force_logging, name = line
126 elif len(line) == 12:
127 sid, version, openmode, logins, archiver, up_seconds, _dbid, \
128 log_mode, database_role, force_logging, name, _dbcreated = line
130 elif len(line) == 22:
131 sid, version, openmode, logins, archiver, up_seconds, _dbid, \
132 log_mode, database_role, force_logging, name, _dbcreated, pluggable, \
133 _con_id, pname, _pdbid, popenmode, prestricted, ptotal_size, _precovery_status, \
134 pup_seconds, _pblock_size = line
136 else:
137 return 2, "Database not running, login failed or unvalid data from agent"
139 if pdb is True:
140 if prestricted.lower == 'no':
141 logins = 'restricted'
142 else:
143 logins = 'allowd'
145 openmode = popenmode
146 up_seconds = pup_seconds
148 infotext = "PDB Name %s.%s, Status %s" % \
149 (name, pname, popenmode)
150 else:
151 if pluggable.lower() == 'true':
152 infotext = "CDB Name %s, Status %s" % \
153 (name, openmode)
154 else:
155 infotext = "Database Name %s, Status %s" % \
156 (name, openmode)
158 # Check state for PRIMARY Database. Normaly there are always OPEN
159 if database_role == 'PRIMARY' and openmode not in ('OPEN', 'READ ONLY', 'READ WRITE'):
160 state = params.get('primarynotopen')
161 if state == 1:
162 infotext += '(!)'
163 elif state == 2:
164 infotext += '(!!)'
165 elif state == 0:
166 infotext += ' (allowed by rule)'
168 if pdb is False:
169 infotext += ", Role %s, Version %s" % (database_role, version)
171 # ORACLE is sick and cannot handle timezone changes >:-P
172 up_seconds = max(0, int(up_seconds))
173 infotext += ", Up since %s (%s)" % (
174 time.strftime("%F %T", time.localtime(time.time() - up_seconds)), \
175 get_age_human_readable(up_seconds))
177 if params.get('uptime_min'):
178 warn, crit = params.get('uptime_min')
179 warn = int(warn)
180 crit = int(crit)
182 infotext += ' (warn/crit at %s/%s)' % (get_age_human_readable(warn),
183 get_age_human_readable(crit))
184 if up_seconds == -1:
185 # PDB in mounted state has no uptime information
186 state = 0
187 elif up_seconds <= crit:
188 state = 2
189 infotext += '(!!) not long enough up'
190 elif up_seconds <= warn:
191 state = max(state, 1)
192 infotext += '(!) not long enough up'
194 # ASM has no login and archivelog check
195 if database_role != 'ASM':
197 # logins are only possible when the database is open
198 if openmode == 'OPEN':
199 infotext += ', Logins %s' % (logins.lower())
200 state, infotext = state_marker(state, infotext, 'logins', logins, 'RESTRICTED')
202 # the new internal database _MGMTDB from 12.1.0.2 is always in NOARCHIVELOG mode
203 if name != '_MGMTDB' and sid != '-MGMTDB' and pdb is False:
204 infotext += ', Log Mode %s' % (log_mode.lower())
205 state, infotext = state_marker(state, infotext, 'archivelog', log_mode,
206 'ARCHIVELOG')
207 state, infotext = state_marker(state, infotext, 'noarchivelog', log_mode,
208 'NOARCHIVELOG')
210 # archivelog is only valid in non pdb
211 # force logging is only usable when archivelog is enabled
212 if log_mode == 'ARCHIVELOG':
213 if archiver != 'STARTED':
214 infotext += '. Archiver %s(!!)' % (archiver.lower())
215 state = 2
217 infotext += ', Force Logging %s' % (force_logging.lower())
218 state, infotext = state_marker(state, infotext, 'forcelogging',
219 force_logging, 'YES')
220 state, infotext = state_marker(state, infotext, 'noforcelogging',
221 force_logging, 'NO')
223 perfdata = [['uptime', up_seconds]]
225 if pdb is True:
226 infotext += ', PDB Size %s' % get_bytes_human_readable(int(ptotal_size))
227 perfdata.append(('fs_size', int(ptotal_size)))
229 return state, infotext, perfdata
231 if '.' in item:
232 # no error from PDB when CDB is down
233 raise MKCounterWrapped("CDB possible down. No results for PDB availible!")
234 else:
235 return 2, "Database not running or login failed"
238 check_info['oracle_instance'] = {
239 "check_function": check_oracle_instance,
240 "inventory_function": inventory_oracle_instance,
241 "service_description": "ORA %s Instance",
242 "default_levels_variable": "oracle_instance_defaults",
243 "group": "oracle_instance",
244 "has_perfdata": True,