Files
zosbuilder/scripts/dev-container.sh
Jan De Landtsheer 334821dacf Integrate zosstorage build path and runtime orchestration
Summary:

* add openssh-client to the builder image and mount host SSH keys into the dev container when available

* switch RFS to git builds, register the zosstorage source, and document the extra Rust component

* wire zosstorage into the build: add build_zosstorage(), ship the binary in the initramfs, and extend component validation

* refresh kernel configuration to 6.12.49 while dropping Xen guest selections and enabling counted-by support

* tighten runtime configs: use cached mycelium key path, add zosstorage zinit unit, bootstrap ovsdb-server, and enable openvswitch module

* adjust the network health check ping invocation and fix the RFS pack-tree --debug flag order

* update NOTES changelog, README component list, and introduce a runit helper for qemu/cloud-hypervisor testing

* add ovsdb init script wiring under config/zinit/init and ensure zosstorage is available before mycelium
2025-10-14 17:47:13 +02:00

266 lines
8.1 KiB
Bash
Executable File

#!/bin/bash
# Efficient development container workflow - persistent container for debugging
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
# Container configuration
CONTAINER_NAME="zero-os-dev"
BUILDER_IMAGE="zero-os-builder:latest"
HOST_SSH_DIR="${SSH_MOUNT_DIR:-${HOME}/.ssh}"
# Default to verbose, streaming logs for dev flows unless explicitly disabled
export DEBUG="${DEBUG:-1}"
# Source common functions
source "${SCRIPT_DIR}/lib/common.sh"
function show_usage() {
cat << EOF
Zero OS Development Container Manager
Usage: $0 [COMMAND]
Commands:
start Start persistent development container
stop Stop development container
shell Enter development container shell
build Run build in persistent container
clean Clean and restart container
status Show container status
logs Show container logs
Environment Variables:
DEBUG Enable debug output (default: 1 for dev)
Examples:
$0 start # Start persistent container
$0 shell # Enter container for debugging
$0 build # Run build in persistent container
EOF
}
function ensure_builder_image() {
section_header "Ensuring Builder Image"
# Check for existing image under common tags (short and localhost-qualified)
local candidates=("$BUILDER_IMAGE" "localhost/${BUILDER_IMAGE}")
for img in "${candidates[@]}"; do
if podman image exists "$img" 2>/dev/null; then
log_info "Found builder image: ${img}"
BUILDER_IMAGE="$img"
return 0
fi
done
log_warn "Builder image not found locally; building: ${BUILDER_IMAGE}"
safe_execute podman build -t "${BUILDER_IMAGE}" -f "${PROJECT_ROOT}/Dockerfile" "${PROJECT_ROOT}"
if podman image exists "$BUILDER_IMAGE" 2>/dev/null; then
log_info "Builder image built successfully: ${BUILDER_IMAGE}"
return 0
fi
# As a fallback, also tag with localhost to satisfy Podman short-name policy
local local_tag="localhost/${BUILDER_IMAGE}"
log_info "Tagging builder image as ${local_tag}"
safe_execute podman tag "${BUILDER_IMAGE}" "${local_tag}" || true
if podman image exists "$local_tag" 2>/dev/null; then
BUILDER_IMAGE="$local_tag"
fi
}
function dev_container_start() {
section_header "Starting Development Container"
# Ensure builder image exists (handles clean --all case and short-name policy)
ensure_builder_image
# Check if container already exists
if podman container exists "$CONTAINER_NAME" 2>/dev/null; then
if podman container inspect "$CONTAINER_NAME" --format '{{.State.Status}}' | grep -q "running"; then
log_info "Development container already running"
return 0
else
log_info "Starting existing development container"
safe_execute podman start "$CONTAINER_NAME"
return 0
fi
fi
log_info "Creating new development container: ${CONTAINER_NAME}"
# Create persistent container with all necessary mounts and environment
local podman_args=(
run -d
--name "$CONTAINER_NAME"
--privileged
-v "${PROJECT_ROOT}:/workspace"
-w /workspace
-e DEBUG=1
-e ALPINE_VERSION=3.22
-e KERNEL_VERSION=6.12.44
-e RUST_TARGET=x86_64-unknown-linux-musl
-e OPTIMIZATION_LEVEL=max
)
if [[ -d "$HOST_SSH_DIR" ]]; then
log_info "Mounting SSH directory: ${HOST_SSH_DIR} -> /root/.ssh (read-only)"
podman_args+=(-v "${HOST_SSH_DIR}:/root/.ssh:ro")
else
log_warn "SSH directory not found at ${HOST_SSH_DIR}; skipping SSH mount"
fi
podman_args+=(
"$BUILDER_IMAGE"
sleep infinity
)
safe_execute podman "${podman_args[@]}"
log_info "Development container started successfully"
log_info "Container name: ${CONTAINER_NAME}"
log_info "Access with: $0 shell"
}
function dev_container_stop() {
section_header "Stopping Development Container"
if podman container exists "$CONTAINER_NAME" 2>/dev/null; then
log_info "Stopping development container: ${CONTAINER_NAME}"
safe_execute podman stop "$CONTAINER_NAME"
log_info "Development container stopped"
else
log_info "Development container not found"
fi
}
function dev_container_shell() {
section_header "Entering Development Container Shell"
if ! podman container exists "$CONTAINER_NAME" 2>/dev/null; then
log_info "Development container not found, starting..."
dev_container_start
fi
if ! podman container inspect "$CONTAINER_NAME" --format '{{.State.Status}}' | grep -q "running"; then
log_info "Starting stopped development container"
safe_execute podman start "$CONTAINER_NAME"
fi
log_info "Entering container shell (exit with 'exit' or Ctrl+D)"
# Use direct execution for interactive shell (don't use safe_execute)
exec podman exec -it "$CONTAINER_NAME" /bin/bash
}
function dev_container_build() {
section_header "Running Build in Development Container"
if ! podman container exists "$CONTAINER_NAME" 2>/dev/null; then
log_info "Development container not found, starting..."
dev_container_start
fi
if ! podman container inspect "$CONTAINER_NAME" --format '{{.State.Status}}' | grep -q "running"; then
log_info "Starting stopped development container"
safe_execute podman start "$CONTAINER_NAME"
fi
log_info "Running build in persistent container (real-time output)"
log_info "Command: podman exec $CONTAINER_NAME ./scripts/build.sh $*"
# Use direct execution to show real-time output (bypass safe_execute)
podman exec "$CONTAINER_NAME" ./scripts/build.sh "$@"
local exit_code=$?
if [[ $exit_code -eq 0 ]]; then
log_info "Build completed successfully in container"
else
log_error "Build failed in container with exit code: $exit_code"
fi
return $exit_code
}
function dev_container_clean() {
section_header "Cleaning Development Container"
if podman container exists "$CONTAINER_NAME" 2>/dev/null; then
log_info "Removing existing development container"
safe_execute podman rm -f "$CONTAINER_NAME"
fi
log_info "Starting fresh development container"
dev_container_start
}
function dev_container_status() {
section_header "Development Container Status"
if podman container exists "$CONTAINER_NAME" 2>/dev/null; then
local status=$(podman container inspect "$CONTAINER_NAME" --format '{{.State.Status}}')
local created=$(podman container inspect "$CONTAINER_NAME" --format '{{.Created}}')
log_info "Container: ${CONTAINER_NAME}"
log_info "Status: ${status}"
log_info "Created: ${created}"
if [[ "$status" == "running" ]]; then
log_info "✓ Ready for development"
else
log_info "⚠ Container stopped - use '$0 start' to start"
fi
else
log_info "Development container not found"
log_info "Use '$0 start' to create"
fi
}
function dev_container_logs() {
section_header "Development Container Logs"
if podman container exists "$CONTAINER_NAME" 2>/dev/null; then
safe_execute podman logs "$CONTAINER_NAME"
else
log_error "Development container not found"
return 1
fi
}
# Main function
function main() {
local command="${1:-help}"
case "$command" in
start)
dev_container_start
;;
stop)
dev_container_stop
;;
shell)
dev_container_shell
;;
build)
shift
dev_container_build "$@"
;;
clean)
dev_container_clean
;;
status)
dev_container_status
;;
logs)
dev_container_logs
;;
help|--help|-h)
show_usage
;;
*)
log_error "Unknown command: $command"
show_usage
exit 1
;;
esac
}
main "$@"