system: validate host-initiated native base builds
This commit is contained in:
@@ -251,11 +251,14 @@ On those systems, Fruix exposes:
|
||||
- `/run/current-system/development-profile`
|
||||
- `/run/current-development`
|
||||
- `/usr/local/bin/fruix-development-environment`
|
||||
- `/usr/include -> /run/current-system/development-profile/usr/include`
|
||||
- `/usr/share/mk -> /run/current-system/development-profile/usr/share/mk`
|
||||
|
||||
The intent is:
|
||||
|
||||
- keep the main runtime profile lean
|
||||
- expose headers, `usr/share/mk`, and selected toolchain commands explicitly
|
||||
- satisfy native FreeBSD buildworld/buildkernel expectations for canonical system paths when development support is enabled
|
||||
- avoid treating a development-heavy system image as the default runtime shape
|
||||
|
||||
Compared with Guix, this is conceptually similar to keeping development-oriented state separate from the main runtime identity, but Fruix currently expresses it as a system-attached development overlay rather than through Guix's broader profile/tooling model.
|
||||
|
||||
@@ -38,6 +38,10 @@ Fruix currently has:
|
||||
- `/run/current-system/development-profile`
|
||||
- `/run/current-development`
|
||||
- `/usr/local/bin/fruix-development-environment`
|
||||
- a validated host-initiated native base-build path inside a Fruix-managed guest via:
|
||||
- real XCP-ng boot of a development-enabled Fruix system
|
||||
- in-guest `buildworld` / `buildkernel`
|
||||
- staged `installworld` / `distribution` / `installkernel`
|
||||
|
||||
Validated boot modes still are:
|
||||
|
||||
@@ -50,37 +54,40 @@ The validated Phase 18 installation work currently uses:
|
||||
|
||||
## Latest completed achievement
|
||||
|
||||
### 2026-04-05 — Phase 20.1 completed
|
||||
### 2026-04-05 — Phase 20.2 completed
|
||||
|
||||
Fruix now has a validated real-VM path where a booted Fruix-managed FreeBSD system exposes a separate development environment for native base work without collapsing the runtime/development split.
|
||||
Fruix now has a validated intermediate path where the host still orchestrates the workflow, but real FreeBSD native base-build work runs inside a booted Fruix-managed FreeBSD guest.
|
||||
|
||||
Highlights:
|
||||
|
||||
- operating-system declarations now support:
|
||||
- `#:development-packages`
|
||||
- system closures can now carry a separate development profile at:
|
||||
- `/run/current-system/development-profile`
|
||||
- `/run/current-development`
|
||||
- opt-in systems now ship an in-guest helper at:
|
||||
- `/usr/local/bin/fruix-development-environment`
|
||||
- the validated Phase 20.1 guest path exposes:
|
||||
- native headers
|
||||
- `usr/share/mk` for `bsd.*.mk`
|
||||
- Clang toolchain commands such as `cc`, `c++`, `ar`, `ranlib`, and `nm`
|
||||
- the validated guest workflow now supports:
|
||||
- `eval "$(/usr/local/bin/fruix-development-environment)"`
|
||||
- direct compilation with the Fruix-provided toolchain
|
||||
- a simple `bsd.prog.mk` build on the running Fruix guest
|
||||
- development-enabled systems now expose canonical native-build compatibility links at:
|
||||
- `/usr/include -> /run/current-system/development-profile/usr/include`
|
||||
- `/usr/share/mk -> /run/current-system/development-profile/usr/share/mk`
|
||||
- media builder versions were bumped so booted images and future installed targets pick up that rootfs layout change
|
||||
- the validated guest build path now runs real FreeBSD native build steps inside the Fruix-managed guest:
|
||||
- `buildworld`
|
||||
- `buildkernel`
|
||||
- `installworld`
|
||||
- `distribution`
|
||||
- `installkernel`
|
||||
- staged install steps use:
|
||||
- `DB_FROM_SRC=yes`
|
||||
- so the staged install is driven by the declared source tree's account database rather than by the guest's minimal local `/etc` state
|
||||
- the validated result now includes staged native artifact outputs for:
|
||||
- kernel
|
||||
- bootloader slice
|
||||
- headers / `usr/share/mk`
|
||||
|
||||
Validation:
|
||||
|
||||
- `PASS phase20-development-environment-xcpng`
|
||||
- `PASS phase20-host-initiated-native-build-xcpng`
|
||||
|
||||
Reports:
|
||||
|
||||
- `docs/system-deployment-workflow.md`
|
||||
- `docs/GUIX_DIFFERENCES.md`
|
||||
- `docs/reports/phase20-development-environment-freebsd.md`
|
||||
- `docs/reports/phase20-host-initiated-native-builds-freebsd.md`
|
||||
|
||||
## Recent major milestones
|
||||
|
||||
@@ -106,6 +113,6 @@ Reports:
|
||||
|
||||
Per `docs/PLAN_4.md`, the next planned step is:
|
||||
|
||||
- **Phase 20.2** — run host-initiated native base builds inside a Fruix-managed environment
|
||||
- **Phase 20.3** — reassess and potentially prototype guest self-hosted base builds
|
||||
|
||||
Phase 20.1 is now complete: Fruix validates a separate in-system development environment for native FreeBSD base work on the approved real XCP-ng path.
|
||||
Phase 20.2 is now complete: Fruix validates host-initiated native FreeBSD base builds running inside the approved real XCP-ng Fruix guest path.
|
||||
|
||||
169
docs/reports/phase20-host-initiated-native-builds-freebsd.md
Normal file
169
docs/reports/phase20-host-initiated-native-builds-freebsd.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# Phase 20.2: host-initiated native base builds inside a Fruix-managed environment
|
||||
|
||||
Date: 2026-04-05
|
||||
|
||||
## Goal
|
||||
|
||||
Validate the next step after Phase 20.1:
|
||||
|
||||
- the host still orchestrates the outer loop
|
||||
- the actual FreeBSD native base build work runs inside a booted Fruix-managed system
|
||||
|
||||
This is the intermediate path between:
|
||||
|
||||
- purely host-side native base builds
|
||||
- any future claim of guest self-hosting
|
||||
|
||||
The target here was not a new self-hosted package manager story.
|
||||
|
||||
It was narrower:
|
||||
|
||||
- boot a Fruix-managed FreeBSD system on the approved real XCP-ng path
|
||||
- expose the development environment required for native base work
|
||||
- run real `buildworld` / `buildkernel` / staged install steps inside that Fruix guest
|
||||
- confirm that the resulting staged artifacts are the expected FreeBSD base slices
|
||||
|
||||
## Implementation
|
||||
|
||||
### Canonical development-path compatibility links
|
||||
|
||||
Phase 20.1 proved that Fruix could keep development content separate in:
|
||||
|
||||
- `/run/current-system/development-profile`
|
||||
- `/run/current-development`
|
||||
|
||||
Phase 20.2 exposed an additional practical requirement:
|
||||
|
||||
- FreeBSD native base builds still expect canonical system paths such as:
|
||||
- `/usr/include`
|
||||
- `/usr/share/mk`
|
||||
|
||||
For development-enabled systems, `populate-rootfs-from-closure` now also exposes:
|
||||
|
||||
- `/usr/include -> /run/current-system/development-profile/usr/include`
|
||||
- `/usr/share/mk -> /run/current-system/development-profile/usr/share/mk`
|
||||
|
||||
This keeps the development profile separate while still satisfying the buildworld/buildkernel assumptions of the native FreeBSD build system.
|
||||
|
||||
### Media builder invalidation
|
||||
|
||||
Because this changed the visible rootfs layout of booted systems, the media builder versions were bumped in `modules/fruix/system/freebsd/media.scm`:
|
||||
|
||||
- `image-builder-version`
|
||||
- `install-builder-version`
|
||||
- `installer-image-builder-version`
|
||||
- `installer-iso-builder-version`
|
||||
|
||||
That ensured booted images and future installed targets actually pick up the new compatibility links.
|
||||
|
||||
### New validation harness
|
||||
|
||||
Added:
|
||||
|
||||
- `tests/system/run-phase20-host-initiated-native-build-xcpng.sh`
|
||||
|
||||
This harness reuses the validated Phase 20.1 XCP-ng path first, then performs the 20.2-native-build step over SSH from the host.
|
||||
|
||||
The guest build flow is:
|
||||
|
||||
1. boot the development-enabled Fruix guest on XCP-ng
|
||||
2. recover the materialized source store from `/run/current-system/metadata/store-layout.scm`
|
||||
3. run real FreeBSD native build commands inside the guest:
|
||||
- `make -j8 buildworld`
|
||||
- `make -j8 buildkernel`
|
||||
- `make DESTDIR=... installworld`
|
||||
- `make DESTDIR=... distribution`
|
||||
- `make DESTDIR=... installkernel`
|
||||
4. stage narrower artifact slices from the staged output:
|
||||
- headers slice
|
||||
- bootloader slice
|
||||
- kernel stage
|
||||
|
||||
### Why `DB_FROM_SRC=yes` is used for staged install steps
|
||||
|
||||
The development-enabled Fruix guest is intentionally lean and does not carry the full ambient host account database.
|
||||
|
||||
`installworld` on modern FreeBSD checks for required users/groups unless `DB_FROM_SRC` is defined. For staged installs into `DESTDIR`, the appropriate controlled input is the source tree's own account database under `etc/`, not the minimal running guest's `/etc/master.passwd`.
|
||||
|
||||
So the validated Phase 20.2 staged install path uses:
|
||||
|
||||
- `DB_FROM_SRC=yes`
|
||||
|
||||
for:
|
||||
|
||||
- `installworld`
|
||||
- `distribution`
|
||||
- `installkernel`
|
||||
|
||||
That keeps the staged install driven by the declared source input rather than by accidental guest-local account state.
|
||||
|
||||
## Validation
|
||||
|
||||
Passing run:
|
||||
|
||||
- `PASS phase20-host-initiated-native-build-xcpng`
|
||||
- workdir: `/tmp/fruix-phase20-host-initiated-native-build-xcpng`
|
||||
|
||||
Validated on the approved real XCP-ng path:
|
||||
|
||||
- VM `90490f2e-e8fc-4b7a-388e-5c26f0157289`
|
||||
- VDI `0f1f90d3-48ca-4fa2-91d8-fc6339b95743`
|
||||
|
||||
Representative result:
|
||||
|
||||
```text
|
||||
build_jobs=8
|
||||
source_store=/frx/store/12d7704362e95afc2697db63f168b878e082b372-freebsd-source-default
|
||||
source_root=/frx/store/12d7704362e95afc2697db63f168b878e082b372-freebsd-source-default/tree
|
||||
build_root=/var/tmp/fruix-phase20-native-build
|
||||
world_stage=/var/tmp/fruix-phase20-native-build/stage-world
|
||||
kernel_stage=/var/tmp/fruix-phase20-native-build/stage-kernel
|
||||
headers_stage=/var/tmp/fruix-phase20-native-build/artifact-headers
|
||||
bootloader_stage=/var/tmp/fruix-phase20-native-build/artifact-bootloader
|
||||
build_root_size=7.6G
|
||||
world_stage_size=672M
|
||||
kernel_stage_size=739M
|
||||
headers_stage_size=32M
|
||||
bootloader_stage_size=1.3M
|
||||
sha_kernel=16950f116a52134b98e2f8e0dacc556e18fe254e4a0ac2c1741422dde281a341
|
||||
sha_loader=ea417846167ece270ada611624dca622ca38bd30125b9a125cd8ebb8b3600313
|
||||
sha_param=9eb140ca7d9666f3d484a4174c9acd94b45427db6292b4e17de19af2c6aa5219
|
||||
host_initiated_native_build=ok
|
||||
```
|
||||
|
||||
The harness verified all of the following:
|
||||
|
||||
- the guest still boots and passes the Phase 20.1 development-environment checks first
|
||||
- development-enabled systems expose canonical native-build compatibility links at:
|
||||
- `/usr/include`
|
||||
- `/usr/share/mk`
|
||||
- the guest can recover the declared materialized FreeBSD source store from system metadata
|
||||
- real FreeBSD `buildworld` succeeds inside the booted Fruix guest
|
||||
- real FreeBSD `buildkernel` succeeds inside the booted Fruix guest
|
||||
- staged `installworld`, `distribution`, and `installkernel` also succeed inside the guest
|
||||
- the staged outputs contain the expected artifact shapes:
|
||||
- `boot/kernel/kernel`
|
||||
- `usr/include/sys/param.h`
|
||||
- `usr/share/mk/bsd.prog.mk`
|
||||
- `boot/loader.efi`
|
||||
- `boot/defaults/loader.conf`
|
||||
- `boot/lua/loader.lua`
|
||||
|
||||
## Result
|
||||
|
||||
Phase 20.2 is complete.
|
||||
|
||||
Fruix now validates a real host-orchestrated path where:
|
||||
|
||||
- the host boots and reaches a Fruix-managed development-enabled guest
|
||||
- the guest uses its own Fruix-exposed development paths and declared source store
|
||||
- the native FreeBSD base build work runs inside that Fruix-managed environment
|
||||
- the host remains the outer orchestrator and result collector
|
||||
|
||||
This materially narrows the gap to any future self-hosting experiment while still avoiding the complexity jump to a full guest-driven package/deployment loop.
|
||||
|
||||
## Next step
|
||||
|
||||
Per `docs/PLAN_4.md`, the next planned step is:
|
||||
|
||||
- **Phase 20.3** — reassess and potentially prototype guest self-hosted base builds
|
||||
@@ -214,15 +214,51 @@ Intended use:
|
||||
eval "$(/usr/local/bin/fruix-development-environment)"
|
||||
```
|
||||
|
||||
That helper exports a development-oriented environment while keeping the main runtime profile separate. The validated Phase 20.1 path currently uses this to expose at least:
|
||||
That helper exports a development-oriented environment while keeping the main runtime profile separate. The validated Phase 20 path currently uses this to expose at least:
|
||||
|
||||
- native headers under `usr/include`
|
||||
- FreeBSD `share/mk` files for `bsd.*.mk`
|
||||
- Clang toolchain commands such as `cc`, `c++`, `ar`, `ranlib`, and `nm`
|
||||
- `MAKEFLAGS` pointing at the development profile's `usr/share/mk`
|
||||
|
||||
For native base-build compatibility, development-enabled systems also now expose canonical links at:
|
||||
|
||||
- `/usr/include -> /run/current-system/development-profile/usr/include`
|
||||
- `/usr/share/mk -> /run/current-system/development-profile/usr/share/mk`
|
||||
|
||||
This is the current Fruix-native way to make a running system suitable for controlled native base-development work without merging development content back into the main runtime profile.
|
||||
|
||||
### Host-initiated native base builds inside a Fruix-managed guest
|
||||
|
||||
The currently validated intermediate path toward self-hosting is still host-orchestrated.
|
||||
|
||||
The host:
|
||||
|
||||
1. boots a development-enabled Fruix guest
|
||||
2. connects over SSH
|
||||
3. recovers the materialized FreeBSD source store from system metadata
|
||||
4. runs native FreeBSD build commands inside the guest
|
||||
5. collects and records the staged outputs
|
||||
|
||||
The validated build sequence inside the guest is:
|
||||
|
||||
- `make -jN buildworld`
|
||||
- `make -jN buildkernel`
|
||||
- `make DESTDIR=... installworld`
|
||||
- `make DESTDIR=... distribution`
|
||||
- `make DESTDIR=... installkernel`
|
||||
|
||||
For staged install steps, the validated path uses:
|
||||
|
||||
- `DB_FROM_SRC=yes`
|
||||
|
||||
so the staged install is driven by the declared source tree's account database rather than by accidental guest-local `/etc/master.passwd` contents.
|
||||
|
||||
This is the current Phase 20.2 answer to “where should native base builds run?”
|
||||
|
||||
- **inside** a Fruix-managed FreeBSD environment
|
||||
- but still with the **host** driving the outer orchestration loop
|
||||
|
||||
## Deployment patterns
|
||||
|
||||
### 1. Build-first workflow
|
||||
|
||||
@@ -376,7 +376,13 @@
|
||||
(string-append rootfs "/usr/local/bin/fruix"))
|
||||
(when (file-exists? (string-append closure-path "/development-profile"))
|
||||
(symlink-force "/run/current-system/development-profile"
|
||||
(string-append rootfs "/run/current-development")))
|
||||
(string-append rootfs "/run/current-development"))
|
||||
(when (file-exists? (string-append closure-path "/development-profile/usr/include"))
|
||||
(symlink-force "/run/current-system/development-profile/usr/include"
|
||||
(string-append rootfs "/usr/include")))
|
||||
(when (file-exists? (string-append closure-path "/development-profile/usr/share/mk"))
|
||||
(symlink-force "/run/current-system/development-profile/usr/share/mk"
|
||||
(string-append rootfs "/usr/share/mk"))))
|
||||
(when (file-exists? (string-append closure-path "/usr/local/bin/fruix-development-environment"))
|
||||
(symlink-force "/run/current-system/usr/local/bin/fruix-development-environment"
|
||||
(string-append rootfs "/usr/local/bin/fruix-development-environment")))
|
||||
@@ -598,10 +604,10 @@
|
||||
(installer-root-partition-label . ,installer-root-partition-label)
|
||||
(target-install . ,target-install-spec))))
|
||||
|
||||
(define image-builder-version "2")
|
||||
(define install-builder-version "1")
|
||||
(define installer-image-builder-version "1")
|
||||
(define installer-iso-builder-version "2")
|
||||
(define image-builder-version "3")
|
||||
(define install-builder-version "2")
|
||||
(define installer-image-builder-version "2")
|
||||
(define installer-iso-builder-version "3")
|
||||
|
||||
(define (operating-system-install-metadata-object install-spec closure-path store-items)
|
||||
`((install-version . ,install-builder-version)
|
||||
|
||||
275
tests/system/run-phase20-host-initiated-native-build-xcpng.sh
Executable file
275
tests/system/run-phase20-host-initiated-native-build-xcpng.sh
Executable file
@@ -0,0 +1,275 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
repo_root=${PROJECT_ROOT:-$(pwd)}
|
||||
os_template=${OS_TEMPLATE:-$repo_root/tests/system/phase20-development-operating-system.scm.in}
|
||||
system_name=${SYSTEM_NAME:-phase20-operating-system}
|
||||
root_size=${ROOT_SIZE:-20g}
|
||||
metadata_target=${METADATA_OUT:-}
|
||||
root_authorized_key_file=${ROOT_AUTHORIZED_KEY_FILE:-$HOME/.ssh/id_ed25519.pub}
|
||||
root_ssh_private_key_file=${ROOT_SSH_PRIVATE_KEY_FILE:-$HOME/.ssh/id_ed25519}
|
||||
cleanup=0
|
||||
|
||||
if [ -n "${WORKDIR:-}" ]; then
|
||||
workdir=$WORKDIR
|
||||
mkdir -p "$workdir"
|
||||
else
|
||||
workdir=$(mktemp -d /tmp/fruix-phase20-native-build-xcpng.XXXXXX)
|
||||
cleanup=1
|
||||
fi
|
||||
if [ "${KEEP_WORKDIR:-0}" -eq 1 ]; then
|
||||
cleanup=0
|
||||
fi
|
||||
|
||||
inner_metadata=$workdir/phase20-native-build-inner-metadata.txt
|
||||
metadata_file=$workdir/phase20-host-initiated-native-build-xcpng-metadata.txt
|
||||
|
||||
action_cleanup() {
|
||||
if [ "$cleanup" -eq 1 ]; then
|
||||
rm -rf "$workdir"
|
||||
fi
|
||||
}
|
||||
trap action_cleanup EXIT INT TERM
|
||||
|
||||
KEEP_WORKDIR=1 WORKDIR="$workdir/inner" METADATA_OUT="$inner_metadata" \
|
||||
ROOT_AUTHORIZED_KEY_FILE="$root_authorized_key_file" \
|
||||
ROOT_SSH_PRIVATE_KEY_FILE="$root_ssh_private_key_file" \
|
||||
OS_TEMPLATE="$os_template" SYSTEM_NAME="$system_name" ROOT_SIZE="$root_size" \
|
||||
"$repo_root/tests/system/run-phase20-development-environment-xcpng.sh"
|
||||
|
||||
phase8_metadata=$(sed -n 's/^phase8_metadata=//p' "$inner_metadata")
|
||||
closure_path=$(sed -n 's/^closure_path=//p' "$inner_metadata")
|
||||
closure_base=$(sed -n 's/^closure_base=//p' "$inner_metadata")
|
||||
guest_ip=$(sed -n 's/^guest_ip=//p' "$inner_metadata")
|
||||
vm_id=$(sed -n 's/^vm_id=//p' "$inner_metadata")
|
||||
vdi_id=$(sed -n 's/^vdi_id=//p' "$inner_metadata")
|
||||
shepherd_pid=$(sed -n 's/^shepherd_pid=//p' "$inner_metadata")
|
||||
sshd_status=$(sed -n 's/^sshd_status=//p' "$inner_metadata")
|
||||
compat_prefix_shims=$(sed -n 's/^compat_prefix_shims=//p' "$inner_metadata")
|
||||
guile_module_smoke=$(sed -n 's/^guile_module_smoke=//p' "$inner_metadata")
|
||||
|
||||
[ "$shepherd_pid" = 1 ] || { echo "shepherd was not PID 1" >&2; exit 1; }
|
||||
[ "$sshd_status" = running ] || { echo "sshd is not running" >&2; exit 1; }
|
||||
[ "$compat_prefix_shims" = absent ] || { echo "compatibility prefix shims reappeared" >&2; exit 1; }
|
||||
[ "$guile_module_smoke" = ok ] || { echo "guest Guile module smoke failed" >&2; exit 1; }
|
||||
|
||||
ssh_guest() {
|
||||
ssh -i "$root_ssh_private_key_file" \
|
||||
-o BatchMode=yes \
|
||||
-o StrictHostKeyChecking=no \
|
||||
-o UserKnownHostsFile=/dev/null \
|
||||
-o ConnectTimeout=5 \
|
||||
root@"$guest_ip" "$@"
|
||||
}
|
||||
|
||||
guest_build_jobs=${GUEST_BUILD_JOBS:-$(ssh_guest 'sysctl -n hw.ncpu')}
|
||||
case "$guest_build_jobs" in
|
||||
''|*[!0-9]*)
|
||||
echo "invalid guest build job count: $guest_build_jobs" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
native_build_metadata=$(ssh_guest env BUILD_JOBS="$guest_build_jobs" sh -s <<'EOF'
|
||||
set -eu
|
||||
[ -L /run/current-development ]
|
||||
[ -L /usr/include ]
|
||||
[ "$(readlink /usr/include)" = "/run/current-system/development-profile/usr/include" ]
|
||||
[ -L /usr/share/mk ]
|
||||
[ "$(readlink /usr/share/mk)" = "/run/current-system/development-profile/usr/share/mk" ]
|
||||
closure=$(readlink /run/current-system)
|
||||
source_store=$(sed -n 's/.*"\(\/frx\/store\/[^\"]*-freebsd-source-[^\"]*\)".*/\1/p' "$closure/metadata/store-layout.scm" | head -n 1)
|
||||
source_root="$source_store/tree"
|
||||
build_root=/var/tmp/fruix-phase20-native-build
|
||||
logdir=$build_root/logs
|
||||
world_stage=$build_root/stage-world
|
||||
kernel_stage=$build_root/stage-kernel
|
||||
headers_stage=$build_root/artifact-headers
|
||||
bootloader_stage=$build_root/artifact-bootloader
|
||||
rm -rf "$build_root"
|
||||
mkdir -p "$logdir"
|
||||
export MAKEOBJDIRPREFIX="$build_root/obj"
|
||||
common='TARGET=amd64 TARGET_ARCH=amd64 KERNCONF=GENERIC __MAKE_CONF=/dev/null SRCCONF=/dev/null SRC_ENV_CONF=/dev/null MK_DEBUG_FILES=no MK_TESTS=no DB_FROM_SRC=yes'
|
||||
make -j"$BUILD_JOBS" -C "$source_root" TARGET=amd64 TARGET_ARCH=amd64 KERNCONF=GENERIC __MAKE_CONF=/dev/null SRCCONF=/dev/null SRC_ENV_CONF=/dev/null MK_DEBUG_FILES=no MK_TESTS=no buildworld > "$logdir/buildworld.log" 2>&1
|
||||
make -j"$BUILD_JOBS" -C "$source_root" TARGET=amd64 TARGET_ARCH=amd64 KERNCONF=GENERIC __MAKE_CONF=/dev/null SRCCONF=/dev/null SRC_ENV_CONF=/dev/null MK_DEBUG_FILES=no MK_TESTS=no buildkernel > "$logdir/buildkernel.log" 2>&1
|
||||
make -C "$source_root" $common DESTDIR="$world_stage" installworld > "$logdir/installworld.log" 2>&1
|
||||
make -C "$source_root" $common DESTDIR="$world_stage" distribution > "$logdir/distribution.log" 2>&1
|
||||
make -C "$source_root" $common DESTDIR="$kernel_stage" installkernel > "$logdir/installkernel.log" 2>&1
|
||||
mkdir -p "$headers_stage/usr" "$bootloader_stage/boot"
|
||||
cp -a "$world_stage/usr/include" "$headers_stage/usr/include"
|
||||
mkdir -p "$headers_stage/usr/share"
|
||||
cp -a "$world_stage/usr/share/mk" "$headers_stage/usr/share/mk"
|
||||
cp -a "$world_stage/boot/loader" "$bootloader_stage/boot/loader"
|
||||
cp -a "$world_stage/boot/loader.efi" "$bootloader_stage/boot/loader.efi"
|
||||
cp -a "$world_stage/boot/device.hints" "$bootloader_stage/boot/device.hints"
|
||||
cp -a "$world_stage/boot/defaults" "$bootloader_stage/boot/defaults"
|
||||
cp -a "$world_stage/boot/lua" "$bootloader_stage/boot/lua"
|
||||
[ -f "$kernel_stage/boot/kernel/kernel" ]
|
||||
[ -f "$headers_stage/usr/include/sys/param.h" ]
|
||||
[ -f "$headers_stage/usr/share/mk/bsd.prog.mk" ]
|
||||
[ -f "$bootloader_stage/boot/loader.efi" ]
|
||||
[ -f "$bootloader_stage/boot/defaults/loader.conf" ]
|
||||
[ -f "$bootloader_stage/boot/lua/loader.lua" ]
|
||||
sha_kernel=$(sha256 -q "$kernel_stage/boot/kernel/kernel")
|
||||
sha_loader=$(sha256 -q "$bootloader_stage/boot/loader.efi")
|
||||
sha_param=$(sha256 -q "$headers_stage/usr/include/sys/param.h")
|
||||
buildworld_tail=$(tail -n 20 "$logdir/buildworld.log" | tr '\n' ' ')
|
||||
buildkernel_tail=$(tail -n 20 "$logdir/buildkernel.log" | tr '\n' ' ')
|
||||
installworld_tail=$(tail -n 20 "$logdir/installworld.log" | tr '\n' ' ')
|
||||
distribution_tail=$(tail -n 20 "$logdir/distribution.log" | tr '\n' ' ')
|
||||
installkernel_tail=$(tail -n 20 "$logdir/installkernel.log" | tr '\n' ' ')
|
||||
root_df=$(df -h / | tail -n 1 | tr -s ' ' | tr '\t' ' ')
|
||||
build_root_size=$(du -sh "$build_root" | awk '{print $1}')
|
||||
world_stage_size=$(du -sh "$world_stage" | awk '{print $1}')
|
||||
kernel_stage_size=$(du -sh "$kernel_stage" | awk '{print $1}')
|
||||
headers_stage_size=$(du -sh "$headers_stage" | awk '{print $1}')
|
||||
bootloader_stage_size=$(du -sh "$bootloader_stage" | awk '{print $1}')
|
||||
printf 'build_jobs=%s\n' "$BUILD_JOBS"
|
||||
printf 'source_store=%s\n' "$source_store"
|
||||
printf 'source_root=%s\n' "$source_root"
|
||||
printf 'build_root=%s\n' "$build_root"
|
||||
printf 'logdir=%s\n' "$logdir"
|
||||
printf 'buildworld_log=%s\n' "$logdir/buildworld.log"
|
||||
printf 'buildkernel_log=%s\n' "$logdir/buildkernel.log"
|
||||
printf 'installworld_log=%s\n' "$logdir/installworld.log"
|
||||
printf 'distribution_log=%s\n' "$logdir/distribution.log"
|
||||
printf 'installkernel_log=%s\n' "$logdir/installkernel.log"
|
||||
printf 'world_stage=%s\n' "$world_stage"
|
||||
printf 'kernel_stage=%s\n' "$kernel_stage"
|
||||
printf 'headers_stage=%s\n' "$headers_stage"
|
||||
printf 'bootloader_stage=%s\n' "$bootloader_stage"
|
||||
printf 'root_df=%s\n' "$root_df"
|
||||
printf 'build_root_size=%s\n' "$build_root_size"
|
||||
printf 'world_stage_size=%s\n' "$world_stage_size"
|
||||
printf 'kernel_stage_size=%s\n' "$kernel_stage_size"
|
||||
printf 'headers_stage_size=%s\n' "$headers_stage_size"
|
||||
printf 'bootloader_stage_size=%s\n' "$bootloader_stage_size"
|
||||
printf 'sha_kernel=%s\n' "$sha_kernel"
|
||||
printf 'sha_loader=%s\n' "$sha_loader"
|
||||
printf 'sha_param=%s\n' "$sha_param"
|
||||
printf 'buildworld_tail=%s\n' "$buildworld_tail"
|
||||
printf 'buildkernel_tail=%s\n' "$buildkernel_tail"
|
||||
printf 'installworld_tail=%s\n' "$installworld_tail"
|
||||
printf 'distribution_tail=%s\n' "$distribution_tail"
|
||||
printf 'installkernel_tail=%s\n' "$installkernel_tail"
|
||||
EOF
|
||||
)
|
||||
|
||||
build_jobs=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^build_jobs=//p')
|
||||
source_store=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^source_store=//p')
|
||||
source_root=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^source_root=//p')
|
||||
build_root=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^build_root=//p')
|
||||
logdir=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^logdir=//p')
|
||||
buildworld_log=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^buildworld_log=//p')
|
||||
buildkernel_log=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^buildkernel_log=//p')
|
||||
installworld_log=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^installworld_log=//p')
|
||||
distribution_log=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^distribution_log=//p')
|
||||
installkernel_log=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^installkernel_log=//p')
|
||||
world_stage=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^world_stage=//p')
|
||||
kernel_stage=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^kernel_stage=//p')
|
||||
headers_stage=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^headers_stage=//p')
|
||||
bootloader_stage=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^bootloader_stage=//p')
|
||||
root_df=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^root_df=//p')
|
||||
build_root_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^build_root_size=//p')
|
||||
world_stage_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^world_stage_size=//p')
|
||||
kernel_stage_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^kernel_stage_size=//p')
|
||||
headers_stage_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^headers_stage_size=//p')
|
||||
bootloader_stage_size=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^bootloader_stage_size=//p')
|
||||
sha_kernel=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^sha_kernel=//p')
|
||||
sha_loader=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^sha_loader=//p')
|
||||
sha_param=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^sha_param=//p')
|
||||
buildworld_tail=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^buildworld_tail=//p')
|
||||
buildkernel_tail=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^buildkernel_tail=//p')
|
||||
installworld_tail=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^installworld_tail=//p')
|
||||
distribution_tail=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^distribution_tail=//p')
|
||||
installkernel_tail=$(printf '%s\n' "$native_build_metadata" | sed -n 's/^installkernel_tail=//p')
|
||||
|
||||
case "$source_store" in
|
||||
/frx/store/*-freebsd-source-*) : ;;
|
||||
*) echo "unexpected source store path: $source_store" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$source_root" in
|
||||
/frx/store/*-freebsd-source-*/*) : ;;
|
||||
*) echo "unexpected source root path: $source_root" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$build_root" in
|
||||
/var/tmp/fruix-phase20-native-build) : ;;
|
||||
*) echo "unexpected build root: $build_root" >&2; exit 1 ;;
|
||||
esac
|
||||
printf '%s\n' "$sha_kernel" | grep -E '^[0-9a-f]{64}$' >/dev/null || {
|
||||
echo "invalid kernel sha256: $sha_kernel" >&2
|
||||
exit 1
|
||||
}
|
||||
printf '%s\n' "$sha_loader" | grep -E '^[0-9a-f]{64}$' >/dev/null || {
|
||||
echo "invalid loader sha256: $sha_loader" >&2
|
||||
exit 1
|
||||
}
|
||||
printf '%s\n' "$sha_param" | grep -E '^[0-9a-f]{64}$' >/dev/null || {
|
||||
echo "invalid param.h sha256: $sha_param" >&2
|
||||
exit 1
|
||||
}
|
||||
case "$buildworld_tail" in
|
||||
*'World build completed on'*) : ;;
|
||||
*) echo "buildworld log does not show completion" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$buildkernel_tail" in
|
||||
*'Kernel(s) GENERIC built in'*) : ;;
|
||||
*) echo "buildkernel log does not show successful kernel build" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
cat >"$metadata_file" <<EOF
|
||||
workdir=$workdir
|
||||
inner_metadata=$inner_metadata
|
||||
phase8_metadata=$phase8_metadata
|
||||
closure_path=$closure_path
|
||||
closure_base=$closure_base
|
||||
vm_id=$vm_id
|
||||
vdi_id=$vdi_id
|
||||
guest_ip=$guest_ip
|
||||
root_size=$root_size
|
||||
build_jobs=$build_jobs
|
||||
source_store=$source_store
|
||||
source_root=$source_root
|
||||
build_root=$build_root
|
||||
logdir=$logdir
|
||||
buildworld_log=$buildworld_log
|
||||
buildkernel_log=$buildkernel_log
|
||||
installworld_log=$installworld_log
|
||||
distribution_log=$distribution_log
|
||||
installkernel_log=$installkernel_log
|
||||
world_stage=$world_stage
|
||||
kernel_stage=$kernel_stage
|
||||
headers_stage=$headers_stage
|
||||
bootloader_stage=$bootloader_stage
|
||||
root_df=$root_df
|
||||
build_root_size=$build_root_size
|
||||
world_stage_size=$world_stage_size
|
||||
kernel_stage_size=$kernel_stage_size
|
||||
headers_stage_size=$headers_stage_size
|
||||
bootloader_stage_size=$bootloader_stage_size
|
||||
sha_kernel=$sha_kernel
|
||||
sha_loader=$sha_loader
|
||||
sha_param=$sha_param
|
||||
buildworld_tail=$buildworld_tail
|
||||
buildkernel_tail=$buildkernel_tail
|
||||
installworld_tail=$installworld_tail
|
||||
distribution_tail=$distribution_tail
|
||||
installkernel_tail=$installkernel_tail
|
||||
boot_backend=xcp-ng-xo-cli
|
||||
init_mode=shepherd-pid1
|
||||
host_initiated_native_build=ok
|
||||
EOF
|
||||
|
||||
if [ -n "$metadata_target" ]; then
|
||||
mkdir -p "$(dirname "$metadata_target")"
|
||||
cp "$metadata_file" "$metadata_target"
|
||||
fi
|
||||
|
||||
printf 'PASS phase20-host-initiated-native-build-xcpng\n'
|
||||
printf 'Work directory: %s\n' "$workdir"
|
||||
printf 'Metadata file: %s\n' "$metadata_file"
|
||||
if [ -n "$metadata_target" ]; then
|
||||
printf 'Copied metadata to: %s\n' "$metadata_target"
|
||||
fi
|
||||
printf '%s\n' '--- metadata ---'
|
||||
cat "$metadata_file"
|
||||
Reference in New Issue
Block a user