File: test_kernel_command_line_match.py

package info (click to toggle)
cloud-init 25.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 12,412 kB
  • sloc: python: 135,894; sh: 3,883; makefile: 141; javascript: 30; xml: 22
file content (143 lines) | stat: -rw-r--r-- 5,331 bytes parent folder | download | duplicates (3)
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"
    )