def test_ruleset_matcher_get_service_ruleset_values_labels( monkeypatch, hostname, service_description, expected_result): ts = Scenario() ts.add_host("host1") ts.set_autochecks("host1", [ Service("cpu.load", None, "CPU load", "{}", service_labels=DiscoveredServiceLabels( ServiceLabel(u"os", u"linux"), ServiceLabel(u"abc", u"xä"), ServiceLabel(u"hu", u"ha"), )) ]) ts.add_host("host2") ts.set_autochecks("host2", [ Service("cpu.load", None, "CPU load", "{}", service_labels=DiscoveredServiceLabels()), ]) config_cache = ts.apply(monkeypatch) matcher = config_cache.ruleset_matcher assert list( matcher.get_service_ruleset_values( config_cache.ruleset_match_object_of_service( hostname, service_description), ruleset=service_label_ruleset, is_binary=False)) == expected_result
def test_get_check_table_of_mgmt_boards(monkeypatch, hostname, expected_result): autochecks = { "mgmt-board-ipmi": [ Service("mgmt_ipmi_sensors", "TEMP X", "Management Interface: IPMI Sensor TEMP X", {}), ], "ipmi-host": [Service("ipmi_sensors", "TEMP Y", "IPMI Sensor TEMP Y", {}),] } ts = Scenario().add_host("mgmt-board-ipmi", tags={ 'piggyback': 'auto-piggyback', 'networking': 'lan', 'address_family': 'no-ip', 'criticality': 'prod', 'snmp_ds': 'no-snmp', 'site': 'heute', 'agent': 'no-agent' }) ts.add_host("ipmi-host", tags={ 'piggyback': 'auto-piggyback', 'networking': 'lan', 'agent': 'cmk-agent', 'criticality': 'prod', 'snmp_ds': 'no-snmp', 'site': 'heute', 'address_family': 'ip-v4-only' }) ts.set_option("management_protocol", {"mgmt-board-ipmi": "ipmi"}) config_cache = ts.apply(monkeypatch) monkeypatch.setattr(config_cache, "get_autochecks_of", lambda h: autochecks.get(h, [])) CheckManager().load(["mgmt_ipmi_sensors", "ipmi_sensors"]) assert check_table.get_check_table(hostname).keys() == expected_result
def _get_static_check_entries(self, host_config): # type: (config.HostConfig) -> List[Service] entries = [] # type: List[Service] for _checkgroup_name, check_plugin_name, item, params in host_config.static_checks: # Make sure, that for dictionary based checks at least those keys # defined in the factory settings are present in the parameters # TODO: Isn't this done during checking for all checks in more generic code? if isinstance(params, dict) and check_plugin_name in config.check_info: def_levels_varname = config.check_info[check_plugin_name].get( "default_levels_variable") if def_levels_varname: for key, value in config.factory_settings.get( def_levels_varname, {}).items(): if key not in params: params[key] = value descr = config.service_description(host_config.hostname, check_plugin_name, item) entries.append(Service(check_plugin_name, item, descr, params)) # Note: We need to reverse the order of the static_checks. This is # because users assume that earlier rules have precedence over later # ones. For static checks that is important if there are two rules for # a host with the same combination of check type and item. return list(reversed(entries))
def test_host_ruleset_match_object_of_service(monkeypatch): ts = Scenario() ts.add_host("xyz") ts.add_host("test-host", tags={"agent": "no-agent"}) ts.set_autochecks("test-host", [ Service("cpu.load", None, "CPU load", "{}", service_labels=DiscoveredServiceLabels(ServiceLabel(u"abc", u"xä"),)) ]) config_cache = ts.apply(monkeypatch) obj = config_cache.ruleset_match_object_of_service("xyz", "bla blä") assert isinstance(obj, RulesetMatchObject) assert obj.to_dict() == { "host_name": "xyz", "service_description": "bla blä", "service_labels": {}, "service_cache_id": ('bla bl\xc3\xa4', None), } obj = config_cache.ruleset_match_object_of_service("test-host", "CPU load") service_labels = {u"abc": u"xä"} assert isinstance(obj, RulesetMatchObject) assert obj.to_dict() == { "host_name": "test-host", "service_description": "CPU load", "service_labels": service_labels, "service_cache_id": ('CPU load', obj._generate_hash(service_labels)), }
def get_precompiled_check_table(hostname, remove_duplicates=True, filter_mode=None, skip_ignored=True): # type: (str, bool, Optional[str], bool) -> List[Service] """The precompiled check table is somehow special compared to the regular check table. a) It is sorted by the service dependencies (which are only relevant for Nagios). The sorting is important here to send the state updates to Nagios in the correct order. Sending the updates in this order gives Nagios a consistent state in a shorter time. b) More important: Some special checks pre-compue a new set of parameters using a plugin specific precompile_params function. It's purpose is to perform time consuming ruleset evaluations once without the need to perform it during each check execution. The effective check parameters are calculated in these steps: 1. Read from config a) autochecks + cmk_base.config.compute_check_parameters() b) static checks 2. Execute the precompile params function The precompile_params function can base on the "params" from a static check or autocheck and computes a new "params". This is the last step that may be cached across the single executions. 3. Execute the check During check execution will update the check parameters once more with checking.determine_check_params() right before execution the check. """ host_checks = _get_sorted_check_table(hostname, remove_duplicates, filter_mode=filter_mode, skip_ignored=skip_ignored) services = [] # type: List[Service] for service in host_checks: # make these globals available to the precompile function check_api_utils.set_service(service.check_plugin_name, service.description) item_state.set_item_state_prefix(service.check_plugin_name, service.item) precompiled_parameters = get_precompiled_check_parameters( hostname, service.item, service.parameters, service.check_plugin_name) services.append( Service(service.check_plugin_name, service.item, service.description, precompiled_parameters, service.service_labels)) return services
def test_get_check_table(monkeypatch, hostname, expected_result): autochecks = { "ping-host": [Service("smart.temp", "bla", u'Temperature SMART bla', {})], "autocheck-overwrite": [ Service('smart.temp', '/dev/sda', u'Temperature SMART /dev/sda', {"is_autocheck": True}), Service('smart.temp', '/dev/sdb', u'Temperature SMART /dev/sdb', {"is_autocheck": True}), ], "ignore-not-existing-checks": [ Service("bla.blub", "ITEM", u'Blub ITEM', {}), ], "node1": [ Service("smart.temp", "auto-clustered", u"Temperature SMART auto-clustered", {}), Service("smart.temp", "auto-not-clustered", u'Temperature SMART auto-not-clustered', {}) ], } ts = Scenario().add_host(hostname, tags={"criticality": "test"}) ts.add_host("ping-host", tags={"agent": "no-agent"}) ts.add_host("node1") ts.add_cluster("cluster1", nodes=["node1"]) ts.set_option( "static_checks", { "temperature": [ (('smart.temp', '/dev/sda', {}), [], ["no-autochecks", "autocheck-overwrite"]), (('blub.bla', 'ITEM', {}), [], ["ignore-not-existing-checks"]), (('smart.temp', 'ITEM1', {}), [], ["ignore-disabled-rules"], { "disabled": True }), (('smart.temp', 'ITEM2', {}), [], ["ignore-disabled-rules"]), (('smart.temp', '/dev/sda', { "rule": 1 }), [], ["static-check-overwrite"]), (('smart.temp', '/dev/sda', { "rule": 2 }), [], ["static-check-overwrite"]), (('smart.temp', 'static-node1', {}), [], ["node1"]), (('smart.temp', 'static-cluster', {}), [], ["cluster1"]), ] }, ) ts.set_ruleset("clustered_services", [ ([], ['node1'], [u'Temperature SMART auto-clustered$']), ]) config_cache = ts.apply(monkeypatch) monkeypatch.setattr(config_cache, "get_autochecks_of", lambda h: autochecks.get(h, [])) CheckManager().load(["smart"]) assert check_table.get_check_table(hostname) == expected_result
def _read_autochecks_of(self, hostname): # type: (str) -> List[Service] """Read automatically discovered checks of one host""" autochecks = [] for service in self._read_raw_autochecks_cached(hostname): autochecks.append( Service( check_plugin_name=service.check_plugin_name, item=service.item, description=service.description, parameters=config.compute_check_parameters(hostname, service.check_plugin_name, service.item, service.parameters), service_labels=service.service_labels, )) return autochecks
def test_get_cmk_passive_service_attributes(monkeypatch, hostname, result): CheckManager().load(["cpu"]) ts = Scenario().add_host("localhost") ts.add_host("blub") ts.set_option( "extra_service_conf", { "contact_groups": [(u'ding', ['localhost'], ["CPU load$"]),], "check_interval": [ (40.0, ['blub'], ["Check_MK$"]), (33.0, ['localhost'], ["CPU load$"]), ], }) config_cache = ts.apply(monkeypatch) host_config = config_cache.get_host_config(hostname) check_mk_attrs = core_config.get_service_attributes(hostname, "Check_MK", config_cache) service = Service("cpu.loads", None, "CPU load", {}) service_spec = core_config.get_cmk_passive_service_attributes(config_cache, host_config, service, check_mk_attrs) assert service_spec == result
def _get_clustered_services(self, hostname, skip_autochecks): # type: (str, bool) -> CheckTable check_table = {} # type: CheckTable for node in self._host_config.nodes or []: # TODO: Cleanup this to work exactly like the logic above (for a single host) node_config = self._config_cache.get_host_config(node) node_checks = self._get_static_check_entries(node_config) if not skip_autochecks: node_checks += self._config_cache.get_autochecks_of(node) for service in node_checks: if self._config_cache.host_of_clustered_service(node, service.description) != hostname: continue cluster_params = config.compute_check_parameters(hostname, service.check_plugin_name, service.item, service.parameters) cluster_service = Service(service.check_plugin_name, service.item, service.description, cluster_params, service.service_labels) check_table.update(self._handle_service(cluster_service)) return check_table
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
from cmk_base.check_utils import Service # TODO: This misses a lot of cases # - different get_check_table arguments @pytest.mark.parametrize( "hostname,expected_result", [ ("empty-host", {}), # Skip the autochecks automatically for ping hosts ("ping-host", {}), ("no-autochecks", { ('smart.temp', '/dev/sda'): Service( check_plugin_name="smart.temp", item=u"/dev/sda", parameters={'levels': (35, 40)}, description=u'Temperature SMART /dev/sda', ), }), # Static checks overwrite the autocheck definitions ("autocheck-overwrite", { ('smart.temp', '/dev/sda'): Service( check_plugin_name="smart.temp", item=u"/dev/sda", parameters={'levels': (35, 40)}, description=u'Temperature SMART /dev/sda', ), ('smart.temp', '/dev/sdb'): Service( check_plugin_name='smart.temp',
(u"[]", []), (u"", []), (u"@", []), (u"[abc123]", []), # Dict: Allow non string items ( u"""[ {'check_plugin_name': 'df', 'item': 123, 'parameters': {}, 'service_labels': {}}, ]""", [ Service( 'df', 123, u"", { 'inodes_levels': (10.0, 5.0), 'levels': (80.0, 90.0), 'levels_low': (50.0, 60.0), 'magic_normsize': 20, 'show_inodes': 'onlow', 'show_levels': 'onmagic', 'show_reserved': False, 'trend_perfdata': True, 'trend_range': 24 }), ], ), # Dict: Exception on invalid check type ( u"""[ {'check_plugin_name': 123, 'item': 'abc', 'parameters': {}, 'service_labels': {}}, ]""", MKGeneralException, ), # Dict: Regular processing