def _parse_autocheck_entry(hostname, entry): # type: (str, Union[ast.Tuple, ast.Dict]) -> Optional[DiscoveredService] if isinstance(entry, ast.Tuple): ast_check_plugin_name, ast_item, ast_parameters_unresolved = _parse_pre_16_tuple_autocheck_entry( entry) ast_service_labels = ast.Dict() elif isinstance(entry, ast.Dict): ast_check_plugin_name, ast_item, ast_parameters_unresolved, ast_service_labels = \ _parse_dict_autocheck_entry(entry) else: raise Exception("Invalid autocheck: Wrong type: %r" % entry) if not isinstance(ast_check_plugin_name, ast.Str): raise Exception("Invalid autocheck: Wrong check plugin type: %r" % ast_check_plugin_name) check_plugin_name = ast_check_plugin_name.s item = None # type: Item if isinstance(ast_item, ast.Str): item = ast_item.s elif isinstance(ast_item, ast.Num): item = int(ast_item.n) elif isinstance(ast_item, ast.Name) and ast_item.id == "None": item = None else: raise Exception("Invalid autocheck: Wrong item type: %r" % ast_item) # With Check_MK 1.2.7i3 items are now defined to be unicode # strings. Convert items from existing autocheck files for # compatibility. if isinstance(item, str): item = config.decode_incoming_string(item) if isinstance(ast_parameters_unresolved, ast.Name): # Keep check variable names as they are: No evaluation of check parameters parameters_unresolved = ast_parameters_unresolved.id else: # Other structures, like dicts, lists and so on should also be loaded as repr() str # instead of an interpreted structure parameters_unresolved = repr( eval( compile(ast.Expression(ast_parameters_unresolved), filename="<ast>", mode="eval"))) try: description = config.service_description(hostname, check_plugin_name, item) except Exception: return None # ignore return DiscoveredService( check_plugin_name, item, description, parameters_unresolved, service_labels=_parse_discovered_service_label_from_ast( ast_service_labels))
def _parse_autocheck_entry(hostname, entry): # type: (str, Union[ast.Tuple, ast.Dict]) -> Optional[DiscoveredService] if isinstance(entry, ast.Tuple): ast_check_plugin_name, ast_item, ast_parameters_unresolved = _parse_pre_16_tuple_autocheck_entry( entry) ast_service_labels = ast.Dict() elif isinstance(entry, ast.Dict): ast_check_plugin_name, ast_item, ast_parameters_unresolved, ast_service_labels = \ _parse_dict_autocheck_entry(entry) else: raise Exception("Invalid autocheck: Wrong type: %r" % entry) if not isinstance(ast_check_plugin_name, ast.Str): raise Exception("Invalid autocheck: Wrong check plugin type: %r" % ast_check_plugin_name) check_plugin_name = ast_check_plugin_name.s item = None # type: Item if isinstance(ast_item, ast.Str): item = ast_item.s elif isinstance(ast_item, ast.Num): item = int(ast_item.n) elif isinstance(ast_item, ast.Name) and ast_item.id == "None": item = None else: raise Exception("Invalid autocheck: Wrong item type: %r" % ast_item) # With Check_MK 1.2.7i3 items are now defined to be unicode # strings. Convert items from existing autocheck files for # compatibility. if isinstance(item, str): item = config.decode_incoming_string(item) try: description = config.service_description(hostname, check_plugin_name, item) except Exception: return None # ignore return DiscoveredService( check_plugin_name, item, description, _parse_unresolved_parameters_from_ast(ast_parameters_unresolved), service_labels=_parse_discovered_service_label_from_ast( ast_service_labels))
def _read_raw_autochecks_of(self, hostname): # type: (str) -> List[Service] """Read automatically discovered checks of one host""" basedir = cmk.utils.paths.autochecks_dir filepath = basedir + '/' + hostname + '.mk' result = [] # type: List[Service] if not os.path.exists(filepath): return result check_config = config.get_check_variables() try: cmk_base.console.vverbose("Loading autochecks from %s\n", filepath) autochecks_raw = eval( file(filepath).read().decode("utf-8"), check_config, check_config) # type: List[Dict] except SyntaxError as e: cmk_base.console.verbose("Syntax error in file %s: %s\n", filepath, e, stream=sys.stderr) if cmk.utils.debug.enabled(): raise return result except Exception as e: cmk_base.console.verbose("Error in file %s:\n%s\n", filepath, e, stream=sys.stderr) if cmk.utils.debug.enabled(): raise return result for entry in autochecks_raw: labels = DiscoveredServiceLabels() for label_id, label_value in entry["service_labels"].items(): labels.add_label(ServiceLabel(label_id, label_value)) # With Check_MK 1.2.7i3 items are now defined to be unicode strings. Convert # items from existing autocheck files for compatibility. TODO remove this one day item = entry["item"] if isinstance(item, str): item = config.decode_incoming_string(item) if not isinstance(entry["check_plugin_name"], six.string_types): raise MKGeneralException( "Invalid entry '%r' in check table of host '%s': " "The check type must be a string." % (entry, hostname)) try: description = config.service_description( hostname, entry["check_plugin_name"], item) except Exception: continue # ignore result.append( Service( check_plugin_name=str(entry["check_plugin_name"]), item=item, description=description, parameters=entry["parameters"], service_labels=labels, )) return result
def _parse_info(self, lines): """Split agent output in chunks, splits lines by whitespaces. Returns a HostSections() object. """ sections = {} # Unparsed info for other hosts. A dictionary, indexed by the piggybacked host name. # The value is a list of lines which were received for this host. piggybacked_raw_data = {} persisted_sections = {} # handle sections with option persist(...) host = None section_content = [] section_options = {} agent_cache_info = {} separator = None encoding = None for line in lines: line = line.rstrip("\r") stripped_line = line.strip() if stripped_line[:4] == '<<<<' and stripped_line[-4:] == '>>>>': host = stripped_line[4:-4] if not host: host = None else: host = config.translate_piggyback_host( self._hostname, host) if host == self._hostname: host = None # unpiggybacked "normal" host # Protect Check_MK against unallowed host names. Normally source scripts # like agent plugins should care about cleaning their provided host names # up, but we need to be sure here to prevent bugs in Check_MK code. # a) Replace spaces by underscores if host: host = host.replace(" ", "_") elif host: # processing data for an other host piggybacked_raw_data.setdefault(host, []).append(line) # Found normal section header # section header has format <<<name:opt1(args):opt2:opt3(args)>>> elif stripped_line[:3] == '<<<' and stripped_line[-3:] == '>>>': section_header = stripped_line[3:-3] headerparts = section_header.split(":") section_name = headerparts[0] section_options = {} for o in headerparts[1:]: opt_parts = o.split("(") opt_name = opt_parts[0] if len(opt_parts) > 1: opt_args = opt_parts[1][:-1] else: opt_args = None section_options[opt_name] = opt_args section_content = sections.get(section_name, None) if section_content is None: # section appears in output for the first time section_content = [] sections[section_name] = section_content try: separator = chr(int(section_options["sep"])) except Exception: separator = None # Split of persisted section for server-side caching if "persist" in section_options: until = int(section_options["persist"]) cached_at = int(time.time()) # Estimate age of the data cache_interval = int(until - cached_at) agent_cache_info[section_name] = (cached_at, cache_interval) persisted_sections[section_name] = (cached_at, until, section_content) if "cached" in section_options: agent_cache_info[section_name] = tuple( map(int, section_options["cached"].split(","))) # The section data might have a different encoding encoding = section_options.get("encoding") elif stripped_line != '': if "nostrip" not in section_options: line = stripped_line if encoding: line = config.decode_incoming_string(line, encoding) else: line = config.decode_incoming_string(line) section_content.append(line.split(separator)) return HostSections(sections, agent_cache_info, piggybacked_raw_data, persisted_sections)
def _parse_info(self, lines): """Split agent output in chunks, splits lines by whitespaces. Returns a HostSections() object. """ sections = {} # Unparsed info for other hosts. A dictionary, indexed by the piggybacked host name. # The value is a list of lines which were received for this host. piggybacked_raw_data = {} piggybacked_hostname = None piggybacked_cached_at = int(time.time()) # Transform to seconds and give the piggybacked host a little bit more time piggybacked_cache_age = int(1.5 * 60 * self._host_config.check_mk_check_interval) persisted_sections = {} # handle sections with option persist(...) section_content = [] section_options = {} agent_cache_info = {} separator = None encoding = None for line in lines: line = line.rstrip("\r") stripped_line = line.strip() if stripped_line[:4] == '<<<<' and stripped_line[-4:] == '>>>>': piggybacked_hostname =\ self._get_sanitized_and_translated_piggybacked_hostname(stripped_line) elif piggybacked_hostname: # processing data for an other host if stripped_line[:3] == '<<<' and stripped_line[-3:] == '>>>': line = self._add_cached_info_to_piggybacked_section_header( stripped_line, piggybacked_cached_at, piggybacked_cache_age) piggybacked_raw_data.setdefault(piggybacked_hostname, []).append(line) # Found normal section header # section header has format <<<name:opt1(args):opt2:opt3(args)>>> elif stripped_line[:3] == '<<<' and stripped_line[-3:] == '>>>': section_header = stripped_line[3:-3] headerparts = section_header.split(":") section_name = headerparts[0] section_options = {} for o in headerparts[1:]: opt_parts = o.split("(") opt_name = opt_parts[0] if len(opt_parts) > 1: opt_args = opt_parts[1][:-1] else: opt_args = None section_options[opt_name] = opt_args section_content = sections.get(section_name, None) if section_content is None: # section appears in output for the first time section_content = [] sections[section_name] = section_content try: separator = chr(int(section_options["sep"])) except Exception: separator = None # Split of persisted section for server-side caching if "persist" in section_options: until = int(section_options["persist"]) cached_at = int(time.time()) # Estimate age of the data cache_interval = int(until - cached_at) agent_cache_info[section_name] = (cached_at, cache_interval) persisted_sections[section_name] = (cached_at, until, section_content) if "cached" in section_options: agent_cache_info[section_name] = tuple( map(int, section_options["cached"].split(","))) # The section data might have a different encoding encoding = section_options.get("encoding") elif stripped_line != '': if "nostrip" not in section_options: line = stripped_line if encoding: line = config.decode_incoming_string(line, encoding) else: line = config.decode_incoming_string(line) section_content.append(line.split(separator)) return HostSections(sections, agent_cache_info, piggybacked_raw_data, persisted_sections)