pixie-lab 0.4.1__tar.gz → 0.4.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/.github/workflows/cicd.yaml +78 -2
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/CHANGELOG.md +27 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/Makefile +12 -1
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/PKG-INFO +1 -1
- pixie_lab-0.4.2/cijoe/configs/live-env-image.toml +34 -0
- pixie_lab-0.4.2/cijoe/scripts/live_env_image.py +307 -0
- pixie_lab-0.4.2/cijoe/scripts/live_env_transform.sh +293 -0
- pixie_lab-0.4.2/cijoe/tasks/live-env-image.yaml +35 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pyproject.toml +1 -1
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/_partition.py +93 -9
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/catalog/_fetcher.py +15 -4
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/catalog/catalog.toml +24 -0
- pixie_lab-0.4.2/src/pixie/oras_pull.py +85 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/pxe/_renderer.py +127 -59
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/pxe/_routes.py +14 -1
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_settings_store.py +40 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/live_env.html +36 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/main.py +59 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_catalog_seed.py +5 -3
- pixie_lab-0.4.2/tests/test_oras_pull.py +89 -0
- pixie_lab-0.4.2/tests/test_partition_select.py +107 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_pxe_plan_json.py +126 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_settings.py +55 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/uv.lock +1 -1
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/.dockerignore +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/.github/workflows/docs.yml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/.gitignore +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/Containerfile +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/LICENSE +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/PLAN.md +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/README.md +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/configs/netboot-pc.toml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/configs/test-pxe-flash-always.toml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/configs/test-pxe-flash.toml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/configs/test-pxe-inventory.toml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/configs/test-pxe-nbdboot.toml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/configs/test-pxe-tui.toml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/configs/test-pxe.toml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/configs/test-usb-ventoy.toml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/configs/usbboot-pc.toml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/scripts/live_build.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/scripts/pixie_ipxe_build.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/scripts/pixie_wheel_stage.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/scripts/pxe_flash_stage.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/scripts/pxe_inventory_stage.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/scripts/pxe_prepare.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/scripts/pxe_run_chain_test.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/scripts/usb_iso_build.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/scripts/usb_iso_verify.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/scripts/usb_ventoy_guest_start.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/scripts/usb_ventoy_stage.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/tasks/netboot-pc.yaml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/tasks/test-pxe-flash-always.yaml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/tasks/test-pxe-flash.yaml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/tasks/test-pxe-inventory.yaml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/tasks/test-pxe-nbdboot.yaml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/tasks/test-pxe-tui.yaml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/tasks/test-pxe.yaml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/tasks/test-usb-ventoy.yaml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/cijoe/tasks/usbboot-pc.yaml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/docs/audit.md +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/docs/src/boot-modes.md +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/docs/src/conf.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/docs/src/deployment.md +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/docs/src/hardware-quirks.md +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/docs/src/index.md +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/docs/src/quickstart.md +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/docs/tooling/README.md +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/docs/tooling/pyproject.toml +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/docs/tooling/src/pixie_docs/__init__.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/docs/tooling/src/pixie_docs/cli.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/README.md +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/auxiliary/cloudinit-metadata.meta +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/auxiliary/ipxe-embed.ipxe +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/auxiliary/ipxe-local-general.h +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/auto/config +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/archives/backports.list.binary +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/archives/backports.list.chroot +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/bootloaders/grub-efi/splash.png +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/bootloaders/syslinux/splash.png +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/hooks/normal/0500-pixie-install.hook.chroot +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/hooks/normal/0500-pixie-skip-bootloader-menu.hook.binary +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/hooks/normal/0600-pixie-r8125-dkms.hook.chroot +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/hooks/normal/0700-pixie-clock-from-http.hook.chroot +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/hooks/normal/0800-pixie-ssh-live.hook.chroot +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/hooks/normal/0900-pixie-enable-services.hook.chroot +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/hooks/normal/0980-pixie-apt-validate.hook.chroot +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/initramfs-tools/conf.d/pixie-modules-most +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/issue +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/modprobe.d/zz-pixie-blacklist-nouveau.conf +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/motd +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/profile.d/pixie-version.sh +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/getty@.service.d/zzz-pixie-autologin-root.conf +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/pixie-banner-early.service +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/pixie-banner-late.service +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/pixie-banner-mid.service +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/pixie-clock-from-http.service +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/pixie-images-discover.service +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/pixie-on-tty1.service +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/pixie-usb-grow.service +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/var-lib-pixie-images.mount +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/etc/udev/rules.d/70-pixie-realtek-2g5-offloads.rules +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/usr/lib/systemd/system-generators/pixie-skip-usb-only-units-on-netboot +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/usr/local/sbin/pixie-boot-banner +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/usr/local/sbin/pixie-clock-from-http +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/usr/local/sbin/pixie-images-discover +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/usr/local/sbin/pixie-on-tty1 +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/usr/local/sbin/pixie-trace +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/includes.chroot/usr/local/sbin/pixie-usb-grow +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/package-lists/pixie-base.list.chroot +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/package-lists/pixie-flash.list.chroot +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/preferences/backports.pref.binary +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/pixie-media/live-build/config/preferences/backports.pref.chroot +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/__init__.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/_util.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/catalog/__init__.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/catalog/_live_env.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/catalog/_routes.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/catalog/_schema.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/catalog/_store.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/deploy/__init__.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/deploy/_main.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/deploy/_templates.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/disks.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/events/__init__.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/events/_kinds.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/events/_log.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/events/_routes.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/exports/__init__.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/exports/_routes.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/exports/_store.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/exports/_supervisor.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/flash.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/images.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/machines/__init__.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/machines/_routes.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/machines/_store.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/oras.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/pivot/__init__.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/pivot/nbdboot +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/pxe/__init__.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/tftp/__init__.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/tftp/_supervisor.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/tui/__init__.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/tui/_app.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/tui_catalog.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/__init__.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_auth.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_bind_preview.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_fsutil.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_images.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_inventory.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_overlay_bind.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_overlays.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_static/.gitkeep +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_static/bootstrap-icons.min.css +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_static/bootstrap.min.css +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_static/fonts/bootstrap-icons.woff +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_static/fonts/bootstrap-icons.woff2 +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_static/htmx.min.js +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_static/pixie-favicon.png +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_static/sse.js +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_table_state.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/_partials/page_description.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/_partials/recent_events.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/_partials/table_helpers.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/catalog.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/catalog_detail.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/dashboard.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/events.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/image_detail.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/images.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/ipxe/bootstrap.j2 +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/ipxe/exit.j2 +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/ipxe/nbdboot.j2 +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/ipxe/pixie-live-env.j2 +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/ipxe/unavailable.j2 +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/layout.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/login.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/machine_detail.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/machines.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/overlays.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/src/pixie/web/_templates/settings.html +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/__init__.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/conftest.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/integration/__init__.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/integration/conftest.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/integration/test_catalog_fetch.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/integration/test_deploy.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/integration/test_exports.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/integration/test_inventory.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/integration/test_pxe.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/integration/test_tftp.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_auth.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_catalog_api.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_deploy_unit.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_event_kinds.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_events_unit.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_exports_unit.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_fetch_progress.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_healthz.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_images_ui.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_live_env_fetch.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_machines_unit.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_overlays_ui.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_pivot.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_schema.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_ui_pages.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_web_bind_preview.py +0 -0
- {pixie_lab-0.4.1 → pixie_lab-0.4.2}/tests/test_web_inventory.py +0 -0
|
@@ -191,6 +191,67 @@ jobs:
|
|
|
191
191
|
~/system_imaging/disk/pixie-usbboot-pc-x86_64-v*.iso
|
|
192
192
|
~/system_imaging/disk/pixie-usbboot-pc-x86_64-v*.sha256
|
|
193
193
|
|
|
194
|
+
build-live-env-image:
|
|
195
|
+
name: Build pixie-live-env image
|
|
196
|
+
# The image the live-env boot modes nbdboot: the nosi arch-headless
|
|
197
|
+
# base disk image with the pixie CLI + pixie-on-tty1 service injected
|
|
198
|
+
# (cijoe/tasks/live-env-image.yaml). Unlike the live-build bakes this
|
|
199
|
+
# does NOT run debootstrap/mksquashfs; it qemu-nbd-mounts a copy of a
|
|
200
|
+
# pulled base image, injects userspace, slims, and gzips. Wired to
|
|
201
|
+
# ``test`` so we don't pay for the ORAS pull + qemu transform on a
|
|
202
|
+
# broken lint/typecheck.
|
|
203
|
+
needs: test
|
|
204
|
+
runs-on: ubuntu-latest
|
|
205
|
+
# 60 min cap for the same reason as build-media: the real ORAS pull
|
|
206
|
+
# of the arch-headless base (~1.6 GiB) + decompress + qemu transform
|
|
207
|
+
# + gzip dominate wall clock.
|
|
208
|
+
timeout-minutes: 60
|
|
209
|
+
steps:
|
|
210
|
+
- uses: actions/checkout@v6
|
|
211
|
+
|
|
212
|
+
- name: Install build dependencies (qemu-nbd, rsync, nbd module)
|
|
213
|
+
run: |
|
|
214
|
+
set -eu
|
|
215
|
+
sudo apt-get update
|
|
216
|
+
sudo apt-get install -y --no-install-recommends \
|
|
217
|
+
qemu-utils rsync gzip
|
|
218
|
+
# The transform attaches a copy of the base image to /dev/nbdX
|
|
219
|
+
# via qemu-nbd; load the module with partition scanning so the
|
|
220
|
+
# root partition shows up as nbdXp1.
|
|
221
|
+
sudo modprobe nbd max_part=16
|
|
222
|
+
ls -la /dev/nbd0
|
|
223
|
+
|
|
224
|
+
- name: Install cijoe
|
|
225
|
+
run: pipx install --force cijoe
|
|
226
|
+
|
|
227
|
+
- name: Install uv
|
|
228
|
+
uses: astral-sh/setup-uv@v8.1.0
|
|
229
|
+
|
|
230
|
+
- name: Build pixie-live-env image
|
|
231
|
+
run: make live-env-image
|
|
232
|
+
|
|
233
|
+
# cijoe captures the full run (per-command output + report.html)
|
|
234
|
+
# under cijoe/cijoe-output/. Upload it ALWAYS so a transform
|
|
235
|
+
# failure leaves a diagnosable artifact.
|
|
236
|
+
- name: Upload cijoe output
|
|
237
|
+
if: always()
|
|
238
|
+
uses: actions/upload-artifact@v7
|
|
239
|
+
with:
|
|
240
|
+
name: cijoe-output-live-env-image
|
|
241
|
+
path: cijoe/cijoe-output
|
|
242
|
+
if-no-files-found: warn
|
|
243
|
+
|
|
244
|
+
- name: Upload artifact (pixie-live-env-image)
|
|
245
|
+
uses: actions/upload-artifact@v7
|
|
246
|
+
with:
|
|
247
|
+
name: pixie-live-env-image-x86_64
|
|
248
|
+
path: |
|
|
249
|
+
~/system_imaging/disk/pixie-live-env-x86_64.img.gz
|
|
250
|
+
~/system_imaging/disk/pixie-live-env-x86_64.img.gz.sha256
|
|
251
|
+
~/system_imaging/disk/pixie-live-env-x86_64.content-sha256
|
|
252
|
+
~/system_imaging/disk/pixie-live-env-catalog.toml
|
|
253
|
+
if-no-files-found: error
|
|
254
|
+
|
|
194
255
|
test-pxe:
|
|
195
256
|
name: PXE bootstrap chain test (containerized pixie + client QEMU VM)
|
|
196
257
|
# Independent of the media bake: the chain test only needs the
|
|
@@ -650,6 +711,7 @@ jobs:
|
|
|
650
711
|
- build-container
|
|
651
712
|
- build-wheel
|
|
652
713
|
- build-media
|
|
714
|
+
- build-live-env-image
|
|
653
715
|
- test-pxe
|
|
654
716
|
- test-pxe-nbdboot
|
|
655
717
|
- test-pxe-inventory
|
|
@@ -692,6 +754,7 @@ jobs:
|
|
|
692
754
|
- build-container
|
|
693
755
|
- build-wheel
|
|
694
756
|
- build-media
|
|
757
|
+
- build-live-env-image
|
|
695
758
|
- test-pxe
|
|
696
759
|
- test-pxe-nbdboot
|
|
697
760
|
- test-pxe-inventory
|
|
@@ -737,6 +800,7 @@ jobs:
|
|
|
737
800
|
- build-container
|
|
738
801
|
- build-wheel
|
|
739
802
|
- build-media
|
|
803
|
+
- build-live-env-image
|
|
740
804
|
- test-pxe
|
|
741
805
|
- test-pxe-nbdboot
|
|
742
806
|
- test-pxe-inventory
|
|
@@ -759,6 +823,15 @@ jobs:
|
|
|
759
823
|
pattern: pixie-*-pc-x86_64
|
|
760
824
|
merge-multiple: true
|
|
761
825
|
path: release-assets
|
|
826
|
+
- name: Download pixie-live-env image
|
|
827
|
+
# The nbdboot live-env image (arch-headless + injected pixie CLI
|
|
828
|
+
# / service): the gzipped disk image + its .sha256, the
|
|
829
|
+
# .content-sha256 sidecar (the value an operator sets
|
|
830
|
+
# PIXIE_LIVE_ENV_IMAGE_SHA to), and the catalog fragment.
|
|
831
|
+
uses: actions/download-artifact@v8
|
|
832
|
+
with:
|
|
833
|
+
name: pixie-live-env-image-x86_64
|
|
834
|
+
path: release-assets
|
|
762
835
|
- name: List release assets
|
|
763
836
|
run: ls -la release-assets
|
|
764
837
|
- name: Assemble live-env fetch tarball
|
|
@@ -798,7 +871,10 @@ jobs:
|
|
|
798
871
|
|
|
799
872
|
## Media assets attached here
|
|
800
873
|
|
|
801
|
-
- `pixie-live-env-x86_64.
|
|
802
|
-
- `pixie-
|
|
874
|
+
- `pixie-live-env-x86_64.img.gz` — the **nbdboot** live-env image: the nosi `arch-headless` base disk image with the pixie CLI + `pixie-on-tty1` service injected. Fetch it from the **Catalog** tab (it seeds into a fresh catalog), then set `PIXIE_LIVE_ENV_IMAGE_SHA` to select it for the `pixie-flash-once` / `pixie-flash-always` / `pixie-inventory` / `pixie-tui` boot modes so they nbdboot this image ephemerally.
|
|
875
|
+
- `pixie-live-env-x86_64.content-sha256` — the raw-image sha256 to set `PIXIE_LIVE_ENV_IMAGE_SHA` to (identical to the `content_sha256` pixie assigns after fetching the `pixie-live-env` catalog entry).
|
|
876
|
+
- `pixie-live-env-catalog.toml` — the catalog fragment (the `pixie-live-env` disk image + its arch-headless netboot bundle) with `content_sha256` filled in; the shipped `catalog.toml` also lists these entries.
|
|
877
|
+
- `pixie-live-env-x86_64.tar.gz` — the older squashfs live-env trio for pixie's in-app **Fetch live-env** action (the default `PIXIE_LIVE_ENV_SRC`) and the `PIXIE_LIVE_ENV_DIR` staging path.
|
|
878
|
+
- `pixie-netboot-pc-x86_64-*.{vmlinuz,initrd,squashfs}` — the squashfs live-env (netboot-pc bake) as loose files, if you prefer to stage `PIXIE_LIVE_ENV_DIR` (`data/live-env/`) by hand.
|
|
803
879
|
- `pixie-usbboot-pc-x86_64-*.iso` — bootable USB / ISO media for the pixie live env (uncompressed; `dd` / Etcher / Ventoy ready).
|
|
804
880
|
- `*.sha256` — checksums for the above.
|
|
@@ -11,6 +11,33 @@ operator-facing summary.
|
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
+
## [0.4.2] - 2026-07-26
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
**The live-env boots as an ephemeral-nbdboot disk image, not a
|
|
19
|
+
live-boot squashfs.** The inventory / tui / flash boot modes now
|
|
20
|
+
nbdboot a normal disk image (nosi `arch-headless` with the pixie CLI +
|
|
21
|
+
`pixie-on-tty1` service injected) with a tmpfs overlay, instead of
|
|
22
|
+
fetching a live-boot squashfs. This fixes boxes whose NIC never came up
|
|
23
|
+
under the old Debian live-boot initramfs (dual-NIC Intel `igb` among
|
|
24
|
+
them): the image rides the same dracut ramboot path that nbdboot
|
|
25
|
+
already uses, which brings those NICs up. Point pixie at it by fetching
|
|
26
|
+
the `pixie-live-env` catalog entry and setting `PIXIE_LIVE_ENV_IMAGE_SHA`
|
|
27
|
+
(or the `live_env.image_sha` setting) to its content sha; the image ships
|
|
28
|
+
as a release asset (`pixie-live-env-x86_64.img.gz`, under 2 GB) built and
|
|
29
|
+
published by CI.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
**Rootfs extraction picks the Linux root partition by GPT type.** The
|
|
34
|
+
fetcher extracted partition 1 as `rootfs.raw`, correct for the
|
|
35
|
+
ubuntu/debian cloud images (root at p1) but not for arch/fedora, whose
|
|
36
|
+
images place BIOS-boot + ESP first and root at p3 -- there it produced a
|
|
37
|
+
1 MiB stub that could not mount. It now selects by type (Linux-root GUID,
|
|
38
|
+
then the largest Linux filesystem, then the largest non-firmware/boot/swap
|
|
39
|
+
partition), so every nosi image extracts its real root.
|
|
40
|
+
|
|
14
41
|
## [0.4.1] - 2026-07-25
|
|
15
42
|
|
|
16
43
|
### Changed
|
|
@@ -23,7 +23,7 @@ endif
|
|
|
23
23
|
|
|
24
24
|
.PHONY: help \
|
|
25
25
|
deps test lint format format-check typecheck ci wheel \
|
|
26
|
-
media-deps build ipxe test-pxe test-usb-ventoy \
|
|
26
|
+
media-deps build live-env-image ipxe test-pxe test-usb-ventoy \
|
|
27
27
|
clean
|
|
28
28
|
|
|
29
29
|
help:
|
|
@@ -43,6 +43,8 @@ help:
|
|
|
43
43
|
@echo " media-deps pipx install cijoe"
|
|
44
44
|
@echo " build build a media image (override VARIANT below)"
|
|
45
45
|
@echo " -> ~/system_imaging/disk/pixie-<variant>.*"
|
|
46
|
+
@echo " live-env-image build the pixie-live-env disk image (arch-headless"
|
|
47
|
+
@echo " base + pixie CLI/service) nbdbooted by the live-env modes"
|
|
46
48
|
@echo " ipxe build pixie's custom iPXE -> IPXE_OUT/ipxe.efi (default dist/ipxe/)"
|
|
47
49
|
@echo " test-pxe end-to-end PXE bootstrap chain test"
|
|
48
50
|
@echo " (needs podman + QEMU + KVM + dnsmasq; a few min wall clock)"
|
|
@@ -107,6 +109,15 @@ media-deps:
|
|
|
107
109
|
build:
|
|
108
110
|
cd cijoe && cijoe $(MEDIA_TASK) --monitor -c configs/$(VARIANT).toml
|
|
109
111
|
|
|
112
|
+
# Build the pixie-live-env disk image: pull the nosi arch-headless base
|
|
113
|
+
# via ORAS, inject the pixie CLI + pixie-on-tty1 service, slim + gzip,
|
|
114
|
+
# and publish the asset (< 2 GiB) plus its sha256 / content-sha256
|
|
115
|
+
# sidecars and a catalog fragment. The live-env boot modes nbdboot this
|
|
116
|
+
# image; PIXIE_LIVE_ENV_IMAGE_SHA selects it (= the content-sha256).
|
|
117
|
+
# Needs qemu-nbd + passwordless sudo + uv + the nbd kernel module.
|
|
118
|
+
live-env-image:
|
|
119
|
+
cd cijoe && cijoe tasks/live-env-image.yaml --monitor -c configs/live-env-image.toml
|
|
120
|
+
|
|
110
121
|
# Build pixie's slim iPXE binary (bin-x86_64-efi/ipxe.efi) with the
|
|
111
122
|
# embedded chain-loader baked in. Landed in the container image so a
|
|
112
123
|
# fresh deploy gets the one-bootfile chain guarantee without needing
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pixie-lab
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Bare-metal netboot appliance: catalog + fetch + NBD + PXE + TFTP + operator TUI in one container
|
|
5
5
|
Project-URL: Homepage, https://github.com/safl/pixie
|
|
6
6
|
Project-URL: Repository, https://github.com/safl/pixie
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# pixie live-env image - build configuration
|
|
2
|
+
#
|
|
3
|
+
# Drives the transform that turns the nosi ``arch-headless`` base disk
|
|
4
|
+
# image into the ``pixie-live-env`` image pixie nbdboots ephemerally for
|
|
5
|
+
# the live-env boot modes. See cijoe/tasks/live-env-image.yaml.
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
# cijoe tasks/live-env-image.yaml --config configs/live-env-image.toml --monitor
|
|
9
|
+
# (or via the Makefile dispatcher: ``make live-env-image``)
|
|
10
|
+
|
|
11
|
+
[pixie]
|
|
12
|
+
variant = "live-env-image"
|
|
13
|
+
|
|
14
|
+
[cijoe.workflow]
|
|
15
|
+
fail_fast = true
|
|
16
|
+
|
|
17
|
+
[live-env-image]
|
|
18
|
+
# The nosi base disk image + its netboot bundle (kernel + initrd). The
|
|
19
|
+
# transform only mutates userspace, so the pixie-live-env image reuses
|
|
20
|
+
# arch-headless's own kernel/initrd unchanged -- ``netboot_src`` points
|
|
21
|
+
# straight at the arch-headless netboot bundle.
|
|
22
|
+
base_src = "oras://ghcr.io/safl/nosi/arch-headless:latest"
|
|
23
|
+
netboot_src = "oras://ghcr.io/safl/nosi/arch-headless-netboot:latest"
|
|
24
|
+
|
|
25
|
+
# The stable release-asset URL the shipped catalog entry references
|
|
26
|
+
# (``.../releases/latest/download/pixie-live-env-x86_64.img.gz``), so a
|
|
27
|
+
# fresh pixie can Fetch it from the Catalog tab like any nosi image.
|
|
28
|
+
catalog_src = "https://github.com/safl/pixie/releases/latest/download/pixie-live-env-x86_64.img.gz"
|
|
29
|
+
|
|
30
|
+
image_name = "pixie-live-env"
|
|
31
|
+
|
|
32
|
+
# Where the published asset + sidecars + catalog fragment land. Mirrors
|
|
33
|
+
# the netboot-pc / usbboot-pc variants so all media live under one tree.
|
|
34
|
+
publish.dir = "{{ local.env.HOME }}/system_imaging/disk"
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Build + publish the pixie-live-env disk image
|
|
3
|
+
=============================================
|
|
4
|
+
|
|
5
|
+
Produces the ``pixie-live-env`` image that pixie nbdboots ephemerally
|
|
6
|
+
for the live-env boot modes (``pixie-flash-once`` / ``-always`` /
|
|
7
|
+
``pixie-inventory`` / ``pixie-tui``). The renderer selects this image
|
|
8
|
+
via the ``PIXIE_LIVE_ENV_IMAGE_SHA`` setting; the value an operator
|
|
9
|
+
sets there is the ``content_sha256`` this build computes and publishes
|
|
10
|
+
(see step 5 below and the ``.content-sha256`` sidecar).
|
|
11
|
+
|
|
12
|
+
Pipeline:
|
|
13
|
+
|
|
14
|
+
1. ``uv build --wheel`` the current pixie-lab, then assemble a vendored
|
|
15
|
+
CLI tree: ``pip install --target`` the pixie package (``--no-deps``)
|
|
16
|
+
plus only the pure-Python CLI runtime deps (``rich`` + ``tomlkit``).
|
|
17
|
+
The CLI reaches the server over stdlib ``urllib`` -- NOT httpx -- so
|
|
18
|
+
the heavy fastapi / uvicorn / pydantic base deps are deliberately
|
|
19
|
+
left out. The image's stock ``python3`` runs this tree.
|
|
20
|
+
|
|
21
|
+
2. Pull the nosi ``arch-headless`` base disk image via ORAS, reusing
|
|
22
|
+
pixie's own resolver (``python -m pixie.oras_pull``) so the bytes +
|
|
23
|
+
digest match a live catalog Fetch. Decompress the ``img.gz`` to a
|
|
24
|
+
raw disk image.
|
|
25
|
+
|
|
26
|
+
3. Run ``live_env_transform.sh`` (privileged: qemu-nbd + mount) to
|
|
27
|
+
inject the vendored CLI + the ``pixie-on-tty1`` service trio and
|
|
28
|
+
slim conservatively, emitting a raw disk image.
|
|
29
|
+
|
|
30
|
+
4. sha256 the RAW image -> ``content_sha256`` (== PIXIE_LIVE_ENV_IMAGE_SHA);
|
|
31
|
+
gzip it to ``pixie-live-env-x86_64.img.gz`` (the release asset);
|
|
32
|
+
assert the gzipped asset is < 2 GiB (GitHub's per-file release
|
|
33
|
+
limit) and fail otherwise.
|
|
34
|
+
|
|
35
|
+
5. Emit alongside the asset: its ``.sha256`` checksum, a
|
|
36
|
+
``.content-sha256`` sidecar carrying the raw-image sha (the value
|
|
37
|
+
for ``PIXIE_LIVE_ENV_IMAGE_SHA``), and ``pixie-live-env-catalog.toml``
|
|
38
|
+
-- a catalog fragment (the bindable disk image with its
|
|
39
|
+
``netboot_src`` + the arch-headless netboot bundle it points at) the
|
|
40
|
+
release job merges into the shipped ``catalog.toml`` so the image is
|
|
41
|
+
fetchable via the Catalog tab like any other.
|
|
42
|
+
|
|
43
|
+
The cwd at run time is ``cijoe/`` (the Makefile cd's there), so the
|
|
44
|
+
repo root is ``Path.cwd().parent``. Requires: passwordless sudo,
|
|
45
|
+
qemu-utils (qemu-nbd + qemu-img), the ``nbd`` module, rsync, gzip, and
|
|
46
|
+
``uv`` on PATH. Skipped for any variant other than ``live-env-image``.
|
|
47
|
+
|
|
48
|
+
Retargetable: False
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
from __future__ import annotations
|
|
52
|
+
|
|
53
|
+
import errno
|
|
54
|
+
import logging as log
|
|
55
|
+
import shutil
|
|
56
|
+
from argparse import ArgumentParser
|
|
57
|
+
from pathlib import Path
|
|
58
|
+
|
|
59
|
+
# Reuse the pyproject version reader so the published asset + catalog
|
|
60
|
+
# fragment carry the same stamped version as the other bakes.
|
|
61
|
+
from usb_iso_build import _read_pixie_version
|
|
62
|
+
|
|
63
|
+
# GitHub's per-file release-asset hard limit. The gzipped image must
|
|
64
|
+
# land under this or the release upload is rejected downstream, so we
|
|
65
|
+
# gate here (loud, early) instead.
|
|
66
|
+
RELEASE_ASSET_LIMIT = 2 * 1024 * 1024 * 1024
|
|
67
|
+
|
|
68
|
+
# Stable, unversioned asset basename so the catalog + settings default
|
|
69
|
+
# can reference ``.../releases/latest/download/<name>`` at a fixed URL
|
|
70
|
+
# (mirrors how the live-env tarball + catalog.toml are published).
|
|
71
|
+
ASSET_BASENAME = "pixie-live-env-x86_64.img.gz"
|
|
72
|
+
CATALOG_FRAGMENT_BASENAME = "pixie-live-env-catalog.toml"
|
|
73
|
+
CONTENT_SHA_BASENAME = "pixie-live-env-x86_64.content-sha256"
|
|
74
|
+
|
|
75
|
+
# Defaults; overridable via the ``[live-env-image]`` config table.
|
|
76
|
+
DEFAULT_BASE_SRC = "oras://ghcr.io/safl/nosi/arch-headless:latest"
|
|
77
|
+
DEFAULT_NETBOOT_SRC = "oras://ghcr.io/safl/nosi/arch-headless-netboot:latest"
|
|
78
|
+
DEFAULT_CATALOG_SRC = (
|
|
79
|
+
"https://github.com/safl/pixie/releases/latest/download/pixie-live-env-x86_64.img.gz"
|
|
80
|
+
)
|
|
81
|
+
DEFAULT_IMAGE_NAME = "pixie-live-env"
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def add_args(parser: ArgumentParser):
|
|
85
|
+
del parser # no flags; signature kept for cijoe consistency
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _sha256_of(cijoe, path: Path) -> str | None:
|
|
89
|
+
err, state = cijoe.run_local(f"sha256sum {path}")
|
|
90
|
+
if err:
|
|
91
|
+
return None
|
|
92
|
+
out = state.output() if hasattr(state, "output") else str(state)
|
|
93
|
+
fields = out.strip().split()
|
|
94
|
+
return fields[0] if fields else None
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _build_vendored_cli(cijoe, repo_root: Path, build_dir: Path) -> Path | None:
|
|
98
|
+
"""Build the wheel and assemble the vendored CLI tree. Returns the
|
|
99
|
+
vendor dir on success, ``None`` on failure."""
|
|
100
|
+
wheel_out = build_dir / "wheel"
|
|
101
|
+
if wheel_out.exists():
|
|
102
|
+
shutil.rmtree(wheel_out)
|
|
103
|
+
wheel_out.mkdir(parents=True)
|
|
104
|
+
|
|
105
|
+
err, _ = cijoe.run_local(f"sh -c 'cd {repo_root} && uv build --wheel --out-dir {wheel_out}'")
|
|
106
|
+
if err:
|
|
107
|
+
log.error("uv build --wheel failed")
|
|
108
|
+
return None
|
|
109
|
+
wheels = sorted(wheel_out.glob("pixie_lab-*-py3-none-any.whl"))
|
|
110
|
+
if not wheels:
|
|
111
|
+
log.error(f"no pixie_lab wheel produced in {wheel_out}")
|
|
112
|
+
return None
|
|
113
|
+
wheel = wheels[-1]
|
|
114
|
+
|
|
115
|
+
vendor = build_dir / "vendor"
|
|
116
|
+
if vendor.exists():
|
|
117
|
+
shutil.rmtree(vendor)
|
|
118
|
+
vendor.mkdir(parents=True)
|
|
119
|
+
|
|
120
|
+
# The pixie package only (no deps -- installing the full wheel would
|
|
121
|
+
# drag fastapi / uvicorn / httpx / pydantic, which are compiled,
|
|
122
|
+
# version-specific, and unused by the CLI).
|
|
123
|
+
err, _ = cijoe.run_local(f"uv pip install --target {vendor} --no-compile --no-deps {wheel}")
|
|
124
|
+
if err:
|
|
125
|
+
log.error("uv pip install (pixie package, --no-deps) failed")
|
|
126
|
+
return None
|
|
127
|
+
# The pure-Python CLI runtime deps. rich powers the wizard; tomlkit
|
|
128
|
+
# backs the catalog round-trip the CLI can reach. Both ship as
|
|
129
|
+
# ``py3-none-any`` wheels, so they import under the image's own
|
|
130
|
+
# python3 regardless of its minor version.
|
|
131
|
+
err, _ = cijoe.run_local(f"uv pip install --target {vendor} --no-compile rich tomlkit")
|
|
132
|
+
if err:
|
|
133
|
+
log.error("uv pip install (rich + tomlkit) failed")
|
|
134
|
+
return None
|
|
135
|
+
return vendor
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def main(args, cijoe):
|
|
139
|
+
del args
|
|
140
|
+
cijoe_dir = Path.cwd()
|
|
141
|
+
repo_root = cijoe_dir.parent
|
|
142
|
+
pixie_media = repo_root / "pixie-media"
|
|
143
|
+
|
|
144
|
+
variant = cijoe.getconf("pixie", {}).get("variant", "")
|
|
145
|
+
if variant != "live-env-image":
|
|
146
|
+
log.info(f"Skipping live_env_image (variant={variant!r}; only 'live-env-image' runs)")
|
|
147
|
+
return 0
|
|
148
|
+
|
|
149
|
+
conf = cijoe.getconf("live-env-image", {})
|
|
150
|
+
base_src = conf.get("base_src", DEFAULT_BASE_SRC)
|
|
151
|
+
netboot_src = conf.get("netboot_src", DEFAULT_NETBOOT_SRC)
|
|
152
|
+
catalog_src = conf.get("catalog_src", DEFAULT_CATALOG_SRC)
|
|
153
|
+
image_name = conf.get("image_name", DEFAULT_IMAGE_NAME)
|
|
154
|
+
publish_dir_str = conf.get("publish", {}).get("dir")
|
|
155
|
+
if not publish_dir_str:
|
|
156
|
+
log.error("live-env-image.publish.dir is unset in the config")
|
|
157
|
+
return errno.EINVAL
|
|
158
|
+
publish_dir = Path(publish_dir_str)
|
|
159
|
+
publish_dir.mkdir(parents=True, exist_ok=True)
|
|
160
|
+
|
|
161
|
+
if not pixie_media.exists():
|
|
162
|
+
log.error(f"pixie-media tree missing: {pixie_media}")
|
|
163
|
+
return errno.ENOENT
|
|
164
|
+
|
|
165
|
+
build_dir = cijoe_dir / "_build" / "live-env-image"
|
|
166
|
+
if build_dir.exists():
|
|
167
|
+
# The transform's scratch is torn down internally, but the raw
|
|
168
|
+
# base image is owned by the invoking user; a plain rm is fine.
|
|
169
|
+
err, _ = cijoe.run_local(f"sudo rm -rf {build_dir}")
|
|
170
|
+
if err:
|
|
171
|
+
log.error(f"failed to remove stale build dir {build_dir}")
|
|
172
|
+
return err
|
|
173
|
+
build_dir.mkdir(parents=True)
|
|
174
|
+
|
|
175
|
+
pixie_version = _read_pixie_version(cijoe_dir)
|
|
176
|
+
log.info(f"Building {image_name} v{pixie_version} from base {base_src}")
|
|
177
|
+
|
|
178
|
+
# 1. Vendored CLI tree.
|
|
179
|
+
vendor = _build_vendored_cli(cijoe, repo_root, build_dir)
|
|
180
|
+
if vendor is None:
|
|
181
|
+
return errno.EIO
|
|
182
|
+
|
|
183
|
+
# 2. Pull + decompress the base image, reusing pixie's ORAS resolver.
|
|
184
|
+
base_gz = build_dir / "base.img.gz"
|
|
185
|
+
err, _ = cijoe.run_local(
|
|
186
|
+
f"sh -c 'cd {repo_root} && uv run python -m pixie.oras_pull {base_src} {base_gz}'"
|
|
187
|
+
)
|
|
188
|
+
if err:
|
|
189
|
+
log.error(f"failed to pull base image {base_src}")
|
|
190
|
+
return err
|
|
191
|
+
base_raw = build_dir / "base.img"
|
|
192
|
+
err, _ = cijoe.run_local(f"sh -c 'gzip -dc {base_gz} > {base_raw}'")
|
|
193
|
+
if err:
|
|
194
|
+
log.error("failed to decompress the base image")
|
|
195
|
+
return err
|
|
196
|
+
|
|
197
|
+
# 3. Transform: inject CLI + service trio, slim, fstrim.
|
|
198
|
+
out_raw = build_dir / "pixie-live-env.img"
|
|
199
|
+
transform = cijoe_dir / "scripts" / "live_env_transform.sh"
|
|
200
|
+
err, _ = cijoe.run_local(
|
|
201
|
+
f"sudo bash {transform} "
|
|
202
|
+
f"--base {base_raw} --out {out_raw} --vendor {vendor} "
|
|
203
|
+
f"--media {pixie_media} --force"
|
|
204
|
+
)
|
|
205
|
+
if err:
|
|
206
|
+
log.error("live_env_transform.sh failed")
|
|
207
|
+
return err
|
|
208
|
+
# The transform chown's the output back to us, but be defensive.
|
|
209
|
+
cijoe.run_local(f"sudo chown $(id -u):$(id -g) {out_raw}")
|
|
210
|
+
|
|
211
|
+
# 4. Content-address on the RAW image (matches pixie's img.gz fetch:
|
|
212
|
+
# decompress -> sha of the raw disk image), then gzip the asset.
|
|
213
|
+
content_sha = _sha256_of(cijoe, out_raw)
|
|
214
|
+
if not content_sha:
|
|
215
|
+
log.error(f"failed computing content sha256 of {out_raw}")
|
|
216
|
+
return errno.EIO
|
|
217
|
+
log.info(f"content_sha256 (PIXIE_LIVE_ENV_IMAGE_SHA) = {content_sha}")
|
|
218
|
+
|
|
219
|
+
asset_path = publish_dir / ASSET_BASENAME
|
|
220
|
+
err, _ = cijoe.run_local(f"sh -c 'gzip -c {out_raw} > {asset_path}'")
|
|
221
|
+
if err:
|
|
222
|
+
log.error("failed gzipping the live-env image asset")
|
|
223
|
+
return err
|
|
224
|
+
|
|
225
|
+
asset_bytes = asset_path.stat().st_size
|
|
226
|
+
log.info(f"asset {asset_path.name}: {asset_bytes} bytes ({asset_bytes / 2**30:.2f} GiB)")
|
|
227
|
+
if asset_bytes >= RELEASE_ASSET_LIMIT:
|
|
228
|
+
log.error(
|
|
229
|
+
f"{asset_path.name} is {asset_bytes / 2**30:.2f} GiB, "
|
|
230
|
+
f">= the 2 GiB GitHub release-asset limit; tighten the transform slim"
|
|
231
|
+
)
|
|
232
|
+
return errno.EFBIG
|
|
233
|
+
|
|
234
|
+
# 5. Sidecars + catalog fragment.
|
|
235
|
+
asset_sha = _sha256_of(cijoe, asset_path)
|
|
236
|
+
if not asset_sha:
|
|
237
|
+
log.error("failed computing sha256 of the gzipped asset")
|
|
238
|
+
return errno.EIO
|
|
239
|
+
(publish_dir / f"{ASSET_BASENAME}.sha256").write_text(
|
|
240
|
+
f"{asset_sha} {ASSET_BASENAME}\n", encoding="utf-8"
|
|
241
|
+
)
|
|
242
|
+
(publish_dir / CONTENT_SHA_BASENAME).write_text(f"{content_sha}\n", encoding="utf-8")
|
|
243
|
+
|
|
244
|
+
fragment = _catalog_fragment(
|
|
245
|
+
image_name=image_name,
|
|
246
|
+
catalog_src=catalog_src,
|
|
247
|
+
netboot_src=netboot_src,
|
|
248
|
+
content_sha=content_sha,
|
|
249
|
+
version=pixie_version,
|
|
250
|
+
)
|
|
251
|
+
(publish_dir / CATALOG_FRAGMENT_BASENAME).write_text(fragment, encoding="utf-8")
|
|
252
|
+
|
|
253
|
+
cijoe.run_local(f"ls -la {publish_dir}")
|
|
254
|
+
log.info(
|
|
255
|
+
f"published {ASSET_BASENAME} (+ .sha256, {CONTENT_SHA_BASENAME}, "
|
|
256
|
+
f"{CATALOG_FRAGMENT_BASENAME}) to {publish_dir}"
|
|
257
|
+
)
|
|
258
|
+
return 0
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def _catalog_fragment(
|
|
262
|
+
*,
|
|
263
|
+
image_name: str,
|
|
264
|
+
catalog_src: str,
|
|
265
|
+
netboot_src: str,
|
|
266
|
+
content_sha: str,
|
|
267
|
+
version: str,
|
|
268
|
+
) -> str:
|
|
269
|
+
"""Render the catalog fragment (no ``version =`` header; the release
|
|
270
|
+
job appends these ``[[images]]`` blocks to the shipped catalog).
|
|
271
|
+
|
|
272
|
+
Two peer entries: the bindable disk image (with a filled-in
|
|
273
|
+
``content_sha256`` == PIXIE_LIVE_ENV_IMAGE_SHA, and a
|
|
274
|
+
``netboot_src`` URL cross-reference) and the arch-headless netboot
|
|
275
|
+
bundle it points at, so the nbdboot renderer resolves the pair.
|
|
276
|
+
"""
|
|
277
|
+
disk_desc = (
|
|
278
|
+
"pixie live-env (nosi arch-headless + the pixie CLI + pixie-on-tty1 service). "
|
|
279
|
+
"nbdbooted ephemerally for the live-env boot modes."
|
|
280
|
+
)
|
|
281
|
+
bundle_desc = (
|
|
282
|
+
"Netboot bundle for arch-headless: vmlinuz + initrd so pixie can nbdboot the "
|
|
283
|
+
"pixie-live-env image over NBD."
|
|
284
|
+
)
|
|
285
|
+
return f"""\
|
|
286
|
+
# pixie-live-env {version} -- the image the live-env boot modes
|
|
287
|
+
# (pixie-flash-once / -always / pixie-inventory / pixie-tui) nbdboot
|
|
288
|
+
# ephemerally. Set PIXIE_LIVE_ENV_IMAGE_SHA to the content_sha256 below
|
|
289
|
+
# to select it (that sha is the sha256 of the raw disk image, which is
|
|
290
|
+
# exactly what pixie content-addresses this img.gz to after fetching).
|
|
291
|
+
|
|
292
|
+
[[images]]
|
|
293
|
+
name = "{image_name}"
|
|
294
|
+
src = "{catalog_src}"
|
|
295
|
+
format = "img.gz"
|
|
296
|
+
arch = "x86_64"
|
|
297
|
+
description = "{disk_desc}"
|
|
298
|
+
netboot_src = "{netboot_src}"
|
|
299
|
+
content_sha256 = "{content_sha}"
|
|
300
|
+
|
|
301
|
+
[[images]]
|
|
302
|
+
name = "nosi arch-headless netboot bundle"
|
|
303
|
+
src = "{netboot_src}"
|
|
304
|
+
format = "tar.gz"
|
|
305
|
+
arch = "x86_64"
|
|
306
|
+
description = "{bundle_desc}"
|
|
307
|
+
"""
|