diff --git a/.github/workflows/publish-asterinas-kata-image.yml b/.github/workflows/publish-asterinas-kata-image.yml index 41848ee647..75f198eb79 100644 --- a/.github/workflows/publish-asterinas-kata-image.yml +++ b/.github/workflows/publish-asterinas-kata-image.yml @@ -39,6 +39,7 @@ jobs: docker_image_version: ${{ steps.resolve.outputs.docker_image_version }} kata_static_tarball_release_repo: ${{ steps.resolve.outputs.kata_static_tarball_release_repo }} kata_static_tarball_url: ${{ steps.resolve.outputs.kata_static_tarball_url }} + kata_static_tarball_sha256: ${{ steps.resolve.outputs.kata_static_tarball_sha256 }} should_push: ${{ steps.resolve.outputs.should_push }} steps: - name: Resolve Publish Inputs @@ -67,6 +68,27 @@ jobs: image_repository="${WORKFLOW_IMAGE_REPOSITORY:-${DEFAULT_IMAGE_REPOSITORY}}" kata_static_tarball_release_repo="${WORKFLOW_RELEASE_REPO:-${GITHUB_REPOSITORY}}" kata_static_tarball_url="${WORKFLOW_STATIC_TARBALL_URL:-}" + kata_static_tarball_sha256= + if [ -z "${kata_static_tarball_url}" ]; then + kata_static_tarball_url="$( + gh api "repos/${kata_static_tarball_release_repo}/releases/latest" --jq ' + .assets[] + | select(.name | test("^kata-static-.*-asterinas-amd64\\.tar\\.zst$")) + | .browser_download_url + ' | head -n 1 + )" + fi + test -n "${kata_static_tarball_url}" + kata_static_tarball_name="${kata_static_tarball_url##*/}" + kata_static_tarball_sha256="$( + gh api "repos/${kata_static_tarball_release_repo}/releases/latest" --jq ' + .assets[] + | select(.name | test("^kata-static-.*-asterinas-amd64\\.SHA256SUMS$")) + | .browser_download_url + ' | head -n 1 | + xargs curl -fsSL | + awk -v asset_name="${kata_static_tarball_name}" '$2 == asset_name || $2 ~ ("/" asset_name "$") { print $1; exit }' + )" should_push=false if [ -n "${DOCKERHUB_USERNAME}" ] && [ -n "${DOCKERHUB_TOKEN}" ]; then @@ -84,6 +106,7 @@ jobs: echo "docker_image_version=${docker_image_version}" >> "${GITHUB_OUTPUT}" echo "kata_static_tarball_release_repo=${kata_static_tarball_release_repo}" >> "${GITHUB_OUTPUT}" echo "kata_static_tarball_url=${kata_static_tarball_url}" >> "${GITHUB_OUTPUT}" + echo "kata_static_tarball_sha256=${kata_static_tarball_sha256}" >> "${GITHUB_OUTPUT}" echo "should_push=${should_push}" >> "${GITHUB_OUTPUT}" { @@ -99,6 +122,7 @@ jobs: else echo "- Explicit Kata tarball URL: not set" fi + echo "- Kata tarball SHA256: \`${kata_static_tarball_sha256}\`" echo "- Push enabled: \`${should_push}\`" } >> "${GITHUB_STEP_SUMMARY}" @@ -145,6 +169,7 @@ jobs: ASTERINAS_BASE_IMAGE=${{ env.ASTERINAS_BASE_IMAGE }} KATA_STATIC_TARBALL_RELEASE_REPO=${{ needs.resolve-upstream-asterinas-image.outputs.kata_static_tarball_release_repo }} KATA_STATIC_TARBALL_URL=${{ needs.resolve-upstream-asterinas-image.outputs.kata_static_tarball_url }} + KATA_STATIC_TARBALL_SHA256=${{ needs.resolve-upstream-asterinas-image.outputs.kata_static_tarball_sha256 }} ASTERINAS_RELEASE_VERSION=${{ needs.resolve-upstream-asterinas-image.outputs.asterinas_version }} ASTERINAS_DOCKER_IMAGE_VERSION=${{ needs.resolve-upstream-asterinas-image.outputs.docker_image_version }} diff --git a/.github/workflows/release-asterinas-kata-bundle.yml b/.github/workflows/release-asterinas-kata-bundle.yml index 55e8cccc15..4472bf3c88 100644 --- a/.github/workflows/release-asterinas-kata-bundle.yml +++ b/.github/workflows/release-asterinas-kata-bundle.yml @@ -59,6 +59,8 @@ jobs: build-asterinas-kernel: name: Build Asterinas kernel artifact runs-on: ubuntu-22.04 + outputs: + asterinas_commit: ${{ steps.asterinas_commit.outputs.value }} container: image: ${{ inputs.asterinas_builder_image || 'asterinas/asterinas:0.17.1-20260319' }} steps: @@ -69,6 +71,13 @@ jobs: ref: ${{ env.ASTERINAS_REF }} path: asterinas + - name: Record Asterinas Commit + id: asterinas_commit + shell: bash + run: | + set -euo pipefail + echo "value=$(git -C asterinas rev-parse HEAD)" >> "${GITHUB_OUTPUT}" + - name: Build qemu-direct Kernels shell: bash run: | @@ -153,6 +162,7 @@ jobs: ASTERINAS_TDX_KERNEL: ${{ github.workspace }}/build/asterinas-kernel/aster-kernel-osdk-bin.qemu_elf-tdx ASTERINAS_REPOSITORY: ${{ env.ASTERINAS_REPOSITORY }} ASTERINAS_REF: ${{ env.ASTERINAS_REF }} + ASTERINAS_COMMIT: ${{ needs.build-asterinas-kernel.outputs.asterinas_commit }} ASTERINAS_BUILDER_IMAGE: ${{ env.ASTERINAS_BUILDER_IMAGE }} FORCE_RUNTIME_BUILD: ${{ env.FORCE_RUNTIME_BUILD }} KATA_STATIC_RELEASE_REPOSITORY: ${{ env.KATA_STATIC_RELEASE_REPOSITORY }} diff --git a/.github/workflows/test-asterinas-kata-docs.yml b/.github/workflows/test-asterinas-kata-docs.yml new file mode 100644 index 0000000000..c5f451182a --- /dev/null +++ b/.github/workflows/test-asterinas-kata-docs.yml @@ -0,0 +1,202 @@ +name: Test | Asterinas Kata Docs + +on: + workflow_dispatch: + push: + branches: + - asterinas + +permissions: + contents: read + +env: + ASTERINAS_REPOSITORY: jjf-dev/asterinas + ASTERINAS_REF: kata-support + +jobs: + resolve-upstream-asterinas-image: + name: Resolve upstream Asterinas image + runs-on: ubuntu-latest + outputs: + asterinas_version: ${{ steps.resolve.outputs.asterinas_version }} + docker_image_version: ${{ steps.resolve.outputs.docker_image_version }} + kata_static_tarball_url: ${{ steps.resolve.outputs.kata_static_tarball_url }} + kata_static_tarball_sha256: ${{ steps.resolve.outputs.kata_static_tarball_sha256 }} + steps: + - name: Resolve Upstream Asterinas Image Metadata + id: resolve + env: + GH_TOKEN: ${{ github.token }} + shell: bash + run: | + set -euo pipefail + + asterinas_version="$( + gh api repos/asterinas/asterinas/contents/VERSION?ref=main --jq .content | + base64 -d | tr -d '\n' + )" + docker_image_version="$( + gh api repos/asterinas/asterinas/contents/DOCKER_IMAGE_VERSION?ref=main --jq .content | + base64 -d | tr -d '\n' + )" + kata_static_tarball_url="$( + gh api "repos/${GITHUB_REPOSITORY}/releases/latest" --jq ' + .assets[] + | select(.name | test("^kata-static-.*-asterinas-amd64\\.tar\\.zst$")) + | .browser_download_url + ' | head -n 1 + )" + test -n "${kata_static_tarball_url}" + kata_static_tarball_name="${kata_static_tarball_url##*/}" + kata_static_tarball_sha256="$( + gh api "repos/${GITHUB_REPOSITORY}/releases/latest" --jq ' + .assets[] + | select(.name | test("^kata-static-.*-asterinas-amd64\\.SHA256SUMS$")) + | .browser_download_url + ' | head -n 1 | + xargs curl -fsSL | + awk -v asset_name="${kata_static_tarball_name}" '$2 == asset_name || $2 ~ ("/" asset_name "$") { print $1; exit }' + )" + test -n "${asterinas_version}" + test -n "${docker_image_version}" + test -n "${kata_static_tarball_sha256}" + + echo "asterinas_version=${asterinas_version}" >> "${GITHUB_OUTPUT}" + echo "docker_image_version=${docker_image_version}" >> "${GITHUB_OUTPUT}" + echo "kata_static_tarball_url=${kata_static_tarball_url}" >> "${GITHUB_OUTPUT}" + echo "kata_static_tarball_sha256=${kata_static_tarball_sha256}" >> "${GITHUB_OUTPUT}" + { + echo '## Resolved upstream Asterinas image' + echo + echo "- \`VERSION\`: \`${asterinas_version}\`" + echo "- \`DOCKER_IMAGE_VERSION\`: \`${docker_image_version}\`" + echo "- Base image: \`asterinas/asterinas:${docker_image_version}\`" + echo "- Kata static tarball: \`${kata_static_tarball_url}\`" + } >> "${GITHUB_STEP_SUMMARY}" + + test-documented-end-user-flow: + name: Test documented end-user flow + needs: + - resolve-upstream-asterinas-image + runs-on: ubuntu-latest + timeout-minutes: 120 + env: + KATA_DOC_LOG_DIR: /tmp/asterinas-kata-doc-logs/end-user + steps: + - uses: actions/checkout@v4 + + - name: Check Host Device Visibility + shell: bash + run: | + set -euxo pipefail + ls -l /dev/kvm /dev/vhost-net /dev/vhost-vsock + ls -l /dev/vsock || true + + - name: Install pexpect if Needed + shell: bash + run: | + set -euxo pipefail + if ! python3 - <<'PY' + import importlib.util + import sys + sys.exit(0 if importlib.util.find_spec("pexpect") else 1) + PY + then + python3 -m pip install --user pexpect + fi + + - name: Pull Published Asterinas Kata Image + shell: bash + run: | + set -euxo pipefail + docker pull "asterinas/kata:${{ needs.resolve-upstream-asterinas-image.outputs.docker_image_version }}" + + - name: Replay Documented End-User Flow + shell: bash + run: | + set -euxo pipefail + python3 -u tools/kata/interactive_doc_test.py \ + --scenario end-user \ + --kata-image "asterinas/kata:${{ needs.resolve-upstream-asterinas-image.outputs.docker_image_version }}" \ + --log-dir "${KATA_DOC_LOG_DIR}" + + - name: Upload End-User Flow Logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: asterinas-kata-doc-end-user-logs + path: ${{ env.KATA_DOC_LOG_DIR }} + if-no-files-found: ignore + + test-documented-kernel-developer-flow: + name: Test documented kernel-developer flow + needs: + - resolve-upstream-asterinas-image + runs-on: ubuntu-latest + timeout-minutes: 180 + env: + KATA_DOC_LOG_DIR: /tmp/asterinas-kata-doc-logs/kernel-developer + KATA_STATIC_TARBALL_RELEASE_REPO: ${{ github.repository }} + KATA_STATIC_TARBALL_URL: ${{ needs.resolve-upstream-asterinas-image.outputs.kata_static_tarball_url }} + KATA_STATIC_TARBALL_SHA256: ${{ needs.resolve-upstream-asterinas-image.outputs.kata_static_tarball_sha256 }} + steps: + - uses: actions/checkout@v4 + + - name: Check Out Asterinas Source + uses: actions/checkout@v4 + with: + repository: ${{ env.ASTERINAS_REPOSITORY }} + ref: ${{ env.ASTERINAS_REF }} + path: asterinas-src + + - name: Prepare Local Asterinas Tree + shell: bash + run: | + set -euxo pipefail + rm -rf "${HOME}/asterinas" + mkdir -p "${HOME}/asterinas" + rsync -a --delete "${GITHUB_WORKSPACE}/asterinas-src/" "${HOME}/asterinas/" + + - name: Check Host Device Visibility + shell: bash + run: | + set -euxo pipefail + ls -l /dev/kvm /dev/vhost-net /dev/vhost-vsock + ls -l /dev/vsock || true + + - name: Install pexpect if Needed + shell: bash + run: | + set -euxo pipefail + if ! python3 - <<'PY' + import importlib.util + import sys + sys.exit(0 if importlib.util.find_spec("pexpect") else 1) + PY + then + python3 -m pip install --user pexpect + fi + + - name: Pull Published Asterinas Builder Image + shell: bash + run: | + set -euxo pipefail + docker pull "asterinas/asterinas:${{ needs.resolve-upstream-asterinas-image.outputs.docker_image_version }}" + + - name: Replay Documented Kernel-Developer Flow + shell: bash + run: | + set -euxo pipefail + python3 -u tools/kata/interactive_doc_test.py \ + --scenario kernel-developer \ + --asterinas-image "asterinas/asterinas:${{ needs.resolve-upstream-asterinas-image.outputs.docker_image_version }}" \ + --asterinas-dir "${HOME}/asterinas" \ + --log-dir "${KATA_DOC_LOG_DIR}" + + - name: Upload Kernel-Developer Flow Logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: asterinas-kata-doc-kernel-developer-logs + path: ${{ env.KATA_DOC_LOG_DIR }} + if-no-files-found: ignore diff --git a/.github/workflows/test-asterinas-kata.yml b/.github/workflows/test-asterinas-kata.yml index b2dc0f6186..33d443676c 100644 --- a/.github/workflows/test-asterinas-kata.yml +++ b/.github/workflows/test-asterinas-kata.yml @@ -20,6 +20,8 @@ jobs: outputs: asterinas_version: ${{ steps.resolve.outputs.asterinas_version }} docker_image_version: ${{ steps.resolve.outputs.docker_image_version }} + kata_static_tarball_url: ${{ steps.resolve.outputs.kata_static_tarball_url }} + kata_static_tarball_sha256: ${{ steps.resolve.outputs.kata_static_tarball_sha256 }} steps: - name: Resolve Upstream Asterinas Image Metadata id: resolve @@ -37,17 +39,39 @@ jobs: gh api repos/asterinas/asterinas/contents/DOCKER_IMAGE_VERSION?ref=main --jq .content | base64 -d | tr -d '\n' )" + kata_static_tarball_url="$( + gh api "repos/${GITHUB_REPOSITORY}/releases/latest" --jq ' + .assets[] + | select(.name | test("^kata-static-.*-asterinas-amd64\\.tar\\.zst$")) + | .browser_download_url + ' | head -n 1 + )" + test -n "${kata_static_tarball_url}" + kata_static_tarball_name="${kata_static_tarball_url##*/}" + kata_static_tarball_sha256="$( + gh api "repos/${GITHUB_REPOSITORY}/releases/latest" --jq ' + .assets[] + | select(.name | test("^kata-static-.*-asterinas-amd64\\.SHA256SUMS$")) + | .browser_download_url + ' | head -n 1 | + xargs curl -fsSL | + awk -v asset_name="${kata_static_tarball_name}" '$2 == asset_name || $2 ~ ("/" asset_name "$") { print $1; exit }' + )" test -n "${asterinas_version}" test -n "${docker_image_version}" + test -n "${kata_static_tarball_sha256}" echo "asterinas_version=${asterinas_version}" >> "${GITHUB_OUTPUT}" echo "docker_image_version=${docker_image_version}" >> "${GITHUB_OUTPUT}" + echo "kata_static_tarball_url=${kata_static_tarball_url}" >> "${GITHUB_OUTPUT}" + echo "kata_static_tarball_sha256=${kata_static_tarball_sha256}" >> "${GITHUB_OUTPUT}" { echo '## Resolved upstream Asterinas image' echo echo "- \`VERSION\`: \`${asterinas_version}\`" echo "- \`DOCKER_IMAGE_VERSION\`: \`${docker_image_version}\`" echo "- Base image: \`asterinas/asterinas:${docker_image_version}\`" + echo "- Kata static tarball: \`${kata_static_tarball_url}\`" } >> "${GITHUB_STEP_SUMMARY}" build-published-kata-image: @@ -88,6 +112,8 @@ jobs: build-args: | ASTERINAS_BASE_IMAGE=${{ env.ASTERINAS_BASE_IMAGE }} KATA_STATIC_TARBALL_RELEASE_REPO=${{ github.repository }} + KATA_STATIC_TARBALL_URL=${{ needs.resolve-upstream-asterinas-image.outputs.kata_static_tarball_url }} + KATA_STATIC_TARBALL_SHA256=${{ needs.resolve-upstream-asterinas-image.outputs.kata_static_tarball_sha256 }} ASTERINAS_RELEASE_VERSION=${{ needs.resolve-upstream-asterinas-image.outputs.asterinas_version }} ASTERINAS_DOCKER_IMAGE_VERSION=${{ needs.resolve-upstream-asterinas-image.outputs.docker_image_version }} @@ -119,6 +145,8 @@ jobs: KATA_GUEST_KERNEL: ${{ matrix.guest_kernel }} KATA_TEST_IMAGE_LOG_LABEL: ${{ matrix.image_variant == 'source' && 'base image / guest kernel' || 'test image / guest kernel' }} KATA_TEST_IMAGE_LOG_VALUE: ${{ matrix.image_variant == 'source' && format('asterinas/asterinas:{0} / {1}', needs.resolve-upstream-asterinas-image.outputs.docker_image_version, matrix.guest_kernel) || format('asterinas/kata:{0} / {1}', needs.resolve-upstream-asterinas-image.outputs.docker_image_version, matrix.guest_kernel) }} + KATA_STATIC_TARBALL_URL: ${{ needs.resolve-upstream-asterinas-image.outputs.kata_static_tarball_url }} + KATA_STATIC_TARBALL_SHA256: ${{ needs.resolve-upstream-asterinas-image.outputs.kata_static_tarball_sha256 }} defaults: run: shell: bash diff --git a/Cargo.toml b/Cargo.toml index b90eec9d52..beea39a10e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -139,7 +139,7 @@ slog-scope = "4.4.0" strum = { version = "0.24.0", features = ["derive"] } tempfile = "3.19.1" thiserror = "1.0" -tokio = "1.46.1" +tokio = "1.52.0" tracing = "0.1.41" tracing-opentelemetry = "0.18.0" ttrpc = "0.8.4" diff --git a/docs/asterinas-kata-doc-workflow-progress.md b/docs/asterinas-kata-doc-workflow-progress.md new file mode 100644 index 0000000000..278a037a29 --- /dev/null +++ b/docs/asterinas-kata-doc-workflow-progress.md @@ -0,0 +1,68 @@ +# Asterinas Kata Doc Workflow Progress + +## 2026-04-22 Initial implementation notes + +- Requirement focus: + - add a new workflow that follows `docs/doc-in-asterinas-repo.md` + - keep the overall documented flow, but correct commands that are currently off + - test the interactive `docker run -it` and inner `nerdctl run -it` behavior with `pexpect` + - mount the local Asterinas tree from `$HOME/asterinas` for the developer flow + - use local `asterinas/asterinas` and `asterinas/kata` images first, then wire the same logic into CI +- Document drift confirmed and corrected in the implementation plan: + - `docker run --cgroupns none` is invalid; use `--cgroupns host` + - the outer container needs `/dev/vhost-net` and `/dev/vsock` in addition to `/dev/kvm` and `/dev/vhost-vsock` + - helper script names are `tools/kata/kata_env.sh` and `tools/kata/kata_services.sh` + - the developer flow bind mount should be `-v "${ASTERINAS_SRC}:/root/asterinas"` + - the Kata config path should be `/etc/kata-containers/configuration.toml` +- Added `tools/kata/interactive_doc_test.py`: + - uses `pexpect` to drive the documented interactive flow instead of only calling the existing non-interactive smoke helper + - covers the end-user scenario on `asterinas/kata` + - covers the kernel-developer scenario on `asterinas/asterinas` + - validates the local kernel handoff path with `/root/asterinas/target/osdk/aster-kernel-osdk-bin.qemu_elf` +- Added `.github/workflows/test-asterinas-kata-docs.yml`: + - one job replays the documented end-user flow against `asterinas/kata` + - one job replays the documented kernel-developer flow against `asterinas/asterinas` + - both jobs install `pexpect` only when needed and upload transcripts as artifacts +- Local environment findings: + - `pexpect` is already available in the current local environment + - local `asterinas/asterinas:*` and `asterinas/kata:*` images are present + - the local Asterinas source tree exists at `/home/jianfeng/asterinas` + - the local machine exposes `/dev/kvm`, `/dev/vhost-net`, `/dev/vhost-vsock`, and `/dev/vsock` + - local Docker Hub access currently times out during the inner `nerdctl run` +- Local validation completed so far: + - the documented end-user flow passed locally with + `python3 tools/kata/interactive_doc_test.py --scenario end-user --workload-image docker.1ms.run/alpine:latest` + - this successfully covered the interactive outer `docker run -it`, `tools/kata/kata_services.sh start`, inner `nerdctl run -it`, and post-exit `nerdctl rm foo` sequence + - after cleaning the `pexpect` output parsing and passing outer env overrides explicitly, the same end-user replay was run again locally and still passed + - per the latest user instruction, the kernel-developer flow does not need to finish locally; CI is now the authoritative validation path for that scenario +- Local validation policy: + - local testing uses `docker.1ms.run/alpine:latest` as the workload image when Docker Hub is unreachable + - CI must keep using `docker.io/alpine:latest` +- CI wiring note: + - the kernel-developer workflow path exports `KATA_STATIC_TARBALL_RELEASE_REPO=${GITHUB_REPOSITORY}` so `tools/kata/kata_env.sh install` validates this repository's published Asterinas Kata release assets instead of defaulting to upstream `kata-containers/kata-containers` + - the first GitHub dispatch attempt exposed a GitHub expression-validation issue: `runner.temp` is not accepted in this workflow's job-level `env`, so the log directory paths were normalized to plain `/tmp/...` + - the first push run also showed that `/dev/vsock` is not guaranteed on GitHub-hosted runners, while `/dev/kvm`, `/dev/vhost-net`, and `/dev/vhost-vsock` are present; the workflow and `pexpect` driver now treat `/dev/vsock` as optional instead of mandatory + - based on user feedback, the `pexpect` driver now streams child output to stdout and prints explicit phase markers before long-running commands such as `kata_env.sh install`, `nerdctl run`, and `make kernel` + - the guest-entry helper now fails fast when `nerdctl run -it ...` falls back to the outer shell instead of opening the inner guest shell, so proxy/image failures no longer look like a generic hang + - CI logs showed the real long pole inside `tools/kata/kata_env.sh install`: the static tarball path unpacked into a temporary directory and then copied a second 4.7 GiB tree into `/opt`; this has now been collapsed into a direct `tar --zstd -xf ... -C / opt/kata` install path, with explicit progress messages around the install phases + - the next CI log sample exposed a follow-on bug in that optimization: the tarball did not contain a directly addressable `opt/kata` member for selective extraction, so the install now unpacks the verified tarball directly at `/` instead + - the latest CI round also exposed an unrelated but real stability issue in `Publish | Asterinas Kata Image`: the Docker build resolved the latest release URL from inside the container and hit unauthenticated GitHub API rate limits, so the workflows now resolve the tarball URL and SHA256 up front and pass them into the container explicitly + - after that pre-resolution change, the next push showed a format mismatch in the release `SHA256SUMS`: the checksum file records the tarball with a full path suffix instead of only the basename, so the workflow-side SHA lookup now accepts either an exact basename match or a trailing `/${asset_name}` + - configuration comparison result: before the local-kernel override, both the end-user flow and the kernel-developer flow start Kata from the same default config target, `/opt/kata/share/defaults/kata-containers/configuration.toml -> configuration-asterinas.toml` + - on interactive failures, `tools/kata/interactive_doc_test.py` now also dumps `/tmp/kata-console.log`, `/tmp/console.log`, `/tmp/kata-qemu-serial.log`, `/tmp/qemu-serial.log`, `/tmp/containerd.log`, and `/tmp/kata-syslog.log` so QEMU-side failures are visible immediately + - to keep the interactive developer replay within the expected post-install budget, the CI job now prebuilds the mounted `$HOME/asterinas` kernel once before invoking the `pexpect` driver; the driver still runs the documented `make kernel BOOT_METHOD=qemu-direct` command inside the container, but that command should now hit an already-built tree and return quickly + - a deeper replay hang was then traced to the Python driver itself rather than Kata: `DockerShell.run()` sent the target command, `status=$?`, and the exit-marker `printf` as three separate queued lines, which is fragile for long-running interactive commands. The driver now wraps each command and exit-marker emission into one shell line so it can no longer stall waiting for a marker that was never executed + - the newest transcript showed the remaining long pole after `kata_env.sh install`: the interactive `make kernel BOOT_METHOD=qemu-direct` reinitialized `/nix`, cargo, and rustup state inside the developer container. The workflow now prebuilds with shared cache mounts and passes the same cache mounts into the interactive container so the documented in-container `make kernel` can reuse the same build state + - the first cache-sharing attempt repeated the earlier workflow-expression mistake by putting `runner.temp` into job-level `env`; the cache directories are now normalized to plain `/tmp/asterinas-kernel-cache/...` + - a follow-up CI attempt showed that directly bind-mounting empty cache directories onto `/nix` and `/root/.cargo` hid the builder image's existing tooling (`nix-build`, `/root/.cargo/env`, etc.). The workflow now uses a safer prewarm approach instead: it prebuilds the kernel in a temporary container, commits that container to a local one-off image, and replays the documented interactive developer flow on top of that prewarmed image + - the first prewarmed-image replay then exposed one more subtle issue: `docker commit` preserved the prewarm container's running command, so the derived image no longer dropped into an interactive shell by default. The `pexpect` driver now explicitly appends `bash` when starting both the end-user and kernel-developer outer containers + - the latest developer replay reached the local-kernel launch stage and then timed out waiting for the guest agent after switching to `/root/asterinas/target/osdk/aster-kernel-osdk-bin.qemu_elf`. That CI path had been building the local kernel from upstream `asterinas/asterinas` `main`, which can drift from the published `asterinas/asterinas:` image and packaged Kata release. The next adjustment is to make the CI checkout use the matching upstream release tag `v${ASTERINAS_VERSION}` so the local source tree aligns with the image/runtime bundle it is being validated against + - user review corrected that assumption: the docs workflow should not use upstream `asterinas/asterinas` at all for the developer source tree. To stay aligned with the existing release workflow, it should use `jjf-dev/asterinas` on the `kata-support` branch + - user review also requested richer release notes: the Asterinas repo/ref line should include the resolved Asterinas commit id, and the release notes should explicitly name the kata-containers commit id as well + - the same release-asset pre-resolution fix also needs to be applied to `.github/workflows/test-asterinas-kata.yml`, because its published-image matrix still calls `tools/kata/kata_env.sh install` with only `KATA_STATIC_TARBALL_RELEASE_REPO`, which reintroduces GitHub API rate-limit failures inside the job container + - the latest kernel-developer replay with `jjf-dev/asterinas@kata-support` got through both the packaged-kernel run and the local-kernel run; the remaining failure was only the final cleanup command using a relative `./tools/kata/kata_services.sh stop` after the script had changed directory into `/root/asterinas`. That cleanup path is now switched to the absolute repo path under `/root/kata-containers/tools/kata/kata_services.sh` + - per latest review, the CI-only prewarm/prebuild shortcut has been removed from `.github/workflows/test-asterinas-kata-docs.yml` so the kernel-developer path now goes back to launching the documented `asterinas/asterinas` image directly during replay +- Next steps: + - run a final quick local end-user replay after the latest script cleanup + - static-check the new workflow and script changes + - push and wait for CI to verify both documented flows end to end diff --git a/docs/doc-in-asterinas-repo.md b/docs/doc-in-asterinas-repo.md new file mode 100644 index 0000000000..dc799ac9bc --- /dev/null +++ b/docs/doc-in-asterinas-repo.md @@ -0,0 +1,134 @@ +Kata Containers is a VM-based container runtime. Each container runs inside its own virtual machine, so containers do not share the host kernel. + +Asterinas now supports Kata Containers and can serve as the guest kernel in common Kata-based scenarios. + +## For End Users +For end users, we provide the `asterinas/kata` container image, which already includes the dependencies and scripts required by Kata. + +You can try it with the following command: + +```bash +ASTERINAS_IMAGE_TAG=0.17.2-20260407 +docker run --rm -it \ + --cgroupns host \ + --privileged \ + --device /dev/kvm \ + --device /dev/vhost-net \ + --device /dev/vhost-vsock \ + --tmpfs /tmp:exec,mode=1777,size=8g \ + --tmpfs /var/lib/containerd:exec,mode=755,size=8g \ + asterinas/kata:${ASTERINAS_IMAGE_TAG} +``` + +After entering the container, start the background services required by Kata. At the moment, these services are `containerd` and `syslogd`: + +```bash +tools/kata/kata_services.sh start +``` + +You can check their status with the following command to make sure they started successfully: + +```bash +tools/kata/kata_services.sh status +``` + +Then you can use `nerdctl` with Kata to start an Alpine container: + +```bash +nerdctl run \ + --cgroup-manager cgroupfs \ + --net none \ + --runtime io.containerd.kata.v2 \ + --name foo \ + -it \ + docker.io/alpine:latest +``` + +If Docker Hub is temporarily unreachable during local validation, you can use +`docker.1ms.run/alpine:latest` instead. CI should keep using +`docker.io/alpine:latest`. + +Once the container starts, you will be inside Alpine. You can run the following commands to verify that you are no longer in the host environment: + +```bash +cat /proc/version +cat /etc/alpine-release +``` + +After you exit the container, remove it with: + +```bash +nerdctl rm foo +``` + +## For Kernel Developers +Kernel developers typically use the `asterinas/asterinas` container image. When starting the container, you also need to pass the additional arguments required by Kata: + +```bash +ASTERINAS_IMAGE_TAG=0.17.2-20260407 +ASTERINAS_SRC=$HOME/asterinas +KATA_SRC=$(git rev-parse --show-toplevel) +docker run --rm -it \ + --cgroupns host \ + --privileged \ + --device /dev/kvm \ + --device /dev/vhost-net \ + --device /dev/vhost-vsock \ + --tmpfs /tmp:exec,mode=1777,size=8g \ + --tmpfs /var/lib/containerd:exec,mode=755,size=8g \ + -v "${ASTERINAS_SRC}:/root/asterinas" \ + -v "${KATA_SRC}:/root/kata-containers" \ + -w /root/kata-containers \ + asterinas/asterinas:${ASTERINAS_IMAGE_TAG} +``` + +After entering the container, you will already be in `/root/kata-containers`. +The examples below assume the current kata-containers checkout is mounted there, +and that the local Asterinas tree is mounted at `/root/asterinas`. + +```bash +pwd +``` + +This script installs the files, scripts, and configuration needed to run Kata. After that, you can test Kata in the same way as an end user: + +```bash +# Install all dependencies +tools/kata/kata_env.sh install + +# Start background services +tools/kata/kata_services.sh start + +nerdctl run \ + --cgroup-manager cgroupfs \ + --net none \ + --runtime io.containerd.kata.v2 \ + --name foo \ + -it \ + docker.io/alpine:latest +``` + +If Docker Hub is temporarily unreachable during local validation, you can use +`docker.1ms.run/alpine:latest` here as well. CI should keep using +`docker.io/alpine:latest`. + +If `/dev/vsock` also exists on your host, it is fine to pass it through too, +but the documented minimum setup only requires `/dev/kvm`, `/dev/vhost-net`, +and `/dev/vhost-vsock`. + +You can also point Kata to a locally built guest kernel. Edit +`/etc/kata-containers/configuration.toml` and set `kernel` to the path of your +local kernel image: + +```toml +[hypervisor.qemu] +kernel = "/root/asterinas/target/osdk/aster-kernel-osdk-bin.qemu_elf" +``` + +Build the kernel with: + +```bash +cd /root/asterinas && make kernel BOOT_METHOD=qemu-direct +``` + +Then start the container with `nerdctl` again, and Kata will boot using your local kernel. diff --git a/src/agent/Cargo.lock b/src/agent/Cargo.lock index c407a479b3..883e0a651e 100644 --- a/src/agent/Cargo.lock +++ b/src/agent/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.0" @@ -417,21 +408,6 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc17ab023b4091c10ff099f9deebaeeb59b5189df07e554c4fef042b70745d68" -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - [[package]] name = "base64" version = "0.13.1" @@ -694,7 +670,7 @@ dependencies = [ "js-sys", "num-traits", "wasm-bindgen", - "windows-link", + "windows-link 0.1.1", ] [[package]] @@ -1472,12 +1448,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "glob" version = "0.3.2" @@ -1896,17 +1866,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "io-uring" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" -dependencies = [ - "bitflags 2.9.0", - "cfg-if", - "libc", -] - [[package]] name = "iovec" version = "0.1.4" @@ -2198,9 +2157,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.172" +version = "0.2.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" [[package]] name = "libseccomp" @@ -2380,14 +2339,14 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2718,15 +2677,6 @@ dependencies = [ "bitflags 2.9.0", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "oci-spec" version = "0.8.1" @@ -3605,12 +3555,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - [[package]] name = "rustc_version" version = "0.4.1" @@ -4109,6 +4053,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -4406,29 +4360,26 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.46.1" +version = "1.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" dependencies = [ - "backtrace", "bytes 1.11.1", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", - "socket2 0.5.9", + "socket2 0.6.3", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", @@ -5052,6 +5003,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-registry" version = "0.4.0" @@ -5078,7 +5035,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" dependencies = [ - "windows-link", + "windows-link 0.1.1", ] [[package]] @@ -5087,7 +5044,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" dependencies = [ - "windows-link", + "windows-link 0.1.1", ] [[package]] @@ -5126,6 +5083,15 @@ dependencies = [ "windows-targets 0.53.2", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-targets" version = "0.48.5" diff --git a/src/agent/Cargo.toml b/src/agent/Cargo.toml index 2ca4b02fa8..58ad99f00b 100644 --- a/src/agent/Cargo.toml +++ b/src/agent/Cargo.toml @@ -35,7 +35,7 @@ async-recursion = "0.3.2" futures = "0.3.30" # Async runtime -tokio = { version = "1.46.1", features = ["full"] } +tokio = { version = "1.52.0", features = ["full"] } tokio-vsock = "0.3.4" netlink-sys = { version = "0.7.0", features = ["tokio_socket"] } diff --git a/src/tools/agent-ctl/Cargo.lock b/src/tools/agent-ctl/Cargo.lock index 1ee2e07c8c..d720e27ab3 100644 --- a/src/tools/agent-ctl/Cargo.lock +++ b/src/tools/agent-ctl/Cargo.lock @@ -23,15 +23,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "addr2line" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.0" @@ -340,21 +331,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "backtrace" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" -dependencies = [ - "addr2line", - "cfg-if 1.0.4", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-link", -] - [[package]] name = "base16ct" version = "0.2.0" @@ -1741,12 +1717,6 @@ dependencies = [ "polyval", ] -[[package]] -name = "gimli" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" - [[package]] name = "glob" version = "0.3.1" @@ -2363,17 +2333,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "io-uring" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" -dependencies = [ - "bitflags 2.6.0", - "cfg-if 1.0.4", - "libc", -] - [[package]] name = "ipnet" version = "2.10.1" @@ -2996,15 +2955,6 @@ dependencies = [ "bitflags 2.6.0", ] -[[package]] -name = "object" -version = "0.37.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" -dependencies = [ - "memchr", -] - [[package]] name = "ocb3" version = "0.1.0" @@ -4199,12 +4149,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - [[package]] name = "rustc-hash" version = "1.1.0" @@ -5267,29 +5211,26 @@ dependencies = [ [[package]] name = "tokio" -version = "1.47.1" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", "socket2 0.6.0", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", @@ -6046,6 +5987,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-targets" version = "0.42.2" diff --git a/src/tools/agent-ctl/Cargo.toml b/src/tools/agent-ctl/Cargo.toml index be2b65278b..ac61afa56c 100644 --- a/src/tools/agent-ctl/Cargo.toml +++ b/src/tools/agent-ctl/Cargo.toml @@ -55,7 +55,7 @@ hypervisor = { path = "../../runtime-rs/crates/hypervisor", features = [ kata-sys-util = { path = "../../libs/kata-sys-util" } safe-path = { path = "../../libs/safe-path" } -tokio = { version = "1.44.2", features = ["signal"] } +tokio = { version = "1.50.0", features = ["signal"] } [features] default = ["cloud-hypervisor"] diff --git a/src/tools/kata-ctl/Cargo.lock b/src/tools/kata-ctl/Cargo.lock index f9e6d7d6f5..5d6ea14412 100644 --- a/src/tools/kata-ctl/Cargo.lock +++ b/src/tools/kata-ctl/Cargo.lock @@ -23,15 +23,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "addr2line" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" @@ -320,21 +311,6 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc17ab023b4091c10ff099f9deebaeeb59b5189df07e554c4fef042b70745d68" -[[package]] -name = "backtrace" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" -dependencies = [ - "addr2line", - "cfg-if 1.0.0", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-link", -] - [[package]] name = "base64" version = "0.13.1" @@ -1362,12 +1338,6 @@ dependencies = [ "syn 2.0.87", ] -[[package]] -name = "gimli" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" - [[package]] name = "glob" version = "0.3.1" @@ -1532,7 +1502,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.5", "tokio", "tower-service", "tracing", @@ -1801,17 +1771,6 @@ dependencies = [ "libc", ] -[[package]] -name = "io-uring" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" -dependencies = [ - "bitflags 2.9.0", - "cfg-if 1.0.0", - "libc", -] - [[package]] name = "ipnet" version = "2.9.0" @@ -1968,9 +1927,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.172" +version = "0.2.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" [[package]] name = "libredox" @@ -2115,13 +2074,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2350,15 +2309,6 @@ dependencies = [ "bitflags 2.9.0", ] -[[package]] -name = "object" -version = "0.37.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" -dependencies = [ - "memchr", -] - [[package]] name = "oci-spec" version = "0.8.1" @@ -3345,12 +3295,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - [[package]] name = "rustix" version = "0.38.25" @@ -3840,6 +3784,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -4188,29 +4142,26 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.46.1" +version = "1.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" +checksum = "a91135f59b1cbf38c91e73cf3386fca9bb77915c45ce2771460c9d92f0f3d776" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", - "socket2", + "socket2 0.6.3", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", diff --git a/src/tools/kata-ctl/Cargo.toml b/src/tools/kata-ctl/Cargo.toml index c2fc08bac7..47479f4cb2 100644 --- a/src/tools/kata-ctl/Cargo.toml +++ b/src/tools/kata-ctl/Cargo.toml @@ -44,7 +44,7 @@ logging = { path = "../../libs/logging" } slog = "2.7.0" slog-scope = "4.4.0" hyper = "0.14.20" -tokio = { version = "1.44.2", features = ["signal"] } +tokio = { version = "1.52.0", features = ["signal"] } prometheus = { version = "0.14.0", features = ["process"] } procfs = "0.12.0" diff --git a/tools/kata/README.md b/tools/kata/README.md index f670fdbecc..1583c1729b 100644 --- a/tools/kata/README.md +++ b/tools/kata/README.md @@ -4,6 +4,9 @@ Kata helpers live here. - `run_kata.sh`: provides predefined `smoke`, `pass`, and `workload` Kata tasks - `kata_env.sh`: provides `install` and `check` for the shared Kata environment lifecycle - `kata_services.sh`: provides `start`, `stop`, and `status` for the background Kata smoke-test services +- `interactive_doc_test.py`: replays the documented `docker run -it` and + inner `nerdctl run -it` flows with `pexpect` for both the `asterinas/kata` + and `asterinas/asterinas` images - `check_overlayfs.sh`: probes whether the current host-side backing filesystem can support overlayfs `upperdir` and `workdir` for local Kata runs - `config/`: repo-owned Kata, CNI, `containerd`, and smoke-test config files used by the scripts @@ -26,6 +29,10 @@ Kata helpers live here. - Legacy `KATA_ALPINE_*` overrides still map to the new `KATA_TEST_*` names. - The default workload still pulls Alpine and runs `cat /etc/alpine-release`, but the image, in-container command, and output check are now script-configurable. +- `interactive_doc_test.py` uses `KATA_DOC_TEST_WORKLOAD_IMAGE`, which defaults + to `docker.io/alpine:latest`. For local validation in environments where + Docker Hub is unreachable, you can temporarily switch it to + `docker.1ms.run/alpine:latest`. ## Local virtio-fs note diff --git a/tools/kata/interactive_doc_test.py b/tools/kata/interactive_doc_test.py new file mode 100644 index 0000000000..3ce12ab0db --- /dev/null +++ b/tools/kata/interactive_doc_test.py @@ -0,0 +1,508 @@ +#!/usr/bin/env python3 + +from __future__ import annotations + +import argparse +import os +import pathlib +import re +import shlex +import subprocess +import sys +import uuid + +import pexpect + + +OUTER_PROMPT = "PEXPECT_OUTER> " +GUEST_PROMPT = "PEXPECT_GUEST> " +DEFAULT_KATA_IMAGE = "asterinas/kata:0.17.2-20260407" +DEFAULT_ASTERINAS_IMAGE = "asterinas/asterinas:0.17.2-20260407" +DEFAULT_WORKLOAD_IMAGE = "docker.io/alpine:latest" +REPO_ROOT = pathlib.Path(__file__).resolve().parents[2] +ANSI_ESCAPE_RE = re.compile(r"\x1b(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])") + + +class ScenarioError(RuntimeError): + pass + + +class TeeWriter: + def __init__(self, *streams) -> None: + self.streams = streams + + def write(self, data: str) -> None: + for stream in self.streams: + stream.write(data) + stream.flush() + + def flush(self) -> None: + for stream in self.streams: + stream.flush() + + +def strip_terminal_control_sequences(text: str) -> str: + return ANSI_ESCAPE_RE.sub("", text).replace("\r", "") + + +def clean_command_output(command: str, output: str) -> str: + cleaned_lines: list[str] = [] + + for raw_line in strip_terminal_control_sequences(output).splitlines(): + line = raw_line.strip() + if not line: + continue + + if line.startswith(OUTER_PROMPT.strip()): + line = line[len(OUTER_PROMPT.strip()) :].strip() + elif line.startswith(GUEST_PROMPT.strip()): + line = line[len(GUEST_PROMPT.strip()) :].strip() + + if not line: + continue + + if line == command: + continue + if line == "'": + continue + if line == "status=$?": + continue + if line.startswith("printf '__DOC_TEST_EXIT__"): + continue + if line.startswith("__DOC_TEST_EXIT__"): + continue + + cleaned_lines.append(line) + + return "\n".join(cleaned_lines).strip() + + +def outer_docker_env_args() -> list[str]: + args = ["-e", "TERM=dumb"] + passthrough_vars = ( + "KATA_FORCE_APT", + "KATA_PAYLOAD_IMAGE", + "KATA_STATIC_TARBALL_RELEASE_REPO", + "KATA_STATIC_TARBALL_SHA256", + "KATA_STATIC_TARBALL_SHA256_URL", + "KATA_STATIC_TARBALL_URL", + "KATA_VERSION", + "NERDCTL_VERSION", + ) + + for env_name in passthrough_vars: + env_value = os.environ.get(env_name) + if env_value: + args.extend(["-e", f"{env_name}={env_value}"]) + + return args + + +def outer_docker_device_args() -> list[str]: + args: list[str] = [] + required_devices = ( + "/dev/kvm", + "/dev/vhost-net", + "/dev/vhost-vsock", + ) + optional_devices = ( + "/dev/vsock", + ) + + for device_path in required_devices: + if not pathlib.Path(device_path).exists(): + raise ScenarioError(f"Required device is missing on the host: {device_path}") + args.extend(["--device", device_path]) + + for device_path in optional_devices: + if pathlib.Path(device_path).exists(): + args.extend(["--device", device_path]) + + return args + + +def kernel_developer_cache_mount_args() -> list[str]: + args: list[str] = [] + cache_mounts = ( + ("KATA_DOC_TEST_NIX_DIR", "/nix"), + ("KATA_DOC_TEST_CARGO_HOME", "/root/.cargo"), + ("KATA_DOC_TEST_RUSTUP_HOME", "/root/.rustup"), + ) + + for env_name, container_path in cache_mounts: + host_path = os.environ.get(env_name) + if not host_path: + continue + + host_dir = pathlib.Path(host_path) + host_dir.mkdir(parents=True, exist_ok=True) + args.extend(["-v", f"{host_dir.resolve()}:{container_path}"]) + + return args + + +class DockerShell: + def __init__(self, name: str, docker_args: list[str], transcript_path: pathlib.Path) -> None: + self.name = name + self.docker_args = docker_args + self.transcript_path = transcript_path + self.child: pexpect.spawn | None = None + self.log_handle = None + self.prompt = OUTER_PROMPT + self.stream_output = os.environ.get("KATA_DOC_TEST_STREAM_OUTPUT", "1") not in {"0", "false", "FALSE", "no", "NO"} + + def start(self) -> "DockerShell": + self.transcript_path.parent.mkdir(parents=True, exist_ok=True) + self.log_handle = self.transcript_path.open("w", encoding="utf-8") + subprocess.run( + ["docker", "rm", "-f", self.name], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=False, + ) + self.child = pexpect.spawn( + "docker", + self.docker_args, + encoding="utf-8", + codec_errors="replace", + echo=False, + timeout=60, + ) + if self.stream_output: + self.child.logfile_read = TeeWriter(self.log_handle, sys.stdout) + else: + self.child.logfile_read = self.log_handle + self.child.setwinsize(60, 200) + self.child.expect(r"[#$] ", timeout=120) + self.set_prompt(OUTER_PROMPT) + return self + + def close(self) -> None: + if self.child is not None: + self.child.close(force=True) + self.child = None + subprocess.run( + ["docker", "rm", "-f", self.name], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + check=False, + ) + if self.log_handle is not None: + self.log_handle.close() + self.log_handle = None + + def set_prompt(self, prompt: str) -> None: + assert self.child is not None + self.child.sendline(f"export PS1={shlex.quote(prompt)}") + self.child.expect(re.escape(prompt), timeout=30) + self.prompt = prompt + + def run(self, command: str, timeout: int = 300, check: bool = True) -> str: + assert self.child is not None + marker = f"__DOC_TEST_EXIT__{uuid.uuid4().hex}__:" + wrapped_command = f"{command}; __doc_test_status=$?; printf '{marker}%s\\n' \"$__doc_test_status\"" + self.child.sendline(wrapped_command) + self.child.expect(re.compile(re.escape(marker) + r"(\d+)\r?\n"), timeout=timeout) + output = clean_command_output(wrapped_command, self.child.before) + status = int(self.child.match.group(1)) + self.child.expect(re.escape(self.prompt), timeout=60) + if check and status != 0: + raise ScenarioError(f"Command failed with exit code {status}: {command}\n{output}") + return output + + def enter_guest(self, command: str, timeout: int = 900) -> None: + assert self.child is not None + self.child.sendline(command) + match_index = self.child.expect([re.escape(OUTER_PROMPT), r"[#$] "], timeout=timeout) + if match_index == 0: + self.prompt = OUTER_PROMPT + failure_output = clean_command_output(command, self.child.before) + raise ScenarioError(f"Guest shell did not start successfully for command: {command}\n{failure_output}") + self.set_prompt(GUEST_PROMPT) + + def exit_guest(self) -> None: + assert self.child is not None + self.child.sendline("exit") + self.child.expect(re.escape(OUTER_PROMPT), timeout=120) + self.prompt = OUTER_PROMPT + + +def require_paths(paths: list[pathlib.Path]) -> None: + missing_paths = [str(path) for path in paths if not path.exists()] + if missing_paths: + raise ScenarioError(f"Missing required path(s): {', '.join(missing_paths)}") + + +def announce(message: str) -> None: + print(message, flush=True) + + +def dump_kata_debug_logs(shell: DockerShell, context: str) -> None: + announce(f"[debug] dumping Kata/QEMU logs after {context}") + for log_path in ( + "/tmp/kata-console.log", + "/tmp/console.log", + "/tmp/kata-qemu-serial.log", + "/tmp/qemu-serial.log", + "/tmp/containerd.log", + "/tmp/kata-syslog.log", + ): + output = shell.run( + f'test -f {shlex.quote(log_path)} && {{ echo "--- {log_path} ---"; tail -n 200 {shlex.quote(log_path)}; }} || true', + check=False, + timeout=60, + ) + if output: + announce(output) + + +def log_active_kata_configs(shell: DockerShell, label: str) -> None: + announce(f"[{label}] active Kata default config:") + announce( + shell.run( + "readlink -f /opt/kata/share/defaults/kata-containers/configuration.toml", + timeout=60, + ) + ) + announce(f"[{label}] active runtime config:") + announce( + shell.run( + "readlink -f /etc/kata-containers/configuration.toml 2>/dev/null || echo /etc/kata-containers/configuration.toml", + timeout=60, + ) + ) + + +def run_guest_workload(shell: DockerShell, workload_image: str, host_proc_version: str, container_name: str = "foo") -> tuple[str, str]: + announce(f"[guest] launching workload container {container_name} from {workload_image}") + shell.run(f"nerdctl rm -f {shlex.quote(container_name)} >/dev/null 2>&1 || true", check=False) + try: + shell.enter_guest( + " ".join( + [ + "nerdctl", + "run", + "--cgroup-manager", + "cgroupfs", + "--net", + "none", + "--runtime", + "io.containerd.kata.v2", + "--name", + shlex.quote(container_name), + "-it", + shlex.quote(workload_image), + ] + ), + timeout=900, + ) + guest_proc_version = shell.run("cat /proc/version") + alpine_release = shell.run("cat /etc/alpine-release") + shell.exit_guest() + announce(f"[guest] removing workload container {container_name}") + shell.run(f"nerdctl rm -f {shlex.quote(container_name)}") + except Exception: + dump_kata_debug_logs(shell, f"failed nerdctl run for {container_name}") + raise + + if guest_proc_version.strip() == host_proc_version.strip(): + raise ScenarioError("Guest /proc/version unexpectedly matches the outer container /proc/version") + if not alpine_release.strip(): + raise ScenarioError("Expected a non-empty /etc/alpine-release inside the guest workload") + + return guest_proc_version.strip(), alpine_release.strip() + + +def run_end_user_scenario(args: argparse.Namespace) -> pathlib.Path: + outer_name = f"kata-doc-end-user-{uuid.uuid4().hex[:12]}" + transcript_path = args.log_dir / "end-user.transcript.log" + shell = DockerShell( + outer_name, + [ + "run", + "--rm", + "-it", + "--name", + outer_name, + "--cgroupns", + "host", + "--privileged", + *outer_docker_device_args(), + "--tmpfs", + "/tmp:exec,mode=1777,size=8g", + "--tmpfs", + "/var/lib/containerd:exec,mode=755,size=8g", + *outer_docker_env_args(), + args.kata_image, + "bash", + ], + transcript_path, + ).start() + + try: + announce(f"[end-user] using outer image: {args.kata_image}") + host_proc_version = shell.run("cat /proc/version") + shell.run("cd /root/asterinas") + announce("[end-user] starting Kata background services") + shell.run("./tools/kata/kata_services.sh start", timeout=300) + log_active_kata_configs(shell, "end-user") + status_output = shell.run("./tools/kata/kata_services.sh status") + if "Kata services are running." not in status_output: + raise ScenarioError(f"Unexpected service status output:\n{status_output}") + guest_proc_version, alpine_release = run_guest_workload(shell, args.workload_image, host_proc_version) + announce(f"[end-user] guest /proc/version: {guest_proc_version}") + announce(f"[end-user] alpine release: {alpine_release}") + announce("[end-user] stopping Kata background services") + shell.run("./tools/kata/kata_services.sh stop", timeout=300) + return transcript_path + finally: + shell.close() + + +def run_kernel_developer_scenario(args: argparse.Namespace) -> pathlib.Path: + require_paths([args.repo_dir, args.asterinas_dir]) + outer_name = f"kata-doc-kernel-dev-{uuid.uuid4().hex[:12]}" + transcript_path = args.log_dir / "kernel-developer.transcript.log" + shell = DockerShell( + outer_name, + [ + "run", + "--rm", + "-it", + "--name", + outer_name, + "--cgroupns", + "host", + "--privileged", + *outer_docker_device_args(), + "--tmpfs", + "/tmp:exec,mode=1777,size=8g", + "--tmpfs", + "/var/lib/containerd:exec,mode=755,size=8g", + *outer_docker_env_args(), + *kernel_developer_cache_mount_args(), + "-v", + f"{args.asterinas_dir.resolve()}:/root/asterinas", + "-v", + f"{args.repo_dir.resolve()}:/root/kata-containers:ro", + "-w", + "/root/kata-containers", + args.asterinas_image, + "bash", + ], + transcript_path, + ).start() + + try: + announce(f"[kernel-developer] using outer image: {args.asterinas_image}") + announce(f"[kernel-developer] mounted Asterinas tree: {args.asterinas_dir}") + host_proc_version = shell.run("cat /proc/version") + shell.run("test -d /root/kata-containers/tools/kata") + announce("[kernel-developer] running tools/kata/kata_env.sh install") + shell.run("./tools/kata/kata_env.sh install", timeout=3600) + announce("[kernel-developer] starting Kata background services") + shell.run("/root/kata-containers/tools/kata/kata_services.sh start", timeout=300) + log_active_kata_configs(shell, "kernel-developer") + status_output = shell.run("/root/kata-containers/tools/kata/kata_services.sh status") + if "Kata services are running." not in status_output: + raise ScenarioError(f"Unexpected service status output:\n{status_output}") + packaged_guest_proc_version, packaged_alpine_release = run_guest_workload( + shell, + args.workload_image, + host_proc_version, + "foo", + ) + announce(f"[kernel-developer] packaged guest /proc/version: {packaged_guest_proc_version}") + announce(f"[kernel-developer] packaged alpine release: {packaged_alpine_release}") + announce("[kernel-developer] building local kernel with make kernel BOOT_METHOD=qemu-direct") + shell.run("cd /root/asterinas && make kernel BOOT_METHOD=qemu-direct", timeout=7200) + shell.run("test -f /root/asterinas/target/osdk/aster-kernel-osdk-bin.qemu_elf") + announce("[kernel-developer] switching Kata to the locally built kernel") + shell.run( + "sed -i 's#^kernel = \".*\"#kernel = \"/root/asterinas/target/osdk/aster-kernel-osdk-bin.qemu_elf\"#' " + "/etc/kata-containers/configuration.toml" + ) + shell.run( + "grep -F 'kernel = \"/root/asterinas/target/osdk/aster-kernel-osdk-bin.qemu_elf\"' " + "/etc/kata-containers/configuration.toml" + ) + local_guest_proc_version, local_alpine_release = run_guest_workload( + shell, + args.workload_image, + host_proc_version, + "foo", + ) + announce(f"[kernel-developer] local-kernel guest /proc/version: {local_guest_proc_version}") + announce(f"[kernel-developer] local-kernel alpine release: {local_alpine_release}") + announce("[kernel-developer] stopping Kata background services") + shell.run("/root/kata-containers/tools/kata/kata_services.sh stop", timeout=300) + return transcript_path + finally: + shell.close() + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Replay the documented Asterinas Kata flows with pexpect") + parser.add_argument( + "--scenario", + choices=["end-user", "kernel-developer", "all"], + default=os.environ.get("KATA_DOC_TEST_SCENARIO", "all"), + ) + parser.add_argument( + "--kata-image", + default=os.environ.get("KATA_DOC_TEST_KATA_IMAGE", DEFAULT_KATA_IMAGE), + ) + parser.add_argument( + "--asterinas-image", + default=os.environ.get("KATA_DOC_TEST_ASTERINAS_IMAGE", DEFAULT_ASTERINAS_IMAGE), + ) + parser.add_argument( + "--workload-image", + default=os.environ.get("KATA_DOC_TEST_WORKLOAD_IMAGE", DEFAULT_WORKLOAD_IMAGE), + ) + parser.add_argument( + "--repo-dir", + type=pathlib.Path, + default=pathlib.Path(os.environ.get("KATA_DOC_TEST_REPO_DIR", str(REPO_ROOT))), + ) + parser.add_argument( + "--asterinas-dir", + type=pathlib.Path, + default=pathlib.Path(os.environ.get("KATA_DOC_TEST_ASTERINAS_DIR", str(pathlib.Path.home() / "asterinas"))), + ) + parser.add_argument( + "--log-dir", + type=pathlib.Path, + default=pathlib.Path(os.environ.get("KATA_DOC_TEST_LOG_DIR", "/tmp/asterinas-kata-doc-tests")), + ) + return parser.parse_args() + + +def main() -> int: + args = parse_args() + args.log_dir.mkdir(parents=True, exist_ok=True) + transcripts: list[pathlib.Path] = [] + + try: + if args.scenario in {"end-user", "all"}: + transcripts.append(run_end_user_scenario(args)) + if args.scenario in {"kernel-developer", "all"}: + transcripts.append(run_kernel_developer_scenario(args)) + except Exception as error: + announce(f"interactive_doc_test failed: {error}") + if transcripts: + announce("available transcript(s):") + for transcript in transcripts: + announce(f" - {transcript}") + else: + announce(f"transcript directory: {args.log_dir}") + return 1 + + announce("interactive_doc_test passed") + for transcript in transcripts: + announce(f"transcript: {transcript}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/kata/kata_env.sh b/tools/kata/kata_env.sh index 69c6bd632f..8c868b4e80 100755 --- a/tools/kata/kata_env.sh +++ b/tools/kata/kata_env.sh @@ -431,23 +431,20 @@ install_kata_from_payload_image() { install_kata_from_static_tarball() { source_marker_path="${KATA_INSTALL_SOURCE_MARKER:-/opt/kata/.kata-install-source}" static_tarball_url="$(resolve_static_tarball_url)" - extract_dir="${KATA_STATIC_EXTRACT_DIR:-/tmp/kata-static-extract}" static_tarball_sha256="$(resolve_static_tarball_sha256)" static_tarball_path="$(prepare_cached_static_tarball)" - rm -rf "${extract_dir}" - install -d -m 0755 "${extract_dir}" - tar --zstd -xf "${static_tarball_path}" -C "${extract_dir}" - - test -d "${extract_dir}/opt/kata" + echo "Installing Kata static tarball from ${static_tarball_url}" rm -rf /opt/kata - cp -a "${extract_dir}/opt/kata" /opt/ + tar --zstd -xf "${static_tarball_path}" -C / + test -d /opt/kata { printf 'static-tarball-url %s\n' "${static_tarball_url}" printf 'static-tarball-sha256 %s\n' "${static_tarball_sha256}" } > "${source_marker_path}" test -x /opt/kata/bin/kata-runtime test -x /opt/kata/bin/containerd-shim-kata-v2 + echo "Installed Kata static tarball into /opt/kata" } patch_qemu_config_for_asterinas() { @@ -545,9 +542,11 @@ wait_for_containerd_ready() { } run_install_task() { + echo "Installing required distro packages" install_required_packages if need_nerdctl_install; then + echo "Installing nerdctl ${NERDCTL_VERSION}" download_release_asset \ /tmp/nerdctl.tgz \ "https://github.com/containerd/nerdctl/releases/download/${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION#v}-linux-amd64.tar.gz" @@ -555,6 +554,7 @@ run_install_task() { fi if should_install_crictl && need_crictl_install; then + echo "Installing crictl ${CRICTL_VERSION}" download_release_asset \ /tmp/crictl.tgz \ "https://github.com/kubernetes-sigs/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-amd64.tar.gz" @@ -563,10 +563,13 @@ run_install_task() { if need_kata_install; then if [ -n "${KATA_ASTERINAS_KERNEL_PATH:-}" ] && [ -f "${KATA_ASTERINAS_KERNEL_PATH}" ]; then + echo "Installing Kata with local Asterinas kernel overlay" install_kata_from_asterinas_kernel_overlay elif [ -n "${KATA_STATIC_TARBALL_URL:-}" ] || [ -n "${KATA_STATIC_TARBALL_RELEASE_REPO:-}" ]; then + echo "Installing Kata from static tarball" install_kata_from_static_tarball else + echo "Installing Kata from payload image" install_kata_from_payload_image fi fi @@ -574,6 +577,7 @@ run_install_task() { install -d -m 0755 /usr/local/bin ln -sf /opt/kata/bin/kata-runtime /usr/local/bin/kata-runtime ln -sf /opt/kata/bin/containerd-shim-kata-v2 /usr/local/bin/containerd-shim-kata-v2 + echo "Kata install task completed" } run_check_task() { diff --git a/tools/packaging/asterinas-kata/Dockerfile b/tools/packaging/asterinas-kata/Dockerfile index f6773e0e36..647ded2d13 100644 --- a/tools/packaging/asterinas-kata/Dockerfile +++ b/tools/packaging/asterinas-kata/Dockerfile @@ -3,6 +3,7 @@ FROM ${ASTERINAS_BASE_IMAGE} ARG KATA_STATIC_TARBALL_RELEASE_REPO=kata-containers/kata-containers ARG KATA_STATIC_TARBALL_URL= +ARG KATA_STATIC_TARBALL_SHA256= ARG ASTERINAS_RELEASE_VERSION= ARG ASTERINAS_DOCKER_IMAGE_VERSION= @@ -12,6 +13,7 @@ COPY tools/kata /root/asterinas/tools/kata RUN KATA_STATIC_TARBALL_RELEASE_REPO="${KATA_STATIC_TARBALL_RELEASE_REPO}" \ KATA_STATIC_TARBALL_URL="${KATA_STATIC_TARBALL_URL}" \ + KATA_STATIC_TARBALL_SHA256="${KATA_STATIC_TARBALL_SHA256}" \ bash /root/asterinas/tools/kata/kata_env.sh install RUN printf '%s\n' "${ASTERINAS_RELEASE_VERSION}" > /root/asterinas/.asterinas-version && \ diff --git a/tools/packaging/release/build-asterinas-release.sh b/tools/packaging/release/build-asterinas-release.sh index 62a9a31d7a..c426c765e7 100644 --- a/tools/packaging/release/build-asterinas-release.sh +++ b/tools/packaging/release/build-asterinas-release.sh @@ -18,6 +18,7 @@ FORCE_RUNTIME_BUILD="${FORCE_RUNTIME_BUILD:-false}" ASTERINAS_REPOSITORY="${ASTERINAS_REPOSITORY:-}" ASTERINAS_REF="${ASTERINAS_REF:-}" +ASTERINAS_COMMIT="${ASTERINAS_COMMIT:-}" ASTERINAS_BUILDER_IMAGE="${ASTERINAS_BUILDER_IMAGE:-}" ASTERINAS_KERNEL="${ASTERINAS_KERNEL:-}" ASTERINAS_TDX_KERNEL="${ASTERINAS_TDX_KERNEL:-}" @@ -380,8 +381,11 @@ write_release_notes() { printf -- '- Kata version: `%s`\n' "${VERSION}" printf -- '- Architecture: `%s`\n' "${ARCHITECTURE}" printf -- '- Base tarball: `%s`\n' "${BASE_TARBALL_URL}" - printf -- '- Kata commit: `%s`\n' "${KATA_COMMIT}" + printf -- '- kata-containers commit: `%s`\n' "${KATA_COMMIT}" printf -- '- Asterinas repo/ref: `%s@%s`\n' "${ASTERINAS_REPOSITORY}" "${ASTERINAS_REF}" + if [ -n "${ASTERINAS_COMMIT}" ]; then + printf -- '- Asterinas commit: `%s`\n' "${ASTERINAS_COMMIT}" + fi printf -- '- Asterinas builder image: `%s`\n' "${ASTERINAS_BUILDER_IMAGE}" printf -- '- Guest kernel: `%s`\n' "${ASTERINAS_KERNEL_PATH}" if [ -n "${ASTERINAS_TDX_KERNEL}" ]; then