pixie-lab 0.2.0__tar.gz → 0.3.0__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.2.0 → pixie_lab-0.3.0}/.github/workflows/cicd.yaml +132 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/CHANGELOG.md +56 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/PKG-INFO +1 -1
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/docs/src/deployment.md +25 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pyproject.toml +1 -1
- pixie_lab-0.3.0/src/pixie/catalog/__init__.py +49 -0
- pixie_lab-0.3.0/src/pixie/catalog/_live_env.py +128 -0
- pixie_lab-0.3.0/src/pixie/catalog/catalog.toml +81 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/events/_kinds.py +20 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/tui/_app.py +5 -3
- pixie_lab-0.3.0/src/pixie/web/_overlays.py +225 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_settings_store.py +23 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/catalog.html +2 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/dashboard.html +36 -29
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/layout.html +6 -0
- pixie_lab-0.3.0/src/pixie/web/_templates/live_env.html +169 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/machine_detail.html +62 -96
- pixie_lab-0.3.0/src/pixie/web/_templates/overlays.html +248 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/settings.html +0 -58
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/main.py +359 -44
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/conftest.py +6 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/integration/conftest.py +7 -0
- pixie_lab-0.3.0/tests/test_catalog_seed.py +118 -0
- pixie_lab-0.3.0/tests/test_live_env_fetch.py +203 -0
- pixie_lab-0.3.0/tests/test_overlays_ui.py +255 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_settings.py +4 -4
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_ui_pages.py +1 -2
- pixie_lab-0.2.0/src/pixie/catalog/__init__.py +0 -25
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/.dockerignore +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/.github/workflows/docs.yml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/.gitignore +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/Containerfile +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/LICENSE +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/Makefile +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/PLAN.md +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/README.md +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/configs/netboot-pc.toml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/configs/test-pxe-flash-always.toml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/configs/test-pxe-flash.toml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/configs/test-pxe-inventory.toml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/configs/test-pxe-nbdboot.toml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/configs/test-pxe-tui.toml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/configs/test-pxe.toml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/configs/usbboot-pc.toml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/scripts/live_build.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/scripts/pixie_ipxe_build.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/scripts/pixie_wheel_stage.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/scripts/pxe_flash_stage.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/scripts/pxe_inventory_stage.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/scripts/pxe_prepare.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/scripts/pxe_run_chain_test.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/scripts/usb_iso_build.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/tasks/netboot-pc.yaml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/tasks/test-pxe-flash-always.yaml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/tasks/test-pxe-flash.yaml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/tasks/test-pxe-inventory.yaml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/tasks/test-pxe-nbdboot.yaml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/tasks/test-pxe-tui.yaml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/tasks/test-pxe.yaml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/cijoe/tasks/usbboot-pc.yaml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/docs/audit.md +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/docs/src/boot-modes.md +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/docs/src/conf.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/docs/src/hardware-quirks.md +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/docs/src/index.md +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/docs/src/quickstart.md +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/docs/tooling/README.md +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/docs/tooling/pyproject.toml +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/docs/tooling/src/pixie_docs/__init__.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/docs/tooling/src/pixie_docs/cli.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/README.md +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/auxiliary/cloudinit-metadata.meta +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/auxiliary/ipxe-embed.ipxe +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/auxiliary/ipxe-local-general.h +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/auto/config +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/archives/backports.list.binary +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/archives/backports.list.chroot +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/bootloaders/grub-efi/splash.png +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/bootloaders/syslinux/splash.png +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/hooks/normal/0500-pixie-install.hook.chroot +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/hooks/normal/0500-pixie-skip-bootloader-menu.hook.binary +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/hooks/normal/0600-pixie-r8125-dkms.hook.chroot +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/hooks/normal/0700-pixie-clock-from-http.hook.chroot +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/hooks/normal/0800-pixie-ssh-live.hook.chroot +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/hooks/normal/0900-pixie-enable-services.hook.chroot +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/hooks/normal/0980-pixie-apt-validate.hook.chroot +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/etc/issue +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/etc/modprobe.d/zz-pixie-blacklist-nouveau.conf +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/etc/motd +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/etc/profile.d/pixie-version.sh +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/getty@.service.d/zzz-pixie-autologin-root.conf +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/pixie-banner-early.service +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/pixie-banner-late.service +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/pixie-banner-mid.service +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/pixie-clock-from-http.service +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/pixie-images-discover.service +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/pixie-on-tty1.service +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/pixie-usb-grow.service +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/etc/systemd/system/var-lib-pixie-images.mount +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/etc/udev/rules.d/70-pixie-realtek-2g5-offloads.rules +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/usr/lib/systemd/system-generators/pixie-skip-usb-only-units-on-netboot +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/usr/local/sbin/pixie-boot-banner +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/usr/local/sbin/pixie-clock-from-http +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/usr/local/sbin/pixie-images-discover +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/usr/local/sbin/pixie-on-tty1 +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/usr/local/sbin/pixie-trace +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/includes.chroot/usr/local/sbin/pixie-usb-grow +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/package-lists/pixie-base.list.chroot +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/package-lists/pixie-flash.list.chroot +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/preferences/backports.pref.binary +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/pixie-media/live-build/config/preferences/backports.pref.chroot +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/__init__.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/_partition.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/_util.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/catalog/_fetcher.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/catalog/_routes.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/catalog/_schema.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/catalog/_store.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/deploy/__init__.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/deploy/_main.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/deploy/_templates.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/disks.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/events/__init__.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/events/_log.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/events/_routes.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/exports/__init__.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/exports/_routes.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/exports/_store.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/exports/_supervisor.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/flash.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/images.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/machines/__init__.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/machines/_routes.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/machines/_store.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/oras.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/pivot/__init__.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/pivot/nbdboot +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/pxe/__init__.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/pxe/_renderer.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/pxe/_routes.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/tftp/__init__.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/tftp/_supervisor.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/tui/__init__.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/tui_catalog.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/__init__.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_auth.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_bind_preview.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_inventory.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_static/.gitkeep +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_static/bootstrap-icons.min.css +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_static/bootstrap.min.css +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_static/fonts/bootstrap-icons.woff +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_static/fonts/bootstrap-icons.woff2 +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_static/htmx.min.js +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_static/pixie-favicon.png +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_static/sse.js +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_table_state.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/_partials/page_description.html +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/_partials/recent_events.html +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/_partials/table_helpers.html +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/catalog_detail.html +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/events.html +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/ipxe/bootstrap.j2 +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/ipxe/exit.j2 +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/ipxe/nbdboot.j2 +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/ipxe/pixie-live-env.j2 +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/ipxe/unavailable.j2 +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/login.html +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/src/pixie/web/_templates/machines.html +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/__init__.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/integration/__init__.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/integration/test_catalog_fetch.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/integration/test_deploy.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/integration/test_exports.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/integration/test_inventory.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/integration/test_pxe.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/integration/test_tftp.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_auth.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_catalog_api.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_deploy_unit.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_event_kinds.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_events_unit.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_exports_unit.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_fetch_progress.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_healthz.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_machines_unit.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_pivot.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_pxe_plan_json.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_schema.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_web_bind_preview.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/tests/test_web_inventory.py +0 -0
- {pixie_lab-0.2.0 → pixie_lab-0.3.0}/uv.lock +0 -0
|
@@ -17,6 +17,14 @@ name: cicd
|
|
|
17
17
|
# version cannot be re-uploaded -- so the job gates on every
|
|
18
18
|
# prior job (test + integration + build-container + build-wheel
|
|
19
19
|
# + build-media + every PXE chain test) succeeding first.
|
|
20
|
+
# * ``publish-container``: build + push the appliance image to
|
|
21
|
+
# ghcr.io/<owner>/pixie (``:<version>`` + ``:latest``), v* tags
|
|
22
|
+
# only. Before this the image was smoke-built and thrown away, so
|
|
23
|
+
# the documented ghcr image was never populated by CI.
|
|
24
|
+
# * ``publish-release``: create the GitHub Release for the tag and
|
|
25
|
+
# attach the media ``build-media`` produces -- the netboot-pc
|
|
26
|
+
# live-env bake + the usbboot-pc bootable image + checksums. These
|
|
27
|
+
# used to live only as ephemeral, login-gated workflow artifacts.
|
|
20
28
|
#
|
|
21
29
|
# First publish (claiming the pixie-lab name) requires a one-time
|
|
22
30
|
# PyPI setup: register a Pending Publisher on https://pypi.org
|
|
@@ -602,3 +610,127 @@ jobs:
|
|
|
602
610
|
# later job is retrying), succeed silently rather than
|
|
603
611
|
# fail.
|
|
604
612
|
skip-existing: true
|
|
613
|
+
|
|
614
|
+
publish-container:
|
|
615
|
+
name: Publish container image to ghcr
|
|
616
|
+
# Build + push the appliance image to ghcr.io/<owner>/pixie on a
|
|
617
|
+
# v* tag: ``:<version>`` (the tag minus its leading ``v``) plus
|
|
618
|
+
# ``:latest``. This is the image the compose deploy runs; before
|
|
619
|
+
# this the ``build-container`` job only smoke-built it and threw it
|
|
620
|
+
# away, so ghcr.io/safl/pixie was never populated by CI. Gated on
|
|
621
|
+
# the whole pipeline like publish-pypi -- never ship an image the
|
|
622
|
+
# boot-chain tests did not pass against.
|
|
623
|
+
needs:
|
|
624
|
+
- test
|
|
625
|
+
- integration
|
|
626
|
+
- build-container
|
|
627
|
+
- build-wheel
|
|
628
|
+
- build-media
|
|
629
|
+
- test-pxe
|
|
630
|
+
- test-pxe-nbdboot
|
|
631
|
+
- test-pxe-inventory
|
|
632
|
+
- test-pxe-tui
|
|
633
|
+
- test-pxe-flash
|
|
634
|
+
- test-pxe-flash-always
|
|
635
|
+
runs-on: ubuntu-latest
|
|
636
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
637
|
+
permissions:
|
|
638
|
+
contents: read
|
|
639
|
+
packages: write
|
|
640
|
+
steps:
|
|
641
|
+
- uses: actions/checkout@v6
|
|
642
|
+
- name: Log in to ghcr.io
|
|
643
|
+
run: |
|
|
644
|
+
echo "${{ secrets.GITHUB_TOKEN }}" \
|
|
645
|
+
| podman login ghcr.io -u "${{ github.actor }}" --password-stdin
|
|
646
|
+
- name: Build + push image
|
|
647
|
+
run: |
|
|
648
|
+
set -eu
|
|
649
|
+
IMAGE=ghcr.io/${{ github.repository_owner }}/pixie
|
|
650
|
+
VERSION=${GITHUB_REF_NAME#v}
|
|
651
|
+
podman build \
|
|
652
|
+
--build-arg PIXIE_VERSION="$VERSION" \
|
|
653
|
+
-t "$IMAGE:$VERSION" \
|
|
654
|
+
-t "$IMAGE:latest" \
|
|
655
|
+
-f Containerfile .
|
|
656
|
+
podman push "$IMAGE:$VERSION"
|
|
657
|
+
podman push "$IMAGE:latest"
|
|
658
|
+
|
|
659
|
+
publish-release:
|
|
660
|
+
name: Publish GitHub Release (media assets)
|
|
661
|
+
# Attach the media CI already builds -- the netboot-pc live-env
|
|
662
|
+
# bake (vmlinuz + initrd + squashfs) and the usbboot-pc bootable
|
|
663
|
+
# image -- to a GitHub Release on v* tags. Before this they only
|
|
664
|
+
# existed as ephemeral, login-gated workflow artifacts, so an
|
|
665
|
+
# operator had no released live-env or USB image to download. Same
|
|
666
|
+
# full-pipeline gate as the other publish jobs.
|
|
667
|
+
needs:
|
|
668
|
+
- test
|
|
669
|
+
- integration
|
|
670
|
+
- build-container
|
|
671
|
+
- build-wheel
|
|
672
|
+
- build-media
|
|
673
|
+
- test-pxe
|
|
674
|
+
- test-pxe-nbdboot
|
|
675
|
+
- test-pxe-inventory
|
|
676
|
+
- test-pxe-tui
|
|
677
|
+
- test-pxe-flash
|
|
678
|
+
- test-pxe-flash-always
|
|
679
|
+
runs-on: ubuntu-latest
|
|
680
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
681
|
+
permissions:
|
|
682
|
+
contents: write
|
|
683
|
+
steps:
|
|
684
|
+
- uses: actions/checkout@v6
|
|
685
|
+
- name: Download media artifacts
|
|
686
|
+
uses: actions/download-artifact@v8
|
|
687
|
+
with:
|
|
688
|
+
# Both build-media matrix legs upload under this shape:
|
|
689
|
+
# ``pixie-netboot-pc-x86_64`` + ``pixie-usbboot-pc-x86_64``.
|
|
690
|
+
# merge-multiple flattens both into one directory.
|
|
691
|
+
pattern: pixie-*-pc-x86_64
|
|
692
|
+
merge-multiple: true
|
|
693
|
+
path: release-assets
|
|
694
|
+
- name: List release assets
|
|
695
|
+
run: ls -la release-assets
|
|
696
|
+
- name: Assemble live-env fetch tarball
|
|
697
|
+
# pixie's in-app "Fetch live-env" pulls ONE tarball that unpacks
|
|
698
|
+
# to vmlinuz + initrd + live.squashfs (see catalog/_live_env.py).
|
|
699
|
+
# Repackage the netboot-pc trio under those stable names so
|
|
700
|
+
# ``.../releases/latest/download/pixie-live-env-x86_64.tar.gz``
|
|
701
|
+
# -- the default PIXIE_LIVE_ENV_SRC -- resolves.
|
|
702
|
+
run: |
|
|
703
|
+
set -eu
|
|
704
|
+
d=$(mktemp -d)
|
|
705
|
+
cp release-assets/pixie-netboot-pc-x86_64-*.vmlinuz "$d/vmlinuz"
|
|
706
|
+
cp release-assets/pixie-netboot-pc-x86_64-*.initrd "$d/initrd"
|
|
707
|
+
cp release-assets/pixie-netboot-pc-x86_64-*.squashfs "$d/live.squashfs"
|
|
708
|
+
tar -C "$d" -czf release-assets/pixie-live-env-x86_64.tar.gz \
|
|
709
|
+
vmlinuz initrd live.squashfs
|
|
710
|
+
( cd release-assets && sha256sum pixie-live-env-x86_64.tar.gz \
|
|
711
|
+
> pixie-live-env-x86_64.tar.gz.sha256 )
|
|
712
|
+
# Ship the curated catalog (the netboot-capable nosi subset)
|
|
713
|
+
# so DEFAULT_CATALOG_URL (.../releases/latest/download/catalog.toml)
|
|
714
|
+
# resolves and pixie's Import + live-env TUI default work.
|
|
715
|
+
cp src/pixie/catalog/catalog.toml release-assets/catalog.toml
|
|
716
|
+
ls -la release-assets
|
|
717
|
+
- name: Create / update GitHub Release
|
|
718
|
+
uses: softprops/action-gh-release@v2
|
|
719
|
+
with:
|
|
720
|
+
files: release-assets/*
|
|
721
|
+
# Fail loud if the glob matched nothing -- a release with no
|
|
722
|
+
# media is the bug this job exists to prevent.
|
|
723
|
+
fail_on_unmatched_files: true
|
|
724
|
+
generate_release_notes: true
|
|
725
|
+
body: |
|
|
726
|
+
## Distribution
|
|
727
|
+
|
|
728
|
+
- Container image: `ghcr.io/${{ github.repository_owner }}/pixie:latest` and the matching version tag (this tag without the leading `v`).
|
|
729
|
+
- Python CLI: `uv tool install pixie-lab` (or `pip install pixie-lab`).
|
|
730
|
+
|
|
731
|
+
## Media assets attached here
|
|
732
|
+
|
|
733
|
+
- `pixie-live-env-x86_64.tar.gz` — the live-env trio packaged for pixie's in-app **Fetch live-env** action (the default `PIXIE_LIVE_ENV_SRC`). Click Fetch live-env on the dashboard and pixie pulls + stages this itself; no manual bake or copy.
|
|
734
|
+
- `pixie-netboot-pc-x86_64-*.{vmlinuz,initrd,squashfs}` — the same live-env (netboot-pc bake) as loose files, if you prefer to stage `PIXIE_LIVE_ENV_DIR` (`data/live-env/`) by hand. Used by the `pixie-flash-once` / `pixie-flash-always` / `pixie-inventory` / `pixie-tui` boot modes.
|
|
735
|
+
- `pixie-usbboot-pc-x86_64-*.iso.gz` — bootable USB / ISO media for the pixie live env.
|
|
736
|
+
- `*.sha256` — checksums for the above.
|
|
@@ -11,6 +11,62 @@ operator-facing summary.
|
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
+
## [0.3.0] - 2026-07-23
|
|
15
|
+
|
|
16
|
+
Operator-facing surface + release plumbing. A fleet overlay-management
|
|
17
|
+
page, a tightened inventory view, and a dedicated live-env pane; the
|
|
18
|
+
release now ships the container image + boot media + a curated catalog,
|
|
19
|
+
and pixie can fetch its own live-env.
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
**Fleet-wide overlay management page.** A new **Overlays** page
|
|
24
|
+
(`/ui/overlays`) lists every persistent nbdboot qcow2 across the fleet
|
|
25
|
+
with disk-used, last-modified, serving port, and a state
|
|
26
|
+
(active / idle / orphaned / missing); per-row Reset and a Prune that
|
|
27
|
+
reclaims only the orphaned + missing ones. The machine-detail Inventory
|
|
28
|
+
view was tightened from stacked stat-cards into one dense summary.
|
|
29
|
+
|
|
30
|
+
**Pixie ships a curated catalog and defaults to it, not nosi's.** A
|
|
31
|
+
fresh (empty) catalog is seeded on first start from a `catalog.toml`
|
|
32
|
+
bundled in the package: a strict subset of the upstream nosi catalog
|
|
33
|
+
restricted to the four netboot-capable images pixie's nbdboot + live-env
|
|
34
|
+
chains actually test and support (debian-13-headless, ubuntu-2404 /
|
|
35
|
+
2604-headless, fedora-44-headless, each with its netboot bundle). The
|
|
36
|
+
desktop / proxmox / rpios / freebsd variants that have no netboot bundle
|
|
37
|
+
are omitted. The "Import catalog" field and the live-env TUI now default
|
|
38
|
+
to the pixie release copy of this curated catalog rather than the full
|
|
39
|
+
nosi catalog; both remain overridable by URL. Seeding is one-shot,
|
|
40
|
+
never clobbers an operator-populated catalog, and is disabled with
|
|
41
|
+
`PIXIE_SEED_CATALOG=0`.
|
|
42
|
+
|
|
43
|
+
**Pixie can fetch its own live-env, from a dedicated Live-env pane.** A
|
|
44
|
+
new **Live env** page (`/ui/live-env`) is the one place the live env is
|
|
45
|
+
managed: staged-media readiness, a **Fetch live env** action, the fetch
|
|
46
|
+
source, and the extra-kernel-cmdline override. Fetch downloads the
|
|
47
|
+
netboot-pc bake as a single tarball (`PIXIE_LIVE_ENV_SRC`, defaulting to
|
|
48
|
+
the latest GitHub release's `pixie-live-env-x86_64.tar.gz`) and stages
|
|
49
|
+
`vmlinuz` + `initrd` + `live.squashfs` under `PIXIE_LIVE_ENV_DIR`,
|
|
50
|
+
reusing the catalog fetch's curl transport. This replaces the only
|
|
51
|
+
artifact an operator previously had to bake locally
|
|
52
|
+
(`make build VARIANT=netboot-pc`) or hand-copy. The source is overridable
|
|
53
|
+
per deploy (point at a mirror for air-gapped installs). The dashboard
|
|
54
|
+
Live-env card is now status-only and links to the pane; the live-env
|
|
55
|
+
knobs moved off the Settings page. The `publish-release` job assembles
|
|
56
|
+
that tarball so the default source resolves.
|
|
57
|
+
|
|
58
|
+
**Releases now ship the container image and the boot media, not just
|
|
59
|
+
the PyPI package.** Tagging `v*` publishes the appliance image to
|
|
60
|
+
`ghcr.io/safl/pixie` (`:<version>` + `:latest`) and creates a GitHub
|
|
61
|
+
Release with the boot media attached: the netboot-pc live-env bake
|
|
62
|
+
(`vmlinuz` + `initrd` + `squashfs`) that the `pixie-flash-once` /
|
|
63
|
+
`pixie-flash-always` / `pixie-inventory` / `pixie-tui` modes chain
|
|
64
|
+
into, and the `usbboot-pc` bootable `.iso.gz`, each with a `.sha256`.
|
|
65
|
+
Previously a tag published only to PyPI, so the ghcr image that
|
|
66
|
+
`pixie-lab deploy` pins and the live-env media both existed only as
|
|
67
|
+
ephemeral CI artifacts or a local `make build` -- a fresh
|
|
68
|
+
`pixie-lab deploy` pulled an image that was never pushed.
|
|
69
|
+
|
|
14
70
|
## [0.2.0] - 2026-07-22
|
|
15
71
|
|
|
16
72
|
First real release after the 0.1.0 skeleton: nbdboot (ephemeral +
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pixie-lab
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
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
|
|
@@ -93,6 +93,20 @@ podman build -t pixie:local -f Containerfile .
|
|
|
93
93
|
cd /opt/pixie && podman compose --env-file envvars up -d
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
+
### Stage the live env
|
|
97
|
+
|
|
98
|
+
The `pixie-flash-*`, `pixie-inventory`, and `pixie-tui` boot modes chain
|
|
99
|
+
into pixie's live env (`vmlinuz` + `initrd` + `live.squashfs`). Open the
|
|
100
|
+
**Live env** page in the UI (`/ui/live-env`) and click **Fetch live
|
|
101
|
+
env**: pixie pulls the netboot-pc bake from `PIXIE_LIVE_ENV_SRC`
|
|
102
|
+
(default: the latest pixie GitHub release's
|
|
103
|
+
`pixie-live-env-x86_64.tar.gz`) and stages it under `PIXIE_LIVE_ENV_DIR`
|
|
104
|
+
itself - no manual bake or copy. For an air-gapped install, point
|
|
105
|
+
`PIXIE_LIVE_ENV_SRC` (or the live override on the Live env page) at a
|
|
106
|
+
local mirror of that tarball. You can still build it yourself with
|
|
107
|
+
`make build VARIANT=netboot-pc` and drop the three files into
|
|
108
|
+
`data/live-env/` by hand.
|
|
109
|
+
|
|
96
110
|
## Environment variables
|
|
97
111
|
|
|
98
112
|
Pixie reads these at container startup. The compose file passes the
|
|
@@ -131,6 +145,17 @@ netboot bundles), `overlays/<mac>/<image_sha>/<profile>.qcow2`
|
|
|
131
145
|
`pixie-*` boot modes degrade to an unavailable plan when this dir is
|
|
132
146
|
missing or incomplete.
|
|
133
147
|
|
|
148
|
+
**`PIXIE_LIVE_ENV_SRC`** (default: the latest pixie GitHub release's
|
|
149
|
+
`pixie-live-env-x86_64.tar.gz`) - the tarball the dashboard **Fetch
|
|
150
|
+
live-env** action downloads and stages into `PIXIE_LIVE_ENV_DIR`.
|
|
151
|
+
Accepts `https://` or `oras://`; it must unpack to `vmlinuz` + `initrd`
|
|
152
|
+
+ `live.squashfs`. Overridable live on the Live env page.
|
|
153
|
+
|
|
154
|
+
**`PIXIE_SEED_CATALOG`** (default: `1`) - seed a fresh (empty) catalog
|
|
155
|
+
from the bundled curated catalog (the netboot-capable nosi subset) on
|
|
156
|
+
first start. Set to `0` to start with an empty catalog. Runs once and
|
|
157
|
+
never overwrites an operator-populated catalog.
|
|
158
|
+
|
|
134
159
|
### NBD supervisor
|
|
135
160
|
|
|
136
161
|
**`PIXIE_NBD_BIND`** (default: `0.0.0.0`) - address nbdkit binds
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Operator-curated image library.
|
|
2
|
+
|
|
3
|
+
Pixie's catalog holds two peer entry shapes: **disk images**
|
|
4
|
+
(``format`` = ``img.gz`` / ``img.zst`` / ``img.xz`` / ``img`` / ...)
|
|
5
|
+
that pixie can flash to a target disk or serve over NBD for nbdboot,
|
|
6
|
+
and **netboot bundles** (``format`` = ``tar.gz``) whose contents pixie
|
|
7
|
+
unpacks into a content-addressed artifacts directory (vmlinuz +
|
|
8
|
+
initrd + manifest.json) so image-native nbdboot has kernel + initrd
|
|
9
|
+
URLs to serve.
|
|
10
|
+
|
|
11
|
+
Disk-image entries can carry a ``netboot_src`` field pointing at the
|
|
12
|
+
sibling bundle by URL; the two are peer catalog entries rather than
|
|
13
|
+
one nested under the other, so a nbdboot-only workflow can fetch a
|
|
14
|
+
bundle standalone and never touch a disk image.
|
|
15
|
+
|
|
16
|
+
There is ONE verb: :func:`pixie.catalog.fetch.fetch`. Downloads +
|
|
17
|
+
sha256s the bytes; if the entry's ``format`` is ``tar.gz``, additionally
|
|
18
|
+
unpacks vmlinuz + initrd + manifest.json into
|
|
19
|
+
``<state_dir>/artifacts/<content-sha256>/``. Presence on disk IS
|
|
20
|
+
readiness; no ready/pending vocabulary, no auto-fetch, no misses page.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from importlib.resources import files
|
|
26
|
+
|
|
27
|
+
# Default "Import catalog" + live-env TUI source. Points at PIXIE's own
|
|
28
|
+
# release copy of the curated catalog (a subset of nosi's, restricted to
|
|
29
|
+
# the netboot-capable images pixie tests + supports), NOT the upstream
|
|
30
|
+
# nosi catalog. Operators can still import the full nosi catalog by URL;
|
|
31
|
+
# this is just the convenience default.
|
|
32
|
+
DEFAULT_CATALOG_URL = "https://github.com/safl/pixie/releases/latest/download/catalog.toml"
|
|
33
|
+
|
|
34
|
+
# The same curated catalog shipped INSIDE the package, used to seed a
|
|
35
|
+
# fresh (empty) catalog on first start so a plain deploy comes up with
|
|
36
|
+
# the known-good set offline -- no network, no release dependency.
|
|
37
|
+
BUNDLED_CATALOG_RESOURCE = "catalog.toml"
|
|
38
|
+
|
|
39
|
+
# Startup seeding is gated on this env (default on). Tests + operators
|
|
40
|
+
# who want an empty catalog set it to ``0``. A one-shot settings marker
|
|
41
|
+
# (below) records that the seed already ran so a later restart never
|
|
42
|
+
# re-seeds after an operator curated the catalog down.
|
|
43
|
+
SEED_CATALOG_ENV = "PIXIE_SEED_CATALOG"
|
|
44
|
+
CATALOG_SEEDED_KEY = "catalog.seeded"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def bundled_catalog_bytes() -> bytes:
|
|
48
|
+
"""The curated ``catalog.toml`` shipped inside the package."""
|
|
49
|
+
return (files("pixie.catalog") / BUNDLED_CATALOG_RESOURCE).read_bytes()
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""Fetch + stage the pixie live-env (the netboot-pc bake).
|
|
2
|
+
|
|
3
|
+
The live env -- ``vmlinuz`` + ``initrd`` + ``live.squashfs`` that the
|
|
4
|
+
``pixie-flash-*`` / ``pixie-inventory`` / ``pixie-tui`` boot modes chain
|
|
5
|
+
into -- was the one artifact pixie could not retrieve itself: it had to
|
|
6
|
+
be baked locally (``make build VARIANT=netboot-pc``) or hand-copied into
|
|
7
|
+
``PIXIE_LIVE_ENV_DIR``. This module pulls it from a single tarball
|
|
8
|
+
``src`` (the same ``https://`` / ``oras://`` schemes the catalog fetch
|
|
9
|
+
speaks) and stages the three files atomically, reusing the catalog
|
|
10
|
+
fetch pipeline's curl download + resume plumbing.
|
|
11
|
+
|
|
12
|
+
Contract with CI's ``publish-release`` job: the tarball carries exactly
|
|
13
|
+
``vmlinuz`` + ``initrd`` + ``live.squashfs`` at the archive root. Any
|
|
14
|
+
other member is ignored; a missing one is a hard error (better a loud
|
|
15
|
+
"tarball is wrong" than a live env that half-stages and boots into a
|
|
16
|
+
mysterious squashfs-fetch hang).
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import os
|
|
22
|
+
import shutil
|
|
23
|
+
import tarfile
|
|
24
|
+
import tempfile
|
|
25
|
+
from dataclasses import dataclass, field
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
|
|
28
|
+
from pixie._util import CHUNK
|
|
29
|
+
from pixie.catalog._fetcher import (
|
|
30
|
+
FetchError,
|
|
31
|
+
ProgressReporter,
|
|
32
|
+
_resolve_fetch_url,
|
|
33
|
+
_stream_to_tmpfile,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# The three files a target's iPXE chain pulls from
|
|
37
|
+
# ``/boot/pixie-live-env/``. Names match what ``pixie-live-env.j2``
|
|
38
|
+
# references (note ``live.squashfs``, not the bake's raw ``*.squashfs``
|
|
39
|
+
# -- the CI tar step renames it).
|
|
40
|
+
LIVE_ENV_FILES: frozenset[str] = frozenset({"vmlinuz", "initrd", "live.squashfs"})
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass
|
|
44
|
+
class LiveEnvResult:
|
|
45
|
+
"""Outcome of a successful stage: the src it came from, the sha256
|
|
46
|
+
of the downloaded tarball, its byte size, and the staged file
|
|
47
|
+
sizes."""
|
|
48
|
+
|
|
49
|
+
src: str
|
|
50
|
+
sha256: str
|
|
51
|
+
size: int
|
|
52
|
+
files: dict[str, int] = field(default_factory=dict)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _unpack_live_env_tar(tar_path: Path, live_env_dir: Path) -> dict[str, int]:
|
|
56
|
+
"""Extract the live-env trio from ``tar_path`` into ``live_env_dir``
|
|
57
|
+
atomically. Returns ``{name: size_bytes}``.
|
|
58
|
+
|
|
59
|
+
Hardening mirrors :func:`pixie.catalog._fetcher._unpack_netboot_bundle`:
|
|
60
|
+
only basenames in :data:`LIVE_ENV_FILES` at the archive root are
|
|
61
|
+
accepted; nested paths, parent traversal, and dotfiles are dropped.
|
|
62
|
+
Files land in a staging subdir first, then each is ``os.replace``'d
|
|
63
|
+
onto its final name so a target fetching mid-stage sees the old
|
|
64
|
+
file or the new one, never a half-written squashfs.
|
|
65
|
+
"""
|
|
66
|
+
live_env_dir.mkdir(parents=True, exist_ok=True)
|
|
67
|
+
staging = Path(tempfile.mkdtemp(prefix=".staging-", dir=str(live_env_dir)))
|
|
68
|
+
try:
|
|
69
|
+
# ``r:*`` transparently handles .tar / .tar.gz / .tar.xz so the
|
|
70
|
+
# CI side can pick whatever compression without a pixie change.
|
|
71
|
+
with tarfile.open(str(tar_path), mode="r:*") as tar:
|
|
72
|
+
for member in tar.getmembers():
|
|
73
|
+
if not member.isfile():
|
|
74
|
+
continue
|
|
75
|
+
name = os.path.basename(member.name)
|
|
76
|
+
if not name or name.startswith(".") or name != member.name:
|
|
77
|
+
continue
|
|
78
|
+
if name not in LIVE_ENV_FILES:
|
|
79
|
+
continue
|
|
80
|
+
extracted = tar.extractfile(member)
|
|
81
|
+
if extracted is None:
|
|
82
|
+
continue
|
|
83
|
+
with (staging / name).open("wb") as out:
|
|
84
|
+
shutil.copyfileobj(extracted, out, length=CHUNK)
|
|
85
|
+
|
|
86
|
+
missing = LIVE_ENV_FILES - {p.name for p in staging.iterdir()}
|
|
87
|
+
if missing:
|
|
88
|
+
raise FetchError(
|
|
89
|
+
f"live-env tarball {tar_path.name} missing required file(s): {sorted(missing)}"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
sizes: dict[str, int] = {}
|
|
93
|
+
for name in sorted(LIVE_ENV_FILES):
|
|
94
|
+
final = live_env_dir / name
|
|
95
|
+
os.replace(staging / name, final)
|
|
96
|
+
sizes[name] = final.stat().st_size
|
|
97
|
+
return sizes
|
|
98
|
+
finally:
|
|
99
|
+
shutil.rmtree(staging, ignore_errors=True)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def stage_live_env(
|
|
103
|
+
src: str,
|
|
104
|
+
live_env_dir: Path,
|
|
105
|
+
*,
|
|
106
|
+
progress: ProgressReporter = None,
|
|
107
|
+
) -> LiveEnvResult:
|
|
108
|
+
"""Download the live-env tarball at ``src`` and stage its three
|
|
109
|
+
files into ``live_env_dir``.
|
|
110
|
+
|
|
111
|
+
Reuses the catalog fetch's curl transport (resume + retry + stall
|
|
112
|
+
detection). The tarball lands in ``live_env_dir`` itself so the
|
|
113
|
+
unpack + ``os.replace`` stay on one filesystem. Raises
|
|
114
|
+
:class:`FetchError` on an empty/bad src, an unsupported scheme, a
|
|
115
|
+
download failure, or a tarball missing a required file.
|
|
116
|
+
"""
|
|
117
|
+
if not (src or "").strip():
|
|
118
|
+
raise FetchError("no live-env src configured (set PIXIE_LIVE_ENV_SRC)")
|
|
119
|
+
url, headers = _resolve_fetch_url(src.strip())
|
|
120
|
+
live_env_dir.mkdir(parents=True, exist_ok=True)
|
|
121
|
+
tmp_tar, sha256, size = _stream_to_tmpfile(url, headers, live_env_dir, progress)
|
|
122
|
+
try:
|
|
123
|
+
if progress is not None:
|
|
124
|
+
progress({"phase": "unpacking"})
|
|
125
|
+
sizes = _unpack_live_env_tar(tmp_tar, live_env_dir)
|
|
126
|
+
finally:
|
|
127
|
+
tmp_tar.unlink(missing_ok=True)
|
|
128
|
+
return LiveEnvResult(src=src.strip(), sha256=sha256, size=size, files=sizes)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
|
|
3
|
+
# pixie curated catalog -- a strict SUBSET of the upstream nosi catalog
|
|
4
|
+
# (https://github.com/safl/nosi/releases/latest/download/catalog.toml),
|
|
5
|
+
# restricted to the images that ship a netboot bundle. Those are the
|
|
6
|
+
# only images pixie's nbdboot chain (and the flash / inventory / tui
|
|
7
|
+
# live-env chains that ride the same bundle) actually test + support,
|
|
8
|
+
# so shipping just this subset keeps a fresh pixie's catalog to the
|
|
9
|
+
# known-good set instead of the full nosi menu (desktop / proxmox /
|
|
10
|
+
# rpios / freebsd variants have no netboot bundle and are omitted).
|
|
11
|
+
#
|
|
12
|
+
# Pixie seeds a fresh (empty) catalog from this file on first start and
|
|
13
|
+
# defaults its "Import catalog" + live-env TUI to the pixie release copy
|
|
14
|
+
# of it, rather than the nosi catalog. Override either freely; this is a
|
|
15
|
+
# convenience default, not a lock-in.
|
|
16
|
+
#
|
|
17
|
+
# Refs use the rolling ``:latest`` oras tags so the shipped catalog
|
|
18
|
+
# stays current without re-releasing pixie; the layer digest is still
|
|
19
|
+
# verified at fetch time. Each disk image cross-references its bundle by
|
|
20
|
+
# URL via ``netboot_src`` (pixie's tight form), so the nbdboot renderer
|
|
21
|
+
# resolves the pair without the legacy name-string ``netboot_ref``.
|
|
22
|
+
|
|
23
|
+
[[images]]
|
|
24
|
+
name = "nosi debian-13-headless"
|
|
25
|
+
src = "oras://ghcr.io/safl/nosi/debian-13-headless:latest"
|
|
26
|
+
format = "img.gz"
|
|
27
|
+
arch = "x86_64"
|
|
28
|
+
description = "Debian 13 (trixie) headless. General-purpose headless base with the nosi dev toolset."
|
|
29
|
+
netboot_src = "oras://ghcr.io/safl/nosi/debian-13-headless-netboot:latest"
|
|
30
|
+
|
|
31
|
+
[[images]]
|
|
32
|
+
name = "nosi debian-13-headless netboot bundle"
|
|
33
|
+
src = "oras://ghcr.io/safl/nosi/debian-13-headless-netboot:latest"
|
|
34
|
+
format = "tar.gz"
|
|
35
|
+
arch = "x86_64"
|
|
36
|
+
description = "Netboot bundle for debian-13-headless: vmlinuz + initrd so pixie can nbdboot it over NBD."
|
|
37
|
+
|
|
38
|
+
[[images]]
|
|
39
|
+
name = "nosi ubuntu-2404-headless"
|
|
40
|
+
src = "oras://ghcr.io/safl/nosi/ubuntu-2404-headless:latest"
|
|
41
|
+
format = "img.gz"
|
|
42
|
+
arch = "x86_64"
|
|
43
|
+
description = "Ubuntu 24.04 LTS (noble) headless. Broad driver support for CUDA / ROCm devices and Mellanox NICs / DPUs."
|
|
44
|
+
netboot_src = "oras://ghcr.io/safl/nosi/ubuntu-2404-headless-netboot:latest"
|
|
45
|
+
|
|
46
|
+
[[images]]
|
|
47
|
+
name = "nosi ubuntu-2404-headless netboot bundle"
|
|
48
|
+
src = "oras://ghcr.io/safl/nosi/ubuntu-2404-headless-netboot:latest"
|
|
49
|
+
format = "tar.gz"
|
|
50
|
+
arch = "x86_64"
|
|
51
|
+
description = "Netboot bundle for ubuntu-2404-headless: vmlinuz + initrd so pixie can nbdboot it over NBD."
|
|
52
|
+
|
|
53
|
+
[[images]]
|
|
54
|
+
name = "nosi ubuntu-2604-headless"
|
|
55
|
+
src = "oras://ghcr.io/safl/nosi/ubuntu-2604-headless:latest"
|
|
56
|
+
format = "img.gz"
|
|
57
|
+
arch = "x86_64"
|
|
58
|
+
description = "Ubuntu 26.04 LTS (resolute) headless. A more recent kernel and user-land on Ubuntu LTS."
|
|
59
|
+
netboot_src = "oras://ghcr.io/safl/nosi/ubuntu-2604-headless-netboot:latest"
|
|
60
|
+
|
|
61
|
+
[[images]]
|
|
62
|
+
name = "nosi ubuntu-2604-headless netboot bundle"
|
|
63
|
+
src = "oras://ghcr.io/safl/nosi/ubuntu-2604-headless-netboot:latest"
|
|
64
|
+
format = "tar.gz"
|
|
65
|
+
arch = "x86_64"
|
|
66
|
+
description = "Netboot bundle for ubuntu-2604-headless: vmlinuz + initrd so pixie can nbdboot it over NBD."
|
|
67
|
+
|
|
68
|
+
[[images]]
|
|
69
|
+
name = "nosi fedora-44-headless"
|
|
70
|
+
src = "oras://ghcr.io/safl/nosi/fedora-44-headless:latest"
|
|
71
|
+
format = "img.gz"
|
|
72
|
+
arch = "x86_64"
|
|
73
|
+
description = "Fedora 44 headless. An RHEL-family alternative (dnf, SELinux, EL package universe)."
|
|
74
|
+
netboot_src = "oras://ghcr.io/safl/nosi/fedora-44-headless-netboot:latest"
|
|
75
|
+
|
|
76
|
+
[[images]]
|
|
77
|
+
name = "nosi fedora-44-headless netboot bundle"
|
|
78
|
+
src = "oras://ghcr.io/safl/nosi/fedora-44-headless-netboot:latest"
|
|
79
|
+
format = "tar.gz"
|
|
80
|
+
arch = "x86_64"
|
|
81
|
+
description = "Netboot bundle for fedora-44-headless: vmlinuz + initrd so pixie can nbdboot it over NBD."
|
|
@@ -193,6 +193,24 @@ EVENTS_CLEARED = "events.cleared"
|
|
|
193
193
|
right after the wipe so the freshly-empty log still records who reset
|
|
194
194
|
it and when; carries the deleted-row count in ``details``."""
|
|
195
195
|
|
|
196
|
+
# ---------- live-env fetch ------------------------------------------
|
|
197
|
+
#
|
|
198
|
+
# The operator "Fetch live-env" action pulls the netboot-pc bake into
|
|
199
|
+
# PIXIE_LIVE_ENV_DIR. No subject (``subject_kind`` = ""): the live env
|
|
200
|
+
# is per-pixie, not per-resource. Dotted ``.done`` / ``.failed`` names
|
|
201
|
+
# mirror the catalog-fetch kinds so ``.failed`` auto-classifies as an
|
|
202
|
+
# error via the ERROR_KINDS ``LIKE '%.failed'`` probe.
|
|
203
|
+
|
|
204
|
+
LIVE_ENV_FETCH_DONE = "live_env.fetch.done"
|
|
205
|
+
"""``POST /ui/live-env/fetch`` downloaded + staged vmlinuz + initrd +
|
|
206
|
+
live.squashfs into PIXIE_LIVE_ENV_DIR. Carries the src + content sha in
|
|
207
|
+
``details``."""
|
|
208
|
+
|
|
209
|
+
LIVE_ENV_FETCH_FAILED = "live_env.fetch.failed"
|
|
210
|
+
"""The live-env fetch failed (bad src scheme, download error, or a
|
|
211
|
+
tarball missing a required file). Carries the src + error in
|
|
212
|
+
``details``."""
|
|
213
|
+
|
|
196
214
|
|
|
197
215
|
# The canonical closed set. Every kind above is registered here; the
|
|
198
216
|
# ``EventsLog.emit`` call rejects anything not in this frozenset.
|
|
@@ -228,6 +246,8 @@ KNOWN_EVENT_KINDS: frozenset[str] = frozenset(
|
|
|
228
246
|
AUTH_LOGIN_SUCCEEDED,
|
|
229
247
|
AUTH_LOGIN_FAILED,
|
|
230
248
|
EVENTS_CLEARED,
|
|
249
|
+
LIVE_ENV_FETCH_DONE,
|
|
250
|
+
LIVE_ENV_FETCH_FAILED,
|
|
231
251
|
}
|
|
232
252
|
)
|
|
233
253
|
|
|
@@ -328,9 +328,11 @@ def collect_lshw(*, timeout: float = 30.0) -> object | None:
|
|
|
328
328
|
# v0.46 stopped publishing a pixie-side catalog.toml mirror and pointed
|
|
329
329
|
# pixie at the upstream image-builder (``safl/nosi``); the wizard's
|
|
330
330
|
# ``[d] default`` shortcut tracks the same source so both consumers
|
|
331
|
-
# resolve to one catalog.
|
|
332
|
-
#
|
|
333
|
-
|
|
331
|
+
# resolve to one catalog. Points at pixie's curated catalog (the
|
|
332
|
+
# netboot-capable nosi subset) shipped as a pixie release asset, so the
|
|
333
|
+
# live-env wizard defaults to the same known-good set the appliance
|
|
334
|
+
# seeds -- not the full upstream nosi catalog.
|
|
335
|
+
_BTY_DEFAULT_CATALOG_URL = "https://github.com/safl/pixie/releases/latest/download/catalog.toml"
|
|
334
336
|
|
|
335
337
|
|
|
336
338
|
# ---------------------------------------------------------------------------
|