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)
|