-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Test that bluechictl monitor receives UnitCreated/UnitRemoved signals
Adds a test, which verifies that bluechictl monitor is able to receive UnitCreated and UnitRemoved signals. Fixes: #784 Signed-off-by: Martin Perina <mperina@redhat.com>
- Loading branch information
Showing
4 changed files
with
175 additions
and
0 deletions.
There are no files selected for viewing
2 changes: 2 additions & 0 deletions
2
tests/tests/tier0/bluechictl-monitor-unit-created-removed/main.fmf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
summary: Test that bluechictl monitor can receive UnitCreated and UnitRemoved signals | ||
id: 1becd1cf-6f07-4bbb-9b16-ec438bbb6c22 |
115 changes: 115 additions & 0 deletions
115
tests/tests/tier0/bluechictl-monitor-unit-created-removed/python/monitor.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
# SPDX-License-Identifier: LGPL-2.1-or-later | ||
|
||
import signal | ||
import subprocess | ||
import tempfile | ||
import threading | ||
import time | ||
import unittest | ||
|
||
node_name_foo = "node-foo" | ||
|
||
service_simple = "simple.service" | ||
|
||
|
||
class FileFollower: | ||
def __init__(self, file_name): | ||
self.pos = 0 | ||
self.file_name = file_name | ||
self.file_desc = None | ||
|
||
def __enter__(self): | ||
self.file_desc = open(self.file_name, mode='r') | ||
return self | ||
|
||
def __exit__(self, exception_type, exception_value, exception_traceback): | ||
if exception_type or exception_type or exception_traceback: | ||
print(f"Exception raised: exception_type='{exception_type}', " | ||
f"exception_value='{exception_value}', exception_traceback: {exception_traceback}") | ||
if self.file_desc: | ||
self.file_desc.close() | ||
|
||
def __iter__(self): | ||
while self.new_lines(): | ||
self.seek() | ||
line = self.file_desc.read().split('\n')[0] | ||
yield line | ||
|
||
self.pos += len(line) + 1 | ||
|
||
def seek(self): | ||
self.file_desc.seek(self.pos) | ||
|
||
def new_lines(self): | ||
self.seek() | ||
return '\n' in self.file_desc.read() | ||
|
||
|
||
class TestMonitorSpecificNodeAndUnit(unittest.TestCase): | ||
|
||
def setUp(self) -> None: | ||
self.bluechictl_proc = None | ||
|
||
self.created = False | ||
self.removed = False | ||
|
||
def timeout_guard(self): | ||
time.sleep(10) | ||
print(f"Loop timeout - UnitRemoved signal for service '{service_simple}' on node '{node_name_foo}' " | ||
f"was not successfully received on time") | ||
self.bluechictl_proc.send_signal(signal.SIGINT) | ||
self.bluechictl_proc.wait() | ||
|
||
def process_events(self): | ||
out_file = None | ||
|
||
with tempfile.NamedTemporaryFile() as out_file: | ||
try: | ||
self.bluechictl_proc = subprocess.Popen( | ||
["/usr/bin/bluechictl", "monitor", f"{node_name_foo}", f"{service_simple}"], | ||
stdout=out_file, | ||
bufsize=1) | ||
|
||
with FileFollower(out_file.name) as bluechictl_out: | ||
events_received = False | ||
while not events_received and self.bluechictl_proc.poll() is None: | ||
for line in bluechictl_out: | ||
print(f"Evaluating line '{line}'") | ||
if not self.created and "Unit created (reason: real)" in line: | ||
print(f"Received UnitCreated signal for service '{service_simple}' " | ||
f"on node '{node_name_foo}'") | ||
self.created = True | ||
|
||
elif self.created and not self.removed and "Unit removed (reason: real)" in line: | ||
print(f"Received UnitRemoved signal for service '{service_simple}' " | ||
f"on node '{node_name_foo}'") | ||
self.removed = True | ||
events_received = True | ||
break | ||
|
||
else: | ||
print(f"Ignoring line '{line}'") | ||
|
||
# Wait for the new output from bluechictl monitor | ||
time.sleep(0.5) | ||
finally: | ||
if self.bluechictl_proc: | ||
self.bluechictl_proc.send_signal(signal.SIGINT) | ||
self.bluechictl_proc.wait() | ||
self.bluechictl_proc = None | ||
|
||
def test_monitor_specific_node_and_unit(self): | ||
t = threading.Thread(target=self.process_events) | ||
# mark the failsafe thread as daemon so it stops when the main process stops | ||
failsafe_thread = threading.Thread(target=self.timeout_guard, daemon=True) | ||
t.start() | ||
failsafe_thread.start() | ||
|
||
t.join() | ||
|
||
assert self.created | ||
assert self.removed | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
7 changes: 7 additions & 0 deletions
7
tests/tests/tier0/bluechictl-monitor-unit-created-removed/systemd/simple.service
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[Unit] | ||
Description=Run a simple service | ||
|
||
[Service] | ||
Type=simple | ||
ExecStart=/bin/true | ||
RemainAfterExit=yes |
51 changes: 51 additions & 0 deletions
51
...0/bluechictl-monitor-unit-created-removed/test_bluechictl_monitor_unit_created_removed.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# SPDX-License-Identifier: LGPL-2.1-or-later | ||
|
||
import os | ||
import threading | ||
import time | ||
|
||
from typing import Dict | ||
|
||
from bluechi_test.test import BluechiTest | ||
from bluechi_test.machine import BluechiControllerMachine, BluechiAgentMachine | ||
from bluechi_test.config import BluechiControllerConfig, BluechiAgentConfig | ||
|
||
node_name_foo = "node-foo" | ||
service_simple = "simple.service" | ||
|
||
|
||
def monitor_service(ctrl: BluechiControllerMachine): | ||
result, output = ctrl.run_python(os.path.join("python", "monitor.py")) | ||
if result != 0: | ||
raise Exception(output) | ||
|
||
|
||
def exec(ctrl: BluechiControllerMachine, nodes: Dict[str, BluechiAgentMachine]): | ||
node_foo = nodes[node_name_foo] | ||
node_foo.copy_systemd_service(service_simple) | ||
assert node_foo.wait_for_unit_state_to_be(service_simple, "inactive") | ||
|
||
t = threading.Thread(target=monitor_service, args=(ctrl,)) | ||
t.start() | ||
|
||
# Wait till monitoring thread on controller starts properly | ||
time.sleep(0.5) | ||
|
||
# Running systemctl status on inactive unit should raise UnitCreated and UnitRemoved signals | ||
assert node_foo.systemctl.get_unit_state(service_simple) == "inactive" | ||
|
||
t.join() | ||
|
||
|
||
def test_bluechictl_monitor_unit_created_removed( | ||
bluechi_test: BluechiTest, | ||
bluechi_ctrl_default_config: BluechiControllerConfig, | ||
bluechi_node_default_config: BluechiAgentConfig): | ||
|
||
bluechi_node_default_config.node_name = node_name_foo | ||
bluechi_ctrl_default_config.allowed_node_names = [bluechi_node_default_config.node_name] | ||
|
||
bluechi_test.set_bluechi_controller_config(bluechi_ctrl_default_config) | ||
bluechi_test.add_bluechi_agent_config(bluechi_node_default_config) | ||
|
||
bluechi_test.run(exec) |