Merge pull request #6559 from stevenhorsman/CCv0-merge-30th-mar

CCv0: Merge main into CCv0 branch
This commit is contained in:
Fabiano Fidêncio
2023-05-17 17:00:39 +02:00
committed by GitHub
243 changed files with 10103 additions and 2674 deletions

View File

@@ -1,10 +1,14 @@
name: CI | Publish kata-deploy payload for amd64
name: CI | Build kata-static tarball for amd64
on:
workflow_call:
inputs:
target-arch:
required: true
tarball-suffix:
required: false
type: string
push-to-registry:
required: false
type: string
default: no
jobs:
build-asset:
@@ -15,21 +19,23 @@ jobs:
- cloud-hypervisor
- firecracker
- kernel
- kernel-dragonball-experimental
- kernel-tdx-experimental
- kernel-gpu
- kernel-gpu-snp
- kernel-gpu-tdx-experimental
- nydus
- qemu
- qemu-tdx-experimental
- rootfs-image
- rootfs-initrd
- shim-v2
- tdvf
- virtiofsd
steps:
- name: Login to Kata Containers quay.io
uses: docker/login-action@v2
with:
registry: quay.io
username: ${{ secrets.QUAY_DEPLOYER_USERNAME }}
password: ${{ secrets.QUAY_DEPLOYER_PASSWORD }}
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0 # This is needed in order to keep the commit ids history
- name: Build ${{ matrix.asset }}
run: |
@@ -40,12 +46,12 @@ jobs:
env:
KATA_ASSET: ${{ matrix.asset }}
TAR_OUTPUT: ${{ matrix.asset }}.tar.gz
PUSH_TO_REGISTRY: yes
PUSH_TO_REGISTRY: ${{ inputs.push-to-registry }}
- name: store-artifact ${{ matrix.asset }}
uses: actions/upload-artifact@v3
with:
name: kata-artifacts-amd64
name: kata-artifacts-amd64${{ inputs.tarball-suffix }}
path: kata-build/kata-static-${{ matrix.asset }}.tar.xz
retention-days: 1
if-no-files-found: error
@@ -55,10 +61,12 @@ jobs:
needs: build-asset
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: get-artifacts
uses: actions/download-artifact@v3
with:
name: kata-artifacts-amd64
name: kata-artifacts-amd64${{ inputs.tarball-suffix }}
path: kata-artifacts
- name: merge-artifacts
run: |
@@ -66,31 +74,7 @@ jobs:
- name: store-artifacts
uses: actions/upload-artifact@v3
with:
name: kata-static-tarball-amd64
name: kata-static-tarball-amd64${{ inputs.tarball-suffix }}
path: kata-static.tar.xz
retention-days: 1
if-no-files-found: error
kata-payload:
needs: create-kata-tarball
runs-on: ubuntu-latest
steps:
- name: Login to Kata Containers quay.io
uses: docker/login-action@v2
with:
registry: quay.io
username: ${{ secrets.QUAY_DEPLOYER_USERNAME }}
password: ${{ secrets.QUAY_DEPLOYER_PASSWORD }}
- uses: actions/checkout@v3
- name: get-kata-tarball
uses: actions/download-artifact@v3
with:
name: kata-static-tarball-amd64
- name: build-and-push-kata-payload
id: build-and-push-kata-payload
run: |
./tools/packaging/kata-deploy/local-build/kata-deploy-build-and-upload-payload.sh \
$(pwd)/kata-static.tar.xz "quay.io/kata-containers/kata-deploy-ci" \
"kata-containers-${{ inputs.target-arch }}"

View File

@@ -1,10 +1,14 @@
name: CI | Publish kata-deploy payload for arm64
name: CI | Build kata-static tarball for arm64
on:
workflow_call:
inputs:
target-arch:
required: true
tarball-suffix:
required: false
type: string
push-to-registry:
required: false
type: string
default: no
jobs:
build-asset:
@@ -15,25 +19,21 @@ jobs:
- cloud-hypervisor
- firecracker
- kernel
- kernel-dragonball-experimental
- nydus
- qemu
- rootfs-image
- rootfs-initrd
- shim-v2
- virtiofsd
steps:
- name: Login to Kata Containers quay.io
uses: docker/login-action@v2
with:
registry: quay.io
username: ${{ secrets.QUAY_DEPLOYER_USERNAME }}
password: ${{ secrets.QUAY_DEPLOYER_PASSWORD }}
- name: Adjust a permission for repo
run: |
sudo chown -R $USER:$USER $GITHUB_WORKSPACE
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0 # This is needed in order to keep the commit ids history
- name: Build ${{ matrix.asset }}
run: |
@@ -44,12 +44,12 @@ jobs:
env:
KATA_ASSET: ${{ matrix.asset }}
TAR_OUTPUT: ${{ matrix.asset }}.tar.gz
PUSH_TO_REGISTRY: yes
PUSH_TO_REGISTRY: ${{ inputs.push-to-registry }}
- name: store-artifact ${{ matrix.asset }}
uses: actions/upload-artifact@v3
with:
name: kata-artifacts-arm64
name: kata-artifacts-arm64${{ inputs.tarball-suffix }}
path: kata-build/kata-static-${{ matrix.asset }}.tar.xz
retention-days: 1
if-no-files-found: error
@@ -63,10 +63,12 @@ jobs:
sudo chown -R $USER:$USER $GITHUB_WORKSPACE
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: get-artifacts
uses: actions/download-artifact@v3
with:
name: kata-artifacts-arm64
name: kata-artifacts-arm64${{ inputs.tarball-suffix }}
path: kata-artifacts
- name: merge-artifacts
run: |
@@ -74,35 +76,7 @@ jobs:
- name: store-artifacts
uses: actions/upload-artifact@v3
with:
name: kata-static-tarball-arm64
name: kata-static-tarball-arm64${{ inputs.tarball-suffix }}
path: kata-static.tar.xz
retention-days: 1
if-no-files-found: error
kata-payload:
needs: create-kata-tarball
runs-on: arm64
steps:
- name: Login to Kata Containers quay.io
uses: docker/login-action@v2
with:
registry: quay.io
username: ${{ secrets.QUAY_DEPLOYER_USERNAME }}
password: ${{ secrets.QUAY_DEPLOYER_PASSWORD }}
- name: Adjust a permission for repo
run: |
sudo chown -R $USER:$USER $GITHUB_WORKSPACE
- uses: actions/checkout@v3
- name: get-kata-tarball
uses: actions/download-artifact@v3
with:
name: kata-static-tarball-arm64
- name: build-and-push-kata-payload
id: build-and-push-kata-payload
run: |
./tools/packaging/kata-deploy/local-build/kata-deploy-build-and-upload-payload.sh \
$(pwd)/kata-static.tar.xz "quay.io/kata-containers/kata-deploy-ci" \
"kata-containers-${{ inputs.target-arch }}"

View File

@@ -1,10 +1,14 @@
name: CI | Publish kata-deploy payload for s390x
name: CI | Build kata-static tarball for s390x
on:
workflow_call:
inputs:
target-arch:
required: true
tarball-suffix:
required: false
type: string
push-to-registry:
required: false
type: string
default: no
jobs:
build-asset:
@@ -13,25 +17,19 @@ jobs:
matrix:
asset:
- kernel
- shim-v2
- qemu
- rootfs-image
- rootfs-initrd
- shim-v2
- virtiofsd
steps:
- name: Login to Kata Containers quay.io
uses: docker/login-action@v2
with:
registry: quay.io
username: ${{ secrets.QUAY_DEPLOYER_USERNAME }}
password: ${{ secrets.QUAY_DEPLOYER_PASSWORD }}
- name: Adjust a permission for repo
run: |
sudo chown -R $USER:$USER $GITHUB_WORKSPACE
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0 # This is needed in order to keep the commit ids history
- name: Build ${{ matrix.asset }}
run: |
@@ -43,12 +41,12 @@ jobs:
env:
KATA_ASSET: ${{ matrix.asset }}
TAR_OUTPUT: ${{ matrix.asset }}.tar.gz
PUSH_TO_REGISTRY: yes
PUSH_TO_REGISTRY: ${{ inputs.push-to-registry }}
- name: store-artifact ${{ matrix.asset }}
uses: actions/upload-artifact@v3
with:
name: kata-artifacts-s390x
name: kata-artifacts-s390x${{ inputs.tarball-suffix }}
path: kata-build/kata-static-${{ matrix.asset }}.tar.xz
retention-days: 1
if-no-files-found: error
@@ -62,10 +60,12 @@ jobs:
sudo chown -R $USER:$USER $GITHUB_WORKSPACE
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: get-artifacts
uses: actions/download-artifact@v3
with:
name: kata-artifacts-s390x
name: kata-artifacts-s390x${{ inputs.tarball-suffix }}
path: kata-artifacts
- name: merge-artifacts
run: |
@@ -73,35 +73,7 @@ jobs:
- name: store-artifacts
uses: actions/upload-artifact@v3
with:
name: kata-static-tarball-s390x
name: kata-static-tarball-s390x${{ inputs.tarball-suffix }}
path: kata-static.tar.xz
retention-days: 1
if-no-files-found: error
kata-payload:
needs: create-kata-tarball
runs-on: s390x
steps:
- name: Login to Kata Containers quay.io
uses: docker/login-action@v2
with:
registry: quay.io
username: ${{ secrets.QUAY_DEPLOYER_USERNAME }}
password: ${{ secrets.QUAY_DEPLOYER_PASSWORD }}
- name: Adjust a permission for repo
run: |
sudo chown -R $USER:$USER $GITHUB_WORKSPACE
- uses: actions/checkout@v3
- name: get-kata-tarball
uses: actions/download-artifact@v3
with:
name: kata-static-tarball-s390x
- name: build-and-push-kata-payload
id: build-and-push-kata-payload
run: |
./tools/packaging/kata-deploy/local-build/kata-deploy-build-and-upload-payload.sh \
$(pwd)/kata-static.tar.xz "quay.io/kata-containers/kata-deploy-ci" \
"kata-containers-${{ inputs.target-arch }}"

38
.github/workflows/ci-on-push.yaml vendored Normal file
View File

@@ -0,0 +1,38 @@
name: Kata Containers CI
on:
pull_request_target:
branches:
- 'main'
jobs:
build-kata-static-tarball-amd64:
uses: ./.github/workflows/build-kata-static-tarball-amd64.yaml
with:
tarball-suffix: -${{ github.event.pull_request.number}}-${{ github.event.pull_request.head.sha }}
publish-kata-deploy-payload-amd64:
needs: build-kata-static-tarball-amd64
uses: ./.github/workflows/publish-kata-deploy-payload-amd64.yaml
with:
tarball-suffix: -${{ github.event.pull_request.number}}-${{ github.event.pull_request.head.sha }}
registry: ghcr.io
repo: ${{ github.repository_owner }}/kata-deploy-ci
tag: ${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }}-amd64
secrets: inherit
run-k8s-tests-on-aks:
needs: publish-kata-deploy-payload-amd64
uses: ./.github/workflows/run-k8s-tests-on-aks.yaml
with:
registry: ghcr.io
repo: ${{ github.repository_owner }}/kata-deploy-ci
tag: ${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }}-amd64
secrets: inherit
run-k8s-tests-on-tdx:
needs: publish-kata-deploy-payload-amd64
uses: ./.github/workflows/run-k8s-tests-on-tdx.yaml
with:
registry: ghcr.io
repo: ${{ github.repository_owner }}/kata-deploy-ci
tag: ${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }}-amd64

View File

@@ -1,84 +0,0 @@
name: kata deploy build
on:
pull_request:
types:
- opened
- edited
- reopened
- synchronize
paths:
- tools/**
- versions.yaml
jobs:
build-asset:
runs-on: ubuntu-latest
strategy:
matrix:
asset:
- kernel
- kernel-dragonball-experimental
- shim-v2
- qemu
- cloud-hypervisor
- firecracker
- rootfs-image
- rootfs-initrd
- virtiofsd
- nydus
steps:
- uses: actions/checkout@v2
- name: Build ${{ matrix.asset }}
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
run: |
make "${KATA_ASSET}-tarball"
build_dir=$(readlink -f build)
# store-artifact does not work with symlink
sudo cp -r --preserve=all "${build_dir}" "kata-build"
env:
KATA_ASSET: ${{ matrix.asset }}
- name: store-artifact ${{ matrix.asset }}
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
uses: actions/upload-artifact@v2
with:
name: kata-artifacts
path: kata-build/kata-static-${{ matrix.asset }}.tar.xz
if-no-files-found: error
create-kata-tarball:
runs-on: ubuntu-latest
needs: build-asset
steps:
- uses: actions/checkout@v2
- name: get-artifacts
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
uses: actions/download-artifact@v2
with:
name: kata-artifacts
path: build
- name: merge-artifacts
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
run: |
make merge-builds
- name: store-artifacts
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
uses: actions/upload-artifact@v2
with:
name: kata-static-tarball
path: kata-static.tar.xz
make-kata-tarball:
runs-on: ubuntu-latest
steps:
- name: Free disk space
run: |
sudo rm -rf /usr/share/dotnet
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
- uses: actions/checkout@v2
- name: make kata-tarball
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
run: |
make kata-tarball
sudo make install-tarball

View File

@@ -1,164 +0,0 @@
on:
workflow_dispatch: # this is used to trigger the workflow on non-main branches
inputs:
pr:
description: 'PR number from the selected branch to test'
type: string
required: true
issue_comment:
types: [created, edited]
name: test-kata-deploy
jobs:
check-comment-and-membership:
runs-on: ubuntu-latest
if: |
github.event.issue.pull_request
&& github.event_name == 'issue_comment'
&& github.event.action == 'created'
&& startsWith(github.event.comment.body, '/test_kata_deploy')
|| github.event_name == 'workflow_dispatch'
steps:
- name: Check membership on comment or dispatch
uses: kata-containers/is-organization-member@1.0.1
id: is_organization_member
with:
organization: kata-containers
username: ${{ github.event.comment.user.login || github.event.sender.login }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Fail if not member
run: |
result=${{ steps.is_organization_member.outputs.result }}
if [ $result == false ]; then
user=${{ github.event.comment.user.login || github.event.sender.login }}
echo Either ${user} is not part of the kata-containers organization
echo or ${user} has its Organization Visibility set to Private at
echo https://github.com/orgs/kata-containers/people?query=${user}
echo
echo Ensure you change your Organization Visibility to Public and
echo trigger the test again.
exit 1
fi
build-asset:
runs-on: ubuntu-latest
needs: check-comment-and-membership
strategy:
matrix:
asset:
- cloud-hypervisor
- firecracker
- kernel
- kernel-dragonball-experimental
- nydus
- qemu
- rootfs-image
- rootfs-initrd
- shim-v2
- virtiofsd
steps:
- name: get-PR-ref
id: get-PR-ref
run: |
if [ ${{ github.event_name }} == 'issue_comment' ]; then
ref=$(cat $GITHUB_EVENT_PATH | jq -r '.issue.pull_request.url' | sed 's#^.*\/pulls#refs\/pull#' | sed 's#$#\/merge#')
else # workflow_dispatch
ref="refs/pull/${{ github.event.inputs.pr }}/merge"
fi
echo "reference for PR: " ${ref} "event:" ${{ github.event_name }}
echo "pr-ref=${ref}" >> $GITHUB_OUTPUT
- uses: actions/checkout@v2
with:
ref: ${{ steps.get-PR-ref.outputs.pr-ref }}
- name: Build ${{ matrix.asset }}
run: |
make "${KATA_ASSET}-tarball"
build_dir=$(readlink -f build)
# store-artifact does not work with symlink
sudo cp -r "${build_dir}" "kata-build"
env:
KATA_ASSET: ${{ matrix.asset }}
TAR_OUTPUT: ${{ matrix.asset }}.tar.gz
- name: store-artifact ${{ matrix.asset }}
uses: actions/upload-artifact@v2
with:
name: kata-artifacts
path: kata-build/kata-static-${{ matrix.asset }}.tar.xz
if-no-files-found: error
create-kata-tarball:
runs-on: ubuntu-latest
needs: build-asset
steps:
- name: get-PR-ref
id: get-PR-ref
run: |
if [ ${{ github.event_name }} == 'issue_comment' ]; then
ref=$(cat $GITHUB_EVENT_PATH | jq -r '.issue.pull_request.url' | sed 's#^.*\/pulls#refs\/pull#' | sed 's#$#\/merge#')
else # workflow_dispatch
ref="refs/pull/${{ github.event.inputs.pr }}/merge"
fi
echo "reference for PR: " ${ref} "event:" ${{ github.event_name }}
echo "pr-ref=${ref}" >> $GITHUB_OUTPUT
- uses: actions/checkout@v2
with:
ref: ${{ steps.get-PR-ref.outputs.pr-ref }}
- name: get-artifacts
uses: actions/download-artifact@v2
with:
name: kata-artifacts
path: kata-artifacts
- name: merge-artifacts
run: |
./tools/packaging/kata-deploy/local-build/kata-deploy-merge-builds.sh kata-artifacts
- name: store-artifacts
uses: actions/upload-artifact@v2
with:
name: kata-static-tarball
path: kata-static.tar.xz
kata-deploy:
needs: create-kata-tarball
runs-on: ubuntu-latest
steps:
- name: get-PR-ref
id: get-PR-ref
run: |
if [ ${{ github.event_name }} == 'issue_comment' ]; then
ref=$(cat $GITHUB_EVENT_PATH | jq -r '.issue.pull_request.url' | sed 's#^.*\/pulls#refs\/pull#' | sed 's#$#\/merge#')
else # workflow_dispatch
ref="refs/pull/${{ github.event.inputs.pr }}/merge"
fi
echo "reference for PR: " ${ref} "event:" ${{ github.event_name }}
echo "pr-ref=${ref}" >> $GITHUB_OUTPUT
- uses: actions/checkout@v2
with:
ref: ${{ steps.get-PR-ref.outputs.pr-ref }}
- name: get-kata-tarball
uses: actions/download-artifact@v2
with:
name: kata-static-tarball
- name: build-and-push-kata-deploy-ci
id: build-and-push-kata-deploy-ci
run: |
PR_SHA=$(git log --format=format:%H -n1)
mv kata-static.tar.xz $GITHUB_WORKSPACE/tools/packaging/kata-deploy/kata-static.tar.xz
docker build --build-arg KATA_ARTIFACTS=kata-static.tar.xz -t quay.io/kata-containers/kata-deploy-ci:$PR_SHA $GITHUB_WORKSPACE/tools/packaging/kata-deploy
docker login -u ${{ secrets.QUAY_DEPLOYER_USERNAME }} -p ${{ secrets.QUAY_DEPLOYER_PASSWORD }} quay.io
docker push quay.io/kata-containers/kata-deploy-ci:$PR_SHA
mkdir -p packaging/kata-deploy
ln -s $GITHUB_WORKSPACE/tools/packaging/kata-deploy/action packaging/kata-deploy/action
echo "PKG_SHA=${PR_SHA}" >> $GITHUB_OUTPUT
- name: test-kata-deploy-ci-in-aks
uses: ./packaging/kata-deploy/action
with:
packaging-sha: ${{steps.build-and-push-kata-deploy-ci.outputs.PKG_SHA}}
env:
PKG_SHA: ${{steps.build-and-push-kata-deploy-ci.outputs.PKG_SHA}}
AZ_APPID: ${{ secrets.AZ_APPID }}
AZ_PASSWORD: ${{ secrets.AZ_PASSWORD }}
AZ_SUBSCRIPTION_ID: ${{ secrets.AZ_SUBSCRIPTION_ID }}
AZ_TENANT_ID: ${{ secrets.AZ_TENANT_ID }}

View File

@@ -7,26 +7,50 @@ on:
jobs:
build-assets-amd64:
uses: ./.github/workflows/payload-after-push-amd64.yaml
uses: ./.github/workflows/build-kata-static-tarball-amd64.yaml
with:
target-arch: amd64
secrets: inherit
push-to-registry: yes
build-assets-arm64:
uses: ./.github/workflows/payload-after-push-arm64.yaml
uses: ./.github/workflows/build-kata-static-tarball-arm64.yaml
with:
target-arch: arm64
secrets: inherit
push-to-registry: yes
build-assets-s390x:
uses: ./.github/workflows/payload-after-push-s390x.yaml
uses: ./.github/workflows/build-kata-static-tarball-s390x.yaml
with:
target-arch: s390x
push-to-registry: yes
publish-kata-deploy-payload-amd64:
needs: build-assets-amd64
uses: ./.github/workflows/publish-kata-deploy-payload-amd64.yaml
with:
registry: quay.io
repo: kata-containers/kata-deploy-ci
tag: kata-containers-amd64
secrets: inherit
publish:
publish-kata-deploy-payload-arm64:
needs: build-assets-arm64
uses: ./.github/workflows/publish-kata-deploy-payload-arm64.yaml
with:
registry: quay.io
repo: kata-containers/kata-deploy-ci
tag: kata-containers-arm64
secrets: inherit
publish-kata-deploy-payload-s390x:
needs: build-assets-s390x
uses: ./.github/workflows/publish-kata-deploy-payload-s390x.yaml
with:
registry: quay.io
repo: kata-containers/kata-deploy-ci
tag: kata-containers-s390x
secrets: inherit
publish-manifest:
runs-on: ubuntu-latest
needs: [build-assets-amd64, build-assets-arm64, build-assets-s390x]
needs: [publish-kata-deploy-payload-amd64, publish-kata-deploy-payload-arm64, publish-kata-deploy-payload-s390x]
steps:
- name: Checkout repository
uses: actions/checkout@v3

View File

@@ -0,0 +1,52 @@
name: CI | Publish kata-deploy payload for amd64
on:
workflow_call:
inputs:
tarball-suffix:
required: false
type: string
registry:
required: true
type: string
repo:
required: true
type: string
tag:
required: true
type: string
jobs:
kata-payload:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: get-kata-tarball
uses: actions/download-artifact@v3
with:
name: kata-static-tarball-amd64${{ inputs.tarball-suffix }}
- name: Login to Kata Containers quay.io
if: ${{ inputs.registry == 'quay.io' }}
uses: docker/login-action@v2
with:
registry: quay.io
username: ${{ secrets.QUAY_DEPLOYER_USERNAME }}
password: ${{ secrets.QUAY_DEPLOYER_PASSWORD }}
- name: Login to Kata Containers ghcr.io
if: ${{ inputs.registry == 'ghcr.io' }}
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: build-and-push-kata-payload
id: build-and-push-kata-payload
run: |
./tools/packaging/kata-deploy/local-build/kata-deploy-build-and-upload-payload.sh \
$(pwd)/kata-static.tar.xz \
${{ inputs.registry }}/${{ inputs.repo }} ${{ inputs.tag }}

View File

@@ -0,0 +1,57 @@
name: CI | Publish kata-deploy payload for arm64
on:
workflow_call:
inputs:
tarball-suffix:
required: false
type: string
registry:
required: true
type: string
repo:
required: true
type: string
tag:
required: true
type: string
jobs:
kata-payload:
runs-on: arm64
steps:
- name: Adjust a permission for repo
run: |
sudo chown -R $USER:$USER $GITHUB_WORKSPACE
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: get-kata-tarball
uses: actions/download-artifact@v3
with:
name: kata-static-tarball-arm64${{ inputs.tarball-suffix }}
- name: Login to Kata Containers quay.io
if: ${{ inputs.registry == 'quay.io' }}
uses: docker/login-action@v2
with:
registry: quay.io
username: ${{ secrets.QUAY_DEPLOYER_USERNAME }}
password: ${{ secrets.QUAY_DEPLOYER_PASSWORD }}
- name: Login to Kata Containers ghcr.io
if: ${{ inputs.registry == 'ghcr.io' }}
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: build-and-push-kata-payload
id: build-and-push-kata-payload
run: |
./tools/packaging/kata-deploy/local-build/kata-deploy-build-and-upload-payload.sh \
$(pwd)/kata-static.tar.xz \
${{ inputs.registry }}/${{ inputs.repo }} ${{ inputs.tag }}

View File

@@ -0,0 +1,56 @@
name: CI | Publish kata-deploy payload for s390x
on:
workflow_call:
inputs:
tarball-suffix:
required: false
type: string
registry:
required: true
type: string
repo:
required: true
type: string
tag:
required: true
type: string
jobs:
kata-payload:
runs-on: s390x
steps:
- name: Adjust a permission for repo
run: |
sudo chown -R $USER:$USER $GITHUB_WORKSPACE
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: get-kata-tarball
uses: actions/download-artifact@v3
with:
name: kata-static-tarball-s390x${{ inputs.tarball-suffix }}
- name: Login to Kata Containers quay.io
if: ${{ inputs.registry == 'quay.io' }}
uses: docker/login-action@v2
with:
registry: quay.io
username: ${{ secrets.QUAY_DEPLOYER_USERNAME }}
password: ${{ secrets.QUAY_DEPLOYER_PASSWORD }}
- name: Login to Kata Containers ghcr.io
if: ${{ inputs.registry == 'ghcr.io' }}
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: build-and-push-kata-payload
id: build-and-push-kata-payload
run: |
./tools/packaging/kata-deploy/local-build/kata-deploy-build-and-upload-payload.sh \
$(pwd)/kata-static.tar.xz \
${{ inputs.registry }}/${{ inputs.repo }} ${{ inputs.tag }}

View File

@@ -5,69 +5,18 @@ on:
- '[0-9]+.[0-9]+.[0-9]+*'
jobs:
build-asset:
runs-on: ubuntu-latest
strategy:
matrix:
asset:
- cloud-hypervisor
- firecracker
- kernel
- kernel-dragonball-experimental
- nydus
- qemu
- rootfs-image
- rootfs-initrd
- shim-v2
- virtiofsd
steps:
- uses: actions/checkout@v2
- name: Build ${{ matrix.asset }}
run: |
./tools/packaging/kata-deploy/local-build/kata-deploy-copy-yq-installer.sh
./tools/packaging/kata-deploy/local-build/kata-deploy-binaries-in-docker.sh --build="${KATA_ASSET}"
build_dir=$(readlink -f build)
# store-artifact does not work with symlink
sudo cp -r "${build_dir}" "kata-build"
env:
KATA_ASSET: ${{ matrix.asset }}
TAR_OUTPUT: ${{ matrix.asset }}.tar.gz
- name: store-artifact ${{ matrix.asset }}
uses: actions/upload-artifact@v2
with:
name: kata-artifacts
path: kata-build/kata-static-${{ matrix.asset }}.tar.xz
if-no-files-found: error
create-kata-tarball:
runs-on: ubuntu-latest
needs: build-asset
steps:
- uses: actions/checkout@v2
- name: get-artifacts
uses: actions/download-artifact@v2
with:
name: kata-artifacts
path: kata-artifacts
- name: merge-artifacts
run: |
./tools/packaging/kata-deploy/local-build/kata-deploy-merge-builds.sh kata-artifacts
- name: store-artifacts
uses: actions/upload-artifact@v2
with:
name: kata-static-tarball
path: kata-static.tar.xz
build-kata-static-tarball-amd64:
uses: ./.github/workflows/build-kata-static-tarball-amd64.yaml
kata-deploy:
needs: create-kata-tarball
needs: build-kata-static-tarball-amd64
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: get-kata-tarball
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
name: kata-static-tarball
name: kata-static-tarball-amd64
- name: build-and-push-kata-deploy-ci
id: build-and-push-kata-deploy-ci
run: |
@@ -112,9 +61,9 @@ jobs:
needs: kata-deploy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: download-artifacts
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
name: kata-static-tarball
- name: install hub
@@ -136,7 +85,7 @@ jobs:
needs: upload-static-tarball
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: generate-and-upload-tarball
run: |
tag=$(echo $GITHUB_REF | cut -d/ -f3-)
@@ -150,7 +99,7 @@ jobs:
needs: upload-cargo-vendored-tarball
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: download-and-upload-tarball
env:
GITHUB_TOKEN: ${{ secrets.GIT_UPLOAD_TOKEN }}

View File

@@ -0,0 +1,92 @@
name: CI | Run kubernetes tests on AKS
on:
workflow_call:
inputs:
registry:
required: true
type: string
repo:
required: true
type: string
tag:
required: true
type: string
jobs:
run-k8s-tests:
strategy:
fail-fast: false
matrix:
vmm:
- clh
- dragonball
- qemu
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Download Azure CLI
run: |
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
- name: Log into the Azure account
run: |
az login \
--service-principal \
-u "${{ secrets.AZ_APPID }}" \
-p "${{ secrets.AZ_PASSWORD }}" \
--tenant "${{ secrets.AZ_TENANT_ID }}"
- name: Create AKS cluster
run: |
az aks create \
-g "kataCI" \
-n "${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }}-${{ matrix.vmm }}-amd64" \
-s "Standard_D4s_v5" \
--node-count 1 \
--generate-ssh-keys
- name: Install `bats`
run: |
sudo apt-get update
sudo apt-get -y install bats
- name: Install `kubectl`
run: |
sudo az aks install-cli
- name: Download credentials for the Kubernetes CLI to use them
run: |
az aks get-credentials -g "kataCI" -n ${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }}-${{ matrix.vmm }}-amd64
- name: Deploy kata-deploy
run: |
sed -i -e "s|quay.io/kata-containers/kata-deploy:latest|${{ inputs.registry }}/${{ inputs.repo }}:${{ inputs.tag }}|g" tools/packaging/kata-deploy/kata-deploy/base/kata-deploy.yaml
cat tools/packaging/kata-deploy/kata-deploy/base/kata-deploy.yaml
cat tools/packaging/kata-deploy/kata-deploy/base/kata-deploy.yaml | grep "${{ inputs.registry }}/${{ inputs.repo }}:${{ inputs.tag }}" || die "Failed to setup the tests image"
kubectl apply -f tools/packaging/kata-deploy/kata-rbac/base/kata-rbac.yaml
kubectl apply -f tools/packaging/kata-deploy/kata-deploy/base/kata-deploy.yaml
kubectl -n kube-system wait --timeout=10m --for=condition=Ready -l name=kata-deploy pod
kubectl apply -f tools/packaging/kata-deploy/runtimeclasses/kata-runtimeClasses.yaml
- name: Run tests
timeout-minutes: 30
run: |
pushd tests/integration/kubernetes
sed -i -e 's|runtimeClassName: kata|runtimeClassName: kata-${{ matrix.vmm }}|' runtimeclass_workloads/*.yaml
bash run_kubernetes_tests.sh
popd
env:
KATA_HYPERVISOR: ${{ matrix.vmm }}
- name: Delete AKS cluster
if: always()
run: |
az aks delete \
-g "kataCI" \
-n "${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.sha }}-${{ matrix.vmm }}-amd64" \
--yes \
--no-wait

View File

@@ -0,0 +1,65 @@
name: CI | Run kubernetes tests on TDX
on:
workflow_call:
inputs:
registry:
required: true
type: string
repo:
required: true
type: string
tag:
required: true
type: string
jobs:
run-k8s-tests:
strategy:
fail-fast: false
matrix:
vmm:
- qemu-tdx
runs-on: tdx
env:
KUBECONFIG: /etc/rancher/k3s/k3s.yaml
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Deploy kata-deploy
run: |
sed -i -e "s|quay.io/kata-containers/kata-deploy:latest|${{ inputs.registry }}/${{ inputs.repo }}:${{ inputs.tag }}|g" tools/packaging/kata-deploy/kata-deploy/base/kata-deploy.yaml
cat tools/packaging/kata-deploy/kata-deploy/base/kata-deploy.yaml
cat tools/packaging/kata-deploy/kata-deploy/base/kata-deploy.yaml | grep "${{ inputs.registry }}/${{ inputs.repo }}:${{ inputs.tag }}" || die "Failed to setup the tests image"
kubectl apply -f tools/packaging/kata-deploy/kata-rbac/base/kata-rbac.yaml
kubectl apply -k tools/packaging/kata-deploy/kata-deploy/overlays/k3s
kubectl -n kube-system wait --timeout=10m --for=condition=Ready -l name=kata-deploy pod
kubectl apply -f tools/packaging/kata-deploy/runtimeclasses/kata-runtimeClasses.yaml
- name: Run tests
timeout-minutes: 30
run: |
pushd tests/integration/kubernetes
sed -i -e 's|runtimeClassName: kata|runtimeClassName: kata-${{ matrix.vmm }}|' runtimeclass_workloads/*.yaml
bash run_kubernetes_tests.sh
popd
env:
KATA_HYPERVISOR: ${{ matrix.vmm }}
- name: Delete kata-deploy
if: always()
run: |
kubectl delete -k tools/packaging/kata-deploy/kata-deploy/overlays/k3s
kubectl -n kube-system wait --timeout=10m --for=delete -l name=kata-deploy pod
sed -i -e "s|quay.io/kata-containers/kata-deploy:latest|${{ inputs.registry }}/${{ inputs.repo }}:${{ inputs.tag }}|g" tools/packaging/kata-deploy/kata-cleanup/base/kata-cleanup.yaml
cat tools/packaging/kata-deploy/kata-cleanup/base/kata-cleanup.yaml
cat tools/packaging/kata-deploy/kata-cleanup/base/kata-cleanup.yaml | grep "${{ inputs.registry }}/${{ inputs.repo }}:${{ inputs.tag }}" || die "Failed to setup the tests image"
kubectl apply -f tools/packaging/kata-deploy/kata-cleanup/base/kata-cleanup.yaml
sleep 180s
kubectl delete -f tools/packaging/kata-deploy/kata-cleanup/base/kata-cleanup.yaml
kubectl delete -f tools/packaging/kata-deploy/kata-rbac/base/kata-rbac.yaml
kubectl delete -f tools/packaging/kata-deploy/runtimeclasses/kata-runtimeClasses.yaml

View File

@@ -1 +1 @@
3.1.0-rc0
3.2.0-alpha0

View File

@@ -36,7 +36,7 @@ compatibility, and performance on par with MACVTAP.
Kata Containers has deprecated support for bridge due to lacking performance relative to TC-filter and MACVTAP.
Kata Containers supports both
[CNM](https://github.com/docker/libnetwork/blob/master/docs/design.md#the-container-network-model)
[CNM](https://github.com/moby/libnetwork/blob/master/docs/design.md#the-container-network-model)
and [CNI](https://github.com/containernetworking/cni) for networking management.
## Network Hotplug

View File

@@ -1,5 +1,5 @@
## Introduction
To improve security, Kata Container supports running the VMM process (currently only QEMU) as a non-`root` user.
To improve security, Kata Container supports running the VMM process (QEMU and cloud-hypervisor) as a non-`root` user.
This document describes how to enable the rootless VMM mode and its limitations.
## Pre-requisites
@@ -27,7 +27,7 @@ Another necessary change is to move the hypervisor runtime files (e.g. `vhost-fs
## Limitations
1. Only the VMM process is running as a non-root user. Other processes such as Kata Container shimv2 and `virtiofsd` still run as the root user.
2. Currently, this feature is only supported in QEMU. Still need to bring it to Firecracker and Cloud Hypervisor (see https://github.com/kata-containers/kata-containers/issues/2567).
2. Currently, this feature is only supported in QEMU and cloud-hypervisor. For firecracker, you can use jailer to run the VMM process with a non-root user.
3. Certain features will not work when rootless VMM is enabled, including:
1. Passing devices to the guest (`virtio-blk`, `virtio-scsi`) will not work if the non-privileged user does not have permission to access it (leading to a permission denied error). A more permissive permission (e.g. 666) may overcome this issue. However, you need to be aware of the potential security implications of reducing the security on such devices.
2. `vfio` device will also not work because of permission denied error.

View File

@@ -49,7 +49,7 @@ Follow the [`kata-deploy`](../../tools/packaging/kata-deploy/README.md).
* Download `Rustup` and install `Rust`
> **Notes:**
> Rust version 1.62.0 is needed
> For Rust version, please see [`versions.yaml`](../../versions.yaml) file's rust section.
Example for `x86_64`
```

View File

@@ -34,54 +34,6 @@ parts:
mkdir -p $(dirname ${kata_dir})
ln -sf $(realpath "${SNAPCRAFT_STAGE}/..") ${kata_dir}
godeps:
after: [metadata]
plugin: nil
prime:
- -*
build-packages:
- curl
override-build: |
source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"
# put everything in stage
cd "${SNAPCRAFT_STAGE}"
version="$(${yq} r ${kata_dir}/versions.yaml languages.golang.meta.newest-version)"
tarfile="go${version}.${goos}-${goarch}.tar.gz"
curl -LO https://golang.org/dl/${tarfile}
tar -xf ${tarfile} --strip-components=1
rustdeps:
after: [metadata]
plugin: nil
prime:
- -*
build-packages:
- curl
override-build: |
source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"
# put everything in stage
cd "${SNAPCRAFT_STAGE}"
version="$(${yq} r ${kata_dir}/versions.yaml languages.rust.meta.newest-version)"
if ! command -v rustup > /dev/null; then
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain ${version}
fi
export PATH=${PATH}:${HOME}/.cargo/bin
rustup toolchain install ${version}
rustup default ${version}
if [ "${arch}" == "ppc64le" ] || [ "${arch}" == "s390x" ] ; then
[ "${arch}" == "ppc64le" ] && arch="powerpc64le"
rustup target add ${arch}-unknown-linux-gnu
else
rustup target add ${arch}-unknown-linux-musl
$([ "$(whoami)" != "root" ] && echo sudo) ln -sf /usr/bin/g++ /bin/musl-g++
fi
rustup component add rustfmt
docker:
after: [metadata]
plugin: nil
@@ -111,240 +63,92 @@ parts:
echo "Adding $USER into docker group"
sudo -E gpasswd -a $USER docker
echo "Starting docker"
# docker may fail to start using "fd://" in docker.service
sudo sed -i 's/fd:\/\//unix:\/\//g' /lib/systemd/system/docker.service
sudo systemctl daemon-reload
sudo -E systemctl start docker || true
image:
after: [godeps, docker, qemu, kernel]
after: [docker]
plugin: nil
build-packages:
- docker.io
- cpio
- git
- iptables
- software-properties-common
- uidmap
- gnupg2
override-build: |
source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"
[ "${arch}" = "ppc64le" ] || [ "${arch}" = "s390x" ] && sudo apt-get --no-install-recommends install -y protobuf-compiler
cd "${SNAPCRAFT_PROJECT_DIR}"
sudo -E NO_TTY=true make rootfs-image-tarball
if [ -n "$http_proxy" ]; then
echo "Setting proxy $http_proxy"
sudo -E systemctl set-environment http_proxy="$http_proxy" || true
sudo -E systemctl set-environment https_proxy="$https_proxy" || true
fi
tarfile="${SNAPCRAFT_PROJECT_DIR}/tools/packaging/kata-deploy/local-build/build/kata-static-rootfs-image.tar.xz"
# Copy yq binary. It's used in the container
cp -a "${yq}" "${GOPATH}/bin/"
tar -xvJpf "${tarfile}" -C "${SNAPCRAFT_PART_INSTALL}"
cd "${kata_dir}/tools/osbuilder"
# build image
export AGENT_INIT=yes
export USE_DOCKER=1
export DEBUG=1
initrd_distro=$(${yq} r -X ${kata_dir}/versions.yaml assets.initrd.architecture.${arch}.name)
image_distro=$(${yq} r -X ${kata_dir}/versions.yaml assets.image.architecture.${arch}.name)
case "$arch" in
x86_64)
# In some build systems it's impossible to build a rootfs image, try with the initrd image
sudo -E PATH=$PATH make image DISTRO="${image_distro}" || sudo -E PATH="$PATH" make initrd DISTRO="${initrd_distro}"
;;
sudo -E NO_TTY=true make rootfs-initrd-tarball
aarch64|ppc64le|s390x)
sudo -E PATH="$PATH" make initrd DISTRO="${initrd_distro}"
;;
tarfile="${SNAPCRAFT_PROJECT_DIR}/tools/packaging/kata-deploy/local-build/build/kata-static-rootfs-initrd.tar.xz"
*) die "unsupported architecture: ${arch}" ;;
esac
tar -xvJpf "${tarfile}" -C "${SNAPCRAFT_PART_INSTALL}"
# Install image
kata_image_dir="${SNAPCRAFT_PART_INSTALL}/usr/share/kata-containers"
mkdir -p "${kata_image_dir}"
cp kata-containers*.img "${kata_image_dir}"
runtime:
after: [godeps, image, cloud-hypervisor]
after: [docker]
plugin: nil
build-attributes: [no-patchelf]
override-build: |
source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"
cd "${kata_dir}/src/runtime"
cd "${SNAPCRAFT_PROJECT_DIR}"
sudo -E NO_TTY=true make shim-v2-tarball
qemu_cmd="qemu-system-${qemu_arch}"
tarfile="${SNAPCRAFT_PROJECT_DIR}/tools/packaging/kata-deploy/local-build/build/kata-static-shim-v2.tar.xz"
# build and install runtime
make \
PREFIX="/snap/${SNAPCRAFT_PROJECT_NAME}/current/usr" \
SKIP_GO_VERSION_CHECK=1 \
QEMUCMD="${qemu_cmd}"
tar -xvJpf "${tarfile}" -C "${SNAPCRAFT_PART_INSTALL}"
make install \
PREFIX=/usr \
DESTDIR="${SNAPCRAFT_PART_INSTALL}" \
SKIP_GO_VERSION_CHECK=1 \
QEMUCMD="${qemu_cmd}"
if [ ! -f ${SNAPCRAFT_PART_INSTALL}/../../image/install/usr/share/kata-containers/kata-containers.img ]; then
sed -i -e "s|^image =.*|initrd = \"/snap/${SNAPCRAFT_PROJECT_NAME}/current/usr/share/kata-containers/kata-containers-initrd.img\"|" \
${SNAPCRAFT_PART_INSTALL}/usr/share/defaults/${SNAPCRAFT_PROJECT_NAME}/configuration.toml
fi
mkdir -p "${SNAPCRAFT_PART_INSTALL}/usr/bin"
ln -sf "${SNAPCRAFT_PART_INSTALL}/opt/kata/bin/containerd-shim-kata-v2" "${SNAPCRAFT_PART_INSTALL}/usr/bin/containerd-shim-kata-v2"
ln -sf "${SNAPCRAFT_PART_INSTALL}/opt/kata/bin/kata-runtime" "${SNAPCRAFT_PART_INSTALL}/usr/bin/kata-runtime"
ln -sf "${SNAPCRAFT_PART_INSTALL}/opt/kata/bin/kata-collect-data.sh" "${SNAPCRAFT_PART_INSTALL}/usr/bin/kata-collect-data.sh"
kernel:
after: [godeps]
after: [docker]
plugin: nil
build-packages:
- libelf-dev
- curl
- build-essential
- bison
- flex
override-build: |
source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"
kernel_version="$(${yq} r $versions_file assets.kernel.version)"
#Remove extra 'v'
kernel_version="${kernel_version#v}"
cd "${SNAPCRAFT_PROJECT_DIR}"
sudo -E NO_TTY=true make kernel-tarball
[ "${arch}" = "s390x" ] && sudo apt-get --no-install-recommends install -y libssl-dev
tarfile="${SNAPCRAFT_PROJECT_DIR}/tools/packaging/kata-deploy/local-build/build/kata-static-kernel.tar.xz"
cd "${kata_dir}/tools/packaging/kernel"
kernel_dir_prefix="kata-linux-"
# Setup and build kernel
./build-kernel.sh -v "${kernel_version}" -d setup
cd ${kernel_dir_prefix}*
make -j $(nproc ${CI:+--ignore 1}) EXTRAVERSION=".container"
kernel_suffix="${kernel_version}.container"
kata_kernel_dir="${SNAPCRAFT_PART_INSTALL}/usr/share/kata-containers"
mkdir -p "${kata_kernel_dir}"
# Install bz kernel
make install INSTALL_PATH="${kata_kernel_dir}" EXTRAVERSION=".container" || true
vmlinuz_name="vmlinuz-${kernel_suffix}"
ln -sf "${vmlinuz_name}" "${kata_kernel_dir}/vmlinuz.container"
# Install raw kernel
vmlinux_path="vmlinux"
[ "${arch}" = "s390x" ] && vmlinux_path="arch/s390/boot/vmlinux"
vmlinux_name="vmlinux-${kernel_suffix}"
cp "${vmlinux_path}" "${kata_kernel_dir}/${vmlinux_name}"
ln -sf "${vmlinux_name}" "${kata_kernel_dir}/vmlinux.container"
tar -xvJpf "${tarfile}" -C "${SNAPCRAFT_PART_INSTALL}"
qemu:
plugin: make
after: [godeps]
build-packages:
- gcc
- python3
- zlib1g-dev
- libcap-ng-dev
- libglib2.0-dev
- libpixman-1-dev
- libnuma-dev
- libltdl-dev
- libcap-dev
- libattr1-dev
- libfdt-dev
- curl
- libcapstone-dev
- bc
- libblkid-dev
- libffi-dev
- libmount-dev
- libseccomp-dev
- libselinux1-dev
- ninja-build
after: [docker]
override-build: |
source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"
branch="$(${yq} r ${versions_file} assets.hypervisor.qemu.version)"
url="$(${yq} r ${versions_file} assets.hypervisor.qemu.url)"
commit=""
patches_dir="${kata_dir}/tools/packaging/qemu/patches/$(echo ${branch} | sed -e 's/.[[:digit:]]*$//' -e 's/^v//').x"
patches_version_dir="${kata_dir}/tools/packaging/qemu/patches/tag_patches/${branch}"
cd "${SNAPCRAFT_PROJECT_DIR}"
sudo -E NO_TTY=true make qemu-tarball
# download source
qemu_dir="${SNAPCRAFT_STAGE}/qemu"
rm -rf "${qemu_dir}"
git clone --depth 1 --branch ${branch} --single-branch ${url} "${qemu_dir}"
cd "${qemu_dir}"
[ -z "${commit}" ] || git checkout "${commit}"
tarfile="${SNAPCRAFT_PROJECT_DIR}/tools/packaging/kata-deploy/local-build/build/kata-static-qemu.tar.xz"
[ -n "$(ls -A ui/keycodemapdb)" ] || git clone --depth 1 https://github.com/qemu/keycodemapdb ui/keycodemapdb/
[ -n "$(ls -A capstone)" ] || git clone --depth 1 https://github.com/qemu/capstone capstone
# Apply branch patches
[ -d "${patches_version_dir}" ] || mkdir "${patches_version_dir}"
${kata_dir}/tools/packaging/scripts/apply_patches.sh "${patches_dir}"
${kata_dir}/tools/packaging/scripts/apply_patches.sh "${patches_version_dir}"
# Only x86_64 supports libpmem
[ "${arch}" = "x86_64" ] && sudo apt-get --no-install-recommends install -y apt-utils ca-certificates libpmem-dev
configure_hypervisor="${kata_dir}/tools/packaging/scripts/configure-hypervisor.sh"
chmod +x "${configure_hypervisor}"
# static build. The --prefix, --libdir, --libexecdir, --datadir arguments are
# based on PREFIX and set by configure-hypervisor.sh
echo "$(PREFIX=/snap/${SNAPCRAFT_PROJECT_NAME}/current/usr ${configure_hypervisor} -s kata-qemu) \
--disable-rbd " \
| xargs ./configure
# Copy QEMU configurations (Kconfigs)
case "${branch}" in
"v5.1.0")
cp -a "${kata_dir}"/tools/packaging/qemu/default-configs/* default-configs
;;
*)
cp -a "${kata_dir}"/tools/packaging/qemu/default-configs/* configs/devices/
;;
esac
# build and install
make -j $(nproc ${CI:+--ignore 1})
make install DESTDIR="${SNAPCRAFT_PART_INSTALL}"
prime:
- -snap/
- -usr/bin/qemu-ga
- -usr/bin/qemu-pr-helper
- -usr/bin/virtfs-proxy-helper
- -usr/include/
- -usr/share/applications/
- -usr/share/icons/
- -usr/var/
- usr/*
- lib/*
organize:
# Hack: move qemu to /
"snap/kata-containers/current/": "./"
tar -xvJpf "${tarfile}" -C "${SNAPCRAFT_PART_INSTALL}"
virtiofsd:
plugin: nil
after: [godeps, rustdeps, docker]
after: [docker]
override-build: |
source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"
echo "INFO: Building rust version of virtiofsd"
cd "${SNAPCRAFT_PROJECT_DIR}"
# Clean-up build dir in case it already exists
sudo -E NO_TTY=true make virtiofsd-tarball
sudo install \
--owner='root' \
--group='root' \
--mode=0755 \
-D \
--target-directory="${SNAPCRAFT_PART_INSTALL}/usr/libexec/" \
build/virtiofsd/builddir/virtiofsd/virtiofsd
tarfile="${SNAPCRAFT_PROJECT_DIR}/tools/packaging/kata-deploy/local-build/build/kata-static-virtiofsd.tar.xz"
tar -xvJpf "${tarfile}" -C "${SNAPCRAFT_PART_INSTALL}"
cloud-hypervisor:
plugin: nil
after: [godeps, docker]
after: [docker]
override-build: |
source "${SNAPCRAFT_PROJECT_DIR}/snap/local/snap-common.sh"
@@ -353,13 +157,8 @@ parts:
sudo -E NO_TTY=true make cloud-hypervisor-tarball
tarfile="${SNAPCRAFT_PROJECT_DIR}/tools/packaging/kata-deploy/local-build/build/kata-static-cloud-hypervisor.tar.xz"
tmpdir=$(mktemp -d)
tar -xvJpf "${tarfile}" -C "${tmpdir}"
install -D "${tmpdir}/opt/kata/bin/cloud-hypervisor" "${SNAPCRAFT_PART_INSTALL}/usr/bin/cloud-hypervisor"
rm -rf "${tmpdir}"
tar -xvJpf "${tarfile}" -C "${SNAPCRAFT_PART_INSTALL}"
fi
apps:

1539
src/agent/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,8 +10,8 @@ oci = { path = "../libs/oci" }
rustjail = { path = "rustjail" }
protocols = { path = "../libs/protocols", features = ["async"] }
lazy_static = "1.3.0"
ttrpc = { version = "0.6.0", features = ["async"], default-features = false }
protobuf = "2.27.0"
ttrpc = { version = "0.7.1", features = ["async"], default-features = false }
protobuf = "3.2.0"
libc = "0.2.58"
nix = "0.24.2"
capctl = "0.2.0"

View File

@@ -18,7 +18,7 @@ scopeguard = "1.0.0"
capctl = "0.2.0"
lazy_static = "1.3.0"
libc = "0.2.58"
protobuf = "2.27.0"
protobuf = "3.2.0"
slog = "2.5.2"
slog-scope = "4.1.2"
scan_fmt = "0.2.6"

View File

@@ -27,7 +27,7 @@ use oci::{
LinuxNetwork, LinuxPids, LinuxResources,
};
use protobuf::{CachedSize, RepeatedField, SingularPtrField, UnknownFields};
use protobuf::MessageField;
use protocols::agent::{
BlkioStats, BlkioStatsEntry, CgroupStats, CpuStats, CpuUsage, HugetlbStats, MemoryData,
MemoryStats, PidsStats, ThrottlingData,
@@ -50,7 +50,7 @@ macro_rules! get_controller_or_return_singular_none {
($cg:ident) => {
match $cg.controller_of() {
Some(c) => c,
None => return SingularPtrField::none(),
None => return MessageField::none(),
}
};
}
@@ -134,11 +134,10 @@ impl CgroupManager for Manager {
let throttling_data = get_cpu_stats(&self.cgroup);
let cpu_stats = SingularPtrField::some(CpuStats {
let cpu_stats = MessageField::some(CpuStats {
cpu_usage,
throttling_data,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
..Default::default()
});
// Memorystats
@@ -160,8 +159,7 @@ impl CgroupManager for Manager {
pids_stats,
blkio_stats,
hugetlb_stats,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
..Default::default()
})
}
@@ -446,14 +444,14 @@ fn set_memory_resources(cg: &cgroups::Cgroup, memory: &LinuxMemory, update: bool
let memstat = get_memory_stats(cg)
.into_option()
.ok_or_else(|| anyhow!("failed to get the cgroup memory stats"))?;
let memusage = memstat.get_usage();
let memusage = memstat.usage();
// When update memory limit, the kernel would check the current memory limit
// set against the new swap setting, if the current memory limit is large than
// the new swap, then set limit first, otherwise the kernel would complain and
// refused to set; on the other hand, if the current memory limit is smaller than
// the new swap, then we should set the swap first and then set the memor limit.
if swap == -1 || memusage.get_limit() < swap as u64 {
if swap == -1 || memusage.limit() < swap as u64 {
mem_controller.set_memswap_limit(swap)?;
set_resource!(mem_controller, set_limit, memory, limit);
} else {
@@ -660,21 +658,20 @@ lazy_static! {
};
}
fn get_cpu_stats(cg: &cgroups::Cgroup) -> SingularPtrField<ThrottlingData> {
fn get_cpu_stats(cg: &cgroups::Cgroup) -> MessageField<ThrottlingData> {
let cpu_controller: &CpuController = get_controller_or_return_singular_none!(cg);
let stat = cpu_controller.cpu().stat;
let h = lines_to_map(&stat);
SingularPtrField::some(ThrottlingData {
MessageField::some(ThrottlingData {
periods: *h.get("nr_periods").unwrap_or(&0),
throttled_periods: *h.get("nr_throttled").unwrap_or(&0),
throttled_time: *h.get("throttled_time").unwrap_or(&0),
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
..Default::default()
})
}
fn get_cpuacct_stats(cg: &cgroups::Cgroup) -> SingularPtrField<CpuUsage> {
fn get_cpuacct_stats(cg: &cgroups::Cgroup) -> MessageField<CpuUsage> {
if let Some(cpuacct_controller) = cg.controller_of::<CpuAcctController>() {
let cpuacct = cpuacct_controller.cpuacct();
@@ -688,13 +685,12 @@ fn get_cpuacct_stats(cg: &cgroups::Cgroup) -> SingularPtrField<CpuUsage> {
let percpu_usage = line_to_vec(&cpuacct.usage_percpu);
return SingularPtrField::some(CpuUsage {
return MessageField::some(CpuUsage {
total_usage,
percpu_usage,
usage_in_kernelmode,
usage_in_usermode,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
..Default::default()
});
}
@@ -707,17 +703,16 @@ fn get_cpuacct_stats(cg: &cgroups::Cgroup) -> SingularPtrField<CpuUsage> {
let total_usage = *h.get("usage_usec").unwrap_or(&0);
let percpu_usage = vec![];
SingularPtrField::some(CpuUsage {
MessageField::some(CpuUsage {
total_usage,
percpu_usage,
usage_in_kernelmode,
usage_in_usermode,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
..Default::default()
})
}
fn get_memory_stats(cg: &cgroups::Cgroup) -> SingularPtrField<MemoryStats> {
fn get_memory_stats(cg: &cgroups::Cgroup) -> MessageField<MemoryStats> {
let memory_controller: &MemController = get_controller_or_return_singular_none!(cg);
// cache from memory stat
@@ -729,52 +724,48 @@ fn get_memory_stats(cg: &cgroups::Cgroup) -> SingularPtrField<MemoryStats> {
let use_hierarchy = value == 1;
// get memory data
let usage = SingularPtrField::some(MemoryData {
let usage = MessageField::some(MemoryData {
usage: memory.usage_in_bytes,
max_usage: memory.max_usage_in_bytes,
failcnt: memory.fail_cnt,
limit: memory.limit_in_bytes as u64,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
..Default::default()
});
// get swap usage
let memswap = memory_controller.memswap();
let swap_usage = SingularPtrField::some(MemoryData {
let swap_usage = MessageField::some(MemoryData {
usage: memswap.usage_in_bytes,
max_usage: memswap.max_usage_in_bytes,
failcnt: memswap.fail_cnt,
limit: memswap.limit_in_bytes as u64,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
..Default::default()
});
// get kernel usage
let kmem_stat = memory_controller.kmem_stat();
let kernel_usage = SingularPtrField::some(MemoryData {
let kernel_usage = MessageField::some(MemoryData {
usage: kmem_stat.usage_in_bytes,
max_usage: kmem_stat.max_usage_in_bytes,
failcnt: kmem_stat.fail_cnt,
limit: kmem_stat.limit_in_bytes as u64,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
..Default::default()
});
SingularPtrField::some(MemoryStats {
MessageField::some(MemoryStats {
cache,
usage,
swap_usage,
kernel_usage,
use_hierarchy,
stats: memory.stat.raw,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
..Default::default()
})
}
fn get_pids_stats(cg: &cgroups::Cgroup) -> SingularPtrField<PidsStats> {
fn get_pids_stats(cg: &cgroups::Cgroup) -> MessageField<PidsStats> {
let pid_controller: &PidController = get_controller_or_return_singular_none!(cg);
let current = pid_controller.get_pid_current().unwrap_or(0);
@@ -788,11 +779,10 @@ fn get_pids_stats(cg: &cgroups::Cgroup) -> SingularPtrField<PidsStats> {
},
} as u64;
SingularPtrField::some(PidsStats {
MessageField::some(PidsStats {
current,
limit,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
..Default::default()
})
}
@@ -828,8 +818,8 @@ https://github.com/opencontainers/runc/blob/a5847db387ae28c0ca4ebe4beee1a76900c8
Total 0
*/
fn get_blkio_stat_blkiodata(blkiodata: &[BlkIoData]) -> RepeatedField<BlkioStatsEntry> {
let mut m = RepeatedField::new();
fn get_blkio_stat_blkiodata(blkiodata: &[BlkIoData]) -> Vec<BlkioStatsEntry> {
let mut m = Vec::new();
if blkiodata.is_empty() {
return m;
}
@@ -842,16 +832,15 @@ fn get_blkio_stat_blkiodata(blkiodata: &[BlkIoData]) -> RepeatedField<BlkioStats
minor: d.minor as u64,
op: op.clone(),
value: d.data,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
..Default::default()
});
}
m
}
fn get_blkio_stat_ioservice(services: &[IoService]) -> RepeatedField<BlkioStatsEntry> {
let mut m = RepeatedField::new();
fn get_blkio_stat_ioservice(services: &[IoService]) -> Vec<BlkioStatsEntry> {
let mut m = Vec::new();
if services.is_empty() {
return m;
@@ -875,17 +864,16 @@ fn build_blkio_stats_entry(major: i16, minor: i16, op: &str, value: u64) -> Blki
minor: minor as u64,
op: op.to_string(),
value,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
..Default::default()
}
}
fn get_blkio_stats_v2(cg: &cgroups::Cgroup) -> SingularPtrField<BlkioStats> {
fn get_blkio_stats_v2(cg: &cgroups::Cgroup) -> MessageField<BlkioStats> {
let blkio_controller: &BlkIoController = get_controller_or_return_singular_none!(cg);
let blkio = blkio_controller.blkio();
let mut resp = BlkioStats::new();
let mut blkio_stats = RepeatedField::new();
let mut blkio_stats = Vec::new();
let stat = blkio.io_stat;
for s in stat {
@@ -901,10 +889,10 @@ fn get_blkio_stats_v2(cg: &cgroups::Cgroup) -> SingularPtrField<BlkioStats> {
resp.io_service_bytes_recursive = blkio_stats;
SingularPtrField::some(resp)
MessageField::some(resp)
}
fn get_blkio_stats(cg: &cgroups::Cgroup) -> SingularPtrField<BlkioStats> {
fn get_blkio_stats(cg: &cgroups::Cgroup) -> MessageField<BlkioStats> {
if cg.v2() {
return get_blkio_stats_v2(cg);
}
@@ -937,7 +925,7 @@ fn get_blkio_stats(cg: &cgroups::Cgroup) -> SingularPtrField<BlkioStats> {
m.sectors_recursive = get_blkio_stat_blkiodata(&blkio.sectors_recursive);
}
SingularPtrField::some(m)
MessageField::some(m)
}
fn get_hugetlb_stats(cg: &cgroups::Cgroup) -> HashMap<String, HugetlbStats> {
@@ -961,8 +949,7 @@ fn get_hugetlb_stats(cg: &cgroups::Cgroup) -> HashMap<String, HugetlbStats> {
usage,
max_usage,
failcnt,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
..Default::default()
},
);
}

View File

@@ -3,7 +3,7 @@
// SPDX-License-Identifier: Apache-2.0
//
use protobuf::{CachedSize, SingularPtrField, UnknownFields};
use protobuf::MessageField;
use crate::cgroups::Manager as CgroupManager;
use crate::protocols::agent::{BlkioStats, CgroupStats, CpuStats, MemoryStats, PidsStats};
@@ -33,13 +33,12 @@ impl CgroupManager for Manager {
fn get_stats(&self) -> Result<CgroupStats> {
Ok(CgroupStats {
cpu_stats: SingularPtrField::some(CpuStats::default()),
memory_stats: SingularPtrField::some(MemoryStats::new()),
pids_stats: SingularPtrField::some(PidsStats::new()),
blkio_stats: SingularPtrField::some(BlkioStats::new()),
cpu_stats: MessageField::some(CpuStats::default()),
memory_stats: MessageField::some(MemoryStats::new()),
pids_stats: MessageField::some(PidsStats::new()),
blkio_stats: MessageField::some(BlkioStats::new()),
hugetlb_stats: HashMap::new(),
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
..Default::default()
})
}

View File

@@ -26,7 +26,7 @@ pub trait SystemdInterface {
fn get_version(&self) -> Result<String>;
fn unit_exist(&self, unit_name: &str) -> Result<bool>;
fn unit_exists(&self, unit_name: &str) -> Result<bool>;
fn add_process(&self, pid: i32, unit_name: &str) -> Result<()>;
}
@@ -36,8 +36,9 @@ pub struct DBusClient {}
impl DBusClient {
fn build_proxy(&self) -> Result<SystemManager<'static>> {
let connection = zbus::blocking::Connection::system()?;
let proxy = SystemManager::new(&connection)?;
let connection =
zbus::blocking::Connection::system().context("Establishing a D-Bus connection")?;
let proxy = SystemManager::new(&connection).context("Building a D-Bus proxy manager")?;
Ok(proxy)
}
}
@@ -108,8 +109,10 @@ impl SystemdInterface for DBusClient {
Ok(systemd_version)
}
fn unit_exist(&self, unit_name: &str) -> Result<bool> {
let proxy = self.build_proxy()?;
fn unit_exists(&self, unit_name: &str) -> Result<bool> {
let proxy = self
.build_proxy()
.with_context(|| format!("Checking if systemd unit {} exists", unit_name))?;
Ok(proxy.get_unit(unit_name).is_ok())
}

View File

@@ -41,7 +41,7 @@ pub struct Manager {
impl CgroupManager for Manager {
fn apply(&self, pid: pid_t) -> Result<()> {
let unit_name = self.unit_name.as_str();
if self.dbus_client.unit_exist(unit_name).unwrap() {
if self.dbus_client.unit_exists(unit_name)? {
self.dbus_client.add_process(pid, self.unit_name.as_str())?;
} else {
self.dbus_client.start_unit(

View File

@@ -48,7 +48,7 @@ use nix::unistd::{self, fork, ForkResult, Gid, Pid, Uid, User};
use std::os::unix::fs::MetadataExt;
use std::os::unix::io::AsRawFd;
use protobuf::SingularPtrField;
use protobuf::MessageField;
use oci::State as OCIState;
use regex::Regex;
@@ -875,7 +875,7 @@ impl BaseContainer for LinuxContainer {
// what about network interface stats?
Ok(StatsContainerResponse {
cgroup_stats: SingularPtrField::some(self.cgroup_manager.as_ref().get_stats()?),
cgroup_stats: MessageField::some(self.cgroup_manager.as_ref().get_stats()?),
..Default::default()
})
}

View File

@@ -82,11 +82,11 @@ pub fn process_grpc_to_oci(p: &grpc::Process) -> oci::Process {
let cap = p.Capabilities.as_ref().unwrap();
Some(oci::LinuxCapabilities {
bounding: cap.Bounding.clone().into_vec(),
effective: cap.Effective.clone().into_vec(),
inheritable: cap.Inheritable.clone().into_vec(),
permitted: cap.Permitted.clone().into_vec(),
ambient: cap.Ambient.clone().into_vec(),
bounding: cap.Bounding.clone(),
effective: cap.Effective.clone(),
inheritable: cap.Inheritable.clone(),
permitted: cap.Permitted.clone(),
ambient: cap.Ambient.clone(),
})
} else {
None
@@ -108,8 +108,8 @@ pub fn process_grpc_to_oci(p: &grpc::Process) -> oci::Process {
terminal: p.Terminal,
console_size,
user,
args: p.Args.clone().into_vec(),
env: p.Env.clone().into_vec(),
args: p.Args.clone(),
env: p.Env.clone(),
cwd: p.Cwd.clone(),
capabilities,
rlimits,
@@ -130,9 +130,9 @@ fn root_grpc_to_oci(root: &grpc::Root) -> oci::Root {
fn mount_grpc_to_oci(m: &grpc::Mount) -> oci::Mount {
oci::Mount {
destination: m.destination.clone(),
r#type: m.field_type.clone(),
r#type: m.type_.clone(),
source: m.source.clone(),
options: m.options.clone().into_vec(),
options: m.options.clone(),
}
}
@@ -143,8 +143,8 @@ fn hook_grpc_to_oci(h: &[grpcHook]) -> Vec<oci::Hook> {
for e in h.iter() {
r.push(oci::Hook {
path: e.Path.clone(),
args: e.Args.clone().into_vec(),
env: e.Env.clone().into_vec(),
args: e.Args.clone(),
env: e.Env.clone(),
timeout: Some(e.Timeout as i32),
});
}
@@ -365,7 +365,7 @@ fn seccomp_grpc_to_oci(sec: &grpc::LinuxSeccomp) -> oci::LinuxSeccomp {
let mut args = Vec::new();
let errno_ret: u32 = if sys.has_errnoret() {
sys.get_errnoret()
sys.errnoret()
} else {
libc::EPERM as u32
};
@@ -380,7 +380,7 @@ fn seccomp_grpc_to_oci(sec: &grpc::LinuxSeccomp) -> oci::LinuxSeccomp {
}
r.push(oci::LinuxSyscall {
names: sys.Names.clone().into_vec(),
names: sys.Names.clone(),
action: sys.Action.clone(),
errno_ret,
args,
@@ -391,8 +391,8 @@ fn seccomp_grpc_to_oci(sec: &grpc::LinuxSeccomp) -> oci::LinuxSeccomp {
oci::LinuxSeccomp {
default_action: sec.DefaultAction.clone(),
architectures: sec.Architectures.clone().into_vec(),
flags: sec.Flags.clone().into_vec(),
architectures: sec.Architectures.clone(),
flags: sec.Flags.clone(),
syscalls,
}
}
@@ -462,8 +462,8 @@ fn linux_grpc_to_oci(l: &grpc::Linux) -> oci::Linux {
devices,
seccomp,
rootfs_propagation: l.RootfsPropagation.clone(),
masked_paths: l.MaskedPaths.clone().into_vec(),
readonly_paths: l.ReadonlyPaths.clone().into_vec(),
masked_paths: l.MaskedPaths.clone(),
readonly_paths: l.ReadonlyPaths.clone(),
mount_label: l.MountLabel.clone(),
intel_rdt,
}
@@ -564,35 +564,30 @@ mod tests {
// All fields specified
grpcproc: grpc::Process {
Terminal: true,
ConsoleSize: protobuf::SingularPtrField::<grpc::Box>::some(grpc::Box {
ConsoleSize: protobuf::MessageField::<grpc::Box>::some(grpc::Box {
Height: 123,
Width: 456,
..Default::default()
}),
User: protobuf::SingularPtrField::<grpc::User>::some(grpc::User {
User: protobuf::MessageField::<grpc::User>::some(grpc::User {
UID: 1234,
GID: 5678,
AdditionalGids: Vec::from([910, 1112]),
Username: String::from("username"),
..Default::default()
}),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg1"),
String::from("arg2"),
])),
Env: protobuf::RepeatedField::from(Vec::from([String::from("env")])),
Args: Vec::from([String::from("arg1"), String::from("arg2")]),
Env: Vec::from([String::from("env")]),
Cwd: String::from("cwd"),
Capabilities: protobuf::SingularPtrField::some(grpc::LinuxCapabilities {
Bounding: protobuf::RepeatedField::from(Vec::from([String::from("bnd")])),
Effective: protobuf::RepeatedField::from(Vec::from([String::from("eff")])),
Inheritable: protobuf::RepeatedField::from(Vec::from([String::from(
"inher",
)])),
Permitted: protobuf::RepeatedField::from(Vec::from([String::from("perm")])),
Ambient: protobuf::RepeatedField::from(Vec::from([String::from("amb")])),
Capabilities: protobuf::MessageField::some(grpc::LinuxCapabilities {
Bounding: Vec::from([String::from("bnd")]),
Effective: Vec::from([String::from("eff")]),
Inheritable: Vec::from([String::from("inher")]),
Permitted: Vec::from([String::from("perm")]),
Ambient: Vec::from([String::from("amb")]),
..Default::default()
}),
Rlimits: protobuf::RepeatedField::from(Vec::from([
Rlimits: Vec::from([
grpc::POSIXRlimit {
Type: String::from("r#type"),
Hard: 123,
@@ -605,7 +600,7 @@ mod tests {
Soft: 1011,
..Default::default()
},
])),
]),
NoNewPrivileges: true,
ApparmorProfile: String::from("apparmor profile"),
OOMScoreAdj: 123456,
@@ -655,7 +650,7 @@ mod tests {
TestData {
// None ConsoleSize
grpcproc: grpc::Process {
ConsoleSize: protobuf::SingularPtrField::<grpc::Box>::none(),
ConsoleSize: protobuf::MessageField::<grpc::Box>::none(),
OOMScoreAdj: 0,
..Default::default()
},
@@ -668,7 +663,7 @@ mod tests {
TestData {
// None User
grpcproc: grpc::Process {
User: protobuf::SingularPtrField::<grpc::User>::none(),
User: protobuf::MessageField::<grpc::User>::none(),
OOMScoreAdj: 0,
..Default::default()
},
@@ -686,7 +681,7 @@ mod tests {
TestData {
// None Capabilities
grpcproc: grpc::Process {
Capabilities: protobuf::SingularPtrField::none(),
Capabilities: protobuf::MessageField::none(),
OOMScoreAdj: 0,
..Default::default()
},
@@ -787,99 +782,57 @@ mod tests {
TestData {
// All specified
grpchooks: grpc::Hooks {
Prestart: protobuf::RepeatedField::from(Vec::from([
Prestart: Vec::from([
grpc::Hook {
Path: String::from("prestartpath"),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg1"),
String::from("arg2"),
])),
Env: protobuf::RepeatedField::from(Vec::from([
String::from("env1"),
String::from("env2"),
])),
Args: Vec::from([String::from("arg1"), String::from("arg2")]),
Env: Vec::from([String::from("env1"), String::from("env2")]),
Timeout: 10,
..Default::default()
},
grpc::Hook {
Path: String::from("prestartpath2"),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg3"),
String::from("arg4"),
])),
Env: protobuf::RepeatedField::from(Vec::from([
String::from("env3"),
String::from("env4"),
])),
Args: Vec::from([String::from("arg3"), String::from("arg4")]),
Env: Vec::from([String::from("env3"), String::from("env4")]),
Timeout: 25,
..Default::default()
},
])),
Poststart: protobuf::RepeatedField::from(Vec::from([grpc::Hook {
]),
Poststart: Vec::from([grpc::Hook {
Path: String::from("poststartpath"),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg1"),
String::from("arg2"),
])),
Env: protobuf::RepeatedField::from(Vec::from([
String::from("env1"),
String::from("env2"),
])),
Args: Vec::from([String::from("arg1"), String::from("arg2")]),
Env: Vec::from([String::from("env1"), String::from("env2")]),
Timeout: 10,
..Default::default()
}])),
Poststop: protobuf::RepeatedField::from(Vec::from([grpc::Hook {
}]),
Poststop: Vec::from([grpc::Hook {
Path: String::from("poststoppath"),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg1"),
String::from("arg2"),
])),
Env: protobuf::RepeatedField::from(Vec::from([
String::from("env1"),
String::from("env2"),
])),
Args: Vec::from([String::from("arg1"), String::from("arg2")]),
Env: Vec::from([String::from("env1"), String::from("env2")]),
Timeout: 10,
..Default::default()
}])),
CreateRuntime: protobuf::RepeatedField::from(Vec::from([grpc::Hook {
}]),
CreateRuntime: Vec::from([grpc::Hook {
Path: String::from("createruntimepath"),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg1"),
String::from("arg2"),
])),
Env: protobuf::RepeatedField::from(Vec::from([
String::from("env1"),
String::from("env2"),
])),
Args: Vec::from([String::from("arg1"), String::from("arg2")]),
Env: Vec::from([String::from("env1"), String::from("env2")]),
Timeout: 10,
..Default::default()
}])),
CreateContainer: protobuf::RepeatedField::from(Vec::from([grpc::Hook {
}]),
CreateContainer: Vec::from([grpc::Hook {
Path: String::from("createcontainerpath"),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg1"),
String::from("arg2"),
])),
Env: protobuf::RepeatedField::from(Vec::from([
String::from("env1"),
String::from("env2"),
])),
Args: Vec::from([String::from("arg1"), String::from("arg2")]),
Env: Vec::from([String::from("env1"), String::from("env2")]),
Timeout: 10,
..Default::default()
}])),
StartContainer: protobuf::RepeatedField::from(Vec::from([grpc::Hook {
}]),
StartContainer: Vec::from([grpc::Hook {
Path: String::from("startcontainerpath"),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg1"),
String::from("arg2"),
])),
Env: protobuf::RepeatedField::from(Vec::from([
String::from("env1"),
String::from("env2"),
])),
Args: Vec::from([String::from("arg1"), String::from("arg2")]),
Env: Vec::from([String::from("env1"), String::from("env2")]),
Timeout: 10,
..Default::default()
}])),
}]),
..Default::default()
},
result: oci::Hooks {
@@ -932,72 +885,42 @@ mod tests {
TestData {
// Prestart empty
grpchooks: grpc::Hooks {
Prestart: protobuf::RepeatedField::from(Vec::from([])),
Poststart: protobuf::RepeatedField::from(Vec::from([grpc::Hook {
Prestart: Vec::from([]),
Poststart: Vec::from([grpc::Hook {
Path: String::from("poststartpath"),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg1"),
String::from("arg2"),
])),
Env: protobuf::RepeatedField::from(Vec::from([
String::from("env1"),
String::from("env2"),
])),
Args: Vec::from([String::from("arg1"), String::from("arg2")]),
Env: Vec::from([String::from("env1"), String::from("env2")]),
Timeout: 10,
..Default::default()
}])),
Poststop: protobuf::RepeatedField::from(Vec::from([grpc::Hook {
}]),
Poststop: Vec::from([grpc::Hook {
Path: String::from("poststoppath"),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg1"),
String::from("arg2"),
])),
Env: protobuf::RepeatedField::from(Vec::from([
String::from("env1"),
String::from("env2"),
])),
Args: Vec::from([String::from("arg1"), String::from("arg2")]),
Env: Vec::from([String::from("env1"), String::from("env2")]),
Timeout: 10,
..Default::default()
}])),
CreateRuntime: protobuf::RepeatedField::from(Vec::from([grpc::Hook {
}]),
CreateRuntime: Vec::from([grpc::Hook {
Path: String::from("createruntimepath"),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg1"),
String::from("arg2"),
])),
Env: protobuf::RepeatedField::from(Vec::from([
String::from("env1"),
String::from("env2"),
])),
Args: Vec::from([String::from("arg1"), String::from("arg2")]),
Env: Vec::from([String::from("env1"), String::from("env2")]),
Timeout: 10,
..Default::default()
}])),
CreateContainer: protobuf::RepeatedField::from(Vec::from([grpc::Hook {
}]),
CreateContainer: Vec::from([grpc::Hook {
Path: String::from("createcontainerpath"),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg1"),
String::from("arg2"),
])),
Env: protobuf::RepeatedField::from(Vec::from([
String::from("env1"),
String::from("env2"),
])),
Args: Vec::from([String::from("arg1"), String::from("arg2")]),
Env: Vec::from([String::from("env1"), String::from("env2")]),
Timeout: 10,
..Default::default()
}])),
StartContainer: protobuf::RepeatedField::from(Vec::from([grpc::Hook {
}]),
StartContainer: Vec::from([grpc::Hook {
Path: String::from("startcontainerpath"),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg1"),
String::from("arg2"),
])),
Env: protobuf::RepeatedField::from(Vec::from([
String::from("env1"),
String::from("env2"),
])),
Args: Vec::from([String::from("arg1"), String::from("arg2")]),
Env: Vec::from([String::from("env1"), String::from("env2")]),
Timeout: 10,
..Default::default()
}])),
}]),
..Default::default()
},
result: oci::Hooks {
@@ -1069,11 +992,8 @@ mod tests {
grpcmount: grpc::Mount {
destination: String::from("destination"),
source: String::from("source"),
field_type: String::from("fieldtype"),
options: protobuf::RepeatedField::from(Vec::from([
String::from("option1"),
String::from("option2"),
])),
type_: String::from("fieldtype"),
options: Vec::from([String::from("option1"), String::from("option2")]),
..Default::default()
},
result: oci::Mount {
@@ -1087,8 +1007,8 @@ mod tests {
grpcmount: grpc::Mount {
destination: String::from("destination"),
source: String::from("source"),
field_type: String::from("fieldtype"),
options: protobuf::RepeatedField::from(Vec::new()),
type_: String::from("fieldtype"),
options: Vec::new(),
..Default::default()
},
result: oci::Mount {
@@ -1102,8 +1022,8 @@ mod tests {
grpcmount: grpc::Mount {
destination: String::new(),
source: String::from("source"),
field_type: String::from("fieldtype"),
options: protobuf::RepeatedField::from(Vec::from([String::from("option1")])),
type_: String::from("fieldtype"),
options: Vec::from([String::from("option1")]),
..Default::default()
},
result: oci::Mount {
@@ -1117,8 +1037,8 @@ mod tests {
grpcmount: grpc::Mount {
destination: String::from("destination"),
source: String::from("source"),
field_type: String::new(),
options: protobuf::RepeatedField::from(Vec::from([String::from("option1")])),
type_: String::new(),
options: Vec::from([String::from("option1")]),
..Default::default()
},
result: oci::Mount {
@@ -1178,27 +1098,15 @@ mod tests {
grpchook: &[
grpc::Hook {
Path: String::from("path"),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg1"),
String::from("arg2"),
])),
Env: protobuf::RepeatedField::from(Vec::from([
String::from("env1"),
String::from("env2"),
])),
Args: Vec::from([String::from("arg1"), String::from("arg2")]),
Env: Vec::from([String::from("env1"), String::from("env2")]),
Timeout: 10,
..Default::default()
},
grpc::Hook {
Path: String::from("path2"),
Args: protobuf::RepeatedField::from(Vec::from([
String::from("arg3"),
String::from("arg4"),
])),
Env: protobuf::RepeatedField::from(Vec::from([
String::from("env3"),
String::from("env4"),
])),
Args: Vec::from([String::from("arg3"), String::from("arg4")]),
Env: Vec::from([String::from("env3"), String::from("env4")]),
Timeout: 20,
..Default::default()
},

View File

@@ -761,7 +761,7 @@ async fn vfio_pci_device_handler(
device: &Device,
sandbox: &Arc<Mutex<Sandbox>>,
) -> Result<SpecUpdate> {
let vfio_in_guest = device.field_type != DRIVER_VFIO_PCI_GK_TYPE;
let vfio_in_guest = device.type_ != DRIVER_VFIO_PCI_GK_TYPE;
let mut pci_fixups = Vec::<(pci::Address, pci::Address)>::new();
let mut group = None;
@@ -876,9 +876,9 @@ pub async fn add_devices(
async fn add_device(device: &Device, sandbox: &Arc<Mutex<Sandbox>>) -> Result<SpecUpdate> {
// log before validation to help with debugging gRPC protocol version differences.
info!(sl!(), "device-id: {}, device-type: {}, device-vm-path: {}, device-container-path: {}, device-options: {:?}",
device.id, device.field_type, device.vm_path, device.container_path, device.options);
device.id, device.type_, device.vm_path, device.container_path, device.options);
if device.field_type.is_empty() {
if device.type_.is_empty() {
return Err(anyhow!("invalid type for device {:?}", device));
}
@@ -890,7 +890,7 @@ async fn add_device(device: &Device, sandbox: &Arc<Mutex<Sandbox>>) -> Result<Sp
return Err(anyhow!("invalid container path for device {:?}", device));
}
match device.field_type.as_str() {
match device.type_.as_str() {
DRIVER_BLK_TYPE => virtio_blk_device_handler(device, sandbox).await,
DRIVER_BLK_CCW_TYPE => virtio_blk_ccw_device_handler(device, sandbox).await,
DRIVER_MMIO_BLK_TYPE => virtiommio_blk_device_handler(device, sandbox).await,
@@ -900,7 +900,7 @@ async fn add_device(device: &Device, sandbox: &Arc<Mutex<Sandbox>>) -> Result<Sp
vfio_pci_device_handler(device, sandbox).await
}
DRIVER_VFIO_AP_TYPE => vfio_ap_device_handler(device, sandbox).await,
_ => Err(anyhow!("Unknown device type {}", device.field_type)),
_ => Err(anyhow!("Unknown device type {}", device.type_)),
}
}

View File

@@ -122,17 +122,17 @@ impl ImageService {
/// If the request specifies a non-empty id, use it; otherwise derive it from the image path.
/// In either case, verify that the chosen id is valid.
fn cid_from_request(&self, req: &image::PullImageRequest) -> Result<String> {
let req_cid = req.get_container_id();
let req_cid = req.container_id();
let cid = if !req_cid.is_empty() {
req_cid.to_string()
} else if let Some(last) = req.get_image().rsplit('/').next() {
} else if let Some(last) = req.image().rsplit('/').next() {
// Support multiple containers with same image
let index = self.container_count.fetch_add(1, Ordering::Relaxed);
// ':' not valid for container id
format!("{}_{}", last.replace(':', "_"), index)
} else {
return Err(anyhow!("Invalid image name. {}", req.get_image()));
return Err(anyhow!("Invalid image name. {}", req.image()));
};
verify_cid(&cid)?;
Ok(cid)
@@ -152,7 +152,7 @@ impl ImageService {
}
let cid = self.cid_from_request(req)?;
let image = req.get_image();
let image = req.image();
if cid.starts_with("pause") {
Self::unpack_pause_image(&cid)?;
@@ -190,7 +190,7 @@ impl ImageService {
);
self.image_client.lock().await.config.security_validate = *enable_signature_verification;
let source_creds = (!req.get_source_creds().is_empty()).then(|| req.get_source_creds());
let source_creds = (!req.source_creds().is_empty()).then(|| req.source_creds());
let bundle_path = Path::new(CONTAINER_BASE).join(&cid);
fs::create_dir_all(&bundle_path)?;

View File

@@ -443,9 +443,8 @@ mod tests {
let msg = format!("test[{}]: {:?}", i, d);
let (rfd, wfd) = unistd::pipe2(OFlag::O_CLOEXEC).unwrap();
defer!({
// rfd is closed by the use of PipeStream in the crate_logger_task function,
// but we will attempt to close in case of a failure
let _ = unistd::close(rfd);
// XXX: Never try to close rfd, because it will be closed by PipeStream in
// create_logger_task() and it's not safe to close the same fd twice time.
unistd::close(wfd).unwrap();
});

View File

@@ -211,10 +211,10 @@ async fn ephemeral_storage_handler(
// By now we only support one option field: "fsGroup" which
// isn't an valid mount option, thus we should remove it when
// do mount.
if storage.options.len() > 0 {
if !storage.options.is_empty() {
// ephemeral_storage didn't support mount options except fsGroup.
let mut new_storage = storage.clone();
new_storage.options = protobuf::RepeatedField::default();
new_storage.options = Default::default();
common_storage_handler(logger, &new_storage)?;
let opts_vec: Vec<String> = storage.options.to_vec();
@@ -654,7 +654,7 @@ pub fn set_ownership(logger: &Logger, storage: &Storage) -> Result<()> {
if storage.fs_group.is_none() {
return Ok(());
}
let fs_group = storage.get_fs_group();
let fs_group = storage.fs_group();
let mut read_only = false;
let opts_vec: Vec<String> = storage.options.to_vec();
@@ -671,7 +671,7 @@ pub fn set_ownership(logger: &Logger, storage: &Storage) -> Result<()> {
err
})?;
if fs_group.group_change_policy == FSGroupChangePolicy::OnRootMismatch
if fs_group.group_change_policy == FSGroupChangePolicy::OnRootMismatch.into()
&& metadata.gid() == fs_group.group_id
{
let mut mask = if read_only { RO_MASK } else { RW_MASK };
@@ -1094,7 +1094,6 @@ fn parse_options(option_list: Vec<String>) -> HashMap<String, String> {
#[cfg(test)]
mod tests {
use super::*;
use protobuf::RepeatedField;
use protocols::agent::FSGroup;
use std::fs::File;
use std::fs::OpenOptions;
@@ -2015,9 +2014,8 @@ mod tests {
mount_path: "rw_mount",
fs_group: Some(FSGroup {
group_id: 3000,
group_change_policy: FSGroupChangePolicy::Always,
unknown_fields: Default::default(),
cached_size: Default::default(),
group_change_policy: FSGroupChangePolicy::Always.into(),
..Default::default()
}),
read_only: false,
expected_group_id: 3000,
@@ -2027,9 +2025,8 @@ mod tests {
mount_path: "ro_mount",
fs_group: Some(FSGroup {
group_id: 3000,
group_change_policy: FSGroupChangePolicy::OnRootMismatch,
unknown_fields: Default::default(),
cached_size: Default::default(),
group_change_policy: FSGroupChangePolicy::OnRootMismatch.into(),
..Default::default()
}),
read_only: true,
expected_group_id: 3000,
@@ -2049,10 +2046,7 @@ mod tests {
let directory_mode = mount_dir.as_path().metadata().unwrap().permissions().mode();
let mut storage_data = Storage::new();
if d.read_only {
storage_data.set_options(RepeatedField::from_slice(&[
"foo".to_string(),
"ro".to_string(),
]));
storage_data.set_options(vec!["foo".to_string(), "ro".to_string()]);
}
if let Some(fs_group) = d.fs_group.clone() {
storage_data.set_fs_group(fs_group);

View File

@@ -7,7 +7,6 @@ use anyhow::{anyhow, Context, Result};
use futures::{future, StreamExt, TryStreamExt};
use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network};
use nix::errno::Errno;
use protobuf::RepeatedField;
use protocols::types::{ARPNeighbor, IPAddress, IPFamily, Interface, Route};
use rtnetlink::{new_connection, packet, IpVersion};
use std::convert::{TryFrom, TryInto};
@@ -83,8 +82,8 @@ impl Handle {
// Add new ip addresses from request
for ip_address in &iface.IPAddresses {
let ip = IpAddr::from_str(ip_address.get_address())?;
let mask = ip_address.get_mask().parse::<u8>()?;
let ip = IpAddr::from_str(ip_address.address())?;
let mask = ip_address.mask().parse::<u8>()?;
self.add_addresses(link.index(), std::iter::once(IpNetwork::new(ip, mask)?))
.await?;
@@ -152,7 +151,7 @@ impl Handle {
.map(|p| p.try_into())
.collect::<Result<Vec<IPAddress>>>()?;
iface.IPAddresses = RepeatedField::from_vec(ips);
iface.IPAddresses = ips;
list.push(iface);
}
@@ -334,7 +333,7 @@ impl Handle {
// `rtnetlink` offers a separate request builders for different IP versions (IP v4 and v6).
// This if branch is a bit clumsy because it does almost the same.
if route.get_family() == IPFamily::v6 {
if route.family() == IPFamily::v6 {
let dest_addr = if !route.dest.is_empty() {
Ipv6Network::from_str(&route.dest)?
} else {
@@ -368,9 +367,9 @@ impl Handle {
if Errno::from_i32(message.code.abs()) != Errno::EEXIST {
return Err(anyhow!(
"Failed to add IP v6 route (src: {}, dst: {}, gtw: {},Err: {})",
route.get_source(),
route.get_dest(),
route.get_gateway(),
route.source(),
route.dest(),
route.gateway(),
message
));
}
@@ -409,9 +408,9 @@ impl Handle {
if Errno::from_i32(message.code.abs()) != Errno::EEXIST {
return Err(anyhow!(
"Failed to add IP v4 route (src: {}, dst: {}, gtw: {},Err: {})",
route.get_source(),
route.get_dest(),
route.get_gateway(),
route.source(),
route.dest(),
route.gateway(),
message
));
}
@@ -506,7 +505,7 @@ impl Handle {
self.add_arp_neighbor(&neigh).await.map_err(|err| {
anyhow!(
"Failed to add ARP neighbor {}: {:?}",
neigh.get_toIPAddress().get_address(),
neigh.toIPAddress().address(),
err
)
})?;
@@ -725,7 +724,7 @@ impl TryFrom<Address> for IPAddress {
let mask = format!("{}", value.0.header.prefix_len);
Ok(IPAddress {
family,
family: family.into(),
address,
mask,
..Default::default()

View File

@@ -21,17 +21,20 @@ use ttrpc::{
use anyhow::{anyhow, Context, Result};
use cgroups::freezer::FreezerState;
use oci::{LinuxNamespace, Root, Spec};
use protobuf::{Message, RepeatedField, SingularPtrField};
use protobuf::{MessageDyn, MessageField};
use protocols::agent::{
AddSwapRequest, AgentDetails, CopyFileRequest, GetIPTablesRequest, GetIPTablesResponse,
GuestDetailsResponse, Interfaces, Metrics, OOMEvent, ReadStreamResponse, Routes,
SetIPTablesRequest, SetIPTablesResponse, StatsContainerResponse, VolumeStatsRequest,
WaitProcessResponse, WriteStreamResponse,
};
use protocols::csi::{VolumeCondition, VolumeStatsResponse, VolumeUsage, VolumeUsage_Unit};
use protocols::csi::{
volume_usage::Unit as VolumeUsage_Unit, VolumeCondition, VolumeStatsResponse, VolumeUsage,
};
use protocols::empty::Empty;
use protocols::health::{
HealthCheckResponse, HealthCheckResponse_ServingStatus, VersionCheckResponse,
health_check_response::ServingStatus as HealthCheckResponse_ServingStatus, HealthCheckResponse,
VersionCheckResponse,
};
use protocols::types::Interface;
use protocols::{
@@ -132,11 +135,11 @@ macro_rules! is_allowed {
if !AGENT_CONFIG
.read()
.await
.is_allowed_endpoint($req.descriptor().name())
.is_allowed_endpoint($req.descriptor_dyn().name())
{
return Err(ttrpc_error!(
ttrpc::Code::UNIMPLEMENTED,
format!("{} is blocked", $req.descriptor().name()),
format!("{} is blocked", $req.descriptor_dyn().name()),
));
}
};
@@ -194,7 +197,7 @@ impl AgentService {
kata_sys_util::validate::verify_id(&cid)?;
let mut oci_spec = req.OCI.clone();
let use_sandbox_pidns = req.get_sandbox_pidns();
let use_sandbox_pidns = req.sandbox_pidns();
let sandbox;
let mut s;
@@ -903,7 +906,7 @@ impl agent_ttrpc::AgentService for AgentService {
) -> ttrpc::Result<protocols::empty::Empty> {
trace_rpc_call!(ctx, "pause_container", req);
is_allowed!(req);
let cid = req.get_container_id();
let cid = req.container_id();
let s = Arc::clone(&self.sandbox);
let mut sandbox = s.lock().await;
@@ -927,7 +930,7 @@ impl agent_ttrpc::AgentService for AgentService {
) -> ttrpc::Result<protocols::empty::Empty> {
trace_rpc_call!(ctx, "resume_container", req);
is_allowed!(req);
let cid = req.get_container_id();
let cid = req.container_id();
let s = Arc::clone(&self.sandbox);
let mut sandbox = s.lock().await;
@@ -1082,16 +1085,12 @@ impl agent_ttrpc::AgentService for AgentService {
trace_rpc_call!(ctx, "update_routes", req);
is_allowed!(req);
let new_routes = req
.routes
.into_option()
.map(|r| r.Routes.into_vec())
.ok_or_else(|| {
ttrpc_error!(
ttrpc::Code::INVALID_ARGUMENT,
"empty update routes request".to_string(),
)
})?;
let new_routes = req.routes.into_option().map(|r| r.Routes).ok_or_else(|| {
ttrpc_error!(
ttrpc::Code::INVALID_ARGUMENT,
"empty update routes request".to_string(),
)
})?;
let mut sandbox = self.sandbox.lock().await;
@@ -1110,7 +1109,7 @@ impl agent_ttrpc::AgentService for AgentService {
})?;
Ok(protocols::agent::Routes {
Routes: RepeatedField::from_vec(list),
Routes: list,
..Default::default()
})
}
@@ -1309,7 +1308,7 @@ impl agent_ttrpc::AgentService for AgentService {
})?;
Ok(protocols::agent::Interfaces {
Interfaces: RepeatedField::from_vec(list),
Interfaces: list,
..Default::default()
})
}
@@ -1332,7 +1331,7 @@ impl agent_ttrpc::AgentService for AgentService {
.map_err(|e| ttrpc_error!(ttrpc::Code::INTERNAL, format!("list routes: {:?}", e)))?;
Ok(protocols::agent::Routes {
Routes: RepeatedField::from_vec(list),
Routes: list,
..Default::default()
})
}
@@ -1448,7 +1447,7 @@ impl agent_ttrpc::AgentService for AgentService {
let neighs = req
.neighbors
.into_option()
.map(|n| n.ARPNeighbors.into_vec())
.map(|n| n.ARPNeighbors)
.ok_or_else(|| {
ttrpc_error!(
ttrpc::Code::INVALID_ARGUMENT,
@@ -1532,7 +1531,7 @@ impl agent_ttrpc::AgentService for AgentService {
// to get agent details
let detail = get_agent_details();
resp.agent_details = SingularPtrField::some(detail);
resp.agent_details = MessageField::some(detail);
Ok(resp)
}
@@ -1657,8 +1656,8 @@ impl agent_ttrpc::AgentService for AgentService {
.map(|u| usage_vec.push(u))
.map_err(|e| ttrpc_error!(ttrpc::Code::INTERNAL, e))?;
resp.usage = RepeatedField::from_vec(usage_vec);
resp.volume_condition = SingularPtrField::some(condition);
resp.usage = usage_vec;
resp.volume_condition = MessageField::some(condition);
Ok(resp)
}
@@ -1762,7 +1761,7 @@ fn get_volume_capacity_stats(path: &str) -> Result<VolumeUsage> {
usage.total = stat.blocks() * block_size;
usage.available = stat.blocks_free() * block_size;
usage.used = usage.total - usage.available;
usage.unit = VolumeUsage_Unit::BYTES;
usage.unit = VolumeUsage_Unit::BYTES.into();
Ok(usage)
}
@@ -1774,7 +1773,7 @@ fn get_volume_inode_stats(path: &str) -> Result<VolumeUsage> {
usage.total = stat.files();
usage.available = stat.files_free();
usage.used = usage.total - usage.available;
usage.unit = VolumeUsage_Unit::INODES;
usage.unit = VolumeUsage_Unit::INODES.into();
Ok(usage)
}
@@ -1794,14 +1793,12 @@ fn get_agent_details() -> AgentDetails {
detail.set_supports_seccomp(have_seccomp());
detail.init_daemon = unistd::getpid() == Pid::from_raw(1);
detail.device_handlers = RepeatedField::new();
detail.storage_handlers = RepeatedField::from_vec(
STORAGE_HANDLER_LIST
.to_vec()
.iter()
.map(|x| x.to_string())
.collect(),
);
detail.device_handlers = Vec::new();
detail.storage_handlers = STORAGE_HANDLER_LIST
.to_vec()
.iter()
.map(|x| x.to_string())
.collect();
detail
}
@@ -2201,7 +2198,7 @@ fn load_kernel_module(module: &protocols::agent::KernelModule) -> Result<()> {
let mut args = vec!["-v".to_string(), module.name.clone()];
if module.parameters.len() > 0 {
if !module.parameters.is_empty() {
args.extend(module.parameters.to_vec())
}

85
src/libs/Cargo.lock generated
View File

@@ -703,9 +703,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.9.0"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "parking_lot"
@@ -845,9 +845,16 @@ name = "protobuf"
version = "2.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf7e6d18738ecd0902d30d1ad232c9125985a3422929b16c65517b38adc14f96"
[[package]]
name = "protobuf"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b55bad9126f378a853655831eb7363b7b01b81d19f8cb1218861086ca4a1a61e"
dependencies = [
"serde",
"serde_derive",
"once_cell",
"protobuf-support",
"thiserror",
]
[[package]]
@@ -856,17 +863,47 @@ version = "2.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aec1632b7c8f2e620343439a7dfd1f3c47b18906c4be58982079911482b5d707"
dependencies = [
"protobuf",
"protobuf 2.27.1",
]
[[package]]
name = "protobuf-codegen-pure"
version = "2.27.1"
name = "protobuf-codegen"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f8122fdb18e55190c796b088a16bdb70cd7acdcd48f7a8b796b58c62e532cc6"
checksum = "0dd418ac3c91caa4032d37cb80ff0d44e2ebe637b2fb243b6234bf89cdac4901"
dependencies = [
"protobuf",
"protobuf-codegen",
"anyhow",
"once_cell",
"protobuf 3.2.0",
"protobuf-parse",
"regex",
"tempfile",
"thiserror",
]
[[package]]
name = "protobuf-parse"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d39b14605eaa1f6a340aec7f320b34064feb26c93aec35d6a9a2272a8ddfa49"
dependencies = [
"anyhow",
"indexmap",
"log",
"protobuf 3.2.0",
"protobuf-support",
"tempfile",
"thiserror",
"which",
]
[[package]]
name = "protobuf-support"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5d4d7b8601c814cfb36bcebb79f0e61e45e1e93640cf778837833bbed05c372"
dependencies = [
"thiserror",
]
[[package]]
@@ -875,7 +912,7 @@ version = "0.1.0"
dependencies = [
"async-trait",
"oci",
"protobuf",
"protobuf 3.2.0",
"serde",
"serde_json",
"ttrpc",
@@ -1314,9 +1351,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "ttrpc"
version = "0.6.1"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ecfff459a859c6ba6668ff72b34c2f1d94d9d58f7088414c2674ad0f31cc7d8"
checksum = "a35f22a2964bea14afee161665bb260b83cb48e665e0260ca06ec0e775c8b06c"
dependencies = [
"async-trait",
"byteorder",
@@ -1324,8 +1361,8 @@ dependencies = [
"libc",
"log",
"nix 0.23.1",
"protobuf",
"protobuf-codegen-pure",
"protobuf 3.2.0",
"protobuf-codegen 3.2.0",
"thiserror",
"tokio",
"tokio-vsock",
@@ -1333,28 +1370,28 @@ dependencies = [
[[package]]
name = "ttrpc-codegen"
version = "0.2.0"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809eda4e459820237104e4b61d6b41bbe6c9e1ce6adf4057955e6e6722a90408"
checksum = "94d7f7631d7a9ebed715a47cd4cb6072cbc7ae1d4ec01598971bbec0024340c2"
dependencies = [
"protobuf",
"protobuf-codegen",
"protobuf-codegen-pure",
"protobuf 2.27.1",
"protobuf-codegen 3.2.0",
"protobuf-support",
"ttrpc-compiler",
]
[[package]]
name = "ttrpc-compiler"
version = "0.4.1"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2978ed3fa047d8fd55cbeb4d4a61d461fb3021a90c9618519c73ce7e5bb66c15"
checksum = "ec3cb5dbf1f0865a34fe3f722290fe776cacb16f50428610b779467b76ddf647"
dependencies = [
"derive-new",
"prost",
"prost-build",
"prost-types",
"protobuf",
"protobuf-codegen",
"protobuf 2.27.1",
"protobuf-codegen 2.27.1",
"tempfile",
]

View File

@@ -308,6 +308,14 @@ pub const KATA_ANNO_CFG_DISABLE_NEW_NETNS: &str =
/// A sandbox annotation to specify how attached VFIO devices should be treated.
pub const KATA_ANNO_CFG_VFIO_MODE: &str = "io.katacontainers.config.runtime.vfio_mode";
/// A sandbox annotation used to specify prefetch_files.list host path container image
/// being used,
/// and runtime will pass it to Hypervisor to search for corresponding prefetch list file.
/// "io.katacontainers.config.hypervisor.prefetch_files.list"
/// = "/path/to/<uid>/xyz.com/fedora:36/prefetch_file.list"
pub const KATA_ANNO_CFG_HYPERVISOR_PREFETCH_FILES_LIST: &str =
"io.katacontainers.config.hypervisor.prefetch_files.list";
/// A helper structure to query configuration information by check annotations.
#[derive(Debug, Default, Deserialize)]
pub struct Annotation {
@@ -673,6 +681,9 @@ impl Annotation {
hv.machine_info.validate_entropy_source(value)?;
hv.machine_info.entropy_source = value.to_string();
}
KATA_ANNO_CFG_HYPERVISOR_PREFETCH_FILES_LIST => {
hv.prefetch_list_path = value.to_string();
}
// Hypervisor Memory related annotations
KATA_ANNO_CFG_HYPERVISOR_DEFAULT_MEMORY => {
match byte_unit::Byte::from_str(value) {

View File

@@ -979,6 +979,13 @@ pub struct Hypervisor {
#[serde(default, flatten)]
pub shared_fs: SharedFsInfo,
/// A sandbox annotation used to specify prefetch_files.list host path container image
/// being used, and runtime will pass it to Hypervisor to search for corresponding
/// prefetch list file:
/// prefetch_list_path = /path/to/<uid>/xyz.com/fedora:36/prefetch_file.list
#[serde(default)]
pub prefetch_list_path: String,
/// Vendor customized runtime configuration.
#[serde(default, flatten)]
pub vendor: HypervisorVendor,
@@ -1022,6 +1029,10 @@ impl ConfigOps for Hypervisor {
hv.network_info.adjust_config()?;
hv.security_info.adjust_config()?;
hv.shared_fs.adjust_config()?;
resolve_path!(
hv.prefetch_list_path,
"prefetch_list_path `{}` is invalid: {}"
)?;
} else {
return Err(eother!("Can not find plugin for hypervisor {}", hypervisor));
}
@@ -1056,6 +1067,10 @@ impl ConfigOps for Hypervisor {
"Hypervisor control executable `{}` is invalid: {}"
)?;
validate_path!(hv.jailer_path, "Hypervisor jailer path `{}` is invalid: {}")?;
validate_path!(
hv.prefetch_list_path,
"prefetch_files.list path `{}` is invalid: {}"
)?;
} else {
return Err(eother!("Can not find plugin for hypervisor {}", hypervisor));
}

View File

@@ -130,6 +130,12 @@ pub struct Runtime {
/// Vendor customized runtime configuration.
#[serde(default, flatten)]
pub vendor: RuntimeVendor,
/// If keep_abnormal is enabled, it means that 1) if the runtime exits abnormally, the cleanup process
/// will be skipped, and 2) the runtime will not exit even if the health check fails.
/// This option is typically used to retain abnormal information for debugging.
#[serde(default)]
pub keep_abnormal: bool,
}
impl ConfigOps for Runtime {

View File

@@ -192,11 +192,23 @@ pub struct Hook {
pub struct Hooks {
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub prestart: Vec<Hook>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[serde(
rename = "createRuntime",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub create_runtime: Vec<Hook>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[serde(
rename = "createContainer",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub create_container: Vec<Hook>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[serde(
rename = "startContainer",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub start_container: Vec<Hook>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub poststart: Vec<Hook>,
@@ -837,6 +849,8 @@ pub struct State {
#[cfg(test)]
mod tests {
use std::vec;
use super::*;
#[test]
@@ -1027,6 +1041,11 @@ mod tests {
"path": "/usr/bin/setup-network"
}
],
"createRuntime": [
{
"path": "/usr/local/bin/nerdctl"
}
],
"poststart": [
{
"path": "/usr/bin/notify-start",
@@ -1395,6 +1414,12 @@ mod tests {
timeout: None,
},
],
create_runtime: vec![crate::Hook {
path: "/usr/local/bin/nerdctl".to_string(),
args: vec![],
env: vec![],
timeout: None,
}],
poststart: vec![crate::Hook {
path: "/usr/bin/notify-start".to_string(),
args: vec![],

View File

@@ -1,14 +1,6 @@
Cargo.lock
src/agent.rs
src/agent_ttrpc.rs
src/agent_ttrpc_async.rs
src/csi.rs
src/empty.rs
src/health.rs
src/health_ttrpc.rs
src/health_ttrpc_async.rs
src/image.rs
src/image_ttrpc.rs
src/image_ttrpc_async.rs
src/oci.rs
src/types.rs
src/*.rs
!src/lib.rs
!src/trans.rs
!src/serde_config.rs

View File

@@ -11,12 +11,13 @@ with-serde = [ "serde", "serde_json" ]
async = ["ttrpc/async", "async-trait"]
[dependencies]
ttrpc = { version = "0.6.0" }
ttrpc = { version = "0.7.1" }
async-trait = { version = "0.1.42", optional = true }
protobuf = { version = "2.27.0", features = ["with-serde"] }
protobuf = { version = "3.2.0" }
serde = { version = "1.0.130", features = ["derive"], optional = true }
serde_json = { version = "1.0.68", optional = true }
oci = { path = "../oci" }
[build-dependencies]
ttrpc-codegen = "0.2.0"
ttrpc-codegen = "0.4.2"
protobuf = { version = "3.2.0" }

View File

@@ -7,7 +7,46 @@ use std::fs::{self, File};
use std::io::{BufRead, BufReader, Read, Write};
use std::path::Path;
use std::process::exit;
use ttrpc_codegen::{Codegen, Customize, ProtobufCustomize};
use protobuf::{
descriptor::field_descriptor_proto::Type,
reflect::{EnumDescriptor, FieldDescriptor, MessageDescriptor, OneofDescriptor},
};
use ttrpc_codegen::{Codegen, Customize, ProtobufCustomize, ProtobufCustomizeCallback};
struct GenSerde;
impl ProtobufCustomizeCallback for GenSerde {
fn message(&self, _message: &MessageDescriptor) -> ProtobufCustomize {
ProtobufCustomize::default().before("#[cfg_attr(feature = \"with-serde\", derive(::serde::Serialize, ::serde::Deserialize))]")
}
fn enumeration(&self, _enum_type: &EnumDescriptor) -> ProtobufCustomize {
ProtobufCustomize::default().before("#[cfg_attr(feature = \"with-serde\", derive(::serde::Serialize, ::serde::Deserialize))]")
}
fn oneof(&self, _oneof: &OneofDescriptor) -> ProtobufCustomize {
ProtobufCustomize::default().before("#[cfg_attr(feature = \"with-serde\", derive(::serde::Serialize, ::serde::Deserialize))]")
}
fn field(&self, field: &FieldDescriptor) -> ProtobufCustomize {
if field.proto().type_() == Type::TYPE_ENUM {
ProtobufCustomize::default().before(
"#[cfg_attr(feature = \"with-serde\", serde(serialize_with = \"crate::serialize_enum_or_unknown\", deserialize_with = \"crate::deserialize_enum_or_unknown\"))]",
)
} else if field.proto().type_() == Type::TYPE_MESSAGE && field.is_singular() {
ProtobufCustomize::default().before(
"#[cfg_attr(feature = \"with-serde\", serde(serialize_with = \"crate::serialize_message_field\", deserialize_with = \"crate::deserialize_message_field\"))]",
)
} else {
ProtobufCustomize::default()
}
}
fn special_field(&self, _message: &MessageDescriptor, _field: &str) -> ProtobufCustomize {
ProtobufCustomize::default().before("#[cfg_attr(feature = \"with-serde\", serde(skip))]")
}
}
fn replace_text_in_file(file_name: &str, from: &str, to: &str) -> Result<(), std::io::Error> {
let mut src = File::open(file_name)?;
@@ -103,10 +142,10 @@ fn codegen(path: &str, protos: &[&str], async_all: bool) -> Result<(), std::io::
..Default::default()
};
let protobuf_options = ProtobufCustomize {
serde_derive: Some(true),
..Default::default()
};
let protobuf_options = ProtobufCustomize::default()
.gen_mod_rs(false)
.generate_getter(true)
.generate_accessors(true);
let out_dir = Path::new("src");
@@ -117,6 +156,7 @@ fn codegen(path: &str, protos: &[&str], async_all: bool) -> Result<(), std::io::
.customize(ttrpc_options)
.rust_protobuf()
.rust_protobuf_customize(protobuf_options)
.rust_protobuf_customize_callback(GenSerde)
.run()?;
let autogen_comment = format!("\n//! Generated by {:?} ({:?})", file!(), module_path!());
@@ -147,6 +187,7 @@ fn real_main() -> Result<(), std::io::Error> {
"src",
&[
"protos/google/protobuf/empty.proto",
"protos/gogo/protobuf/gogoproto/gogo.proto",
"protos/oci.proto",
"protos/types.proto",
"protos/csi.proto",

View File

@@ -11,6 +11,7 @@ pub mod agent_ttrpc;
pub mod agent_ttrpc_async;
pub mod csi;
pub mod empty;
mod gogo;
pub mod health;
pub mod health_ttrpc;
#[cfg(feature = "async")]
@@ -20,5 +21,13 @@ pub mod image_ttrpc;
#[cfg(feature = "async")]
pub mod image_ttrpc_async;
pub mod oci;
#[cfg(feature = "with-serde")]
mod serde_config;
pub mod trans;
pub mod types;
#[cfg(feature = "with-serde")]
pub use serde_config::{
deserialize_enum_or_unknown, deserialize_message_field, serialize_enum_or_unknown,
serialize_message_field,
};

View File

@@ -0,0 +1,68 @@
// Copyright (c) 2023 Ant Group
//
// SPDX-License-Identifier: Apache-2.0
//
use protobuf::{EnumOrUnknown, MessageField};
use serde::{Deserialize, Serialize};
#[cfg(feature = "with-serde")]
pub fn serialize_enum_or_unknown<E: protobuf::EnumFull, S: serde::Serializer>(
e: &protobuf::EnumOrUnknown<E>,
s: S,
) -> Result<S::Ok, S::Error> {
e.value().serialize(s)
}
pub fn serialize_message_field<E: Serialize, S: serde::Serializer>(
e: &protobuf::MessageField<E>,
s: S,
) -> Result<S::Ok, S::Error> {
if e.is_some() {
e.as_ref().unwrap().serialize(s)
} else {
s.serialize_unit()
}
}
pub fn deserialize_enum_or_unknown<'de, E: Deserialize<'de>, D: serde::Deserializer<'de>>(
d: D,
) -> Result<protobuf::EnumOrUnknown<E>, D::Error> {
i32::deserialize(d).map(EnumOrUnknown::from_i32)
}
pub fn deserialize_message_field<'de, E: Deserialize<'de>, D: serde::Deserializer<'de>>(
d: D,
) -> Result<protobuf::MessageField<E>, D::Error> {
Option::deserialize(d).map(MessageField::from_option)
}
#[cfg(test)]
mod tests {
use crate::agent::{ExecProcessRequest, StringUser};
use crate::health::{health_check_response::ServingStatus, HealthCheckResponse};
#[test]
fn test_serde_for_enum_or_unknown() {
let mut hc = HealthCheckResponse::new();
hc.set_status(ServingStatus::SERVING);
let json = serde_json::to_string(&hc).unwrap();
let from_json: HealthCheckResponse = serde_json::from_str(&json).unwrap();
assert_eq!(from_json, hc);
}
#[test]
fn test_serde_for_message_field() {
let mut epr = ExecProcessRequest::new();
let mut str_user = StringUser::new();
str_user.uid = "Someone's id".to_string();
epr.set_string_user(str_user);
let json = serde_json::to_string(&epr).unwrap();
let from_json: ExecProcessRequest = serde_json::from_str(&json).unwrap();
assert_eq!(from_json, epr);
}
}

View File

@@ -15,19 +15,19 @@ use oci::{
};
// translate from interface to ttprc tools
fn from_option<F: Sized, T: From<F>>(from: Option<F>) -> ::protobuf::SingularPtrField<T> {
fn from_option<F: Sized, T: From<F>>(from: Option<F>) -> protobuf::MessageField<T> {
match from {
Some(f) => ::protobuf::SingularPtrField::from_option(Some(T::from(f))),
None => ::protobuf::SingularPtrField::none(),
Some(f) => protobuf::MessageField::from_option(Some(f.into())),
None => protobuf::MessageField::none(),
}
}
fn from_vec<F: Sized, T: From<F>>(from: Vec<F>) -> ::protobuf::RepeatedField<T> {
fn from_vec<F: Sized, T: From<F>>(from: Vec<F>) -> Vec<T> {
let mut to: Vec<T> = vec![];
for data in from {
to.push(T::from(data));
to.push(data.into());
}
::protobuf::RepeatedField::from_vec(to)
to
}
impl From<oci::Box> for crate::oci::Box {
@@ -35,8 +35,7 @@ impl From<oci::Box> for crate::oci::Box {
crate::oci::Box {
Height: from.height,
Width: from.width,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -48,8 +47,7 @@ impl From<oci::User> for crate::oci::User {
GID: from.gid,
AdditionalGids: from.additional_gids,
Username: from.username,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -57,13 +55,12 @@ impl From<oci::User> for crate::oci::User {
impl From<oci::LinuxCapabilities> for crate::oci::LinuxCapabilities {
fn from(from: LinuxCapabilities) -> Self {
crate::oci::LinuxCapabilities {
Bounding: from_vec(from.bounding),
Effective: from_vec(from.effective),
Inheritable: from_vec(from.inheritable),
Permitted: from_vec(from.permitted),
Ambient: from_vec(from.ambient),
unknown_fields: Default::default(),
cached_size: Default::default(),
Bounding: from.bounding,
Effective: from.effective,
Inheritable: from.inheritable,
Permitted: from.permitted,
Ambient: from.ambient,
..Default::default()
}
}
}
@@ -74,8 +71,7 @@ impl From<oci::PosixRlimit> for crate::oci::POSIXRlimit {
Type: from.r#type,
Hard: from.hard,
Soft: from.soft,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -86,8 +82,8 @@ impl From<oci::Process> for crate::oci::Process {
Terminal: from.terminal,
ConsoleSize: from_option(from.console_size),
User: from_option(Some(from.user)),
Args: from_vec(from.args),
Env: from_vec(from.env),
Args: from.args,
Env: from.env,
Cwd: from.cwd,
Capabilities: from_option(from.capabilities),
Rlimits: from_vec(from.rlimits),
@@ -95,8 +91,7 @@ impl From<oci::Process> for crate::oci::Process {
ApparmorProfile: from.apparmor_profile,
OOMScoreAdj: from.oom_score_adj.map_or(0, |t| t as i64),
SelinuxLabel: from.selinux_label,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -109,8 +104,7 @@ impl From<oci::LinuxDeviceCgroup> for crate::oci::LinuxDeviceCgroup {
Major: from.major.map_or(0, |t| t),
Minor: from.minor.map_or(0, |t| t),
Access: from.access,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -125,8 +119,7 @@ impl From<oci::LinuxMemory> for crate::oci::LinuxMemory {
KernelTCP: from.kernel_tcp.map_or(0, |t| t),
Swappiness: from.swappiness.map_or(0, |t| t),
DisableOOMKiller: from.disable_oom_killer.map_or(false, |t| t),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -141,8 +134,7 @@ impl From<oci::LinuxCpu> for crate::oci::LinuxCPU {
RealtimePeriod: from.realtime_period.map_or(0, |t| t),
Cpus: from.cpus,
Mems: from.mems,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -151,8 +143,7 @@ impl From<oci::LinuxPids> for crate::oci::LinuxPids {
fn from(from: LinuxPids) -> Self {
crate::oci::LinuxPids {
Limit: from.limit,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -165,8 +156,7 @@ impl From<oci::LinuxWeightDevice> for crate::oci::LinuxWeightDevice {
Minor: 0,
Weight: from.weight.map_or(0, |t| t as u32),
LeafWeight: from.leaf_weight.map_or(0, |t| t as u32),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -178,8 +168,7 @@ impl From<oci::LinuxThrottleDevice> for crate::oci::LinuxThrottleDevice {
Major: 0,
Minor: 0,
Rate: from.rate,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -194,8 +183,7 @@ impl From<oci::LinuxBlockIo> for crate::oci::LinuxBlockIO {
ThrottleWriteBpsDevice: from_vec(from.throttle_write_bps_device),
ThrottleReadIOPSDevice: from_vec(from.throttle_read_iops_device),
ThrottleWriteIOPSDevice: from_vec(from.throttle_write_iops_device),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -205,8 +193,7 @@ impl From<oci::LinuxHugepageLimit> for crate::oci::LinuxHugepageLimit {
crate::oci::LinuxHugepageLimit {
Pagesize: from.page_size,
Limit: from.limit,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -216,8 +203,7 @@ impl From<oci::LinuxInterfacePriority> for crate::oci::LinuxInterfacePriority {
crate::oci::LinuxInterfacePriority {
Name: from.name,
Priority: from.priority,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -227,8 +213,7 @@ impl From<oci::LinuxNetwork> for crate::oci::LinuxNetwork {
crate::oci::LinuxNetwork {
ClassID: from.class_id.map_or(0, |t| t),
Priorities: from_vec(from.priorities),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -243,8 +228,7 @@ impl From<oci::LinuxResources> for crate::oci::LinuxResources {
BlockIO: from_option(from.block_io),
HugepageLimits: from_vec(from.hugepage_limits),
Network: from_option(from.network),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -254,8 +238,7 @@ impl From<oci::Root> for crate::oci::Root {
crate::oci::Root {
Path: from.path,
Readonly: from.readonly,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -265,10 +248,9 @@ impl From<oci::Mount> for crate::oci::Mount {
crate::oci::Mount {
destination: from.destination,
source: from.source,
field_type: from.r#type,
options: from_vec(from.options),
unknown_fields: Default::default(),
cached_size: Default::default(),
type_: from.r#type,
options: from.options,
..Default::default()
}
}
}
@@ -281,11 +263,10 @@ impl From<oci::Hook> for crate::oci::Hook {
}
crate::oci::Hook {
Path: from.path,
Args: from_vec(from.args),
Env: from_vec(from.env),
Args: from.args,
Env: from.env,
Timeout: timeout,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -299,8 +280,7 @@ impl From<oci::Hooks> for crate::oci::Hooks {
StartContainer: from_vec(from.start_container),
Poststart: from_vec(from.poststart),
Poststop: from_vec(from.poststop),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -311,8 +291,7 @@ impl From<oci::LinuxIdMapping> for crate::oci::LinuxIDMapping {
HostID: from.host_id,
ContainerID: from.container_id,
Size: from.size,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -322,8 +301,7 @@ impl From<oci::LinuxNamespace> for crate::oci::LinuxNamespace {
crate::oci::LinuxNamespace {
Type: from.r#type,
Path: from.path,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -338,8 +316,7 @@ impl From<oci::LinuxDevice> for crate::oci::LinuxDevice {
FileMode: from.file_mode.map_or(0, |v| v),
UID: from.uid.map_or(0, |v| v),
GID: from.gid.map_or(0, |v| v),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -351,8 +328,7 @@ impl From<oci::LinuxSeccompArg> for crate::oci::LinuxSeccompArg {
Value: from.value,
ValueTwo: from.value_two,
Op: from.op,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -360,14 +336,13 @@ impl From<oci::LinuxSeccompArg> for crate::oci::LinuxSeccompArg {
impl From<oci::LinuxSyscall> for crate::oci::LinuxSyscall {
fn from(from: LinuxSyscall) -> Self {
crate::oci::LinuxSyscall {
Names: from_vec(from.names),
Names: from.names,
Action: from.action,
Args: from_vec(from.args),
ErrnoRet: Some(crate::oci::LinuxSyscall_oneof_ErrnoRet::errnoret(
ErrnoRet: Some(crate::oci::linux_syscall::ErrnoRet::Errnoret(
from.errno_ret,
)),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -376,11 +351,10 @@ impl From<oci::LinuxSeccomp> for crate::oci::LinuxSeccomp {
fn from(from: LinuxSeccomp) -> Self {
crate::oci::LinuxSeccomp {
DefaultAction: from.default_action,
Architectures: from_vec(from.architectures),
Architectures: from.architectures,
Syscalls: from_vec(from.syscalls),
Flags: from_vec(from.flags),
unknown_fields: Default::default(),
cached_size: Default::default(),
Flags: from.flags,
..Default::default()
}
}
}
@@ -389,8 +363,7 @@ impl From<oci::LinuxIntelRdt> for crate::oci::LinuxIntelRdt {
fn from(from: LinuxIntelRdt) -> Self {
crate::oci::LinuxIntelRdt {
L3CacheSchema: from.l3_cache_schema,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -407,12 +380,11 @@ impl From<oci::Linux> for crate::oci::Linux {
Devices: from_vec(from.devices),
Seccomp: from_option(from.seccomp),
RootfsPropagation: from.rootfs_propagation,
MaskedPaths: from_vec(from.masked_paths),
ReadonlyPaths: from_vec(from.readonly_paths),
MaskedPaths: from.masked_paths,
ReadonlyPaths: from.readonly_paths,
MountLabel: from.mount_label,
IntelRdt: from_option(from.intel_rdt),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -430,8 +402,7 @@ impl From<oci::Spec> for crate::oci::Spec {
Linux: from_option(from.linux),
Solaris: Default::default(),
Windows: Default::default(),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -449,7 +420,7 @@ impl From<crate::oci::Mount> for oci::Mount {
fn from(mut from: crate::oci::Mount) -> Self {
let options = from.take_options().to_vec();
Self {
r#type: from.take_field_type(),
r#type: from.take_type_(),
destination: from.take_destination(),
source: from.take_source(),
options,
@@ -460,9 +431,9 @@ impl From<crate::oci::Mount> for oci::Mount {
impl From<crate::oci::LinuxIDMapping> for oci::LinuxIdMapping {
fn from(from: crate::oci::LinuxIDMapping) -> Self {
LinuxIdMapping {
container_id: from.get_ContainerID(),
host_id: from.get_HostID(),
size: from.get_Size(),
container_id: from.ContainerID(),
host_id: from.HostID(),
size: from.Size(),
}
}
}
@@ -470,17 +441,17 @@ impl From<crate::oci::LinuxIDMapping> for oci::LinuxIdMapping {
impl From<crate::oci::LinuxDeviceCgroup> for oci::LinuxDeviceCgroup {
fn from(mut from: crate::oci::LinuxDeviceCgroup) -> Self {
let mut major = None;
if from.get_Major() > 0 {
major = Some(from.get_Major());
if from.Major() > 0 {
major = Some(from.Major());
}
let mut minor = None;
if from.get_Minor() > 0 {
minor = Some(from.get_Minor())
if from.Minor() > 0 {
minor = Some(from.Minor())
}
oci::LinuxDeviceCgroup {
allow: from.get_Allow(),
allow: from.Allow(),
r#type: Some(from.take_Type()),
major,
minor,
@@ -492,36 +463,36 @@ impl From<crate::oci::LinuxDeviceCgroup> for oci::LinuxDeviceCgroup {
impl From<crate::oci::LinuxMemory> for oci::LinuxMemory {
fn from(from: crate::oci::LinuxMemory) -> Self {
let mut limit = None;
if from.get_Limit() > 0 {
limit = Some(from.get_Limit());
if from.Limit() > 0 {
limit = Some(from.Limit());
}
let mut reservation = None;
if from.get_Reservation() > 0 {
reservation = Some(from.get_Reservation());
if from.Reservation() > 0 {
reservation = Some(from.Reservation());
}
let mut swap = None;
if from.get_Swap() > 0 {
swap = Some(from.get_Swap());
if from.Swap() > 0 {
swap = Some(from.Swap());
}
let mut kernel = None;
if from.get_Kernel() > 0 {
kernel = Some(from.get_Kernel());
if from.Kernel() > 0 {
kernel = Some(from.Kernel());
}
let mut kernel_tcp = None;
if from.get_KernelTCP() > 0 {
kernel_tcp = Some(from.get_KernelTCP());
if from.KernelTCP() > 0 {
kernel_tcp = Some(from.KernelTCP());
}
let mut swappiness = None;
if from.get_Swappiness() > 0 {
swappiness = Some(from.get_Swappiness());
if from.Swappiness() > 0 {
swappiness = Some(from.Swappiness());
}
let disable_oom_killer = Some(from.get_DisableOOMKiller());
let disable_oom_killer = Some(from.DisableOOMKiller());
oci::LinuxMemory {
limit,
@@ -538,28 +509,28 @@ impl From<crate::oci::LinuxMemory> for oci::LinuxMemory {
impl From<crate::oci::LinuxCPU> for oci::LinuxCpu {
fn from(mut from: crate::oci::LinuxCPU) -> Self {
let mut shares = None;
if from.get_Shares() > 0 {
shares = Some(from.get_Shares());
if from.Shares() > 0 {
shares = Some(from.Shares());
}
let mut quota = None;
if from.get_Quota() > 0 {
quota = Some(from.get_Quota());
if from.Quota() > 0 {
quota = Some(from.Quota());
}
let mut period = None;
if from.get_Period() > 0 {
period = Some(from.get_Period());
if from.Period() > 0 {
period = Some(from.Period());
}
let mut realtime_runtime = None;
if from.get_RealtimeRuntime() > 0 {
realtime_runtime = Some(from.get_RealtimeRuntime());
if from.RealtimeRuntime() > 0 {
realtime_runtime = Some(from.RealtimeRuntime());
}
let mut realtime_period = None;
if from.get_RealtimePeriod() > 0 {
realtime_period = Some(from.get_RealtimePeriod());
if from.RealtimePeriod() > 0 {
realtime_period = Some(from.RealtimePeriod());
}
let cpus = from.take_Cpus();
@@ -580,7 +551,7 @@ impl From<crate::oci::LinuxCPU> for oci::LinuxCpu {
impl From<crate::oci::LinuxPids> for oci::LinuxPids {
fn from(from: crate::oci::LinuxPids) -> Self {
oci::LinuxPids {
limit: from.get_Limit(),
limit: from.Limit(),
}
}
}
@@ -588,35 +559,35 @@ impl From<crate::oci::LinuxPids> for oci::LinuxPids {
impl From<crate::oci::LinuxBlockIO> for oci::LinuxBlockIo {
fn from(from: crate::oci::LinuxBlockIO) -> Self {
let mut weight = None;
if from.get_Weight() > 0 {
weight = Some(from.get_Weight() as u16);
if from.Weight() > 0 {
weight = Some(from.Weight() as u16);
}
let mut leaf_weight = None;
if from.get_LeafWeight() > 0 {
leaf_weight = Some(from.get_LeafWeight() as u16);
if from.LeafWeight() > 0 {
leaf_weight = Some(from.LeafWeight() as u16);
}
let mut weight_device = Vec::new();
for wd in from.get_WeightDevice() {
for wd in from.WeightDevice() {
weight_device.push(wd.clone().into());
}
let mut throttle_read_bps_device = Vec::new();
for td in from.get_ThrottleReadBpsDevice() {
for td in from.ThrottleReadBpsDevice() {
throttle_read_bps_device.push(td.clone().into());
}
let mut throttle_write_bps_device = Vec::new();
for td in from.get_ThrottleWriteBpsDevice() {
for td in from.ThrottleWriteBpsDevice() {
throttle_write_bps_device.push(td.clone().into());
}
let mut throttle_read_iops_device = Vec::new();
for td in from.get_ThrottleReadIOPSDevice() {
for td in from.ThrottleReadIOPSDevice() {
throttle_read_iops_device.push(td.clone().into());
}
let mut throttle_write_iops_device = Vec::new();
for td in from.get_ThrottleWriteIOPSDevice() {
for td in from.ThrottleWriteIOPSDevice() {
throttle_write_iops_device.push(td.clone().into());
}
@@ -661,7 +632,7 @@ impl From<crate::oci::LinuxInterfacePriority> for oci::LinuxInterfacePriority {
fn from(mut from: crate::oci::LinuxInterfacePriority) -> Self {
oci::LinuxInterfacePriority {
name: from.take_Name(),
priority: from.get_Priority(),
priority: from.Priority(),
}
}
}
@@ -669,11 +640,11 @@ impl From<crate::oci::LinuxInterfacePriority> for oci::LinuxInterfacePriority {
impl From<crate::oci::LinuxNetwork> for oci::LinuxNetwork {
fn from(mut from: crate::oci::LinuxNetwork) -> Self {
let mut class_id = None;
if from.get_ClassID() > 0 {
class_id = Some(from.get_ClassID());
if from.ClassID() > 0 {
class_id = Some(from.ClassID());
}
let mut priorities = Vec::new();
for p in from.take_Priorities().to_vec() {
for p in from.take_Priorities() {
priorities.push(p.into())
}
@@ -688,7 +659,7 @@ impl From<crate::oci::LinuxHugepageLimit> for oci::LinuxHugepageLimit {
fn from(mut from: crate::oci::LinuxHugepageLimit) -> Self {
oci::LinuxHugepageLimit {
page_size: from.take_Pagesize(),
limit: from.get_Limit(),
limit: from.Limit(),
}
}
}
@@ -696,7 +667,7 @@ impl From<crate::oci::LinuxHugepageLimit> for oci::LinuxHugepageLimit {
impl From<crate::oci::LinuxResources> for oci::LinuxResources {
fn from(mut from: crate::oci::LinuxResources) -> Self {
let mut devices = Vec::new();
for d in from.take_Devices().to_vec() {
for d in from.take_Devices() {
devices.push(d.into());
}
@@ -712,16 +683,16 @@ impl From<crate::oci::LinuxResources> for oci::LinuxResources {
let mut pids = None;
if from.has_Pids() {
pids = Some(from.get_Pids().clone().into())
pids = Some(from.Pids().clone().into())
}
let mut block_io = None;
if from.has_BlockIO() {
block_io = Some(from.get_BlockIO().clone().into());
block_io = Some(from.BlockIO().clone().into());
}
let mut hugepage_limits = Vec::new();
for hl in from.get_HugepageLimits() {
for hl in from.HugepageLimits() {
hugepage_limits.push(hl.clone().into());
}
@@ -750,11 +721,11 @@ impl From<crate::oci::LinuxDevice> for oci::LinuxDevice {
oci::LinuxDevice {
path: from.take_Path(),
r#type: from.take_Type(),
major: from.get_Major(),
minor: from.get_Minor(),
file_mode: Some(from.get_FileMode()),
uid: Some(from.get_UID()),
gid: Some(from.get_GID()),
major: from.Major(),
minor: from.Minor(),
file_mode: Some(from.FileMode()),
uid: Some(from.UID()),
gid: Some(from.GID()),
}
}
}
@@ -762,9 +733,9 @@ impl From<crate::oci::LinuxDevice> for oci::LinuxDevice {
impl From<crate::oci::LinuxSeccompArg> for oci::LinuxSeccompArg {
fn from(mut from: crate::oci::LinuxSeccompArg) -> Self {
oci::LinuxSeccompArg {
index: from.get_Index() as u32,
value: from.get_Value(),
value_two: from.get_ValueTwo(),
index: from.Index() as u32,
value: from.Value(),
value_two: from.ValueTwo(),
op: from.take_Op(),
}
}
@@ -773,14 +744,14 @@ impl From<crate::oci::LinuxSeccompArg> for oci::LinuxSeccompArg {
impl From<crate::oci::LinuxSyscall> for oci::LinuxSyscall {
fn from(mut from: crate::oci::LinuxSyscall) -> Self {
let mut args = Vec::new();
for ag in from.take_Args().to_vec() {
for ag in from.take_Args() {
args.push(ag.into());
}
oci::LinuxSyscall {
names: from.take_Names().to_vec(),
action: from.take_Action(),
args,
errno_ret: from.get_errnoret(),
errno_ret: from.errnoret(),
}
}
}
@@ -788,7 +759,7 @@ impl From<crate::oci::LinuxSyscall> for oci::LinuxSyscall {
impl From<crate::oci::LinuxSeccomp> for oci::LinuxSeccomp {
fn from(mut from: crate::oci::LinuxSeccomp) -> Self {
let mut syscalls = Vec::new();
for s in from.take_Syscalls().to_vec() {
for s in from.take_Syscalls() {
syscalls.push(s.into());
}
@@ -813,16 +784,16 @@ impl From<crate::oci::LinuxNamespace> for oci::LinuxNamespace {
impl From<crate::oci::Linux> for oci::Linux {
fn from(mut from: crate::oci::Linux) -> Self {
let mut uid_mappings = Vec::new();
for id_map in from.take_UIDMappings().to_vec() {
for id_map in from.take_UIDMappings() {
uid_mappings.push(id_map.into())
}
let mut gid_mappings = Vec::new();
for id_map in from.take_GIDMappings().to_vec() {
for id_map in from.take_GIDMappings() {
gid_mappings.push(id_map.into())
}
let sysctl = from.get_Sysctl().clone();
let sysctl = from.Sysctl().clone();
let mut resources = None;
if from.has_Resources() {
resources = Some(from.take_Resources().into());
@@ -830,12 +801,12 @@ impl From<crate::oci::Linux> for oci::Linux {
let cgroups_path = from.take_CgroupsPath();
let mut namespaces = Vec::new();
for ns in from.take_Namespaces().to_vec() {
for ns in from.take_Namespaces() {
namespaces.push(ns.into())
}
let mut devices = Vec::new();
for d in from.take_Devices().to_vec() {
for d in from.take_Devices() {
devices.push(d.into());
}
@@ -874,8 +845,8 @@ impl From<crate::oci::POSIXRlimit> for oci::PosixRlimit {
fn from(mut from: crate::oci::POSIXRlimit) -> Self {
oci::PosixRlimit {
r#type: from.take_Type(),
hard: from.get_Hard(),
soft: from.get_Soft(),
hard: from.Hard(),
soft: from.Soft(),
}
}
}
@@ -895,8 +866,8 @@ impl From<crate::oci::LinuxCapabilities> for oci::LinuxCapabilities {
impl From<crate::oci::User> for oci::User {
fn from(mut from: crate::oci::User) -> Self {
oci::User {
uid: from.get_UID(),
gid: from.get_GID(),
uid: from.UID(),
gid: from.GID(),
additional_gids: from.take_AdditionalGids().to_vec(),
username: from.take_Username(),
}
@@ -906,8 +877,8 @@ impl From<crate::oci::User> for oci::User {
impl From<crate::oci::Box> for oci::Box {
fn from(from: crate::oci::Box) -> Self {
oci::Box {
height: from.get_Height(),
width: from.get_Width(),
height: from.Height(),
width: from.Width(),
}
}
}
@@ -920,22 +891,22 @@ impl From<crate::oci::Process> for oci::Process {
}
let user = from.take_User().into();
let args = from.take_Args().into_vec();
let env = from.take_Env().into_vec();
let args = from.take_Args();
let env = from.take_Env();
let cwd = from.take_Cwd();
let mut capabilities = None;
if from.has_Capabilities() {
capabilities = Some(from.take_Capabilities().into());
}
let mut rlimits = Vec::new();
for rl in from.take_Rlimits().to_vec() {
for rl in from.take_Rlimits() {
rlimits.push(rl.into());
}
let no_new_privileges = from.get_NoNewPrivileges();
let no_new_privileges = from.NoNewPrivileges();
let apparmor_profile = from.take_ApparmorProfile();
let mut oom_score_adj = None;
if from.get_OOMScoreAdj() != 0 {
oom_score_adj = Some(from.get_OOMScoreAdj() as i32);
if from.OOMScoreAdj() != 0 {
oom_score_adj = Some(from.OOMScoreAdj() as i32);
}
let selinux_label = from.take_SelinuxLabel();
@@ -959,8 +930,8 @@ impl From<crate::oci::Process> for oci::Process {
impl From<crate::oci::Hook> for oci::Hook {
fn from(mut from: crate::oci::Hook) -> Self {
let mut timeout = None;
if from.get_Timeout() > 0 {
timeout = Some(from.get_Timeout() as i32);
if from.Timeout() > 0 {
timeout = Some(from.Timeout() as i32);
}
oci::Hook {
path: from.take_Path(),
@@ -1020,7 +991,7 @@ impl From<crate::oci::Spec> for oci::Spec {
}
let mut mounts = Vec::new();
for m in from.take_Mounts().into_vec() {
for m in from.take_Mounts() {
mounts.push(m.into())
}
@@ -1085,7 +1056,7 @@ mod tests {
#[test]
fn test_from_vec_len_0() {
let from: Vec<TestA> = vec![];
let to: ::protobuf::RepeatedField<TestB> = from_vec(from.clone());
let to: Vec<TestB> = from_vec(from.clone());
assert_eq!(from.len(), to.len());
}
@@ -1094,7 +1065,7 @@ mod tests {
let from: Vec<TestA> = vec![TestA {
from: "a".to_string(),
}];
let to: ::protobuf::RepeatedField<TestB> = from_vec(from.clone());
let to: Vec<TestB> = from_vec(from.clone());
assert_eq!(from.len(), to.len());
assert_eq!(from[0].from, to[0].to);

View File

@@ -50,7 +50,7 @@ dependencies = [
"logging",
"nix 0.24.3",
"oci",
"protobuf",
"protobuf 3.2.0",
"protocols",
"serde",
"serde_json",
@@ -423,6 +423,7 @@ dependencies = [
"nix 0.26.2",
"serde",
"serde_json",
"thiserror",
"tokio",
]
@@ -474,7 +475,7 @@ dependencies = [
"nix 0.24.3",
"oci",
"persist",
"protobuf",
"protobuf 3.2.0",
"serde_json",
"slog",
"slog-scope",
@@ -507,13 +508,14 @@ checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279"
[[package]]
name = "containerd-shim-protos"
version = "0.2.0"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "077ec778a0835d9d85502e8535362130187759b69eddabe2bdb3a68ffb575bd0"
checksum = "ef45f1c71aa587d8f657c546d8da38ea04f113dd05da0ef993c4515fa25fbdd1"
dependencies = [
"async-trait",
"protobuf",
"protobuf 3.2.0",
"ttrpc",
"ttrpc-codegen",
]
[[package]]
@@ -1733,6 +1735,16 @@ dependencies = [
"tokio",
]
[[package]]
name = "netns-rs"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23541694f1d7d18cd1a0da3a1352a6ea48b01cbb4a8e7a6e547963823fd5276e"
dependencies = [
"nix 0.23.2",
"thiserror",
]
[[package]]
name = "nix"
version = "0.23.2"
@@ -2181,9 +2193,16 @@ name = "protobuf"
version = "2.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94"
[[package]]
name = "protobuf"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b55bad9126f378a853655831eb7363b7b01b81d19f8cb1218861086ca4a1a61e"
dependencies = [
"serde",
"serde_derive",
"once_cell",
"protobuf-support",
"thiserror",
]
[[package]]
@@ -2192,36 +2211,47 @@ version = "2.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "033460afb75cf755fcfc16dfaed20b86468082a2ea24e05ac35ab4a099a017d6"
dependencies = [
"protobuf",
"protobuf 2.28.0",
]
[[package]]
name = "protobuf-codegen-pure"
version = "2.28.0"
name = "protobuf-codegen"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95a29399fc94bcd3eeaa951c715f7bea69409b2445356b00519740bcd6ddd865"
checksum = "0dd418ac3c91caa4032d37cb80ff0d44e2ebe637b2fb243b6234bf89cdac4901"
dependencies = [
"protobuf",
"protobuf-codegen",
"anyhow",
"once_cell",
"protobuf 3.2.0",
"protobuf-parse",
"regex",
"tempfile",
"thiserror",
]
[[package]]
name = "protobuf-codegen-pure3"
version = "2.28.2"
name = "protobuf-parse"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b351add14db0721ad0842f4858aec11a5088684112ef163fc50f113c63e69b2e"
checksum = "9d39b14605eaa1f6a340aec7f320b34064feb26c93aec35d6a9a2272a8ddfa49"
dependencies = [
"protobuf",
"protobuf-codegen3",
"anyhow",
"indexmap",
"log",
"protobuf 3.2.0",
"protobuf-support",
"tempfile",
"thiserror",
"which",
]
[[package]]
name = "protobuf-codegen3"
version = "2.28.2"
name = "protobuf-support"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73c5878d0fa872bd7d61782c6aa2d2d56761ba4ed4514eb6992f5f83162f1d2f"
checksum = "a5d4d7b8601c814cfb36bcebb79f0e61e45e1e93640cf778837833bbed05c372"
dependencies = [
"protobuf",
"thiserror",
]
[[package]]
@@ -2230,7 +2260,7 @@ version = "0.1.0"
dependencies = [
"async-trait",
"oci",
"protobuf",
"protobuf 3.2.0",
"ttrpc",
"ttrpc-codegen",
]
@@ -2400,6 +2430,7 @@ dependencies = [
"byte-unit 4.0.18",
"cgroups-rs",
"futures 0.3.26",
"hex",
"hypervisor",
"kata-sys-util",
"kata-types",
@@ -2408,6 +2439,7 @@ dependencies = [
"logging",
"netlink-packet-route",
"netlink-sys",
"netns-rs",
"nix 0.24.3",
"oci",
"persist",
@@ -2463,9 +2495,11 @@ dependencies = [
"lazy_static",
"linux_container",
"logging",
"netns-rs",
"nix 0.25.1",
"oci",
"persist",
"resource",
"serde_json",
"shim-interface",
"slog",
@@ -2661,7 +2695,7 @@ dependencies = [
"logging",
"nix 0.24.3",
"oci",
"protobuf",
"protobuf 3.2.0",
"rand 0.8.5",
"serial_test",
"service",
@@ -3121,9 +3155,9 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "ttrpc"
version = "0.6.1"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ecfff459a859c6ba6668ff72b34c2f1d94d9d58f7088414c2674ad0f31cc7d8"
checksum = "a35f22a2964bea14afee161665bb260b83cb48e665e0260ca06ec0e775c8b06c"
dependencies = [
"async-trait",
"byteorder",
@@ -3131,8 +3165,8 @@ dependencies = [
"libc",
"log",
"nix 0.23.2",
"protobuf",
"protobuf-codegen-pure",
"protobuf 3.2.0",
"protobuf-codegen 3.2.0",
"thiserror",
"tokio",
"tokio-vsock",
@@ -3140,28 +3174,28 @@ dependencies = [
[[package]]
name = "ttrpc-codegen"
version = "0.2.3"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2365c9179ad82b29bda1b0162c7542ab5861a7844abfedd8cfdf8bd7e12358f9"
checksum = "94d7f7631d7a9ebed715a47cd4cb6072cbc7ae1d4ec01598971bbec0024340c2"
dependencies = [
"protobuf",
"protobuf-codegen-pure3",
"protobuf-codegen3",
"protobuf 2.28.0",
"protobuf-codegen 3.2.0",
"protobuf-support",
"ttrpc-compiler",
]
[[package]]
name = "ttrpc-compiler"
version = "0.4.3"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed57c2d6669099791507b8b491b2940f2e8975b52a73fe82efad24257d10e9bc"
checksum = "ec3cb5dbf1f0865a34fe3f722290fe776cacb16f50428610b779467b76ddf647"
dependencies = [
"derive-new",
"prost",
"prost-build",
"prost-types",
"protobuf",
"protobuf-codegen3",
"protobuf 2.28.0",
"protobuf-codegen 2.28.0",
"tempfile",
]
@@ -3282,7 +3316,7 @@ dependencies = [
"nix 0.24.3",
"oci",
"persist",
"protobuf",
"protobuf 3.2.0",
"resource",
"serde",
"serde_derive",

View File

@@ -206,15 +206,22 @@ container_pipe_size=@PIPESIZE@
#debug_console_enabled = true
# Agent connection dialing timeout value in seconds
# (default: 30)
#dial_timeout = 30
# (default: 45)
dial_timeout = 45
[runtime]
# If enabled, the runtime will log additional debug messages to the
# system log
# (default: disabled)
#enable_debug = true
#
# If enabled, enabled, it means that 1) if the runtime exits abnormally,
# the cleanup process will be skipped, and 2) the runtime will not exit
# even if the health check fails.
# This option is typically used to retain abnormal information for debugging.
# (default: false)
#keep_abnormal = true
# Internetworking model
# Determines how the VM should be connected to the
# the container network interface

View File

@@ -12,12 +12,12 @@ futures = "0.1.27"
anyhow = "1.0.26"
async-trait = "0.1.48"
log = "0.4.14"
protobuf = "2.27.0"
protobuf = "3.2.0"
serde = { version = "^1.0", features = ["derive"] }
serde_json = ">=1.0.9"
slog = "2.5.2"
slog-scope = "4.4.0"
ttrpc = { version = "0.6.1" }
ttrpc = { version = "0.7.1" }
tokio = { version = "1.8.0", features = ["fs", "rt"] }
url = "2.2.2"
nix = "0.24.2"

View File

@@ -56,7 +56,7 @@ macro_rules! impl_health_service {
impl HealthService for KataAgent {
$(async fn $name(&self, req: $req) -> Result<$resp> {
let r = req.into();
let (mut client, timeout, _) = self.get_health_client().await.context("get health client")?;
let (client, timeout, _) = self.get_health_client().await.context("get health client")?;
let resp = client.$name(new_ttrpc_ctx(timeout * MILLISECOND_TO_NANOSECOND), &r).await?;
Ok(resp.into())
})*
@@ -75,7 +75,7 @@ macro_rules! impl_agent {
impl Agent for KataAgent {
$(async fn $name(&self, req: $req) -> Result<$resp> {
let r = req.into();
let (mut client, mut timeout, _) = self.get_agent_client().await.context("get client")?;
let (client, mut timeout, _) = self.get_agent_client().await.context("get client")?;
// update new timeout
if let Some(v) = $new_timeout {

View File

@@ -30,30 +30,18 @@ use crate::{
OomEventResponse, WaitProcessResponse, WriteStreamResponse,
};
fn from_vec<F: Into<T>, T: Sized>(from: Vec<F>) -> ::protobuf::RepeatedField<T> {
let mut to: Vec<T> = vec![];
for data in from {
to.push(data.into());
}
::protobuf::RepeatedField::from_vec(to)
fn trans_vec<F: Sized + Clone, T: From<F>>(from: Vec<F>) -> Vec<T> {
from.into_iter().map(|f| f.into()).collect()
}
fn into_vec<F: Sized + Clone, T: From<F>>(from: ::protobuf::RepeatedField<F>) -> Vec<T> {
let mut to: Vec<T> = vec![];
for data in from.to_vec() {
to.push(data.into());
}
to
}
fn from_option<F: Sized, T: From<F>>(from: Option<F>) -> ::protobuf::SingularPtrField<T> {
fn from_option<F: Sized, T: From<F>>(from: Option<F>) -> protobuf::MessageField<T> {
match from {
Some(f) => ::protobuf::SingularPtrField::from_option(Some(T::from(f))),
None => ::protobuf::SingularPtrField::none(),
Some(f) => protobuf::MessageField::from_option(Some(T::from(f))),
None => protobuf::MessageField::none(),
}
}
fn into_option<F: Into<T>, T: Sized>(from: ::protobuf::SingularPtrField<F>) -> Option<T> {
fn into_option<F: Into<T>, T: Sized>(from: protobuf::MessageField<F>) -> Option<T> {
from.into_option().map(|f| f.into())
}
@@ -84,9 +72,8 @@ impl From<FSGroup> for agent::FSGroup {
Self {
group_id: from.group_id,
group_change_policy: policy,
unknown_fields: Default::default(),
cached_size: Default::default(),
group_change_policy: policy.into(),
..Default::default()
}
}
}
@@ -96,9 +83,8 @@ impl From<StringUser> for agent::StringUser {
Self {
uid: from.uid,
gid: from.gid,
additionalGids: ::protobuf::RepeatedField::from_vec(from.additional_gids),
unknown_fields: Default::default(),
cached_size: Default::default(),
additionalGids: from.additional_gids,
..Default::default()
}
}
}
@@ -107,12 +93,11 @@ impl From<Device> for agent::Device {
fn from(from: Device) -> Self {
Self {
id: from.id,
field_type: from.field_type,
type_: from.field_type,
vm_path: from.vm_path,
container_path: from.container_path,
options: from_vec(from.options),
unknown_fields: Default::default(),
cached_size: Default::default(),
options: trans_vec(from.options),
..Default::default()
}
}
}
@@ -121,14 +106,13 @@ impl From<Storage> for agent::Storage {
fn from(from: Storage) -> Self {
Self {
driver: from.driver,
driver_options: from_vec(from.driver_options),
driver_options: trans_vec(from.driver_options),
source: from.source,
fstype: from.fs_type,
fs_group: from_option(from.fs_group),
options: from_vec(from.options),
options: trans_vec(from.options),
mount_point: from.mount_point,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -137,9 +121,8 @@ impl From<KernelModule> for agent::KernelModule {
fn from(from: KernelModule) -> Self {
Self {
name: from.name,
parameters: from_vec(from.parameters),
unknown_fields: Default::default(),
cached_size: Default::default(),
parameters: trans_vec(from.parameters),
..Default::default()
}
}
}
@@ -166,11 +149,10 @@ impl From<types::IPFamily> for IPFamily {
impl From<IPAddress> for types::IPAddress {
fn from(from: IPAddress) -> Self {
Self {
family: from.family.into(),
family: protobuf::EnumOrUnknown::new(from.family.into()),
address: from.address,
mask: from.mask,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -178,7 +160,7 @@ impl From<IPAddress> for types::IPAddress {
impl From<types::IPAddress> for IPAddress {
fn from(src: types::IPAddress) -> Self {
Self {
family: src.family.into(),
family: src.family.unwrap().into(),
address: "".to_string(),
mask: "".to_string(),
}
@@ -190,14 +172,13 @@ impl From<Interface> for types::Interface {
Self {
device: from.device,
name: from.name,
IPAddresses: from_vec(from.ip_addresses),
IPAddresses: trans_vec(from.ip_addresses),
mtu: from.mtu,
hwAddr: from.hw_addr,
pciPath: from.pci_addr,
field_type: from.field_type,
type_: from.field_type,
raw_flags: from.raw_flags,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -207,11 +188,11 @@ impl From<types::Interface> for Interface {
Self {
device: src.device,
name: src.name,
ip_addresses: into_vec(src.IPAddresses),
ip_addresses: trans_vec(src.IPAddresses),
mtu: src.mtu,
hw_addr: src.hwAddr,
pci_addr: src.pciPath,
field_type: src.field_type,
field_type: src.type_,
raw_flags: src.raw_flags,
}
}
@@ -220,7 +201,7 @@ impl From<types::Interface> for Interface {
impl From<agent::Interfaces> for Interfaces {
fn from(src: agent::Interfaces) -> Self {
Self {
interfaces: into_vec(src.Interfaces),
interfaces: trans_vec(src.Interfaces),
}
}
}
@@ -233,9 +214,8 @@ impl From<Route> for types::Route {
device: from.device,
source: from.source,
scope: from.scope,
family: from.family.into(),
unknown_fields: Default::default(),
cached_size: Default::default(),
family: protobuf::EnumOrUnknown::new(from.family.into()),
..Default::default()
}
}
}
@@ -248,7 +228,7 @@ impl From<types::Route> for Route {
device: src.device,
source: src.source,
scope: src.scope,
family: src.family.into(),
family: src.family.unwrap().into(),
}
}
}
@@ -256,9 +236,8 @@ impl From<types::Route> for Route {
impl From<Routes> for agent::Routes {
fn from(from: Routes) -> Self {
Self {
Routes: from_vec(from.routes),
unknown_fields: Default::default(),
cached_size: Default::default(),
Routes: trans_vec(from.routes),
..Default::default()
}
}
}
@@ -266,7 +245,7 @@ impl From<Routes> for agent::Routes {
impl From<agent::Routes> for Routes {
fn from(src: agent::Routes) -> Self {
Self {
routes: into_vec(src.Routes),
routes: trans_vec(src.Routes),
}
}
}
@@ -277,12 +256,11 @@ impl From<CreateContainerRequest> for agent::CreateContainerRequest {
container_id: from.process_id.container_id(),
exec_id: from.process_id.exec_id(),
string_user: from_option(from.string_user),
devices: from_vec(from.devices),
storages: from_vec(from.storages),
devices: trans_vec(from.devices),
storages: trans_vec(from.storages),
OCI: from_option(from.oci),
sandbox_pidns: from.sandbox_pidns,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -292,8 +270,7 @@ impl From<RemoveContainerRequest> for agent::RemoveContainerRequest {
Self {
container_id: from.container_id,
timeout: from.timeout,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -302,8 +279,7 @@ impl From<ContainerID> for agent::StartContainerRequest {
fn from(from: ContainerID) -> Self {
Self {
container_id: from.container_id,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -312,8 +288,7 @@ impl From<ContainerID> for agent::StatsContainerRequest {
fn from(from: ContainerID) -> Self {
Self {
container_id: from.container_id,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -322,8 +297,7 @@ impl From<ContainerID> for agent::PauseContainerRequest {
fn from(from: ContainerID) -> Self {
Self {
container_id: from.container_id,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -332,8 +306,7 @@ impl From<ContainerID> for agent::ResumeContainerRequest {
fn from(from: ContainerID) -> Self {
Self {
container_id: from.container_id,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -344,8 +317,7 @@ impl From<SignalProcessRequest> for agent::SignalProcessRequest {
container_id: from.process_id.container_id(),
exec_id: from.process_id.exec_id(),
signal: from.signal,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -355,8 +327,7 @@ impl From<WaitProcessRequest> for agent::WaitProcessRequest {
Self {
container_id: from.process_id.container_id(),
exec_id: from.process_id.exec_id(),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -366,8 +337,7 @@ impl From<UpdateContainerRequest> for agent::UpdateContainerRequest {
Self {
container_id: from.container_id,
resources: from_option(Some(from.resources)),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -378,8 +348,7 @@ impl From<WriteStreamRequest> for agent::WriteStreamRequest {
container_id: from.process_id.container_id(),
exec_id: from.process_id.exec_id(),
data: from.data,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -402,7 +371,7 @@ impl From<GetIPTablesRequest> for agent::GetIPTablesRequest {
impl From<agent::GetIPTablesResponse> for GetIPTablesResponse {
fn from(from: agent::GetIPTablesResponse) -> Self {
Self {
data: from.get_data().to_vec(),
data: from.data().to_vec(),
}
}
}
@@ -420,7 +389,7 @@ impl From<SetIPTablesRequest> for agent::SetIPTablesRequest {
impl From<agent::SetIPTablesResponse> for SetIPTablesResponse {
fn from(from: agent::SetIPTablesResponse) -> Self {
Self {
data: from.get_data().to_vec(),
data: from.data().to_vec(),
}
}
}
@@ -432,8 +401,7 @@ impl From<ExecProcessRequest> for agent::ExecProcessRequest {
exec_id: from.process_id.exec_id(),
string_user: from_option(from.string_user),
process: from_option(from.process),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -515,14 +483,14 @@ impl From<agent::BlkioStatsEntry> for BlkioStatsEntry {
impl From<agent::BlkioStats> for BlkioStats {
fn from(src: agent::BlkioStats) -> Self {
Self {
io_service_bytes_recursive: into_vec(src.io_service_bytes_recursive),
io_serviced_recursive: into_vec(src.io_serviced_recursive),
io_queued_recursive: into_vec(src.io_queued_recursive),
io_service_time_recursive: into_vec(src.io_service_time_recursive),
io_wait_time_recursive: into_vec(src.io_wait_time_recursive),
io_merged_recursive: into_vec(src.io_merged_recursive),
io_time_recursive: into_vec(src.io_time_recursive),
sectors_recursive: into_vec(src.sectors_recursive),
io_service_bytes_recursive: trans_vec(src.io_service_bytes_recursive),
io_serviced_recursive: trans_vec(src.io_serviced_recursive),
io_queued_recursive: trans_vec(src.io_queued_recursive),
io_service_time_recursive: trans_vec(src.io_service_time_recursive),
io_wait_time_recursive: trans_vec(src.io_wait_time_recursive),
io_merged_recursive: trans_vec(src.io_merged_recursive),
io_time_recursive: trans_vec(src.io_time_recursive),
sectors_recursive: trans_vec(src.sectors_recursive),
}
}
}
@@ -570,7 +538,7 @@ impl From<agent::StatsContainerResponse> for StatsContainerResponse {
fn from(src: agent::StatsContainerResponse) -> Self {
Self {
cgroup_stats: into_option(src.cgroup_stats),
network_stats: into_vec(src.network_stats),
network_stats: trans_vec(src.network_stats),
}
}
}
@@ -581,8 +549,7 @@ impl From<ReadStreamRequest> for agent::ReadStreamRequest {
container_id: from.process_id.container_id(),
exec_id: from.process_id.exec_id(),
len: from.len,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -598,8 +565,7 @@ impl From<CloseStdinRequest> for agent::CloseStdinRequest {
Self {
container_id: from.process_id.container_id(),
exec_id: from.process_id.exec_id(),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -611,8 +577,7 @@ impl From<TtyWinResizeRequest> for agent::TtyWinResizeRequest {
exec_id: from.process_id.exec_id(),
row: from.row,
column: from.column,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -621,8 +586,7 @@ impl From<UpdateInterfaceRequest> for agent::UpdateInterfaceRequest {
fn from(from: UpdateInterfaceRequest) -> Self {
Self {
interface: from_option(from.interface),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -630,8 +594,7 @@ impl From<UpdateInterfaceRequest> for agent::UpdateInterfaceRequest {
impl From<Empty> for agent::ListInterfacesRequest {
fn from(_: Empty) -> Self {
Self {
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -640,8 +603,7 @@ impl From<UpdateRoutesRequest> for agent::UpdateRoutesRequest {
fn from(from: UpdateRoutesRequest) -> Self {
Self {
routes: from_option(from.route),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -649,8 +611,7 @@ impl From<UpdateRoutesRequest> for agent::UpdateRoutesRequest {
impl From<Empty> for agent::ListRoutesRequest {
fn from(_: Empty) -> Self {
Self {
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -663,8 +624,7 @@ impl From<ARPNeighbor> for types::ARPNeighbor {
lladdr: from.ll_addr,
state: from.state,
flags: from.flags,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -672,9 +632,8 @@ impl From<ARPNeighbor> for types::ARPNeighbor {
impl From<ARPNeighbors> for agent::ARPNeighbors {
fn from(from: ARPNeighbors) -> Self {
Self {
ARPNeighbors: from_vec(from.neighbors),
unknown_fields: Default::default(),
cached_size: Default::default(),
ARPNeighbors: trans_vec(from.neighbors),
..Default::default()
}
}
}
@@ -683,8 +642,7 @@ impl From<AddArpNeighborRequest> for agent::AddARPNeighborsRequest {
fn from(from: AddArpNeighborRequest) -> Self {
Self {
neighbors: from_option(from.neighbors),
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -693,14 +651,13 @@ impl From<CreateSandboxRequest> for agent::CreateSandboxRequest {
fn from(from: CreateSandboxRequest) -> Self {
Self {
hostname: from.hostname,
dns: from_vec(from.dns),
storages: from_vec(from.storages),
dns: trans_vec(from.dns),
storages: trans_vec(from.storages),
sandbox_pidns: from.sandbox_pidns,
sandbox_id: from.sandbox_id,
guest_hook_path: from.guest_hook_path,
kernel_modules: from_vec(from.kernel_modules),
unknown_fields: Default::default(),
cached_size: Default::default(),
kernel_modules: trans_vec(from.kernel_modules),
..Default::default()
}
}
}
@@ -708,8 +665,7 @@ impl From<CreateSandboxRequest> for agent::CreateSandboxRequest {
impl From<Empty> for agent::DestroySandboxRequest {
fn from(_: Empty) -> Self {
Self {
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -720,8 +676,7 @@ impl From<OnlineCPUMemRequest> for agent::OnlineCPUMemRequest {
wait: from.wait,
nb_cpus: from.nb_cpus,
cpu_only: from.cpu_only,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -730,8 +685,7 @@ impl From<ReseedRandomDevRequest> for agent::ReseedRandomDevRequest {
fn from(from: ReseedRandomDevRequest) -> Self {
Self {
data: from.data,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -740,8 +694,7 @@ impl From<MemHotplugByProbeRequest> for agent::MemHotplugByProbeRequest {
fn from(from: MemHotplugByProbeRequest) -> Self {
Self {
memHotplugProbeAddr: from.mem_hotplug_probe_addr,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -751,8 +704,7 @@ impl From<SetGuestDateTimeRequest> for agent::SetGuestDateTimeRequest {
Self {
Sec: from.sec,
Usec: from.usec,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -762,8 +714,8 @@ impl From<agent::AgentDetails> for AgentDetails {
Self {
version: src.version,
init_daemon: src.init_daemon,
device_handlers: into_vec(src.device_handlers),
storage_handlers: into_vec(src.storage_handlers),
device_handlers: trans_vec(src.device_handlers),
storage_handlers: trans_vec(src.storage_handlers),
supports_seccomp: src.supports_seccomp,
}
}
@@ -790,8 +742,7 @@ impl From<CopyFileRequest> for agent::CopyFileRequest {
gid: from.gid,
offset: from.offset,
data: from.data,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -807,8 +758,7 @@ impl From<agent::WaitProcessResponse> for WaitProcessResponse {
impl From<Empty> for agent::GetOOMEventRequest {
fn from(_: Empty) -> Self {
Self {
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -817,8 +767,7 @@ impl From<CheckRequest> for health::CheckRequest {
fn from(from: CheckRequest) -> Self {
Self {
service: from.service,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -826,7 +775,7 @@ impl From<CheckRequest> for health::CheckRequest {
impl From<health::HealthCheckResponse> for HealthCheckResponse {
fn from(from: health::HealthCheckResponse) -> Self {
Self {
status: from.status as u32,
status: from.status.value() as u32,
}
}
}
@@ -852,8 +801,7 @@ impl From<VolumeStatsRequest> for agent::VolumeStatsRequest {
fn from(from: VolumeStatsRequest) -> Self {
Self {
volume_guest_path: from.volume_guest_path,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}
@@ -862,8 +810,8 @@ impl From<csi::VolumeStatsResponse> for VolumeStatsResponse {
fn from(from: csi::VolumeStatsResponse) -> Self {
let result: String = format!(
"Usage: {:?} Volume Condition: {:?}",
from.get_usage(),
from.get_volume_condition()
from.usage(),
from.volume_condition()
);
Self { data: result }
}
@@ -874,8 +822,7 @@ impl From<ResizeVolumeRequest> for agent::ResizeVolumeRequest {
Self {
volume_guest_path: from.volume_guest_path,
size: from.size,
unknown_fields: Default::default(),
cached_size: Default::default(),
..Default::default()
}
}
}

View File

@@ -23,3 +23,4 @@ api_client = { git = "https://github.com/cloud-hypervisor/cloud-hypervisor", cra
kata-types = { path = "../../../../libs/kata-types"}
nix = "0.26.2"
thiserror = "1.0.38"

View File

@@ -91,7 +91,7 @@ pub async fn cloud_hypervisor_vm_fs_add(
mut socket: UnixStream,
fs_config: FsConfig,
) -> Result<Option<String>> {
let result = task::spawn_blocking(move || -> Result<Option<String>> {
task::spawn_blocking(move || -> Result<Option<String>> {
let response = simple_api_full_command_and_response(
&mut socket,
"PUT",
@@ -102,7 +102,5 @@ pub async fn cloud_hypervisor_vm_fs_add(
Ok(response)
})
.await?;
result
.await?
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,107 @@
// Copyright (c) 2023 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
use std::convert::TryFrom;
use thiserror::Error;
#[derive(Error, Debug, PartialEq)]
pub enum VmConfigError {
#[error("empty sandbox path")]
EmptySandboxPath,
#[error("empty VSOCK socket path")]
EmptyVsockSocketPath,
#[error("cannot specify image and initrd")]
MultipleBootFiles,
#[error("missing boot image (no rootfs image or initrd)")]
NoBootFile,
#[error("CPU config error: {0}")]
CPUError(CpusConfigError),
#[error("Pmem config error: {0}")]
PmemError(PmemConfigError),
#[error("Payload config error: {0}")]
PayloadError(PayloadConfigError),
#[error("Disk config error: {0}")]
DiskError(DiskConfigError),
#[error("Memory config error: {0}")]
MemoryError(MemoryConfigError),
// The 2nd arg is actually a std::io::Error but that doesn't implement
// PartialEq, so we convert it to a String.
#[error("Failed to create sandbox path ({0}: {1}")]
SandboxError(String, String),
#[error("VSOCK config error: {0}")]
VsockError(VsockConfigError),
}
#[derive(Error, Debug, PartialEq)]
pub enum PmemConfigError {
#[error("Need rootfs image for PmemConfig")]
MissingImage,
}
#[derive(Error, Debug, PartialEq)]
pub enum DiskConfigError {
#[error("Need path for DiskConfig")]
MissingPath,
#[error("Found unexpected path for DiskConfig with TDX: {0}")]
UnexpectedPathForTDX(String),
}
#[derive(Error, Debug, PartialEq)]
pub enum CpusConfigError {
#[error("Too many boot vCPUs specified: {0}")]
BootVCPUsTooBig(<u8 as TryFrom<i32>>::Error),
#[error("Too many max vCPUs specified: {0}")]
MaxVCPUsTooBig(<u8 as TryFrom<u32>>::Error),
}
#[derive(Error, Debug, PartialEq)]
pub enum PayloadConfigError {
#[error("No kernel specified")]
NoKernel,
#[error("No initrd/initramfs specified")]
NoInitrd,
#[error("Need firmware for TDX")]
TDXFirmwareMissing,
}
#[derive(Error, Debug, PartialEq)]
pub enum MemoryConfigError {
#[error("No default memory specified")]
NoDefaultMemory,
#[error("Default memory size > available RAM")]
DefaultMemSizeTooBig,
#[error("Cannot convert default memory to bytes: {0}")]
BadDefaultMemSize(u32),
#[error("Cannot calculate hotplug memory size from default memory: {0}")]
BadMemSizeForHotplug(u64),
#[error("Cannot align hotplug memory size from pmem: {0}")]
BadPmemAlign(u64),
#[error("Failed to query system memory information: {0}")]
SysInfoFail(#[source] nix::errno::Errno),
}
#[derive(Error, Debug, PartialEq)]
pub enum VsockConfigError {
#[error("Missing VSOCK socket path")]
NoVsockSocketPath,
}

View File

@@ -17,6 +17,8 @@ pub use net_util::MacAddr;
pub const MAX_NUM_PCI_SEGMENTS: u16 = 16;
mod errors;
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)]
pub struct BalloonConfig {
pub size: u64,
@@ -330,7 +332,6 @@ pub struct PlatformConfig {
pub uuid: Option<String>,
#[serde(default)]
pub oem_strings: Option<Vec<String>>,
#[cfg(feature = "tdx")]
#[serde(default)]
pub tdx: bool,
}
@@ -425,9 +426,7 @@ pub struct VmConfig {
pub fs: Option<Vec<FsConfig>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pmem: Option<Vec<PmemConfig>>,
//#[serde(default = "ConsoleConfig::default_serial")]
pub serial: ConsoleConfig,
//#[serde(default = "ConsoleConfig::default_console")]
pub console: ConsoleConfig,
#[serde(skip_serializing_if = "Option::is_none")]
pub devices: Option<Vec<DeviceConfig>>,
@@ -484,12 +483,13 @@ fn u16_is_zero(v: &u16) -> bool {
// Type used to simplify conversion from a generic Hypervisor config
// to a CH specific VmConfig.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Default)]
pub struct NamedHypervisorConfig {
pub kernel_params: String,
pub sandbox_path: String,
pub vsock_socket_path: String,
pub cfg: HypervisorConfig,
pub tdx_enabled: bool,
pub shared_fs_devices: Option<Vec<FsConfig>>,
}

View File

@@ -68,6 +68,8 @@ impl CloudHypervisorInner {
let enable_debug = cfg.debug_info.enable_debug;
let confidential_guest = cfg.security_info.confidential_guest;
// Note that the configuration option hypervisor.block_device_driver is not used.
let rootfs_driver = VM_ROOTFS_DRIVER_PMEM;
@@ -81,6 +83,18 @@ impl CloudHypervisorInner {
let mut rootfs_param = KernelParams::new_rootfs_kernel_params(rootfs_driver, rootfs_type)?;
let mut extra_params = if enable_debug {
if confidential_guest {
KernelParams::from_string("console=hvc0")
} else {
KernelParams::from_string("console=ttyS0,115200n8")
}
} else {
KernelParams::from_string("quiet")
};
params.append(&mut extra_params);
// Add the rootfs device
params.append(&mut rootfs_param);
@@ -121,11 +135,18 @@ impl CloudHypervisorInner {
let kernel_params = self.get_kernel_params().await?;
// FIXME: See:
//
// - https://github.com/kata-containers/kata-containers/issues/6383
// - https://github.com/kata-containers/kata-containers/pull/6257
let tdx_enabled = false;
let named_cfg = NamedHypervisorConfig {
kernel_params,
sandbox_path,
vsock_socket_path,
cfg: hypervisor_config.clone(),
tdx_enabled,
shared_fs_devices,
};
@@ -229,7 +250,13 @@ impl CloudHypervisorInner {
async fn cloud_hypervisor_launch(&mut self, _timeout_secs: i32) -> Result<()> {
self.cloud_hypervisor_ensure_not_launched().await?;
let debug = false;
let cfg = self
.config
.as_ref()
.ok_or("no hypervisor config for CH")
.map_err(|e| anyhow!(e))?;
let debug = cfg.debug_info.enable_debug;
let disable_seccomp = true;

View File

@@ -188,6 +188,9 @@ impl DragonballInner {
let args: Vec<&str> = opt_list.split(',').collect();
for arg in args {
match arg {
"cache=none" => fs_cfg.cache_policy = String::from("none"),
"cache=auto" => fs_cfg.cache_policy = String::from("auto"),
"cache=always" => fs_cfg.cache_policy = String::from("always"),
"no_open" => fs_cfg.no_open = true,
"open" => fs_cfg.no_open = false,
"writeback_cache" => fs_cfg.writeback_cache = true,

View File

@@ -16,8 +16,10 @@ bitflags = "1.2.1"
byte-unit = "4.0.14"
cgroups-rs = "0.3.2"
futures = "0.3.11"
hex = "0.4.3"
lazy_static = "1.4.0"
libc = ">=0.2.39"
netns-rs = "0.1.0"
netlink-sys = "0.8.3"
netlink-packet-route = "0.13.0"
nix = "0.24.2"

View File

@@ -4,6 +4,7 @@
// SPDX-License-Identifier: Apache-2.0
//
use crate::network::NetworkConfig;
use crate::resource_persist::ResourceState;
use crate::{manager_inner::ResourceManagerInner, rootfs::Rootfs, volume::Volume, ResourceConfig};
use agent::{Agent, Storage};
@@ -55,6 +56,11 @@ impl ResourceManager {
inner.prepare_before_start_vm(device_configs).await
}
pub async fn handle_network(&self, network_config: NetworkConfig) -> Result<()> {
let mut inner = self.inner.write().await;
inner.handle_network(network_config).await
}
pub async fn setup_after_start_vm(&self) -> Result<()> {
let mut inner = self.inner.write().await;
inner.setup_after_start_vm().await

View File

@@ -6,7 +6,7 @@
use std::{sync::Arc, thread};
use crate::resource_persist::ResourceState;
use crate::{network::NetworkConfig, resource_persist::ResourceState};
use agent::{Agent, Storage};
use anyhow::{anyhow, Context, Ok, Result};
use async_trait::async_trait;
@@ -89,32 +89,9 @@ impl ResourceManagerInner {
};
}
ResourceConfig::Network(c) => {
// 1. When using Rust asynchronous programming, we use .await to
// allow other task to run instead of waiting for the completion of the current task.
// 2. Also, when handling the pod network, we need to set the shim threads
// into the network namespace to perform those operations.
// However, as the increase of the I/O intensive tasks, two issues could be caused by the two points above:
// a. When the future is blocked, the current thread (which is in the pod netns)
// might be take over by other tasks. After the future is finished, the thread take over
// the current task might not be in the pod netns. But the current task still need to run in pod netns
// b. When finish setting up the network, the current thread will be set back to the host namespace.
// In Rust Async, if the current thread is taken over by other task, the netns is dropped on another thread,
// but it is not in netns. So, the previous thread would still remain in the pod netns.
// The solution is to block the future on the current thread, it is enabled by spawn an os thread, create a
// tokio runtime, and block the task on it.
let hypervisor = self.hypervisor.clone();
let network = thread::spawn(move || -> Result<Arc<dyn Network>> {
let rt = runtime::Builder::new_current_thread().enable_io().build()?;
let d = rt.block_on(network::new(&c)).context("new network")?;
rt.block_on(d.setup(hypervisor.as_ref()))
.context("setup network")?;
Ok(d)
})
.join()
.map_err(|e| anyhow!("{:?}", e))
.context("Couldn't join on the associated thread")?
.context("failed to set up network")?;
self.network = Some(network);
self.handle_network(c)
.await
.context("failed to handle network")?;
}
};
}
@@ -122,6 +99,38 @@ impl ResourceManagerInner {
Ok(())
}
pub async fn handle_network(&mut self, network_config: NetworkConfig) -> Result<()> {
// 1. When using Rust asynchronous programming, we use .await to
// allow other task to run instead of waiting for the completion of the current task.
// 2. Also, when handling the pod network, we need to set the shim threads
// into the network namespace to perform those operations.
// However, as the increase of the I/O intensive tasks, two issues could be caused by the two points above:
// a. When the future is blocked, the current thread (which is in the pod netns)
// might be take over by other tasks. After the future is finished, the thread take over
// the current task might not be in the pod netns. But the current task still need to run in pod netns
// b. When finish setting up the network, the current thread will be set back to the host namespace.
// In Rust Async, if the current thread is taken over by other task, the netns is dropped on another thread,
// but it is not in netns. So, the previous thread would still remain in the pod netns.
// The solution is to block the future on the current thread, it is enabled by spawn an os thread, create a
// tokio runtime, and block the task on it.
let hypervisor = self.hypervisor.clone();
let network = thread::spawn(move || -> Result<Arc<dyn Network>> {
let rt = runtime::Builder::new_current_thread().enable_io().build()?;
let d = rt
.block_on(network::new(&network_config))
.context("new network")?;
rt.block_on(d.setup(hypervisor.as_ref()))
.context("setup network")?;
Ok(d)
})
.join()
.map_err(|e| anyhow!("{:?}", e))
.context("Couldn't join on the associated thread")?
.context("failed to set up network")?;
self.network = Some(network);
Ok(())
}
async fn handle_interfaces(&self, network: &dyn Network) -> Result<()> {
for i in network.interfaces().await.context("get interfaces")? {
// update interface

View File

@@ -18,7 +18,7 @@ use network_with_netns::NetworkWithNetns;
mod network_pair;
use network_pair::NetworkPair;
mod utils;
pub use utils::netns::NetnsGuard;
pub use utils::netns::{generate_netns_name, NetnsGuard};
use std::sync::Arc;
@@ -38,6 +38,7 @@ pub trait Network: Send + Sync {
async fn routes(&self) -> Result<Vec<agent::Route>>;
async fn neighs(&self) -> Result<Vec<agent::ARPNeighbor>>;
async fn save(&self) -> Option<Vec<EndpointState>>;
async fn remove(&self, h: &dyn Hypervisor) -> Result<()>;
}
pub async fn new(config: &NetworkConfig) -> Result<Arc<dyn Network>> {

View File

@@ -4,9 +4,12 @@
// SPDX-License-Identifier: Apache-2.0
//
use std::sync::{
atomic::{AtomicU32, Ordering},
Arc,
use std::{
fs,
sync::{
atomic::{AtomicU32, Ordering},
Arc,
},
};
use super::endpoint::endpoint_persist::EndpointState;
@@ -14,6 +17,7 @@ use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use futures::stream::TryStreamExt;
use hypervisor::Hypervisor;
use netns_rs::get_from_path;
use scopeguard::defer;
use tokio::sync::RwLock;
@@ -33,11 +37,13 @@ pub struct NetworkWithNetNsConfig {
pub network_model: String,
pub netns_path: String,
pub queues: usize,
pub network_created: bool,
}
struct NetworkWithNetnsInner {
netns_path: String,
entity_list: Vec<NetworkEntity>,
network_created: bool,
}
impl NetworkWithNetnsInner {
@@ -54,6 +60,7 @@ impl NetworkWithNetnsInner {
Ok(Self {
netns_path: config.netns_path.to_string(),
entity_list,
network_created: config.network_created,
})
}
}
@@ -120,6 +127,26 @@ impl Network for NetworkWithNetns {
}
Some(endpoint)
}
async fn remove(&self, h: &dyn Hypervisor) -> Result<()> {
let inner = self.inner.read().await;
// The network namespace would have been deleted at this point
// if it has not been created by virtcontainers.
if !inner.network_created {
return Ok(());
}
{
let _netns_guard =
netns::NetnsGuard::new(&inner.netns_path).context("net netns guard")?;
for e in &inner.entity_list {
e.endpoint.detach(h).await.context("detach")?;
}
}
let netns = get_from_path(inner.netns_path.clone())?;
netns.remove()?;
fs::remove_dir_all(inner.netns_path.clone()).context("failed to remove netns path")?;
Ok(())
}
}
async fn get_entity_from_netns(config: &NetworkWithNetNsConfig) -> Result<Vec<NetworkEntity>> {

View File

@@ -9,6 +9,7 @@ use std::{fs::File, os::unix::io::AsRawFd};
use anyhow::{Context, Result};
use nix::sched::{setns, CloneFlags};
use nix::unistd::{getpid, gettid};
use rand::Rng;
pub struct NetnsGuard {
old_netns: Option<File>,
@@ -50,6 +51,20 @@ impl Drop for NetnsGuard {
}
}
// generate the network namespace name
pub fn generate_netns_name() -> String {
let mut rng = rand::thread_rng();
let random_bytes: [u8; 16] = rng.gen();
format!(
"cnitest-{}-{}-{}-{}-{}",
hex::encode(&random_bytes[..4]),
hex::encode(&random_bytes[4..6]),
hex::encode(&random_bytes[6..8]),
hex::encode(&random_bytes[8..10]),
hex::encode(&random_bytes[10..])
)
}
#[cfg(test)]
mod tests {
use super::*;
@@ -67,4 +82,14 @@ mod tests {
let empty_path = "";
assert!(NetnsGuard::new(empty_path).unwrap().old_netns.is_none());
}
#[test]
fn test_generate_netns_name() {
let name1 = generate_netns_name();
let name2 = generate_netns_name();
let name3 = generate_netns_name();
assert_ne!(name1, name2);
assert_ne!(name2, name3);
assert_ne!(name1, name3);
}
}

View File

@@ -3,7 +3,7 @@
//
// SPDX-License-Identifier: Apache-2.0
//
use std::{fs, sync::Arc};
use std::{fs, path::Path, sync::Arc};
use super::{Rootfs, TYPE_OVERLAY_FS};
use crate::{
@@ -28,6 +28,8 @@ const NYDUS_ROOTFS_V6: &str = "v6";
const SNAPSHOT_DIR: &str = "snapshotdir";
const KATA_OVERLAY_DEV_TYPE: &str = "overlayfs";
// nydus prefetch file list name
const NYDUS_PREFETCH_FILE_LIST: &str = "prefetch_file.list";
pub(crate) struct NydusRootfs {
guest_path: String,
@@ -42,6 +44,9 @@ impl NydusRootfs {
cid: &str,
rootfs: &Mount,
) -> Result<Self> {
let prefetch_list_path =
get_nydus_prefetch_files(h.hypervisor_config().await.prefetch_list_path).await;
let share_fs_mount = share_fs.get_share_fs_mount();
let extra_options =
NydusExtraOptions::new(rootfs).context("failed to parse nydus extra options")?;
@@ -59,7 +64,7 @@ impl NydusRootfs {
rafs_meta.to_string(),
rafs_mnt,
extra_options.config.clone(),
None,
prefetch_list_path,
)
.await
.context("failed to do rafs mount")?;
@@ -151,3 +156,67 @@ impl Rootfs for NydusRootfs {
Ok(())
}
}
// Check prefetch files list path, and if invalid, discard it directly.
// As the result of caller `rafs_mount`, it returns `Option<String>`.
async fn get_nydus_prefetch_files(nydus_prefetch_path: String) -> Option<String> {
// nydus_prefetch_path is an annotation and pod with it will indicate
// that prefetch_files will be included.
if nydus_prefetch_path.is_empty() {
info!(sl!(), "nydus prefetch files path not set, just skip it.");
return None;
}
// Ensure the string ends with "/prefetch_files.list"
if !nydus_prefetch_path.ends_with(format!("/{}", NYDUS_PREFETCH_FILE_LIST).as_str()) {
info!(
sl!(),
"nydus prefetch file path no {:?} file exist.", NYDUS_PREFETCH_FILE_LIST
);
return None;
}
// ensure the prefetch_list_path is a regular file.
let prefetch_list_path = Path::new(nydus_prefetch_path.as_str());
if !prefetch_list_path.is_file() {
info!(
sl!(),
"nydus prefetch list file {:?} not a regular file", &prefetch_list_path
);
return None;
}
return Some(prefetch_list_path.display().to_string());
}
#[cfg(test)]
mod tests {
use super::*;
use std::{fs::File, path::PathBuf};
use tempfile::tempdir;
#[tokio::test]
async fn test_get_nydus_prefetch_files() {
let temp_dir = tempdir().unwrap();
let prefetch_list_path01 = temp_dir.path().join("nydus_prefetch_files");
// /tmp_dir/nydus_prefetch_files/
std::fs::create_dir_all(prefetch_list_path01.clone()).unwrap();
// /tmp_dir/nydus_prefetch_files/prefetch_file.list
let prefetch_list_path02 = prefetch_list_path01
.as_path()
.join(NYDUS_PREFETCH_FILE_LIST);
let file = File::create(prefetch_list_path02.clone());
assert!(file.is_ok());
let prefetch_file =
get_nydus_prefetch_files(prefetch_list_path02.as_path().display().to_string()).await;
assert!(prefetch_file.is_some());
assert_eq!(PathBuf::from(prefetch_file.unwrap()), prefetch_list_path02);
drop(file);
temp_dir.close().unwrap_or_default();
}
}

View File

@@ -8,6 +8,7 @@ license = "Apache-2.0"
[dependencies]
anyhow = "^1.0"
lazy_static = "1.4.0"
netns-rs = "0.1.0"
slog = "2.5.2"
slog-scope = "4.4.0"
tokio = { version = "1.8.0", features = ["rt-multi-thread"] }
@@ -26,6 +27,8 @@ oci = { path = "../../../libs/oci" }
shim-interface = { path = "../../../libs/shim-interface" }
persist = { path = "../persist" }
hypervisor = { path = "../hypervisor" }
resource = { path = "../resource" }
# runtime handler
linux_container = { path = "./linux_container", optional = true }
virt_container = { path = "./virt_container", optional = true }

View File

@@ -10,17 +10,17 @@ license = "Apache-2.0"
[dependencies]
anyhow = "^1.0"
async-trait = "0.1.48"
containerd-shim-protos = { version = "0.2.0", features = ["async"]}
containerd-shim-protos = { version = "0.3.0", features = ["async"]}
lazy_static = "1.4.0"
nix = "0.24.2"
protobuf = "2.27.0"
protobuf = "3.2.0"
serde_json = "1.0.39"
slog = "2.5.2"
slog-scope = "4.4.0"
strum = { version = "0.24.0", features = ["derive"] }
thiserror = "^1.0"
tokio = { version = "1.8.0", features = ["rt-multi-thread", "process", "fs"] }
ttrpc = { version = "0.6.1" }
ttrpc = { version = "0.7.1" }
persist = {path = "../../persist"}
agent = { path = "../../agent" }
kata-sys-util = { path = "../../../../libs/kata-sys-util" }

View File

@@ -11,5 +11,5 @@ pub mod message;
mod runtime_handler;
pub use runtime_handler::{RuntimeHandler, RuntimeInstance};
mod sandbox;
pub use sandbox::Sandbox;
pub use sandbox::{Sandbox, SandboxNetworkEnv};
pub mod types;

View File

@@ -7,14 +7,20 @@
use anyhow::Result;
use async_trait::async_trait;
#[derive(Clone)]
pub struct SandboxNetworkEnv {
pub netns: Option<String>,
pub network_created: bool,
}
#[async_trait]
pub trait Sandbox: Send + Sync {
async fn start(
&self,
netns: Option<String>,
dns: Vec<String>,
spec: &oci::Spec,
state: &oci::State,
network_env: SandboxNetworkEnv,
) -> Result<()>;
async fn stop(&self) -> Result<()>;
async fn cleanup(&self) -> Result<()>;

View File

@@ -151,7 +151,7 @@ impl From<Option<agent::StatsContainerResponse>> for StatsInfo {
}
if !cg_stats.hugetlb_stats.is_empty() {
let mut p_huge = ::protobuf::RepeatedField::new();
let mut p_huge = Vec::new();
for (k, v) in cg_stats.hugetlb_stats {
let mut h = metrics::HugetlbStat::new();
h.set_pagesize(k);
@@ -166,7 +166,7 @@ impl From<Option<agent::StatsContainerResponse>> for StatsInfo {
let net_stats = stats.network_stats;
if !net_stats.is_empty() {
let mut p_net = ::protobuf::RepeatedField::new();
let mut p_net = Vec::new();
for v in net_stats.iter() {
let mut h = metrics::NetworkStat::new();
h.set_name(v.name.clone());
@@ -195,10 +195,8 @@ impl From<Option<agent::StatsContainerResponse>> for StatsInfo {
}
}
fn copy_blkio_entry(
entry: &[agent::BlkioStatsEntry],
) -> ::protobuf::RepeatedField<metrics::BlkIOEntry> {
let mut p_entry = ::protobuf::RepeatedField::new();
fn copy_blkio_entry(entry: &[agent::BlkioStatsEntry]) -> Vec<metrics::BlkIOEntry> {
let mut p_entry = Vec::new();
for e in entry.iter() {
let mut blk = metrics::BlkIOEntry::new();

View File

@@ -16,7 +16,7 @@ use std::{
path::PathBuf,
};
fn trans_from_shim_mount(from: api::Mount) -> Mount {
fn trans_from_shim_mount(from: &api::Mount) -> Mount {
let options = from.options.to_vec();
let mut read_only = false;
for o in &options {
@@ -29,7 +29,7 @@ fn trans_from_shim_mount(from: api::Mount) -> Mount {
Mount {
source: from.source.clone(),
destination: PathBuf::from(&from.target),
fs_type: from.field_type,
fs_type: from.type_.clone(),
options,
device_id: None,
host_shared_fs_path: None,
@@ -41,19 +41,14 @@ impl TryFrom<api::CreateTaskRequest> for Request {
type Error = anyhow::Error;
fn try_from(from: api::CreateTaskRequest) -> Result<Self> {
let options = if from.has_options() {
Some(from.get_options().get_value().to_vec())
Some(from.options().value.to_vec())
} else {
None
};
Ok(Request::CreateContainer(ContainerConfig {
container_id: from.id.clone(),
bundle: from.bundle.clone(),
rootfs_mounts: from
.rootfs
.to_vec()
.into_iter()
.map(trans_from_shim_mount)
.collect(),
rootfs_mounts: from.rootfs.iter().map(trans_from_shim_mount).collect(),
terminal: from.terminal,
options,
stdin: (!from.stdin.is_empty()).then(|| from.stdin.clone()),
@@ -84,15 +79,15 @@ impl TryFrom<api::DeleteRequest> for Request {
impl TryFrom<api::ExecProcessRequest> for Request {
type Error = anyhow::Error;
fn try_from(from: api::ExecProcessRequest) -> Result<Self> {
let spec = from.get_spec();
let spec = from.spec();
Ok(Request::ExecProcess(ExecProcessRequest {
process: ContainerProcess::new(&from.id, &from.exec_id).context("new process id")?,
terminal: from.terminal,
stdin: (!from.stdin.is_empty()).then(|| from.stdin.clone()),
stdout: (!from.stdout.is_empty()).then(|| from.stdout.clone()),
stderr: (!from.stderr.is_empty()).then(|| from.stderr.clone()),
spec_type_url: spec.get_type_url().to_string(),
spec_value: spec.get_value().to_vec(),
spec_type_url: spec.type_url.to_string(),
spec_value: spec.value.to_vec(),
}))
}
}
@@ -182,7 +177,7 @@ impl TryFrom<api::UpdateTaskRequest> for Request {
fn try_from(from: api::UpdateTaskRequest) -> Result<Self> {
Ok(Request::UpdateContainer(UpdateRequest {
container_id: from.id.to_string(),
value: from.get_resources().get_value().to_vec(),
value: from.resources().value.to_vec(),
}))
}
}

View File

@@ -16,24 +16,24 @@ use containerd_shim_protos::api;
use super::{ProcessExitStatus, ProcessStateInfo, ProcessStatus, Response};
use crate::error::Error;
fn system_time_into(time: time::SystemTime) -> ::protobuf::well_known_types::Timestamp {
let mut proto_time = ::protobuf::well_known_types::Timestamp::new();
proto_time.set_seconds(
time.duration_since(time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs()
.try_into()
.unwrap_or_default(),
);
fn system_time_into(time: time::SystemTime) -> ::protobuf::well_known_types::timestamp::Timestamp {
let mut proto_time = ::protobuf::well_known_types::timestamp::Timestamp::new();
proto_time.seconds = time
.duration_since(time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs()
.try_into()
.unwrap_or_default();
proto_time
}
fn option_system_time_into(
time: Option<time::SystemTime>,
) -> ::protobuf::SingularPtrField<::protobuf::well_known_types::Timestamp> {
) -> protobuf::MessageField<protobuf::well_known_types::timestamp::Timestamp> {
match time {
Some(v) => ::protobuf::SingularPtrField::some(system_time_into(v)),
None => ::protobuf::SingularPtrField::none(),
Some(v) => ::protobuf::MessageField::some(system_time_into(v)),
None => ::protobuf::MessageField::none(),
}
}
@@ -66,7 +66,7 @@ impl From<ProcessStateInfo> for api::StateResponse {
id: from.container_id.clone(),
bundle: from.bundle.clone(),
pid: from.pid.pid,
status: from.status.into(),
status: protobuf::EnumOrUnknown::new(from.status.into()),
stdin: from.stdin.unwrap_or_default(),
stdout: from.stdout.unwrap_or_default(),
stderr: from.stderr.unwrap_or_default(),
@@ -164,13 +164,13 @@ impl TryFrom<Response> for api::StateResponse {
impl TryFrom<Response> for api::StatsResponse {
type Error = anyhow::Error;
fn try_from(from: Response) -> Result<Self> {
let mut any = ::protobuf::well_known_types::Any::new();
let mut any = ::protobuf::well_known_types::any::Any::new();
let mut response = api::StatsResponse::new();
match from {
Response::StatsContainer(resp) => {
if let Some(value) = resp.value {
any.set_type_url(value.type_url);
any.set_value(value.value);
any.type_url = value.type_url;
any.value = value.value;
response.set_stats(any);
}
Ok(response)
@@ -193,8 +193,7 @@ impl TryFrom<Response> for api::PidsResponse {
let mut res = api::PidsResponse::new();
p_info.set_pid(resp.pid);
processes.push(p_info);
let v = protobuf::RepeatedField::<api::ProcessInfo>::from_vec(processes);
res.set_processes(v);
res.set_processes(processes);
Ok(res)
}
_ => Err(anyhow!(Error::UnexpectedResponse(

View File

@@ -4,20 +4,22 @@
// SPDX-License-Identifier: Apache-2.0
//
use std::{str::from_utf8, sync::Arc};
use anyhow::{anyhow, Context, Result};
use std::{path::PathBuf, str::from_utf8, sync::Arc};
use crate::{shim_mgmt::server::MgmtServer, static_resource::StaticResourceManager};
use anyhow::{anyhow, Context, Result};
use common::{
message::Message,
types::{Request, Response},
RuntimeHandler, RuntimeInstance, Sandbox,
RuntimeHandler, RuntimeInstance, Sandbox, SandboxNetworkEnv,
};
use hypervisor::Param;
use kata_sys_util::spec::load_oci_spec;
use kata_types::{
annotations::Annotation, config::default::DEFAULT_GUEST_DNS_FILE, config::TomlConfig,
};
use netns_rs::NetNs;
use resource::network::generate_netns_name;
#[cfg(feature = "linux")]
use linux_container::LinuxContainer;
@@ -53,7 +55,7 @@ impl RuntimeHandlerManagerInner {
&mut self,
spec: &oci::Spec,
state: &oci::State,
netns: Option<String>,
network_env: SandboxNetworkEnv,
dns: Vec<String>,
config: Arc<TomlConfig>,
) -> Result<()> {
@@ -77,7 +79,7 @@ impl RuntimeHandlerManagerInner {
// start sandbox
runtime_instance
.sandbox
.start(netns, dns, spec, state)
.start(dns, spec, state, network_env)
.await
.context("start sandbox")?;
self.runtime_instance = Some(Arc::new(runtime_instance));
@@ -104,23 +106,6 @@ impl RuntimeHandlerManagerInner {
#[cfg(feature = "virt")]
VirtContainer::init().context("init virt container")?;
let netns = if let Some(linux) = &spec.linux {
let mut netns = None;
for ns in &linux.namespaces {
if ns.r#type.as_str() != oci::NETWORKNAMESPACE {
continue;
}
if !ns.path.is_empty() {
netns = Some(ns.path.clone());
break;
}
}
netns
} else {
None
};
for m in &spec.mounts {
if m.destination == DEFAULT_GUEST_DNS_FILE {
let contents = fs::read_to_string(&m.source).await?;
@@ -129,7 +114,42 @@ impl RuntimeHandlerManagerInner {
}
let config = load_config(spec, options).context("load config")?;
self.init_runtime_handler(spec, state, netns, dns, Arc::new(config))
let mut network_created = false;
// set netns to None if we want no network for the VM
let netns = if config.runtime.disable_new_netns {
None
} else {
let mut netns_path = None;
if let Some(linux) = &spec.linux {
for ns in &linux.namespaces {
if ns.r#type.as_str() != oci::NETWORKNAMESPACE {
continue;
}
// get netns path from oci spec
if !ns.path.is_empty() {
netns_path = Some(ns.path.clone());
}
// if we get empty netns from oci spec, we need to create netns for the VM
else {
let ns_name = generate_netns_name();
let netns = NetNs::new(ns_name)?;
let path = PathBuf::from(netns.path()).to_str().map(|s| s.to_string());
info!(sl!(), "the netns path is {:?}", path);
netns_path = path;
network_created = true;
}
break;
}
}
netns_path
};
let network_env = SandboxNetworkEnv {
netns,
network_created,
};
self.init_runtime_handler(spec, state, network_env, dns, Arc::new(config))
.await
.context("init runtime handler")?;
@@ -171,9 +191,16 @@ impl RuntimeHandlerManager {
let sender = inner.msg_sender.clone();
let sandbox_state = persist::from_disk::<SandboxState>(&inner.id)
.context("failed to load the sandbox state")?;
let config = if let Ok(spec) = load_oci_spec() {
load_config(&spec, &None).context("load config")?
} else {
TomlConfig::default()
};
let sandbox_args = SandboxRestoreArgs {
sid: inner.id.clone(),
toml_config: TomlConfig::default(),
toml_config: config,
sender,
};
match sandbox_state.sandbox_type.clone() {
@@ -189,6 +216,10 @@ impl RuntimeHandlerManager {
}
#[cfg(feature = "virt")]
name if name == VirtContainer::name() => {
if sandbox_args.toml_config.runtime.keep_abnormal {
info!(sl!(), "skip cleanup for keep_abnormal");
return Ok(());
}
let sandbox = VirtSandbox::restore(sandbox_args, sandbox_state)
.await
.context("failed to restore the sandbox")?;
@@ -236,7 +267,7 @@ impl RuntimeHandlerManager {
id: container_config.container_id.to_string(),
status: oci::ContainerState::Creating,
pid: 0,
bundle: bundler_path,
bundle: container_config.bundle.clone(),
annotations: spec.annotations.clone(),
};

View File

@@ -9,12 +9,12 @@ license = "Apache-2.0"
anyhow = "^1.0"
async-trait = "0.1.48"
awaitgroup = "0.6.0"
containerd-shim-protos = { version = "0.2.0", features = ["async"]}
containerd-shim-protos = { version = "0.3.0", features = ["async"]}
futures = "0.3.19"
lazy_static = "1.4.0"
libc = ">=0.2.39"
nix = "0.24.2"
protobuf = "2.27.0"
protobuf = "3.2.0"
serde = { version = "1.0.100", features = ["derive"] }
serde_derive = "1.0.27"
serde_json = "1.0.82"

View File

@@ -21,17 +21,17 @@ const HEALTH_CHECK_STOP_CHANNEL_BUFFER_SIZE: usize = 1;
pub struct HealthCheck {
pub keep_alive: bool,
keep_vm: bool,
keep_abnormal: bool,
stop_tx: mpsc::Sender<()>,
stop_rx: Arc<Mutex<mpsc::Receiver<()>>>,
}
impl HealthCheck {
pub fn new(keep_alive: bool, keep_vm: bool) -> HealthCheck {
pub fn new(keep_alive: bool, keep_abnormal: bool) -> HealthCheck {
let (tx, rx) = mpsc::channel(HEALTH_CHECK_STOP_CHANNEL_BUFFER_SIZE);
HealthCheck {
keep_alive,
keep_vm,
keep_abnormal,
stop_tx: tx,
stop_rx: Arc::new(Mutex::new(rx)),
}
@@ -46,7 +46,7 @@ impl HealthCheck {
info!(sl!(), "start runtime keep alive");
let stop_rx = self.stop_rx.clone();
let keep_vm = self.keep_vm;
let keep_abnormal = self.keep_abnormal;
let _ = tokio::spawn(async move {
let mut version_check_threshold_count = 0;
@@ -87,7 +87,7 @@ impl HealthCheck {
error!(sl!(), "failed to do {} agent health check: {}", id, e);
if let Err(mpsc::error::TryRecvError::Empty) = stop_rx.try_recv() {
error!(sl!(), "failed to receive stop monitor signal");
if !keep_vm {
if !keep_abnormal {
::std::process::exit(1);
}
} else {

View File

@@ -14,7 +14,7 @@ use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use common::{
message::{Action, Message},
Sandbox,
Sandbox, SandboxNetworkEnv,
};
use containerd_shim_protos::events::task::TaskOOM;
use hypervisor::{dragonball::Dragonball, Hypervisor, HYPERVISOR_DRAGONBALL};
@@ -75,6 +75,8 @@ impl VirtSandbox {
hypervisor: Arc<dyn Hypervisor>,
resource_manager: Arc<ResourceManager>,
) -> Result<Self> {
let config = resource_manager.config().await;
let keep_abnormal = config.runtime.keep_abnormal;
Ok(Self {
sid: sid.to_string(),
msg_sender: Arc::new(Mutex::new(msg_sender)),
@@ -82,34 +84,25 @@ impl VirtSandbox {
agent,
hypervisor,
resource_manager,
monitor: Arc::new(HealthCheck::new(true, false)),
monitor: Arc::new(HealthCheck::new(true, keep_abnormal)),
})
}
async fn prepare_for_start_sandbox(
async fn prepare_config_for_sandbox(
&self,
_id: &str,
netns: Option<String>,
network_env: SandboxNetworkEnv,
) -> Result<Vec<ResourceConfig>> {
let mut resource_configs = vec![];
let config = self.resource_manager.config().await;
if let Some(netns_path) = netns {
let network_config = ResourceConfig::Network(NetworkConfig::NetworkResourceWithNetNs(
NetworkWithNetNsConfig {
network_model: config.runtime.internetworking_model.clone(),
netns_path,
queues: self
.hypervisor
.hypervisor_config()
.await
.network_info
.network_queues as usize,
},
));
resource_configs.push(network_config);
if !network_env.network_created {
if let Some(netns_path) = network_env.netns {
let network_config = ResourceConfig::Network(
self.prepare_network_config(netns_path, network_env.network_created)
.await,
);
resource_configs.push(network_config);
}
}
let hypervisor_config = self.hypervisor.hypervisor_config().await;
let virtio_fs_config = ResourceConfig::ShareFs(hypervisor_config.shared_fs);
resource_configs.push(virtio_fs_config);
@@ -149,16 +142,43 @@ impl VirtSandbox {
Ok(())
}
async fn prepare_network_config(
&self,
netns_path: String,
network_created: bool,
) -> NetworkConfig {
let config = self.resource_manager.config().await;
NetworkConfig::NetworkResourceWithNetNs(NetworkWithNetNsConfig {
network_model: config.runtime.internetworking_model.clone(),
netns_path,
queues: self
.hypervisor
.hypervisor_config()
.await
.network_info
.network_queues as usize,
network_created,
})
}
fn has_prestart_hooks(
&self,
prestart_hooks: Vec<oci::Hook>,
create_runtime_hooks: Vec<oci::Hook>,
) -> bool {
!prestart_hooks.is_empty() || !create_runtime_hooks.is_empty()
}
}
#[async_trait]
impl Sandbox for VirtSandbox {
async fn start(
&self,
netns: Option<String>,
dns: Vec<String>,
spec: &oci::Spec,
state: &oci::State,
network_env: SandboxNetworkEnv,
) -> Result<()> {
let id = &self.sid;
@@ -171,13 +191,15 @@ impl Sandbox for VirtSandbox {
}
self.hypervisor
.prepare_vm(id, netns.clone())
.prepare_vm(id, network_env.netns.clone())
.await
.context("prepare vm")?;
// generate device and setup before start vm
// should after hypervisor.prepare_vm
let resources = self.prepare_for_start_sandbox(id, netns).await?;
let resources = self
.prepare_config_for_sandbox(id, network_env.clone())
.await?;
self.resource_manager
.prepare_before_start_vm(resources)
.await
@@ -195,8 +217,28 @@ impl Sandbox for VirtSandbox {
self.execute_oci_hook_functions(&prestart_hooks, &create_runtime_hooks, state)
.await?;
// TODO: if prestart_hooks is not empty, rescan the network endpoints(rely on hotplug endpoints).
// see: https://github.com/kata-containers/kata-containers/issues/6378
// 1. if there are pre-start hook functions, network config might have been changed.
// We need to rescan the netns to handle the change.
// 2. Do not scan the netns if we want no network for the VM.
// TODO In case of vm factory, scan the netns to hotplug interfaces after the VM is started.
if self.has_prestart_hooks(prestart_hooks, create_runtime_hooks)
&& !self
.resource_manager
.config()
.await
.runtime
.disable_new_netns
{
if let Some(netns_path) = network_env.netns {
let network_resource = self
.prepare_network_config(netns_path, network_env.network_created)
.await;
self.resource_manager
.handle_network(network_resource)
.await
.context("set up device after start vm")?;
}
}
// connect agent
// set agent socket
@@ -400,6 +442,7 @@ impl Persist for VirtSandbox {
}?;
let agent = Arc::new(KataAgent::new(kata_types::config::Agent::default()));
let sid = sandbox_args.sid;
let keep_abnormal = config.runtime.keep_abnormal;
let args = ManagerArgs {
sid: sid.clone(),
agent: agent.clone(),
@@ -414,7 +457,7 @@ impl Persist for VirtSandbox {
agent,
hypervisor,
resource_manager,
monitor: Arc::new(HealthCheck::new(true, false)),
monitor: Arc::new(HealthCheck::new(true, keep_abnormal)),
})
}
}

View File

@@ -11,10 +11,10 @@ async-trait = "0.1.48"
slog = "2.5.2"
slog-scope = "4.4.0"
tokio = { version = "1.8.0", features = ["rt-multi-thread"] }
ttrpc = { version = "0.6.1" }
ttrpc = { version = "0.7.1" }
common = { path = "../runtimes/common" }
containerd-shim-protos = { version = "0.2.0", features = ["async"]}
containerd-shim-protos = { version = "0.3.0", features = ["async"]}
logging = { path = "../../../libs/logging"}
shim-interface = { path = "../../../libs/shim-interface" }
runtimes = { path = "../runtimes" }

View File

@@ -14,7 +14,7 @@ use std::{
use anyhow::{Context, Result};
use common::message::{Action, Event, Message};
use containerd_shim_protos::{
protobuf::{well_known_types::Any, Message as ProtobufMessage},
protobuf::{well_known_types::any::Any, Message as ProtobufMessage},
shim_async,
};
use runtimes::RuntimeHandlerManager;

View File

@@ -15,12 +15,12 @@ path = "src/bin/main.rs"
[dependencies]
anyhow = "^1.0"
backtrace = {version = ">=0.3.35", features = ["libunwind", "libbacktrace", "std"], default-features = false}
containerd-shim-protos = { version = "0.2.0", features = ["async"]}
containerd-shim-protos = { version = "0.3.0", features = ["async"]}
go-flag = "0.1.0"
libc = "0.2.108"
log = "0.4.14"
nix = "0.24.2"
protobuf = "2.27.0"
protobuf = "3.2.0"
sha2 = "=0.9.3"
slog = {version = "2.5.2", features = ["std", "release_max_level_trace", "max_level_trace"]}
slog-async = "2.5.2"

View File

@@ -26,12 +26,12 @@ impl ShimExecutor {
async fn do_cleanup(&self) -> Result<api::DeleteResponse> {
let mut rsp = api::DeleteResponse::new();
rsp.set_exit_status(128 + libc::SIGKILL as u32);
let mut exited_time = protobuf::well_known_types::Timestamp::new();
let mut exited_time = protobuf::well_known_types::timestamp::Timestamp::new();
let seconds = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map_err(Error::SystemTime)?
.as_secs() as i64;
exited_time.set_seconds(seconds);
exited_time.seconds = seconds;
rsp.set_exited_at(exited_time);
let address = self

View File

@@ -97,6 +97,8 @@ GENERATED_VARS = \
VERSION \
CONFIG_ACRN_IN \
CONFIG_QEMU_IN \
CONFIG_QEMU_TDX_IN \
CONFIG_QEMU_GPU_IN \
CONFIG_CLH_IN \
CONFIG_FC_IN \
CONFIG_CLH_TDX_IN \
@@ -130,8 +132,6 @@ DEFROOTFSTYPE := $(ROOTFSTYPE_EXT4)
FIRMWAREPATH :=
FIRMWAREVOLUMEPATH :=
TDVFFIRMWAREPATH := $(PREFIXDEPS)/share/tdvf/OVMF_CODE.fd
TDVFFIRMWAREVOLUMEPATH := $(PREFIXDEPS)/share/tdvf/OVMF_VARS.fd
TDSHIMFIRMWAREPATH := ${PREFIXDEPS}/share/td-shim/td-shim.bin
SEVFIRMWAREPATH := $(PREFIXDEPS)/share/ovmf/AMDSEV.fd
SNPFIRMWAREPATH := $(PREFIXDEPS)/share/ovmf/OVMF.fd
@@ -146,12 +146,15 @@ AGENT_AA_KBC_PARAMS_TDX ?= ""
AGENT_AA_KBC_PARAMS_SEV ?= ""
AGENT_AA_KBC_PARAMS_SNP ?= ""
TDXKERNELPARAMS := tdx_disable_filter agent.enable_signature_verification=false $(AGENT_AA_KBC_PARAMS_TDX)
TDXKERNELPARAMS_QEMU += $(TDXKERNELPARAMS) $(ROOTMEASURECONFIGTDX)
KERNELTDXPARAMS += $(TDXKERNELPARAMS) $(ROOTMEASURECONFIGTDX)
TDXKERNELPARAMS_CLH += $(TDXKERNELPARAMS) $(ROOTMEASURECONFIG)
SEVKERNELPARAMS := $(AGENTCONFIGFILEKERNELPARAM) agent.enable_signature_verification=false $(AGENT_AA_KBC_PARAMS_SEV)
SNPKERNELPARAMS := $(AGENTCONFIGFILEKERNELPARAM) agent.enable_signature_verification=false $(AGENT_AA_KBC_PARAMS_SNP)
KERNELPARAMS += $(ROOTMEASURECONFIG) agent.enable_signature_verification=false $(AGENT_AA_KBC_PARAMS)
FIRMWARETDVFPATH := $(PREFIXDEPS)/share/tdvf/OVMF.fd
FIRMWARETDVFVOLUMEPATH := $(PREFIXDEPS)/share/tdvf/OVMF_VARS.fd
# Name of default configuration file the runtime will use.
CONFIG_FILE = configuration.toml
@@ -233,6 +236,7 @@ DEFVALIDENTROPYSOURCES := [\"/dev/urandom\",\"/dev/random\",\"\"]
DEFDISABLEBLOCK := false
DEFSHAREDFS_CLH_VIRTIOFS := virtio-fs
DEFSHAREDFS_QEMU_VIRTIOFS := virtio-fs
DEFSHAREDFS_QEMU_TDX_VIRTIOFS := virtio-9p
DEFVIRTIOFSDAEMON := $(LIBEXECDIR)/virtiofsd
ifeq ($(ARCH),ppc64le)
DEFVIRTIOFSDAEMON := $(LIBEXECDIR)/qemu/virtiofsd
@@ -328,7 +332,7 @@ ifneq (,$(QEMUCMD))
CONFIG_PATHS += $(CONFIG_PATH_QEMU_TDX)
SYSCONFIG_QEMU_TDX = $(abspath $(SYSCONFDIR)/$(CONFIG_FILE_QEMU_TDX))
SYSCONFIG_PATHS += $(SYSCONFIG_QEMU_TDX)
SYSCONFIG_PATHS_TDX += $(SYSCONFIG_QEMU_TDX)
CONFIGS += $(CONFIG_QEMU_TDX)
@@ -380,10 +384,18 @@ ifneq (,$(QEMUCMD))
CONFIGS += $(CONFIG_REMOTE)
CONFIG_FILE_QEMU_GPU = configuration-qemu-gpu.toml
CONFIG_QEMU_GPU = config/$(CONFIG_FILE_QEMU_GPU)
CONFIG_QEMU_GPU_IN = $(CONFIG_QEMU_GPU).in
CONFIGS += $(CONFIG_QEMU_GPU)
# qemu-specific options (all should be suffixed by "_QEMU")
DEFBLOCKSTORAGEDRIVER_QEMU := virtio-scsi
DEFBLOCKDEVICEAIO_QEMU := io_uring
DEFNETWORKMODEL_QEMU := tcfilter
KERNELTYPE = uncompressed
KERNELNAME = $(call MAKE_KERNEL_NAME,$(KERNELTYPE))
KERNELPATH = $(KERNELDIR)/$(KERNELNAME)
@@ -582,10 +594,10 @@ USER_VARS += KERNELTDXPATH_CLH
USER_VARS += KERNELPATH_FC
USER_VARS += KERNELVIRTIOFSPATH
USER_VARS += FIRMWAREPATH
USER_VARS += FIRMWARETDVFPATH
USER_VARS += FIRMWAREVOLUMEPATH
USER_VARS += TDSHIMFIRMWAREPATH
USER_VARS += TDVFFIRMWAREPATH
USER_VARS += TDVFFIRMWAREVOLUMEPATH
USER_VARS += FIRMWARETDVFVOLUMEPATH
USER_VARS += SEVFIRMWAREPATH
USER_VARS += SNPFIRMWAREPATH
USER_VARS += MACHINEACCELERATORS
@@ -598,6 +610,7 @@ USER_VARS += TDXKERNELPARAMS_QEMU
USER_VARS += TDXKERNELPARAMS_CLH
USER_VARS += SEVKERNELPARAMS
USER_VARS += SNPKERNELPARAMS
USER_VARS += KERNELTDXPARAMS
USER_VARS += LIBEXECDIR
USER_VARS += LOCALSTATEDIR
USER_VARS += PKGDATADIR
@@ -613,8 +626,11 @@ USER_VARS += PROJECT_TYPE
USER_VARS += PROJECT_URL
USER_VARS += QEMUBINDIR
USER_VARS += QEMUCMD
USER_VARS += QEMUTDXCMD
USER_VARS += QEMUPATH
USER_VARS += QEMUTDXPATH
USER_VARS += QEMUVALIDHYPERVISORPATHS
USER_VARS += QEMUTDXVALIDHYPERVISORPATHS
USER_VARS += QEMUVIRTIOFSCMD
USER_VARS += QEMUVIRTIOFSPATH
USER_VARS += QEMUSNPPATH
@@ -648,6 +664,7 @@ USER_VARS += DEFBLOCKSTORAGEDRIVER_QEMU
USER_VARS += DEFBLOCKDEVICEAIO_QEMU
USER_VARS += DEFSHAREDFS_CLH_VIRTIOFS
USER_VARS += DEFSHAREDFS_QEMU_VIRTIOFS
USER_VARS += DEFSHAREDFS_QEMU_TDX_VIRTIOFS
USER_VARS += DEFVIRTIOFSDAEMON
USER_VARS += DEFVALIDVIRTIOFSDAEMONPATHS
USER_VARS += DEFVIRTIOFSCACHESIZE
@@ -770,6 +787,10 @@ define MAKE_KERNEL_VIRTIOFS_NAME
$(if $(findstring uncompressed,$1),vmlinux-virtiofs.container,vmlinuz-virtiofs.container)
endef
define MAKE_KERNEL_TDX_NAME
$(if $(findstring uncompressed,$1),vmlinux-tdx.container,vmlinuz-tdx.container)
endef
GENERATED_FILES += pkg/katautils/config-settings.go
$(RUNTIME_OUTPUT): $(SOURCES) $(GENERATED_FILES) $(MAKEFILE_LIST) | show-summary

View File

@@ -9,10 +9,10 @@ MACHINETYPE := q35
KERNELPARAMS :=
MACHINEACCELERATORS :=
CPUFEATURES := pmu=off
TDXCPUFEATURES := -vmx-rdseed-exit,pmu=off
QEMUCMD := qemu-system-x86_64
QEMUTDXCMD := qemu-system-x86_64-tdx
QEMUTDXCMD := qemu-system-x86_64-tdx-experimental
TDXCPUFEATURES := -vmx-rdseed-exit,pmu=off
QEMUSNPCMD := qemu-system-x86_64-snp
# Firecracker binary name

View File

@@ -52,6 +52,8 @@ The **log-level** allows the chose how verbose the logs should be. The default i
**NOTE: The debug endpoints are available only if the [Kata Containers configuration file](https://github.com/kata-containers/kata-containers/blob/9d5b03a1b70bbd175237ec4b9f821d6ccee0a1f6/src/runtime/config/configuration-qemu.toml.in#L590-L592) includes** `enable_pprof = true` **in the** `[runtime]` **section**.
The `/metrics` has a query parameter `filter_family`, which filter Kata sandboxes metrics with specific names. If `filter_family` is set to `A` (and `B`, split with `,`), metrics with prefix `A` (and `B`) will only be returned.
The `/sandboxes` endpoint lists the _sandbox ID_ of all the detected Kata runtimes. If accessed via a web browser, it provides html links to the endpoints available for each sandbox.
In order to retrieve data for a specific Kata workload, the _sandbox ID_ should be passed in the query string using the _sandbox_ key. The `/agent-url`, and all the `/debug/`* endpoints require `sandbox_id` to be specified in the query string.

View File

@@ -154,8 +154,8 @@ disable_selinux=@DEFDISABLESELINUX@
#debug_console_enabled = true
# Agent connection dialing timeout value in seconds
# (default: 30)
#dial_timeout = 30
# (default: 45)
dial_timeout = 45
[runtime]
# If enabled, the runtime will log additional debug messages to the

View File

@@ -41,6 +41,11 @@ rootfs_type=@DEFROOTFSTYPE@
# Default false
# confidential_guest = true
# Enable running clh VMM as a non-root user.
# By default clh VMM run as root. When this is set to true, clh VMM process runs as
# a non-root random user. See documentation for the limitations of this mode.
# rootless = true
# disable applying SELinux on the VMM process (default false)
disable_selinux=@DEFDISABLESELINUX@
@@ -300,8 +305,8 @@ block_device_driver = "virtio-blk"
#debug_console_enabled = true
# Agent connection dialing timeout value in seconds
# (default: 30)
#dial_timeout = 30
# (default: 45)
dial_timeout = 45
[runtime]
# If enabled, the runtime will log additional debug messages to the

View File

@@ -284,8 +284,8 @@ kernel_modules=[]
#debug_console_enabled = true
# Agent connection dialing timeout value in seconds
# (default: 30)
#dial_timeout = 30
# (default: 45)
dial_timeout = 45
[runtime]
# If enabled, the runtime will log additional debug messages to the

View File

@@ -0,0 +1,692 @@
# Copyright (c) 2017-2019 Intel Corporation
# Copyright (c) 2021 Adobe Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# XXX: WARNING: this file is auto-generated.
# XXX:
# XXX: Source file: "@CONFIG_QEMU_IN@"
# XXX: Project:
# XXX: Name: @PROJECT_NAME@
# XXX: Type: @PROJECT_TYPE@
[hypervisor.qemu]
path = "@QEMUPATH@"
kernel = "@KERNELPATH@"
image = "@IMAGEPATH@"
# initrd = "@INITRDPATH@"
machine_type = "@MACHINETYPE@"
# rootfs filesystem type:
# - ext4 (default)
# - xfs
# - erofs
rootfs_type=@DEFROOTFSTYPE@
# Enable confidential guest support.
# Toggling that setting may trigger different hardware features, ranging
# from memory encryption to both memory and CPU-state encryption and integrity.
# The Kata Containers runtime dynamically detects the available feature set and
# aims at enabling the largest possible one, returning an error if none is
# available, or none is supported by the hypervisor.
#
# Known limitations:
# * Does not work by design:
# - CPU Hotplug
# - Memory Hotplug
# - NVDIMM devices
#
# Default false
# confidential_guest = true
# Choose AMD SEV-SNP confidential guests
# In case of using confidential guests on AMD hardware that supports both SEV
# and SEV-SNP, the following enables SEV-SNP guests. SEV guests are default.
# Default false
# sev_snp_guest = true
# Enable running QEMU VMM as a non-root user.
# By default QEMU VMM run as root. When this is set to true, QEMU VMM process runs as
# a non-root random user. See documentation for the limitations of this mode.
# rootless = true
# List of valid annotation names for the hypervisor
# Each member of the list is a regular expression, which is the base name
# of the annotation, e.g. "path" for io.katacontainers.config.hypervisor.path"
enable_annotations = @DEFENABLEANNOTATIONS@
# List of valid annotations values for the hypervisor
# Each member of the list is a path pattern as described by glob(3).
# The default if not set is empty (all annotations rejected.)
# Your distribution recommends: @QEMUVALIDHYPERVISORPATHS@
valid_hypervisor_paths = @QEMUVALIDHYPERVISORPATHS@
# Optional space-separated list of options to pass to the guest kernel.
# For example, use `kernel_params = "vsyscall=emulate"` if you are having
# trouble running pre-2.15 glibc.
#
# WARNING: - any parameter specified here will take priority over the default
# parameter value of the same name used to start the virtual machine.
# Do not set values here unless you understand the impact of doing so as you
# may stop the virtual machine from booting.
# To see the list of default parameters, enable hypervisor debug, create a
# container and look for 'default-kernel-parameters' log entries.
kernel_params = "@KERNELPARAMS@"
# Path to the firmware.
# If you want that qemu uses the default firmware leave this option empty
firmware = "@FIRMWAREPATH@"
# Path to the firmware volume.
# firmware TDVF or OVMF can be split into FIRMWARE_VARS.fd (UEFI variables
# as configuration) and FIRMWARE_CODE.fd (UEFI program image). UEFI variables
# can be customized per each user while UEFI code is kept same.
firmware_volume = "@FIRMWAREVOLUMEPATH@"
# Machine accelerators
# comma-separated list of machine accelerators to pass to the hypervisor.
# For example, `machine_accelerators = "nosmm,nosmbus,nosata,nopit,static-prt,nofw"`
machine_accelerators="@MACHINEACCELERATORS@"
# Qemu seccomp sandbox feature
# comma-separated list of seccomp sandbox features to control the syscall access.
# For example, `seccompsandbox= "on,obsolete=deny,spawn=deny,resourcecontrol=deny"`
# Note: "elevateprivileges=deny" doesn't work with daemonize option, so it's removed from the seccomp sandbox
# Another note: enabling this feature may reduce performance, you may enable
# /proc/sys/net/core/bpf_jit_enable to reduce the impact. see https://man7.org/linux/man-pages/man8/bpfc.8.html
#seccompsandbox="@DEFSECCOMPSANDBOXPARAM@"
# CPU features
# comma-separated list of cpu features to pass to the cpu
# For example, `cpu_features = "pmu=off,vmx=off"
cpu_features="@CPUFEATURES@"
# Default number of vCPUs per SB/VM:
# unspecified or 0 --> will be set to @DEFVCPUS@
# < 0 --> will be set to the actual number of physical cores
# > 0 <= number of physical cores --> will be set to the specified number
# > number of physical cores --> will be set to the actual number of physical cores
default_vcpus = 1
# Default maximum number of vCPUs per SB/VM:
# unspecified or == 0 --> will be set to the actual number of physical cores or to the maximum number
# of vCPUs supported by KVM if that number is exceeded
# > 0 <= number of physical cores --> will be set to the specified number
# > number of physical cores --> will be set to the actual number of physical cores or to the maximum number
# of vCPUs supported by KVM if that number is exceeded
# WARNING: Depending of the architecture, the maximum number of vCPUs supported by KVM is used when
# the actual number of physical cores is greater than it.
# WARNING: Be aware that this value impacts the virtual machine's memory footprint and CPU
# the hotplug functionality. For example, `default_maxvcpus = 240` specifies that until 240 vCPUs
# can be added to a SB/VM, but the memory footprint will be big. Another example, with
# `default_maxvcpus = 8` the memory footprint will be small, but 8 will be the maximum number of
# vCPUs supported by the SB/VM. In general, we recommend that you do not edit this variable,
# unless you know what are you doing.
# NOTICE: on arm platform with gicv2 interrupt controller, set it to 8.
default_maxvcpus = @DEFMAXVCPUS@
# Bridges can be used to hot plug devices.
# Limitations:
# * Currently only pci bridges are supported
# * Until 30 devices per bridge can be hot plugged.
# * Until 5 PCI bridges can be cold plugged per VM.
# This limitation could be a bug in qemu or in the kernel
# Default number of bridges per SB/VM:
# unspecified or 0 --> will be set to @DEFBRIDGES@
# > 1 <= 5 --> will be set to the specified number
# > 5 --> will be set to 5
default_bridges = @DEFBRIDGES@
# Default memory size in MiB for SB/VM.
# If unspecified then it will be set @DEFMEMSZ@ MiB.
default_memory = @DEFMEMSZ@
#
# Default memory slots per SB/VM.
# If unspecified then it will be set @DEFMEMSLOTS@.
# This is will determine the times that memory will be hotadded to sandbox/VM.
#memory_slots = @DEFMEMSLOTS@
# Default maximum memory in MiB per SB / VM
# unspecified or == 0 --> will be set to the actual amount of physical RAM
# > 0 <= amount of physical RAM --> will be set to the specified number
# > amount of physical RAM --> will be set to the actual amount of physical RAM
default_maxmemory = @DEFMAXMEMSZ@
# The size in MiB will be plused to max memory of hypervisor.
# It is the memory address space for the NVDIMM devie.
# If set block storage driver (block_device_driver) to "nvdimm",
# should set memory_offset to the size of block device.
# Default 0
#memory_offset = 0
# Specifies virtio-mem will be enabled or not.
# Please note that this option should be used with the command
# "echo 1 > /proc/sys/vm/overcommit_memory".
# Default false
#enable_virtio_mem = true
# Disable block device from being used for a container's rootfs.
# In case of a storage driver like devicemapper where a container's
# root file system is backed by a block device, the block device is passed
# directly to the hypervisor for performance reasons.
# This flag prevents the block device from being passed to the hypervisor,
# virtio-fs is used instead to pass the rootfs.
disable_block_device_use = @DEFDISABLEBLOCK@
# Shared file system type:
# - virtio-fs (default)
# - virtio-9p
# - virtio-fs-nydus
shared_fs = "@DEFSHAREDFS_QEMU_VIRTIOFS@"
# Path to vhost-user-fs daemon.
virtio_fs_daemon = "@DEFVIRTIOFSDAEMON@"
# List of valid annotations values for the virtiofs daemon
# The default if not set is empty (all annotations rejected.)
# Your distribution recommends: @DEFVALIDVIRTIOFSDAEMONPATHS@
valid_virtio_fs_daemon_paths = @DEFVALIDVIRTIOFSDAEMONPATHS@
# Default size of DAX cache in MiB
virtio_fs_cache_size = @DEFVIRTIOFSCACHESIZE@
# Default size of virtqueues
virtio_fs_queue_size = @DEFVIRTIOFSQUEUESIZE@
# Extra args for virtiofsd daemon
#
# Format example:
# ["-o", "arg1=xxx,arg2", "-o", "hello world", "--arg3=yyy"]
# Examples:
# Set virtiofsd log level to debug : ["-o", "log_level=debug"] or ["-d"]
#
# see `virtiofsd -h` for possible options.
virtio_fs_extra_args = @DEFVIRTIOFSEXTRAARGS@
# Cache mode:
#
# - never
# Metadata, data, and pathname lookup are not cached in guest. They are
# always fetched from host and any changes are immediately pushed to host.
#
# - auto
# Metadata and pathname lookup cache expires after a configured amount of
# time (default is 1 second). Data is cached while the file is open (close
# to open consistency).
#
# - always
# Metadata, data, and pathname lookup are cached in guest and never expire.
virtio_fs_cache = "@DEFVIRTIOFSCACHE@"
# Block storage driver to be used for the hypervisor in case the container
# rootfs is backed by a block device. This is virtio-scsi, virtio-blk
# or nvdimm.
block_device_driver = "@DEFBLOCKSTORAGEDRIVER_QEMU@"
# aio is the I/O mechanism used by qemu
# Options:
#
# - threads
# Pthread based disk I/O.
#
# - native
# Native Linux I/O.
#
# - io_uring
# Linux io_uring API. This provides the fastest I/O operations on Linux, requires kernel>5.1 and
# qemu >=5.0.
block_device_aio = "@DEFBLOCKDEVICEAIO_QEMU@"
# Specifies cache-related options will be set to block devices or not.
# Default false
#block_device_cache_set = true
# Specifies cache-related options for block devices.
# Denotes whether use of O_DIRECT (bypass the host page cache) is enabled.
# Default false
#block_device_cache_direct = true
# Specifies cache-related options for block devices.
# Denotes whether flush requests for the device are ignored.
# Default false
#block_device_cache_noflush = true
# Enable iothreads (data-plane) to be used. This causes IO to be
# handled in a separate IO thread. This is currently only implemented
# for SCSI.
#
enable_iothreads = @DEFENABLEIOTHREADS@
# Enable pre allocation of VM RAM, default false
# Enabling this will result in lower container density
# as all of the memory will be allocated and locked
# This is useful when you want to reserve all the memory
# upfront or in the cases where you want memory latencies
# to be very predictable
# Default false
#enable_mem_prealloc = true
# Enable huge pages for VM RAM, default false
# Enabling this will result in the VM memory
# being allocated using huge pages.
# This is useful when you want to use vhost-user network
# stacks within the container. This will automatically
# result in memory pre allocation
#enable_hugepages = true
# Enable vhost-user storage device, default false
# Enabling this will result in some Linux reserved block type
# major range 240-254 being chosen to represent vhost-user devices.
enable_vhost_user_store = @DEFENABLEVHOSTUSERSTORE@
# The base directory specifically used for vhost-user devices.
# Its sub-path "block" is used for block devices; "block/sockets" is
# where we expect vhost-user sockets to live; "block/devices" is where
# simulated block device nodes for vhost-user devices to live.
vhost_user_store_path = "@DEFVHOSTUSERSTOREPATH@"
# Enable vIOMMU, default false
# Enabling this will result in the VM having a vIOMMU device
# This will also add the following options to the kernel's
# command line: intel_iommu=on,iommu=pt
#enable_iommu = true
# Enable IOMMU_PLATFORM, default false
# Enabling this will result in the VM device having iommu_platform=on set
#enable_iommu_platform = true
# List of valid annotations values for the vhost user store path
# The default if not set is empty (all annotations rejected.)
# Your distribution recommends: @DEFVALIDVHOSTUSERSTOREPATHS@
valid_vhost_user_store_paths = @DEFVALIDVHOSTUSERSTOREPATHS@
# The timeout for reconnecting on non-server spdk sockets when the remote end goes away.
# qemu will delay this many seconds and then attempt to reconnect.
# Zero disables reconnecting, and the default is zero.
vhost_user_reconnect_timeout_sec = 0
# Enable file based guest memory support. The default is an empty string which
# will disable this feature. In the case of virtio-fs, this is enabled
# automatically and '/dev/shm' is used as the backing folder.
# This option will be ignored if VM templating is enabled.
#file_mem_backend = "@DEFFILEMEMBACKEND@"
# List of valid annotations values for the file_mem_backend annotation
# The default if not set is empty (all annotations rejected.)
# Your distribution recommends: @DEFVALIDFILEMEMBACKENDS@
valid_file_mem_backends = @DEFVALIDFILEMEMBACKENDS@
# -pflash can add image file to VM. The arguments of it should be in format
# of ["/path/to/flash0.img", "/path/to/flash1.img"]
pflashes = []
# This option changes the default hypervisor and kernel parameters
# to enable debug output where available. And Debug also enable the hmp socket.
#
# Default false
#enable_debug = true
# Disable the customizations done in the runtime when it detects
# that it is running on top a VMM. This will result in the runtime
# behaving as it would when running on bare metal.
#
#disable_nesting_checks = true
# This is the msize used for 9p shares. It is the number of bytes
# used for 9p packet payload.
#msize_9p = @DEFMSIZE9P@
# If false and nvdimm is supported, use nvdimm device to plug guest image.
# Otherwise virtio-block device is used.
#
# nvdimm is not supported when `confidential_guest = true`.
#
# Default is false
#disable_image_nvdimm = true
# VFIO devices are hotplugged on a bridge by default.
# Enable hotplugging on root bus. This may be required for devices with
# a large PCI bar, as this is a current limitation with hotplugging on
# a bridge.
# Default false
hotplug_vfio_on_root_bus = true
# Before hot plugging a PCIe device, you need to add a pcie_root_port device.
# Use this parameter when using some large PCI bar devices, such as Nvidia GPU
# The value means the number of pcie_root_port
# This value is valid when hotplug_vfio_on_root_bus is true and machine_type is "q35"
# Default 0
pcie_root_port = 1
# If vhost-net backend for virtio-net is not desired, set to true. Default is false, which trades off
# security (vhost-net runs ring0) for network I/O performance.
#disable_vhost_net = true
#
# Default entropy source.
# The path to a host source of entropy (including a real hardware RNG)
# /dev/urandom and /dev/random are two main options.
# Be aware that /dev/random is a blocking source of entropy. If the host
# runs out of entropy, the VMs boot time will increase leading to get startup
# timeouts.
# The source of entropy /dev/urandom is non-blocking and provides a
# generally acceptable source of entropy. It should work well for pretty much
# all practical purposes.
#entropy_source= "@DEFENTROPYSOURCE@"
# List of valid annotations values for entropy_source
# The default if not set is empty (all annotations rejected.)
# Your distribution recommends: @DEFVALIDENTROPYSOURCES@
valid_entropy_sources = @DEFVALIDENTROPYSOURCES@
# Path to OCI hook binaries in the *guest rootfs*.
# This does not affect host-side hooks which must instead be added to
# the OCI spec passed to the runtime.
#
# You can create a rootfs with hooks by customizing the osbuilder scripts:
# https://github.com/kata-containers/kata-containers/tree/main/tools/osbuilder
#
# Hooks must be stored in a subdirectory of guest_hook_path according to their
# hook type, i.e. "guest_hook_path/{prestart,poststart,poststop}".
# The agent will scan these directories for executable files and add them, in
# lexicographical order, to the lifecycle of the guest container.
# Hooks are executed in the runtime namespace of the guest. See the official documentation:
# https://github.com/opencontainers/runtime-spec/blob/v1.0.1/config.md#posix-platform-hooks
# Warnings will be logged if any error is encountered while scanning for hooks,
# but it will not abort container execution.
guest_hook_path = "/etc/oci/hooks.d"
#
# Use rx Rate Limiter to control network I/O inbound bandwidth(size in bits/sec for SB/VM).
# In Qemu, we use classful qdiscs HTB(Hierarchy Token Bucket) to discipline traffic.
# Default 0-sized value means unlimited rate.
#rx_rate_limiter_max_rate = 0
# Use tx Rate Limiter to control network I/O outbound bandwidth(size in bits/sec for SB/VM).
# In Qemu, we use classful qdiscs HTB(Hierarchy Token Bucket) and ifb(Intermediate Functional Block)
# to discipline traffic.
# Default 0-sized value means unlimited rate.
#tx_rate_limiter_max_rate = 0
# Set where to save the guest memory dump file.
# If set, when GUEST_PANICKED event occurred,
# guest memeory will be dumped to host filesystem under guest_memory_dump_path,
# This directory will be created automatically if it does not exist.
#
# The dumped file(also called vmcore) can be processed with crash or gdb.
#
# WARNING:
# Dump guests memory can take very long depending on the amount of guest memory
# and use much disk space.
#guest_memory_dump_path="/var/crash/kata"
# If enable paging.
# Basically, if you want to use "gdb" rather than "crash",
# or need the guest-virtual addresses in the ELF vmcore,
# then you should enable paging.
#
# See: https://www.qemu.org/docs/master/qemu-qmp-ref.html#Dump-guest-memory for details
#guest_memory_dump_paging=false
# Enable swap in the guest. Default false.
# When enable_guest_swap is enabled, insert a raw file to the guest as the swap device
# if the swappiness of a container (set by annotation "io.katacontainers.container.resource.swappiness")
# is bigger than 0.
# The size of the swap device should be
# swap_in_bytes (set by annotation "io.katacontainers.container.resource.swap_in_bytes") - memory_limit_in_bytes.
# If swap_in_bytes is not set, the size should be memory_limit_in_bytes.
# If swap_in_bytes and memory_limit_in_bytes is not set, the size should
# be default_memory.
#enable_guest_swap = true
# use legacy serial for guest console if available and implemented for architecture. Default false
#use_legacy_serial = true
# disable applying SELinux on the VMM process (default false)
disable_selinux=@DEFDISABLESELINUX@
# disable applying SELinux on the container process
# If set to false, the type `container_t` is applied to the container process by default.
# Note: To enable guest SELinux, the guest rootfs must be CentOS that is created and built
# with `SELINUX=yes`.
# (default: true)
disable_guest_selinux=@DEFDISABLEGUESTSELINUX@
[factory]
# VM templating support. Once enabled, new VMs are created from template
# using vm cloning. They will share the same initial kernel, initramfs and
# agent memory by mapping it readonly. It helps speeding up new container
# creation and saves a lot of memory if there are many kata containers running
# on the same host.
#
# When disabled, new VMs are created from scratch.
#
# Note: Requires "initrd=" to be set ("image=" is not supported).
#
# Default false
#enable_template = true
# Specifies the path of template.
#
# Default "/run/vc/vm/template"
#template_path = "/run/vc/vm/template"
# The number of caches of VMCache:
# unspecified or == 0 --> VMCache is disabled
# > 0 --> will be set to the specified number
#
# VMCache is a function that creates VMs as caches before using it.
# It helps speed up new container creation.
# The function consists of a server and some clients communicating
# through Unix socket. The protocol is gRPC in protocols/cache/cache.proto.
# The VMCache server will create some VMs and cache them by factory cache.
# It will convert the VM to gRPC format and transport it when gets
# requestion from clients.
# Factory grpccache is the VMCache client. It will request gRPC format
# VM and convert it back to a VM. If VMCache function is enabled,
# kata-runtime will request VM from factory grpccache when it creates
# a new sandbox.
#
# Default 0
#vm_cache_number = 0
# Specify the address of the Unix socket that is used by VMCache.
#
# Default /var/run/kata-containers/cache.sock
#vm_cache_endpoint = "/var/run/kata-containers/cache.sock"
[agent.@PROJECT_TYPE@]
# If enabled, make the agent display debug-level messages.
# (default: disabled)
#enable_debug = true
# Enable agent tracing.
#
# If enabled, the agent will generate OpenTelemetry trace spans.
#
# Notes:
#
# - If the runtime also has tracing enabled, the agent spans will be
# associated with the appropriate runtime parent span.
# - If enabled, the runtime will wait for the container to shutdown,
# increasing the container shutdown time slightly.
#
# (default: disabled)
#enable_tracing = true
# Comma separated list of kernel modules and their parameters.
# These modules will be loaded in the guest kernel using modprobe(8).
# The following example can be used to load two kernel modules with parameters
# - kernel_modules=["e1000e InterruptThrottleRate=3000,3000,3000 EEE=1", "i915 enable_ppgtt=0"]
# The first word is considered as the module name and the rest as its parameters.
# Container will not be started when:
# * A kernel module is specified and the modprobe command is not installed in the guest
# or it fails loading the module.
# * The module is not available in the guest or it doesn't met the guest kernel
# requirements, like architecture and version.
#
kernel_modules=[]
# Enable debug console.
# If enabled, user can connect guest OS running inside hypervisor
# through "kata-runtime exec <sandbox-id>" command
#debug_console_enabled = true
# Agent connection dialing timeout value in seconds
# (default: 30)
#dial_timeout = 30
[runtime]
# If enabled, the runtime will log additional debug messages to the
# system log
# (default: disabled)
#enable_debug = true
#
# Internetworking model
# Determines how the VM should be connected to the
# the container network interface
# Options:
#
# - macvtap
# Used when the Container network interface can be bridged using
# macvtap.
#
# - none
# Used when customize network. Only creates a tap device. No veth pair.
#
# - tcfilter
# Uses tc filter rules to redirect traffic from the network interface
# provided by plugin to a tap interface connected to the VM.
#
internetworking_model="@DEFNETWORKMODEL_QEMU@"
# disable guest seccomp
# Determines whether container seccomp profiles are passed to the virtual
# machine and applied by the kata agent. If set to true, seccomp is not applied
# within the guest
# (default: true)
disable_guest_seccomp=@DEFDISABLEGUESTSECCOMP@
# vCPUs pinning settings
# if enabled, each vCPU thread will be scheduled to a fixed CPU
# qualified condition: num(vCPU threads) == num(CPUs in sandbox's CPUSet)
# enable_vcpus_pinning = false
# Apply a custom SELinux security policy to the container process inside the VM.
# This is used when you want to apply a type other than the default `container_t`,
# so general users should not uncomment and apply it.
# (format: "user:role:type")
# Note: You cannot specify MCS policy with the label because the sensitivity levels and
# categories are determined automatically by high-level container runtimes such as containerd.
#guest_selinux_label="@DEFGUESTSELINUXLABEL@"
# If enabled, the runtime will create opentracing.io traces and spans.
# (See https://www.jaegertracing.io/docs/getting-started).
# (default: disabled)
#enable_tracing = true
# Set the full url to the Jaeger HTTP Thrift collector.
# The default if not set will be "http://localhost:14268/api/traces"
#jaeger_endpoint = ""
# Sets the username to be used if basic auth is required for Jaeger.
#jaeger_user = ""
# Sets the password to be used if basic auth is required for Jaeger.
#jaeger_password = ""
# If enabled, the runtime will not create a network namespace for shim and hypervisor processes.
# This option may have some potential impacts to your host. It should only be used when you know what you're doing.
# `disable_new_netns` conflicts with `internetworking_model=tcfilter` and `internetworking_model=macvtap`. It works only
# with `internetworking_model=none`. The tap device will be in the host network namespace and can connect to a bridge
# (like OVS) directly.
# (default: false)
#disable_new_netns = true
# if enabled, the runtime will add all the kata processes inside one dedicated cgroup.
# The container cgroups in the host are not created, just one single cgroup per sandbox.
# The runtime caller is free to restrict or collect cgroup stats of the overall Kata sandbox.
# The sandbox cgroup path is the parent cgroup of a container with the PodSandbox annotation.
# The sandbox cgroup is constrained if there is no container type annotation.
# See: https://pkg.go.dev/github.com/kata-containers/kata-containers/src/runtime/virtcontainers#ContainerType
sandbox_cgroup_only=@DEFSANDBOXCGROUPONLY@
# If enabled, the runtime will attempt to determine appropriate sandbox size (memory, CPU) before booting the virtual machine. In
# this case, the runtime will not dynamically update the amount of memory and CPU in the virtual machine. This is generally helpful
# when a hardware architecture or hypervisor solutions is utilized which does not support CPU and/or memory hotplug.
# Compatibility for determining appropriate sandbox (VM) size:
# - When running with pods, sandbox sizing information will only be available if using Kubernetes >= 1.23 and containerd >= 1.6. CRI-O
# does not yet support sandbox sizing annotations.
# - When running single containers using a tool like ctr, container sizing information will be available.
static_sandbox_resource_mgmt=@DEFSTATICRESOURCEMGMT@
# If specified, sandbox_bind_mounts identifieds host paths to be mounted (ro) into the sandboxes shared path.
# This is only valid if filesystem sharing is utilized. The provided path(s) will be bindmounted into the shared fs directory.
# If defaults are utilized, these mounts should be available in the guest at `/run/kata-containers/shared/containers/sandbox-mounts`
# These will not be exposed to the container workloads, and are only provided for potential guest services.
sandbox_bind_mounts=@DEFBINDMOUNTS@
# VFIO Mode
# Determines how VFIO devices should be be presented to the container.
# Options:
#
# - vfio
# Matches behaviour of OCI runtimes (e.g. runc) as much as
# possible. VFIO devices will appear in the container as VFIO
# character devices under /dev/vfio. The exact names may differ
# from the host (they need to match the VM's IOMMU group numbers
# rather than the host's)
#
# - guest-kernel
# This is a Kata-specific behaviour that's useful in certain cases.
# The VFIO device is managed by whatever driver in the VM kernel
# claims it. This means it will appear as one or more device nodes
# or network interfaces depending on the nature of the device.
# Using this mode requires specially built workloads that know how
# to locate the relevant device interfaces within the VM.
#
vfio_mode="@DEFVFIOMODE@"
# If enabled, the runtime will not create Kubernetes emptyDir mounts on the guest filesystem. Instead, emptyDir mounts will
# 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@
# 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.
# Supported experimental features:
# (default: [])
experimental=@DEFAULTEXPFEATURES@
# If enabled, user can run pprof tools with shim v2 process through kata-monitor.
# (default: false)
# enable_pprof = true
# WARNING: All the options in the following section have not been implemented yet.
# This section was added as a placeholder. DO NOT USE IT!
[image]
# Container image service.
#
# Offload the CRI image management service to the Kata agent.
# (default: false)
#service_offload = true
# Container image decryption keys provisioning.
# Applies only if service_offload is true.
# Keys can be provisioned locally (e.g. through a special command or
# a local file) or remotely (usually after the guest is remotely attested).
# The provision setting is a complete URL that lets the Kata agent decide
# which method to use in order to fetch the keys.
#
# Keys can be stored in a local file, in a measured and attested initrd:
#provision=data:///local/key/file
#
# Keys could be fetched through a special command or binary from the
# initrd (guest) image, e.g. a firmware call:
#provision=file:///path/to/bin/fetcher/in/guest
#
# Keys can be remotely provisioned. The Kata agent fetches them from e.g.
# a HTTPS URL:
#provision=https://my-key-broker.foo/tenant/<tenant-id>

View File

@@ -14,9 +14,16 @@
[hypervisor.qemu]
path = "@QEMUTDXPATH@"
kernel = "@KERNELTDXPATH@"
image = "@IMAGETDXPATH@"
image = "@IMAGEPATH@"
# initrd = "@INITRDPATH@"
machine_type = "@MACHINETYPE@"
# rootfs filesystem type:
# - ext4 (default)
# - xfs
# - erofs
rootfs_type=@DEFROOTFSTYPE@
# Enable confidential guest support.
# Toggling that setting may trigger different hardware features, ranging
# from memory encryption to both memory and CPU-state encryption and integrity.
@@ -59,17 +66,17 @@ valid_hypervisor_paths = @QEMUTDXVALIDHYPERVISORPATHS@
# may stop the virtual machine from booting.
# To see the list of default parameters, enable hypervisor debug, create a
# container and look for 'default-kernel-parameters' log entries.
kernel_params = "@TDXKERNELPARAMS_QEMU@"
kernel_params = "@KERNELTDXPARAMS@"
# Path to the firmware.
# If you want that qemu uses the default firmware leave this option empty
firmware = "@TDVFFIRMWAREPATH@"
firmware = "@FIRMWARETDVFPATH@"
# Path to the firmware volume.
# firmware TDVF or OVMF can be split into FIRMWARE_VARS.fd (UEFI variables
# as configuration) and FIRMWARE_CODE.fd (UEFI program image). UEFI variables
# can be customized per each user while UEFI code is kept same.
firmware_volume = "@TDVFFIRMWAREVOLUMEPATH@"
firmware_volume = "@FIRMWARETDVFVOLUMEPATH@"
# Machine accelerators
# comma-separated list of machine accelerators to pass to the hypervisor.
@@ -165,7 +172,7 @@ disable_block_device_use = @DEFDISABLEBLOCK@
# - virtio-fs (default)
# - virtio-9p
# - virtio-fs-nydus
shared_fs = "@DEFSHAREDFS_QEMU_VIRTIOFS@"
shared_fs = "@DEFSHAREDFS_QEMU_TDX_VIRTIOFS@"
# Path to vhost-user-fs daemon.
virtio_fs_daemon = "@DEFVIRTIOFSDAEMON@"
@@ -178,6 +185,9 @@ valid_virtio_fs_daemon_paths = @DEFVALIDVIRTIOFSDAEMONPATHS@
# Default size of DAX cache in MiB
virtio_fs_cache_size = @DEFVIRTIOFSCACHESIZE@
# Default size of virtqueues
virtio_fs_queue_size = @DEFVIRTIOFSQUEUESIZE@
# Extra args for virtiofsd daemon
#
# Format example:
@@ -190,7 +200,7 @@ virtio_fs_extra_args = @DEFVIRTIOFSEXTRAARGS@
# Cache mode:
#
# - none
# - never
# Metadata, data, and pathname lookup are not cached in guest. They are
# always fetched from host and any changes are immediately pushed to host.
#
@@ -208,6 +218,20 @@ virtio_fs_cache = "@DEFVIRTIOFSCACHE@"
# or nvdimm.
block_device_driver = "@DEFBLOCKSTORAGEDRIVER_QEMU@"
# aio is the I/O mechanism used by qemu
# Options:
#
# - threads
# Pthread based disk I/O.
#
# - native
# Native Linux I/O.
#
# - io_uring
# Linux io_uring API. This provides the fastest I/O operations on Linux, requires kernel>5.1 and
# qemu >=5.0.
block_device_aio = "@DEFBLOCKDEVICEAIO_QEMU@"
# Specifies cache-related options will be set to block devices or not.
# Default false
#block_device_cache_set = true
@@ -271,6 +295,11 @@ vhost_user_store_path = "@DEFVHOSTUSERSTOREPATH@"
# Your distribution recommends: @DEFVALIDVHOSTUSERSTOREPATHS@
valid_vhost_user_store_paths = @DEFVALIDVHOSTUSERSTOREPATHS@
# The timeout for reconnecting on non-server spdk sockets when the remote end goes away.
# qemu will delay this many seconds and then attempt to reconnect.
# Zero disables reconnecting, and the default is zero.
vhost_user_reconnect_timeout_sec = 0
# Enable file based guest memory support. The default is an empty string which
# will disable this feature. In the case of virtio-fs, this is enabled
# automatically and '/dev/shm' is used as the backing folder.
@@ -287,7 +316,7 @@ valid_file_mem_backends = @DEFVALIDFILEMEMBACKENDS@
pflashes = []
# This option changes the default hypervisor and kernel parameters
# to enable debug output where available.
# to enable debug output where available. And Debug also enable the hmp socket.
#
# Default false
#enable_debug = true
@@ -499,8 +528,8 @@ kernel_modules=[]
#debug_console_enabled = true
# Agent connection dialing timeout value in seconds
# (default: 30)
#dial_timeout = 30
# (default: 60)
dial_timeout = 60
[runtime]
# If enabled, the runtime will log additional debug messages to the
@@ -533,6 +562,11 @@ internetworking_model="@DEFNETWORKMODEL_QEMU@"
# (default: true)
disable_guest_seccomp=@DEFDISABLEGUESTSECCOMP@
# vCPUs pinning settings
# if enabled, each vCPU thread will be scheduled to a fixed CPU
# qualified condition: num(vCPU threads) == num(CPUs in sandbox's CPUSet)
# enable_vcpus_pinning = false
# Apply a custom SELinux security policy to the container process inside the VM.
# This is used when you want to apply a type other than the default `container_t`,
# so general users should not uncomment and apply it.
@@ -630,7 +664,7 @@ experimental=@DEFAULTEXPFEATURES@
#
# Offload the CRI image management service to the Kata agent.
# (default: false)
service_offload = @DEFSERVICEOFFLOAD@
#service_offload = true
# Container image decryption keys provisioning.
# Applies only if service_offload is true.

View File

@@ -563,8 +563,8 @@ kernel_modules=[]
#debug_console_enabled = true
# Agent connection dialing timeout value in seconds
# (default: 30)
#dial_timeout = 30
# (default: 45)
dial_timeout = 45
[runtime]
# If enabled, the runtime will log additional debug messages to the

View File

@@ -243,7 +243,7 @@ func (s *service) genericIPTablesHandler(w http.ResponseWriter, r *http.Request,
func (s *service) startManagementServer(ctx context.Context, ociSpec *specs.Spec) {
// metrics socket will under sandbox's bundle path
metricsAddress := SocketAddress(s.id)
metricsAddress := ServerSocketAddress(s.id)
listener, err := cdshim.NewSocket(metricsAddress)
if err != nil {
@@ -312,14 +312,38 @@ func GetSandboxesStoragePathRust() string {
return "/run/kata"
}
// SocketAddress returns the address of the unix domain socket for communicating with the
// SocketPath returns the path of the socket using the given storagePath
func SocketPath(id string, storagePath string) string {
return filepath.Join(string(filepath.Separator), storagePath, id, "shim-monitor.sock")
}
// SocketPathGo returns the path of the socket to be used with the go runtime
func SocketPathGo(id string) string {
return SocketPath(id, GetSandboxesStoragePath())
}
// SocketPathRust returns the path of the socket to be used with the rust runtime
func SocketPathRust(id string) string {
return SocketPath(id, GetSandboxesStoragePathRust())
}
// ServerSocketAddress returns the address of the unix domain socket the shim management endpoint
// should listen.
// NOTE: this code is only called by the go shim management implementation.
func ServerSocketAddress(id string) string {
return fmt.Sprintf("unix://%s", SocketPathGo(id))
}
// ClientSocketAddress returns the address of the unix domain socket for communicating with the
// shim management endpoint
func SocketAddress(id string) string {
// NOTE: this code allows various go clients, e.g. kata-runtime or kata-monitor commands, to
// connect to the rust shim management implementation.
func ClientSocketAddress(id string) string {
// get the go runtime uds path
socketPath := filepath.Join(string(filepath.Separator), GetSandboxesStoragePath(), id, "shim-monitor.sock")
socketPath := SocketPathGo(id)
// if the path not exist, use the rust runtime uds path instead
if _, err := os.Stat(socketPath); err != nil {
return fmt.Sprintf("unix://%s", filepath.Join(string(filepath.Separator), GetSandboxesStoragePathRust(), id, "shim-monitor.sock"))
socketPath = SocketPathRust(id)
}
return fmt.Sprintf("unix://%s", socketPath)
}

View File

@@ -54,6 +54,25 @@ func NewVFIODevice(devInfo *config.DeviceInfo) *VFIODevice {
}
}
// Ignore specific PCI devices, supply the pciClass and the bitmask to check
// against the device class, deviceBDF for meaningfull info message
func (device *VFIODevice) checkIgnorePCIClass(pciClass string, deviceBDF string, bitmask uint64) (bool, error) {
if pciClass == "" {
return false, nil
}
pciClassID, err := strconv.ParseUint(pciClass, 0, 32)
if err != nil {
return false, err
}
// ClassID is 16 bits, remove the two trailing zeros
pciClassID = pciClassID >> 8
if pciClassID&bitmask == bitmask {
deviceLogger().Infof("Ignoring PCI (Host) Bridge deviceBDF %v Class %x", deviceBDF, pciClassID)
return true, nil
}
return false, nil
}
// Attach is standard interface of api.Device, it's used to add device to some
// DeviceReceiver
func (device *VFIODevice) Attach(ctx context.Context, devReceiver api.DeviceReceiver) (retErr error) {
@@ -88,6 +107,18 @@ func (device *VFIODevice) Attach(ctx context.Context, devReceiver api.DeviceRece
}
id := utils.MakeNameID("vfio", device.DeviceInfo.ID+strconv.Itoa(i), maxDevIDSize)
pciClass := getPCIDeviceProperty(deviceBDF, PCISysFsDevicesClass)
// We need to ignore Host or PCI Bridges that are in the same IOMMU group as the
// passed-through devices. One CANNOT pass-through a PCI bridge or Host bridge.
// Class 0x0604 is PCI bridge, 0x0600 is Host bridge
ignorePCIDevice, err := device.checkIgnorePCIClass(pciClass, deviceBDF, 0x0600)
if err != nil {
return err
}
if ignorePCIDevice {
continue
}
var vfio config.VFIODev
switch vfioDeviceType {
@@ -100,7 +131,7 @@ func (device *VFIODevice) Attach(ctx context.Context, devReceiver api.DeviceRece
BDF: deviceBDF,
SysfsDev: deviceSysfsDev,
IsPCIe: isPCIe,
Class: getPCIDeviceProperty(deviceBDF, PCISysFsDevicesClass),
Class: pciClass,
}
if isPCIe {
vfioPCI.Bus = fmt.Sprintf("%s%d", pcieRootPortPrefix, len(AllPCIeDevs))
@@ -121,6 +152,7 @@ func (device *VFIODevice) Attach(ctx context.Context, devReceiver api.DeviceRece
default:
return fmt.Errorf("Failed to append device: VFIO device type unrecognized")
}
device.VfioDevs = append(device.VfioDevs, &vfio)
}

View File

@@ -363,16 +363,12 @@ func (object Object) QemuParams(config *Config) []string {
case TDXGuest:
objectParams = append(objectParams, string(object.Type))
objectParams = append(objectParams, "sept-ve-disable=on")
objectParams = append(objectParams, fmt.Sprintf("id=%s", object.ID))
if object.Debug {
objectParams = append(objectParams, "debug=on")
}
deviceParams = append(deviceParams, string(object.Driver))
deviceParams = append(deviceParams, fmt.Sprintf("id=%s", object.DeviceID))
deviceParams = append(deviceParams, fmt.Sprintf("file=%s", object.File))
if object.FirmwareVolume != "" {
deviceParams = append(deviceParams, fmt.Sprintf("config-firmware-volume=%s", object.FirmwareVolume))
}
config.Bios = object.File
case SEVGuest:
objectParams = append(objectParams, string(object.Type))
objectParams = append(objectParams, fmt.Sprintf("id=%s", object.ID))

View File

@@ -114,25 +114,32 @@ func (km *KataMonitor) ProcessMetricsRequest(w http.ResponseWriter, r *http.Requ
writer = gz
}
// create encoder to encode metrics.
encoder := expfmt.NewEncoder(writer, contentType)
// gather metrics collected for management agent.
mfs, err := prometheus.DefaultGatherer.Gather()
filterFamilies, err := getFilterFamilyFromReq(r)
if err != nil {
monitorLog.WithError(err).Error("failed to Gather metrics from prometheus.DefaultGatherer")
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
// encode metric gathered in current process
if err := encodeMetricFamily(mfs, encoder); err != nil {
monitorLog.WithError(err).Warnf("failed to encode metrics")
// create encoder to encode metrics.
encoder := expfmt.NewEncoder(writer, contentType)
if len(filterFamilies) == 0 {
// gather metrics collected for management agent.
mfs, err := prometheus.DefaultGatherer.Gather()
if err != nil {
monitorLog.WithError(err).Error("failed to Gather metrics from prometheus.DefaultGatherer")
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
// encode metric gathered in current process
if err := encodeMetricFamily(mfs, encoder); err != nil {
monitorLog.WithError(err).Warnf("failed to encode metrics")
}
}
// aggregate sandboxes metrics and write to response by encoder
if err := km.aggregateSandboxMetrics(encoder); err != nil {
if err := km.aggregateSandboxMetrics(encoder, filterFamilies); err != nil {
monitorLog.WithError(err).Errorf("failed aggregateSandboxMetrics")
scrapeFailedCount.Inc()
}
@@ -155,7 +162,7 @@ func encodeMetricFamily(mfs []*dto.MetricFamily, encoder expfmt.Encoder) error {
}
// aggregateSandboxMetrics will get metrics from one sandbox and do some process
func (km *KataMonitor) aggregateSandboxMetrics(encoder expfmt.Encoder) error {
func (km *KataMonitor) aggregateSandboxMetrics(encoder expfmt.Encoder, filterFamilies []string) error {
// get all kata sandboxes from cache
sandboxes := km.sandboxCache.getSandboxList()
// save running kata pods as a metrics.
@@ -230,9 +237,21 @@ func (km *KataMonitor) aggregateSandboxMetrics(encoder expfmt.Encoder) error {
}
// write metrics to response.
for _, mf := range metricsMap {
if err := encoder.Encode(mf); err != nil {
return err
if len(filterFamilies) > 0 {
for _, filterName := range filterFamilies {
for fullName, mf := range metricsMap {
if strings.HasPrefix(fullName, filterName) {
if err := encoder.Encode(mf); err != nil {
return err
}
}
}
}
} else {
for _, mf := range metricsMap {
if err := encoder.Encode(mf); err != nil {
return err
}
}
}
return nil

View File

@@ -32,7 +32,7 @@ func (km *KataMonitor) composeSocketAddress(r *http.Request) (string, error) {
return "", err
}
return shim.SocketAddress(sandbox), nil
return shim.ClientSocketAddress(sandbox), nil
}
func (km *KataMonitor) proxyRequest(w http.ResponseWriter, r *http.Request,

View File

@@ -8,6 +8,7 @@ package katamonitor
import (
"fmt"
"net/http"
"strings"
"time"
shim "github.com/kata-containers/kata-containers/src/runtime/pkg/containerd-shim-v2"
@@ -36,3 +37,11 @@ func getSandboxIDFromReq(r *http.Request) (string, error) {
func getSandboxFS() string {
return shim.GetSandboxesStoragePath()
}
func getFilterFamilyFromReq(r *http.Request) ([]string, error) {
filterFamilies := r.URL.Query().Get("filter_family")
if filterFamilies != "" {
return strings.Split(filterFamilies, ","), nil
}
return nil, nil
}

View File

@@ -786,6 +786,16 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
kataUtilsLogger.Info("Setting 'disable_image_nvdimm = true' as microvm does not support NVDIMM")
}
// Nvdimm can only be support when UEFI/ACPI is enabled on arm64, otherwise disable it.
if goruntime.GOARCH == "arm64" && firmware == "" {
if p, err := h.PFlash(); err == nil {
if len(p) == 0 {
h.DisableImageNvdimm = true
kataUtilsLogger.Info("Setting 'disable_image_nvdimm = true' if there is no firmware specified")
}
}
}
blockDriver, err := h.blockDeviceDriver()
if err != nil {
return vc.HypervisorConfig{}, err
@@ -1071,6 +1081,7 @@ func newClhHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
EnableAnnotations: h.EnableAnnotations,
DisableSeccomp: h.DisableSeccomp,
ConfidentialGuest: h.ConfidentialGuest,
Rootless: h.Rootless,
DisableSeLinux: h.DisableSeLinux,
DisableGuestSeLinux: h.DisableGuestSeLinux,
NetRateLimiterBwMaxRate: h.getNetRateLimiterBwMaxRate(),

View File

@@ -13,6 +13,7 @@ import (
"path"
"path/filepath"
"reflect"
goruntime "runtime"
"strings"
"syscall"
"testing"
@@ -182,6 +183,10 @@ func createAllRuntimeConfigFiles(dir, hypervisor string) (config testRuntimeConf
SNPGuestPolicy: defaultSNPGuestPolicy,
}
if goruntime.GOARCH == "arm64" && len(hypervisorConfig.PFlash) == 0 && hypervisorConfig.FirmwarePath == "" {
hypervisorConfig.DisableImageNvdimm = true
}
agentConfig := vc.KataAgentConfig{
LongLiveConn: true,
}

View File

@@ -19,7 +19,7 @@ import (
// BuildShimClient builds and returns an http client for communicating with the provided sandbox
func BuildShimClient(sandboxID string, timeout time.Duration) (*http.Client, error) {
return buildUnixSocketClient(shim.SocketAddress(sandboxID), timeout)
return buildUnixSocketClient(shim.ClientSocketAddress(sandboxID), timeout)
}
// buildUnixSocketClient build http client for Unix socket

View File

@@ -19,6 +19,7 @@ import (
"net/http/httputil"
"os"
"os/exec"
"os/user"
"path/filepath"
"regexp"
"strconv"
@@ -37,6 +38,8 @@ import (
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/config"
hv "github.com/kata-containers/kata-containers/src/runtime/pkg/hypervisors"
"github.com/kata-containers/kata-containers/src/runtime/pkg/katautils/katatrace"
pkgUtils "github.com/kata-containers/kata-containers/src/runtime/pkg/utils"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/rootless"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
)
@@ -653,7 +656,7 @@ func (clh *cloudHypervisor) StartVM(ctx context.Context, timeout int) error {
clh.Logger().WithField("function", "StartVM").Info("starting Sandbox")
vmPath := filepath.Join(clh.config.VMStorePath, clh.id)
err := os.MkdirAll(vmPath, DirMode)
err := utils.MkdirAllWithInheritedOwner(vmPath, DirMode)
if err != nil {
return err
}
@@ -1364,9 +1367,16 @@ func (clh *cloudHypervisor) launchClh() (int, error) {
cmdHypervisor.Stdout = clh.console
}
}
cmdHypervisor.Stderr = cmdHypervisor.Stdout
attr := syscall.SysProcAttr{}
attr.Credential = &syscall.Credential{
Uid: clh.config.Uid,
Gid: clh.config.Gid,
Groups: clh.config.Groups,
}
cmdHypervisor.SysProcAttr = &attr
err = utils.StartCmd(cmdHypervisor)
if err != nil {
return -1, err
@@ -1691,6 +1701,30 @@ func (clh *cloudHypervisor) cleanupVM(force bool) error {
clh.Logger().WithError(err).WithField("path", dir).Warnf("failed to remove vm path")
}
}
if rootless.IsRootless() {
if _, err := user.Lookup(clh.config.User); err != nil {
clh.Logger().WithError(err).WithFields(
log.Fields{
"user": clh.config.User,
"uid": clh.config.Uid,
}).Warn("failed to find the user, it might have been removed")
return nil
}
if err := pkgUtils.RemoveVmmUser(clh.config.User); err != nil {
clh.Logger().WithError(err).WithFields(
log.Fields{
"user": clh.config.User,
"uid": clh.config.Uid,
}).Warn("failed to delete the user")
return nil
}
clh.Logger().WithFields(
log.Fields{
"user": clh.config.User,
"uid": clh.config.Uid,
}).Debug("successfully removed the non root user")
}
clh.reset()

View File

@@ -8,15 +8,28 @@ package virtcontainers
import "os"
const (
tdxSysFirmwareDir = "/sys/firmware/tdx_seam/"
tdxSeamSysFirmwareDir = "/sys/firmware/tdx_seam/"
tdxCPUFlag = "tdx"
tdxSysFirmwareDir = "/sys/firmware/tdx/"
sevKvmParameterPath = "/sys/module/kvm_amd/parameters/sev"
snpKvmParameterPath = "/sys/module/kvm_amd/parameters/sev_snp"
)
// TDX is supported and properly loaded when the firmware directory (either tdx or tdx_seam) exists or `tdx` is part of the CPU flag
func checkTdxGuestProtection(flags map[string]bool) bool {
if d, err := os.Stat(tdxSysFirmwareDir); err == nil && d.IsDir() {
return true
}
if d, err := os.Stat(tdxSeamSysFirmwareDir); err == nil && d.IsDir() {
return true
}
return false
}
// Implementation of this function is architecture specific
func availableGuestProtection() (guestProtection, error) {
flags, err := CPUFlags(procCPUInfo)
@@ -24,10 +37,10 @@ func availableGuestProtection() (guestProtection, error) {
return noneProtection, err
}
// TDX is supported and properly loaded when the firmware directory exists or `tdx` is part of the CPU flags
if d, err := os.Stat(tdxSysFirmwareDir); (err == nil && d.IsDir()) || flags[tdxCPUFlag] {
if checkTdxGuestProtection(flags) {
return tdxProtection, nil
}
// SEV-SNP is supported and enabled when the kvm module `sev_snp` parameter is set to `Y`
// SEV-SNP support infers SEV (-ES) support
if _, err := os.Stat(snpKvmParameterPath); err == nil {

View File

@@ -157,7 +157,7 @@ func (nd *nydusd) args() ([]string, error) {
logLevel = "debug"
}
args := []string{
"virtiofs", "--hybrid-mode",
"virtiofs",
"--log-level", logLevel,
"--apisock", nd.apiSockPath,
"--sock", nd.sockPath,

View File

@@ -99,13 +99,13 @@ func TestNydusdArgs(t *testing.T) {
apiSockPath: "/var/lib/api.sock",
debug: true,
}
expected := "virtiofs --hybrid-mode --log-level debug --apisock /var/lib/api.sock --sock /var/lib/vhost-user.sock"
expected := "virtiofs --log-level debug --apisock /var/lib/api.sock --sock /var/lib/vhost-user.sock"
args, err := nd.args()
assert.NoError(err)
assert.Equal(expected, strings.Join(args, " "))
nd.debug = false
expected = "virtiofs --hybrid-mode --log-level info --apisock /var/lib/api.sock --sock /var/lib/vhost-user.sock"
expected = "virtiofs --log-level info --apisock /var/lib/api.sock --sock /var/lib/vhost-user.sock"
args, err = nd.args()
assert.NoError(err)
assert.Equal(expected, strings.Join(args, " "))

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