def module_init(args): global qh comp = cconf.parse_conf(nagios_cfg) for v in comp.params: if v[0] == 'query_socket': qh = v[1] break
def module_init(args): global qh global single rem_args = [] comp = cconf.parse_conf(nagios_cfg) for v in comp.params: if v[0] == 'query_socket': qh = v[1] break for arg in args: if arg.startswith('--socket='): qh = arg.split('=', 1)[1] continue if arg == '--single': single = True continue rem_args.append(arg) if not qh: if os.access(nagios_cfg, os.R_OK): comp = cconf.parse_nagios_cfg(nagios_cfg) qh = comp.query_socket else: print "ERROR: Unable to find Naemon query socket" return 1 return rem_args
def cmd_spool(args=False): """[--maxage=<seconds>] [--warning=X] [--critical=X] <path> [--delete] Checks a certain spool directory for files (and files only) that are older than 'maxage'. It is intended to prevent buildup of checkresult files and unprocessed performance-data files in the various spool directories used by op5 Monitor. --delete causes too old files to be removed. --maxage is given in seconds and defaults to 300 (5 minutes). <path> may be 'perfdata' or 'checks', in which case directory names will be taken from op5 defaults. --warning and --critical have no effect if '--delete' is given and will otherwise specify threshold values. Only one directory at a time may be checked. """ maxage = 300 warning = 5 critical = 10 path = False delete = False npcd_config = '/opt/monitor/etc/pnp/npcd.cfg' for arg in args: if arg.startswith('--maxage='): maxage = str_to_seconds(arg.split('=', 1)[1]) elif arg.startswith('--warning='): warning = int(arg.split('=', 1)[1]) elif arg.startswith('--critical='): critical = int(arg.split('=', 1)[1]) elif arg == '--delete': delete = True elif path == False: path = arg if path == False: nplug.unknown("'path' is a required argument") if path == 'checks': path = check_result_path elif path == 'perfdata': if os.access(npcd_config, os.R_OK): comp = cconf.parse_conf(npcd_config) for k, v in comp.params: if k == 'perfdata_spool_dir': path = v break comp = False else: path = '/opt/monitor/var/spool/perfdata' bad = 0 bad_paths = [] now = int(time.time()) try: result = get_files(path) except OSError, e: nplug.die(nplug.STATE_UNKNOWN, "Spool directory \"%s\" doesn't exist" % (path, ))
def cmd_spool(args=False): """[--maxage=<seconds>] [--warning=X] [--critical=X] <path> [--delete] Checks a certain spool directory for files (and files only) that are older than 'maxage'. It is intended to prevent buildup of checkresult files and unprocessed performance-data files in the various spool directories used by op5 Monitor. --delete causes too old files to be removed. --maxage is given in seconds and defaults to 300 (5 minutes). <path> may be 'perfdata' or 'checks', in which case directory names will be taken from op5 defaults. --warning and --critical have no effect if '--delete' is given and will otherwise specify threshold values. Only one directory at a time may be checked. """ maxage = 300 warning = 5 critical = 10 path = False delete = False npcd_config = '/opt/monitor/etc/pnp/npcd.cfg' for arg in args: if arg.startswith('--maxage='): maxage = str_to_seconds(arg.split('=', 1)[1]) elif arg.startswith('--warning='): warning = int(arg.split('=', 1)[1]) elif arg.startswith('--critical='): critical = int(arg.split('=', 1)[1]) elif arg == '--delete': delete = True elif path == False: path = arg if path == False: nplug.unknown("'path' is a required argument") if path == 'checks': path = check_result_path elif path == 'perfdata': if os.access(npcd_config, os.R_OK): comp = cconf.parse_conf(npcd_config) for k, v in comp.params: if k == 'perfdata_spool_dir': path = v break comp = False else: path = '/opt/monitor/var/spool/perfdata' bad = 0 bad_paths = [] now = int(time.time()) try: result = get_files(path) except OSError, e: nplug.die(nplug.STATE_UNKNOWN, "Spool directory \"%s\" doesn't exist" % (path,))
def module_init(args): global qh rem_args = [] comp = cconf.parse_conf(nagios_cfg) for v in comp.params: if v[0] == 'query_socket': qh = v[1] break for arg in args: if arg.startswith('--socket='): qh = arg.split('=', 1)[1] continue rem_args.append(arg) return rem_args
def module_init(args): global wanted_types, wanted_names global have_type_arg, have_name_arg global mst, lsc, ls_path, qh rem_args = [] i = -1 for arg in args: i += 1 if arg == '--': rem_args += args[i:] break if arg.startswith('--merlin-cfg=') or arg.startswith('--config='): mconf.config_file = arg.split('=', 1)[1] elif arg.startswith('--type='): wanted_types = arg.split('=')[1].split(',') have_type_arg = True elif arg.startswith('--name='): wanted_names = arg.split('=')[1].split(',') have_name_arg = True else: # not an argument we recognize, so stash it and move on rem_args += [arg] continue comp = cconf.parse_conf(nagios_cfg) for v in comp.params: if v[0] == 'query_socket': qh = v[1] elif v[0] == 'broker_module' and 'livestatus' in v[1]: ary = v[1].rsplit(' ') for p in ary[1:]: if not '=' in p: ls_path = p break lsc = livestatus.SingleSiteConnection('unix:' + ls_path) mst = merlin_status(lsc, qh) return rem_args
def module_init(args): global wanted_types, wanted_names global have_type_arg, have_name_arg global qh comp = cconf.parse_conf(nagios_cfg) for v in comp.params: if v[0] == 'query_socket': qh = v[1] break wanted_types = mconf.merlin_node.valid_types rem_args = [] i = -1 for arg in args: i += 1 # stop parsing immediately if we hit double-dashes, or we # may well break recursive commands sent with mon node ctrl. if arg == '--': rem_args += args[i:] break if arg.startswith('--merlin-cfg=') or arg.startswith('--config='): mconf.config_file = arg.split('=', 1)[1] elif arg.startswith('--type='): wanted_types = arg.split('=')[1].split(',') have_type_arg = True elif arg.startswith('--name='): wanted_names = arg.split('=')[1].split(',') have_name_arg = True else: # not an argument we recognize, so stash it and move on rem_args += [arg] continue # load the merlin configuration, and thus all nodes mconf.parse() return rem_args
def cmd_pasv(args): """ Submits passive checkresults to the nagios.cmd pipe and verifies that the data gets written to database correctly and in a timely manner. Available options for 'mon test pasv' --nagios-cfg=<file> default /opt/monitor/var/etc/nagios.cfg --counters=<int> number of counters per object (default 30) --hosts=<int> number of hosts (default 1) --services=<int> number of services (default 5) --loops=<int> number of loops (default 1) --interval=<int> interval in seconds between loops (def 1800) --delay=<int> delay between submitting and checking (def 25) !!! WARNING !!! !!! WARNING !!! This command will disble active checks on your system and have other side-effects as well. !!! WARNING !!! !!! WARNING !!! """ global verbose nagios_cfg = False num_hosts = 1 num_services = 5 num_loops = 1 num_counters = 30 interval = 1800 delay = 25 cmd_pipe = False global send_host_checks for arg in args: if arg.startswith('--nagios-cfg='): nagios_cfg = arg.split('=')[1] elif arg.startswith('--counters='): num_counters = int(arg.split('=')[1]) elif arg.startswith('--hosts='): num_hosts = int(arg.split('=')[1]) elif arg.startswith('--services='): num_services = int(arg.split('=')[1]) elif arg.startswith('--loops='): num_loops = int(arg.split('=')[1]) elif arg.startswith('--interval='): interval = int(arg.split('=')[1]) elif arg.startswith('--delay='): delay = int(arg.split('=')[1]) elif arg == '--verbose' or arg == '-v': verbose = True elif arg == '--nohostchecks': send_host_checks = False else: prettyprint_docstring("pasv", cmd_pasv.__doc__, "Unknown argument: %s" % arg) if arg == '--help' or arg == 'help': sys.exit(0) else: sys.exit(1) if nagios_cfg: comp = cconf.parse_conf(nagios_cfg) for v in comp.params: if v[0] == 'command_file': cmd_pipe = v[1] break db = merlin_db.connect(mconf) dbc = db.cursor() if not cmd_pipe: cmd_pipe = "/opt/monitor/var/rw/nagios.cmd" cmd_fd = _pasv_open_cmdpipe(cmd_pipe) # disable active checks while we test the passive ones, or # active checkresults might overwrite the passive ones and # contaminate the testresults test_cmd(cmd_fd, "STOP_EXECUTING_HOST_CHECKS") test_cmd(cmd_fd, "STOP_EXECUTING_SVC_CHECKS") test_cmd(cmd_fd, "START_ACCEPTING_PASSIVE_HOST_CHECKS") test_cmd(cmd_fd, "START_ACCEPTING_PASSIVE_SVC_CHECKS") os.close(cmd_fd) # now we update the database with impossible values so we # know we don't get the right test-data by mistake in case # the test-case is run multiple times directly following # each other dbc.execute("UPDATE host SET last_check = 5, current_state = 5") dbc.execute("UPDATE service SET last_check = 5, current_state = 5") host_list = [] test_objs = [] query = "SELECT host_name FROM host ORDER BY host_name ASC" dbc.execute(query) hi = 0 # arbitrary (very) large value min_services = 100123098 min_services_host = '' for row in dbc.fetchall(): if hi < num_hosts: obj = pasv_test_host(row[0]) host_list.append(obj) if send_host_checks: test_objs.append(obj) hi += 1 for host in host_list: query = ("SELECT service_description FROM service " "WHERE host_name = '%s' ORDER BY service_description ASC" % host.name) dbc.execute(query) services = 0 si = 0 for row in dbc.fetchall(): if si < num_services: services += 1 obj = pasv_test_service(host.name, row[0]) host.services.append(obj) test_objs.append(obj) si += 1 if services < min_services: min_services_host = host.name min_services = services if num_hosts > host_list: print("Can't run tests for %d hosts when only %d are configured" % (num_hosts, len(host_list))) if num_services > min_services: print("Can't run tests for %d services / host when %s has only %d configured" % (num_services, min_services_host, min_services)) # primary testing loop loops = 0 while loops < num_loops: loops += 1 # generate the counters we'll be using. # We get fresh ones for each iteration counters = _generate_counters(num_counters) cnt_string = "%s" % " ".join(counters) cnt_hash = hashlib.sha(cnt_string).hexdigest() # why we have to disconnect from db and re-open the # command pipe is beyond me, but that's the way it is, it # seems. It also matches real-world use a lot better, # since the reader imitates ninja and the writer imitates # nsca. cmd_fd = _pasv_open_cmdpipe(cmd_pipe) merlin_db.disconnect() # new status every time so we can differ between the values # and also test the worst-case scenario where the daemon has # to run two queries for each passive checkresult status = loops % 3 loop_start = time.time() print("Submitting passive check results (%s) @ %s" % (cnt_hash, time.time())) for t in test_objs: cmd = _pasv_build_cmd(t, status) cmd += "%s|%s\n" % (cnt_hash, cnt_string) t.cmd_hash = hashlib.sha(cmd).hexdigest() t.submit_time = time.time() result = os.write(cmd_fd, cmd) test(result, len(cmd), "%d of %d bytes written for %s" % (result, len(cmd), t.name)) os.close(cmd_fd) db = merlin_db.connect(mconf) dbc = db.cursor() print("Sleeping %d seconds before reaping results" % delay) time.sleep(delay) for t in test_objs: query = ("SELECT " "last_check, current_state, output, perf_data " "FROM %s" % t.query()) dbc.execute(query) row = dbc.fetchone() test(row[0] + delay > t.submit_time, True, "reasonable delay for %s" % t.name) test(row[1], status, "status updated for %s" % t.name) test(str(row[2]), cnt_hash, "output update for %s" % t.name) test(str(row[3]), cnt_string, "counter truncation check for %s" % t.name) if loops < num_loops: interval_sleep = (loop_start + interval) - time.time() if interval_sleep > 0: print("Sleeping %d seconds until next test-set" % interval_sleep) time.sleep(interval_sleep) total_tests = failed + passed print("failed: %d/%.3f%%" % (failed, float(failed * 100) / total_tests)) print("passed: %d/%.3f%%" % (passed, float(passed * 100) / total_tests)) print("total tests: %d" % total_tests)
def _import_objects_from_cache(self, inputfile, is_cache=True): '''Given a file name, insert all objects in it into the database''' last_obj_type = '' obj_array = {} if not self.tables_truncated: for table in self.tables_to_truncate: self.db.sql_exec('TRUNCATE ' + table) self.tables_truncated = True service_slaves = {'serviceescalation': 1, 'servicedependency': 1} try: root = parse_conf(inputfile, (is_cache and '\t' or '=')) except IOError: print "Error: Couldn't open file '%s'." % inputfile return if not root.objects: print "Couldn't parse file." return if root.objects[0].name in ('info', 'program'): self.importing_status = True for obj in root.objects: obj_type = obj.name if obj_type.startswith('define '): obj_type = obj_type[7:] if self.conv_type.has_key(obj_type): obj_type = self.conv_type[obj_type] if obj_type != last_obj_type: obj_array = self._done_parsing_obj_type_objects(last_obj_type, obj_array) last_obj_type = obj_type obj_data = self._mangle_data(obj_type, obj.params) if not obj_data: continue obj_name = self._get_obj_name(obj_type, obj_data) old_obj = self.indexer.get(obj_type, obj_name) if not old_obj: old_obj = Entry() old_obj.name = obj_name if not self.base_oid.has_key(obj_type): self.base_oid[obj_type] = 1 old_obj.id = self.base_oid[obj_type] self.base_oid[obj_type] += 1 obj_data['is a fresh one'] = True if obj_name: self.indexer.set(obj_type, obj_name, old_obj.id) if old_obj.instance_id != 0: obj_data['instance_id'] = old_obj.instance_id obj_key = old_obj.id if obj_type in ('host', 'program_status'): pass elif obj_type == 'timeperiod': pass elif obj_type not in ('hostgroup', 'servicegroup', 'contactgroup'): if service_slaves.has_key(obj_type): obj_data = self._post_mangle_service_slave(obj_type, obj_data) if obj_data: if not obj_array.has_key(obj_type): obj_array[obj_type] = {} obj_array[obj_type][obj_key] = obj_data self.obj_array = self._done_parsing_obj_type_objects(obj_type, obj_array)
def _import_objects_from_cache(self, inputfile, is_cache=True): '''Given a file name, insert all objects in it into the database''' last_obj_type = '' obj_array = {} if not self.tables_truncated: for table in self.tables_to_truncate: self.db.sql_exec('TRUNCATE ' + table) self.tables_truncated = True service_slaves = {'serviceescalation': 1, 'servicedependency': 1} try: root = parse_conf(inputfile, (is_cache and '\t' or '=')) except IOError: print "Error: Couldn't open file '%s'." % inputfile return if not root.objects: print "Couldn't parse file." return if root.objects[0].name in ('info', 'program'): self.importing_status = True for obj in root.objects: obj_type = obj.name if obj_type.startswith('define '): obj_type = obj_type[7:] if self.conv_type.has_key(obj_type): obj_type = self.conv_type[obj_type] if obj_type != last_obj_type: obj_array = self._done_parsing_obj_type_objects( last_obj_type, obj_array) last_obj_type = obj_type obj_data = self._mangle_data(obj_type, obj.params) if not obj_data: continue obj_name = self._get_obj_name(obj_type, obj_data) old_obj = self.indexer.get(obj_type, obj_name) if not old_obj: old_obj = Entry() old_obj.name = obj_name if not self.base_oid.has_key(obj_type): self.base_oid[obj_type] = 1 old_obj.id = self.base_oid[obj_type] self.base_oid[obj_type] += 1 obj_data['is a fresh one'] = True if obj_name: self.indexer.set(obj_type, obj_name, old_obj.id) if old_obj.instance_id != 0: obj_data['instance_id'] = old_obj.instance_id obj_key = old_obj.id if obj_type in ('host', 'program_status'): pass elif obj_type == 'timeperiod': pass elif obj_type not in ('hostgroup', 'servicegroup', 'contactgroup'): if service_slaves.has_key(obj_type): obj_data = self._post_mangle_service_slave( obj_type, obj_data) if obj_data: if not obj_array.has_key(obj_type): obj_array[obj_type] = {} obj_array[obj_type][obj_key] = obj_data self.obj_array = self._done_parsing_obj_type_objects( obj_type, obj_array)