Skip to content

Commit ea89189

Browse files
committed
WIP answerfile generation
This process has several steps: - building of a data structure holding all of the answerfile data, from a customizable base in data.py and from tests-specific items - serialization as XML to be read by host-installer - necessary changes to the ISO for host-installer to use it This is needed so: - different tests can use different parameters without the need for provisionning every answerfile to be used - tests can dynamically add contents for their own needs, before the XML gets actualy written FIXME: - this covers boot from remastered ISO and not PXE, install on UEFI/NVMe disk (xml needs generation there too) and not BIOS/ATA (needs clever parametrization) - doc
1 parent d44d3d9 commit ea89189

File tree

4 files changed

+67
-6
lines changed

4 files changed

+67
-6
lines changed

conftest.py

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,10 +256,42 @@ def sr_disk_for_all_hosts(request, host):
256256
logging.info(f">> Disk or block device {disk} is present and free on all pool members")
257257
yield candidates[0]
258258

259-
@pytest.fixture(scope='session')
260-
def iso_remaster():
259+
@pytest.fixture(scope='function')
260+
def answerfile(request):
261+
markers = request.node.get_closest_marker("answerfile")
262+
263+
if markers is None:
264+
yield None # no answerfile to generate
265+
return
266+
267+
# construct answerfile definition from option "base", and explicit bits
268+
marker = markers.args[0]
269+
if marker["base"]:
270+
from data import BASE_ANSWERFILES
271+
answerfile_def = BASE_ANSWERFILES[marker["base"]]
272+
del marker["base"]
273+
else:
274+
answerfile_def = {}
275+
answerfile_def.update(marker)
276+
277+
# convert to a ElementTree.Element tree suitable for further
278+
# modification before we serialize it to XML
279+
import xml.etree.ElementTree as ET
280+
root = ET.Element(answerfile_def["mode"])
281+
del answerfile_def["mode"]
282+
for name, defn in answerfile_def.items():
283+
text = defn.get("text", None)
284+
if text:
285+
del defn["text"]
286+
element = ET.SubElement(root, name, **defn)
287+
if text:
288+
element.text = text
289+
290+
yield ET.ElementTree(root)
291+
292+
@pytest.fixture(scope='function')
293+
def iso_remaster(answerfile):
261294
SOURCE_ISO = "/home/user/iso/xcp-ng-8.2.1-20231130.iso" # FIXME dict in data.py
262-
ANSWERFILE_URL = "http://pxe/configs/custom/ydi/install-8.2-uefi-iso-ext.xml" # FIXME
263295

264296
from data import ISOSR_SRV, ISOSR_PATH, TEST_SSH_PUBKEY, TOOLS
265297
assert "iso-remaster" in TOOLS
@@ -270,6 +302,13 @@ def iso_remaster():
270302
remastered_iso = os.path.join(isotmp, "image.iso")
271303
iso_patcher_script = os.path.join(isotmp, "iso-patcher")
272304
img_patcher_script = os.path.join(isotmp, "img-patcher")
305+
answerfile_xml = os.path.join(isotmp, "answerfile.xml")
306+
307+
if answerfile:
308+
logging.info("generating answerfile %s", answerfile_xml)
309+
answerfile.write(answerfile_xml)
310+
else:
311+
logging.info("no answerfile")
273312

274313
logging.info("Remastering %s to %s", SOURCE_ISO, remastered_iso)
275314

@@ -282,7 +321,8 @@ def iso_remaster():
282321
mkdir -p "$INSTALLIMG/root/.ssh"
283322
echo "{TEST_SSH_PUBKEY}" > "$INSTALLIMG/root/.ssh/authorized_keys"
284323
285-
curl {ANSWERFILE_URL} -o "$INSTALLIMG/root/answerfile.xml"
324+
test ! -e "{answerfile_xml}" ||
325+
cp "{answerfile_xml}" "$INSTALLIMG/root/answerfile.xml"
286326
""",
287327
file=patcher_fd)
288328
os.chmod(patcher_fd.fileno(), 0o755)
@@ -293,8 +333,9 @@ def iso_remaster():
293333
print(f"""#!/bin/bash
294334
set -ex
295335
ISODIR="$1"
296-
SED_COMMANDS=(-e "s@/vmlinuz@/vmlinuz sshpassword={passwd} atexit=shell@")
297-
SED_COMMANDS+=(-e "s@/vmlinuz@/vmlinuz install answerfile=file:///root/answerfile.xml network_device=all@")
336+
SED_COMMANDS=(-e "s@/vmlinuz@/vmlinuz sshpassword={passwd} atexit=shell network_device=all@")
337+
test ! -e "{answerfile_xml}" ||
338+
SED_COMMANDS+=(-e "s@/vmlinuz@/vmlinuz install answerfile=file:///root/answerfile.xml@")
298339
299340
sed -i "${{SED_COMMANDS[@]}}" \
300341
"$ISODIR"/*/*/grub*.cfg \

data.py-dist

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# You need to have an SSH key into the hosts' /root/.ssh/authorized_keys.
66
HOST_DEFAULT_USER = "root"
77
HOST_DEFAULT_PASSWORD = ""
8+
HOST_DEFAULT_PASSWORD_HASH = "" # FIXME
89

910
# Public key for a private key available to the test runner
1011
TEST_SSH_PUBKEY = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKz9uQOoxq6Q0SQ0XTzQHhDolvuo/7EyrDZsYQbRELhcPJG8MT/o5u3HyJFhIP2+HqBSXXgmqRPJUkwz9wUwb2sUwf44qZm/pyPUWOoxyVtrDXzokU/uiaNKUMhbnfaXMz6Ogovtjua63qld2+ZRXnIgrVtYKtYBeu/qKGVSnf4FTOUKl1w3uKkr59IUwwAO8ay3wVnxXIHI/iJgq6JBgQNHbn3C/SpYU++nqL9G7dMyqGD36QPFuqH/cayL8TjNZ67TgAzsPX8OvmRSqjrv3KFbeSlpS/R4enHkSemhgfc8Z2f49tE7qxWZ6x4Uyp5E6ur37FsRf/tEtKIUJGMRXN XCP-ng CI"
@@ -109,3 +110,13 @@ DEFAULT_LVMOISCSI_DEVICE_CONFIG = {
109110
# 'targetIQN': 'target.example',
110111
# 'SCSIid': 'id'
111112
}
113+
114+
BASE_ANSWERFILES = dict(
115+
INSTALL={
116+
"mode": "installation",
117+
"root-password": {"type": "hash", "text": HOST_DEFAULT_PASSWORD_HASH},
118+
"admin-interface": {"name": "eth0", "proto": "dhcp"},
119+
"timezone": {"text": "Europe/Paris"},
120+
"keymap": {"text": "us"},
121+
},
122+
)

pytest.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ markers =
2121
# * VM-related markers to give parameters to fixtures
2222
vm_definitions: dicts of VM defs for create_vms fixture.
2323

24+
# * FIXME
25+
answerfile: def of an answerfile
26+
2427
# * Test targets related to VMs
2528
small_vm: tests that it is enough to run just once, using the smallest possible VM.
2629
big_vm: tests that it would be good to run with a big VM.

tests/install/test_install.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ class TestInstallNested:
2424
vdis=[dict(name="vm 1 system disk", size="100GiB", device="xvda", userdevice="0")],
2525
vifs=[dict(index=0, network_uuid="eabc1038-e40f-2ae5-0781-a3adbec1cae8")], # FIXME
2626
))
27+
@pytest.mark.answerfile(
28+
{
29+
"base": "INSTALL",
30+
"source": {"type": "local"},
31+
"primary-disk": {"text": "nvme0n1"},
32+
})
2733
def test_install_nested_821_uefi(self, iso_remaster, create_vms):
2834
assert len(create_vms) == 1
2935
host_vm = create_vms[0]

0 commit comments

Comments
 (0)