diff --git a/tests/bluechi_test/bluechi_is_online.py b/tests/bluechi_test/bluechi_is_online.py index b9382be072..aa9b0e9ed2 100644 --- a/tests/bluechi_test/bluechi_is_online.py +++ b/tests/bluechi_test/bluechi_is_online.py @@ -57,3 +57,12 @@ def system_is_online(self) -> bool: 0, ) return result == 0 + + def monitor_node(self, node_name: str) -> bool: + result, output = self.run( + f"Monitoring status of node {node_name}.", + f"node {node_name} --monitor", + False, + 0, + ) + return result == 0 diff --git a/tests/tests/tier0/bluechi-is-online-node-monitor/main.fmf b/tests/tests/tier0/bluechi-is-online-node-monitor/main.fmf new file mode 100644 index 0000000000..8c9ee36900 --- /dev/null +++ b/tests/tests/tier0/bluechi-is-online-node-monitor/main.fmf @@ -0,0 +1,2 @@ +summary: --monitor keeps monitoring as long as node is online and exits if it detects an offline state. +id: 929f11ba-00ab-4c4f-8614-e1aebcbaa96d diff --git a/tests/tests/tier0/bluechi-is-online-node-monitor/test_bluechi_is_online_node_monitor.py b/tests/tests/tier0/bluechi-is-online-node-monitor/test_bluechi_is_online_node_monitor.py new file mode 100644 index 0000000000..b465ab0d26 --- /dev/null +++ b/tests/tests/tier0/bluechi-is-online-node-monitor/test_bluechi_is_online_node_monitor.py @@ -0,0 +1,79 @@ +# +# Copyright Contributors to the Eclipse BlueChi project +# +# SPDX-License-Identifier: LGPL-2.1-or-later +import logging +import threading +import time +from typing import Dict + +from bluechi_test.config import BluechiAgentConfig, BluechiControllerConfig +from bluechi_test.machine import BluechiAgentMachine, BluechiControllerMachine +from bluechi_test.test import BluechiTest + +LOGGER = logging.getLogger(__name__) + +NODE_FOO = "node-foo" +AGENT_ONE = "agent-one" + + +def monitor_command( + ctrl: BluechiControllerMachine, node_name: str, monitor_output: list +): + """Run the node --monitor command and monitor output.""" + result = ctrl.bluechi_is_online.monitor_node(node_name) + if not result: + monitor_output.append(f"Monitoring node {node_name} failed.") + + +def exec(ctrl: BluechiControllerMachine, nodes: Dict[str, BluechiAgentMachine]): + node_foo = nodes[NODE_FOO] + + # Test 1: Agent and node are running, no monitor output expected + LOGGER.debug("Starting NODE_FOO.") + node_foo.systemctl.start_unit("bluechi-agent") + + monitor_output_test_one = [] + monitor_thread = threading.Thread( + target=monitor_command, args=(ctrl, NODE_FOO, monitor_output_test_one) + ) + monitor_thread.start() + time.sleep(2) + assert ( + not monitor_output_test_one + ), "Monitor command should not produce output when node is running." + + # Test 2: Stop NODE_FOO and verify monitoring detects the failure + LOGGER.debug("Starting monitor thread before stopping NODE_FOO.") + monitor_output_test_two = [] + monitor_thread = threading.Thread( + target=monitor_command, args=(ctrl, NODE_FOO, monitor_output_test_two) + ) + monitor_thread.start() + + LOGGER.debug("Stopping NODE_FOO.") + node_foo.systemctl.stop_unit("bluechi-agent") + assert node_foo.wait_for_unit_state_to_be("bluechi-agent", "inactive") + assert ( + monitor_output_test_two + ), "Monitor command should produce output when NODE_FOO is stopped." + + +def test_bluechi_is_online_node_monitor( + bluechi_test: BluechiTest, + bluechi_node_default_config: BluechiAgentConfig, + bluechi_ctrl_default_config: BluechiControllerConfig, +): + node_foo_cfg = bluechi_node_default_config.deep_copy() + node_foo_cfg.node_name = NODE_FOO + + agent_one_cfg = bluechi_node_default_config.deep_copy() + agent_one_cfg.node_name = AGENT_ONE + + bluechi_ctrl_default_config.allowed_node_names = [NODE_FOO, AGENT_ONE] + + bluechi_test.set_bluechi_controller_config(bluechi_ctrl_default_config) + bluechi_test.add_bluechi_agent_config(node_foo_cfg) + bluechi_test.add_bluechi_agent_config(agent_one_cfg) + + bluechi_test.run(exec)