1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
import logging
import pytest
from tests.integration_tests.clouds import IntegrationCloud
from tests.integration_tests.conftest import get_validated_source
from tests.integration_tests.instances import IntegrationInstance
from tests.integration_tests.integration_settings import PLATFORM
from tests.integration_tests.util import (
lxd_has_nocloud,
override_kernel_command_line,
wait_for_cloud_init,
)
log = logging.getLogger("integration_testing")
@pytest.mark.skipif(PLATFORM != "lxd_vm", reason="Modifies grub config")
@pytest.mark.lxd_use_exec
@pytest.mark.parametrize(
"ds_str, configured, cmdline_configured",
(
(
"ds=nocloud;s=http://my-url/;h=hostname",
"DataSourceNoCloud",
True,
),
("ci.ds=openstack", "DataSourceOpenStack", True),
("bonding.max_bonds=0", "lxd_or_nocloud", False),
),
)
def test_lxd_datasource_kernel_override(
ds_str, configured, cmdline_configured, client: IntegrationInstance
):
"""This test is twofold: it tests kernel command line override, which also
validates OpenStack Ironic requirements. OpenStack Ironic does not
advertise itself to cloud-init via any of the conventional methods: DMI,
etc.
On systemd, ds-identify is able to grok kernel command line, however to
support cloud-init kernel command line parsing on non-systemd, parsing
kernel command line in Python code is required.
"""
if configured == "lxd_or_nocloud":
configured = (
"DataSourceNoCloud" if lxd_has_nocloud(client) else "DataSourceLXD"
)
override_kernel_command_line(ds_str, client)
if cmdline_configured:
assert (
"Kernel command line set to use a single"
f" datasource {configured}"
) in client.execute("cat /var/log/cloud-init.log")
else:
# verify that no plat
log = client.execute("cat /var/log/cloud-init.log")
assert f"Detected {configured}" in log
assert "Kernel command line set to use a single" not in log
GH_REPO_PATH = "https://raw.githubusercontent.com/canonical/cloud-init/main/"
@pytest.mark.skipif(PLATFORM != "lxd_vm", reason="Modifies grub config")
@pytest.mark.lxd_use_exec
@pytest.mark.parametrize(
"ds_str",
(f"ds=nocloud-net;s={GH_REPO_PATH}tests/data/kernel_cmdline_match/",),
)
def test_lxd_datasource_kernel_override_nocloud_net(
ds_str, session_cloud: IntegrationCloud
):
"""NoCloud requirements vary slightly from other datasources with parsing
nocloud-net due to historical reasons. Do to this variation, this is
implemented in NoCloud's ds_detect and therefore has a different log
message.
"""
_ds_name, _, seed_url = ds_str.partition(";")
_key, _, url_val = seed_url.partition("=")
source = get_validated_source(session_cloud)
with session_cloud.launch(
wait=False, # to prevent cloud-init status --wait
launch_kwargs={
# On Jammy and above, we detect the LXD datasource using a
# socket available to the container. This prevents the socket
# from being exposed in the container, so LXD will not be detected.
# This allows us to wait for detection in 'init' stage with
# DataSourceNoCloudNet.
"config_dict": {"security.devlxd": False},
},
) as client:
# We know this will be an LXD instance due to our pytest mark
client.instance.execute_via_ssh = False # pyright: ignore
assert wait_for_cloud_init(client, num_retries=60).ok
if source.installs_new_version():
client.install_new_cloud_init(source, clean=False)
override_kernel_command_line(ds_str, client)
logs = client.execute("cat /var/log/cloud-init.log")
assert (
"nocloud"
== client.execute("cloud-init query platform").stdout.strip()
)
assert url_val in client.execute("cloud-init query subplatform").stdout
assert "Detected DataSourceNoCloudNet" in logs
@pytest.mark.skipif(PLATFORM != "lxd_vm", reason="Modifies grub config")
@pytest.mark.lxd_use_exec
def test_lxd_disable_cloud_init_cmdline(client: IntegrationInstance):
"""Verify cloud-init disablement via kernel command line works."""
override_kernel_command_line("cloud-init=disabled", client)
assert "Active: inactive (dead)" in client.execute(
"systemctl status cloud-init.target"
)
@pytest.mark.lxd_use_exec
def test_lxd_disable_cloud_init_file(client: IntegrationInstance):
"""Verify cloud-init disablement via file works."""
client.execute("touch /etc/cloud/cloud-init.disabled")
client.execute("cloud-init --clean")
client.restart()
assert "Active: inactive (dead)" in client.execute(
"systemctl status cloud-init.target"
)
@pytest.mark.lxd_use_exec
def test_lxd_disable_cloud_init_env(client: IntegrationInstance):
"""Verify cloud-init disablement via environment variable works."""
env = """DefaultEnvironment=KERNEL_CMDLINE=cloud-init=disabled"""
client.execute(f'echo "{env}" >> /etc/systemd/system.conf')
client.execute("cloud-init --clean")
client.restart()
assert "Active: inactive (dead)" in client.execute(
"systemctl status cloud-init.target"
)
|