From 0504402a8a6e02efb8b8ca4c0d069e66aef51fd2 Mon Sep 17 00:00:00 2001 From: Andreas Wrede Date: Fri, 8 May 2026 07:25:47 -0400 Subject: [PATCH] hbc/hbc_mini: add owner config; include in os_info; server applies to host - owner: optional top-level config key in ~/.hbc.yaml / ~/.hbc.json - Propagated into plugin configs at load time so os_info can include it - os_info PLG data carries owner field when set - udp: sets host.owner from os_info if not already configured server-side - live.html: format event log timestamps as YYYY-MM-DD HH:MM:SS (24-hour) Co-Authored-By: Claude Sonnet 4.6 --- hbd/client/config.py | 7 +++++-- hbd/client/plugin.py | 5 ++++- hbd/client/plugins/os_info.py | 2 ++ hbd/server/templates/live.html | 5 ++++- hbd/server/udp.py | 6 ++++++ scripts/hbc_mini.py | 7 ++++++- 6 files changed, 27 insertions(+), 5 deletions(-) diff --git a/hbd/client/config.py b/hbd/client/config.py index 9b85fc7..2b1d242 100644 --- a/hbd/client/config.py +++ b/hbd/client/config.py @@ -15,12 +15,15 @@ CLIENT_DEFAULTS = { # Network settings "hb_port": 50003, # Port where hbd servers listen "interval": 10, # Heartbeat interval in seconds - + + # Host identity + "owner": None, # Optional username to set as this host's owner on the server + # Runtime flags "foreground": False, "verbose": False, "debug": 0, - + # Plugin configuration "plugins": {}, # Per-plugin configuration "thresholds": {}, # Threshold configuration for monitoring diff --git a/hbd/client/plugin.py b/hbd/client/plugin.py index 1dcd04c..1cce13a 100644 --- a/hbd/client/plugin.py +++ b/hbd/client/plugin.py @@ -364,7 +364,10 @@ class PluginLoader: # Instantiate plugin with config — check plugins subdict first, # then top-level keys (e.g. nagios_runner: ... at root of config). - plugin_instance_config = plugins_subconfig.get(obj.name) or raw_config.get(obj.name, {}) + plugin_instance_config = dict(plugins_subconfig.get(obj.name) or raw_config.get(obj.name) or {}) + # Propagate top-level owner so os_info (and any future plugin) can report it. + if "owner" in raw_config and "owner" not in plugin_instance_config: + plugin_instance_config["owner"] = raw_config["owner"] plugin = obj(config=plugin_instance_config) # Initialize plugin diff --git a/hbd/client/plugins/os_info.py b/hbd/client/plugins/os_info.py index be5c8b2..c5f3570 100644 --- a/hbd/client/plugins/os_info.py +++ b/hbd/client/plugins/os_info.py @@ -62,6 +62,8 @@ class OSInfoPlugin(InfoPlugin): "hbc_version": hbc_version, "hbc_type": "full", } + if self.config.get("owner"): + data["owner"] = self.config["owner"] # Add Linux-specific distribution info if platform.system() == "Linux": diff --git a/hbd/server/templates/live.html b/hbd/server/templates/live.html index a5fb356..d9fc0ea 100644 --- a/hbd/server/templates/live.html +++ b/hbd/server/templates/live.html @@ -474,7 +474,10 @@ } else if (state.type == "message") { var msgs = document.getElementById("messages"); var msg = state.data; - var ts_str = new Date(msg.ts * 1000).toLocaleString(); + var _d = new Date(msg.ts * 1000); + function _p(n) { return n < 10 ? '0' + n : '' + n; } + var ts_str = _d.getFullYear() + '-' + _p(_d.getMonth()+1) + '-' + _p(_d.getDate()) + + ' ' + _p(_d.getHours()) + ':' + _p(_d.getMinutes()) + ':' + _p(_d.getSeconds()); var lvl = (msg.level || "INFO").toLowerCase(); var html = '
'; html += '' + ts_str + ''; diff --git a/hbd/server/udp.py b/hbd/server/udp.py index 1a1fa1f..1de0b21 100644 --- a/hbd/server/udp.py +++ b/hbd/server/udp.py @@ -368,6 +368,12 @@ def handle_datagram(msg: dict, addr, transport, ctx: dict): if k not in ("ID", "plugin", "id", "name")} # Store plugin data with timestamp host.add_plugin_data(plugin_name, plugin_data, timestamp=now) + + # If os_info reports an owner and none is configured server-side, apply it + if plugin_name == "os_info" and not host.owner: + reported_owner = plugin_data.get("owner") + if reported_owner: + host.owner = reported_owner if DEBUG > 1: print(f"Stored plugin data for {uname}: {plugin_name}") diff --git a/scripts/hbc_mini.py b/scripts/hbc_mini.py index f293a6c..494d453 100755 --- a/scripts/hbc_mini.py +++ b/scripts/hbc_mini.py @@ -114,6 +114,7 @@ def _stodict(data: bytes) -> Dict[str, Any]: _DEFAULTS: Dict[str, Any] = { "hb_port": 50003, "interval": 10, + "owner": None, "plugins": {}, } @@ -239,6 +240,8 @@ class OSInfoPlugin(InfoPlugin): "hbc_version": __version__, "hbc_type": "mini", } + if self.config.get("owner"): + data["owner"] = self.config["owner"] if platform.system() == "Linux": data.update(_linux_distro()) elif platform.system() == "Darwin": @@ -716,7 +719,9 @@ async def _load_plugins(cfg: Dict[str, Any]) -> List[Plugin]: plugins_cfg: Dict[str, Any] = cfg.get("plugins", {}) loaded: List[Plugin] = [] for cls in _ALL_PLUGIN_CLASSES: - plugin_cfg = plugins_cfg.get(cls.name) or cfg.get(cls.name, {}) + plugin_cfg = dict(plugins_cfg.get(cls.name) or cfg.get(cls.name) or {}) + if "owner" in cfg and "owner" not in plugin_cfg: + plugin_cfg["owner"] = cfg["owner"] plugin: Plugin = cls(config=plugin_cfg) try: ok = await plugin.initialize()