Compare commits

..

2 Commits

Author SHA1 Message Date
Fabiano Fidêncio
446a083f3e genpolicy: Adapt to CRI-O
Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2026-02-24 17:01:09 +01:00
Fabiano Fidêncio
e58f4bceb0 tests: Add CRI-O tests for qemu-coco-dev
We had zero tests with CRI-O for these setups. This adds CRI-O to the CoCo
nontee matrix (same scenarios as containerd, but without auto-generated policy
for now). Vanilla k8s can now be deployed with kubeadm using CRI-O; CRI-O
version is derived from the current k8s stable and we fall back to x.y-1 if
that CRI-O release isn't out yet.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2026-02-24 17:01:04 +01:00
421 changed files with 10374 additions and 44408 deletions

View File

@@ -28,9 +28,3 @@ self-hosted-runner:
- s390x-large
- tdx
- ubuntu-24.04-arm
paths:
.github/workflows/**/*.{yml,yaml}:
ignore:
# We use if: false to "temporarily" skip jobs with issues
- 'constant expression "false" in condition'

View File

@@ -15,8 +15,6 @@ updates:
- "/src/tools/trace-forwarder"
schedule:
interval: "daily"
cooldown:
default-days: 7
ignore:
# rust-vmm repos might cause incompatibilities on patch versions, so
# lets handle them manually for now.
@@ -87,12 +85,8 @@ updates:
- "src/tools/csi-kata-directvolume"
schedule:
interval: "daily"
cooldown:
default-days: 7
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
cooldown:
default-days: 7

View File

@@ -13,13 +13,18 @@ concurrency:
jobs:
run-actionlint:
name: run-actionlint
env:
GH_TOKEN: ${{ github.token }}
runs-on: ubuntu-24.04
steps:
- name: Checkout the code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
persist-credentials: false
- name: Install actionlint gh extension
run: gh extension install https://github.com/cschleiden/gh-actionlint
- name: Run actionlint
uses: raven-actions/actionlint@e01d1ea33dd6a5ed517d95b4c0c357560ac6f518 # v2.1.1
run: gh actionlint

View File

@@ -47,23 +47,6 @@ jobs:
env:
TARGET_BRANCH: ${{ inputs.target-branch }}
- name: Install yq
run: |
./ci/install_yq.sh
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 }}
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: ${{ env.GO_VERSION }}
- name: Install dependencies
run: bash tests/integration/cri-containerd/gha-run.sh install-dependencies
env:

View File

@@ -47,25 +47,8 @@ jobs:
env:
TARGET_BRANCH: ${{ inputs.target-branch }}
- name: Install yq
run: |
./ci/install_yq.sh
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 }}
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: ${{ env.GO_VERSION }}
- name: Install dependencies
run: bash tests/integration/cri-containerd/gha-run.sh install-dependencies
run: bash tests/integration/cri-containerd/gha-run.sh
env:
GH_TOKEN: ${{ github.token }}

View File

@@ -82,17 +82,11 @@ jobs:
./ci/install_yq.sh
env:
INSTALL_IN_GOPATH: false
- name: Read properties from versions.yaml
- name: Install golang
if: contains(matrix.component.needs, 'golang')
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 }}
if: contains(matrix.component.needs, 'golang')
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: ${{ env.GO_VERSION }}
./tests/install_go.sh -f -p
echo "/usr/local/go/bin" >> "$GITHUB_PATH"
- name: Setup rust
if: contains(matrix.component.needs, 'rust')
run: |

View File

@@ -94,19 +94,11 @@ jobs:
./ci/install_yq.sh
env:
INSTALL_IN_GOPATH: false
- name: Read properties from versions.yaml
- name: Install golang
if: contains(matrix.component.needs, 'golang')
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 }}
if: contains(matrix.component.needs, 'golang')
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: ${{ env.GO_VERSION }}
# Setup-go doesn't work properly with ppc64le: https://github.com/actions/setup-go/issues/648
architecture: ${{ contains(inputs.instance, 'ppc64le') && 'ppc64le' || '' }}
./tests/install_go.sh -f -p
echo "/usr/local/go/bin" >> "$GITHUB_PATH"
- name: Setup rust
if: contains(matrix.component.needs, 'rust')
run: |

View File

@@ -143,7 +143,7 @@ jobs:
if-no-files-found: error
- name: store-extratarballs-artifact ${{ matrix.asset }}
if: ${{ startsWith(matrix.asset, 'kernel-nvidia-gpu') }}
if: ${{ matrix.asset == 'kernel' || startsWith(matrix.asset, 'kernel-nvidia-gpu') }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: kata-artifacts-amd64-${{ matrix.asset }}-modules${{ inputs.tarball-suffix }}
@@ -235,6 +235,7 @@ jobs:
asset:
- busybox
- coco-guest-components
- kernel-modules
- kernel-nvidia-gpu-modules
- pause-image
steps:
@@ -367,6 +368,7 @@ jobs:
matrix:
asset:
- agent-ctl
- csi-kata-directvolume
- genpolicy
- kata-ctl
- kata-manager

View File

@@ -120,6 +120,15 @@ jobs:
retention-days: 15
if-no-files-found: error
- name: store-extratarballs-artifact ${{ matrix.asset }}
if: ${{ matrix.asset == 'kernel' }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: kata-artifacts-s390x-${{ matrix.asset }}-modules${{ inputs.tarball-suffix }}
path: kata-build/kata-static-${{ matrix.asset }}-modules.tar.zst
retention-days: 15
if-no-files-found: error
build-asset-rootfs:
name: build-asset-rootfs
runs-on: s390x

View File

@@ -17,7 +17,6 @@ jobs:
pr-number: "dev"
tag: ${{ github.sha }}-dev
target-branch: ${{ github.ref_name }}
extensive-matrix-autogenerated-policy: "yes"
secrets:
AUTHENTICATED_IMAGE_PASSWORD: ${{ secrets.AUTHENTICATED_IMAGE_PASSWORD }}

View File

@@ -22,7 +22,6 @@ jobs:
pr-number: "nightly"
tag: ${{ github.sha }}-nightly
target-branch: ${{ github.ref_name }}
extensive-matrix-autogenerated-policy: "yes"
secrets:
AUTHENTICATED_IMAGE_PASSWORD: ${{ secrets.AUTHENTICATED_IMAGE_PASSWORD }}
AZ_APPID: ${{ secrets.AZ_APPID }}

View File

@@ -19,10 +19,6 @@ on:
required: false
type: string
default: no
extensive-matrix-autogenerated-policy:
required: false
type: string
default: no
secrets:
AUTHENTICATED_IMAGE_PASSWORD:
required: true
@@ -216,6 +212,61 @@ jobs:
platforms: linux/amd64, linux/s390x
file: tests/integration/kubernetes/runtimeclass_workloads/confidential/unencrypted/Dockerfile
publish-csi-driver-amd64:
name: publish-csi-driver-amd64
needs: build-kata-static-tarball-amd64
permissions:
contents: read
packages: write
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ inputs.commit-hash }}
fetch-depth: 0
persist-credentials: false
- name: Rebase atop of the latest target branch
run: |
./tests/git-helper.sh "rebase-atop-of-the-latest-target-branch"
env:
TARGET_BRANCH: ${{ inputs.target-branch }}
- name: get-kata-tools-tarball
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: kata-tools-static-tarball-amd64-${{ inputs.tag }}
path: kata-tools-artifacts
- name: Install kata-tools
run: bash tests/integration/kubernetes/gha-run.sh install-kata-tools kata-tools-artifacts
- name: Copy binary into Docker context
run: |
# Copy to the location where the Dockerfile expects the binary.
mkdir -p src/tools/csi-kata-directvolume/bin/
cp /opt/kata/bin/csi-kata-directvolume src/tools/csi-kata-directvolume/bin/directvolplugin
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
- name: Login to Kata Containers ghcr.io
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker build and push
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
with:
tags: ghcr.io/kata-containers/csi-kata-directvolume:${{ inputs.pr-number }}
push: true
context: src/tools/csi-kata-directvolume/
platforms: linux/amd64
file: src/tools/csi-kata-directvolume/Dockerfile
run-kata-monitor-tests:
if: ${{ inputs.skip-test != 'yes' }}
needs: build-kata-static-tarball-amd64
@@ -294,6 +345,7 @@ jobs:
needs:
- publish-kata-deploy-payload-amd64
- build-and-publish-tee-confidential-unencrypted-image
- publish-csi-driver-amd64
uses: ./.github/workflows/run-kata-coco-tests.yaml
permissions:
contents: read
@@ -306,7 +358,6 @@ jobs:
commit-hash: ${{ inputs.commit-hash }}
pr-number: ${{ inputs.pr-number }}
target-branch: ${{ inputs.target-branch }}
extensive-matrix-autogenerated-policy: ${{ inputs.extensive-matrix-autogenerated-policy }}
secrets:
AUTHENTICATED_IMAGE_PASSWORD: ${{ secrets.AUTHENTICATED_IMAGE_PASSWORD }}
AZ_APPID: ${{ secrets.AZ_APPID }}

View File

@@ -72,7 +72,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@4bdb89f48054571735e3792627da6195c57459e2 # v3.31.10
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -95,6 +95,6 @@ jobs:
make -C src/runtime
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@4bdb89f48054571735e3792627da6195c57459e2 # v3.31.10
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View File

@@ -31,22 +31,10 @@ jobs:
with:
persist-credentials: false
- name: Install yq
- name: Install golang
run: |
./ci/install_yq.sh
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 }}
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: ${{ env.GO_VERSION }}
./tests/install_go.sh -f -p
echo "/usr/local/go/bin" >> "${GITHUB_PATH}"
- name: Install Rust
run: ./tests/install_rust.sh

View File

@@ -24,22 +24,10 @@ jobs:
fetch-depth: 0
persist-credentials: false
- name: Install yq
- name: Install golang
run: |
./ci/install_yq.sh
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 }}
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: ${{ env.GO_VERSION }}
./tests/install_go.sh -f -p
echo "/usr/local/go/bin" >> "${GITHUB_PATH}"
- name: Docs URL Alive Check
run: |

View File

@@ -16,17 +16,17 @@ jobs:
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
- uses: actions/configure-pages@v5
- uses: actions/checkout@v5
with:
persist-credentials: false
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
- uses: actions/setup-python@v5
with:
python-version: 3.x
- run: pip install zensical
- run: zensical build --clean
- uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
- uses: actions/upload-pages-artifact@v4
with:
path: site
- uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
- uses: actions/deploy-pages@v4
id: deployment

View File

@@ -27,22 +27,10 @@ jobs:
fetch-depth: 0
persist-credentials: false
- name: Install yq
- name: Install golang
run: |
./ci/install_yq.sh
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 }}
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: ${{ env.GO_VERSION }}
./tests/install_go.sh -f -p
echo "/usr/local/go/bin" >> "${GITHUB_PATH}"
- name: Install govulncheck
run: |

View File

@@ -35,6 +35,8 @@ on:
jobs:
run-cri-containerd:
name: run-cri-containerd-${{ inputs.arch }} (${{ inputs.containerd_version }}, ${{ inputs.vmm }})
strategy:
fail-fast: false
runs-on: ${{ inputs.runner }}
env:
CONTAINERD_VERSION: ${{ inputs.containerd_version }}
@@ -53,25 +55,6 @@ jobs:
env:
TARGET_BRANCH: ${{ inputs.target-branch }}
- name: Install yq
run: |
./ci/install_yq.sh
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 }}
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: ${{ env.GO_VERSION }}
# Setup-go doesn't work properly with ppc64le: https://github.com/actions/setup-go/issues/648
architecture: ${{ inputs.arch == 'ppc64le' && 'ppc64le' || '' }}
- name: Install dependencies
timeout-minutes: 15
run: bash tests/integration/cri-containerd/gha-run.sh install-dependencies

View File

@@ -57,24 +57,10 @@ jobs:
env:
TARGET_BRANCH: ${{ inputs.target-branch }}
- name: Install yq
- name: Install golang
run: |
./ci/install_yq.sh
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 }}
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: ${{ env.GO_VERSION }}
# Setup-go doesn't work properly with ppc64le: https://github.com/actions/setup-go/issues/648
architecture: 'ppc64le'
./tests/install_go.sh -f -p
echo "/usr/local/go/bin" >> "$GITHUB_PATH"
- name: Prepare the runner for k8s test suite
run: bash "${HOME}/scripts/k8s_cluster_prepare.sh"

View File

@@ -24,10 +24,6 @@ on:
required: false
type: string
default: ""
extensive-matrix-autogenerated-policy:
required: false
type: string
default: no
secrets:
AUTHENTICATED_IMAGE_PASSWORD:
required: true
@@ -110,6 +106,10 @@ jobs:
timeout-minutes: 10
run: bash tests/integration/kubernetes/gha-run.sh install-kbs-client
- name: Deploy CSI driver
timeout-minutes: 5
run: bash tests/integration/kubernetes/gha-run.sh deploy-csi-driver
- name: Run tests
timeout-minutes: 100
run: bash tests/integration/kubernetes/gha-run.sh run-tests
@@ -130,6 +130,10 @@ jobs:
[[ "${KATA_HYPERVISOR}" == "qemu-tdx" ]] && echo "ITA_KEY=${GH_ITA_KEY}" >> "${GITHUB_ENV}"
bash tests/integration/kubernetes/gha-run.sh delete-coco-kbs
- name: Delete CSI driver
timeout-minutes: 5
run: bash tests/integration/kubernetes/gha-run.sh delete-csi-driver
# Generate jobs for testing CoCo on non-TEE environments
run-k8s-tests-coco-nontee:
name: run-k8s-tests-coco-nontee
@@ -227,6 +231,10 @@ jobs:
timeout-minutes: 10
run: bash tests/integration/kubernetes/gha-run.sh install-kbs-client
- name: Deploy CSI driver
timeout-minutes: 5
run: bash tests/integration/kubernetes/gha-run.sh deploy-csi-driver
- name: Run tests
timeout-minutes: 80
run: bash tests/integration/kubernetes/gha-run.sh run-tests
@@ -245,28 +253,19 @@ jobs:
timeout-minutes: 10
run: bash tests/integration/kubernetes/gha-run.sh delete-coco-kbs
# Extensive matrix: autogenerated policy tests (nydus + experimental-force-guest-pull) on k0s, k3s, rke2, microk8s with qemu-coco-dev / qemu-coco-dev-runtime-rs
run-k8s-tests-coco-nontee-extensive-matrix:
if: ${{ inputs.extensive-matrix-autogenerated-policy == 'yes' }}
name: run-k8s-tests-coco-nontee-extensive-matrix
- name: Delete CSI driver
if: always()
timeout-minutes: 5
run: bash tests/integration/kubernetes/gha-run.sh delete-csi-driver
run-k8s-tests-coco-nontee-crio:
name: run-k8s-tests-coco-nontee-crio
strategy:
fail-fast: false
matrix:
environment: [
{ k8s: k0s, vmm: qemu-coco-dev, snapshotter: nydus, pull_type: guest-pull },
{ k8s: k0s, vmm: qemu-coco-dev, snapshotter: "", pull_type: experimental-force-guest-pull },
{ k8s: k0s, vmm: qemu-coco-dev-runtime-rs, snapshotter: nydus, pull_type: guest-pull },
{ k8s: k3s, vmm: qemu-coco-dev, snapshotter: nydus, pull_type: guest-pull },
{ k8s: k3s, vmm: qemu-coco-dev, snapshotter: "", pull_type: experimental-force-guest-pull },
{ k8s: k3s, vmm: qemu-coco-dev-runtime-rs, snapshotter: nydus, pull_type: guest-pull },
{ k8s: rke2, vmm: qemu-coco-dev, snapshotter: nydus, pull_type: guest-pull },
{ k8s: rke2, vmm: qemu-coco-dev, snapshotter: "", pull_type: experimental-force-guest-pull },
{ k8s: rke2, vmm: qemu-coco-dev-runtime-rs, snapshotter: nydus, pull_type: guest-pull },
{ k8s: microk8s, vmm: qemu-coco-dev, snapshotter: nydus, pull_type: guest-pull },
{ k8s: microk8s, vmm: qemu-coco-dev, snapshotter: "", pull_type: experimental-force-guest-pull },
{ k8s: microk8s, vmm: qemu-coco-dev-runtime-rs, snapshotter: nydus, pull_type: guest-pull },
]
runs-on: ubuntu-24.04
vmm:
- qemu-coco-dev
runs-on: fidencio-crio
permissions:
contents: read
environment: ci
@@ -275,17 +274,20 @@ jobs:
DOCKER_REPO: ${{ inputs.repo }}
DOCKER_TAG: ${{ inputs.tag }}
GH_PR_NUMBER: ${{ inputs.pr-number }}
KATA_HYPERVISOR: ${{ matrix.environment.vmm }}
KATA_HYPERVISOR: ${{ matrix.vmm }}
KBS: "true"
KBS_INGRESS: "nodeport"
KUBERNETES: ${{ matrix.environment.k8s }}
SNAPSHOTTER: ${{ matrix.environment.snapshotter }}
PULL_TYPE: ${{ matrix.environment.pull_type }}
EXPERIMENTAL_FORCE_GUEST_PULL: ${{ matrix.environment.pull_type == 'experimental-force-guest-pull' && matrix.environment.vmm || '' }}
KUBERNETES: "vanilla"
PULL_TYPE: "guest-pull"
AUTHENTICATED_IMAGE_USER: ${{ vars.AUTHENTICATED_IMAGE_USER }}
AUTHENTICATED_IMAGE_PASSWORD: ${{ secrets.AUTHENTICATED_IMAGE_PASSWORD }}
SNAPSHOTTER: ""
EXPERIMENTAL_FORCE_GUEST_PULL: ""
AUTO_GENERATE_POLICY: "yes"
K8S_TEST_HOST_TYPE: "all"
CONTAINER_ENGINE: "crio"
CONTAINER_RUNTIME: "crio"
CONTAINER_ENGINE_VERSION: "active"
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
@@ -309,36 +311,9 @@ jobs:
- name: Install kata-tools
run: bash tests/integration/kubernetes/gha-run.sh install-kata-tools kata-tools-artifacts
- name: Remove unnecessary directories to free up space
run: |
sudo rm -rf /usr/local/.ghcup
sudo rm -rf /opt/hostedtoolcache/CodeQL
sudo rm -rf /usr/local/lib/android
sudo rm -rf /usr/share/dotnet
sudo rm -rf /opt/ghc
sudo rm -rf /usr/local/share/boost
sudo rm -rf /usr/lib/jvm
sudo rm -rf /usr/share/swift
sudo rm -rf /usr/local/share/powershell
sudo rm -rf /usr/local/julia*
sudo rm -rf /opt/az
sudo rm -rf /usr/local/share/chromium
sudo rm -rf /opt/microsoft
sudo rm -rf /opt/google
sudo rm -rf /usr/lib/firefox
- name: Deploy ${{ matrix.environment.k8s }}
timeout-minutes: 15
run: bash tests/integration/kubernetes/gha-run.sh deploy-k8s
- name: Install `bats`
run: bash tests/integration/kubernetes/gha-run.sh install-bats
- name: Deploy Kata
timeout-minutes: 20
run: bash tests/integration/kubernetes/gha-run.sh deploy-kata
env:
USE_EXPERIMENTAL_SETUP_SNAPSHOTTER: ${{ matrix.environment.snapshotter == 'nydus' }}
- name: Deploy CoCo KBS
timeout-minutes: 10
@@ -348,6 +323,10 @@ jobs:
timeout-minutes: 10
run: bash tests/integration/kubernetes/gha-run.sh install-kbs-client
- name: Deploy CSI driver
timeout-minutes: 5
run: bash tests/integration/kubernetes/gha-run.sh deploy-csi-driver
- name: Run tests
timeout-minutes: 80
run: bash tests/integration/kubernetes/gha-run.sh run-tests
@@ -366,6 +345,11 @@ jobs:
timeout-minutes: 10
run: bash tests/integration/kubernetes/gha-run.sh delete-coco-kbs
- name: Delete CSI driver
if: always()
timeout-minutes: 5
run: bash tests/integration/kubernetes/gha-run.sh delete-csi-driver
# Generate jobs for testing CoCo on non-TEE environments with erofs-snapshotter
run-k8s-tests-coco-nontee-with-erofs-snapshotter:
name: run-k8s-tests-coco-nontee-with-erofs-snapshotter
@@ -452,6 +436,10 @@ jobs:
timeout-minutes: 20
run: bash tests/integration/kubernetes/gha-run.sh deploy-kata
- name: Deploy CSI driver
timeout-minutes: 5
run: bash tests/integration/kubernetes/gha-run.sh deploy-csi-driver
- name: Run tests
timeout-minutes: 80
run: bash tests/integration/kubernetes/gha-run.sh run-tests
@@ -464,3 +452,8 @@ jobs:
if: always()
timeout-minutes: 15
run: bash tests/integration/kubernetes/gha-run.sh cleanup
- name: Delete CSI driver
if: always()
timeout-minutes: 5
run: bash tests/integration/kubernetes/gha-run.sh delete-csi-driver

View File

@@ -55,6 +55,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard (optional).
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@4bdb89f48054571735e3792627da6195c57459e2 # v3.31.10
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif

View File

@@ -126,16 +126,11 @@ jobs:
./ci/install_yq.sh
env:
INSTALL_IN_GOPATH: false
- name: Read properties from versions.yaml
- name: Install golang
run: |
cd "${GOPATH}/src/github.com/${GITHUB_REPOSITORY}"
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 }}
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: ${{ env.GO_VERSION }}
./tests/install_go.sh -f -p
echo "/usr/local/go/bin" >> "$GITHUB_PATH"
- name: Install system dependencies
run: |
sudo apt-get update && sudo apt-get -y install moreutils hunspell hunspell-en-gb hunspell-en-us pandoc

3
.gitignore vendored
View File

@@ -20,6 +20,3 @@ tools/packaging/static-build/agent/install_libseccomp.sh
.direnv
**/.DS_Store
site/
opt/
tools/packaging/kernel/configs/**/.config
root_hash.txt

1720
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -22,9 +22,6 @@ members = [
"src/dragonball/dbs_utils",
"src/dragonball/dbs_virtio_devices",
# genpolicy
"src/tools/genpolicy",
# runtime-rs
"src/runtime-rs",
"src/runtime-rs/crates/agent",
@@ -110,9 +107,6 @@ safe-path = { path = "src/libs/safe-path" }
shim-interface = { path = "src/libs/shim-interface" }
test-utils = { path = "src/libs/test-utils" }
# Local dependencies from `src/agent`
kata-agent-policy = { path = "src/agent/policy" }
# Outside dependencies
actix-rt = "2.7.0"
anyhow = "1.0"

View File

@@ -187,10 +187,9 @@ different compared to `runc` containers:
into the guest and exposes it directly to the container.
**Mounting guest devices**: When the source path of a hostPath volume is
under `/dev` (or `/dev` itself), and the path corresponds to a
non-regular file (i.e., a device, directory, or any other special file)
or is not accessible by the Kata shim, the Kata agent bind mounts the
source path directly from the *guest* filesystem into the container.
under `/dev`, and the path either corresponds to a host device or is not
accessible by the Kata shim, the Kata agent bind mounts the source path
directly from the *guest* filesystem into the container.
[runtime-config]: /src/runtime/README.md#configuration
[k8s-hostpath]: https://kubernetes.io/docs/concepts/storage/volumes/#hostpath
@@ -227,35 +226,6 @@ Importantly, the default behavior to pass the host devices to a
privileged container is not supported in Kata Containers and needs to be
disabled, see [Privileged Kata Containers](how-to/privileged.md).
## Guest pulled container images
When using features like **nydus guest-pull**, set user/group IDs explicitly in the pod spec.
If the ID values are omitted:
- Your workload might be executed with unexpected user/group ID values, because image layers
may be unavailable to containerd, so image config (including user/group) is not applied.
- If using policy or genpolicy, the generated policy may detect these unexpected values and
reject the creation of workload containers.
Set `securityContext` explicitly. Use **pod-level** `spec.securityContext` (for Pods) or
`spec.template.spec.securityContext` (for controllers like Deployments) and/or **container-level**
`spec.containers[].securityContext`. Include at least:
- `runAsUser` — primary user ID
- `runAsGroup` — primary group ID
- `fsGroup` — volume group ownership (often reflected as a supplemental group)
- `supplementalGroups` — list of additional group IDs (if needed)
Example:
```yaml
# Explicit user/group/supplementary groups to support nydus guest-pull
securityContext:
runAsUser: 0
runAsGroup: 0
fsGroup: 0
supplementalGroups: [1, 2, 3, 4, 6, 10, 11, 20, 26, 27]
```
# Appendices
## The constraints challenge

View File

@@ -99,9 +99,6 @@ The [`genpolicy`](../../src/tools/genpolicy/) application can be used to generat
**Warning** Users should review carefully the automatically-generated Policy, and modify the Policy file if needed to match better their use case, before using this Policy.
**Important — User / Group / Supplemental groups for Policy and genpolicy**
When using features like **nydus guest-pull**, set user/group IDs explicitly in the pod spec, as described in [Limitations](../Limitations.md#guest-pulled-container-images).
See the [`genpolicy` documentation](../../src/tools/genpolicy/README.md) and the [Policy contents examples](#policy-contents) for additional information.
## Policy contents

View File

@@ -1,8 +0,0 @@
[[IgnoredVulns]]
# yaml-rust is unmaintained.
# We tried the most promising alternative in https://github.com/kata-containers/kata-containers/pull/12509,
# but its literal quoting is not conformant.
id = "RUSTSEC-2024-0320"
ignoreUntil = 2026-10-01 # TODO(burgerdev): revisit yml library ecosystem
reason = "No alternative currently supports 'yes' strings correctly; genpolicy processes only trusted input."

48
src/agent/Cargo.lock generated
View File

@@ -743,6 +743,12 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "common-path"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101"
[[package]]
name = "concurrent-queue"
version = "2.5.0"
@@ -979,12 +985,6 @@ dependencies = [
"parking_lot_core",
]
[[package]]
name = "data-encoding"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
[[package]]
name = "deranged"
version = "0.5.5"
@@ -1098,18 +1098,6 @@ dependencies = [
"serde",
]
[[package]]
name = "enum-as-inner"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc"
dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.101",
]
[[package]]
name = "enumflags2"
version = "0.7.11"
@@ -2114,6 +2102,8 @@ version = "0.1.0"
dependencies = [
"anyhow",
"byteorder",
"chrono",
"common-path",
"fail",
"hex",
"kata-types",
@@ -2122,9 +2112,11 @@ dependencies = [
"mockall",
"nix 0.26.4",
"oci-spec",
"once_cell",
"pci-ids",
"rand",
"runtime-spec",
"safe-path",
"serde",
"serde_json",
"slog",
@@ -2143,8 +2135,8 @@ dependencies = [
"byte-unit",
"flate2",
"glob",
"hex",
"lazy_static",
"nix 0.26.4",
"num_cpus",
"oci-spec",
"regex",
@@ -2155,7 +2147,6 @@ dependencies = [
"sha2 0.10.9",
"slog",
"slog-scope",
"sysctl",
"sysinfo",
"thiserror 1.0.69",
"toml",
@@ -2315,6 +2306,7 @@ name = "mem-agent"
version = "0.2.0"
dependencies = [
"anyhow",
"async-trait",
"chrono",
"maplit",
"nix 0.30.1",
@@ -3434,7 +3426,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843c3d97f07e3b5ac0955d53ad0af4c91fe4a4f8525843ece5bf014f27829b73"
dependencies = [
"anyhow",
"data-encoding",
"lazy_static",
"rand",
"regex",
@@ -3584,6 +3575,7 @@ dependencies = [
name = "runtime-spec"
version = "0.1.0"
dependencies = [
"libc",
"serde",
"serde_derive",
"serde_json",
@@ -4223,20 +4215,6 @@ dependencies = [
"syn 2.0.101",
]
[[package]]
name = "sysctl"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cca424247104946a59dacd27eaad296223b7feec3d168a6dd04585183091eb0b"
dependencies = [
"bitflags 2.9.0",
"byteorder",
"enum-as-inner",
"libc",
"thiserror 2.0.12",
"walkdir",
]
[[package]]
name = "sysinfo"
version = "0.34.2"

View File

@@ -18,8 +18,6 @@ serde_json.workspace = true
# Agent Policy
regorus = { version = "0.2.8", default-features = false, features = [
"arc",
"base64",
"base64url",
"regex",
"std",
] }

View File

@@ -2308,6 +2308,9 @@ fn is_sealed_secret_path(source_path: &str) -> bool {
}
async fn cdh_handler_trusted_storage(oci: &mut Spec) -> Result<()> {
if !confidential_data_hub::is_cdh_client_initialized() {
return Ok(());
}
let linux = oci
.linux()
.as_ref()
@@ -2317,8 +2320,26 @@ async fn cdh_handler_trusted_storage(oci: &mut Spec) -> Result<()> {
for specdev in devices.iter() {
if specdev.path().as_path().to_str() == Some(TRUSTED_IMAGE_STORAGE_DEVICE) {
let dev_major_minor = format!("{}:{}", specdev.major(), specdev.minor());
cdh_secure_mount("BlockDevice", &dev_major_minor, "LUKS", KATA_IMAGE_WORK_DIR)
.await?;
let secure_storage_integrity = AGENT_CONFIG.secure_storage_integrity.to_string();
info!(
sl(),
"trusted_store device major:min {}, enable data integrity {}",
dev_major_minor,
secure_storage_integrity
);
let options = std::collections::HashMap::from([
("deviceId".to_string(), dev_major_minor),
("encryptType".to_string(), "LUKS".to_string()),
("dataIntegrity".to_string(), secure_storage_integrity),
]);
confidential_data_hub::secure_mount(
"BlockDevice",
&options,
vec![],
KATA_IMAGE_WORK_DIR,
)
.await?;
break;
}
}
@@ -2326,38 +2347,6 @@ async fn cdh_handler_trusted_storage(oci: &mut Spec) -> Result<()> {
Ok(())
}
pub(crate) async fn cdh_secure_mount(
device_type: &str,
device_id: &str,
encrypt_type: &str,
mount_point: &str,
) -> Result<()> {
if !confidential_data_hub::is_cdh_client_initialized() {
return Ok(());
}
let integrity = AGENT_CONFIG.secure_storage_integrity.to_string();
info!(
sl(),
"cdh_secure_mount: device_type {}, device_id {}, encrypt_type {}, integrity {}",
device_type,
device_id,
encrypt_type,
integrity
);
let options = std::collections::HashMap::from([
("deviceId".to_string(), device_id.to_string()),
("encryptType".to_string(), encrypt_type.to_string()),
("dataIntegrity".to_string(), integrity),
]);
confidential_data_hub::secure_mount(device_type, &options, vec![], mount_point).await?;
Ok(())
}
async fn cdh_handler_sealed_secrets(oci: &mut Spec) -> Result<()> {
if !confidential_data_hub::is_cdh_client_initialized() {
return Ok(());

View File

@@ -65,12 +65,6 @@ type UeventWatcher = (Box<dyn UeventMatcher>, oneshot::Sender<Uevent>);
pub struct StorageState {
count: Arc<AtomicU32>,
device: Arc<dyn StorageDevice>,
/// Whether the storage is shared across multiple containers (e.g.
/// block-based emptyDirs). Shared storages should not be cleaned up
/// when a container exits; cleanup happens only when the sandbox is
/// destroyed.
shared: bool,
}
impl Debug for StorageState {
@@ -80,11 +74,17 @@ impl Debug for StorageState {
}
impl StorageState {
fn new(shared: bool) -> Self {
fn new() -> Self {
StorageState {
count: Arc::new(AtomicU32::new(1)),
device: Arc::new(StorageDeviceGeneric::default()),
shared,
}
}
pub fn from_device(device: Arc<dyn StorageDevice>) -> Self {
Self {
count: Arc::new(AtomicU32::new(1)),
device,
}
}
@@ -92,10 +92,6 @@ impl StorageState {
self.device.path()
}
pub fn is_shared(&self) -> bool {
self.shared
}
pub async fn ref_count(&self) -> u32 {
self.count.load(Ordering::Relaxed)
}
@@ -175,10 +171,8 @@ impl Sandbox {
/// Add a new storage object or increase reference count of existing one.
/// The caller may detect new storage object by checking `StorageState.refcount == 1`.
/// The `shared` flag indicates if this storage is shared across multiple containers;
/// if true, cleanup will be skipped when containers exit.
#[instrument]
pub async fn add_sandbox_storage(&mut self, path: &str, shared: bool) -> StorageState {
pub async fn add_sandbox_storage(&mut self, path: &str) -> StorageState {
match self.storages.entry(path.to_string()) {
Entry::Occupied(e) => {
let state = e.get().clone();
@@ -186,7 +180,7 @@ impl Sandbox {
state
}
Entry::Vacant(e) => {
let state = StorageState::new(shared);
let state = StorageState::new();
e.insert(state.clone());
state
}
@@ -194,32 +188,22 @@ impl Sandbox {
}
/// Update the storage device associated with a path.
/// Preserves the existing shared flag and reference count.
pub fn update_sandbox_storage(
&mut self,
path: &str,
device: Arc<dyn StorageDevice>,
) -> std::result::Result<Arc<dyn StorageDevice>, Arc<dyn StorageDevice>> {
match self.storages.get(path) {
None => Err(device),
Some(existing) => {
let state = StorageState {
device,
..existing.clone()
};
// Safe to unwrap() because we have just ensured existence of entry via get().
let state = self.storages.insert(path.to_string(), state).unwrap();
Ok(state.device)
}
if !self.storages.contains_key(path) {
return Err(device);
}
let state = StorageState::from_device(device);
// Safe to unwrap() because we have just ensured existence of entry.
let state = self.storages.insert(path.to_string(), state).unwrap();
Ok(state.device)
}
/// Decrease reference count and destroy the storage object if reference count reaches zero.
///
/// For shared storages (e.g., emptyDir volumes), cleanup is skipped even when refcount
/// reaches zero. The storage entry is kept in the map so subsequent containers can reuse
/// the already-mounted storage. Actual cleanup happens when the sandbox is destroyed.
///
/// Returns `Ok(true)` if the reference count has reached zero and the storage object has been
/// removed.
#[instrument]
@@ -228,10 +212,6 @@ impl Sandbox {
None => Err(anyhow!("Sandbox storage with path {} not found", path)),
Some(state) => {
if state.dec_and_test_ref_count().await {
if state.is_shared() {
state.count.store(1, Ordering::Release);
return Ok(false);
}
if let Some(storage) = self.storages.remove(path) {
storage.device.cleanup()?;
}
@@ -740,7 +720,7 @@ mod tests {
let tmpdir_path = tmpdir.path().to_str().unwrap();
// Add a new sandbox storage
let new_storage = s.add_sandbox_storage(tmpdir_path, false).await;
let new_storage = s.add_sandbox_storage(tmpdir_path).await;
// Check the reference counter
let ref_count = new_storage.ref_count().await;
@@ -750,7 +730,7 @@ mod tests {
);
// Use the existing sandbox storage
let new_storage = s.add_sandbox_storage(tmpdir_path, false).await;
let new_storage = s.add_sandbox_storage(tmpdir_path).await;
// Since we are using existing storage, the reference counter
// should be 2 by now.
@@ -791,7 +771,7 @@ mod tests {
assert!(bind_mount(srcdir_path, destdir_path, &logger).is_ok());
s.add_sandbox_storage(destdir_path, false).await;
s.add_sandbox_storage(destdir_path).await;
let storage = StorageDeviceGeneric::new(destdir_path.to_string());
assert!(s
.update_sandbox_storage(destdir_path, Arc::new(storage))
@@ -809,7 +789,7 @@ mod tests {
let other_dir_path = other_dir.path().to_str().unwrap();
other_dir_str = other_dir_path.to_string();
s.add_sandbox_storage(other_dir_path, false).await;
s.add_sandbox_storage(other_dir_path).await;
let storage = StorageDeviceGeneric::new(other_dir_path.to_string());
assert!(s
.update_sandbox_storage(other_dir_path, Arc::new(storage))
@@ -828,9 +808,9 @@ mod tests {
let storage_path = "/tmp/testEphe";
// Add a new sandbox storage
s.add_sandbox_storage(storage_path, false).await;
s.add_sandbox_storage(storage_path).await;
// Use the existing sandbox storage
let state = s.add_sandbox_storage(storage_path, false).await;
let state = s.add_sandbox_storage(storage_path).await;
assert!(
state.ref_count().await > 1,
"Expects false as the storage is not new."

View File

@@ -6,7 +6,7 @@
use crate::linux_abi::pcipath_from_dev_tree_path;
use std::fs;
use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
use std::sync::Arc;
@@ -17,7 +17,6 @@ use kata_types::device::{
DRIVER_BLK_MMIO_TYPE, DRIVER_BLK_PCI_TYPE, DRIVER_NVDIMM_TYPE, DRIVER_SCSI_TYPE,
};
use kata_types::mount::StorageDevice;
use nix::sys::stat::{major, minor};
use protocols::agent::Storage;
use tracing::instrument;
@@ -30,44 +29,10 @@ use crate::device::block_device_handler::{
};
use crate::device::nvdimm_device_handler::wait_for_pmem_device;
use crate::device::scsi_device_handler::get_scsi_device_name;
use crate::storage::{
common_storage_handler, new_device, set_ownership, StorageContext, StorageHandler,
};
use slog::Logger;
use crate::storage::{common_storage_handler, new_device, StorageContext, StorageHandler};
#[cfg(target_arch = "s390x")]
use std::str::FromStr;
fn get_device_number(dev_path: &str, metadata: Option<&fs::Metadata>) -> Result<String> {
let dev_id = match metadata {
Some(m) => m.rdev(),
None => {
let m =
fs::metadata(dev_path).context(format!("get metadata on file {:?}", dev_path))?;
m.rdev()
}
};
Ok(format!("{}:{}", major(dev_id), minor(dev_id)))
}
async fn handle_block_storage(
logger: &Logger,
storage: &Storage,
dev_num: &str,
) -> Result<Arc<dyn StorageDevice>> {
let has_ephemeral_encryption = storage
.driver_options
.contains(&"encryption_key=ephemeral".to_string());
if has_ephemeral_encryption {
crate::rpc::cdh_secure_mount("BlockDevice", dev_num, "LUKS", &storage.mount_point).await?;
set_ownership(logger, storage)?;
new_device(storage.mount_point.clone())
} else {
let path = common_storage_handler(logger, storage)?;
new_device(path)
}
}
#[derive(Debug)]
pub struct VirtioBlkMmioHandler {}
@@ -110,8 +75,6 @@ impl StorageHandler for VirtioBlkPciHandler {
mut storage: Storage,
ctx: &mut StorageContext,
) -> Result<Arc<dyn StorageDevice>> {
let dev_num: String;
// If hot-plugged, get the device node path based on the PCI path
// otherwise use the virt path provided in Storage Source
if storage.source.starts_with("/dev") {
@@ -121,16 +84,15 @@ impl StorageHandler for VirtioBlkPciHandler {
if mode & libc::S_IFBLK == 0 {
return Err(anyhow!("Invalid device {}", &storage.source));
}
dev_num = get_device_number(&storage.source, Some(&metadata))?;
} else {
let (root_complex, pcipath) = pcipath_from_dev_tree_path(&storage.source)?;
let dev_path =
get_virtio_blk_pci_device_name(ctx.sandbox, root_complex, &pcipath).await?;
storage.source = dev_path;
dev_num = get_device_number(&storage.source, None)?;
}
handle_block_storage(ctx.logger, &storage, &dev_num).await
let path = common_storage_handler(ctx.logger, &storage)?;
new_device(path)
}
}
@@ -189,10 +151,10 @@ impl StorageHandler for ScsiHandler {
) -> Result<Arc<dyn StorageDevice>> {
// Retrieve the device path from SCSI address.
let dev_path = get_scsi_device_name(ctx.sandbox, &storage.source).await?;
storage.source = dev_path.clone();
storage.source = dev_path;
let dev_num = get_device_number(&dev_path, None)?;
handle_block_storage(ctx.logger, &storage, &dev_num).await
let path = common_storage_handler(ctx.logger, &storage)?;
new_device(path)
}
}

View File

@@ -172,11 +172,7 @@ pub async fn add_storages(
for storage in storages {
let path = storage.mount_point.clone();
let state = sandbox
.lock()
.await
.add_sandbox_storage(&path, storage.shared)
.await;
let state = sandbox.lock().await.add_sandbox_storage(&path).await;
if state.ref_count().await > 1 {
if let Some(path) = state.path() {
if !path.is_empty() {

View File

@@ -48,6 +48,7 @@ vmm-sys-util = { workspace = true }
virtio-queue = { workspace = true, optional = true }
vm-memory = { workspace = true, features = ["backend-mmap"] }
crossbeam-channel = "0.5.6"
fuse-backend-rs = "0.10.5"
vfio-bindings = { workspace = true, optional = true }
vfio-ioctls = { workspace = true, optional = true }
@@ -85,6 +86,3 @@ host-device = ["dep:vfio-bindings", "dep:vfio-ioctls", "dep:dbs-pci"]
unexpected_cfgs = { level = "warn", check-cfg = [
'cfg(feature, values("test-mock"))',
] }
[package.metadata.cargo-machete]
ignored = ["vfio-bindings"]

View File

@@ -242,7 +242,7 @@ mod tests {
let metrics = Arc::new(SerialDeviceMetrics::default());
let out: Arc<Mutex<Option<Box<dyn std::io::Write + Send + 'static>>>> =
let out: Arc<Mutex<Option<Box<(dyn std::io::Write + Send + 'static)>>>> =
Arc::new(Mutex::new(Some(Box::new(std::io::sink()))));
let mut serial = SerialDevice {
serial: Serial::with_events(

View File

@@ -23,22 +23,24 @@ dbs-interrupt = { workspace = true, features = [
"kvm-legacy-irq",
"kvm-msi-irq",
] }
downcast-rs = "1.2.0"
byteorder = "1.4.3"
serde = "1.0.27"
vm-memory = { workspace = true }
kvm-ioctls = { workspace = true }
kvm-bindings = { workspace = true }
vfio-ioctls = { workspace = true }
vfio-bindings = { workspace = true }
vm-memory = {workspace = true}
kvm-ioctls = {workspace = true}
kvm-bindings = {workspace = true}
vfio-ioctls = {workspace = true}
vfio-bindings = {workspace = true}
libc = "0.2.39"
virtio-queue = { workspace = true }
dbs-utils = { workspace = true }
vmm-sys-util = {workspace = true}
virtio-queue = {workspace = true}
dbs-utils = {workspace = true}
[dev-dependencies]
dbs-arch = { workspace = true }
kvm-ioctls = { workspace = true }
kvm-ioctls = {workspace = true}
test-utils = { workspace = true }
nix = { workspace = true }

View File

@@ -1174,6 +1174,7 @@ pub(crate) mod tests {
use dbs_virtio_devices::Result as VirtIoResult;
use dbs_virtio_devices::{
ActivateResult, VirtioDeviceConfig, VirtioDeviceInfo, VirtioSharedMemory,
DEVICE_ACKNOWLEDGE, DEVICE_DRIVER, DEVICE_DRIVER_OK, DEVICE_FEATURES_OK, DEVICE_INIT,
};
use dbs_address_space::{AddressSpaceLayout, AddressSpaceRegion, AddressSpaceRegionType};

View File

@@ -11,6 +11,7 @@ keywords = ["dragonball", "secure-sandbox", "devices", "upcall", "virtio"]
readme = "README.md"
[dependencies]
anyhow = "1"
log = "0.4.14"
thiserror = "1"
timerfd = "1.2.0"

View File

@@ -99,61 +99,76 @@ impl Default for EpollManager {
#[cfg(test)]
mod tests {
use super::*;
use std::os::fd::AsRawFd;
use std::sync::mpsc::channel;
use std::time::Duration;
use std::os::unix::io::AsRawFd;
use vmm_sys_util::{epoll::EventSet, eventfd::EventFd};
struct DummySubscriber {
pub event: Arc<EventFd>,
pub notify: std::sync::mpsc::Sender<()>,
pub event: EventFd,
}
impl DummySubscriber {
fn new(event: Arc<EventFd>, notify: std::sync::mpsc::Sender<()>) -> Self {
Self { event, notify }
fn new() -> Self {
Self {
event: EventFd::new(0).unwrap(),
}
}
}
impl MutEventSubscriber for DummySubscriber {
fn init(&mut self, ops: &mut EventOps) {
ops.add(Events::new(self.event.as_ref(), EventSet::IN))
.unwrap();
}
fn process(&mut self, events: Events, _ops: &mut EventOps) {
if events.fd() == self.event.as_raw_fd() && events.event_set().contains(EventSet::IN) {
let _ = self.event.read();
let _ = self.notify.send(());
let source = events.fd();
let event_set = events.event_set();
assert_ne!(source, self.event.as_raw_fd());
match event_set {
EventSet::IN => {
unreachable!()
}
EventSet::OUT => {
self.event.read().unwrap();
}
_ => {
unreachable!()
}
}
}
fn init(&mut self, _ops: &mut EventOps) {}
}
#[test]
fn test_epoll_manager() {
let epoll_manager = EpollManager::default();
let (stop_tx, stop_rx) = channel::<()>();
let worker_mgr = epoll_manager.clone();
let worker = std::thread::spawn(move || {
while stop_rx.try_recv().is_err() {
let _ = worker_mgr.handle_events(50);
let mut epoll_manager = EpollManager::default();
let epoll_manager_clone = epoll_manager.clone();
let thread = std::thread::spawn(move || loop {
let count = epoll_manager_clone.handle_events(-1).unwrap();
if count == 0 {
continue;
}
assert_eq!(count, 1);
break;
});
let (notify_tx, notify_rx) = channel::<()>();
let event = Arc::new(EventFd::new(0).unwrap());
let handler = DummySubscriber::new(event.clone(), notify_tx);
let handler = DummySubscriber::new();
let event = handler.event.try_clone().unwrap();
let id = epoll_manager.add_subscriber(Box::new(handler));
thread.join().unwrap();
epoll_manager
.add_event(id, Events::new(&event, EventSet::OUT))
.unwrap();
event.write(1).unwrap();
notify_rx
.recv_timeout(Duration::from_secs(2))
.expect("timeout waiting for subscriber to be processed");
let epoll_manager_clone = epoll_manager.clone();
let thread = std::thread::spawn(move || loop {
let count = epoll_manager_clone.handle_events(-1).unwrap();
if count == 0 {
continue;
}
assert_eq!(count, 2);
break;
});
epoll_manager.clone().remove_subscriber(id).unwrap();
let _ = stop_tx.send(());
worker.join().unwrap();
thread.join().unwrap();
epoll_manager.remove_subscriber(id).unwrap();
}
}

View File

@@ -24,8 +24,8 @@ dbs-boot = { workspace = true }
epoll = ">=4.3.1, <4.3.2"
io-uring = "0.5.2"
fuse-backend-rs = { version = "0.10.5", optional = true }
kvm-bindings = { workspace = true }
kvm-ioctls = { workspace = true }
kvm-bindings = { workspace = true}
kvm-ioctls = {workspace = true}
libc = "0.2.119"
log = "0.4.14"
nix = "0.24.3"
@@ -37,16 +37,19 @@ serde = "1.0.27"
serde_json = "1.0.9"
thiserror = "1"
threadpool = "1"
virtio-bindings = { workspace = true }
virtio-queue = { workspace = true }
vmm-sys-util = { workspace = true }
virtio-bindings = {workspace = true}
virtio-queue = {workspace = true}
vmm-sys-util = {workspace = true}
vm-memory = { workspace = true, features = ["backend-mmap"] }
sendfd = "0.4.3"
vhost-rs = { version = "0.6.1", package = "vhost", optional = true }
timerfd = "1.0"
[dev-dependencies]
vm-memory = { workspace = true, features = ["backend-mmap", "backend-atomic"] }
vm-memory = { workspace = true, features = [
"backend-mmap",
"backend-atomic",
] }
test-utils = { workspace = true }
[features]

View File

@@ -439,19 +439,19 @@ pub mod tests {
VirtqDesc { desc }
}
pub fn addr(&self) -> VolatileRef<'_, u64> {
pub fn addr(&self) -> VolatileRef<u64> {
self.desc.get_ref(offset_of!(DescriptorTmp, addr)).unwrap()
}
pub fn len(&self) -> VolatileRef<'_, u32> {
pub fn len(&self) -> VolatileRef<u32> {
self.desc.get_ref(offset_of!(DescriptorTmp, len)).unwrap()
}
pub fn flags(&self) -> VolatileRef<'_, u16> {
pub fn flags(&self) -> VolatileRef<u16> {
self.desc.get_ref(offset_of!(DescriptorTmp, flags)).unwrap()
}
pub fn next(&self) -> VolatileRef<'_, u16> {
pub fn next(&self) -> VolatileRef<u16> {
self.desc.get_ref(offset_of!(DescriptorTmp, next)).unwrap()
}
@@ -513,11 +513,11 @@ pub mod tests {
self.start.unchecked_add(self.ring.len() as GuestUsize)
}
pub fn flags(&self) -> VolatileRef<'_, u16> {
pub fn flags(&self) -> VolatileRef<u16> {
self.ring.get_ref(0).unwrap()
}
pub fn idx(&self) -> VolatileRef<'_, u16> {
pub fn idx(&self) -> VolatileRef<u16> {
self.ring.get_ref(2).unwrap()
}
@@ -525,12 +525,12 @@ pub mod tests {
4 + mem::size_of::<T>() * (i as usize)
}
pub fn ring(&self, i: u16) -> VolatileRef<'_, T> {
pub fn ring(&self, i: u16) -> VolatileRef<T> {
assert!(i < self.qsize);
self.ring.get_ref(Self::ring_offset(i)).unwrap()
}
pub fn event(&self) -> VolatileRef<'_, u16> {
pub fn event(&self) -> VolatileRef<u16> {
self.ring.get_ref(Self::ring_offset(self.qsize)).unwrap()
}
@@ -602,7 +602,7 @@ pub mod tests {
(self.dtable.len() / VirtqDesc::dtable_len(1)) as u16
}
pub fn dtable(&self, i: u16) -> VirtqDesc<'_> {
pub fn dtable(&self, i: u16) -> VirtqDesc {
VirtqDesc::new(&self.dtable, i)
}

View File

@@ -690,15 +690,6 @@ mod tests {
use crate::tests::{create_address_space, create_vm_and_irq_manager};
use crate::{create_queue_notifier, VirtioQueueConfig};
fn unique_tap_name(prefix: &str) -> String {
use std::sync::atomic::{AtomicUsize, Ordering};
static CNT: AtomicUsize = AtomicUsize::new(0);
let n = CNT.fetch_add(1, Ordering::Relaxed);
// "vtap" + pid(<=5) + n(<=3) => max len <= 15
format!("{}{:x}{:x}", prefix, std::process::id() & 0xfff, n & 0xfff)
}
fn create_vhost_kern_net_epoll_handler(
id: String,
) -> NetEpollHandler<Arc<GuestMemoryMmap>, QueueSync, GuestRegionMmap> {
@@ -732,16 +723,13 @@ mod tests {
let guest_mac = MacAddr::parse_str(guest_mac_str).unwrap();
let queue_sizes = Arc::new(vec![128]);
let epoll_mgr = EpollManager::default();
let tap_name = unique_tap_name("vtap");
let dev_result: VirtioResult<Net<Arc<GuestMemoryMmap>, QueueSync, GuestRegionMmap>> =
Net::new(tap_name.clone(), Some(&guest_mac), queue_sizes, epoll_mgr);
let mut dev: Net<Arc<GuestMemoryMmap>, QueueSync, GuestRegionMmap> = match dev_result {
Ok(d) => d,
Err(e) => {
eprintln!("skip test: failed to create tap {}: {:?}", tap_name, e);
return;
}
};
let mut dev: Net<Arc<GuestMemoryMmap>, QueueSync, GuestRegionMmap> = Net::new(
String::from("test_vhosttap"),
Some(&guest_mac),
queue_sizes,
epoll_mgr,
)
.unwrap();
assert_eq!(dev.device_type(), TYPE_NET);
@@ -777,16 +765,14 @@ mod tests {
{
let queue_sizes = Arc::new(vec![128]);
let epoll_mgr = EpollManager::default();
let tap_name = unique_tap_name("vtap");
let dev_result: VirtioResult<Net<Arc<GuestMemoryMmap>, QueueSync, GuestRegionMmap>> =
Net::new(tap_name.clone(), Some(&guest_mac), queue_sizes, epoll_mgr);
let mut dev: Net<Arc<GuestMemoryMmap>, QueueSync, GuestRegionMmap> = match dev_result {
Ok(d) => d,
Err(e) => {
eprintln!("skip test: failed to create tap {}: {:?}", tap_name, e);
return;
}
};
let mut dev: Net<Arc<GuestMemoryMmap>, QueueSync, GuestRegionMmap> = Net::new(
String::from("test_vhosttap"),
Some(&guest_mac),
queue_sizes,
epoll_mgr,
)
.unwrap();
let queues = vec![
VirtioQueueConfig::create(128, 0).unwrap(),
VirtioQueueConfig::create(128, 0).unwrap(),
@@ -823,17 +809,13 @@ mod tests {
let queue_eventfd2 = Arc::new(EventFd::new(0).unwrap());
let queue_sizes = Arc::new(vec![128, 128]);
let epoll_mgr = EpollManager::default();
let tap_name = unique_tap_name("vtap");
let dev_result: VirtioResult<Net<Arc<GuestMemoryMmap>, Queue, GuestRegionMmap>> =
Net::new(tap_name.clone(), Some(&guest_mac), queue_sizes, epoll_mgr);
let mut dev: Net<Arc<GuestMemoryMmap>, Queue, GuestRegionMmap> = match dev_result {
Ok(d) => d,
Err(e) => {
eprintln!("skip test: failed to create tap {}: {:?}", tap_name, e);
return;
}
};
let mut dev: Net<Arc<GuestMemoryMmap>, Queue, GuestRegionMmap> = Net::new(
String::from("test_vhosttap"),
Some(&guest_mac),
queue_sizes,
epoll_mgr,
)
.unwrap();
let queues = vec![
VirtioQueueConfig::new(queue, queue_eventfd, notifier.clone(), 1),

View File

@@ -865,11 +865,11 @@ mod tests {
0
);
let config: [u8; 8] = [0; 8];
let _ = VirtioDevice::<Arc<GuestMemoryMmap<()>>, QueueSync, GuestRegionMmap>::write_config(
VirtioDevice::<Arc<GuestMemoryMmap<()>>, QueueSync, GuestRegionMmap>::write_config(
&mut dev, 0, &config,
);
let mut data: [u8; 8] = [1; 8];
let _ = VirtioDevice::<Arc<GuestMemoryMmap<()>>, QueueSync, GuestRegionMmap>::read_config(
VirtioDevice::<Arc<GuestMemoryMmap<()>>, QueueSync, GuestRegionMmap>::read_config(
&mut dev, 0, &mut data,
);
assert_eq!(config, data);

View File

@@ -590,7 +590,6 @@ where
mod tests {
use std::sync::Arc;
use std::thread;
use std::time::{Duration, Instant};
use dbs_device::resources::DeviceResources;
use dbs_interrupt::{InterruptManager, InterruptSourceType, MsiNotifier, NoopNotifier};
@@ -610,16 +609,19 @@ mod tests {
};
use crate::{VirtioDevice, VirtioDeviceConfig, VirtioQueueConfig, TYPE_NET};
fn connect_slave(path: &str, timeout: Duration) -> Option<Endpoint<MasterReq>> {
let deadline = Instant::now() + timeout;
fn connect_slave(path: &str) -> Option<Endpoint<MasterReq>> {
let mut retry_count = 5;
loop {
match Endpoint::<MasterReq>::connect(path) {
Ok(ep) => return Some(ep),
Ok(endpoint) => return Some(endpoint),
Err(_) => {
if Instant::now() >= deadline {
if retry_count > 0 {
std::thread::sleep(std::time::Duration::from_millis(100));
retry_count -= 1;
continue;
} else {
return None;
}
thread::sleep(Duration::from_millis(20));
}
}
}
@@ -637,88 +639,62 @@ mod tests {
#[test]
fn test_vhost_user_net_virtio_device_normal() {
let dir_path = std::path::Path::new("/tmp");
let socket_path = dir_path.join(format!(
"vhost-user-net-{}-{:?}.sock",
std::process::id(),
thread::current().id()
));
let socket_str = socket_path.to_str().unwrap().to_string();
let _ = std::fs::remove_file(&socket_path);
let queue_sizes = Arc::new(vec![128u16]);
let device_socket = concat!("vhost.", line!());
let queue_sizes = Arc::new(vec![128]);
let epoll_mgr = EpollManager::default();
let socket_for_slave = socket_str.clone();
let slave_th = thread::spawn(move || {
let mut slave = connect_slave(&socket_for_slave, Duration::from_secs(5))
.unwrap_or_else(|| panic!("slave connect timeout: {}", socket_for_slave));
let handler = thread::spawn(move || {
let mut slave = connect_slave(device_socket).unwrap();
create_vhost_user_net_slave(&mut slave);
});
let (tx, rx) = std::sync::mpsc::channel();
let socket_for_master = socket_str.clone();
let queue_sizes_for_master = queue_sizes.clone();
let epoll_mgr_for_master = epoll_mgr.clone();
thread::spawn(move || {
let res = VhostUserNet::<Arc<GuestMemoryMmap>>::new_server(
&socket_for_master,
None,
queue_sizes_for_master,
epoll_mgr_for_master,
);
let _ = tx.send(res);
});
let dev_res = rx
.recv_timeout(Duration::from_secs(5))
.unwrap_or_else(|_| panic!("new_server() stuck/timeout: {}", socket_str));
let dev: VhostUserNet<Arc<GuestMemoryMmap>> = dev_res.unwrap_or_else(|e| {
panic!(
"new_server() returned error: {:?}, socket={}",
e, socket_str
)
});
let mut dev: VhostUserNet<Arc<GuestMemoryMmap>> =
VhostUserNet::new_server(device_socket, None, queue_sizes, epoll_mgr).unwrap();
assert_eq!(
VirtioDevice::<Arc<GuestMemoryMmap<()>>, QueueSync, GuestRegionMmap>::device_type(&dev),
TYPE_NET
);
let queue_size = [128u16];
let queue_size = [128];
assert_eq!(
VirtioDevice::<Arc<GuestMemoryMmap<()>>, QueueSync, GuestRegionMmap>::queue_max_sizes(
&dev
),
&queue_size[..]
);
slave_th.join().unwrap();
let _ = std::fs::remove_file(&socket_path);
drop(dev);
assert_eq!(
VirtioDevice::<Arc<GuestMemoryMmap<()>>, QueueSync, GuestRegionMmap>::get_avail_features(&dev, 0),
dev.device().device_info.get_avail_features(0)
);
assert_eq!(
VirtioDevice::<Arc<GuestMemoryMmap<()>>, QueueSync, GuestRegionMmap>::get_avail_features(&dev, 1),
dev.device().device_info.get_avail_features(1)
);
assert_eq!(
VirtioDevice::<Arc<GuestMemoryMmap<()>>, QueueSync, GuestRegionMmap>::get_avail_features(&dev, 2),
dev.device().device_info.get_avail_features(2)
);
VirtioDevice::<Arc<GuestMemoryMmap<()>>, QueueSync, GuestRegionMmap>::set_acked_features(
&mut dev, 2, 0,
);
assert_eq!(VirtioDevice::<Arc<GuestMemoryMmap<()>>, QueueSync, GuestRegionMmap>::get_avail_features(&dev, 2), 0);
let config: [u8; 8] = [0; 8];
let _ = VirtioDevice::<Arc<GuestMemoryMmap<()>>, QueueSync, GuestRegionMmap>::write_config(
&mut dev, 0, &config,
);
let mut data: [u8; 8] = [1; 8];
let _ = VirtioDevice::<Arc<GuestMemoryMmap<()>>, QueueSync, GuestRegionMmap>::read_config(
&mut dev, 0, &mut data,
);
assert_eq!(config, data);
handler.join().unwrap();
}
#[test]
fn test_vhost_user_net_virtio_device_activate() {
skip_if_kvm_unaccessable!();
let dir_path = std::path::Path::new("/tmp");
let socket_path = dir_path.join(format!(
"vhost-user-net-{}-{:?}.sock",
std::process::id(),
thread::current().id()
));
let socket_str = socket_path.to_str().unwrap().to_string();
let _ = std::fs::remove_file(&socket_path);
let queue_sizes = Arc::new(vec![128u16]);
let device_socket = concat!("vhost.", line!());
let queue_sizes = Arc::new(vec![128]);
let epoll_mgr = EpollManager::default();
let socket_for_slave = socket_str.clone();
let slave_th = thread::spawn(move || {
let mut slave = connect_slave(&socket_for_slave, Duration::from_secs(10))
.unwrap_or_else(|| panic!("slave connect timeout: {}", socket_for_slave));
let handler = thread::spawn(move || {
let mut slave = connect_slave(device_socket).unwrap();
create_vhost_user_net_slave(&mut slave);
let mut pfeatures = VhostUserProtocolFeatures::all();
// A workaround for no support for `INFLIGHT_SHMFD`. File an issue to track
@@ -726,30 +702,8 @@ mod tests {
pfeatures -= VhostUserProtocolFeatures::INFLIGHT_SHMFD;
negotiate_slave(&mut slave, pfeatures, true, 1);
});
let (tx, rx) = std::sync::mpsc::channel();
let socket_for_master = socket_str.clone();
let queue_sizes_for_master = queue_sizes.clone();
let epoll_mgr_for_master = epoll_mgr.clone();
thread::spawn(move || {
let res = VhostUserNet::<Arc<GuestMemoryMmap>>::new_server(
&socket_for_master,
None,
queue_sizes_for_master,
epoll_mgr_for_master,
);
let _ = tx.send(res);
});
let mut dev: VhostUserNet<Arc<GuestMemoryMmap>> = rx
.recv_timeout(Duration::from_secs(10))
.unwrap_or_else(|_| panic!("new_server() stuck/timeout: {}", socket_str))
.unwrap_or_else(|e| {
panic!(
"new_server() returned error: {:?}, socket={}",
e, socket_str
)
});
let mut dev: VhostUserNet<Arc<GuestMemoryMmap>> =
VhostUserNet::new_server(device_socket, None, queue_sizes, epoll_mgr).unwrap();
// invalid queue size
{
let kvm = Kvm::new().unwrap();
@@ -806,9 +760,6 @@ mod tests {
);
dev.activate(config).unwrap();
}
slave_th.join().unwrap();
let _ = std::fs::remove_file(&socket_path);
drop(dev);
handler.join().unwrap();
}
}

View File

@@ -867,96 +867,56 @@ mod tests {
.set_read_timeout(Some(Duration::from_millis(150)))
.is_ok());
// stage:
// 0 = handler started
// 1 = first read timed out (main can do first write now)
// 2 = timeout cancelled, handler is about to do 3rd blocking read
let stage = Arc::new((Mutex::new(0u32), Condvar::new()));
let stage2 = Arc::clone(&stage);
let handler = thread::spawn(move || {
// notify started
{
let (lock, cvar) = &*stage2;
let mut s = lock.lock().unwrap();
*s = 0;
let cond_pair = Arc::new((Mutex::new(false), Condvar::new()));
let cond_pair_2 = Arc::clone(&cond_pair);
let handler = thread::Builder::new()
.spawn(move || {
// notify handler thread start
let (lock, cvar) = &*cond_pair_2;
let mut started = lock.lock().unwrap();
*started = true;
cvar.notify_one();
}
drop(started);
let mut reader_buf = [0u8; 5];
let start_time1 = Instant::now();
let mut reader_buf = [0; 5];
// first read would timed out
assert_eq!(
outer_stream.read_exact(&mut reader_buf).unwrap_err().kind(),
ErrorKind::TimedOut
);
let end_time1 = Instant::now().duration_since(start_time1).as_millis();
assert!((150..250).contains(&end_time1));
// 1) first read should timed out
let start_time1 = Instant::now();
assert_eq!(
outer_stream.read_exact(&mut reader_buf).unwrap_err().kind(),
ErrorKind::TimedOut
);
let end_time1 = start_time1.elapsed().as_millis();
assert!((150..300).contains(&end_time1));
// second read would ok
assert!(outer_stream.read_exact(&mut reader_buf).is_ok());
assert_eq!(reader_buf, [1, 2, 3, 4, 5]);
outer_stream
.set_read_timeout(Some(Duration::from_secs(10)))
.unwrap();
// cancel the read timeout
let start_time2 = Instant::now();
outer_stream.set_read_timeout(None).unwrap();
assert!(outer_stream.read_exact(&mut reader_buf).is_ok());
let end_time2 = Instant::now().duration_since(start_time2).as_millis();
assert!(end_time2 >= 500);
})
.unwrap();
// notify main: timeout observed, now do first write
{
let (lock, cvar) = &*stage2;
let mut s = lock.lock().unwrap();
*s = 1;
cvar.notify_one();
}
// 2) second read should ok (main will write after stage==1)
outer_stream.read_exact(&mut reader_buf).unwrap();
assert_eq!(reader_buf, [1, 2, 3, 4, 5]);
// 3) cancel timeout, then do a blocking read; notify main before blocking
outer_stream.set_read_timeout(None).unwrap();
{
let (lock, cvar) = &*stage2;
let mut s = lock.lock().unwrap();
*s = 2;
cvar.notify_one();
}
let start_time2 = Instant::now();
outer_stream.read_exact(&mut reader_buf).unwrap();
let end_time2 = start_time2.elapsed().as_millis();
assert!(end_time2 >= 500);
assert_eq!(reader_buf, [1, 2, 3, 4, 5]);
});
// wait handler started (stage==0)
{
let (lock, cvar) = &*stage;
let mut s = lock.lock().unwrap();
while *s != 0 {
s = cvar.wait(s).unwrap();
}
// wait handler thread started
let (lock, cvar) = &*cond_pair;
let mut started = lock.lock().unwrap();
while !*started {
started = cvar.wait(started).unwrap();
}
// wait first timeout done (stage==1), then do first write
{
let (lock, cvar) = &*stage;
let mut s = lock.lock().unwrap();
while *s < 1 {
s = cvar.wait(s).unwrap();
}
}
inner_stream.write_all(&[1, 2, 3, 4, 5]).unwrap();
// wait handler cancelled timeout and is about to block-read (stage==2)
{
let (lock, cvar) = &*stage;
let mut s = lock.lock().unwrap();
while *s < 2 {
s = cvar.wait(s).unwrap();
}
}
// sleep 300ms, test timeout
thread::sleep(Duration::from_millis(300));
let writer_buf = [1, 2, 3, 4, 5];
inner_stream.write_all(&writer_buf).unwrap();
// sleep 500ms again, test cancel timeout
thread::sleep(Duration::from_millis(500));
inner_stream.write_all(&[1, 2, 3, 4, 5]).unwrap();
let writer_buf = [1, 2, 3, 4, 5];
inner_stream.write_all(&writer_buf).unwrap();
handler.join().unwrap();
}

View File

@@ -339,7 +339,7 @@ mod tests {
}
}
pub fn create_event_handler_context(&self) -> EventHandlerContext<'_> {
pub fn create_event_handler_context(&self) -> EventHandlerContext {
const QSIZE: u16 = 256;
let guest_rxvq = GuestQ::new(GuestAddress(0x0010_0000), &self.mem, QSIZE);

View File

@@ -120,7 +120,7 @@ mod tests {
use libc::{cpu_set_t, syscall};
use std::convert::TryInto;
use std::{mem, thread};
use std::{mem, process, thread};
use seccompiler::{apply_filter, BpfProgram, SeccompAction, SeccompFilter};
@@ -157,16 +157,6 @@ mod tests {
let child = thread::spawn(move || {
assert!(register_signal_handlers().is_ok());
// Trigger SIGBUS/SIGSEGV *before* installing the seccomp filter.
// Call SIGBUS signal handler.
assert_eq!(METRICS.read().unwrap().signals.sigbus.count(), 0);
unsafe { libc::raise(SIGBUS) };
// Call SIGSEGV signal handler.
assert_eq!(METRICS.read().unwrap().signals.sigsegv.count(), 0);
unsafe { libc::raise(SIGSEGV) };
// Install a seccomp filter that traps a known syscall so that we can verify SIGSYS handling.
let filter = SeccompFilter::new(
vec![(libc::SYS_mkdirat, vec![])].into_iter().collect(),
SeccompAction::Allow,
@@ -178,8 +168,20 @@ mod tests {
assert!(apply_filter(&TryInto::<BpfProgram>::try_into(filter).unwrap()).is_ok());
assert_eq!(METRICS.read().unwrap().seccomp.num_faults.count(), 0);
// Invoke the blacklisted syscall to trigger SIGSYS and exercise the SIGSYS handler.
// Call the blacklisted `SYS_mkdirat`.
unsafe { syscall(libc::SYS_mkdirat, "/foo/bar\0") };
// Call SIGBUS signal handler.
assert_eq!(METRICS.read().unwrap().signals.sigbus.count(), 0);
unsafe {
syscall(libc::SYS_kill, process::id(), SIGBUS);
}
// Call SIGSEGV signal handler.
assert_eq!(METRICS.read().unwrap().signals.sigsegv.count(), 0);
unsafe {
syscall(libc::SYS_kill, process::id(), SIGSEGV);
}
});
assert!(child.join().is_ok());

View File

@@ -13,10 +13,13 @@ edition = "2018"
[dependencies]
anyhow = "1.0.31"
byteorder = "1.4.3"
chrono = "0.4.0"
common-path = "=1.0.0"
fail = "0.5.0"
lazy_static = "1.4.0"
libc = "0.2.100"
nix = "0.26.4"
once_cell = "1.9.0"
serde = { version = "1.0.138", features = ["derive"] }
serde_json = "1.0.73"
slog = "2.5.2"
@@ -31,7 +34,10 @@ mockall = "0.13.1"
kata-types = { path = "../kata-types" }
oci-spec = { version = "0.8.1", features = ["runtime"] }
runtime-spec = { path = "../runtime-spec" }
safe-path = { path = "../safe-path" }
[dev-dependencies]
num_cpus = "1.13.1"
serial_test = "0.5.1"
tempfile = "3.19.1"
test-utils = { path = "../test-utils" }

View File

@@ -29,14 +29,12 @@ serde-enum-str = "0.4"
sysinfo = "0.34.2"
sha2 = "0.10.8"
flate2 = "1.1"
nix = "0.26.4"
hex = "0.4"
oci-spec = { version = "0.8.1", features = ["runtime"] }
safe-path = { path = "../safe-path", optional = true }
[target.'cfg(target_os = "macos")'.dependencies]
sysctl = "0.7.1"
[dev-dependencies]
tempfile = "3.19.1"
test-utils = { path = "../test-utils" }

View File

@@ -13,7 +13,6 @@ use super::{default, register_hypervisor_plugin};
use crate::config::default::MAX_CH_VCPUS;
use crate::config::default::MIN_CH_MEMORY_SIZE_MB;
use crate::config::hypervisor::VIRTIO_BLK_MMIO;
use crate::config::{ConfigPlugin, TomlConfig};
use crate::{resolve_path, validate_path};
@@ -105,16 +104,6 @@ impl ConfigPlugin for CloudHypervisorConfig {
));
}
// CoCo guest hardening: virtio-mmio is not hardened for confidential computing.
if ch.security_info.confidential_guest
&& ch.boot_info.vm_rootfs_driver == VIRTIO_BLK_MMIO
{
return Err(std::io::Error::other(
"Confidential guests must not use virtio-blk-mmio (use virtio-blk-pci); \
virtio-mmio is not hardened for CoCo",
));
}
if ch.boot_info.kernel.is_empty() {
return Err(std::io::Error::other("Guest kernel image for CH is empty"));
}

View File

@@ -26,6 +26,7 @@
use super::{default, ConfigOps, ConfigPlugin, TomlConfig};
use crate::annotations::KATA_ANNO_CFG_HYPERVISOR_PREFIX;
use crate::{resolve_path, sl, validate_path};
use byte_unit::{Byte, Unit};
use lazy_static::lazy_static;
use regex::RegexSet;
use serde_enum_str::{Deserialize_enum_str, Serialize_enum_str};
@@ -33,6 +34,7 @@ use std::collections::HashMap;
use std::io::{self, Result};
use std::path::Path;
use std::sync::{Arc, Mutex};
use sysinfo::{MemoryRefreshKind, RefreshKind, System};
mod dragonball;
pub use self::dragonball::{DragonballConfig, HYPERVISOR_NAME_DRAGONBALL};
@@ -1005,57 +1007,6 @@ fn default_guest_swap_create_threshold_secs() -> u64 {
60
}
/// Get host memory size in MiB.
/// Retrieves the total physical memory of the host across different platforms.
fn host_memory_mib() -> io::Result<u64> {
// Select a platform-specific implementation via a function pointer.
let get_memory: fn() -> io::Result<u64> = {
#[cfg(target_os = "linux")]
{
|| {
let info = nix::sys::sysinfo::sysinfo().map_err(io::Error::other)?;
Ok(info.ram_total() / (1024 * 1024)) // MiB
}
}
#[cfg(target_os = "macos")]
{
|| {
use sysctl::{Ctl, CtlValue, Sysctl};
let v = Ctl::new("hw.memsize")
.map_err(io::Error::other)?
.value()
.map_err(io::Error::other)?;
let bytes = match v {
CtlValue::S64(x) if x >= 0 => x as u64,
other => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("unexpected sysctl hw.memsize value type: {:?}", other),
));
}
};
Ok(bytes / (1024 * 1024)) // MiB
}
}
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
{
|| {
Err(io::Error::new(
io::ErrorKind::Unsupported,
"host memory query not implemented on this platform",
))
}
}
};
get_memory()
}
impl MemoryInfo {
/// Adjusts the configuration information after loading from a configuration file.
///
@@ -1067,15 +1018,13 @@ impl MemoryInfo {
self.file_mem_backend,
"Memory backend file {} is invalid: {}"
)?;
let host_memory = host_memory_mib()?;
if u64::from(self.default_memory) > host_memory {
self.default_memory = host_memory as u32;
}
if self.default_maxmemory == 0 || u64::from(self.default_maxmemory) > host_memory {
self.default_maxmemory = host_memory as u32;
if self.default_maxmemory == 0 {
let s = System::new_with_specifics(
RefreshKind::nothing().with_memory(MemoryRefreshKind::everything()),
);
self.default_maxmemory = Byte::from_u64(s.total_memory())
.get_adjusted_unit(Unit::MiB)
.get_value() as u32;
}
Ok(())
}
@@ -1218,29 +1167,6 @@ pub struct SecurityInfo {
#[serde(default)]
pub sev_snp_guest: bool,
/// SNP 'ID Block' and 'ID Authentication Information Structure'.
/// If one of snp_id_block or snp_id_auth is specified, the other must be specified, too.
/// Notice that the default SNP policy of QEMU (0x30000) is used by Kata, if not explicitly
/// set via 'snp_guest_policy' option. The IDBlock contains the guest policy as field, and
/// it must match the value from 'snp_guest_policy' or, if unset, the QEMU default policy.
/// 96-byte, base64-encoded blob to provide the 'ID Block' structure for the
/// SNP_LAUNCH_FINISH command defined in the SEV-SNP firmware ABI (QEMU default: all-zero)
#[serde(default)]
pub snp_id_block: String,
/// 4096-byte, base64-encoded blob to provide the 'ID Authentication Information Structure'
/// for the SNP_LAUNCH_FINISH command defined in the SEV-SNP firmware ABI (QEMU default: all-zero)
#[serde(default)]
pub snp_id_auth: String,
/// SNP Guest Policy, the 'POLICY' parameter to the SNP_LAUNCH_START command.
/// If unset, the QEMU default policy (0x30000) will be used.
/// Notice that the guest policy is enforced at VM launch, and your pod VMs
/// won't start at all if the policy denys it. This will be indicated by a
/// 'SNP_LAUNCH_START' error.
#[serde(default = "default_snp_guest_policy")]
pub snp_guest_policy: u32,
/// Path to OCI hook binaries in the *guest rootfs*.
///
/// This setting does not affect host-side hooks, which must instead be
@@ -1302,10 +1228,6 @@ fn default_qgs_port() -> u32 {
4050
}
fn default_snp_guest_policy() -> u32 {
0x30000
}
impl SecurityInfo {
/// Adjusts the security configuration information after loading from a configuration file.
///

View File

@@ -124,17 +124,6 @@ impl ConfigPlugin for QemuConfig {
));
}
// CoCo guest hardening: virtio-mmio transport is not hardened for confidential
// computing; only virtio-pci is. Ensure we never use virtio-blk-mmio for rootfs.
if qemu.security_info.confidential_guest
&& qemu.boot_info.vm_rootfs_driver == VIRTIO_BLK_MMIO
{
return Err(std::io::Error::other(
"Confidential guests must not use virtio-blk-mmio (use virtio-blk-pci); \
virtio-mmio is not hardened for CoCo",
));
}
if qemu.boot_info.kernel.is_empty() {
return Err(std::io::Error::other(
"Guest kernel image for qemu is empty",

View File

@@ -10,6 +10,7 @@ anyhow = "1.0"
page_size = "0.6"
chrono = "0.4"
tokio = { version = "1.45.1", features = ["full"] }
async-trait = "0.1"
maplit = "1.0"
nix = { version = "0.30.1", features = ["fs", "sched"] }

View File

@@ -520,11 +520,6 @@ message Storage {
// FSGroup consists of the group ID and group ownership change policy
// that the mounted volume must have its group ID changed to when specified.
FSGroup fs_group = 7;
// Shared indicates this storage is shared across multiple containers
// (e.g., block-based emptyDirs). When true, the agent should not clean up
// the storage when a container using it exits, as other containers
// may still need it. Cleanup will happen when the sandbox is destroyed.
bool shared = 8;
}
// Device represents only the devices that could have been defined through the

View File

@@ -9,3 +9,4 @@ license = "Apache-2.0"
serde = "1.0.131"
serde_derive = "1.0.131"
serde_json = "1.0.73"
libc = "0.2.112"

View File

@@ -28,4 +28,5 @@ nix = { workspace = true }
tokio = { workspace = true, features = ["rt", "rt-multi-thread"] }
shim = { path = "crates/shim" }
common = { workspace = true }
logging = { workspace = true }
runtimes = { workspace = true }

View File

@@ -15,11 +15,6 @@ PROJECT_URL = https://github.com/kata-containers
PROJECT_COMPONENT = containerd-shim-kata-v2
CONTAINERD_RUNTIME_NAME = io.containerd.kata.v2
# This snippet finds all packages inside runtime-rs. Used for tessting.
PACKAGES := $(shell cargo metadata --no-deps --format-version 1 | \
jq -r '.packages[] | select(.manifest_path | contains("runtime-rs")) | .name')
PACKAGE_FLAGS := $(patsubst %,-p %,$(PACKAGES))
include ../../utils.mk
ARCH_DIR = arch
@@ -50,9 +45,9 @@ test:
else
##TARGET default: build code
default: runtime show-header
##TARGET test: run cargo tests for runtime-rs and all its sub-crates.
##TARGET test: run cargo tests
test: static-checks-build
@cargo test $(PACKAGE_FLAGS) --target $(TRIPLE) $(EXTRA_RUSTFEATURES) -- --nocapture --skip bindgen
@cargo test --all --target $(TRIPLE) $(EXTRA_RUSTFEATURES) -- --nocapture --skip bindgen
install: install-runtime install-configs
endif
@@ -738,7 +733,7 @@ static-checks-build: $(GENERATED_FILES)
$(TARGET): $(GENERATED_FILES) $(TARGET_PATH)
$(TARGET_PATH): $(SOURCES) | show-summary
@RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings" cargo build -p runtime-rs --target $(TRIPLE) $(if $(findstring release,$(BUILD_TYPE)),--release) $(EXTRA_RUSTFEATURES)
@RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings" cargo build --target $(TRIPLE) $(if $(findstring release,$(BUILD_TYPE)),--release) $(EXTRA_RUSTFEATURES)
$(GENERATED_FILES): %: %.in
@sed \
@@ -774,7 +769,7 @@ endif
##TARGET run: build and run agent
run:
@cargo run -p runtime-rs --target $(TRIPLE)
@cargo run --target $(TRIPLE)
show-header:
@printf "%s - version %s (commit %s)\n\n" "$(TARGET)" "$(VERSION)" "$(COMMIT_MSG)"

View File

@@ -5,9 +5,13 @@ authors = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
[dev-dependencies]
futures = "0.1.27"
[dependencies]
anyhow = { workspace = true }
async-trait = { workspace = true }
log = { workspace = true }
protobuf = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
@@ -27,6 +31,3 @@ protocols = { workspace = true, features = ["async"] }
[features]
default = []
[package.metadata.cargo-machete]
ignored = ["slog-scope"]

View File

@@ -28,6 +28,8 @@ path-clean = "1.0.1"
lazy_static = { workspace = true }
tracing = { workspace = true }
ttrpc = { workspace = true, features = ["async"] }
protobuf = { workspace = true }
oci-spec = { workspace = true }
futures = "0.3.25"
safe-path = "0.1.0"
crossbeam-channel = "0.5.6"
@@ -42,6 +44,7 @@ kata-sys-util = { workspace = true }
kata-types = { workspace = true }
logging = { workspace = true }
protocols = { workspace = true, features = ["async"] }
shim-interface = { workspace = true }
persist = { workspace = true }
ch-config = { workspace = true, optional = true }
tests_utils = { workspace = true }

View File

@@ -110,16 +110,6 @@ pub struct DeviceConfig {
pub pci_segment: u16,
}
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum ImageType {
FixedVhd,
Qcow2,
Raw,
Vhdx,
#[default]
Unknown,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)]
pub struct DiskConfig {
pub path: Option<PathBuf>,
@@ -145,8 +135,6 @@ pub struct DiskConfig {
pub disable_io_uring: bool,
#[serde(default)]
pub pci_segment: u16,
#[serde(default)]
pub image_type: ImageType,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)]

View File

@@ -27,7 +27,6 @@ use ch_config::ch_api::{
};
use ch_config::convert::DEFAULT_NUM_PCI_SEGMENTS;
use ch_config::DiskConfig;
use ch_config::ImageType;
use ch_config::{net_util::MacAddr, DeviceConfig, FsConfig, NetConfig, VsockConfig};
use kata_sys_util::netns::NetnsGuard;
use kata_types::config::hypervisor::RateLimiterConfig;
@@ -470,10 +469,7 @@ impl CloudHypervisorInner {
net_config.id = None;
net_config.num_queues = network_queues_pairs * 2;
info!(
sl!(),
"network device queue pairs {:?}", network_queues_pairs
);
info!(sl!(), "network device queue pairs {:?}", network_queues_pairs);
// we need ensure opening network device happens in netns.
let netns = self.netns.clone().unwrap_or_default();
@@ -554,7 +550,6 @@ impl TryFrom<BlockConfig> for DiskConfig {
readonly: blkcfg.is_readonly,
num_queues: blkcfg.num_queues,
queue_size: blkcfg.queue_size as u16,
image_type: ImageType::Raw,
..Default::default()
};

View File

@@ -256,8 +256,29 @@ struct Memory {
impl Memory {
fn new(config: &HypervisorConfig) -> Memory {
let mem_size = config.memory_info.default_memory as u64;
let max_mem_size = config.memory_info.default_maxmemory as u64;
// Move this to QemuConfig::adjust_config()?
let mut mem_size = config.memory_info.default_memory as u64;
let mut max_mem_size = config.memory_info.default_maxmemory as u64;
if let Ok(sysinfo) = nix::sys::sysinfo::sysinfo() {
let host_memory = sysinfo.ram_total() >> 20;
if mem_size > host_memory {
info!(sl!(), "'default_memory' given in configuration.toml is greater than host memory, adjusting to host memory");
mem_size = host_memory
}
if max_mem_size == 0 || max_mem_size > host_memory {
max_mem_size = host_memory
}
} else {
warn!(sl!(), "Failed to get host memory size, cannot verify or adjust configuration.toml's 'default_maxmemory'");
if max_mem_size == 0 {
max_mem_size = mem_size;
};
}
// Memory sizes are given in megabytes in configuration.toml so we
// need to convert them to bytes for storage.
@@ -279,18 +300,6 @@ impl Memory {
self.memory_backend_file = Some(mem_file.clone());
self
}
#[allow(dead_code)]
fn set_maxmem_size(&mut self, max_size: u64) -> &mut Self {
self.max_size = max_size;
self
}
#[allow(dead_code)]
fn set_num_slots(&mut self, num_slots: u32) -> &mut Self {
self.num_slots = num_slots;
self
}
}
#[async_trait]
@@ -1879,7 +1888,6 @@ struct ObjectSevSnpGuest {
reduced_phys_bits: u32,
kernel_hashes: bool,
host_data: Option<String>,
policy: u32,
is_snp: bool,
}
@@ -1891,15 +1899,9 @@ impl ObjectSevSnpGuest {
reduced_phys_bits,
kernel_hashes: true,
host_data,
policy: 0x30000,
is_snp,
}
}
fn set_policy(&mut self, policy: u32) -> &mut Self {
self.policy = policy;
self
}
}
#[async_trait]
@@ -1922,7 +1924,6 @@ impl ToQemuParams for ObjectSevSnpGuest {
"kernel-hashes={}",
if self.kernel_hashes { "on" } else { "off" }
));
params.push(format!("policy=0x{:x}", self.policy));
if let Some(host_data) = &self.host_data {
params.push(format!("host-data={host_data}"))
}
@@ -2578,19 +2579,13 @@ impl<'a> QemuCmdLine<'a> {
firmware: &str,
host_data: &Option<String>,
) {
// For SEV-SNP, memory overcommit is not supported. we only set the memory size.
self.memory.set_maxmem_size(0).set_num_slots(0);
let mut sev_snp_object =
let sev_snp_object =
ObjectSevSnpGuest::new(true, cbitpos, phys_addr_reduction, host_data.clone());
sev_snp_object.set_policy(self.config.security_info.snp_guest_policy);
self.devices.push(Box::new(sev_snp_object));
self.devices.push(Box::new(Bios::new(firmware.to_owned())));
self.machine
.set_kernel_irqchip("split")
.set_confidential_guest_support("snp")
.set_nvdimm(false);

View File

@@ -9,8 +9,8 @@ use crate::device::topology::PCIePort;
use crate::qemu::qmp::get_qmp_socket_path;
use crate::{
device::driver::ProtectionDeviceConfig, hypervisor_persist::HypervisorState, selinux,
HypervisorConfig, MemoryConfig, VcpuThreadIds, VsockDevice, HYPERVISOR_QEMU, KATA_BLK_DEV_TYPE,
KATA_CCW_DEV_TYPE, KATA_NVDIMM_DEV_TYPE, KATA_SCSI_DEV_TYPE,
HypervisorConfig, MemoryConfig, VcpuThreadIds, VsockDevice, HYPERVISOR_QEMU,
KATA_BLK_DEV_TYPE, KATA_CCW_DEV_TYPE, KATA_NVDIMM_DEV_TYPE, KATA_SCSI_DEV_TYPE,
};
use crate::utils::{
@@ -138,16 +138,15 @@ impl QemuInner {
&block_dev.config.path_on_host,
block_dev.config.is_readonly,
)?,
KATA_CCW_DEV_TYPE | KATA_BLK_DEV_TYPE | KATA_SCSI_DEV_TYPE => cmdline
.add_block_device(
block_dev.device_id.as_str(),
&block_dev.config.path_on_host,
block_dev
.config
.is_direct
.unwrap_or(self.config.blockdev_info.block_device_cache_direct),
block_dev.config.driver_option.as_str() == KATA_SCSI_DEV_TYPE,
)?,
KATA_CCW_DEV_TYPE | KATA_BLK_DEV_TYPE | KATA_SCSI_DEV_TYPE => cmdline.add_block_device(
block_dev.device_id.as_str(),
&block_dev.config.path_on_host,
block_dev
.config
.is_direct
.unwrap_or(self.config.blockdev_info.block_device_cache_direct),
block_dev.config.driver_option.as_str() == KATA_SCSI_DEV_TYPE,
)?,
unsupported => {
info!(sl!(), "unsupported block device driver: {}", unsupported)
}

View File

@@ -187,21 +187,11 @@ impl Qmp {
continue;
}
(None, _) => {
warn!(
sl!(),
"hotpluggable vcpu {} has no socket_id for driver {}, skipping",
core_id,
driver
);
warn!(sl!(), "hotpluggable vcpu {} has no socket_id for driver {}, skipping", core_id, driver);
continue;
}
(_, None) => {
warn!(
sl!(),
"hotpluggable vcpu {} has no thread_id for driver {}, skipping",
core_id,
driver
);
warn!(sl!(), "hotpluggable vcpu {} has no thread_id for driver {}, skipping", core_id, driver);
continue;
}
}
@@ -763,9 +753,10 @@ impl Qmp {
Ok((None, Some(scsi_addr)))
} else if block_driver == VIRTIO_BLK_CCW {
let subchannel = self.ccw_subchannel.as_mut().ok_or_else(|| {
anyhow!("CCW subchannel not available for virtio-blk-ccw hotplug")
})?;
let subchannel = self
.ccw_subchannel
.as_mut()
.ok_or_else(|| anyhow!("CCW subchannel not available for virtio-blk-ccw hotplug"))?;
let slot = subchannel
.add_device(&node_name)

View File

@@ -8,10 +8,12 @@ license = { workspace = true }
[dependencies]
async-trait = { workspace = true }
anyhow = { workspace = true }
libc = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
# Local dependencies
kata-sys-util = { workspace = true }
kata-types = { workspace = true }
shim-interface = { workspace = true }
safe-path = { workspace = true }

View File

@@ -15,6 +15,7 @@ test-utils = { workspace = true }
actix-rt = { workspace = true }
anyhow = { workspace = true }
async-trait = { workspace = true }
bitflags = "2.9.0"
byte-unit = "5.1.6"
cgroups-rs = { version = "0.5.0", features = ["oci"] }
futures = "0.3.11"
@@ -40,6 +41,7 @@ hex = "0.4"
## Dependencies from `rust-netlink`
netlink-packet-route = "0.26"
netlink-sys = "0.8"
rtnetlink = "0.19"
# Local dependencies
@@ -52,7 +54,3 @@ persist = { workspace = true }
tests_utils = { workspace = true }
[features]
[package.metadata.cargo-machete]
ignored = ["slog-scope"]

View File

@@ -11,7 +11,6 @@ lazy_static = { workspace = true }
netns-rs = { workspace = true }
slog = { workspace = true }
slog-scope = { workspace = true }
containerd-shim-protos = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread"] }
tracing = { workspace = true }
tracing-opentelemetry = { workspace = true }
@@ -27,6 +26,7 @@ opentelemetry-jaeger = { version = "0.17.0", features = [
] }
tracing-subscriber = { version = "0.3", features = ["registry", "std"] }
hyper = { workspace = true, features = ["stream", "server", "http1"] }
hyperlocal = { workspace = true }
serde_json = { workspace = true }
nix = "0.25.0"
url = { workspace = true }

View File

@@ -11,14 +11,20 @@ license = { workspace = true }
anyhow = { workspace = true }
async-trait = { workspace = true }
containerd-shim-protos = { workspace = true, features = ["sandbox"] }
lazy_static = { workspace = true }
nix = { workspace = true }
protobuf = { workspace = true }
serde_json = { workspace = true }
slog = { workspace = true }
slog-scope = { workspace = true }
strum = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread", "process", "fs"] }
ttrpc = { workspace = true }
oci-spec = { workspace = true }
# Local dependencies
persist = { workspace = true }
agent = { workspace = true }
kata-sys-util = { workspace = true }
kata-types = { workspace = true }

View File

@@ -6,7 +6,7 @@
use std::sync::Arc;
use anyhow::{Context, Result};
use containerd_shim_protos::events::task::{TaskCreate, TaskDelete, TaskExit, TaskOOM, TaskStart};
use containerd_shim_protos::events::task::{TaskExit, TaskOOM};
use containerd_shim_protos::protobuf::Message as ProtobufMessage;
use tokio::sync::mpsc::{channel, Receiver, Sender};
@@ -49,15 +49,9 @@ impl Message {
const TASK_OOM_EVENT_TOPIC: &str = "/tasks/oom";
const TASK_EXIT_EVENT_TOPIC: &str = "/tasks/exit";
const TASK_START_EVENT_TOPIC: &str = "/tasks/start";
const TASK_CREATE_EVENT_TOPIC: &str = "/tasks/create";
const TASK_DELETE_EVENT_TOPIC: &str = "/tasks/delete";
const TASK_OOM_EVENT_URL: &str = "containerd.events.TaskOOM";
const TASK_EXIT_EVENT_URL: &str = "containerd.events.TaskExit";
const TASK_START_EVENT_URL: &str = "containerd.events.TaskStart";
const TASK_CREATE_EVENT_URL: &str = "containerd.events.TaskCreate";
const TASK_DELETE_EVENT_URL: &str = "containerd.events.TaskDelete";
pub trait Event: std::fmt::Debug + Send {
fn r#type(&self) -> String;
@@ -92,45 +86,3 @@ impl Event for TaskExit {
self.write_to_bytes().context("get exit value")
}
}
impl Event for TaskStart {
fn r#type(&self) -> String {
TASK_START_EVENT_TOPIC.to_string()
}
fn type_url(&self) -> String {
TASK_START_EVENT_URL.to_string()
}
fn value(&self) -> Result<Vec<u8>> {
self.write_to_bytes().context("get start value")
}
}
impl Event for TaskCreate {
fn r#type(&self) -> String {
TASK_CREATE_EVENT_TOPIC.to_string()
}
fn type_url(&self) -> String {
TASK_CREATE_EVENT_URL.to_string()
}
fn value(&self) -> Result<Vec<u8>> {
self.write_to_bytes().context("get create value")
}
}
impl Event for TaskDelete {
fn r#type(&self) -> String {
TASK_DELETE_EVENT_TOPIC.to_string()
}
fn type_url(&self) -> String {
TASK_DELETE_EVENT_URL.to_string()
}
fn value(&self) -> Result<Vec<u8>> {
self.write_to_bytes().context("get delete value")
}
}

View File

@@ -6,16 +6,14 @@
use anyhow::{anyhow, Context, Result};
use common::{
message::{Action, Message},
message::Message,
types::{
ContainerProcess, PlatformInfo, ProcessType, SandboxConfig, SandboxRequest,
SandboxResponse, SandboxStatusInfo, StartSandboxInfo, TaskRequest, TaskResponse,
DEFAULT_SHM_SIZE,
ContainerProcess, PlatformInfo, SandboxConfig, SandboxRequest, SandboxResponse,
SandboxStatusInfo, StartSandboxInfo, TaskRequest, TaskResponse, DEFAULT_SHM_SIZE,
},
RuntimeHandler, RuntimeInstance, Sandbox, SandboxNetworkEnv,
};
use containerd_shim_protos::events::task::{TaskCreate, TaskDelete, TaskStart};
use hypervisor::{
utils::{create_dir_all_with_inherit_owner, create_vmm_user, remove_vmm_user},
Param,
@@ -35,13 +33,13 @@ use netns_rs::{Env, NetNs};
use nix::{sys::statfs, unistd::User};
use oci_spec::runtime as oci;
use persist::sandbox_persist::Persist;
use protobuf::Message as ProtobufMessage;
use resource::{
cpu_mem::initial_size::InitialSizeManager,
network::{dan_config_path, generate_netns_name},
};
use runtime_spec as spec;
use shim_interface::shim_mgmt::ERR_NO_SHIM_SERVER;
use protobuf::Message as ProtobufMessage;
use std::{
collections::HashMap,
env,
@@ -482,7 +480,6 @@ impl RuntimeHandlerManager {
.await
.context("start sandbox in task handler")?;
let bundle = container_config.bundle.clone();
let container_id = container_config.container_id.clone();
let shim_pid = instance
.container_manager
@@ -504,19 +501,6 @@ impl RuntimeHandlerManager {
}
});
let msg_sender = self.inner.read().await.msg_sender.clone();
let event = TaskCreate {
container_id,
bundle,
pid,
..Default::default()
};
let msg = Message::new(Action::Event(Arc::new(event)));
msg_sender
.send(msg)
.await
.context("send task create event")?;
Ok(TaskResponse::CreateContainer(shim_pid))
} else {
self.handler_task_request(req)
@@ -586,7 +570,6 @@ impl RuntimeHandlerManager {
.context("get runtime instance")?;
let sandbox = instance.sandbox.clone();
let cm = instance.container_manager.clone();
let msg_sender = self.inner.read().await.msg_sender.clone();
match req {
TaskRequest::CreateContainer(req) => Err(anyhow!("Unreachable TaskRequest {:?}", req)),
@@ -596,20 +579,6 @@ impl RuntimeHandlerManager {
}
TaskRequest::DeleteProcess(process_id) => {
let resp = cm.delete_process(&process_id).await.context("do delete")?;
if process_id.process_type == ProcessType::Container {
let event = TaskDelete {
id: process_id.container_id().to_string(),
pid: resp.pid.pid,
exit_status: resp.exit_status as u32,
..Default::default()
};
let msg = Message::new(Action::Event(Arc::new(event)));
msg_sender
.send(msg)
.await
.context("send task delete event")?;
}
Ok(TaskResponse::DeleteProcess(resp))
}
TaskRequest::ExecProcess(req) => {
@@ -645,28 +614,12 @@ impl RuntimeHandlerManager {
.context("start process")?;
let pid = shim_pid.pid;
let process_type = process_id.process_type;
let container_id = process_id.container_id().to_string();
tokio::spawn(async move {
let result = sandbox.wait_process(cm, process_id, pid).await;
if let Err(e) = result {
error!(sl!(), "sandbox wait process error: {:?}", e);
}
});
if process_type == ProcessType::Container {
let event = TaskStart {
container_id,
pid,
..Default::default()
};
let msg = Message::new(Action::Event(Arc::new(event)));
msg_sender
.send(msg)
.await
.context("send task start event")?;
}
Ok(TaskResponse::StartProcess(shim_pid))
}

View File

@@ -10,6 +10,8 @@ anyhow = { workspace = true }
async-trait = { workspace = true }
awaitgroup = "0.6.0"
containerd-shim-protos = { workspace = true }
futures = "0.3.19"
lazy_static = { workspace = true }
libc = { workspace = true }
nix = { workspace = true }
protobuf = { workspace = true }
@@ -19,7 +21,9 @@ serde_json = { workspace = true }
slog = { workspace = true }
slog-scope = { workspace = true }
tokio = { workspace = true }
toml = "0.4.2"
url = { workspace = true }
async-std = "1.12.0"
tracing = { workspace = true }
oci-spec = { workspace = true }
strum = { workspace = true }
@@ -44,7 +48,3 @@ cloud-hypervisor = ["hypervisor/cloud-hypervisor"]
# Enable the build-in VMM Dragtonball
dragonball = ["hypervisor/dragonball"]
[package.metadata.cargo-machete]
ignored = ["slog-scope"]

View File

@@ -11,6 +11,7 @@ async-trait = { workspace = true }
slog = { workspace = true }
slog-scope = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread"] }
tracing = { workspace = true }
ttrpc = { workspace = true }
containerd-shim-protos = { workspace = true, features = ["async", "sandbox"] }
containerd-shim = { workspace = true }
@@ -20,7 +21,4 @@ common = { workspace = true }
logging = { workspace = true }
kata-types = { workspace = true }
runtimes = { workspace = true }
[package.metadata.cargo-machete]
ignored = ["slog-scope"]
persist = { workspace = true }

View File

@@ -9,8 +9,9 @@ license = { workspace = true }
[dependencies]
anyhow = { workspace = true }
tokio = { workspace = true, features = ["rt", "rt-multi-thread"] }
tokio = { workspace = true, features = [ "rt", "rt-multi-thread" ] }
# Local dependencies
common = { workspace = true }
logging = { workspace = true }
runtimes = { workspace = true }

View File

@@ -36,6 +36,8 @@ slog-stdlog = "4.1.0"
thiserror = { workspace = true }
tokio = { workspace = true, features = ["rt", "rt-multi-thread"] }
unix_socket2 = "0.5.4"
tracing = { workspace = true }
tracing-opentelemetry = { workspace = true }
oci-spec = { workspace = true }
# Local dependencies
@@ -44,7 +46,12 @@ kata-sys-util = { workspace = true }
logging = { workspace = true }
runtime-spec = { workspace = true }
service = { workspace = true }
runtimes = { workspace = true }
[dev-dependencies]
tempfile = { workspace = true }
rand = { workspace = true }
serial_test = "0.10.0"
# Local dev-dependencies
tests_utils = { workspace = true }

View File

@@ -147,14 +147,10 @@ DEFROOTFSTYPE := $(ROOTFSTYPE_EXT4)
FIRMWAREPATH :=
FIRMWAREVOLUMEPATH :=
FIRMWAREPATH_NV = $(FIRMWAREPATH)
FIRMWARETDVFPATH := $(PREFIXDEPS)/share/ovmf/OVMF.inteltdx.fd
FIRMWARETDVFPATH_NV := $(FIRMWARETDVFPATH)
FIRMWARETDVFVOLUMEPATH :=
FIRMWARESNPPATH := $(PREFIXDEPS)/share/ovmf/AMDSEV.fd
FIRMWARESNPPATH_NV := $(FIRMWARESNPPATH)
KERNELVERITYPARAMS ?= ""
KERNELVERITYPARAMS_NV ?= ""
@@ -225,8 +221,6 @@ DEFENABLEANNOTATIONS := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_pa
DEFENABLEANNOTATIONS_COCO := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"kernel_verity_params\", \"default_vcpus\", \"default_memory\", \"cc_init_data\"]
DEFDISABLEGUESTSECCOMP := true
DEFDISABLEGUESTEMPTYDIR := false
DEFEMPTYDIRMODE := shared-fs
DEFEMPTYDIRMODE_COCO := block-encrypted
#Default experimental features enabled
DEFAULTEXPFEATURES := []
@@ -278,7 +272,6 @@ DEFVIRTIOFSEXTRAARGS ?= [\"--thread-pool-size=1\", \"--announce-submounts\"]
DEFENABLEIOTHREADS := false
DEFINDEPIOTHREADS := 0
DEFENABLEVHOSTUSERSTORE := false
DEFENABLEVIRTIOMEM ?= false
DEFVHOSTUSERSTOREPATH := $(PKGRUNDIR)/vhost-user
DEFVALIDVHOSTUSERSTOREPATHS := [\"$(DEFVHOSTUSERSTOREPATH)\"]
DEFFILEMEMBACKEND := ""
@@ -307,11 +300,9 @@ DEFDANCONF := /run/kata-containers/dans
DEFFORCEGUESTPULL := false
DEFKUBELETROOTDIR := /var/lib/kubelet
# Device cold plug
DEFPODRESOURCEAPISOCK := ""
DEFPODRESOURCEAPISOCK_NV := "$(DEFKUBELETROOTDIR)/pod-resources/kubelet.sock"
DEFPODRESOURCEAPISOCK_NV := "/var/lib/kubelet/pod-resources/kubelet.sock"
SED = sed
@@ -476,8 +467,8 @@ ifneq (,$(QEMUCMD))
KERNELSEPATH = $(KERNELDIR)/$(KERNELSENAME)
# NVIDIA GPU specific options (all should be suffixed by _NV)
KERNELTYPE_NV = compressed
KERNELNAME_NV = $(call MAKE_KERNEL_NAME_NV,$(KERNELTYPE_NV))
# Normal: uncompressed (KERNELTYPE). Confidential: compressed (KERNELCONFIDENTIALTYPE).
KERNELNAME_NV = $(call MAKE_KERNEL_NAME_NV,$(KERNELTYPE))
KERNELPATH_NV = $(KERNELDIR)/$(KERNELNAME_NV)
KERNELNAME_CONFIDENTIAL_NV = $(call MAKE_KERNEL_NAME_NV,$(KERNELCONFIDENTIALTYPE))
KERNELPATH_CONFIDENTIAL_NV = $(KERNELDIR)/$(KERNELNAME_CONFIDENTIAL_NV)
@@ -493,9 +484,6 @@ ifneq (,$(QEMUCMD))
# using an image and /dev is already mounted.
KERNELPARAMS_NV = "cgroup_no_v1=all"
KERNELPARAMS_NV += "devtmpfs.mount=0"
KERNELPARAMS_NV += "pci=realloc"
KERNELPARAMS_NV += "pci=nocrs"
KERNELPARAMS_NV += "pci=assign-busses"
# Setting this to false can lead to cgroup leakages in the host
# Best practice for production is to set this to true
@@ -692,13 +680,10 @@ USER_VARS += KERNELPATH_FC
USER_VARS += KERNELPATH_STRATOVIRT
USER_VARS += KERNELVIRTIOFSPATH
USER_VARS += FIRMWAREPATH
USER_VARS += FIRMWAREPATH_NV
USER_VARS += FIRMWARETDVFPATH
USER_VARS += FIRMWAREVOLUMEPATH
USER_VARS += FIRMWARETDVFVOLUMEPATH
USER_VARS += FIRMWARESNPPATH
USER_VARS += FIRMWARETDVFPATH_NV
USER_VARS += FIRMWARESNPPATH_NV
USER_VARS += MACHINEACCELERATORS
USER_VARS += CPUFEATURES
USER_VARS += TDXCPUFEATURES
@@ -752,8 +737,6 @@ USER_VARS += DEFNETWORKMODEL_FC
USER_VARS += DEFNETWORKMODEL_QEMU
USER_VARS += DEFNETWORKMODEL_STRATOVIRT
USER_VARS += DEFDISABLEGUESTEMPTYDIR
USER_VARS += DEFEMPTYDIRMODE
USER_VARS += DEFEMPTYDIRMODE_COCO
USER_VARS += DEFDISABLEGUESTSECCOMP
USER_VARS += DEFDISABLESELINUX
USER_VARS += DEFDISABLEGUESTSELINUX
@@ -781,7 +764,6 @@ USER_VARS += DEFENABLEANNOTATIONS
USER_VARS += DEFENABLEANNOTATIONS_COCO
USER_VARS += DEFENABLEIOTHREADS
USER_VARS += DEFINDEPIOTHREADS
USER_VARS += DEFENABLEVIRTIOMEM
USER_VARS += DEFSECCOMPSANDBOXPARAM
USER_VARS += DEFENABLEVHOSTUSERSTORE
USER_VARS += DEFVHOSTUSERSTOREPATH
@@ -801,7 +783,6 @@ USER_VARS += DEFSTATICRESOURCEMGMT_NV
USER_VARS += DEFBINDMOUNTS
USER_VARS += DEFCREATECONTAINERTIMEOUT
USER_VARS += DEFDANCONF
USER_VARS += DEFKUBELETROOTDIR
USER_VARS += DEFFORCEGUESTPULL
USER_VARS += DEFVFIOMODE
USER_VARS += DEFVFIOMODE_SE

View File

@@ -18,6 +18,3 @@ ifneq (,$(NEEDS_CC_SETTING))
CC := gcc
export CC
endif
# Enable virtio-mem for s390x
DEFENABLEVIRTIOMEM = true

View File

@@ -196,7 +196,7 @@ func indexPageText(w http.ResponseWriter, r *http.Request) {
formatter := fmt.Sprintf("%%-%ds: %%s\n", spacing)
for _, endpoint := range endpoints {
fmt.Fprintf(w, formatter, endpoint.path, endpoint.desc)
w.Write([]byte(fmt.Sprintf(formatter, endpoint.path, endpoint.desc)))
}
}

View File

@@ -63,7 +63,7 @@ func setCPUtype(hypervisorType vc.HypervisorType) error {
cpuType = getCPUtype()
if cpuType == cpuTypeUnknown {
return fmt.Errorf("Unknown CPU Type")
return fmt.Errorf("Unknow CPU Type")
} else if cpuType == cpuTypeIntel {
var kvmIntelParams map[string]string
onVMM, err := vc.RunningOnVMM(procCPUInfo)

View File

@@ -55,17 +55,18 @@ func TestCCCheckCLIFunction(t *testing.T) {
var moduleData []testModuleData
cpuType = getCPUtype()
moduleData = []testModuleData{}
switch cpuType {
case cpuTypeIntel:
if cpuType == cpuTypeIntel {
cpuData = []testCPUData{
{archGenuineIntel, "lm vmx sse4_1", false},
}
case cpuTypeAMD:
moduleData = []testModuleData{}
} else if cpuType == cpuTypeAMD {
cpuData = []testCPUData{
{archAuthenticAMD, "lm svm sse4_1", false},
}
moduleData = []testModuleData{}
}
genericCheckCLIFunction(t, cpuData, moduleData)
@@ -275,8 +276,7 @@ func TestCheckHostIsVMContainerCapable(t *testing.T) {
var moduleData []testModuleData
cpuType = getCPUtype()
switch cpuType {
case cpuTypeIntel:
if cpuType == cpuTypeIntel {
cpuData = []testCPUData{
{"", "", true},
{"Intel", "", true},
@@ -292,7 +292,7 @@ func TestCheckHostIsVMContainerCapable(t *testing.T) {
{filepath.Join(sysModuleDir, "kvm_intel/parameters/nested"), "Y", false},
{filepath.Join(sysModuleDir, "kvm_intel/parameters/unrestricted_guest"), "Y", false},
}
case cpuTypeAMD:
} else if cpuType == cpuTypeAMD {
cpuData = []testCPUData{
{"", "", true},
{"AMD", "", true},
@@ -340,7 +340,7 @@ func TestCheckHostIsVMContainerCapable(t *testing.T) {
// Write the following into the denylist file
// blacklist <mod>
// install <mod> /bin/false
_, err = fmt.Fprintf(denylistFile, "blacklist %s\ninstall %s /bin/false\n", mod, mod)
_, err = denylistFile.WriteString(fmt.Sprintf("blacklist %s\ninstall %s /bin/false\n", mod, mod))
assert.Nil(err)
}
denylistFile.Close()
@@ -505,10 +505,9 @@ func TestSetCPUtype(t *testing.T) {
assert.NotEmpty(archRequiredKernelModules)
cpuType = getCPUtype()
switch cpuType {
case cpuTypeIntel:
if cpuType == cpuTypeIntel {
assert.Equal(archRequiredCPUFlags["vmx"], "Virtualization support")
case cpuTypeAMD:
} else if cpuType == cpuTypeAMD {
assert.Equal(archRequiredCPUFlags["svm"], "Virtualization support")
}

View File

@@ -17,6 +17,7 @@ import (
"testing"
"github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils"
ktu "github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils"
"github.com/kata-containers/kata-containers/src/runtime/pkg/katautils"
vc "github.com/kata-containers/kata-containers/src/runtime/virtcontainers"
"github.com/sirupsen/logrus"
@@ -508,7 +509,7 @@ func TestCheckCheckCPUAttribs(t *testing.T) {
}
func TestCheckHaveKernelModule(t *testing.T) {
if tc.NotValid(katatestutils.NeedRoot()) {
if tc.NotValid(ktu.NeedRoot()) {
t.Skip(testDisabledAsNonRoot)
}
@@ -637,8 +638,8 @@ func TestCheckCheckKernelModules(t *testing.T) {
func TestCheckCheckKernelModulesUnreadableFile(t *testing.T) {
assert := assert.New(t)
if tc.NotValid(katatestutils.NeedNonRoot()) {
t.Skip(katatestutils.TestDisabledNeedNonRoot)
if tc.NotValid(ktu.NeedNonRoot()) {
t.Skip(ktu.TestDisabledNeedNonRoot)
}
dir := t.TempDir()

View File

@@ -56,10 +56,9 @@ func TestEnvGetEnvInfoSetsCPUType(t *testing.T) {
assert.NotEmpty(archRequiredKernelModules)
cpuType = getCPUtype()
switch cpuType {
case cpuTypeIntel:
if cpuType == cpuTypeIntel {
assert.Equal(archRequiredCPUFlags["vmx"], "Virtualization support")
case cpuTypeAMD:
} else if cpuType == cpuTypeAMD {
assert.Equal(archRequiredCPUFlags["svm"], "Virtualization support")
}

View File

@@ -14,6 +14,7 @@ import (
"path"
"path/filepath"
"runtime"
goruntime "runtime"
"strings"
"testing"
@@ -183,7 +184,7 @@ func genericGetExpectedHostDetails(tmpdir string, expectedVendor string, expecte
}
const expectedKernelVersion = "99.1"
const expectedArch = runtime.GOARCH
const expectedArch = goruntime.GOARCH
expectedDistro := DistroInfo{
Name: "Foo",
@@ -253,7 +254,7 @@ VERSION_ID="%s"
}
}
if runtime.GOARCH == "arm64" {
if goruntime.GOARCH == "arm64" {
expectedHostDetails.CPU.Vendor = "ARM Limited"
expectedHostDetails.CPU.Model = "v8"
}

View File

@@ -55,9 +55,9 @@ var getIPTablesCommand = cli.Command{
return err
}
url := containerdshim.IPTablesURL
url := containerdshim.IPTablesUrl
if isIPv6 {
url = containerdshim.IP6TablesURL
url = containerdshim.IP6TablesUrl
}
body, err := shimclient.DoGet(sandboxID, defaultTimeout, url)
if err != nil {
@@ -108,9 +108,9 @@ var setIPTablesCommand = cli.Command{
return err
}
url := containerdshim.IPTablesURL
url := containerdshim.IPTablesUrl
if isIPv6 {
url = containerdshim.IP6TablesURL
url = containerdshim.IP6TablesUrl
}
if err = shimclient.DoPut(sandboxID, defaultTimeout, url, "application/octet-stream", buf); err != nil {

View File

@@ -62,7 +62,7 @@ var setPolicyCommand = cli.Command{
return err
}
url := containerdshim.PolicyURL
url := containerdshim.PolicyUrl
if err = shimclient.DoPut(sandboxID, defaultTimeout, url, "application/octet-stream", buf); err != nil {
return fmt.Errorf("Error observed when making policy-set request(%s): %s", policyFile, err)

View File

@@ -126,7 +126,7 @@ var resizeCommand = cli.Command{
// Stats retrieves the filesystem stats of the direct volume inside the guest.
func Stats(volumePath string) ([]byte, error) {
sandboxID, err := volume.GetSandboxIDForVolume(volumePath)
sandboxId, err := volume.GetSandboxIdForVolume(volumePath)
if err != nil {
return nil, err
}
@@ -136,8 +136,8 @@ func Stats(volumePath string) ([]byte, error) {
}
urlSafeDevicePath := url.PathEscape(volumeMountInfo.Device)
body, err := shimclient.DoGet(sandboxID, defaultTimeout,
fmt.Sprintf("%s?%s=%s", containerdshim.DirectVolumeStatURL, containerdshim.DirectVolumePathKey, urlSafeDevicePath))
body, err := shimclient.DoGet(sandboxId, defaultTimeout,
fmt.Sprintf("%s?%s=%s", containerdshim.DirectVolumeStatUrl, containerdshim.DirectVolumePathKey, urlSafeDevicePath))
if err != nil {
return nil, err
}
@@ -146,7 +146,7 @@ func Stats(volumePath string) ([]byte, error) {
// Resize resizes a direct volume inside the guest.
func Resize(volumePath string, size uint64) error {
sandboxID, err := volume.GetSandboxIDForVolume(volumePath)
sandboxId, err := volume.GetSandboxIdForVolume(volumePath)
if err != nil {
return err
}
@@ -163,5 +163,5 @@ func Resize(volumePath string, size uint64) error {
if err != nil {
return err
}
return shimclient.DoPost(sandboxID, defaultTimeout, containerdshim.DirectVolumeResizeURL, "application/json", encoded)
return shimclient.DoPost(sandboxId, defaultTimeout, containerdshim.DirectVolumeResizeUrl, "application/json", encoded)
}

View File

@@ -94,12 +94,11 @@ func releaseURLIsValid(url string) error {
func getReleaseURL(currentVersion semver.Version) (url string, err error) {
major := currentVersion.Major
switch major {
case 0:
if major == 0 {
return "", fmt.Errorf("invalid current version: %v", currentVersion)
case 1:
} else if major == 1 {
url = kataLegacyReleaseURL
default:
} else {
url = kataReleaseURL
}

View File

@@ -463,18 +463,6 @@ vfio_mode = "@DEFVFIOMODE@"
# be created on the host and shared via virtio-fs. This is potentially slower, but allows sharing of files from host to guest.
disable_guest_empty_dir = @DEFDISABLEGUESTEMPTYDIR@
# Specifies how Kubernetes emptyDir volumes are handled.
# Options:
#
# - shared-fs (default)
# Shares the emptyDir folder with the guest using the method given
# by the `shared_fs` setting.
#
# - block-encrypted
# Plugs a block device to be encrypted in the guest.
#
emptydir_mode = "@DEFEMPTYDIRMODE@"
# Enabled experimental feature list, format: ["a", "b"].
# Experimental features are features not stable enough for production,
# they may break compatibility, and are prepared for a big version bump.
@@ -503,11 +491,6 @@ create_container_timeout = @DEFCREATECONTAINERTIMEOUT@
# (default: /run/kata-containers/dans)
dan_conf = "@DEFDANCONF@"
# kubelet_root_dir is the kubelet root directory used to match ConfigMap/Secret
# volume paths for propagation. Override for distros that use a different path
# (e.g. k0s: /var/lib/k0s/kubelet).
kubelet_root_dir = "@DEFKUBELETROOTDIR@"
# pod_resource_api_sock specifies the unix socket for the Kubelet's
# PodResource API endpoint. If empty, kubernetes based cold plug
# will not be attempted. In order for this feature to work, the

View File

@@ -354,18 +354,6 @@ static_sandbox_resource_mgmt = @DEFSTATICRESOURCEMGMT_FC@
# be created on the host and shared via virtio-fs. This is potentially slower, but allows sharing of files from host to guest.
disable_guest_empty_dir = @DEFDISABLEGUESTEMPTYDIR@
# Specifies how Kubernetes emptyDir volumes are handled.
# Options:
#
# - shared-fs (default)
# Shares the emptyDir folder with the guest using the method given
# by the `shared_fs` setting.
#
# - block-encrypted
# Plugs a block device to be encrypted in the guest.
#
emptydir_mode = "@DEFEMPTYDIRMODE@"
# Enabled experimental feature list, format: ["a", "b"].
# Experimental features are features not stable enough for production,
# they may break compatibility, and are prepared for a big version bump.
@@ -394,11 +382,6 @@ create_container_timeout = @DEFCREATECONTAINERTIMEOUT@
# (default: /run/kata-containers/dans)
dan_conf = "@DEFDANCONF@"
# kubelet_root_dir is the kubelet root directory used to match ConfigMap/Secret
# volume paths for propagation. Override for distros that use a different path
# (e.g. k0s: /var/lib/k0s/kubelet).
kubelet_root_dir = "@DEFKUBELETROOTDIR@"
# pod_resource_api_sock specifies the unix socket for the Kubelet's
# PodResource API endpoint. If empty, kubernetes based cold plug
# will not be attempted. In order for this feature to work, the

View File

@@ -638,18 +638,6 @@ vfio_mode = "@DEFVFIOMODE@"
# be created on the host and shared via virtio-fs. This is potentially slower, but allows sharing of files from host to guest.
disable_guest_empty_dir = @DEFDISABLEGUESTEMPTYDIR@
# Specifies how Kubernetes emptyDir volumes are handled.
# Options:
#
# - shared-fs (default)
# Shares the emptyDir folder with the guest using the method given
# by the `shared_fs` setting.
#
# - block-encrypted
# Plugs a block device to be encrypted in the guest.
#
emptydir_mode = "@DEFEMPTYDIRMODE@"
# Enabled experimental feature list, format: ["a", "b"].
# Experimental features are features not stable enough for production,
# they may break compatibility, and are prepared for a big version bump.
@@ -682,12 +670,6 @@ dan_conf = "@DEFDANCONF@"
# the container image should be pulled in the guest, without using an external snapshotter.
# This is an experimental feature and might be removed in the future.
experimental_force_guest_pull = @DEFFORCEGUESTPULL@
# kubelet_root_dir is the kubelet root directory used to match ConfigMap/Secret
# volume paths for propagation. Override for distros that use a different path
# (e.g. k0s: /var/lib/k0s/kubelet).
kubelet_root_dir = "@DEFKUBELETROOTDIR@"
# pod_resource_api_sock specifies the unix socket for the Kubelet's
# PodResource API endpoint. If empty, kubernetes based cold plug
# will not be attempted. In order for this feature to work, the

View File

@@ -701,18 +701,6 @@ vfio_mode = "@DEFVFIOMODE@"
# be created on the host and shared via virtio-fs. This is potentially slower, but allows sharing of files from host to guest.
disable_guest_empty_dir = @DEFDISABLEGUESTEMPTYDIR@
# Specifies how Kubernetes emptyDir volumes are handled.
# Options:
#
# - shared-fs (default)
# Shares the emptyDir folder with the guest using the method given
# by the `shared_fs` setting.
#
# - block-encrypted
# Plugs a block device to be encrypted in the guest.
#
emptydir_mode = "@DEFEMPTYDIRMODE_COCO@"
# Enabled experimental feature list, format: ["a", "b"].
# Experimental features are features not stable enough for production,
# they may break compatibility, and are prepared for a big version bump.
@@ -746,11 +734,6 @@ dan_conf = "@DEFDANCONF@"
# This is an experimental feature and might be removed in the future.
experimental_force_guest_pull = @DEFFORCEGUESTPULL@
# kubelet_root_dir is the kubelet root directory used to match ConfigMap/Secret
# volume paths for propagation. Override for distros that use a different path
# (e.g. k0s: /var/lib/k0s/kubelet).
kubelet_root_dir = "@DEFKUBELETROOTDIR@"
# pod_resource_api_sock specifies the unix socket for the Kubelet's
# PodResource API endpoint. If empty, kubernetes based cold plug
# will not be attempted. In order for this feature to work, the

View File

@@ -99,7 +99,7 @@ kernel_verity_params = "@KERNELVERITYPARAMS_CONFIDENTIAL_NV@"
# Path to the firmware.
# If you want that qemu uses the default firmware leave this option empty
firmware = "@FIRMWARESNPPATH_NV@"
firmware = "@FIRMWARESNPPATH@"
# Path to the firmware volume.
# firmware TDVF or OVMF can be split into FIRMWARE_VARS.fd (UEFI variables
@@ -717,18 +717,6 @@ vfio_mode = "@DEFVFIOMODE@"
# be created on the host and shared via virtio-fs. This is potentially slower, but allows sharing of files from host to guest.
disable_guest_empty_dir = @DEFDISABLEGUESTEMPTYDIR@
# Specifies how Kubernetes emptyDir volumes are handled.
# Options:
#
# - shared-fs (default)
# Shares the emptyDir folder with the guest using the method given
# by the `shared_fs` setting.
#
# - block-encrypted
# Plugs a block device to be encrypted in the guest.
#
emptydir_mode = "@DEFEMPTYDIRMODE@"
# Enabled experimental feature list, format: ["a", "b"].
# Experimental features are features not stable enough for production,
# they may break compatibility, and are prepared for a big version bump.
@@ -762,11 +750,6 @@ dan_conf = "@DEFDANCONF@"
# This is an experimental feature and might be removed in the future.
experimental_force_guest_pull = @DEFFORCEGUESTPULL@
# kubelet_root_dir is the kubelet root directory used to match ConfigMap/Secret
# volume paths for propagation. Override for distros that use a different path
# (e.g. k0s: /var/lib/k0s/kubelet).
kubelet_root_dir = "@DEFKUBELETROOTDIR@"
# pod_resource_api_sock specifies the unix socket for the Kubelet's
# PodResource API endpoint. If empty, kubernetes based cold plug
# will not be attempted. In order for this feature to work, the

View File

@@ -76,7 +76,7 @@ kernel_verity_params = "@KERNELVERITYPARAMS_CONFIDENTIAL_NV@"
# Path to the firmware.
# If you want that qemu uses the default firmware leave this option empty
firmware = "@FIRMWARETDVFPATH_NV@"
firmware = "@FIRMWARETDVFPATH@"
# Path to the firmware volume.
# firmware TDVF or OVMF can be split into FIRMWARE_VARS.fd (UEFI variables
@@ -694,18 +694,6 @@ vfio_mode = "@DEFVFIOMODE@"
# be created on the host and shared via virtio-fs. This is potentially slower, but allows sharing of files from host to guest.
disable_guest_empty_dir = @DEFDISABLEGUESTEMPTYDIR@
# Specifies how Kubernetes emptyDir volumes are handled.
# Options:
#
# - shared-fs (default)
# Shares the emptyDir folder with the guest using the method given
# by the `shared_fs` setting.
#
# - block-encrypted
# Plugs a block device to be encrypted in the guest.
#
emptydir_mode = "@DEFEMPTYDIRMODE@"
# Enabled experimental feature list, format: ["a", "b"].
# Experimental features are features not stable enough for production,
# they may break compatibility, and are prepared for a big version bump.
@@ -739,11 +727,6 @@ dan_conf = "@DEFDANCONF@"
# This is an experimental feature and might be removed in the future.
experimental_force_guest_pull = @DEFFORCEGUESTPULL@
# kubelet_root_dir is the kubelet root directory used to match ConfigMap/Secret
# volume paths for propagation. Override for distros that use a different path
# (e.g. k0s: /var/lib/k0s/kubelet).
kubelet_root_dir = "@DEFKUBELETROOTDIR@"
# pod_resource_api_sock specifies the unix socket for the Kubelet's
# PodResource API endpoint. If empty, kubernetes based cold plug
# will not be attempted. In order for this feature to work, the

View File

@@ -58,7 +58,7 @@ kernel_verity_params = "@KERNELVERITYPARAMS_NV@"
# Path to the firmware.
# If you want that qemu uses the default firmware leave this option empty
firmware = "@FIRMWAREPATH_NV@"
firmware = "@FIRMWAREPATH@"
# Path to the firmware volume.
# firmware TDVF or OVMF can be split into FIRMWARE_VARS.fd (UEFI variables
@@ -696,18 +696,6 @@ vfio_mode = "@DEFVFIOMODE@"
# be created on the host and shared via virtio-fs. This is potentially slower, but allows sharing of files from host to guest.
disable_guest_empty_dir = @DEFDISABLEGUESTEMPTYDIR@
# Specifies how Kubernetes emptyDir volumes are handled.
# Options:
#
# - shared-fs (default)
# Shares the emptyDir folder with the guest using the method given
# by the `shared_fs` setting.
#
# - block-encrypted
# Plugs a block device to be encrypted in the guest.
#
emptydir_mode = "@DEFEMPTYDIRMODE@"
# Enabled experimental feature list, format: ["a", "b"].
# Experimental features are features not stable enough for production,
# they may break compatibility, and are prepared for a big version bump.
@@ -736,11 +724,6 @@ create_container_timeout = @DEFAULTTIMEOUT_NV@
# (default: /run/kata-containers/dans)
dan_conf = "@DEFDANCONF@"
# kubelet_root_dir is the kubelet root directory used to match ConfigMap/Secret
# volume paths for propagation. Override for distros that use a different path
# (e.g. k0s: /var/lib/k0s/kubelet).
kubelet_root_dir = "@DEFKUBELETROOTDIR@"
# pod_resource_api_sock specifies the unix socket for the Kubelet's
# PodResource API endpoint. If empty, kubernetes based cold plug
# will not be attempted. In order for this feature to work, the

View File

@@ -679,18 +679,6 @@ vfio_mode = "@DEFVFIOMODE_SE@"
# be created on the host and shared via virtio-fs. This is potentially slower, but allows sharing of files from host to guest.
disable_guest_empty_dir = @DEFDISABLEGUESTEMPTYDIR@
# Specifies how Kubernetes emptyDir volumes are handled.
# Options:
#
# - shared-fs (default)
# Shares the emptyDir folder with the guest using the method given
# by the `shared_fs` setting.
#
# - block-encrypted
# Plugs a block device to be encrypted in the guest.
#
emptydir_mode = "@DEFEMPTYDIRMODE@"
# Enabled experimental feature list, format: ["a", "b"].
# Experimental features are features not stable enough for production,
# they may break compatibility, and are prepared for a big version bump.
@@ -724,11 +712,6 @@ dan_conf = "@DEFDANCONF@"
# This is an experimental feature and might be removed in the future.
experimental_force_guest_pull = @DEFFORCEGUESTPULL@
# kubelet_root_dir is the kubelet root directory used to match ConfigMap/Secret
# volume paths for propagation. Override for distros that use a different path
# (e.g. k0s: /var/lib/k0s/kubelet).
kubelet_root_dir = "@DEFKUBELETROOTDIR@"
# pod_resource_api_sock specifies the unix socket for the Kubelet's
# PodResource API endpoint. If empty, kubernetes based cold plug
# will not be attempted. In order for this feature to work, the

View File

@@ -704,18 +704,6 @@ vfio_mode = "@DEFVFIOMODE@"
# be created on the host and shared via virtio-fs. This is potentially slower, but allows sharing of files from host to guest.
disable_guest_empty_dir = @DEFDISABLEGUESTEMPTYDIR@
# Specifies how Kubernetes emptyDir volumes are handled.
# Options:
#
# - shared-fs (default)
# Shares the emptyDir folder with the guest using the method given
# by the `shared_fs` setting.
#
# - block-encrypted
# Plugs a block device to be encrypted in the guest.
#
emptydir_mode = "@DEFEMPTYDIRMODE_COCO@"
# Enabled experimental feature list, format: ["a", "b"].
# Experimental features are features not stable enough for production,
# they may break compatibility, and are prepared for a big version bump.
@@ -749,11 +737,6 @@ dan_conf = "@DEFDANCONF@"
# This is an experimental feature and might be removed in the future.
experimental_force_guest_pull = @DEFFORCEGUESTPULL@
# kubelet_root_dir is the kubelet root directory used to match ConfigMap/Secret
# volume paths for propagation. Override for distros that use a different path
# (e.g. k0s: /var/lib/k0s/kubelet).
kubelet_root_dir = "@DEFKUBELETROOTDIR@"
# pod_resource_api_sock specifies the unix socket for the Kubelet's
# PodResource API endpoint. If empty, kubernetes based cold plug
# will not be attempted. In order for this feature to work, the

View File

@@ -686,18 +686,6 @@ vfio_mode = "@DEFVFIOMODE@"
# be created on the host and shared via virtio-fs. This is potentially slower, but allows sharing of files from host to guest.
disable_guest_empty_dir = @DEFDISABLEGUESTEMPTYDIR@
# Specifies how Kubernetes emptyDir volumes are handled.
# Options:
#
# - shared-fs (default)
# Shares the emptyDir folder with the guest using the method given
# by the `shared_fs` setting.
#
# - block-encrypted
# Plugs a block device to be encrypted in the guest.
#
emptydir_mode = "@DEFEMPTYDIRMODE_COCO@"
# Enabled experimental feature list, format: ["a", "b"].
# Experimental features are features not stable enough for production,
# they may break compatibility, and are prepared for a big version bump.
@@ -731,11 +719,6 @@ dan_conf = "@DEFDANCONF@"
# This is an experimental feature and might be removed in the future.
experimental_force_guest_pull = @DEFFORCEGUESTPULL@
# kubelet_root_dir is the kubelet root directory used to match ConfigMap/Secret
# volume paths for propagation. Override for distros that use a different path
# (e.g. k0s: /var/lib/k0s/kubelet).
kubelet_root_dir = "@DEFKUBELETROOTDIR@"
# pod_resource_api_sock specifies the unix socket for the Kubelet's
# PodResource API endpoint. If empty, kubernetes based cold plug
# will not be attempted. In order for this feature to work, the

View File

@@ -142,7 +142,7 @@ memory_offset = 0
# Please note that this option should be used with the command
# "echo 1 > /proc/sys/vm/overcommit_memory".
# Default false
enable_virtio_mem = @DEFENABLEVIRTIOMEM@
enable_virtio_mem = false
# Disable hotplugging host block devices to guest VMs for container rootfs.
# In case of a storage driver like devicemapper where a container's
@@ -695,18 +695,6 @@ vfio_mode = "@DEFVFIOMODE@"
# be created on the host and shared via virtio-fs. This is potentially slower, but allows sharing of files from host to guest.
disable_guest_empty_dir = @DEFDISABLEGUESTEMPTYDIR@
# Specifies how Kubernetes emptyDir volumes are handled.
# Options:
#
# - shared-fs (default)
# Shares the emptyDir folder with the guest using the method given
# by the `shared_fs` setting.
#
# - block-encrypted
# Plugs a block device to be encrypted in the guest.
#
emptydir_mode = "@DEFEMPTYDIRMODE@"
# Enabled experimental feature list, format: ["a", "b"].
# Experimental features are features not stable enough for production,
# they may break compatibility, and are prepared for a big version bump.
@@ -735,11 +723,6 @@ create_container_timeout = @DEFCREATECONTAINERTIMEOUT@
# (default: /run/kata-containers/dans)
dan_conf = "@DEFDANCONF@"
# kubelet_root_dir is the kubelet root directory used to match ConfigMap/Secret
# volume paths for propagation. Override for distros that use a different path
# (e.g. k0s: /var/lib/k0s/kubelet).
kubelet_root_dir = "@DEFKUBELETROOTDIR@"
# pod_resource_api_sock specifies the unix socket for the Kubelet's
# PodResource API endpoint. If empty, kubernetes based cold plug
# will not be attempted. In order for this feature to work, the

View File

@@ -262,18 +262,6 @@ vfio_mode = "@DEFVFIOMODE@"
# Note: remote hypervisor has no sharing of emptydir mounts from host to guest
disable_guest_empty_dir = false
# Specifies how Kubernetes emptyDir volumes are handled.
# Options:
#
# - shared-fs (default)
# Shares the emptyDir folder with the guest using the method given
# by the `shared_fs` setting.
#
# - block-encrypted
# Plugs a block device to be encrypted in the guest.
#
emptydir_mode = "@DEFEMPTYDIRMODE@"
# Enabled experimental feature list, format: ["a", "b"].
# Experimental features are features not stable enough for production,
# they may break compatibility, and are prepared for a big version bump.
@@ -302,11 +290,6 @@ create_container_timeout = @DEFCREATECONTAINERTIMEOUT@
# (default: /run/kata-containers/dans)
dan_conf = "@DEFDANCONF@"
# kubelet_root_dir is the kubelet root directory used to match ConfigMap/Secret
# volume paths for propagation. Override for distros that use a different path
# (e.g. k0s: /var/lib/k0s/kubelet).
kubelet_root_dir = "@DEFKUBELETROOTDIR@"
# pod_resource_api_sock specifies the unix socket for the Kubelet's
# PodResource API endpoint. If empty, kubernetes based cold plug
# will not be attempted. In order for this feature to work, the

View File

@@ -397,18 +397,6 @@ static_sandbox_resource_mgmt = @DEFSTATICRESOURCEMGMT_STRATOVIRT@
# be created on the host and shared via virtio-fs. This is potentially slower, but allows sharing of files from host to guest.
disable_guest_empty_dir = @DEFDISABLEGUESTEMPTYDIR@
# Specifies how Kubernetes emptyDir volumes are handled.
# Options:
#
# - shared-fs (default)
# Shares the emptyDir folder with the guest using the method given
# by the `shared_fs` setting.
#
# - block-encrypted
# Plugs a block device to be encrypted in the guest.
#
emptydir_mode = "@DEFEMPTYDIRMODE@"
# Enabled experimental feature list, format: ["a", "b"].
# Experimental features are features not stable enough for production,
# they may break compatibility, and are prepared for a big version bump.
@@ -437,11 +425,6 @@ create_container_timeout = @DEFCREATECONTAINERTIMEOUT@
# (default: /run/kata-containers/dans)
dan_conf = "@DEFDANCONF@"
# kubelet_root_dir is the kubelet root directory used to match ConfigMap/Secret
# volume paths for propagation. Override for distros that use a different path
# (e.g. k0s: /var/lib/k0s/kubelet).
kubelet_root_dir = "@DEFKUBELETROOTDIR@"
# pod_resource_api_sock specifies the unix socket for the Kubelet's
# PodResource API endpoint. If empty, kubernetes based cold plug
# will not be attempted. In order for this feature to work, the

Some files were not shown because too many files have changed in this diff Show More