Skip to content

Commit 30ab3f7

Browse files
committed
ephemeral: Implement cloud-init ConfigDrive support
Implement cloud-init support for ephemeral VMs using the ConfigDrive datasource approach, using a VFAT filesystem (more compatible than ISOs). This uses the same approach as systemd for populating VFAT filesystems: mkfs.vfat to create the filesystem, and mcopy (from mtools) to populate it. We avoid using systemd-repart itself as it creates GPT-partitioned disks rather than raw VFAT filesystems. The ConfigDrive is attached as a raw disk image and will be automatically detected by cloud-init in the guest VM. Fixes: #108 Assisted-by: Claude Code (Sonnet 4.5) Signed-off-by: Colin Walters <walters@verbum.org>
1 parent cec4402 commit 30ab3f7

File tree

16 files changed

+1011
-26
lines changed

16 files changed

+1011
-26
lines changed

.github/workflows/main.yml

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@ jobs:
4242
- name: Run unit tests
4343
run: just unit
4444

45-
- name: Pull test images
46-
run: just pull-test-images
47-
4845
- name: Create nextest archive
4946
run: |
5047
cargo nextest archive --release -p integration-tests --archive-file nextest-archive.tar.zst
@@ -95,17 +92,12 @@ jobs:
9592
with:
9693
libvirt: 'true'
9794

98-
- name: Extract image lists from Justfile
99-
run: |
100-
echo "PRIMARY_IMAGE=$(just --evaluate PRIMARY_IMAGE)" >> $GITHUB_ENV
101-
echo "ALL_BASE_IMAGES=$(just --evaluate ALL_BASE_IMAGES)" >> $GITHUB_ENV
95+
- name: Install additional dependencies
96+
run: sudo apt install -y go-md2man dosfstools mtools
10297

10398
- name: Setup Rust
10499
uses: ./.github/actions/setup-rust
105100

106-
- name: Pull test images
107-
run: just pull-test-images
108-
109101
- name: Download nextest archive
110102
uses: actions/download-artifact@v4
111103
with:
@@ -121,17 +113,7 @@ jobs:
121113
run: chmod +x target/release/bcvk
122114

123115
- name: Run integration tests (partition ${{ matrix.partition }}/4)
124-
run: |
125-
# Clean up any leftover containers before starting
126-
cargo run --release --bin test-cleanup -p integration-tests 2>/dev/null || true
127-
128-
# Run the partitioned tests
129-
cargo nextest run --archive-file nextest-archive.tar.zst \
130-
--profile integration \
131-
--partition hash:${{ matrix.partition }}/4
132-
133-
# Clean up containers after tests complete
134-
cargo run --release --bin test-cleanup -p integration-tests 2>/dev/null || true
116+
run: just test-integration-partition nextest-archive.tar.zst ${{ matrix.partition }}
135117
env:
136118
BCVK_PATH: ${{ github.workspace }}/target/release/bcvk
137119
BCVK_PRIMARY_IMAGE: ${{ env.PRIMARY_IMAGE }}

Justfile

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,16 @@ unit *ARGS:
2222
pull-test-images:
2323
podman pull -q {{ALL_BASE_IMAGES}} >/dev/null
2424

25+
# Build cloud-init test image
26+
build-cloud-init-image:
27+
#!/usr/bin/env bash
28+
set -euo pipefail
29+
echo "Building cloud-init test image..."
30+
podman build -t localhost/bootc-cloud-init tests/fixtures/cloud-init/
31+
echo "✓ Cloud-init test image built: localhost/bootc-cloud-init"
32+
2533
# Run integration tests (auto-detects nextest, with cleanup)
26-
test-integration *ARGS: build pull-test-images
34+
test-integration *ARGS: build pull-test-images build-cloud-init-image
2735
#!/usr/bin/env bash
2836
set -euo pipefail
2937
export BCVK_PATH=$(pwd)/target/release/bcvk
@@ -48,6 +56,25 @@ test-integration *ARGS: build pull-test-images
4856

4957
exit $TEST_EXIT_CODE
5058

59+
# Run integration tests from a partition (used by CI)
60+
test-integration-partition ARCHIVE PARTITION: pull-test-images build-cloud-init-image
61+
#!/usr/bin/env bash
62+
set -euo pipefail
63+
64+
# Clean up any leftover containers before starting
65+
cargo run --release --bin test-cleanup -p integration-tests 2>/dev/null || true
66+
67+
# Run the partitioned tests
68+
cargo nextest run --archive-file {{ARCHIVE}} \
69+
--profile integration \
70+
--partition hash:{{ PARTITION }}/4
71+
TEST_EXIT_CODE=$?
72+
73+
# Clean up containers after tests complete
74+
cargo run --release --bin test-cleanup -p integration-tests 2>/dev/null || true
75+
76+
exit $TEST_EXIT_CODE
77+
5178
# Clean up integration test containers
5279
test-cleanup:
5380
cargo run --release --bin test-cleanup -p integration-tests

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,34 @@ disk images that can be imported into other virtualization frameworks.
77

88
See [docs/src/installation.md](./docs/src/installation.md).
99

10+
## Dependencies
11+
12+
bcvk requires the following runtime dependencies:
13+
14+
### Core virtualization
15+
- **QEMU** - The core virtualization engine
16+
- **virtiofsd** - VirtIO filesystem daemon for sharing directories with VMs
17+
- **podman** - Container runtime for managing bootc images
18+
19+
### For libvirt integration
20+
- **libvirt** - Virtualization management for persistent VMs
21+
22+
### For cloud-init support
23+
- **dosfstools** - Provides `mkfs.vfat` for creating VFAT filesystems
24+
- **mtools** - Provides `mcopy` for populating VFAT images (used for cloud-init ConfigDrive)
25+
26+
### Package installation
27+
28+
**Debian/Ubuntu:**
29+
```bash
30+
sudo apt install qemu-kvm qemu-system qemu-utils virtiofsd podman libvirt-daemon libvirt-clients dosfstools mtools
31+
```
32+
33+
**Fedora/RHEL:**
34+
```bash
35+
sudo dnf install qemu-kvm qemu-img virtiofsd podman libvirt libvirt-client dosfstools mtools
36+
```
37+
1038
## Quick Start
1139

1240
### Running a bootc container as ephemeral VM

crates/integration-tests/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub(crate) use integration_tests::{
1616
};
1717

1818
mod tests {
19+
pub mod cloud_init;
1920
pub mod libvirt_base_disks;
2021
pub mod libvirt_port_forward;
2122
pub mod libvirt_upload_disk;

0 commit comments

Comments
 (0)