diff --git a/examples/test-3.hmdl.json b/examples/test-3.hmdl.json index 64edf2d..9f21d03 100644 --- a/examples/test-3.hmdl.json +++ b/examples/test-3.hmdl.json @@ -1,24 +1,10 @@ { - "defaults": { - "threshold": 1, - "schedule": { - "regular_interval": 10, - "attentive_interval": 1 - }, - "notifications": [ - { - "kind": "console", - "parameters": { - } - } - ] - }, "checks": [ { "name": "test", "kind": "generic_remote", "parameters": { - "ssh_host": "bragi.pool.greenscale.de", + "host": "bragi.pool.greenscale.de", "ssh_user": "fenris", "ssh_port": 8192, "ssh_key": "/home/fenris/.ssh/keypairs/gs-bragi" diff --git a/examples/test.hmdl.json b/examples/test.hmdl.json index b1eea19..0b5f1fc 100644 --- a/examples/test.hmdl.json +++ b/examples/test.hmdl.json @@ -4,6 +4,7 @@ "regular_interval": 10, "attentive_interval": 1 }, + "threshold": 1, "notifications": [ { "kind": "console", diff --git a/source/logic/checks/generic_remote.py b/source/logic/checks/generic_remote.py index abb0df2..22a022f 100644 --- a/source/logic/checks/generic_remote.py +++ b/source/logic/checks/generic_remote.py @@ -8,7 +8,7 @@ class implementation_check_kind_generic_remote(interface_check_kind): "type": "object", "additionalProperties": False, "properties": { - "ssh_host" : { + "host" : { "type" : "string" }, "ssh_port": { @@ -38,7 +38,7 @@ class implementation_check_kind_generic_remote(interface_check_kind): } }, "required": [ - "ssh_host" + "host" ] } @@ -47,8 +47,8 @@ class implementation_check_kind_generic_remote(interface_check_kind): [implementation] ''' def normalize_conf_node(self, node): - if (not "ssh_host" in node): - raise ValueError("mandatory parameter \"ssh_host\" missing") + if (not "host" in node): + raise ValueError("mandatory parameter \"host\" missing") else: return dict_merge( { @@ -78,7 +78,7 @@ class implementation_check_kind_generic_remote(interface_check_kind): if True: outer_command_parts.append("ssh"); if True: - outer_command_parts.append(string_coin("{{host}}", {"host": parameters["ssh_host"]})); + outer_command_parts.append(string_coin("{{host}}", {"host": parameters["host"]})); if (parameters["ssh_port"] is not None): outer_command_parts.append(string_coin("-p {{port}}", {"port": ("%u" % parameters["ssh_port"])})); if (parameters["ssh_user"] is not None): @@ -104,8 +104,8 @@ class implementation_check_kind_generic_remote(interface_check_kind): stuff = result["stdout"].split("\n")[-2].split(" ") data = { "device": stuff[0], - "used": stuff[2], - "avail": stuff[3], + "used": int(stuff[2]), + "avail": int(stuff[3]), "perc": int(stuff[4][:-1]), } if (data["perc"] > parameters["threshold"]): @@ -116,12 +116,14 @@ class implementation_check_kind_generic_remote(interface_check_kind): enum_condition.warning ), "info": { - "ssh_host": parameters["ssh_host"], - "mount_point": parameters["mount_point"], - "device": data["device"], - "used": data["used"], # ToDo: Humanlesbarkeit herstellen - "available": data["avail"], # ToDo: Humanlesbarkeit herstellen - "percentage": (str(data["perc"]) + "%"), + "data": { + "host": parameters["host"], + "device": data["device"], + "mount_point": parameters["mount_point"], + "used": format_bytes(data["used"]), + "available": format_bytes(data["avail"]), + "percentage": (str(data["perc"]) + "%"), + }, "faults": [ translation_get("checks.generic_remote.overflow") ], diff --git a/source/logic/conf.py b/source/logic/conf.py index b8a76d2..3bb50f3 100644 --- a/source/logic/conf.py +++ b/source/logic/conf.py @@ -309,8 +309,8 @@ def conf_normalize_check( node__["annoy"] = node_["annoy"] if ("schedule" in node_): node__["schedule"] = conf_normalize_schedule(node_["schedule"]) - if ("notification" in node_): - node__["notification"] = list( + if ("notifications" in node_): + node__["notifications"] = list( map( lambda x: conf_normalize_notification(notification_channel_implementations, x), node_["notifications"] diff --git a/source/logic/lib.py b/source/logic/lib.py index fb686c6..de3d928 100644 --- a/source/logic/lib.py +++ b/source/logic/lib.py @@ -60,3 +60,26 @@ def shell_command(command): "stderr": result.stderr.decode(), } + +def format_bytes(bytes_): + units = [ + {"label": "B", "digits": 0}, + {"label": "KB", "digits": 1}, + {"label": "MB", "digits": 1}, + {"label": "GB", "digits": 1}, + {"label": "TB", "digits": 1}, + {"label": "PB", "digits": 1}, + ] + number = bytes_ + index = 0 + while ((number >= 1000) and (index < (len(units) - 1))): + number /= 1000 + index += 1 + return ( + ("%." + ("%u" % units[index]["digits"]) + "f %s") + % ( + number, + units[index]["label"], + ) + ) + diff --git a/source/logic/main.py b/source/logic/main.py index 51bed75..705447f 100644 --- a/source/logic/main.py +++ b/source/logic/main.py @@ -107,7 +107,7 @@ def main(): "script": implementation_check_kind_script(), "file_state": implementation_check_kind_file_state(), "http_request": implementation_check_kind_http_request(), - "generic_remote" : implementation_check_kind_generic_remote() + "generic_remote" : implementation_check_kind_generic_remote(), } ### load notification channel implementations diff --git a/source/test/test.py b/source/test/test.py new file mode 100644 index 0000000..6f5048d --- /dev/null +++ b/source/test/test.py @@ -0,0 +1,102 @@ +definitions = [ + { + "name": "lib.string_coin", + "procedure": lambda input_: string_coin(input_["template"], input_["arguments"]), + "cases": [ + { + "input": { + "template": "{{sachen}} sind {{farbe}}", + "arguments": { + "farbe": "rot", + }, + }, + "output": "{{sachen}} sind rot" + }, + { + "input": { + "template": "{{sachen}} sind {{farbe}}", + "arguments": { + }, + }, + "output": "{{sachen}} sind {{farbe}}" + }, + { + "input": { + "template": "{{sachen}} sind {{farbe}}", + "arguments": { + "sachen": "rosen", + "farbe": "rot", + }, + }, + "output": "rosen sind rot" + }, + { + "input": { + "template": "{{sachen}} sind {{farbe}}", + "arguments": { + "sachen": "rosen", + "farbe": "rot", + "ort": "frankreich", + }, + }, + "output": "rosen sind rot" + }, + ], + }, + { + "name": "lib.format_bytes", + "procedure": lambda input_: format_bytes(input_), + "cases": [ + { + "input": 999, + "output": "999 B", + }, + { + "input": 1000, + "output": "1.0 KB", + }, + { + "input": 1000000, + "output": "1.0 MB", + }, + { + "input": 1000000000, + "output": "1.0 GB", + }, + { + "input": 1000000000000, + "output": "1.0 TB", + }, + { + "input": 1000000000000000, + "output": "1.0 PB", + }, + { + "input": 1000000000000000000, + "output": "1000.0 PB", + }, + ], + }, +] + + +for definition in definitions: + for index in range(len(definition["cases"])): + case = definition["cases"][index] + output_actual = definition["procedure"](case["input"]) + output_expected = case["output"] + passed = (output_actual == output_expected) + info = { + "input": case["input"], + "output_expected": output_expected, + "output_actual": output_actual, + } + _sys.stderr.write( + "[%s] %s.%u%s\n" + % ( + ("+" if passed else "x"), + definition["name"], + index, + ("" if passed else (": " + _json.dumps(info))), + ) + ) diff --git a/tools/build b/tools/build index 511564f..621c89f 100755 --- a/tools/build +++ b/tools/build @@ -4,6 +4,7 @@ import sys as _sys import os as _os import json as _json import stat as _stat +import argparse as _argparse def file_read(path): @@ -34,24 +35,62 @@ def main(): ## consts dir_source = "source" dir_build = "build" - sources_logic = [ - _os.path.join(dir_source, "logic", "packages.py"), - _os.path.join(dir_source, "logic", "lib.py"), - _os.path.join(dir_source, "logic", "localization.py"), - _os.path.join(dir_source, "logic", "condition.py"), - _os.path.join(dir_source, "logic", "conf.py"), - _os.path.join(dir_source, "logic", "checks", "_interface.py"), - _os.path.join(dir_source, "logic", "checks", "script.py"), - _os.path.join(dir_source, "logic", "checks", "file_state.py"), - _os.path.join(dir_source, "logic", "checks", "http_request.py"), - _os.path.join(dir_source, "logic", "checks", "generic_remote.py"), - _os.path.join(dir_source, "logic", "channels", "_interface.py"), - _os.path.join(dir_source, "logic", "channels", "console.py"), - _os.path.join(dir_source, "logic", "channels", "email.py"), - _os.path.join(dir_source, "logic", "channels", "libnotify.py"), - _os.path.join(dir_source, "logic", "main.py"), - ] - path_compilation = _os.path.join(dir_build, "heimdall") + targets = { + "app": { + "sources": [ + _os.path.join(dir_source, "logic", "packages.py"), + _os.path.join(dir_source, "logic", "lib.py"), + _os.path.join(dir_source, "logic", "localization.py"), + _os.path.join(dir_source, "logic", "condition.py"), + _os.path.join(dir_source, "logic", "conf.py"), + _os.path.join(dir_source, "logic", "checks", "_interface.py"), + _os.path.join(dir_source, "logic", "checks", "script.py"), + _os.path.join(dir_source, "logic", "checks", "file_state.py"), + _os.path.join(dir_source, "logic", "checks", "http_request.py"), + _os.path.join(dir_source, "logic", "checks", "generic_remote.py"), + _os.path.join(dir_source, "logic", "channels", "_interface.py"), + _os.path.join(dir_source, "logic", "channels", "console.py"), + _os.path.join(dir_source, "logic", "channels", "email.py"), + _os.path.join(dir_source, "logic", "channels", "libnotify.py"), + _os.path.join(dir_source, "logic", "main.py"), + ], + "build": _os.path.join(dir_build, "heimdall"), + }, + "test": { + "sources": [ + _os.path.join(dir_source, "logic", "packages.py"), + _os.path.join(dir_source, "logic", "lib.py"), + _os.path.join(dir_source, "logic", "localization.py"), + _os.path.join(dir_source, "logic", "condition.py"), + _os.path.join(dir_source, "logic", "conf.py"), + _os.path.join(dir_source, "logic", "checks", "_interface.py"), + _os.path.join(dir_source, "logic", "checks", "script.py"), + _os.path.join(dir_source, "logic", "checks", "file_state.py"), + _os.path.join(dir_source, "logic", "checks", "http_request.py"), + _os.path.join(dir_source, "logic", "checks", "generic_remote.py"), + _os.path.join(dir_source, "logic", "channels", "_interface.py"), + _os.path.join(dir_source, "logic", "channels", "console.py"), + _os.path.join(dir_source, "logic", "channels", "email.py"), + _os.path.join(dir_source, "logic", "channels", "libnotify.py"), + _os.path.join(dir_source, "test", "test.py"), + ], + "build": _os.path.join(dir_build, "heimdall-test"), + }, + } + + ## args + argument_parser = _argparse.ArgumentParser( + ) + argument_parser.add_argument( + "-t", + "--target", + type = str, + choices = ["app", "test"], + default = "app", + dest = "target_name", + help = "which target to build", + ) + args = argument_parser.parse_args() ## exec if (not _os.path.exists(dir_build)): @@ -82,17 +121,17 @@ def main(): ) ### logic - for path in sources_logic: + for path in targets[args.target_name]["sources"]: compilation += (file_read(path) + "\n") ### write to file - if _os.path.exists(path_compilation): - _os.remove(path_compilation) - file_write(path_compilation, compilation) + if _os.path.exists(targets[args.target_name]["build"]): + _os.remove(targets[args.target_name]["build"]) + file_write(targets[args.target_name]["build"], compilation) ### postproess _os.chmod( - path_compilation, + targets[args.target_name]["build"], (_stat.S_IRWXU | _stat.S_IXGRP | _stat.S_IXOTH) )