245 lines
10 KiB
Bash
Executable File
245 lines
10 KiB
Bash
Executable File
#!/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-self-hosted-native-build-xcpng.XXXXXX)
|
|
cleanup=1
|
|
fi
|
|
if [ "${KEEP_WORKDIR:-0}" -eq 1 ]; then
|
|
cleanup=0
|
|
fi
|
|
|
|
inner_metadata=$workdir/phase20-self-hosted-inner-metadata.txt
|
|
metadata_file=$workdir/phase20-self-hosted-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
|
|
|
|
ssh_guest '[ -x /usr/local/bin/fruix-self-hosted-native-build ]'
|
|
ssh_guest '[ -L /usr/include ]'
|
|
ssh_guest '[ -L /usr/share/mk ]'
|
|
|
|
self_hosted_metadata=$(ssh_guest env FRUIX_SELF_HOSTED_NATIVE_BUILD_JOBS="$guest_build_jobs" /usr/local/bin/fruix-self-hosted-native-build)
|
|
|
|
run_id=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^run_id=//p')
|
|
helper_version=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^helper_version=//p')
|
|
source_store=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^source_store=//p')
|
|
source_root=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^source_root=//p')
|
|
build_jobs=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^build_jobs=//p')
|
|
build_common=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^build_common=//p')
|
|
install_common=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^install_common=//p')
|
|
build_root=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^build_root=//p')
|
|
result_root=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^result_root=//p')
|
|
logdir=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^logdir=//p')
|
|
status_file=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^status_file=//p')
|
|
guest_metadata_file=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^metadata_file=//p')
|
|
world_stage=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^world_stage=//p')
|
|
kernel_stage=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^kernel_stage=//p')
|
|
kernel_artifact=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^kernel_artifact=//p')
|
|
headers_artifact=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^headers_artifact=//p')
|
|
bootloader_artifact=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^bootloader_artifact=//p')
|
|
latest_link=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^latest_link=//p')
|
|
root_df=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^root_df=//p')
|
|
build_root_size=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^build_root_size=//p')
|
|
result_root_size=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^result_root_size=//p')
|
|
kernel_artifact_size=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^kernel_artifact_size=//p')
|
|
headers_artifact_size=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^headers_artifact_size=//p')
|
|
bootloader_artifact_size=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^bootloader_artifact_size=//p')
|
|
sha_kernel=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^sha_kernel=//p')
|
|
sha_loader=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^sha_loader=//p')
|
|
sha_param=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^sha_param=//p')
|
|
buildworld_tail=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^buildworld_tail=//p')
|
|
buildkernel_tail=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^buildkernel_tail=//p')
|
|
installworld_tail=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^installworld_tail=//p')
|
|
distribution_tail=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^distribution_tail=//p')
|
|
installkernel_tail=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^installkernel_tail=//p')
|
|
self_hosted_native_build=$(printf '%s\n' "$self_hosted_metadata" | sed -n 's/^self_hosted_native_build=//p')
|
|
|
|
status_value=$(ssh_guest "cat '$status_file'")
|
|
latest_target=$(ssh_guest "readlink '$latest_link'")
|
|
|
|
[ "$helper_version" = 2 ] || { echo "unexpected helper version: $helper_version" >&2; exit 1; }
|
|
[ "$build_jobs" = "$guest_build_jobs" ] || { echo "unexpected build job count: $build_jobs" >&2; exit 1; }
|
|
[ "$status_value" = ok ] || { echo "self-hosted build status is not ok: $status_value" >&2; exit 1; }
|
|
[ "$latest_target" = "$result_root" ] || { echo "latest link target mismatch: $latest_target" >&2; exit 1; }
|
|
[ "$self_hosted_native_build" = ok ] || { echo "self-hosted build marker missing" >&2; exit 1; }
|
|
|
|
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-self-hosted-native-builds/*) : ;;
|
|
*) echo "unexpected build root: $build_root" >&2; exit 1 ;;
|
|
esac
|
|
case "$result_root" in
|
|
/var/lib/fruix/native-builds/*) : ;;
|
|
*) echo "unexpected result root: $result_root" >&2; exit 1 ;;
|
|
esac
|
|
case "$latest_link" in
|
|
/var/lib/fruix/native-builds/latest) : ;;
|
|
*) echo "unexpected latest link path: $latest_link" >&2; exit 1 ;;
|
|
esac
|
|
printf '%s\n' "$run_id" | grep -E '^[0-9]{8}T[0-9]{6}Z$' >/dev/null || {
|
|
echo "unexpected run id: $run_id" >&2
|
|
exit 1
|
|
}
|
|
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
|
|
case "$installworld_tail" in
|
|
*'Install world completed in'*) : ;;
|
|
*) echo "installworld log does not show successful completion" >&2; exit 1 ;;
|
|
esac
|
|
case "$installkernel_tail" in
|
|
*'Install kernel(s) GENERIC completed in'*) : ;;
|
|
*) echo "installkernel log does not show successful completion" >&2; exit 1 ;;
|
|
esac
|
|
printf '%s\n' "$build_common" | grep -F 'TARGET=amd64 TARGET_ARCH=amd64 KERNCONF=GENERIC' >/dev/null || {
|
|
echo "unexpected build_common flags: $build_common" >&2
|
|
exit 1
|
|
}
|
|
printf '%s\n' "$install_common" | grep -F 'DB_FROM_SRC=yes' >/dev/null || {
|
|
echo "install_common is missing DB_FROM_SRC=yes" >&2
|
|
exit 1
|
|
}
|
|
|
|
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
|
|
run_id=$run_id
|
|
helper_version=$helper_version
|
|
build_jobs=$build_jobs
|
|
source_store=$source_store
|
|
source_root=$source_root
|
|
build_common=$build_common
|
|
install_common=$install_common
|
|
build_root=$build_root
|
|
result_root=$result_root
|
|
logdir=$logdir
|
|
status_file=$status_file
|
|
guest_metadata_file=$guest_metadata_file
|
|
world_stage=$world_stage
|
|
kernel_stage=$kernel_stage
|
|
kernel_artifact=$kernel_artifact
|
|
headers_artifact=$headers_artifact
|
|
bootloader_artifact=$bootloader_artifact
|
|
latest_link=$latest_link
|
|
latest_target=$latest_target
|
|
status_value=$status_value
|
|
root_df=$root_df
|
|
build_root_size=$build_root_size
|
|
result_root_size=$result_root_size
|
|
kernel_artifact_size=$kernel_artifact_size
|
|
headers_artifact_size=$headers_artifact_size
|
|
bootloader_artifact_size=$bootloader_artifact_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
|
|
self_hosted_native_build=ok
|
|
EOF
|
|
|
|
if [ -n "$metadata_target" ]; then
|
|
mkdir -p "$(dirname "$metadata_target")"
|
|
cp "$metadata_file" "$metadata_target"
|
|
fi
|
|
|
|
printf 'PASS phase20-self-hosted-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"
|