diff --git a/Dockerfile b/Dockerfile index c534f26..65eca13 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1 FROM scratch AS runner -COPY --from=qemux/qemu:7.37 / / +COPY --from=qemux/qemu:7.39 / / ARG VERSION_ARG="0.0" ARG DEBCONF_NOWARNINGS="yes" @@ -27,14 +27,7 @@ RUN <<'EOF' set -eu sed -i \ - -e 's|websocket=$WSS_PORT -vga|websocket=$WSS_PORT${LOSSY_OPT:-} -vga|' \ - -e 's|"-display vnc=:$port -vga $VGA"|"-display vnc=:$port${LOSSY_OPT:-} -vga $VGA"|' \ - -e 's| -vnc :$port,websocket=$WSS_PORT"| -vnc :$port,websocket=$WSS_PORT${LOSSY_OPT:-}"|' \ - -e 's| -vnc :$port"| -vnc :$port${LOSSY_OPT:-}"|' \ - /run/display.sh - - sed -i \ - 's|if ! enabled "$GPU" || isAmdCpu || \[\[ "$ARCH" != "amd64" \]\]; then|if ! enabled "$GPU" || [[ "$ARCH" != "amd64" ]]; then|' \ + 's@if ! enabled "$GPU" || isAmdCpu || \[\[ "$ARCH" != "amd64" \]\]; then@if ! enabled "$GPU" || [[ "$ARCH" != "amd64" ]]; then@' \ /run/display.sh sed -i \ @@ -45,11 +38,6 @@ RUN <<'EOF' 's@USB_OPTS="-device $USB"@& \&\& { [[ "${TABLET:-Y}" =~ ^[Yy] ]] \&\& USB_OPTS+=" -device usb-tablet" || USB_OPTS+=" -device usb-mouse"; }@' \ /run/config.sh - [ "$(grep -c 'LOSSY_OPT' /run/display.sh)" -ge 4 ] || { - echo "patch failed: expected 4 LOSSY_OPT sites in display.sh" >&2 - exit 1 - } - grep -q 'usb-mouse' /run/config.sh || { echo "patch failed: TABLET conditional not injected into config.sh" >&2 exit 1 @@ -59,6 +47,8 @@ RUN <<'EOF' echo "patch failed: AMD GPU gate not removed from display.sh" >&2 exit 1 } + + bash -n /run/display.sh /run/config.sh EOF VOLUME /storage diff --git a/kubernetes.yml b/kubernetes.yml index a4dedb4..27f3cc3 100644 --- a/kubernetes.yml +++ b/kubernetes.yml @@ -18,6 +18,8 @@ metadata: name: chromeos spec: replicas: 1 + strategy: + type: Recreate selector: matchLabels: app: chromeos diff --git a/src/entry.sh b/src/entry.sh index 8865cbd..f83ef02 100644 --- a/src/entry.sh +++ b/src/entry.sh @@ -5,8 +5,9 @@ set -Eeuo pipefail : "${SUPPORT:="https://github.com/forkymcforkface/chromeos"}" : "${AUDIO:="N"}" +: "${LOSSY:="N"}" : "${SHUTDOWN:="Y"}" -: "${TIMEOUT:="115"}" +: "${TIMEOUT:="105"}" : "${PLATFORM:="x64"}" : "${BOOT_MODE:="uefi"}" @@ -44,7 +45,7 @@ if ! interactive; then "${cmd[@]}" ${ARGS:+ $ARGS} & else startConsole - setsid -w "${cmd[@]}" ${ARGS:+ $ARGS} /dev/null | awk -F'[ =,]+' '/EFI-SYSTEM/ {for(i=1;i<=NF;i++) if($i=="start") print $(i+1)}') + efi_start=$(sfdisk -d "$DATA_IMG" 2>/dev/null | + awk -F'[ =,]+' '/EFI-SYSTEM/ {for(i=1;i<=NF;i++) if($i=="start") print $(i+1)}') + if [ -n "$efi_start" ]; then efi_off=$((efi_start * 512)) tmp=$(mktemp) + mtype -i "$DATA_IMG@@$efi_off" ::/syslinux/default.cfg > "$tmp" 2>/dev/null + if [ -s "$tmp" ]; then if [[ "${DEV_MODE:-}" =~ ^[Yy] ]] && grep -q 'chromeos-vhd' "$tmp"; then sed -i 's|chromeos-vhd|chromeos-hd|g' "$tmp" + mcopy -o -i "$DATA_IMG@@$efi_off" "$tmp" ::/syslinux/default.cfg 2>/dev/null && \ info "DEV_MODE=Y: switched boot default to chromeos-hd.A" + elif [[ "${DEV_MODE:-}" =~ ^[Nn] ]] && grep -q 'chromeos-hd' "$tmp"; then sed -i 's|chromeos-hd|chromeos-vhd|g' "$tmp" + mcopy -o -i "$DATA_IMG@@$efi_off" "$tmp" ::/syslinux/default.cfg 2>/dev/null && \ info "DEV_MODE=N: switched boot default to chromeos-vhd.A" fi fi + rm -f "$tmp" fi + set -e fi info "Booting ChromeOS Flex from data disk." + BOOT="none" STORAGE="$FLEX_DIR" + return 0 fi @@ -86,10 +99,12 @@ fi if [ -f "/boot.img" ] && [ -s "/boot.img" ]; then info "Using custom ChromeOS image from /boot.img" + BOOT="/boot.img" STORAGE="$FLEX_DIR" BOOT_MODE="uefi" BOOT_DESC=" ChromeOS Flex (custom)" + return 0 fi @@ -99,54 +114,82 @@ fi if [ -f "$FLEX_DIR/boot.img" ] && [ -s "$FLEX_DIR/boot.img" ]; then info "Reusing existing installer at $FLEX_DIR/boot.img" + BOOT="$FLEX_DIR/boot.img" STORAGE="$FLEX_DIR" BOOT_MODE="uefi" + return 0 fi +downloadFile() { + + local url="$1" + local dest="$2" + local message="$3" + local expected="${4:-0}" + local connections="${5:-1}" + + downloadToFile \ + "$url" \ + "$dest" \ + "$message" \ + "$expected" \ + "$connections" \ + "Y" +} + +downloadImage() { + + local url="$1" + local dest="$2" + local base="$3" + local version="$4" + local expected="${5:-0}" + local connections="${CONNECTIONS:-1}" + local msg="Downloading ChromeOS Flex $version" + + info "Downloading $base..." + + downloadRetry \ + "$dest" \ + "$connections" \ + "5" \ + "$base" \ + "100000000" \ + "$url" \ + "$dest" \ + "$msg" \ + "$expected" || return $? + + return 0 +} + zipsize="0" if [ -n "$VERSION_FILTER" ]; then info "Fetching ChromeOS Flex manifest ($VERSION_LC channel)..." - html "Fetching manifest..." - rc=0 - reason="" - log=$(mktemp) manifest="$FLEX_DIR/manifest.json" - rm -f "$manifest" + rm -f -- "$manifest" "$manifest.aria2" - { - LC_ALL=C wget "$MANIFEST_URL" -O "$manifest" --no-verbose --timeout=30 \ - --no-http-keep-alive --output-file="$log" - rc=$? - } || : + if ! downloadToFile \ + "$MANIFEST_URL" \ + "$manifest" \ + "Fetching ChromeOS Flex manifest" \ + "0" \ + "1" \ + "N"; then - if (( rc != 0 )); then - reason=$(sed -n \ - -e 's/^wget: //p' \ - -e 's/^[0-9-]\{10\} [0-9:]\{8\} ERROR //p' \ - "$log" | tail -n 1) - fi - - rm -f "$log" - - if (( rc == 3 )); then - error "Failed to download $MANIFEST_URL because the file could not be written (disk full?)." - exit 60 - elif (( rc != 0 )); then - if [ -n "$reason" ]; then - error "Failed to download $MANIFEST_URL: ${reason%.}." - else - error "Failed to download $MANIFEST_URL with exit status $rc." - fi + rm -f -- "$manifest" "$manifest.aria2" exit 60 fi if [ ! -s "$manifest" ]; then - error "Manifest is empty!" && exit 60 + rm -f -- "$manifest" "$manifest.aria2" + error "Manifest is empty!" + exit 60 fi url=$(jq -r --arg c "$VERSION_FILTER" ' @@ -180,110 +223,63 @@ fi base="$(basename "${url%%\?*}")" zip_dest="$FLEX_DIR/$base" -progress=() -output="" - -# Use Wget's progress bar in a terminal and progress.sh in container logs. -if [ -t 1 ]; then - progress=( --show-progress --progress=bar:noscroll ) -else - output="log" -fi - -msg="Downloading ChromeOS Flex $version" -html "$msg..." - -rc=0 -reason="" -log=$(mktemp) - -info "Downloading $base..." - -rm -f "$zip_dest" -/run/progress.sh "$zip_dest" "${zipsize:-0}" "$msg ([P])..." "$output" & - -{ - LC_ALL=C wget "$url" -O "$zip_dest" --continue --no-verbose --timeout=30 \ - --no-http-keep-alive "${progress[@]}" \ - --output-file="$log" - rc=$? -} || : - -fKill "progress.sh" - -if (( rc != 0 )); then - reason=$(sed -n \ - -e 's/^wget: //p' \ - -e 's/^[0-9-]\{10\} [0-9:]\{8\} ERROR //p' \ - "$log" | tail -n 1) -fi - -rm -f "$log" - -if (( rc == 3 )); then - error "Failed to download $url because the file could not be written (disk full?)." - exit 60 -elif (( rc != 0 )); then - if [ -n "$reason" ]; then - error "Failed to download $url: ${reason%.}." - else - error "Failed to download $url with exit status $rc." - fi - exit 60 -fi - -if [ ! -s "$zip_dest" ]; then - error "Failed to download $url: the downloaded file is empty." +if ! downloadImage \ + "$url" \ + "$zip_dest" \ + "$base" \ + "$version" \ + "${zipsize:-0}"; then exit 60 fi -# Catch silent truncation: a valid Flex recovery zip is always >1GB; <100MB means CDN error page or partial download. -if ! actual_size=$(stat -c%s "$zip_dest"); then - error "Failed to determine downloaded file size: $zip_dest" - exit 60 -fi - -if [ "$actual_size" -lt 100000000 ]; then - error "Downloaded file is suspiciously small ($actual_size bytes)" - exit 60 -fi - -html "Download finished successfully..." - info "Extracting $base..." html "Extracting image..." tmp="$FLEX_DIR/extract" + rm -rf "$tmp" mkdir -p "$tmp" extract_size=$(7z l -slt "$zip_dest" 2>/dev/null | awk -F' = ' '/^Size = [0-9]+$/ && $2 > max { max = $2 } END { print max + 0 }') -/run/progress.sh "$tmp" "${extract_size:-0}" "Extracting image ([P])..." & +/run/progress.sh \ + "$tmp" \ + "${extract_size:-0}" \ + "Extracting image ([P])..." & rc=0 -{ 7z x -y "$zip_dest" -o"$tmp" > /dev/null; rc=$?; } || : + +{ + 7z x -y "$zip_dest" -o"$tmp" > /dev/null + rc=$? +} || : fKill "progress.sh" if (( rc != 0 )); then rm -rf "$tmp" - error "Failed to extract $base" && exit 32 + + error "Failed to extract $base" + exit 32 fi img=$(find "$tmp" -type f -iname "*.bin" -print -quit) if [ ! -s "$img" ]; then rm -rf "$tmp" - error "Could not find ChromeOS Flex image in archive" && exit 32 + + error "Could not find ChromeOS Flex image in archive" + exit 32 fi mv "$img" "$FLEX_DIR/boot.img" + rm -rf "$tmp" rm -f "$zip_dest" -setOwner "$FLEX_DIR/boot.img" || warn "failed to set owner on installer image" +setOwner "$FLEX_DIR/boot.img" || + warn "failed to set owner on installer image" BOOT_MODE="uefi" BOOT="$FLEX_DIR/boot.img" @@ -291,4 +287,5 @@ STORAGE="$FLEX_DIR" BOOT_DESC=" ChromeOS Flex $version" info "ChromeOS Flex installer ready at $BOOT" + return 0