"""Integration test of the cc_power_state_change module. Test that the power state config options work as expected. """ import time import pytest from tests.integration_tests.clouds import IntegrationCloud from tests.integration_tests.instances import IntegrationInstance from tests.integration_tests.util import verify_ordered_items_in_text USER_DATA = """\ #cloud-config power_state: delay: {delay} mode: {mode} message: msg timeout: {timeout} condition: {condition} """ def _detect_reboot(instance: IntegrationInstance): # We'll wait for instance up here, but we don't know if we're # detecting the first boot or second boot, so we also check # the logs to ensure we've booted twice. If the logs show we've # only booted once, wait until we've booted twice instance.instance.wait() for _ in range(600): try: log = instance.read_from_file("/var/log/cloud-init.log") boot_count = log.count("running 'init-local'") if boot_count == 1: instance.instance.wait() elif boot_count > 1: break except Exception: pass time.sleep(1) else: raise Exception("Could not detect reboot") def _can_connect(instance): return instance.execute("true").ok # This test is marked unstable because even though it should be able to # run anywhere, I can only get it to run in an lxd container, and even then # occasionally some timing issues will crop up. @pytest.mark.unstable @pytest.mark.sru_2020_11 @pytest.mark.ubuntu @pytest.mark.lxd_container class TestPowerChange: @pytest.mark.parametrize( "mode,delay,timeout,expected", [ ("poweroff", "now", "10", "will execute: shutdown -P now msg"), ("reboot", "now", "0", "will execute: shutdown -r now msg"), ("halt", "+1", "0", "will execute: shutdown -H +1 msg"), ], ) def test_poweroff( self, session_cloud: IntegrationCloud, mode, delay, timeout, expected ): with session_cloud.launch( user_data=USER_DATA.format( delay=delay, mode=mode, timeout=timeout, condition="true" ), launch_kwargs={"wait": False}, ) as instance: if mode == "reboot": _detect_reboot(instance) else: instance.instance.wait_for_stop() instance.instance.start(wait=True) log = instance.read_from_file("/var/log/cloud-init.log") assert _can_connect(instance) lines_to_check = [ "Running module power-state-change", expected, "running 'init-local'", "config-power-state-change already ran", ] verify_ordered_items_in_text(lines_to_check, log) @pytest.mark.user_data( USER_DATA.format( delay="0", mode="poweroff", timeout="0", condition="false" ) ) def test_poweroff_false_condition(self, client: IntegrationInstance): log = client.read_from_file("/var/log/cloud-init.log") assert _can_connect(client) assert "Condition was false. Will not perform state change" in log