Skip to content

Commit

Permalink
test: add (slightly messy) disk-customization test
Browse files Browse the repository at this point in the history
  • Loading branch information
mvo5 committed Nov 25, 2024
1 parent 60169e7 commit c8ea8e3
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 22 deletions.
65 changes: 48 additions & 17 deletions test/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class ImageBuildResult(NamedTuple):
img_arch: str
container_ref: str
rootfs: str
disk_config: str
username: str
password: str
ssh_keyfile_private_path: str
Expand Down Expand Up @@ -327,7 +328,8 @@ def build_images(shared_tmpdir, build_container, request, force_aws_upload, gpg_
bib_output = bib_output_path.read_text(encoding="utf8")
results.append(ImageBuildResult(
image_type, generated_img, tc.target_arch,
container_ref, tc.rootfs, username, password,
container_ref, tc.rootfs, tc.disk_config,
username, password,
ssh_keyfile_private_path, kargs, bib_output, journal_output))

# generate new keyfile
Expand Down Expand Up @@ -368,12 +370,16 @@ def build_images(shared_tmpdir, build_container, request, force_aws_upload, gpg_
"groups": ["wheel"],
},
],
"filesystem": testutil.create_filesystem_customizations(tc.rootfs),
"kernel": {
"append": kargs,
},
},
}
if tc.disk_config:
cfg["customizations"]["disk"] = testutil.create_disk_customizations(tc.disk_config)
# XXX: disk_config/fs_config cannot be combined, for our tests disk wins
elif tc.rootfs:
cfg["customizations"]["filesystem"] = testutil.create_filesystem_customizations(tc.disk_config, tc.rootfs)

config_json_path = output_path / "config.json"
config_json_path.write_text(json.dumps(cfg), encoding="utf-8")
Expand Down Expand Up @@ -473,7 +479,8 @@ def del_ami():
for image_type in image_types:
results.append(ImageBuildResult(
image_type, artifact[image_type], tc.target_arch,
container_ref, tc.rootfs, username, password,
container_ref, tc.rootfs, tc.disk_config,
username, password,
ssh_keyfile_private_path, kargs, bib_output, journal_output, metadata))
yield results

Expand Down Expand Up @@ -532,19 +539,11 @@ def test_image_boots(image_type):
# XXX: read the fully yaml instead?
assert f"image: {image_type.container_ref}" in output

# check the minsize specified in the build configuration for each mountpoint against the sizes in the image
# TODO: replace 'df' call with 'parted --json' and find the partition size for each mountpoint
exit_status, output = test_vm.run("df --output=target,size", user="root",
keyfile=image_type.ssh_keyfile_private_path)
assert exit_status == 0
# parse the output of 'df' to a mountpoint -> size dict for convenience
mountpoint_sizes = {}
for line in output.splitlines()[1:]:
fields = line.split()
# Note that df output is in 1k blocks, not bytes
mountpoint_sizes[fields[0]] = int(fields[1]) * 2 ** 10 # in bytes
if image_type.disk_config:
assert_disk_customizations(image_type, test_vm)
else:
assert_fs_customizations(image_type, test_vm)

assert_fs_customizations(image_type, mountpoint_sizes)


@pytest.mark.parametrize("image_type", gen_testcases("ami-boot"), indirect=["image_type"])
Expand Down Expand Up @@ -663,17 +662,49 @@ def test_multi_build_request(images):
assert artifacts == expected


def assert_fs_customizations(image_type, mountpoint_sizes):
def assert_fs_customizations(image_type, test_vm):
"""
Asserts that each mountpoint that appears in the build configuration also appears in mountpoint_sizes.
TODO: assert that the size of each filesystem (or partition) also matches the expected size based on the
customization.
"""
fs_customizations = testutil.create_filesystem_customizations(image_type.rootfs)
# check the minsize specified in the build configuration for each mountpoint against the sizes in the image
# TODO: replace 'df' call with 'parted --json' and find the partition size for each mountpoint
exit_status, output = test_vm.run("df --output=target,size", user="root",
keyfile=image_type.ssh_keyfile_private_path)
assert exit_status == 0
# parse the output of 'df' to a mountpoint -> size dict for convenience
mountpoint_sizes = {}
for line in output.splitlines()[1:]:
fields = line.split()
# Note that df output is in 1k blocks, not bytes
mountpoint_sizes[fields[0]] = int(fields[1]) * 2 ** 10 # in bytes

fs_customizations = testutil.create_filesystem_customizations(image_type.disk_config, image_type.rootfs)
for fs in fs_customizations:
mountpoint = fs["mountpoint"]
if mountpoint == "/":
# / is actually /sysroot
mountpoint = "/sysroot"
assert mountpoint in mountpoint_sizes


def assert_disk_customizations(image_type, test_vm):
exit_status, output = test_vm.run("findmnt --json", user="root",
keyfile=image_type.ssh_keyfile_private_path)
assert exit_status == 0
findmnt = json.loads(output)
if dc := image_type.disk_config:
if dc == "lvm":
mnts = [mnt for mnt in findmnt["filesystems"][0]["children"]
if mnt["target"] == "/sysroot"]
assert len(mnts) == 1
assert "/dev/mapper/vg00-rootlv" == mnts[0]["source"]
elif dc == "btrfs":
mnts = [mnt for mnt in findmnt["filesystems"][0]["children"]
if mnt["target"] == "/sysroot"]
assert len(mnts) == 1
assert "btrfs" == mnts[0]["fstype"]
# ensure sysroot comes from the "root" subvolume
assert mnts[0]["source"].endswith("[/root]")
8 changes: 4 additions & 4 deletions test/testcases.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ class TestCase:
rootfs: str = ""
# Sign the container_ref and use the new signed image instead of the original one
sign: bool = False
# use special partition_mode like "lvm"
partition_mode: str = ""
# use special disk_config like "lvm"
disk_config: str = ""

def bib_rootfs_args(self):
if self.rootfs:
Expand Down Expand Up @@ -92,9 +92,9 @@ def gen_testcases(what): # pylint: disable=too-many-return-statements
# and custom with raw (this is arbitrary, we could do it the
# other way around too
test_cases.append(
TestCaseCentos(image="raw", partition_mode="lvm"))
TestCaseCentos(image="raw", disk_config="lvm"))
test_cases.append(
TestCaseFedora(image="raw", partition_mode="btrfs"))
TestCaseFedora(image="raw", disk_config="btrfs"))
# do a cross arch test too
if platform.machine() == "x86_64":
# TODO: re-enable once
Expand Down
46 changes: 45 additions & 1 deletion test/testutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,11 @@ def deregister_ami(ami_id):
print(f"Error {err_code}: {err_msg}")


def create_filesystem_customizations(rootfs: str):
def create_filesystem_customizations(disk_config: str, rootfs: str):
if disk_config:
# XXX: make this nicer, disk-customizations and fs-customizations
# cannot be combined right now
return []
if rootfs == "btrfs":
# only minimal customizations are supported for btrfs currently
return [
Expand Down Expand Up @@ -140,6 +144,46 @@ def create_filesystem_customizations(rootfs: str):
]


def create_disk_customizations(disk_config: str):
if disk_config == "lvm":
return {
# XXX: needed because we have no defaults in images currently
"minsize": "10 GiB",
"partitions": [
{
"type": "lvm",
"logical_volumes": [
{
# XXX: without this we get
# .pipelines[1].stages[2].options.volumes[0].size:
# '0B' does not match '[1-9][0-9]*[bBsSkKmMgGtTpPeE]?'
"minsize": 10000000000,
"fs_type": "xfs",
"mountpoint": "/",
}
]
}
]
}
if disk_config == "btrfs":
return {
# XXX: needed because we have no defaults in images currently
"minsize": "10 GiB",
"partitions": [
{
"type": "btrfs",
"subvolumes": [
{
"name": "varlog",
"mountpoint": "/var/log",
}
]
}
]
}
raise ValueError(f"unsupported disk_config {disk_config}")


# podman_run_common has the common prefix for the podman run invocations
podman_run_common = [
"podman", "run", "--rm",
Expand Down

0 comments on commit c8ea8e3

Please sign in to comment.