From 116ae66025c21c6c4c2ce4ed74c330f263aa3ec3 Mon Sep 17 00:00:00 2001 From: Alex Lyn Date: Thu, 30 Apr 2026 18:07:43 +0800 Subject: [PATCH 01/11] runtime-rs: Introduce a cached sandbox exit information Introduce an exit_info field in SandboxInner so sandbox teardown can store a stable exit result in runtime state. The follow-on WaitSandbox rework needs a place to keep the final SandboxExitInfo after the sandbox has already stopped. Without that cached result, later waiters would have no consistent value to return once the original stop event has passed. This change only adds the state holder. Behaviour changes follow in later commits. Signed-off-by: Alex Lyn --- src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs index 7337d50849..cd61d52439 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs @@ -75,6 +75,7 @@ use resource::{ResourceConfig, ResourceManager}; use runtime_spec as spec; use std::path::{Path, PathBuf}; use std::sync::Arc; +use std::time::SystemTime; use strum::Display; use tokio::sync::{mpsc::Sender, Mutex, RwLock}; use tracing::instrument; @@ -96,12 +97,14 @@ pub enum SandboxState { struct SandboxInner { state: SandboxState, + exit_info: Option, } impl SandboxInner { pub fn new() -> Self { Self { state: SandboxState::Init, + exit_info: None, } } } From ac2d39fc34ad624f202679581a97a24ef4c340d6 Mon Sep 17 00:00:00 2001 From: Alex Lyn Date: Thu, 30 Apr 2026 18:02:39 +0800 Subject: [PATCH 02/11] runtime-rs: Add sandbox exit notifier in VirtSandbox Add an internal exit_notify_tx channel to VirtSandbox and initialise it in both the regular and restore constructors. The later WaitSandbox rework needs a way to block until sandbox stop has been observed without polling runtime state. This commit only wires in the notifier so the follow-on behaviour change can subscribe to a dedicated stop signal. No WaitSandbox behaviour changes are made here yet. Signed-off-by: Alex Lyn --- .../crates/runtimes/virt_container/src/sandbox.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs index cd61d52439..2007461fcd 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs @@ -77,7 +77,7 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use std::time::SystemTime; use strum::Display; -use tokio::sync::{mpsc::Sender, Mutex, RwLock}; +use tokio::sync::{mpsc::Sender, watch, Mutex, RwLock}; use tracing::instrument; pub(crate) const VIRTCONTAINER: &str = "virt_container"; @@ -118,6 +118,7 @@ pub struct VirtSandbox { agent: Arc, hypervisor: Arc, monitor: Arc, + exit_notify_tx: watch::Sender, sandbox_config: Option, shm_size: u64, factory: Option, @@ -133,6 +134,7 @@ impl std::fmt::Debug for VirtSandbox { .field("agent", &"") .field("hypervisor", &self.hypervisor) .field("monitor", &"") + .field("exit_notify_tx", &">") .field("sandbox_config", &self.sandbox_config) .field("factory", &self.factory) .finish() @@ -151,6 +153,7 @@ impl VirtSandbox { ) -> Result { let config = resource_manager.config().await; let keep_abnormal = config.runtime.keep_abnormal; + let (exit_notify_tx, _) = watch::channel(false); Ok(Self { sid: sid.to_string(), msg_sender: Arc::new(Mutex::new(msg_sender)), @@ -159,6 +162,7 @@ impl VirtSandbox { hypervisor, resource_manager, monitor: Arc::new(HealthCheck::new(true, keep_abnormal)), + exit_notify_tx, shm_size: sandbox_config.shm_size, sandbox_config: Some(sandbox_config), factory: Some(factory), @@ -1254,6 +1258,7 @@ impl Persist for VirtSandbox { hypervisor, resource_manager, monitor: Arc::new(HealthCheck::new(true, keep_abnormal)), + exit_notify_tx: watch::channel(false).0, sandbox_config: None, shm_size: DEFAULT_SHM_SIZE, factory: None, From 2b980b3a34104fb6f27ac796fc4a69ea1560687a Mon Sep 17 00:00:00 2001 From: Alex Lyn Date: Mon, 18 May 2026 16:00:33 +0800 Subject: [PATCH 03/11] runtime-rs: Block WaitSandbox until sandbox exits Rework sandbox waiting so the WaitSandbox path blocks on sandbox lifetime rather than directly borrowing the hypervisor wait call. Once stop has been observed, the cached exit result is returned to later waiters. While the sandbox is still alive, waiters subscribe to the internal stop notifier and sleep until shutdown or VM exit records the final result. Together with the preceding support commits, this keeps the overall behaviour identical to the original WaitSandbox fix while making the dependency chain explicit. Signed-off-by: Alex Lyn --- .../runtimes/virt_container/src/sandbox.rs | 92 ++++++++++++++++--- 1 file changed, 81 insertions(+), 11 deletions(-) diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs index 2007461fcd..b5be1156c0 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs @@ -181,6 +181,20 @@ impl VirtSandbox { self.hypervisor.clone() } + async fn record_stop(&self, exit_status: u32, exited_at: SystemTime) { + let mut inner = self.inner.write().await; + if inner.state == SandboxState::Stopped { + return; + } + + inner.state = SandboxState::Stopped; + inner.exit_info = Some(SandboxExitInfo { + exit_status, + exited_at: Some(exited_at), + }); + let _ = self.exit_notify_tx.send(true); + } + #[instrument] async fn prepare_for_start_sandbox( &self, @@ -758,6 +772,22 @@ impl Sandbox for VirtSandbox { self.hypervisor.start_vm(10_000).await.context("start vm")?; info!(sl!(), "start vm"); + let sandbox = self.clone(); + // wait for vm exit in background, and record the exit status and time when vm exited. + tokio::spawn(async move { + match sandbox.hypervisor.wait_vm().await { + Ok(exit_code) => { + sandbox + .record_stop(exit_code as u32, SystemTime::now()) + .await; + } + Err(err) => { + warn!(sl!(), "failed waiting for sandbox VM exit: {:?}", err); + sandbox.record_stop(255, SystemTime::now()).await; + } + } + }); + // execute pre-start hook functions, including Prestart Hooks and CreateRuntime Hooks let (prestart_hooks, create_runtime_hooks) = if let Some(hooks) = sandbox_config.hooks.as_ref() { @@ -944,6 +974,22 @@ impl Sandbox for VirtSandbox { .await .context("start template vm")?; info!(sl!(), "vm started from template"); + + let sandbox = self.clone(); + tokio::spawn(async move { + match sandbox.hypervisor.wait_vm().await { + Ok(exit_code) => { + sandbox + .record_stop(exit_code as u32, SystemTime::now()) + .await; + } + Err(err) => { + warn!(sl!(), "failed waiting for sandbox VM exit: {:?}", err); + sandbox.record_stop(255, SystemTime::now()).await; + } + } + }); + Ok(()) } @@ -962,23 +1008,47 @@ impl Sandbox for VirtSandbox { async fn wait(&self) -> Result { info!(sl!(), "wait sandbox"); - let exit_code = self.hypervisor.wait_vm().await.context("wait vm")?; - Ok(SandboxExitInfo { - exit_status: exit_code as u32, - exited_at: Some(std::time::SystemTime::now()), - }) + { + let inner = self.inner.read().await; + if inner.state == SandboxState::Stopped { + return Ok(inner.exit_info.clone().unwrap_or_default()); + } + } + + let mut exit_notify_rx = self.exit_notify_tx.subscribe(); + while !*exit_notify_rx.borrow() { + exit_notify_rx + .changed() + .await + .context("wait for sandbox stop notification")?; + } + + let inner = self.inner.read().await; + Ok(inner.exit_info.clone().unwrap_or_default()) } async fn stop(&self) -> Result<()> { - let mut sandbox_inner = self.inner.write().await; + let state = { + let sandbox_inner = self.inner.read().await; + sandbox_inner.state + }; - if sandbox_inner.state != SandboxState::Stopped { - info!(sl!(), "begin stop sandbox"); - self.hypervisor.stop_vm().await.context("stop vm")?; - sandbox_inner.state = SandboxState::Stopped; - info!(sl!(), "sandbox stopped"); + if state == SandboxState::Stopped { + return Ok(()); } + info!(sl!(), "begin stop sandbox"); + if state == SandboxState::Init { + let _ = self.hypervisor.stop_vm().await; + self.record_stop(0, SystemTime::now()).await; + info!(sl!(), "sandbox stopped during Init"); + return Ok(()); + } + + self.hypervisor.stop_vm().await.context("stop vm")?; + self.wait().await.context("wait for vm exit after stop")?; + info!(sl!(), "sandbox stopped"); + Ok(()) } From 3358c7634b2f564cf4465b602fc7095623e05b62 Mon Sep 17 00:00:00 2001 From: Alex Lyn Date: Thu, 30 Apr 2026 16:50:26 +0800 Subject: [PATCH 04/11] runtime-rs: Avoid shutting down sandbox on container exit Prevent the sandbox from being prematurely shut down when a standard workload container exits. Previously, the shutdown logic incorrectly triggered a sandbox shutdown whenever the container list became empty. This resulted in unintended lifecycle termination for non-transient sandboxes. This change refines the `need_shutdown_sandbox()` criteria in `virt_container/src/container_manager/manager.rs` to only initiate a shutdown under specific conditions: - The shutdown request is explicit (`req.is_now`). - The request targets the sandbox itself (`req.container_id == self.sid`). By removing the implicit dependency on the empty container list, we ensure the sandbox remains active as expected after workload containers finish execution. Signed-off-by: Alex Lyn --- .../runtimes/virt_container/src/container_manager/manager.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/manager.rs b/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/manager.rs index 43d2ce8df8..fe0ff2a82c 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/manager.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/manager.rs @@ -460,7 +460,7 @@ impl ContainerManager for VirtContainerManager { #[instrument] async fn need_shutdown_sandbox(&self, req: &ShutdownRequest) -> bool { - req.is_now || self.containers.read().await.is_empty() || self.sid == req.container_id + req.is_now || self.sid == req.container_id } #[instrument] From 3f42929e2b74bf625026d3275dee0f8d601f6461 Mon Sep 17 00:00:00 2001 From: Alex Lyn Date: Thu, 30 Apr 2026 16:32:24 +0800 Subject: [PATCH 05/11] runtime-rs: Update sandbox status to include created_at field Ensure the `created_at` timestamp is correctly propagated in the sandbox status. Although `created_at` is present in the `SandboxStatus` and `SandboxStatusResponse` data structures, it was previously omitted during the status transition. This commit completes the implementation by passing the value recorded during sandbox initialization. Signed-off-by: Alex Lyn --- src/runtime-rs/crates/runtimes/common/src/types/mod.rs | 1 + src/runtime-rs/crates/runtimes/src/manager.rs | 2 +- .../crates/runtimes/virt_container/src/sandbox.rs | 6 +++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/runtime-rs/crates/runtimes/common/src/types/mod.rs b/src/runtime-rs/crates/runtimes/common/src/types/mod.rs index d0f40d78ab..30b630abcd 100644 --- a/src/runtime-rs/crates/runtimes/common/src/types/mod.rs +++ b/src/runtime-rs/crates/runtimes/common/src/types/mod.rs @@ -233,6 +233,7 @@ pub struct SandboxStatus { pub pid: u32, pub state: String, pub info: std::collections::HashMap, + pub created_at: Option, } #[derive(Debug, Clone)] diff --git a/src/runtime-rs/crates/runtimes/src/manager.rs b/src/runtime-rs/crates/runtimes/src/manager.rs index 8be85f5701..458cdbe3eb 100644 --- a/src/runtime-rs/crates/runtimes/src/manager.rs +++ b/src/runtime-rs/crates/runtimes/src/manager.rs @@ -581,7 +581,7 @@ impl RuntimeHandlerManager { sandbox_id: status.sandbox_id, pid: status.pid, state: status.state, - created_at: None, + created_at: status.created_at, exited_at: None, })) } diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs index b5be1156c0..bf52404703 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs @@ -98,6 +98,7 @@ pub enum SandboxState { struct SandboxInner { state: SandboxState, exit_info: Option, + created_at: Option, } impl SandboxInner { @@ -105,6 +106,7 @@ impl SandboxInner { Self { state: SandboxState::Init, exit_info: None, + created_at: None, } } } @@ -880,6 +882,7 @@ impl Sandbox for VirtSandbox { .context("create sandbox")?; inner.state = SandboxState::Running; + inner.created_at = Some(std::time::SystemTime::now()); // get and store guest details self.store_guest_details() @@ -1002,7 +1005,8 @@ impl Sandbox for VirtSandbox { sandbox_id: self.sid.clone(), pid: std::process::id(), state, - ..Default::default() + info: std::collections::HashMap::new(), + created_at: inner.created_at, }) } From 486f5f94120f854eb86d000634d34f6b837f2350 Mon Sep 17 00:00:00 2001 From: Alex Lyn Date: Thu, 30 Apr 2026 16:42:28 +0800 Subject: [PATCH 06/11] runtime-rs: Align sandbox status with CRI expectations Update the sandbox status reporting to align with containerd/CRI requirements. This commit aims to address issue of `State Mapping` Previously, internal state strings were returned, which containerd could not recognize, causing running sandboxes to be misinterpreted as SANDBOX_NOTREADY. This maps internal states to CRI constants: - Running -> SANDBOX_READY - Init | Stopped -> SANDBOX_NOTREADY These changes ensure the sandbox status is both accurately interpreted and fully compliant with the expected interface. Signed-off-by: Alex Lyn --- .../crates/runtimes/virt_container/src/sandbox.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs index bf52404703..3c90002c59 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs @@ -95,6 +95,15 @@ pub enum SandboxState { Stopped, } +impl SandboxState { + fn to_cri_state(self) -> &'static str { + match self { + SandboxState::Running => "SANDBOX_READY", + SandboxState::Init | SandboxState::Stopped => "SANDBOX_NOTREADY", + } + } +} + struct SandboxInner { state: SandboxState, exit_info: Option, @@ -183,7 +192,7 @@ impl VirtSandbox { self.hypervisor.clone() } - async fn record_stop(&self, exit_status: u32, exited_at: SystemTime) { + async fn record_stop(&self, exit_status: u32, exited_at: std::time::SystemTime) { let mut inner = self.inner.write().await; if inner.state == SandboxState::Stopped { return; @@ -997,9 +1006,8 @@ impl Sandbox for VirtSandbox { } async fn status(&self) -> Result { - info!(sl!(), "get sandbox status"); let inner = self.inner.read().await; - let state = inner.state.to_string(); + let state = inner.state.to_cri_state().to_string(); Ok(SandboxStatus { sandbox_id: self.sid.clone(), From a7739579d6ed163b1400588b51a584a7c0f222ed Mon Sep 17 00:00:00 2001 From: Alex Lyn Date: Thu, 30 Apr 2026 18:27:47 +0800 Subject: [PATCH 07/11] tests: Use podsandbox sandboxer for the runc sanity check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The check_daemon_setup function verifies that containerd + runc are functional before the real kata tests run. Using the shim sandboxer for this runc check hits a known containerd bug where the OCI spec is not populated before NewBundle is called, so config.json is never written and containerd-shim-runc-v2 fails at startup. See containerd/containerd#11640 The sandboxer choice is irrelevant for this sanity check, so use podsandbox which works correctly with runc. Signed-off-by: Fabiano Fidêncio Signed-off-by: Alex Lyn --- tests/integration/cri-containerd/integration-tests.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/integration/cri-containerd/integration-tests.sh b/tests/integration/cri-containerd/integration-tests.sh index 4c14e5219f..8c8851cb64 100755 --- a/tests/integration/cri-containerd/integration-tests.sh +++ b/tests/integration/cri-containerd/integration-tests.sh @@ -170,6 +170,13 @@ function err_report() { function check_daemon_setup() { info "containerd(cri): Check daemon works with runc" + # Use podsandbox for the runc sanity check: the shim sandboxer has a known + # containerd-side bug where the OCI spec is not populated before NewBundle is + # called, so config.json is never written and containerd-shim-runc-v2 fails. + # See https://github.com/containerd/containerd/issues/11640 + # This check only verifies that containerd + runc are functional before the + # real kata tests run, so the sandboxer choice doesn't matter here. + local SANDBOXER="podsandbox" create_containerd_config "runc" # containerd cri-integration will modify the passed in config file. Let's From 328fccfbbdbf663203e8c5f674527541e850c6f5 Mon Sep 17 00:00:00 2001 From: Alex Lyn Date: Thu, 30 Apr 2026 18:32:22 +0800 Subject: [PATCH 08/11] ci: Re-enable run-containerd-sandboxapi job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The job was disabled because TestImageLoad was failing when using the shim sandboxer with runc due to a containerd bug (config.json not being written to the bundle directory). Now that check_daemon_setup uses podsandbox for the runc sanity check, the root cause of the failure is worked around on our side and the job can be re-enabled. Also update the runner to ubuntu-24.04. Signed-off-by: Fabiano Fidêncio Signed-off-by: Alex Lyn --- .github/workflows/basic-ci-amd64.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/basic-ci-amd64.yaml b/.github/workflows/basic-ci-amd64.yaml index 07d4ed2945..d8fec03a60 100644 --- a/.github/workflows/basic-ci-amd64.yaml +++ b/.github/workflows/basic-ci-amd64.yaml @@ -33,9 +33,7 @@ jobs: concurrency: group: ${{ github.workflow }}-${{ github.job }}-${{ github.event.pull_request.number || github.ref }}-sandboxapi-amd64-${{ toJSON(matrix) }} cancel-in-progress: true - # TODO: enable me when https://github.com/containerd/containerd/issues/11640 is fixed - if: false - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 env: CONTAINERD_VERSION: ${{ matrix.containerd_version }} GOPATH: ${{ github.workspace }} From 9f78dc687fbdfc95a863ac0480d705a393870881 Mon Sep 17 00:00:00 2001 From: Alex Lyn Date: Thu, 30 Apr 2026 18:36:31 +0800 Subject: [PATCH 09/11] tests: exclude TestContainerRestart from the cri-containerd test list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Creating a new container in the same sandbox VM after the previous container has exited and been removed has never been supported by kata-containers (neither with the go-based nor the rust-based runtime). When the last container is removed the kata VM shuts down, so any attempt to start a new container in the same sandbox fails. This test exercises a use-case kata does not currently support, and it has never been part of the passing list for good reason. Mark it explicitly excluded with a comment so it is clear this is a deliberate omission rather than an oversight. Signed-off-by: Fabiano Fidêncio Signed-off-by: Alex Lyn --- tests/integration/cri-containerd/integration-tests.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/integration/cri-containerd/integration-tests.sh b/tests/integration/cri-containerd/integration-tests.sh index 8c8851cb64..56ef6955d5 100755 --- a/tests/integration/cri-containerd/integration-tests.sh +++ b/tests/integration/cri-containerd/integration-tests.sh @@ -687,8 +687,13 @@ function main() { info "containerd(cri): Running cri-integration" - - passing_test="TestContainerStats|TestContainerRestart|TestContainerListStatsWithIdFilter|TestContainerListStatsWithIdSandboxIdFilter|TestDuplicateName|TestImageLoad|TestImageFSInfo|TestSandboxCleanRemove" + # TestContainerRestart is excluded: creating a new container in the same + # sandbox VM after the previous container has exited and been removed has + # never been supported by kata-containers (neither with the go-based nor + # the rust-based runtime). The kata VM shuts down when its last container + # is removed, so any attempt to start a new container in the same sandbox + # fails. This test exercises a use-case kata does not currently support. + passing_test="TestContainerStats|TestContainerListStatsWithIdFilter|TestContainerListStatsWithIdSandboxIdFilter|TestDuplicateName|TestImageLoad|TestImageFSInfo|TestSandboxCleanRemove" if [[ "${KATA_HYPERVISOR}" == "clh-runtime-rs" || \ "${KATA_HYPERVISOR}" == "qemu" ]]; then From b5349f4d78a84d73c4337b10d76564ee5496f088 Mon Sep 17 00:00:00 2001 From: Alex Lyn Date: Wed, 6 May 2026 17:27:25 +0800 Subject: [PATCH 10/11] versions: bump containerd to 2.3 for sandbox API tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit containerd 2.3 requires Go 1.26.3, but Kata still pins Go 1.25.10. Use Go 1.26.3 for the sandbox-api job so that make cri-integration can build containerd from source. Signed-off-by: Fabiano Fidêncio Signed-off-by: Alex Lyn --- .github/workflows/basic-ci-amd64.yaml | 13 ++++--------- tests/common.bash | 8 ++++++++ .../integration/cri-containerd/integration-tests.sh | 4 +++- versions.yaml | 1 + 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/.github/workflows/basic-ci-amd64.yaml b/.github/workflows/basic-ci-amd64.yaml index d8fec03a60..72348b2454 100644 --- a/.github/workflows/basic-ci-amd64.yaml +++ b/.github/workflows/basic-ci-amd64.yaml @@ -28,7 +28,7 @@ jobs: # all the tests due to a single flaky instance. fail-fast: false matrix: - containerd_version: ['active'] + containerd_version: ['sandbox_api'] vmm: ['dragonball', 'clh-runtime-rs', 'qemu-runtime-rs'] concurrency: group: ${{ github.workflow }}-${{ github.job }}-${{ github.event.pull_request.number || github.ref }}-sandboxapi-amd64-${{ toJSON(matrix) }} @@ -58,16 +58,11 @@ jobs: env: INSTALL_IN_GOPATH: false - - name: Read properties from versions.yaml - run: | - go_version="$(yq '.languages.golang.version' versions.yaml)" - [ -n "$go_version" ] - echo "GO_VERSION=${go_version}" >> "$GITHUB_ENV" - - - name: Setup Golang version ${{ env.GO_VERSION }} + # TODO: revert to versions.yaml Go once Kata bumps to a Go version compatible with containerd 2.3 + - name: Setup Golang 1.26.3 (required by containerd 2.3) uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: - go-version: ${{ env.GO_VERSION }} + go-version: "1.26.3" - name: Install dependencies run: bash tests/integration/cri-containerd/gha-run.sh install-dependencies diff --git a/tests/common.bash b/tests/common.bash index 256265d344..7c740a089f 100644 --- a/tests/common.bash +++ b/tests/common.bash @@ -767,6 +767,14 @@ function get_latest_patch_release_from_a_github_project() { | grep "${regex}" -m1 } +# GitHub Actions' setup-go often sets GOTOOLCHAIN=local, which forbids fetching a newer +# toolchain required by cloned containerd (e.g. v2.3 go.mod vs Kata's pinned Go). Use +# automatic toolchain selection only while building upstream containerd. +function export_go_toolchain_for_containerd_source_builds() { + export GOTOOLCHAIN=auto + info "GOTOOLCHAIN=auto so containerd is built with the toolchain its go.mod requires" +} + # base_version: The version to be intalled in the ${major}.${minor} format function clone_cri_containerd() { base_version="${1}" diff --git a/tests/integration/cri-containerd/integration-tests.sh b/tests/integration/cri-containerd/integration-tests.sh index 56ef6955d5..5ec7d7ce73 100755 --- a/tests/integration/cri-containerd/integration-tests.sh +++ b/tests/integration/cri-containerd/integration-tests.sh @@ -113,7 +113,7 @@ function create_containerd_config() { fi # check containerd config version - if containerd config default | grep -q "version = 3\>"; then + if containerd config default | grep -qE "^version = [34]"; then pluginid=\"io.containerd.cri.v1.runtime\" else pluginid="cri" @@ -669,6 +669,8 @@ function main() { pushd "containerd" + export_go_toolchain_for_containerd_source_builds + # Make sure the right artifacts are going to be built sudo make clean diff --git a/versions.yaml b/versions.yaml index cc46e7f8e3..93cad9e9f1 100644 --- a/versions.yaml +++ b/versions.yaml @@ -315,6 +315,7 @@ externals: version: "v1.7.25" lts: "v1.7" active: "v2.2" + sandbox_api: "v2.3" critools: description: "CLI tool for Container Runtime Interface (CRI)" From adf6d43e2433bc6618f08c4509b212a984c51673 Mon Sep 17 00:00:00 2001 From: Alex Lyn Date: Thu, 14 May 2026 14:29:31 +0800 Subject: [PATCH 11/11] test: skip TestContainerMemoryUpdate for sandbox api Temporarily skip the `TestContainerMemoryUpdate` test case for sandbox api. This test case is currently skipped in other VMMs (e.g., QEMU, Cloud-Hypervisor) due to known issues and environmental stability concerns. To maintain consistency across the project, we are skipping it for sandbox as well. A follow-up PR will be dedicated to addressing these issues and properly enabling/refining this test case for all VMMs. Signed-off-by: Alex Lyn --- tests/integration/cri-containerd/integration-tests.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/integration/cri-containerd/integration-tests.sh b/tests/integration/cri-containerd/integration-tests.sh index 5ec7d7ce73..7a144cea34 100755 --- a/tests/integration/cri-containerd/integration-tests.sh +++ b/tests/integration/cri-containerd/integration-tests.sh @@ -275,7 +275,8 @@ function TestContainerMemoryUpdate() { # Currently, dragonball fails at decrease memory, just test increasing memory. # We'll re-enable it as soon as we get it to work. # Reference: https://github.com/kata-containers/kata-containers/issues/8804 - DoContainerMemoryUpdate 0 + # DoContainerMemoryUpdate 0 + info "TestContainerMemoryUpdate skipped for dragonball" fi if [[ "${KATA_HYPERVISOR}" == "qemu-runtime-rs" ]]; then