summaryrefslogtreecommitdiff
path: root/tests/integration_tests/test_kernel_commandline_match.py
blob: cbbce9ca96dea2596946dbb70c1ca7c8d0baf450 (plain)
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
import pytest

from tests.integration_tests.instances import IntegrationInstance
from tests.integration_tests.integration_settings import PLATFORM


def override_kernel_cmdline(ds_str: str, c: IntegrationInstance) -> str:
    """
    Configure grub's kernel command line to tell cloud-init to use OpenStack
    - even though LXD should naturally be detected.

    This runs on LXD, but forces cloud-init to attempt to run OpenStack.
    This will inevitably fail on LXD, but we only care that it tried - on
    Ironic, for example, it will succeed.
    """
    client = c

    # The final output in /etc/default/grub should be:
    #
    # GRUB_CMDLINE_LINUX="'ds=nocloud;s=http://my-url/'"
    #
    # That ensures that the kernel commandline passed into
    # /boot/efi/EFI/ubuntu/grub.cfg will be properly single-quoted
    #
    # Example:
    #
    # linux /boot/vmlinuz-5.15.0-1030-kvm ro 'ds=nocloud;s=http://my-url/'
    #
    # Not doing this will result in a semicolon-delimited ds argument
    # terminating the kernel arguments prematurely.
    client.execute('printf "GRUB_CMDLINE_LINUX=\\"" >> /etc/default/grub')
    client.execute('printf "\'" >> /etc/default/grub')
    client.execute(f"printf '{ds_str}' >> /etc/default/grub")
    client.execute('printf "\'\\"" >> /etc/default/grub')

    # We should probably include non-systemd distros at some point. This should
    # most likely be as simple as updating the output path for grub-mkconfig
    client.execute("grub-mkconfig -o /boot/efi/EFI/ubuntu/grub.cfg")
    client.execute("cloud-init clean --logs")
    client.instance.shutdown()
    client.instance.execute_via_ssh = False
    client.instance.start()
    client.execute("cloud-init status --wait")
    return client.execute("cat /var/log/cloud-init.log")


@pytest.mark.skipif(PLATFORM != "lxd_vm", reason="Modifies grub config")
@pytest.mark.lxd_use_exec
@pytest.mark.parametrize(
    "ds_str, configured",
    (
        ("ds=nocloud;s=http://my-url/", "DataSourceNoCloud"),
        ("ci.ds=openstack", "DataSourceOpenStack"),
    ),
)
def test_lxd_datasource_kernel_override(
    ds_str, configured, client: IntegrationInstance
):
    """This test is twofold: it tests kernel commandline 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 commandline, however to
    support cloud-init kernel command line parsing on non-systemd, parsing
    kernel commandline in Python code is required.
    """

    assert (
        "Machine is configured by the kernel commandline to run on single "
        f"datasource {configured}"
    ) in override_kernel_cmdline(ds_str, client)


@pytest.mark.skipif(PLATFORM != "lxd_vm", reason="Modifies grub config")
@pytest.mark.lxd_use_exec
@pytest.mark.parametrize("ds_str", ("ci.ds=nocloud-net",))
def test_lxd_datasource_kernel_override_nocloud_net(
    ds_str, client: IntegrationInstance
):
    """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.
    """

    assert (
        "Machine is running on DataSourceNoCloud [seed=None][dsmode=net]."
    ) in override_kernel_cmdline(ds_str, client)