Skip to content

Instantly share code, notes, and snippets.

@bpradipt
Last active January 23, 2023 14:16
Show Gist options
  • Save bpradipt/e7635b35b2e21204e7ce4f5408303957 to your computer and use it in GitHub Desktop.
Save bpradipt/e7635b35b2e21204e7ce4f5408303957 to your computer and use it in GitHub Desktop.
ccv0 patch for stable-2.5
This file has been truncated, but you can view the full file.
diff --git a/.github/workflows/cargo-deny-runner.yaml b/.github/workflows/cargo-deny-runner.yaml
index 5d6dfeb6c..65237c7be 100644
--- a/.github/workflows/cargo-deny-runner.yaml
+++ b/.github/workflows/cargo-deny-runner.yaml
@@ -1,5 +1,12 @@
name: Cargo Crates Check Runner
-on: [pull_request]
+on:
+ pull_request:
+ types:
+ - opened
+ - edited
+ - reopened
+ - synchronize
+ paths-ignore: [ '**.md', '**.png', '**.jpg', '**.jpeg', '**.svg', '/docs/**' ]
jobs:
cargo-deny-runner:
runs-on: ubuntu-latest
diff --git a/.github/workflows/cc-payload-after-push-amd64.yaml b/.github/workflows/cc-payload-after-push-amd64.yaml
new file mode 100644
index 000000000..447d0135e
--- /dev/null
+++ b/.github/workflows/cc-payload-after-push-amd64.yaml
@@ -0,0 +1,159 @@
+name: CI | Publish CC runtime payload for amd64
+on:
+ workflow_call:
+ inputs:
+ target-arch:
+ required: true
+ type: string
+
+jobs:
+ build-asset:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ asset:
+ - cc-cloud-hypervisor
+ - cc-kernel
+ - cc-qemu
+ - cc-rootfs-image
+ - cc-virtiofsd
+ - cc-sev-kernel
+ - cc-sev-ovmf
+ - cc-sev-rootfs-initrd
+ - cc-tdx-kernel
+ - cc-tdx-rootfs-image
+ - cc-tdx-qemu
+ - cc-tdx-td-shim
+ - cc-tdx-tdvf
+ 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:
+ fetch-depth: 0 # This is needed in order to keep the commit ids history
+ - 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
+ PUSH_TO_REGISTRY: yes
+
+ - name: store-artifact ${{ matrix.asset }}
+ uses: actions/upload-artifact@v3
+ with:
+ name: kata-artifacts
+ path: kata-build/kata-static-${{ matrix.asset }}.tar.xz
+ retention-days: 1
+ if-no-files-found: error
+
+ - name: store-artifact root_hash_tdx.txt
+ uses: actions/upload-artifact@v3
+ with:
+ name: root_hash_tdx.txt
+ path: tools/osbuilder/root_hash_tdx.txt
+ retention-days: 1
+ if-no-files-found: ignore
+
+ - name: store-artifact root_hash_vanilla.txt
+ uses: actions/upload-artifact@v3
+ with:
+ name: root_hash_vanilla.txt
+ path: tools/osbuilder/root_hash_vanilla.txt
+ retention-days: 1
+ if-no-files-found: ignore
+
+ build-asset-cc-shim-v2:
+ runs-on: ubuntu-latest
+ needs: build-asset
+ 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 root_hash_tdx.txt
+ uses: actions/download-artifact@v3
+ with:
+ name: root_hash_tdx.txt
+ path: tools/osbuilder/
+
+ - name: Get root_hash_vanilla.txt
+ uses: actions/download-artifact@v3
+ with:
+ name: root_hash_vanilla.txt
+ path: tools/osbuilder/
+
+ - name: Build cc-shim-v2
+ run: |
+ make cc-shim-v2-tarball
+ build_dir=$(readlink -f build)
+ # store-artifact does not work with symlink
+ sudo cp -r "${build_dir}" "kata-build"
+ env:
+ PUSH_TO_REGISTRY: yes
+
+ - name: store-artifact cc-shim-v2
+ uses: actions/upload-artifact@v3
+ with:
+ name: kata-artifacts
+ path: kata-build/kata-static-cc-shim-v2.tar.xz
+ retention-days: 1
+ if-no-files-found: error
+
+ create-kata-tarball:
+ runs-on: ubuntu-latest
+ needs: [build-asset, build-asset-cc-shim-v2]
+ steps:
+ - uses: actions/checkout@v3
+ - name: get-artifacts
+ uses: actions/download-artifact@v3
+ 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@v3
+ with:
+ name: kata-static-tarball
+ 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 Confidential Containers quay.io
+ uses: docker/login-action@v2
+ with:
+ registry: quay.io
+ username: ${{ secrets.COCO_QUAY_DEPLOYER_USERNAME }}
+ password: ${{ secrets.COCO_QUAY_DEPLOYER_PASSWORD }}
+
+ - uses: actions/checkout@v3
+ - name: get-kata-tarball
+ uses: actions/download-artifact@v3
+ with:
+ name: kata-static-tarball
+
+ - 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/confidential-containers/runtime-payload-ci" \
+ "kata-containers-${{ inputs.target-arch }}"
diff --git a/.github/workflows/cc-payload-after-push-s390x.yaml b/.github/workflows/cc-payload-after-push-s390x.yaml
new file mode 100644
index 000000000..dc1d384e1
--- /dev/null
+++ b/.github/workflows/cc-payload-after-push-s390x.yaml
@@ -0,0 +1,149 @@
+name: CI | Publish CC runtime payload for s390x
+on:
+ workflow_call:
+ inputs:
+ target-arch:
+ required: true
+ type: string
+
+jobs:
+ build-asset:
+ runs-on: s390x
+ strategy:
+ matrix:
+ asset:
+ - cc-kernel
+ - cc-qemu
+ - cc-rootfs-image
+ - cc-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:
+ fetch-depth: 0 # This is needed in order to keep the commit ids history
+ - 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"
+ sudo chown -R $(id -u):$(id -g) "kata-build"
+ env:
+ KATA_ASSET: ${{ matrix.asset }}
+ TAR_OUTPUT: ${{ matrix.asset }}.tar.gz
+ PUSH_TO_REGISTRY: yes
+
+ - name: store-artifact ${{ matrix.asset }}
+ uses: actions/upload-artifact@v3
+ with:
+ name: kata-artifacts-s390x
+ path: kata-build/kata-static-${{ matrix.asset }}.tar.xz
+ retention-days: 1
+ if-no-files-found: error
+
+ - name: store-artifact root_hash_vanilla.txt
+ uses: actions/upload-artifact@v3
+ with:
+ name: root_hash_vanilla.txt-s390x
+ path: tools/osbuilder/root_hash_vanilla.txt
+ retention-days: 1
+ if-no-files-found: ignore
+
+ build-asset-cc-shim-v2:
+ runs-on: s390x
+ needs: build-asset
+ 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 root_hash_vanilla.txt
+ uses: actions/download-artifact@v3
+ with:
+ name: root_hash_vanilla.txt-s390x
+ path: tools/osbuilder/
+
+ - name: Build cc-shim-v2
+ run: |
+ make cc-shim-v2-tarball
+ build_dir=$(readlink -f build)
+ # store-artifact does not work with symlink
+ sudo cp -r "${build_dir}" "kata-build"
+ env:
+ PUSH_TO_REGISTRY: yes
+
+ - name: store-artifact cc-shim-v2
+ uses: actions/upload-artifact@v3
+ with:
+ name: kata-artifacts-s390x
+ path: kata-build/kata-static-cc-shim-v2.tar.xz
+ retention-days: 1
+ if-no-files-found: error
+
+ create-kata-tarball:
+ runs-on: s390x
+ needs: [build-asset, build-asset-cc-shim-v2]
+ steps:
+ - name: Adjust a permission for repo
+ run: |
+ sudo chown -R $USER:$USER $GITHUB_WORKSPACE
+
+ - uses: actions/checkout@v3
+ - name: get-artifacts
+ uses: actions/download-artifact@v3
+ with:
+ name: kata-artifacts-s390x
+ 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@v3
+ with:
+ name: kata-static-tarball-s390x
+ 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 Confidential Containers quay.io
+ uses: docker/login-action@v2
+ with:
+ registry: quay.io
+ username: ${{ secrets.COCO_QUAY_DEPLOYER_USERNAME }}
+ password: ${{ secrets.COCO_QUAY_DEPLOYER_PASSWORD }}
+
+ - 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/confidential-containers/runtime-payload-ci" \
+ "kata-containers-${{ inputs.target-arch }}"
diff --git a/.github/workflows/cc-payload-after-push.yaml b/.github/workflows/cc-payload-after-push.yaml
new file mode 100644
index 000000000..fb047272b
--- /dev/null
+++ b/.github/workflows/cc-payload-after-push.yaml
@@ -0,0 +1,39 @@
+name: CI | Publish Kata Containers payload for Confidential Containers
+on:
+ push:
+ branches:
+ - CCv0
+
+jobs:
+ build-assets-amd64:
+ uses: ./.github/workflows/cc-payload-after-push-amd64.yaml
+ with:
+ target-arch: amd64
+ secrets: inherit
+
+ build-assets-s390x:
+ uses: ./.github/workflows/cc-payload-after-push-s390x.yaml
+ with:
+ target-arch: s390x
+ secrets: inherit
+
+ publish:
+ runs-on: ubuntu-latest
+ needs: [build-assets-amd64, build-assets-s390x]
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Login to Confidential Containers quay.io
+ uses: docker/login-action@v2
+ with:
+ registry: quay.io
+ username: ${{ secrets.COCO_QUAY_DEPLOYER_USERNAME }}
+ password: ${{ secrets.COCO_QUAY_DEPLOYER_PASSWORD }}
+
+ - name: Push multi-arch manifest
+ run: |
+ docker manifest create quay.io/confidential-containers/runtime-payload-ci:kata-containers-latest \
+ --amend quay.io/confidential-containers/runtime-payload-ci:kata-containers-amd64 \
+ --amend quay.io/confidential-containers/runtime-payload-ci:kata-containers-s390x
+ docker manifest push quay.io/confidential-containers/runtime-payload-ci:kata-containers-latest
diff --git a/.github/workflows/cc-payload-amd64.yaml b/.github/workflows/cc-payload-amd64.yaml
new file mode 100644
index 000000000..c4c1eb035
--- /dev/null
+++ b/.github/workflows/cc-payload-amd64.yaml
@@ -0,0 +1,142 @@
+name: Publish Kata Containers payload for Confidential Containers (amd64)
+on:
+ workflow_call:
+ inputs:
+ target-arch:
+ required: true
+ type: string
+
+jobs:
+ build-asset:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ asset:
+ - cc-cloud-hypervisor
+ - cc-kernel
+ - cc-qemu
+ - cc-rootfs-image
+ - cc-virtiofsd
+ - cc-sev-kernel
+ - cc-sev-ovmf
+ - cc-sev-rootfs-initrd
+ - cc-tdx-kernel
+ - cc-tdx-rootfs-image
+ - cc-tdx-qemu
+ - cc-tdx-td-shim
+ - cc-tdx-tdvf
+ steps:
+ - uses: actions/checkout@v3
+ - 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@v3
+ with:
+ name: kata-artifacts
+ path: kata-build/kata-static-${{ matrix.asset }}.tar.xz
+ retention-days: 1
+ if-no-files-found: error
+
+ - name: store-artifact root_hash_tdx.txt
+ uses: actions/upload-artifact@v3
+ with:
+ name: root_hash_tdx.txt
+ path: tools/osbuilder/root_hash_tdx.txt
+ retention-days: 1
+ if-no-files-found: ignore
+
+ - name: store-artifact root_hash_vanilla.txt
+ uses: actions/upload-artifact@v3
+ with:
+ name: root_hash_vanilla.txt
+ path: tools/osbuilder/root_hash_vanilla.txt
+ retention-days: 1
+ if-no-files-found: ignore
+
+ build-asset-cc-shim-v2:
+ runs-on: ubuntu-latest
+ needs: build-asset
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Get root_hash_tdx.txt
+ uses: actions/download-artifact@v3
+ with:
+ name: root_hash_tdx.txt
+ path: tools/osbuilder/
+
+ - name: Get root_hash_vanilla.txt
+ uses: actions/download-artifact@v3
+ with:
+ name: root_hash_vanilla.txt
+ path: tools/osbuilder/
+
+ - name: Build cc-shim-v2
+ run: |
+ make cc-shim-v2-tarball
+ build_dir=$(readlink -f build)
+ # store-artifact does not work with symlink
+ sudo cp -r "${build_dir}" "kata-build"
+
+ - name: store-artifact cc-shim-v2
+ uses: actions/upload-artifact@v3
+ with:
+ name: kata-artifacts
+ path: kata-build/kata-static-cc-shim-v2.tar.xz
+ retention-days: 1
+ if-no-files-found: error
+
+ create-kata-tarball:
+ runs-on: ubuntu-latest
+ needs: [build-asset, build-asset-cc-shim-v2]
+ steps:
+ - uses: actions/checkout@v3
+ - name: get-artifacts
+ uses: actions/download-artifact@v3
+ 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@v3
+ with:
+ name: kata-static-tarball
+ 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 quay.io
+ uses: docker/login-action@v2
+ with:
+ registry: quay.io
+ username: ${{ secrets.COCO_QUAY_DEPLOYER_USERNAME }}
+ password: ${{ secrets.COCO_QUAY_DEPLOYER_PASSWORD }}
+
+ - uses: actions/checkout@v3
+ - name: get-kata-tarball
+ uses: actions/download-artifact@v3
+ with:
+ name: kata-static-tarball
+
+ - 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/confidential-containers/runtime-payload" \
+ "kata-containers-${{ inputs.target-arch }}"
+
diff --git a/.github/workflows/cc-payload-s390x.yaml b/.github/workflows/cc-payload-s390x.yaml
new file mode 100644
index 000000000..c062ac3ab
--- /dev/null
+++ b/.github/workflows/cc-payload-s390x.yaml
@@ -0,0 +1,134 @@
+name: Publish Kata Containers payload for Confidential Containers (s390x)
+on:
+ workflow_call:
+ inputs:
+ target-arch:
+ required: true
+ type: string
+
+jobs:
+ build-asset:
+ runs-on: s390x
+ strategy:
+ matrix:
+ asset:
+ - cc-kernel
+ - cc-qemu
+ - cc-rootfs-image
+ - cc-virtiofsd
+ steps:
+ - name: Adjust a permission for repo
+ run: |
+ sudo chown -R $USER:$USER $GITHUB_WORKSPACE
+
+ - uses: actions/checkout@v3
+ - 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@v3
+ with:
+ name: kata-artifacts-s390x
+ path: kata-build/kata-static-${{ matrix.asset }}.tar.xz
+ retention-days: 1
+ if-no-files-found: error
+
+ - name: store-artifact root_hash_vanilla.txt
+ uses: actions/upload-artifact@v3
+ with:
+ name: root_hash_vanilla.txt-s390x
+ path: tools/osbuilder/root_hash_vanilla.txt
+ retention-days: 1
+ if-no-files-found: ignore
+
+ build-asset-cc-shim-v2:
+ runs-on: s390x
+ needs: build-asset
+ steps:
+ - name: Adjust a permission for repo
+ run: |
+ sudo chown -R $USER:$USER $GITHUB_WORKSPACE
+
+ - uses: actions/checkout@v3
+
+ - name: Get root_hash_vanilla.txt
+ uses: actions/download-artifact@v3
+ with:
+ name: root_hash_vanilla.txt-s390x
+ path: tools/osbuilder/
+
+ - name: Build cc-shim-v2
+ run: |
+ make cc-shim-v2-tarball
+ build_dir=$(readlink -f build)
+ # store-artifact does not work with symlink
+ sudo cp -r "${build_dir}" "kata-build"
+
+ - name: store-artifact cc-shim-v2
+ uses: actions/upload-artifact@v3
+ with:
+ name: kata-artifacts-s390x
+ path: kata-build/kata-static-cc-shim-v2.tar.xz
+ retention-days: 1
+ if-no-files-found: error
+
+ create-kata-tarball:
+ runs-on: s390x
+ needs: [build-asset, build-asset-cc-shim-v2]
+ steps:
+ - name: Adjust a permission for repo
+ run: |
+ sudo chown -R $USER:$USER $GITHUB_WORKSPACE
+
+ - uses: actions/checkout@v3
+ - name: get-artifacts
+ uses: actions/download-artifact@v3
+ with:
+ name: kata-artifacts-s390x
+ 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@v3
+ with:
+ name: kata-static-tarball-s390x
+ 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 quay.io
+ uses: docker/login-action@v2
+ with:
+ registry: quay.io
+ username: ${{ secrets.COCO_QUAY_DEPLOYER_USERNAME }}
+ password: ${{ secrets.COCO_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/confidential-containers/runtime-payload" \
+ "kata-containers-${{ inputs.target-arch }}"
diff --git a/.github/workflows/cc-payload.yaml b/.github/workflows/cc-payload.yaml
new file mode 100644
index 000000000..f07936907
--- /dev/null
+++ b/.github/workflows/cc-payload.yaml
@@ -0,0 +1,39 @@
+name: Publish Kata Containers payload for Confidential Containers
+on:
+ push:
+ tags:
+ - 'CC\-[0-9]+.[0-9]+.[0-9]+'
+
+jobs:
+ build-assets-amd64:
+ uses: ./.github/workflows/cc-payload-amd64.yaml
+ with:
+ target-arch: amd64
+ secrets: inherit
+
+ build-assets-s390x:
+ uses: ./.github/workflows/cc-payload-s390x.yaml
+ with:
+ target-arch: s390x
+ secrets: inherit
+
+ publish:
+ runs-on: ubuntu-latest
+ needs: [build-assets-amd64, build-assets-s390x]
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Login to Confidential Containers quay.io
+ uses: docker/login-action@v2
+ with:
+ registry: quay.io
+ username: ${{ secrets.COCO_QUAY_DEPLOYER_USERNAME }}
+ password: ${{ secrets.COCO_QUAY_DEPLOYER_PASSWORD }}
+
+ - name: Push multi-arch manifest
+ run: |
+ docker manifest create quay.io/confidential-containers/runtime-payload:kata-containers-latest \
+ --amend quay.io/confidential-containers/runtime-payload:kata-containers-amd64 \
+ --amend quay.io/confidential-containers/runtime-payload:kata-containers-s390x
+ docker manifest push quay.io/confidential-containers/runtime-payload:kata-containers-latest
diff --git a/.github/workflows/commit-message-check.yaml b/.github/workflows/commit-message-check.yaml
index fbdb02b6d..191e94b0d 100644
--- a/.github/workflows/commit-message-check.yaml
+++ b/.github/workflows/commit-message-check.yaml
@@ -47,7 +47,7 @@ jobs:
uses: tim-actions/[email protected]
with:
commits: ${{ steps.get-pr-commits.outputs.commits }}
- pattern: '^.{0,75}(\n.*)*$'
+ pattern: '^.{0,75}(\n.*)*$|^Merge pull request (?:kata-containers)?#[\d]+ from.*'
error: 'Subject too long (max 75)'
post_error: ${{ env.error_msg }}
@@ -95,6 +95,6 @@ jobs:
uses: tim-actions/[email protected]
with:
commits: ${{ steps.get-pr-commits.outputs.commits }}
- pattern: '^[\s\t]*[^:\s\t]+[\s\t]*:'
+ pattern: '^[\s\t]*[^:\s\t]+[\s\t]*:|^Merge pull request (?:kata-containers)?#[\d]+ from.*'
error: 'Failed to find subsystem in subject'
post_error: ${{ env.error_msg }}
diff --git a/.github/workflows/darwin-tests.yaml b/.github/workflows/darwin-tests.yaml
index 278d2e287..bf8813776 100644
--- a/.github/workflows/darwin-tests.yaml
+++ b/.github/workflows/darwin-tests.yaml
@@ -5,7 +5,7 @@ on:
- edited
- reopened
- synchronize
-
+ paths-ignore: [ '**.md', '**.png', '**.jpg', '**.jpeg', '**.svg', '/docs/**' ]
name: Darwin tests
jobs:
test:
@@ -14,7 +14,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
- go-version: 1.19.2
+ go-version: 1.19.3
- name: Checkout code
uses: actions/checkout@v2
- name: Build utils
diff --git a/.github/workflows/deploy-ccv0-demo.yaml b/.github/workflows/deploy-ccv0-demo.yaml
new file mode 100644
index 000000000..1e9ebe8f1
--- /dev/null
+++ b/.github/workflows/deploy-ccv0-demo.yaml
@@ -0,0 +1,129 @@
+on:
+ issue_comment:
+ types: [created, edited]
+
+name: deploy-ccv0-demo
+
+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, '/deploy-ccv0-demo')
+ steps:
+ - name: Check membership
+ uses: kata-containers/[email protected]
+ id: is_organization_member
+ with:
+ organization: kata-containers
+ username: ${{ github.event.comment.user.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 }}
+ 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
+ - qemu
+ - rootfs-image
+ - rootfs-initrd
+ - shim-v2
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install docker
+ run: |
+ curl -fsSL https://test.docker.com -o test-docker.sh
+ sh test-docker.sh
+
+ - name: Prepare confidential container rootfs
+ if: ${{ matrix.asset == 'rootfs-initrd' }}
+ run: |
+ pushd include_rootfs/etc
+ curl -LO https://raw.githubusercontent.com/confidential-containers/documentation/main/demos/ssh-demo/aa-offline_fs_kbc-keys.json
+ mkdir kata-containers
+ envsubst < docs/how-to/data/confidential-agent-config.toml.in > kata-containers/agent.toml
+ popd
+ env:
+ AA_KBC_PARAMS: offline_fs_kbc::null
+
+ - 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:
+ AA_KBC: offline_fs_kbc
+ INCLUDE_ROOTFS: include_rootfs
+ 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
+
+ kata-deploy:
+ needs: create-kata-tarball
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - 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: |
+ tag=$(echo $GITHUB_REF | cut -d/ -f3-)
+ pushd $GITHUB_WORKSPACE
+ git checkout $tag
+ pkg_sha=$(git rev-parse HEAD)
+ popd
+ 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/confidential-containers/runtime-payload:$pkg_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/confidential-containers/runtime-payload:$pkg_sha
+ mkdir -p packaging/kata-deploy
+ ln -s $GITHUB_WORKSPACE/tools/packaging/kata-deploy/action packaging/kata-deploy/action
+ echo "::set-output name=PKG_SHA::${pkg_sha}"
diff --git a/.github/workflows/docs-url-alive-check.yaml b/.github/workflows/docs-url-alive-check.yaml
index f8ca138ff..bd1f5ab2c 100644
--- a/.github/workflows/docs-url-alive-check.yaml
+++ b/.github/workflows/docs-url-alive-check.yaml
@@ -14,7 +14,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v2
with:
- go-version: 1.19.2
+ go-version: 1.19.3
env:
GOPATH: ${{ runner.workspace }}/kata-containers
- name: Set env
diff --git a/.github/workflows/kata-deploy-test.yaml b/.github/workflows/kata-deploy-test.yaml
index 746f94c9b..7f6839b40 100644
--- a/.github/workflows/kata-deploy-test.yaml
+++ b/.github/workflows/kata-deploy-test.yaml
@@ -1,5 +1,10 @@
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]
@@ -13,19 +18,20 @@ jobs:
&& 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
+ - name: Check membership on comment or dispatch
uses: kata-containers/[email protected]
id: is_organization_member
with:
organization: kata-containers
- username: ${{ github.event.comment.user.login }}
+ 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 }}
+ 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}
@@ -54,8 +60,12 @@ jobs:
- name: get-PR-ref
id: get-PR-ref
run: |
- ref=$(cat $GITHUB_EVENT_PATH | jq -r '.issue.pull_request.url' | sed 's#^.*\/pulls#refs\/pull#' | sed 's#$#\/merge#')
- echo "reference for PR: " ${ref}
+ 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 "##[set-output name=pr-ref;]${ref}"
- uses: actions/checkout@v2
with:
@@ -90,8 +100,12 @@ jobs:
- name: get-PR-ref
id: get-PR-ref
run: |
- ref=$(cat $GITHUB_EVENT_PATH | jq -r '.issue.pull_request.url' | sed 's#^.*\/pulls#refs\/pull#' | sed 's#$#\/merge#')
- echo "reference for PR: " ${ref}
+ 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 "##[set-output name=pr-ref;]${ref}"
- uses: actions/checkout@v2
with:
@@ -117,8 +131,12 @@ jobs:
- name: get-PR-ref
id: get-PR-ref
run: |
- ref=$(cat $GITHUB_EVENT_PATH | jq -r '.issue.pull_request.url' | sed 's#^.*\/pulls#refs\/pull#' | sed 's#$#\/merge#')
- echo "reference for PR: " ${ref}
+ 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 "##[set-output name=pr-ref;]${ref}"
- uses: actions/checkout@v2
with:
diff --git a/.github/workflows/snap-release.yaml b/.github/workflows/snap-release.yaml
index b271d7d3d..0d41197a0 100644
--- a/.github/workflows/snap-release.yaml
+++ b/.github/workflows/snap-release.yaml
@@ -4,6 +4,9 @@ on:
tags:
- '[0-9]+.[0-9]+.[0-9]+*'
+env:
+ SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.snapcraft_token }}
+
jobs:
release-snap:
runs-on: ubuntu-20.04
@@ -14,9 +17,16 @@ jobs:
fetch-depth: 0
- name: Install Snapcraft
- uses: samuelmeuli/action-snapcraft@v1
- with:
- snapcraft_token: ${{ secrets.snapcraft_token }}
+ run: |
+ # Required to avoid snapcraft install failure
+ sudo chown root:root /
+
+ # "--classic" is needed for the GitHub action runner
+ # environment.
+ sudo snap install snapcraft --classic
+
+ # Allow other parts to access snap binaries
+ echo /snap/bin >> "$GITHUB_PATH"
- name: Build snap
run: |
diff --git a/.github/workflows/snap.yaml b/.github/workflows/snap.yaml
index 9176d45d2..2f1495824 100644
--- a/.github/workflows/snap.yaml
+++ b/.github/workflows/snap.yaml
@@ -6,6 +6,7 @@ on:
- synchronize
- reopened
- edited
+ paths-ignore: [ '**.md', '**.png', '**.jpg', '**.jpeg', '**.svg', '/docs/**' ]
jobs:
test:
@@ -19,7 +20,16 @@ jobs:
- name: Install Snapcraft
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- uses: samuelmeuli/action-snapcraft@v1
+ run: |
+ # Required to avoid snapcraft install failure
+ sudo chown root:root /
+
+ # "--classic" is needed for the GitHub action runner
+ # environment.
+ sudo snap install snapcraft --classic
+
+ # Allow other parts to access snap binaries
+ echo /snap/bin >> "$GITHUB_PATH"
- name: Build snap
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
diff --git a/.github/workflows/static-checks-dragonball.yaml b/.github/workflows/static-checks-dragonball.yaml
new file mode 100644
index 000000000..9c8ae694b
--- /dev/null
+++ b/.github/workflows/static-checks-dragonball.yaml
@@ -0,0 +1,33 @@
+on:
+ pull_request:
+ types:
+ - opened
+ - edited
+ - reopened
+ - synchronize
+ paths-ignore: [ '**.md', '**.png', '**.jpg', '**.jpeg', '**.svg', '/docs/**' ]
+
+name: Static checks dragonball
+jobs:
+ test-dragonball:
+ runs-on: self-hosted
+ env:
+ RUST_BACKTRACE: "1"
+ steps:
+ - uses: actions/checkout@v3
+ - name: Set env
+ if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
+ run: |
+ echo "GOPATH=${{ github.workspace }}" >> $GITHUB_ENV
+ - name: Install Rust
+ if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
+ run: |
+ ./ci/install_rust.sh
+ PATH=$PATH:"$HOME/.cargo/bin"
+ - name: Run Unit Test
+ if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
+ run: |
+ cd src/dragonball
+ cargo version
+ rustc --version
+ sudo -E env PATH=$PATH LIBC=gnu SUPPORT_VIRTUALIZATION=true make test
diff --git a/.github/workflows/static-checks.yaml b/.github/workflows/static-checks.yaml
index e781507d0..69dfbae59 100644
--- a/.github/workflows/static-checks.yaml
+++ b/.github/workflows/static-checks.yaml
@@ -8,60 +8,16 @@ on:
name: Static checks
jobs:
- check-vendored-code:
- runs-on: ubuntu-20.04
- env:
- TRAVIS: "true"
- TRAVIS_BRANCH: ${{ github.base_ref }}
- TRAVIS_PULL_REQUEST_BRANCH: ${{ github.head_ref }}
- TRAVIS_PULL_REQUEST_SHA : ${{ github.event.pull_request.head.sha }}
- RUST_BACKTRACE: "1"
- target_branch: ${{ github.base_ref }}
- steps:
- - name: Install Go
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- uses: actions/setup-go@v3
- with:
- go-version: 1.19.2
- env:
- GOPATH: ${{ runner.workspace }}/kata-containers
- - name: Setup GOPATH
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- echo "TRAVIS_BRANCH: ${TRAVIS_BRANCH}"
- echo "TRAVIS_PULL_REQUEST_BRANCH: ${TRAVIS_PULL_REQUEST_BRANCH}"
- echo "TRAVIS_PULL_REQUEST_SHA: ${TRAVIS_PULL_REQUEST_SHA}"
- echo "TRAVIS: ${TRAVIS}"
- - name: Set env
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- echo "GOPATH=${{ github.workspace }}" >> $GITHUB_ENV
- echo "${{ github.workspace }}/bin" >> $GITHUB_PATH
- - name: Checkout code
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- uses: actions/checkout@v3
- with:
- fetch-depth: 0
- path: ./src/github.com/${{ github.repository }}
- - name: Setup travis references
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- echo "TRAVIS_BRANCH=${TRAVIS_BRANCH:-$(echo $GITHUB_REF | awk 'BEGIN { FS = \"/\" } ; { print $3 }')}"
- target_branch=${TRAVIS_BRANCH}
- - name: Setup
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- cd ${GOPATH}/src/github.com/${{ github.repository }} && ./ci/setup.sh
- env:
- GOPATH: ${{ runner.workspace }}/kata-containers
- # Check whether the vendored code is up-to-date & working as the first thing
- - name: Check vendored code
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- cd ${GOPATH}/src/github.com/${{ github.repository }} && make vendor
-
static-checks:
runs-on: ubuntu-20.04
+ strategy:
+ matrix:
+ cmd:
+ - "make vendor"
+ - "make static-checks"
+ - "make check"
+ - "make test"
+ - "sudo -E PATH=\"$PATH\" make test"
env:
TRAVIS: "true"
TRAVIS_BRANCH: ${{ github.base_ref }}
@@ -70,144 +26,16 @@ jobs:
RUST_BACKTRACE: "1"
target_branch: ${{ github.base_ref }}
steps:
- - name: Install Go
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- uses: actions/setup-go@v3
- with:
- go-version: 1.19.2
- env:
- GOPATH: ${{ runner.workspace }}/kata-containers
- - name: Setup GOPATH
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- echo "TRAVIS_BRANCH: ${TRAVIS_BRANCH}"
- echo "TRAVIS_PULL_REQUEST_BRANCH: ${TRAVIS_PULL_REQUEST_BRANCH}"
- echo "TRAVIS_PULL_REQUEST_SHA: ${TRAVIS_PULL_REQUEST_SHA}"
- echo "TRAVIS: ${TRAVIS}"
- - name: Set env
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- echo "GOPATH=${{ github.workspace }}" >> $GITHUB_ENV
- echo "${{ github.workspace }}/bin" >> $GITHUB_PATH
- - name: Checkout code
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- uses: actions/checkout@v3
- with:
- fetch-depth: 0
- path: ./src/github.com/${{ github.repository }}
- - name: Setup travis references
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- echo "TRAVIS_BRANCH=${TRAVIS_BRANCH:-$(echo $GITHUB_REF | awk 'BEGIN { FS = \"/\" } ; { print $3 }')}"
- target_branch=${TRAVIS_BRANCH}
- - name: Setup
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- cd ${GOPATH}/src/github.com/${{ github.repository }} && ./ci/setup.sh
- env:
- GOPATH: ${{ runner.workspace }}/kata-containers
- - name: Installing rust
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- cd ${GOPATH}/src/github.com/${{ github.repository }} && ./ci/install_rust.sh
- PATH=$PATH:"$HOME/.cargo/bin"
- rustup target add x86_64-unknown-linux-musl
- rustup component add rustfmt clippy
- - name: Setup seccomp
- run: |
- libseccomp_install_dir=$(mktemp -d -t libseccomp.XXXXXXXXXX)
- gperf_install_dir=$(mktemp -d -t gperf.XXXXXXXXXX)
- cd ${GOPATH}/src/github.com/${{ github.repository }} && ./ci/install_libseccomp.sh "${libseccomp_install_dir}" "${gperf_install_dir}"
- echo "Set environment variables for the libseccomp crate to link the libseccomp library statically"
- echo "LIBSECCOMP_LINK_TYPE=static" >> $GITHUB_ENV
- echo "LIBSECCOMP_LIB_PATH=${libseccomp_install_dir}/lib" >> $GITHUB_ENV
- - name: Static Checks
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- cd ${GOPATH}/src/github.com/${{ github.repository }} && make static-checks
-
-
- compiler-checks:
- runs-on: ubuntu-20.04
- env:
- TRAVIS: "true"
- TRAVIS_BRANCH: ${{ github.base_ref }}
- TRAVIS_PULL_REQUEST_BRANCH: ${{ github.head_ref }}
- TRAVIS_PULL_REQUEST_SHA : ${{ github.event.pull_request.head.sha }}
- RUST_BACKTRACE: "1"
- target_branch: ${{ github.base_ref }}
- steps:
- - name: Install Go
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- uses: actions/setup-go@v3
- with:
- go-version: 1.19.2
- env:
- GOPATH: ${{ runner.workspace }}/kata-containers
- - name: Setup GOPATH
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- echo "TRAVIS_BRANCH: ${TRAVIS_BRANCH}"
- echo "TRAVIS_PULL_REQUEST_BRANCH: ${TRAVIS_PULL_REQUEST_BRANCH}"
- echo "TRAVIS_PULL_REQUEST_SHA: ${TRAVIS_PULL_REQUEST_SHA}"
- echo "TRAVIS: ${TRAVIS}"
- - name: Set env
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- echo "GOPATH=${{ github.workspace }}" >> $GITHUB_ENV
- echo "${{ github.workspace }}/bin" >> $GITHUB_PATH
- name: Checkout code
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
uses: actions/checkout@v3
with:
fetch-depth: 0
path: ./src/github.com/${{ github.repository }}
- - name: Setup travis references
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- echo "TRAVIS_BRANCH=${TRAVIS_BRANCH:-$(echo $GITHUB_REF | awk 'BEGIN { FS = \"/\" } ; { print $3 }')}"
- target_branch=${TRAVIS_BRANCH}
- - name: Setup
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- cd ${GOPATH}/src/github.com/${{ github.repository }} && ./ci/setup.sh
- env:
- GOPATH: ${{ runner.workspace }}/kata-containers
- - name: Installing rust
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- cd ${GOPATH}/src/github.com/${{ github.repository }} && ./ci/install_rust.sh
- PATH=$PATH:"$HOME/.cargo/bin"
- rustup target add x86_64-unknown-linux-musl
- rustup component add rustfmt clippy
- - name: Setup seccomp
- run: |
- libseccomp_install_dir=$(mktemp -d -t libseccomp.XXXXXXXXXX)
- gperf_install_dir=$(mktemp -d -t gperf.XXXXXXXXXX)
- cd ${GOPATH}/src/github.com/${{ github.repository }} && ./ci/install_libseccomp.sh "${libseccomp_install_dir}" "${gperf_install_dir}"
- echo "Set environment variables for the libseccomp crate to link the libseccomp library statically"
- echo "LIBSECCOMP_LINK_TYPE=static" >> $GITHUB_ENV
- echo "LIBSECCOMP_LIB_PATH=${libseccomp_install_dir}/lib" >> $GITHUB_ENV
- - name: Run Compiler Checks
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- cd ${GOPATH}/src/github.com/${{ github.repository }} && make check
-
- unit-tests:
- runs-on: ubuntu-20.04
- env:
- TRAVIS: "true"
- TRAVIS_BRANCH: ${{ github.base_ref }}
- TRAVIS_PULL_REQUEST_BRANCH: ${{ github.head_ref }}
- TRAVIS_PULL_REQUEST_SHA : ${{ github.event.pull_request.head.sha }}
- RUST_BACKTRACE: "1"
- target_branch: ${{ github.base_ref }}
- steps:
- name: Install Go
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
uses: actions/setup-go@v3
with:
- go-version: 1.19.2
+ go-version: 1.19.3
env:
GOPATH: ${{ runner.workspace }}/kata-containers
- name: Setup GOPATH
@@ -222,12 +50,6 @@ jobs:
run: |
echo "GOPATH=${{ github.workspace }}" >> $GITHUB_ENV
echo "${{ github.workspace }}/bin" >> $GITHUB_PATH
- - name: Checkout code
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- uses: actions/checkout@v3
- with:
- fetch-depth: 0
- path: ./src/github.com/${{ github.repository }}
- name: Setup travis references
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
run: |
@@ -247,72 +69,7 @@ jobs:
rustup target add x86_64-unknown-linux-musl
rustup component add rustfmt clippy
- name: Setup seccomp
- run: |
- libseccomp_install_dir=$(mktemp -d -t libseccomp.XXXXXXXXXX)
- gperf_install_dir=$(mktemp -d -t gperf.XXXXXXXXXX)
- cd ${GOPATH}/src/github.com/${{ github.repository }} && ./ci/install_libseccomp.sh "${libseccomp_install_dir}" "${gperf_install_dir}"
- echo "Set environment variables for the libseccomp crate to link the libseccomp library statically"
- echo "LIBSECCOMP_LINK_TYPE=static" >> $GITHUB_ENV
- echo "LIBSECCOMP_LIB_PATH=${libseccomp_install_dir}/lib" >> $GITHUB_ENV
- - name: Run Unit Tests
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- cd ${GOPATH}/src/github.com/${{ github.repository }} && make test
-
- unit-tests-as-root:
- runs-on: ubuntu-20.04
- env:
- TRAVIS: "true"
- TRAVIS_BRANCH: ${{ github.base_ref }}
- TRAVIS_PULL_REQUEST_BRANCH: ${{ github.head_ref }}
- TRAVIS_PULL_REQUEST_SHA : ${{ github.event.pull_request.head.sha }}
- RUST_BACKTRACE: "1"
- target_branch: ${{ github.base_ref }}
- steps:
- - name: Install Go
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- uses: actions/setup-go@v3
- with:
- go-version: 1.19.2
- env:
- GOPATH: ${{ runner.workspace }}/kata-containers
- - name: Setup GOPATH
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- echo "TRAVIS_BRANCH: ${TRAVIS_BRANCH}"
- echo "TRAVIS_PULL_REQUEST_BRANCH: ${TRAVIS_PULL_REQUEST_BRANCH}"
- echo "TRAVIS_PULL_REQUEST_SHA: ${TRAVIS_PULL_REQUEST_SHA}"
- echo "TRAVIS: ${TRAVIS}"
- - name: Set env
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- echo "GOPATH=${{ github.workspace }}" >> $GITHUB_ENV
- echo "${{ github.workspace }}/bin" >> $GITHUB_PATH
- - name: Checkout code
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- uses: actions/checkout@v3
- with:
- fetch-depth: 0
- path: ./src/github.com/${{ github.repository }}
- - name: Setup travis references
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- echo "TRAVIS_BRANCH=${TRAVIS_BRANCH:-$(echo $GITHUB_REF | awk 'BEGIN { FS = \"/\" } ; { print $3 }')}"
- target_branch=${TRAVIS_BRANCH}
- - name: Setup
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- cd ${GOPATH}/src/github.com/${{ github.repository }} && ./ci/setup.sh
- env:
- GOPATH: ${{ runner.workspace }}/kata-containers
- - name: Installing rust
- if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
- run: |
- cd ${GOPATH}/src/github.com/${{ github.repository }} && ./ci/install_rust.sh
- PATH=$PATH:"$HOME/.cargo/bin"
- rustup target add x86_64-unknown-linux-musl
- rustup component add rustfmt clippy
- - name: Setup seccomp
run: |
libseccomp_install_dir=$(mktemp -d -t libseccomp.XXXXXXXXXX)
gperf_install_dir=$(mktemp -d -t gperf.XXXXXXXXXX)
@@ -320,7 +77,7 @@ jobs:
echo "Set environment variables for the libseccomp crate to link the libseccomp library statically"
echo "LIBSECCOMP_LINK_TYPE=static" >> $GITHUB_ENV
echo "LIBSECCOMP_LIB_PATH=${libseccomp_install_dir}/lib" >> $GITHUB_ENV
- - name: Run Unit Tests As Root User
+ - name: Run check
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
run: |
- cd ${GOPATH}/src/github.com/${{ github.repository }} && sudo -E PATH="$PATH" make test
+ cd ${GOPATH}/src/github.com/${{ github.repository }} && ${{ matrix.cmd }}
diff --git a/.gitignore b/.gitignore
index 1a149208c..fca150940 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,8 @@
**/*.rej
**/target
**/.vscode
+**/.idea
+**/.fleet
pkg/logging/Cargo.lock
src/agent/src/version.rs
src/agent/kata-agent.service
@@ -11,4 +13,3 @@ src/agent/protocols/src/*.rs
!src/agent/protocols/src/lib.rs
build
src/tools/log-parser/kata-log-parser
-
diff --git a/Makefile b/Makefile
index 4d2be6b4d..d4a3dad05 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,7 @@ COMPONENTS =
COMPONENTS += libs
COMPONENTS += agent
+COMPONENTS += dragonball
COMPONENTS += runtime
COMPONENTS += runtime-rs
@@ -15,11 +16,12 @@ COMPONENTS += runtime-rs
TOOLS =
TOOLS += agent-ctl
-TOOLS += trace-forwarder
-TOOLS += runk
+TOOLS += kata-ctl
TOOLS += log-parser
+TOOLS += runk
+TOOLS += trace-forwarder
-STANDARD_TARGETS = build check clean install test vendor
+STANDARD_TARGETS = build check clean install static-checks-build test vendor
default: all
@@ -35,7 +37,7 @@ generate-protocols:
make -C src/agent generate-protocols
# Some static checks rely on generated source files of components.
-static-checks: build
+static-checks: static-checks-build
bash ci/static-checks.sh
docs-url-alive-check:
diff --git a/README.md b/README.md
index 2b0759a2c..6972ed278 100644
--- a/README.md
+++ b/README.md
@@ -119,10 +119,8 @@ The table below lists the core parts of the project:
| [runtime](src/runtime) | core | Main component run by a container manager and providing a containerd shimv2 runtime implementation. |
| [runtime-rs](src/runtime-rs) | core | The Rust version runtime. |
| [agent](src/agent) | core | Management process running inside the virtual machine / POD that sets up the container environment. |
-| [libraries](src/libs) | core | Library crates shared by multiple Kata Container components or published to [`crates.io`](https://crates.io/index.html) |
| [`dragonball`](src/dragonball) | core | An optional built-in VMM brings out-of-the-box Kata Containers experience with optimizations on container workloads |
| [documentation](docs) | documentation | Documentation common to all components (such as design and install documentation). |
-| [libraries](src/libs) | core | Library crates shared by multiple Kata Container components or published to [`crates.io`](https://crates.io/index.html) |
| [tests](https://github.com/kata-containers/tests) | tests | Excludes unit tests which live with the main code. |
### Additional components
@@ -135,6 +133,7 @@ The table below lists the remaining parts of the project:
| [kernel](https://www.kernel.org) | kernel | Linux kernel used by the hypervisor to boot the guest image. Patches are stored [here](tools/packaging/kernel). |
| [osbuilder](tools/osbuilder) | infrastructure | Tool to create "mini O/S" rootfs and initrd images and kernel for the hypervisor. |
| [`agent-ctl`](src/tools/agent-ctl) | utility | Tool that provides low-level access for testing the agent. |
+| [`kata-ctl`](src/tools/kata-ctl) | utility | Tool that provides advanced commands and debug facilities. |
| [`trace-forwarder`](src/tools/trace-forwarder) | utility | Agent tracing helper. |
| [`runk`](src/tools/runk) | utility | Standard OCI container runtime based on the agent. |
| [`ci`](https://github.com/kata-containers/ci) | CI | Continuous Integration configuration files and scripts. |
diff --git a/VERSION b/VERSION
index cb2b00e4f..d0e50ca07 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.0.1
+3.1.0-alpha1
diff --git a/ci/install_libseccomp.sh b/ci/install_libseccomp.sh
index 3b1f8aa86..a1815616b 100755
--- a/ci/install_libseccomp.sh
+++ b/ci/install_libseccomp.sh
@@ -72,7 +72,8 @@ build_and_install_gperf() {
curl -sLO "${gperf_tarball_url}"
tar -xf "${gperf_tarball}"
pushd "gperf-${gperf_version}"
- # Unset $CC for configure, we will always use native for gperf
+ # gperf is a build time dependency of libseccomp and not to be used in the target.
+ # Unset $CC since that might point to a cross compiler.
CC= ./configure --prefix="${gperf_install_dir}"
make
make install
diff --git a/ci/install_yq.sh b/ci/install_yq.sh
index 56ad7d669..cc3e988b7 100755
--- a/ci/install_yq.sh
+++ b/ci/install_yq.sh
@@ -43,6 +43,16 @@ function install_yq() {
"aarch64")
goarch=arm64
;;
+ "arm64")
+ # If we're on an apple silicon machine, just assign amd64.
+ # The version of yq we use doesn't have a darwin arm build,
+ # but Rosetta can come to the rescue here.
+ if [ $goos == "Darwin" ]; then
+ goarch=amd64
+ else
+ goarch=arm64
+ fi
+ ;;
"ppc64le")
goarch=ppc64le
;;
@@ -64,7 +74,7 @@ function install_yq() {
fi
## NOTE: ${var,,} => gives lowercase value of var
- local yq_url="https://${yq_pkg}/releases/download/${yq_version}/yq_${goos,,}_${goarch}"
+ local yq_url="https://${yq_pkg}/releases/download/${yq_version}/yq_${goos}_${goarch}"
curl -o "${yq_path}" -LSsf "${yq_url}"
[ $? -ne 0 ] && die "Download ${yq_url} failed"
chmod +x "${yq_path}"
diff --git a/docs/Developer-Guide.md b/docs/Developer-Guide.md
index ed9bec490..65d81523e 100644
--- a/docs/Developer-Guide.md
+++ b/docs/Developer-Guide.md
@@ -33,51 +33,41 @@ You need to install the following to build Kata Containers components:
- `make`.
- `gcc` (required for building the shim and runtime).
-# Build and install the Kata Containers runtime
+# Build and install Kata Containers
+## Build and install the Kata Containers runtime
-```
-$ go get -d -u github.com/kata-containers/kata-containers
-$ cd $GOPATH/src/github.com/kata-containers/kata-containers/src/runtime
-$ make && sudo -E PATH=$PATH make install
+```bash
+$ git clone https://github.com/kata-containers/kata-containers.git
+$ pushd kata-containers/src/runtime
+$ make && sudo -E "PATH=$PATH" make install
+$ sudo mkdir -p /etc/kata-containers/
+$ sudo install -o root -g root -m 0640 /usr/share/defaults/kata-containers/configuration.toml /etc/kata-containers
+$ popd
```
The build will create the following:
- runtime binary: `/usr/local/bin/kata-runtime` and `/usr/local/bin/containerd-shim-kata-v2`
-- configuration file: `/usr/share/defaults/kata-containers/configuration.toml`
-
-# Check hardware requirements
-
-You can check if your system is capable of creating a Kata Container by running the following:
-
-```
-$ sudo kata-runtime check
-```
-
-If your system is *not* able to run Kata Containers, the previous command will error out and explain why.
+- configuration file: `/usr/share/defaults/kata-containers/configuration.toml` and `/etc/kata-containers/configuration.toml`
## Configure to use initrd or rootfs image
Kata containers can run with either an initrd image or a rootfs image.
-If you want to test with `initrd`, make sure you have `initrd = /usr/share/kata-containers/kata-containers-initrd.img`
-in your configuration file, commenting out the `image` line:
-
-`/usr/share/defaults/kata-containers/configuration.toml` and comment out the `image` line with the following. For example:
+If you want to test with `initrd`, make sure you have uncommented `initrd = /usr/share/kata-containers/kata-containers-initrd.img`
+in your configuration file, commenting out the `image` line in
+`/etc/kata-containers/configuration.toml`. For example:
-```
-$ sudo mkdir -p /etc/kata-containers/
-$ sudo install -o root -g root -m 0640 /usr/share/defaults/kata-containers/configuration.toml /etc/kata-containers
+```bash
$ sudo sed -i 's/^\(image =.*\)/# \1/g' /etc/kata-containers/configuration.toml
+$ sudo sed -i 's/^# \(initrd =.*\)/\1/g' /etc/kata-containers/configuration.toml
```
You can create the initrd image as shown in the [create an initrd image](#create-an-initrd-image---optional) section.
-If you want to test with a rootfs `image`, make sure you have `image = /usr/share/kata-containers/kata-containers.img`
+If you want to test with a rootfs `image`, make sure you have uncommented `image = /usr/share/kata-containers/kata-containers.img`
in your configuration file, commenting out the `initrd` line. For example:
-```
-$ sudo mkdir -p /etc/kata-containers/
-$ sudo install -o root -g root -m 0640 /usr/share/defaults/kata-containers/configuration.toml /etc/kata-containers
+```bash
$ sudo sed -i 's/^\(initrd =.*\)/# \1/g' /etc/kata-containers/configuration.toml
```
The rootfs image is created as shown in the [create a rootfs image](#create-a-rootfs-image) section.
@@ -90,19 +80,38 @@ rootfs `image`(100MB+).
Enable seccomp as follows:
-```
+```bash
$ sudo sed -i '/^disable_guest_seccomp/ s/true/false/' /etc/kata-containers/configuration.toml
```
This will pass container seccomp profiles to the kata agent.
+## Enable SELinux on the guest
+
+> **Note:**
+>
+> - To enable SELinux on the guest, SELinux MUST be also enabled on the host.
+> - You MUST create and build a rootfs image for SELinux in advance.
+> See [Create a rootfs image](#create-a-rootfs-image) and [Build a rootfs image](#build-a-rootfs-image).
+> - SELinux on the guest is supported in only a rootfs image currently, so
+> you cannot enable SELinux with the agent init (`AGENT_INIT=yes`) yet.
+
+Enable guest SELinux in Enforcing mode as follows:
+
+```
+$ sudo sed -i '/^disable_guest_selinux/ s/true/false/g' /etc/kata-containers/configuration.toml
+```
+
+The runtime automatically will set `selinux=1` to the kernel parameters and `xattr` option to
+`virtiofsd` when `disable_guest_selinux` is set to `false`.
+
+If you want to enable SELinux in Permissive mode, add `enforcing=0` to the kernel parameters.
+
## Enable full debug
Enable full debug as follows:
-```
-$ sudo mkdir -p /etc/kata-containers/
-$ sudo install -o root -g root -m 0640 /usr/share/defaults/kata-containers/configuration.toml /etc/kata-containers
+```bash
$ sudo sed -i -e 's/^# *\(enable_debug\).*=.*$/\1 = true/g' /etc/kata-containers/configuration.toml
$ sudo sed -i -e 's/^kernel_params = "\(.*\)"/kernel_params = "\1 agent.log=debug initcall_debug"/g' /etc/kata-containers/configuration.toml
```
@@ -175,7 +184,7 @@ and offers possible workarounds and fixes.
it stores. When messages are suppressed, it is noted in the logs. This can be checked
for by looking for those notifications, such as:
-```sh
+```bash
$ sudo journalctl --since today | fgrep Suppressed
Jun 29 14:51:17 mymachine systemd-journald[346]: Suppressed 4150 messages from /system.slice/docker.service
```
@@ -200,7 +209,7 @@ RateLimitBurst=0
Restart `systemd-journald` for the changes to take effect:
-```sh
+```bash
$ sudo systemctl restart systemd-journald
```
@@ -214,25 +223,24 @@ $ sudo systemctl restart systemd-journald
The agent is built with a statically linked `musl.` The default `libc` used is `musl`, but on `ppc64le` and `s390x`, `gnu` should be used. To configure this:
-```
-$ export ARCH=$(uname -m)
+```bash
+$ export ARCH="$(uname -m)"
$ if [ "$ARCH" = "ppc64le" -o "$ARCH" = "s390x" ]; then export LIBC=gnu; else export LIBC=musl; fi
-$ [ ${ARCH} == "ppc64le" ] && export ARCH=powerpc64le
-$ rustup target add ${ARCH}-unknown-linux-${LIBC}
+$ [ "${ARCH}" == "ppc64le" ] && export ARCH=powerpc64le
+$ rustup target add "${ARCH}-unknown-linux-${LIBC}"
```
To build the agent:
-```
-$ go get -d -u github.com/kata-containers/kata-containers
-$ cd $GOPATH/src/github.com/kata-containers/kata-containers/src/agent && make
+```bash
+$ make -C kata-containers/src/agent
```
The agent is built with seccomp capability by default.
If you want to build the agent without the seccomp capability, you need to run `make` with `SECCOMP=no` as follows.
-```
-$ make -C $GOPATH/src/github.com/kata-containers/kata-containers/src/agent SECCOMP=no
+```bash
+$ make -C kata-containers/src/agent SECCOMP=no
```
> **Note:**
@@ -240,13 +248,6 @@ $ make -C $GOPATH/src/github.com/kata-containers/kata-containers/src/agent SECCO
> - If you enable seccomp in the main configuration file but build the agent without seccomp capability,
> the runtime exits conservatively with an error message.
-## Get the osbuilder
-
-```
-$ go get -d -u github.com/kata-containers/kata-containers
-$ cd $GOPATH/src/github.com/kata-containers/kata-containers/tools/osbuilder
-```
-
## Create a rootfs image
### Create a local rootfs
@@ -254,24 +255,32 @@ As a prerequisite, you need to install Docker. Otherwise, you will not be
able to run the `rootfs.sh` script with `USE_DOCKER=true` as expected in
the following example.
-```
-$ export ROOTFS_DIR=${GOPATH}/src/github.com/kata-containers/kata-containers/tools/osbuilder/rootfs-builder/rootfs
-$ sudo rm -rf ${ROOTFS_DIR}
-$ cd $GOPATH/src/github.com/kata-containers/kata-containers/tools/osbuilder/rootfs-builder
-$ script -fec 'sudo -E GOPATH=$GOPATH USE_DOCKER=true ./rootfs.sh ${distro}'
+```bash
+$ export distro="ubuntu" # example
+$ export ROOTFS_DIR="$(realpath kata-containers/tools/osbuilder/rootfs-builder/rootfs)"
+$ sudo rm -rf "${ROOTFS_DIR}"
+$ pushd kata-containers/tools/osbuilder/rootfs-builder
+$ script -fec 'sudo -E USE_DOCKER=true ./rootfs.sh "${distro}"'
+$ popd
```
You MUST choose a distribution (e.g., `ubuntu`) for `${distro}`.
You can get a supported distributions list in the Kata Containers by running the following.
-```
-$ ./rootfs.sh -l
+```bash
+$ ./kata-containers/tools/osbuilder/rootfs-builder/rootfs.sh -l
```
If you want to build the agent without seccomp capability, you need to run the `rootfs.sh` script with `SECCOMP=no` as follows.
+```bash
+$ script -fec 'sudo -E AGENT_INIT=yes USE_DOCKER=true SECCOMP=no ./rootfs.sh "${distro}"'
+```
+
+If you want to enable SELinux on the guest, you MUST choose `centos` and run the `rootfs.sh` script with `SELINUX=yes` as follows.
+
```
-$ script -fec 'sudo -E GOPATH=$GOPATH AGENT_INIT=yes USE_DOCKER=true SECCOMP=no ./rootfs.sh ${distro}'
+$ script -fec 'sudo -E GOPATH=$GOPATH USE_DOCKER=true SELINUX=yes ./rootfs.sh centos'
```
> **Note:**
@@ -287,19 +296,33 @@ $ script -fec 'sudo -E GOPATH=$GOPATH AGENT_INIT=yes USE_DOCKER=true SECCOMP=no
>
> - You should only do this step if you are testing with the latest version of the agent.
-```
-$ sudo install -o root -g root -m 0550 -t ${ROOTFS_DIR}/usr/bin ../../../src/agent/target/x86_64-unknown-linux-musl/release/kata-agent
-$ sudo install -o root -g root -m 0440 ../../../src/agent/kata-agent.service ${ROOTFS_DIR}/usr/lib/systemd/system/
-$ sudo install -o root -g root -m 0440 ../../../src/agent/kata-containers.target ${ROOTFS_DIR}/usr/lib/systemd/system/
+```bash
+$ sudo install -o root -g root -m 0550 -t "${ROOTFS_DIR}/usr/bin" "${ROOTFS_DIR}/../../../../src/agent/target/x86_64-unknown-linux-musl/release/kata-agent"
+$ sudo install -o root -g root -m 0440 "${ROOTFS_DIR}/../../../../src/agent/kata-agent.service" "${ROOTFS_DIR}/usr/lib/systemd/system/"
+$ sudo install -o root -g root -m 0440 "${ROOTFS_DIR}/../../../../src/agent/kata-containers.target" "${ROOTFS_DIR}/usr/lib/systemd/system/"
```
### Build a rootfs image
+```bash
+$ pushd kata-containers/tools/osbuilder/image-builder
+$ script -fec 'sudo -E USE_DOCKER=true ./image_builder.sh "${ROOTFS_DIR}"'
+$ popd
+```
+
+If you want to enable SELinux on the guest, you MUST run the `image_builder.sh` script with `SELINUX=yes`
+to label the guest image as follows.
+To label the image on the host, you need to make sure that SELinux is enabled (`selinuxfs` is mounted) on the host
+and the rootfs MUST be created by running the `rootfs.sh` with `SELINUX=yes`.
+
```
-$ cd $GOPATH/src/github.com/kata-containers/kata-containers/tools/osbuilder/image-builder
-$ script -fec 'sudo -E USE_DOCKER=true ./image_builder.sh ${ROOTFS_DIR}'
+$ script -fec 'sudo -E USE_DOCKER=true SELINUX=yes ./image_builder.sh ${ROOTFS_DIR}'
```
+Currently, the `image_builder.sh` uses `chcon` as an interim solution in order to apply `container_runtime_exec_t`
+to the `kata-agent`. Hence, if you run `restorecon` to the guest image after running the `image_builder.sh`,
+the `kata-agent` needs to be labeled `container_runtime_exec_t` again by yourself.
+
> **Notes:**
>
> - You must ensure that the *default Docker runtime* is `runc` to make use of
@@ -313,21 +336,26 @@ $ script -fec 'sudo -E USE_DOCKER=true ./image_builder.sh ${ROOTFS_DIR}'
### Install the rootfs image
-```
-$ commit=$(git log --format=%h -1 HEAD)
-$ date=$(date +%Y-%m-%d-%T.%N%z)
+```bash
+$ pushd kata-containers/tools/osbuilder/image-builder
+$ commit="$(git log --format=%h -1 HEAD)"
+$ date="$(date +%Y-%m-%d-%T.%N%z)"
$ image="kata-containers-${date}-${commit}"
$ sudo install -o root -g root -m 0640 -D kata-containers.img "/usr/share/kata-containers/${image}"
$ (cd /usr/share/kata-containers && sudo ln -sf "$image" kata-containers.img)
+$ popd
```
## Create an initrd image - OPTIONAL
### Create a local rootfs for initrd image
-```
-$ export ROOTFS_DIR="${GOPATH}/src/github.com/kata-containers/kata-containers/tools/osbuilder/rootfs-builder/rootfs"
-$ sudo rm -rf ${ROOTFS_DIR}
-$ cd $GOPATH/src/github.com/kata-containers/kata-containers/tools/osbuilder/rootfs-builder
-$ script -fec 'sudo -E GOPATH=$GOPATH AGENT_INIT=yes USE_DOCKER=true ./rootfs.sh ${distro}'
+
+```bash
+$ export distro="ubuntu" # example
+$ export ROOTFS_DIR="$(realpath kata-containers/tools/osbuilder/rootfs-builder/rootfs)"
+$ sudo rm -rf "${ROOTFS_DIR}"
+$ pushd kata-containers/tools/osbuilder/rootfs-builder/
+$ script -fec 'sudo -E AGENT_INIT=yes USE_DOCKER=true ./rootfs.sh "${distro}"'
+$ popd
```
`AGENT_INIT` controls if the guest image uses the Kata agent as the guest `init` process. When you create an initrd image,
always set `AGENT_INIT` to `yes`.
@@ -335,14 +363,14 @@ always set `AGENT_INIT` to `yes`.
You MUST choose a distribution (e.g., `ubuntu`) for `${distro}`.
You can get a supported distributions list in the Kata Containers by running the following.
-```
-$ ./rootfs.sh -l
+```bash
+$ ./kata-containers/tools/osbuilder/rootfs-builder/rootfs.sh -l
```
If you want to build the agent without seccomp capability, you need to run the `rootfs.sh` script with `SECCOMP=no` as follows.
-```
-$ script -fec 'sudo -E GOPATH=$GOPATH AGENT_INIT=yes USE_DOCKER=true SECCOMP=no ./rootfs.sh ${distro}'
+```bash
+$ script -fec 'sudo -E AGENT_INIT=yes USE_DOCKER=true SECCOMP=no ./rootfs.sh "${distro}"'
```
> **Note:**
@@ -351,28 +379,31 @@ $ script -fec 'sudo -E GOPATH=$GOPATH AGENT_INIT=yes USE_DOCKER=true SECCOMP=no
Optionally, add your custom agent binary to the rootfs with the following commands. The default `$LIBC` used
is `musl`, but on ppc64le and s390x, `gnu` should be used. Also, Rust refers to ppc64le as `powerpc64le`:
-```
-$ export ARCH=$(uname -m)
-$ [ ${ARCH} == "ppc64le" ] || [ ${ARCH} == "s390x" ] && export LIBC=gnu || export LIBC=musl
-$ [ ${ARCH} == "ppc64le" ] && export ARCH=powerpc64le
-$ sudo install -o root -g root -m 0550 -T ../../../src/agent/target/${ARCH}-unknown-linux-${LIBC}/release/kata-agent ${ROOTFS_DIR}/sbin/init
+```bash
+$ export ARCH="$(uname -m)"
+$ [ "${ARCH}" == "ppc64le" ] || [ "${ARCH}" == "s390x" ] && export LIBC=gnu || export LIBC=musl
+$ [ "${ARCH}" == "ppc64le" ] && export ARCH=powerpc64le
+$ sudo install -o root -g root -m 0550 -T "${ROOTFS_DIR}/../../../../src/agent/target/${ARCH}-unknown-linux-${LIBC}/release/kata-agent" "${ROOTFS_DIR}/sbin/init"
```
### Build an initrd image
-```
-$ cd $GOPATH/src/github.com/kata-containers/kata-containers/tools/osbuilder/initrd-builder
-$ script -fec 'sudo -E AGENT_INIT=yes USE_DOCKER=true ./initrd_builder.sh ${ROOTFS_DIR}'
+```bash
+$ pushd kata-containers/tools/osbuilder/initrd-builder
+$ script -fec 'sudo -E AGENT_INIT=yes USE_DOCKER=true ./initrd_builder.sh "${ROOTFS_DIR}"'
+$ popd
```
### Install the initrd image
-```
-$ commit=$(git log --format=%h -1 HEAD)
-$ date=$(date +%Y-%m-%d-%T.%N%z)
+```bash
+$ pushd kata-containers/tools/osbuilder/initrd-builder
+$ commit="$(git log --format=%h -1 HEAD)"
+$ date="$(date +%Y-%m-%d-%T.%N%z)"
$ image="kata-containers-initrd-${date}-${commit}"
$ sudo install -o root -g root -m 0640 -D kata-containers-initrd.img "/usr/share/kata-containers/${image}"
$ (cd /usr/share/kata-containers && sudo ln -sf "$image" kata-containers-initrd.img)
+$ popd
```
# Install guest kernel images
@@ -391,44 +422,44 @@ Kata Containers makes use of upstream QEMU branch. The exact version
and repository utilized can be found by looking at the [versions file](../versions.yaml).
Find the correct version of QEMU from the versions file:
-```
-$ source ${GOPATH}/src/github.com/kata-containers/kata-containers/tools/packaging/scripts/lib.sh
-$ qemu_version=$(get_from_kata_deps "assets.hypervisor.qemu.version")
-$ echo ${qemu_version}
+```bash
+$ source kata-containers/tools/packaging/scripts/lib.sh
+$ qemu_version="$(get_from_kata_deps "assets.hypervisor.qemu.version")"
+$ echo "${qemu_version}"
```
Get source from the matching branch of QEMU:
-```
-$ go get -d github.com/qemu/qemu
-$ cd ${GOPATH}/src/github.com/qemu/qemu
-$ git checkout ${qemu_version}
-$ your_qemu_directory=${GOPATH}/src/github.com/qemu/qemu
+```bash
+$ git clone -b "${qemu_version}" https://github.com/qemu/qemu.git
+$ your_qemu_directory="$(realpath qemu)"
```
There are scripts to manage the build and packaging of QEMU. For the examples below, set your
environment as:
-```
-$ go get -d github.com/kata-containers/kata-containers
-$ packaging_dir="${GOPATH}/src/github.com/kata-containers/kata-containers/tools/packaging"
+```bash
+$ packaging_dir="$(realpath kata-containers/tools/packaging)"
```
Kata often utilizes patches for not-yet-upstream and/or backported fixes for components,
including QEMU. These can be found in the [packaging/QEMU directory](../tools/packaging/qemu/patches),
and it's *recommended* that you apply them. For example, suppose that you are going to build QEMU
version 5.2.0, do:
-```
-$ cd $your_qemu_directory
-$ $packaging_dir/scripts/apply_patches.sh $packaging_dir/qemu/patches/5.2.x/
+```bash
+$ "$packaging_dir/scripts/apply_patches.sh" "$packaging_dir/qemu/patches/5.2.x/"
```
To build utilizing the same options as Kata, you should make use of the `configure-hypervisor.sh` script. For example:
-```
-$ cd $your_qemu_directory
-$ $packaging_dir/scripts/configure-hypervisor.sh kata-qemu > kata.cfg
+```bash
+$ pushd "$your_qemu_directory"
+$ "$packaging_dir/scripts/configure-hypervisor.sh" kata-qemu > kata.cfg
$ eval ./configure "$(cat kata.cfg)"
$ make -j $(nproc --ignore=1)
+# Optional
$ sudo -E make install
+$ popd
```
+If you do not want to install the respective QEMU version, the configuration file can be modified to point to the correct binary. In `/etc/kata-containers/configuration.toml`, change `path = "/path/to/qemu/build/qemu-system-x86_64"` to point to the correct QEMU binary.
+
See the [static-build script for QEMU](../tools/packaging/static-build/qemu/build-static-qemu.sh) for a reference on how to get, setup, configure and build QEMU for Kata.
### Build a custom QEMU for aarch64/arm64 - REQUIRED
@@ -439,11 +470,33 @@ See the [static-build script for QEMU](../tools/packaging/static-build/qemu/buil
> under upstream review for supporting NVDIMM on aarch64.
>
You could build the custom `qemu-system-aarch64` as required with the following command:
+```bash
+$ git clone https://github.com/kata-containers/tests.git
+$ script -fec 'sudo -E tests/.ci/install_qemu.sh'
```
-$ go get -d github.com/kata-containers/tests
-$ script -fec 'sudo -E ${GOPATH}/src/github.com/kata-containers/tests/.ci/install_qemu.sh'
+
+## Build `virtiofsd`
+
+When using the file system type virtio-fs (default), `virtiofsd` is required
+
+```bash
+$ pushd kata-containers/tools/packaging/static-build/virtiofsd
+$ ./build.sh
+$ popd
```
+Modify `/etc/kata-containers/configuration.toml` and update value `virtio_fs_daemon = "/path/to/kata-containers/tools/packaging/static-build/virtiofsd/virtiofsd/virtiofsd"` to point to the binary.
+
+# Check hardware requirements
+
+You can check if your system is capable of creating a Kata Container by running the following:
+
+```bash
+$ sudo kata-runtime check
+```
+
+If your system is *not* able to run Kata Containers, the previous command will error out and explain why.
+
# Run Kata Containers with Containerd
Refer to the [How to use Kata Containers and Containerd](how-to/containerd-kata.md) how-to guide.
@@ -474,7 +527,7 @@ See [Set up a debug console](#set-up-a-debug-console).
## Checking Docker default runtime
-```
+```bash
$ sudo docker info 2>/dev/null | grep -i "default runtime" | cut -d: -f2- | grep -q runc && echo "SUCCESS" || echo "ERROR: Incorrect default Docker runtime"
```
## Set up a debug console
@@ -491,7 +544,7 @@ contain either `/bin/sh` or `/bin/bash`.
Enable debug_console_enabled in the `configuration.toml` configuration file:
-```
+```toml
[agent.kata]
debug_console_enabled = true
```
@@ -502,7 +555,7 @@ This will pass `agent.debug_console agent.debug_console_vport=1026` to agent as
For Kata Containers `2.0.x` releases, the `kata-runtime exec` command depends on the`kata-monitor` running, in order to get the sandbox's `vsock` address to connect to. Thus, first start the `kata-monitor` process.
-```
+```bash
$ sudo kata-monitor
```
@@ -564,10 +617,10 @@ an additional `coreutils` package.
For example using CentOS:
-```
-$ cd $GOPATH/src/github.com/kata-containers/kata-containers/tools/osbuilder/rootfs-builder
-$ export ROOTFS_DIR=${GOPATH}/src/github.com/kata-containers/kata-containers/tools/osbuilder/rootfs-builder/rootfs
-$ script -fec 'sudo -E GOPATH=$GOPATH USE_DOCKER=true EXTRA_PKGS="bash coreutils" ./rootfs.sh centos'
+```bash
+$ pushd kata-containers/tools/osbuilder/rootfs-builder
+$ export ROOTFS_DIR="$(realpath ./rootfs)"
+$ script -fec 'sudo -E USE_DOCKER=true EXTRA_PKGS="bash coreutils" ./rootfs.sh centos'
```
#### Build the debug image
@@ -582,9 +635,10 @@ Install the image:
>**Note**: When using an initrd image, replace the below rootfs image name `kata-containers.img`
>with the initrd image name `kata-containers-initrd.img`.
-```
+```bash
$ name="kata-containers-centos-with-debug-console.img"
$ sudo install -o root -g root -m 0640 kata-containers.img "/usr/share/kata-containers/${name}"
+$ popd
```
Next, modify the `image=` values in the `[hypervisor.qemu]` section of the
@@ -593,7 +647,7 @@ to specify the full path to the image name specified in the previous code
section. Alternatively, recreate the symbolic link so it points to
the new debug image:
-```
+```bash
$ (cd /usr/share/kata-containers && sudo ln -sf "$name" kata-containers.img)
```
@@ -604,7 +658,7 @@ to avoid all subsequently created containers from using the debug image.
Create a container as normal. For example using `crictl`:
-```
+```bash
$ sudo crictl run -r kata container.yaml pod.yaml
```
@@ -617,7 +671,7 @@ those for firecracker / cloud-hypervisor.
Add `agent.debug_console` to the guest kernel command line to allow the agent process to start a debug console.
-```
+```bash
$ sudo sed -i -e 's/^kernel_params = "\(.*\)"/kernel_params = "\1 agent.debug_console"/g' "${kata_configuration_file}"
```
@@ -638,7 +692,7 @@ between the host and the guest. The kernel command line option `agent.debug_cons
Add the parameter `agent.debug_console_vport=1026` to the kernel command line
as shown below:
-```
+```bash
sudo sed -i -e 's/^kernel_params = "\(.*\)"/kernel_params = "\1 agent.debug_console_vport=1026"/g' "${kata_configuration_file}"
```
@@ -651,7 +705,7 @@ Next, connect to the debug console. The VSOCKS paths vary slightly between each
VMM solution.
In case of cloud-hypervisor, connect to the `vsock` as shown:
-```
+```bash
$ sudo su -c 'cd /var/run/vc/vm/${sandbox_id}/root/ && socat stdin unix-connect:clh.sock'
CONNECT 1026
```
@@ -659,7 +713,7 @@ CONNECT 1026
**Note**: You need to type `CONNECT 1026` and press `RETURN` key after entering the `socat` command.
For firecracker, connect to the `hvsock` as shown:
-```
+```bash
$ sudo su -c 'cd /var/run/vc/firecracker/${sandbox_id}/root/ && socat stdin unix-connect:kata.hvsock'
CONNECT 1026
```
@@ -668,7 +722,7 @@ CONNECT 1026
For QEMU, connect to the `vsock` as shown:
-```
+```bash
$ sudo su -c 'cd /var/run/vc/vm/${sandbox_id} && socat "stdin,raw,echo=0,escape=0x11" "unix-connect:console.sock"'
```
@@ -681,7 +735,7 @@ If the image is created using
[osbuilder](../tools/osbuilder), the following YAML
file exists and contains details of the image and how it was created:
-```
+```bash
$ cat /var/lib/osbuilder/osbuilder.yaml
```
diff --git a/docs/design/README.md b/docs/design/README.md
index adcffd019..d2a9414ef 100644
--- a/docs/design/README.md
+++ b/docs/design/README.md
@@ -7,7 +7,9 @@ Kata Containers design documents:
- [Design requirements for Kata Containers](kata-design-requirements.md)
- [VSocks](VSocks.md)
- [VCPU handling](vcpu-handling.md)
+- [VCPU threads pinning](vcpu-threads-pinning.md)
- [Host cgroups](host-cgroups.md)
+- [Agent systemd cgroup](agent-systemd-cgroup.md)
- [`Inotify` support](inotify.md)
- [Metrics(Kata 2.0)](kata-2-0-metrics.md)
- [Design for Kata Containers `Lazyload` ability with `nydus`](kata-nydus-design.md)
diff --git a/docs/design/agent-systemd-cgroup.md b/docs/design/agent-systemd-cgroup.md
new file mode 100644
index 000000000..686a27b30
--- /dev/null
+++ b/docs/design/agent-systemd-cgroup.md
@@ -0,0 +1,84 @@
+# Systemd Cgroup for Agent
+
+As we know, we can interact with cgroups in two ways, **`cgroupfs`** and **`systemd`**. The former is achieved by reading and writing cgroup `tmpfs` files under `/sys/fs/cgroup` while the latter is done by configuring a transient unit by requesting systemd. Kata agent uses **`cgroupfs`** by default, unless you pass the parameter `--systemd-cgroup`.
+
+## usage
+
+For systemd, kata agent configures cgroups according to the following `linux.cgroupsPath` format standard provided by `runc` (`[slice]:[prefix]:[name]`). If you don't provide a valid `linux.cgroupsPath`, kata agent will treat it as `"system.slice:kata_agent:<container-id>"`.
+
+> Here slice is a systemd slice under which the container is placed. If empty, it defaults to system.slice, except when cgroup v2 is used and rootless container is created, in which case it defaults to user.slice.
+>
+> Note that slice can contain dashes to denote a sub-slice (e.g. user-1000.slice is a correct notation, meaning a `subslice` of user.slice), but it must not contain slashes (e.g. user.slice/user-1000.slice is invalid).
+>
+> A slice of `-` represents a root slice.
+>
+> Next, prefix and name are used to compose the unit name, which is `<prefix>-<name>.scope`, unless name has `.slice` suffix, in which case prefix is ignored and the name is used as is.
+
+## supported properties
+
+The kata agent will translate the parameters in the `linux.resources` of `config.json` into systemd unit properties, and send it to systemd for configuration. Since systemd supports limited properties, only the following parameters in `linux.resources` will be applied. We will simply treat hybrid mode as legacy mode by the way.
+
+- CPU
+
+ - v1
+
+ | runtime spec resource | systemd property name |
+ | --------------------- | --------------------- |
+ | `cpu.shares` | `CPUShares` |
+
+ - v2
+
+ | runtime spec resource | systemd property name |
+ | -------------------------- | -------------------------- |
+ | `cpu.shares` | `CPUShares` |
+ | `cpu.period` | `CPUQuotaPeriodUSec`(v242) |
+ | `cpu.period` & `cpu.quota` | `CPUQuotaPerSecUSec` |
+
+- MEMORY
+
+ - v1
+
+ | runtime spec resource | systemd property name |
+ | --------------------- | --------------------- |
+ | `memory.limit` | `MemoryLimit` |
+
+ - v2
+
+ | runtime spec resource | systemd property name |
+ | ------------------------------ | --------------------- |
+ | `memory.low` | `MemoryLow` |
+ | `memory.max` | `MemoryMax` |
+ | `memory.swap` & `memory.limit` | `MemorySwapMax` |
+
+- PIDS
+
+ | runtime spec resource | systemd property name |
+ | --------------------- | --------------------- |
+ | `pids.limit ` | `TasksMax` |
+
+- CPUSET
+
+ | runtime spec resource | systemd property name |
+ | --------------------- | -------------------------- |
+ | `cpuset.cpus` | `AllowedCPUs`(v244) |
+ | `cpuset.mems` | `AllowedMemoryNodes`(v244) |
+
+## Systemd Interface
+
+`session.rs` and `system.rs` in `src/agent/rustjail/src/cgroups/systemd/interface` are automatically generated by `zbus-xmlgen`, which is is an accompanying tool provided by `zbus` to generate Rust code from `D-Bus XML interface descriptions`. The specific commands to generate these two files are as follows:
+
+```shell
+// system.rs
+zbus-xmlgen --system org.freedesktop.systemd1 /org/freedesktop/systemd1
+// session.rs
+zbus-xmlgen --session org.freedesktop.systemd1 /org/freedesktop/systemd1
+```
+
+The current implementation of `cgroups/systemd` uses `system.rs` while `session.rs` could be used to build rootless containers in the future.
+
+## references
+
+- [runc - systemd cgroup driver](https://github.com/opencontainers/runc/blob/main/docs/systemd.md)
+
+- [systemd.resource-control — Resource control unit settings](https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html)
+
diff --git a/docs/design/arch-images/vcpus-pinning-process.png b/docs/design/arch-images/vcpus-pinning-process.png
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs/design/architecture_3.0/README.md b/docs/design/architecture_3.0/README.md
index 815940948..bc0acf6b2 100644
--- a/docs/design/architecture_3.0/README.md
+++ b/docs/design/architecture_3.0/README.md
@@ -64,8 +64,8 @@ The kata-runtime is controlled by TOKIO_RUNTIME_WORKER_THREADS to run the OS thr
├─ TTRPC listener thread(M * tokio task)
├─ TTRPC client handler thread(7 * M * tokio task)
├─ container stdin io thread(M * tokio task)
- ├─ container stdin io thread(M * tokio task)
- └─ container stdin io thread(M * tokio task)
+ ├─ container stdout io thread(M * tokio task)
+ └─ container stderr io thread(M * tokio task)
```
### Extensible Framework
The Kata 3.x runtime is designed with the extension of service, runtime, and hypervisor, combined with configuration to meet the needs of different scenarios. At present, the service provides a register mechanism to support multiple services. Services could interact with runtime through messages. In addition, the runtime handler handles messages from services. To meet the needs of a binary that supports multiple runtimes and hypervisors, the startup must obtain the runtime handler type and hypervisor type through configuration.
diff --git a/docs/design/direct-blk-device-assignment.md b/docs/design/direct-blk-device-assignment.md
index 9997d0e7a..0703140f1 100644
--- a/docs/design/direct-blk-device-assignment.md
+++ b/docs/design/direct-blk-device-assignment.md
@@ -81,7 +81,7 @@ Notes: given that the `mountInfo` is persisted to the disk by the Kata runtime,
Instead of the CSI node driver writing the mount info into a `csiPlugin.json` file under the volume root,
as described in the original proposal, here we propose that the CSI node driver passes the mount information to
the Kata Containers runtime through a new `kata-runtime` commandline command. The `kata-runtime` then writes the mount
-information to a `mount-info.json` file in a predefined location (`/run/kata-containers/shared/direct-volumes/[volume_path]/`).
+information to a `mountInfo.json` file in a predefined location (`/run/kata-containers/shared/direct-volumes/[volume_path]/`).
When the Kata Containers runtime starts a container, it verifies whether a volume mount is a direct-assigned volume by checking
whether there is a `mountInfo` file under the computed Kata `direct-volumes` directory. If it is, the runtime parses the `mountInfo` file,
diff --git a/docs/design/vcpu-threads-pinning.md b/docs/design/vcpu-threads-pinning.md
new file mode 100644
index 000000000..4de6ae986
--- /dev/null
+++ b/docs/design/vcpu-threads-pinning.md
@@ -0,0 +1,37 @@
+# Design Doc for Kata Containers' VCPUs Pinning Feature
+
+## Background
+By now, vCPU threads of Kata Containers are scheduled randomly to CPUs. And each pod would request a specific set of CPUs which we call it CPU set (just the CPU set meaning in Linux cgroups).
+
+If the number of vCPU threads are equal to that of CPUs claimed in CPU set, we can then pin each vCPU thread to one specified CPU, to reduce the cost of random scheduling.
+
+## Detailed Design
+
+### Passing Config Parameters
+Two ways are provided to use this vCPU thread pinning feature: through `QEMU` configuration file and through annotations. Finally the pinning parameter is passed to `HypervisorConfig`.
+
+### Related Linux Thread Scheduling API
+
+| API Info | Value |
+|-------------------|-----------------------------------------------------------|
+| Package | `golang.org/x/sys/unix` |
+| Method | `unix.SchedSetaffinity(thread_id, &unixCPUSet)` |
+| Official Doc Page | https://pkg.go.dev/golang.org/x/sys/unix#SchedSetaffinity |
+
+### When is VCPUs Pinning Checked?
+
+As shown in Section 1, when `num(vCPU threads) == num(CPUs in CPU set)`, we shall pin each vCPU thread to a specified CPU. And when this condition is broken, we should restore to the original random scheduling pattern.
+So when may `num(CPUs in CPU set)` change? There are 5 possible scenes:
+
+| Possible scenes | Related Code |
+|-----------------------------------|--------------------------------------------|
+| when creating a container | File Sandbox.go, in method `CreateContainer` |
+| when starting a container | File Sandbox.go, in method `StartContainer` |
+| when deleting a container | File Sandbox.go, in method `DeleteContainer` |
+| when updating a container | File Sandbox.go, in method `UpdateContainer` |
+| when creating multiple containers | File Sandbox.go, in method `createContainers` |
+
+### Core Pinning Logics
+
+We can split the whole process into the following steps. Related methods are `checkVCPUsPinning` and `resetVCPUsPinning`, in file Sandbox.go.
+![](arch-images/vcpus-pinning-process.png)
\ No newline at end of file
diff --git a/docs/design/virtualization.md b/docs/design/virtualization.md
index 3bd6ae582..074ef14a4 100644
--- a/docs/design/virtualization.md
+++ b/docs/design/virtualization.md
@@ -110,7 +110,7 @@ Devices and features used:
- VFIO
- hotplug
- seccomp filters
-- [HTTP OpenAPI](https://github.com/cloud-hypervisor/cloud-hypervisor/blob/master/vmm/src/api/openapi/cloud-hypervisor.yaml)
+- [HTTP OpenAPI](https://github.com/cloud-hypervisor/cloud-hypervisor/blob/main/vmm/src/api/openapi/cloud-hypervisor.yaml)
### Summary
diff --git a/docs/how-to/README.md b/docs/how-to/README.md
index aa09b49c7..07ca974a8 100644
--- a/docs/how-to/README.md
+++ b/docs/how-to/README.md
@@ -42,4 +42,9 @@
- [How to setup swap devices in guest kernel](how-to-setup-swap-devices-in-guest-kernel.md)
- [How to run rootless vmm](how-to-run-rootless-vmm.md)
- [How to run Docker with Kata Containers](how-to-run-docker-with-kata.md)
-- [How to run Kata Containers with `nydus`](how-to-use-virtio-fs-nydus-with-kata.md)
\ No newline at end of file
+- [How to run Kata Containers with `nydus`](how-to-use-virtio-fs-nydus-with-kata.md)
+- [How to run Kata Containers with AMD SEV-SNP](how-to-run-kata-containers-with-SNP-VMs.md)
+
+## Confidential Containers
+- [How to use build and test the Confidential Containers `CCv0` proof of concept](how-to-build-and-test-ccv0.md)
+- [How to generate a Kata Containers payload for the Confidential Containers Operator](how-to-generate-a-kata-containers-payload-for-the-confidential-containers-operator.md)
diff --git a/docs/how-to/ccv0.sh b/docs/how-to/ccv0.sh
new file mode 100755
index 000000000..6877cfb8a
--- /dev/null
+++ b/docs/how-to/ccv0.sh
@@ -0,0 +1,640 @@
+#!/bin/bash -e
+#
+# Copyright (c) 2021, 2022 IBM Corporation
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+# Disclaimer: This script is work in progress for supporting the CCv0 prototype
+# It shouldn't be considered supported by the Kata Containers community, or anyone else
+
+# Based on https://github.com/kata-containers/kata-containers/blob/main/docs/Developer-Guide.md,
+# but with elements of the tests/.ci scripts used
+
+readonly script_name="$(basename "${BASH_SOURCE[0]}")"
+
+# By default in Golang >= 1.16 GO111MODULE is set to "on", but not all modules support it, so overwrite to "auto"
+export GO111MODULE="auto"
+
+# Setup kata containers environments if not set - we default to use containerd
+export CRI_CONTAINERD=${CRI_CONTAINERD:-"yes"}
+export CRI_RUNTIME=${CRI_RUNTIME:-"containerd"}
+export CRIO=${CRIO:-"no"}
+export KATA_HYPERVISOR="${KATA_HYPERVISOR:-qemu}"
+export KUBERNETES=${KUBERNETES:-"no"}
+export AGENT_INIT="${AGENT_INIT:-${TEST_INITRD:-no}}"
+export AA_KBC="${AA_KBC:-offline_fs_kbc}"
+
+# Allow the user to overwrite the default repo and branch names if they want to build from a fork
+export katacontainers_repo="${katacontainers_repo:-github.com/kata-containers/kata-containers}"
+export katacontainers_branch="${katacontainers_branch:-CCv0}"
+export kata_default_branch=${katacontainers_branch}
+export tests_repo="${tests_repo:-github.com/kata-containers/tests}"
+export tests_branch="${tests_branch:-CCv0}"
+export target_branch=${tests_branch} # kata-containers/ci/lib.sh uses target branch var to check out tests repo
+
+# if .bash_profile exists then use it, otherwise fall back to .profile
+export PROFILE="${HOME}/.profile"
+if [ -r "${HOME}/.bash_profile" ]; then
+ export PROFILE="${HOME}/.bash_profile"
+fi
+# Stop PS1: unbound variable error happening
+export PS1=${PS1:-}
+
+# Create a bunch of common, derived values up front so we don't need to create them in all the different functions
+. ${PROFILE}
+if [ -z ${GOPATH} ]; then
+ export GOPATH=${HOME}/go
+fi
+export tests_repo_dir="${GOPATH}/src/${tests_repo}"
+export katacontainers_repo_dir="${GOPATH}/src/${katacontainers_repo}"
+export ROOTFS_DIR="${katacontainers_repo_dir}/tools/osbuilder/rootfs-builder/rootfs"
+export PULL_IMAGE="${PULL_IMAGE:-quay.io/kata-containers/confidential-containers:signed}" # Doesn't need authentication
+export CONTAINER_ID="${CONTAINER_ID:-0123456789}"
+source /etc/os-release || source /usr/lib/os-release
+grep -Eq "\<fedora\>" /etc/os-release 2> /dev/null && export USE_PODMAN=true
+
+
+# If we've already checked out the test repo then source the confidential scripts
+if [ "${KUBERNETES}" == "yes" ]; then
+ export BATS_TEST_DIRNAME="${tests_repo_dir}/integration/kubernetes/confidential"
+ [ -d "${BATS_TEST_DIRNAME}" ] && source "${BATS_TEST_DIRNAME}/lib.sh"
+else
+ export BATS_TEST_DIRNAME="${tests_repo_dir}/integration/containerd/confidential"
+ [ -d "${BATS_TEST_DIRNAME}" ] && source "${BATS_TEST_DIRNAME}/lib.sh"
+fi
+
+[ -d "${BATS_TEST_DIRNAME}" ] && source "${BATS_TEST_DIRNAME}/../../confidential/lib.sh"
+
+export RUNTIME_CONFIG_PATH=/etc/kata-containers/configuration.toml
+
+usage() {
+ exit_code="$1"
+ cat <<EOF
+Overview:
+ Build and test kata containers from source
+ Optionally set kata-containers and tests repo and branch as exported variables before running
+ e.g. export katacontainers_repo=github.com/stevenhorsman/kata-containers && export katacontainers_branch=kata-ci-from-fork && export tests_repo=github.com/stevenhorsman/tests && export tests_branch=kata-ci-from-fork && ~/${script_name} build_and_install_all
+Usage:
+ ${script_name} [options] <command>
+Commands:
+- agent_create_container: Run CreateContainer command against the agent with agent-ctl
+- agent_pull_image: Run PullImage command against the agent with agent-ctl
+- all: Build and install everything, test kata with containerd and capture the logs
+- build_and_add_agent_to_rootfs: Builds the kata-agent and adds it to the rootfs
+- build_and_install_all: Build and install everything
+- build_and_install_rootfs: Builds and installs the rootfs image
+- build_kata_runtime: Build and install the kata runtime
+- build_cloud_hypervisor Checkout, patch, build and install Cloud Hypervisor
+- build_qemu: Checkout, patch, build and install QEMU
+- configure: Configure Kata to use rootfs and enable debug
+- connect_to_ssh_demo_pod: Ssh into the ssh demo pod, showing that the decryption succeeded
+- copy_signature_files_to_guest Copies signature verification files to guest
+- create_rootfs: Create a local rootfs
+- crictl_create_cc_container Use crictl to create a new busybox container in the kata cc pod
+- crictl_create_cc_pod Use crictl to create a new kata cc pod
+- crictl_delete_cc Use crictl to delete the kata cc pod sandbox and container in it
+- help: Display this help
+- init_kubernetes: initialize a Kubernetes cluster on this system
+- initialize: Install dependencies and check out kata-containers source
+- install_guest_kernel: Setup, build and install the guest kernel
+- kubernetes_create_cc_pod: Create a Kata CC runtime busybox-based pod in Kubernetes
+- kubernetes_create_ssh_demo_pod: Create a Kata CC runtime pod based on the ssh demo
+- kubernetes_delete_cc_pod: Delete the Kata CC runtime busybox-based pod in Kubernetes
+- kubernetes_delete_ssh_demo_pod: Delete the Kata CC runtime pod based on the ssh demo
+- open_kata_shell: Open a shell into the kata runtime
+- rebuild_and_install_kata: Rebuild the kata runtime and agent and build and install the image
+- shim_pull_image: Run PullImage command against the shim with ctr
+- test_capture_logs: Test using kata with containerd and capture the logs in the user's home directory
+- test: Test using kata with containerd
+
+Options:
+ -d: Enable debug
+ -h: Display this help
+EOF
+ # if script sourced don't exit as this will exit the main shell, just return instead
+ [[ $_ != $0 ]] && return "$exit_code" || exit "$exit_code"
+}
+
+build_and_install_all() {
+ initialize
+ build_and_install_kata_runtime
+ configure
+ create_a_local_rootfs
+ build_and_install_rootfs
+ install_guest_kernel_image
+ case "$KATA_HYPERVISOR" in
+ "qemu")
+ build_qemu
+ ;;
+ "cloud-hypervisor")
+ build_cloud_hypervisor
+ ;;
+ *)
+ echo "Invalid option: $KATA_HYPERVISOR is not supported." >&2
+ ;;
+ esac
+
+ check_kata_runtime
+ if [ "${KUBERNETES}" == "yes" ]; then
+ init_kubernetes
+ fi
+}
+
+rebuild_and_install_kata() {
+ checkout_tests_repo
+ checkout_kata_containers_repo
+ build_and_install_kata_runtime
+ build_and_add_agent_to_rootfs
+ build_and_install_rootfs
+ check_kata_runtime
+}
+
+# Based on the jenkins_job_build.sh script in kata-containers/tests/.ci - checks out source code and installs dependencies
+initialize() {
+ # We need git to checkout and bootstrap the ci scripts and some other packages used in testing
+ sudo apt-get update && sudo apt-get install -y curl git qemu-utils
+
+ grep -qxF "export GOPATH=\${HOME}/go" "${PROFILE}" || echo "export GOPATH=\${HOME}/go" >> "${PROFILE}"
+ grep -qxF "export GOROOT=/usr/local/go" "${PROFILE}" || echo "export GOROOT=/usr/local/go" >> "${PROFILE}"
+ grep -qxF "export PATH=\${GOPATH}/bin:/usr/local/go/bin:\${PATH}" "${PROFILE}" || echo "export PATH=\${GOPATH}/bin:/usr/local/go/bin:\${PATH}" >> "${PROFILE}"
+
+ # Load the new go and PATH parameters from the profile
+ . ${PROFILE}
+ mkdir -p "${GOPATH}"
+
+ checkout_tests_repo
+
+ pushd "${tests_repo_dir}"
+ local ci_dir_name=".ci"
+ sudo -E PATH=$PATH -s "${ci_dir_name}/install_go.sh" -p -f
+ sudo -E PATH=$PATH -s "${ci_dir_name}/install_rust.sh"
+ # Need to change ownership of rustup so later process can create temp files there
+ sudo chown -R ${USER}:${USER} "${HOME}/.rustup"
+
+ checkout_kata_containers_repo
+
+ # Run setup, but don't install kata as we will build it ourselves in locations matching the developer guide
+ export INSTALL_KATA="no"
+ sudo -E PATH=$PATH -s ${ci_dir_name}/setup.sh
+ # Reload the profile to pick up installed dependencies
+ . ${PROFILE}
+ popd
+}
+
+checkout_tests_repo() {
+ echo "Creating repo: ${tests_repo} and branch ${tests_branch} into ${tests_repo_dir}..."
+ # Due to git https://github.blog/2022-04-12-git-security-vulnerability-announced/ the tests repo needs
+ # to be owned by root as it is re-checked out in rootfs.sh
+ mkdir -p $(dirname "${tests_repo_dir}")
+ [ -d "${tests_repo_dir}" ] || sudo -E git clone "https://${tests_repo}.git" "${tests_repo_dir}"
+ sudo -E chown -R root:root "${tests_repo_dir}"
+ pushd "${tests_repo_dir}"
+ sudo -E git fetch
+ if [ -n "${tests_branch}" ]; then
+ sudo -E git checkout ${tests_branch}
+ fi
+ sudo -E git reset --hard origin/${tests_branch}
+ popd
+
+ source "${BATS_TEST_DIRNAME}/lib.sh"
+ source "${BATS_TEST_DIRNAME}/../../confidential/lib.sh"
+}
+
+# Note: clone_katacontainers_repo using go, so that needs to be installed first
+checkout_kata_containers_repo() {
+ source "${tests_repo_dir}/.ci/lib.sh"
+ echo "Creating repo: ${katacontainers_repo} and branch ${kata_default_branch} into ${katacontainers_repo_dir}..."
+ clone_katacontainers_repo
+ sudo -E chown -R ${USER}:${USER} "${katacontainers_repo_dir}"
+}
+
+build_and_install_kata_runtime() {
+ pushd ${katacontainers_repo_dir}/src/runtime
+ make clean && make DEFAULT_HYPERVISOR=${KATA_HYPERVISOR} && sudo -E PATH=$PATH make DEFAULT_HYPERVISOR=${KATA_HYPERVISOR} install
+ popd
+}
+
+configure() {
+ configure_kata_to_use_rootfs
+ enable_full_debug
+ enable_agent_console
+
+ # Switch image offload to true in kata config
+ switch_image_service_offload "on"
+
+ configure_cc_containerd
+ # From crictl v1.24.1 the default timoout leads to the pod creation failing, so update it
+ sudo crictl config --set timeout=10
+}
+
+configure_kata_to_use_rootfs() {
+ sudo mkdir -p /etc/kata-containers/
+ sudo install -o root -g root -m 0640 /usr/share/defaults/kata-containers/configuration.toml /etc/kata-containers
+ sudo sed -i 's/^\(initrd =.*\)/# \1/g' ${RUNTIME_CONFIG_PATH}
+}
+
+build_and_add_agent_to_rootfs() {
+ build_a_custom_kata_agent
+ add_custom_agent_to_rootfs
+}
+
+build_a_custom_kata_agent() {
+ # Install libseccomp for static linking
+ sudo -E PATH=$PATH GOPATH=$GOPATH ${katacontainers_repo_dir}/ci/install_libseccomp.sh /tmp/kata-libseccomp /tmp/kata-gperf
+ export LIBSECCOMP_LINK_TYPE=static
+ export LIBSECCOMP_LIB_PATH=/tmp/kata-libseccomp/lib
+
+ . "$HOME/.cargo/env"
+ pushd ${katacontainers_repo_dir}/src/agent
+ sudo -E PATH=$PATH make
+
+ ARCH=$(uname -m)
+ [ ${ARCH} == "ppc64le" ] || [ ${ARCH} == "s390x" ] && export LIBC=gnu || export LIBC=musl
+ [ ${ARCH} == "ppc64le" ] && export ARCH=powerpc64le
+
+ # Run a make install into the rootfs directory in order to create the kata-agent.service file which is required when we add to the rootfs
+ sudo -E PATH=$PATH make install DESTDIR="${ROOTFS_DIR}"
+ popd
+}
+
+create_a_local_rootfs() {
+ sudo rm -rf "${ROOTFS_DIR}"
+ pushd ${katacontainers_repo_dir}/tools/osbuilder/rootfs-builder
+ export distro="ubuntu"
+ [[ -z "${USE_PODMAN:-}" ]] && use_docker="${use_docker:-1}"
+ sudo -E OS_VERSION="${OS_VERSION:-}" GOPATH=$GOPATH EXTRA_PKGS="vim iputils-ping net-tools" DEBUG="${DEBUG:-}" USE_DOCKER="${use_docker:-}" SKOPEO=${SKOPEO:-} AA_KBC=${AA_KBC:-} UMOCI=yes SECCOMP=yes ./rootfs.sh -r ${ROOTFS_DIR} ${distro}
+
+ # Install_rust.sh during rootfs.sh switches us to the main branch of the tests repo, so switch back now
+ pushd "${tests_repo_dir}"
+ sudo -E git checkout ${tests_branch}
+ popd
+ # During the ./rootfs.sh call the kata agent is built as root, so we need to update the permissions, so we can rebuild it
+ sudo chown -R ${USER}:${USER} "${katacontainers_repo_dir}/src/agent/"
+
+ popd
+}
+
+add_custom_agent_to_rootfs() {
+ pushd ${katacontainers_repo_dir}/tools/osbuilder/rootfs-builder
+
+ ARCH=$(uname -m)
+ [ ${ARCH} == "ppc64le" ] || [ ${ARCH} == "s390x" ] && export LIBC=gnu || export LIBC=musl
+ [ ${ARCH} == "ppc64le" ] && export ARCH=powerpc64le
+
+ sudo install -o root -g root -m 0550 -t ${ROOTFS_DIR}/usr/bin ${katacontainers_repo_dir}/src/agent/target/${ARCH}-unknown-linux-${LIBC}/release/kata-agent
+ sudo install -o root -g root -m 0440 ../../../src/agent/kata-agent.service ${ROOTFS_DIR}/usr/lib/systemd/system/
+ sudo install -o root -g root -m 0440 ../../../src/agent/kata-containers.target ${ROOTFS_DIR}/usr/lib/systemd/system/
+ popd
+}
+
+build_and_install_rootfs() {
+ build_rootfs_image
+ install_rootfs_image
+}
+
+build_rootfs_image() {
+ pushd ${katacontainers_repo_dir}/tools/osbuilder/image-builder
+ # Logic from install_kata_image.sh - if we aren't using podman (ie on a fedora like), then use docker
+ [[ -z "${USE_PODMAN:-}" ]] && use_docker="${use_docker:-1}"
+ sudo -E USE_DOCKER="${use_docker:-}" ./image_builder.sh ${ROOTFS_DIR}
+ popd
+}
+
+install_rootfs_image() {
+ pushd ${katacontainers_repo_dir}/tools/osbuilder/image-builder
+ local commit=$(git log --format=%h -1 HEAD)
+ local date=$(date +%Y-%m-%d-%T.%N%z)
+ local image="kata-containers-${date}-${commit}"
+ sudo install -o root -g root -m 0640 -D kata-containers.img "/usr/share/kata-containers/${image}"
+ (cd /usr/share/kata-containers && sudo ln -sf "$image" kata-containers.img)
+ echo "Built Rootfs from ${ROOTFS_DIR} to /usr/share/kata-containers/${image}"
+ ls -al /usr/share/kata-containers/
+ popd
+}
+
+install_guest_kernel_image() {
+ pushd ${katacontainers_repo_dir}/tools/packaging/kernel
+ sudo -E PATH=$PATH ./build-kernel.sh setup
+ sudo -E PATH=$PATH ./build-kernel.sh build
+ sudo chmod u+wrx /usr/share/kata-containers/ # Give user permission to install kernel
+ sudo -E PATH=$PATH ./build-kernel.sh install
+ popd
+}
+
+build_qemu() {
+ ${tests_repo_dir}/.ci/install_virtiofsd.sh
+ ${tests_repo_dir}/.ci/install_qemu.sh
+}
+
+build_cloud_hypervisor() {
+ ${tests_repo_dir}/.ci/install_virtiofsd.sh
+ ${tests_repo_dir}/.ci/install_cloud_hypervisor.sh
+}
+
+check_kata_runtime() {
+ sudo kata-runtime check
+}
+
+k8s_pod_file="${HOME}/busybox-cc.yaml"
+init_kubernetes() {
+ # Check that kubeadm was installed and install it otherwise
+ if ! [ -x "$(command -v kubeadm)" ]; then
+ pushd "${tests_repo_dir}/.ci"
+ sudo -E PATH=$PATH -s install_kubernetes.sh
+ if [ "${CRI_CONTAINERD}" == "yes" ]; then
+ sudo -E PATH=$PATH -s "configure_containerd_for_kubernetes.sh"
+ fi
+ popd
+ fi
+
+ # If kubernetes init has previously run we need to clean it by removing the image and resetting k8s
+ local cid=$(sudo docker ps -a -q -f name=^/kata-registry$)
+ if [ -n "${cid}" ]; then
+ sudo docker stop ${cid} && sudo docker rm ${cid}
+ fi
+ local k8s_nodes=$(kubectl get nodes -o name 2>/dev/null || true)
+ if [ -n "${k8s_nodes}" ]; then
+ sudo kubeadm reset -f
+ fi
+
+ export CI="true" && sudo -E PATH=$PATH -s ${tests_repo_dir}/integration/kubernetes/init.sh
+ sudo chown ${USER}:$(id -g -n ${USER}) "$HOME/.kube/config"
+ cat << EOF > ${k8s_pod_file}
+apiVersion: v1
+kind: Pod
+metadata:
+ name: busybox-cc
+spec:
+ runtimeClassName: kata
+ containers:
+ - name: nginx
+ image: quay.io/kata-containers/confidential-containers:signed
+ imagePullPolicy: Always
+EOF
+}
+
+call_kubernetes_create_cc_pod() {
+ kubernetes_create_cc_pod ${k8s_pod_file}
+}
+
+call_kubernetes_delete_cc_pod() {
+ pod_name=$(kubectl get pods -o jsonpath='{.items..metadata.name}')
+ kubernetes_delete_cc_pod $pod_name
+}
+
+call_kubernetes_create_ssh_demo_pod() {
+ setup_decryption_files_in_guest
+ kubernetes_create_ssh_demo_pod
+}
+
+call_connect_to_ssh_demo_pod() {
+ connect_to_ssh_demo_pod
+}
+
+call_kubernetes_delete_ssh_demo_pod() {
+ pod=$(kubectl get pods -o jsonpath='{.items..metadata.name}')
+ kubernetes_delete_ssh_demo_pod $pod
+}
+
+crictl_sandbox_name=kata-cc-busybox-sandbox
+call_crictl_create_cc_pod() {
+ # Update iptables to allow forwarding to the cni0 bridge avoiding issues caused by the docker0 bridge
+ sudo iptables -P FORWARD ACCEPT
+
+ # get_pod_config in tests_common exports `pod_config` that points to the prepared pod config yaml
+ get_pod_config
+
+ crictl_delete_cc_pod_if_exists "${crictl_sandbox_name}"
+ crictl_create_cc_pod "${pod_config}"
+ sudo crictl pods
+}
+
+call_crictl_create_cc_container() {
+ # Create container configuration yaml based on our test copy of busybox
+ # get_pod_config in tests_common exports `pod_config` that points to the prepared pod config yaml
+ get_pod_config
+
+ local container_config="${FIXTURES_DIR}/${CONTAINER_CONFIG_FILE:-container-config.yaml}"
+ local pod_name=${crictl_sandbox_name}
+ crictl_create_cc_container ${pod_name} ${pod_config} ${container_config}
+ sudo crictl ps -a
+}
+
+crictl_delete_cc() {
+ crictl_delete_cc_pod ${crictl_sandbox_name}
+}
+
+test_kata_runtime() {
+ echo "Running ctr with the kata runtime..."
+ local test_image="quay.io/kata-containers/confidential-containers:signed"
+ if [ -z $(ctr images ls -q name=="${test_image}") ]; then
+ sudo ctr image pull "${test_image}"
+ fi
+ sudo ctr run --runtime "io.containerd.kata.v2" --rm -t "${test_image}" test-kata uname -a
+}
+
+run_kata_and_capture_logs() {
+ echo "Clearing systemd journal..."
+ sudo systemctl stop systemd-journald
+ sudo rm -f /var/log/journal/*/* /run/log/journal/*/*
+ sudo systemctl start systemd-journald
+ test_kata_runtime
+ echo "Collecting logs..."
+ sudo journalctl -q -o cat -a -t kata-runtime > ${HOME}/kata-runtime.log
+ sudo journalctl -q -o cat -a -t kata > ${HOME}/shimv2.log
+ echo "Logs output to ${HOME}/kata-runtime.log and ${HOME}/shimv2.log"
+}
+
+get_ids() {
+ guest_cid=$(sudo ss -H --vsock | awk '{print $6}' | cut -d: -f1)
+ sandbox_id=$(ps -ef | grep containerd-shim-kata-v2 | egrep -o "id [^,][^,].* " | awk '{print $2}')
+}
+
+open_kata_shell() {
+ get_ids
+ sudo -E "PATH=$PATH" kata-runtime exec ${sandbox_id}
+}
+
+build_bundle_dir_if_necessary() {
+ bundle_dir="/tmp/bundle"
+ if [ ! -d "${bundle_dir}" ]; then
+ rootfs_dir="$bundle_dir/rootfs"
+ image="quay.io/kata-containers/confidential-containers:signed"
+ mkdir -p "$rootfs_dir" && (cd "$bundle_dir" && runc spec)
+ sudo docker export $(sudo docker create "$image") | tar -C "$rootfs_dir" -xvf -
+ fi
+ # There were errors in create container agent-ctl command due to /bin/ seemingly not being on the path, so hardcode it
+ sudo sed -i -e 's%^\(\t*\)"sh"$%\1"/bin/sh"%g' "${bundle_dir}/config.json"
+}
+
+build_agent_ctl() {
+ cd ${GOPATH}/src/${katacontainers_repo}/src/tools/agent-ctl/
+ if [ -e "${HOME}/.cargo/registry" ]; then
+ sudo chown -R ${USER}:${USER} "${HOME}/.cargo/registry"
+ fi
+ sudo -E PATH=$PATH -s make
+ ARCH=$(uname -m)
+ [ ${ARCH} == "ppc64le" ] || [ ${ARCH} == "s390x" ] && export LIBC=gnu || export LIBC=musl
+ [ ${ARCH} == "ppc64le" ] && export ARCH=powerpc64le
+ cd "./target/${ARCH}-unknown-linux-${LIBC}/release/"
+}
+
+run_agent_ctl_command() {
+ get_ids
+ build_bundle_dir_if_necessary
+ command=$1
+ # If kata-agent-ctl pre-built in this directory, use it directly, otherwise build it first and switch to release
+ if [ ! -x kata-agent-ctl ]; then
+ build_agent_ctl
+ fi
+ ./kata-agent-ctl -l debug connect --bundle-dir "${bundle_dir}" --server-address "vsock://${guest_cid}:1024" -c "${command}"
+}
+
+agent_pull_image() {
+ run_agent_ctl_command "PullImage image=${PULL_IMAGE} cid=${CONTAINER_ID} source_creds=${SOURCE_CREDS}"
+}
+
+agent_create_container() {
+ run_agent_ctl_command "CreateContainer cid=${CONTAINER_ID}"
+}
+
+shim_pull_image() {
+ get_ids
+ local ctr_shim_command="sudo ctr --namespace k8s.io shim --id ${sandbox_id} pull-image ${PULL_IMAGE} ${CONTAINER_ID}"
+ echo "Issuing command '${ctr_shim_command}'"
+ ${ctr_shim_command}
+}
+
+call_copy_signature_files_to_guest() {
+ # TODO #5173 - remove this once the kernel_params aren't ignored by the agent config
+ export DEBUG_CONSOLE="true"
+
+ if [ "${SKOPEO:-}" = "yes" ]; then
+ add_kernel_params "agent.container_policy_file=/etc/containers/quay_verification/quay_policy.json"
+ setup_skopeo_signature_files_in_guest
+ else
+ # TODO #4888 - set config to specifically enable signature verification to be on in ImageClient
+ setup_offline_fs_kbc_signature_files_in_guest
+ fi
+}
+
+main() {
+ while getopts "dh" opt; do
+ case "$opt" in
+ d)
+ export DEBUG="-d"
+ set -x
+ ;;
+ h)
+ usage 0
+ ;;
+ \?)
+ echo "Invalid option: -$OPTARG" >&2
+ usage 1
+ ;;
+ esac
+ done
+
+ shift $((OPTIND - 1))
+
+ subcmd="${1:-}"
+
+ [ -z "${subcmd}" ] && usage 1
+
+ case "${subcmd}" in
+ all)
+ build_and_install_all
+ run_kata_and_capture_logs
+ ;;
+ build_and_install_all)
+ build_and_install_all
+ ;;
+ rebuild_and_install_kata)
+ rebuild_and_install_kata
+ ;;
+ initialize)
+ initialize
+ ;;
+ build_kata_runtime)
+ build_and_install_kata_runtime
+ ;;
+ configure)
+ configure
+ ;;
+ create_rootfs)
+ create_a_local_rootfs
+ ;;
+ build_and_add_agent_to_rootfs)
+ build_and_add_agent_to_rootfs
+ ;;
+ build_and_install_rootfs)
+ build_and_install_rootfs
+ ;;
+ install_guest_kernel)
+ install_guest_kernel_image
+ ;;
+ build_cloud_hypervisor)
+ build_cloud_hypervisor
+ ;;
+ build_qemu)
+ build_qemu
+ ;;
+ init_kubernetes)
+ init_kubernetes
+ ;;
+ crictl_create_cc_pod)
+ call_crictl_create_cc_pod
+ ;;
+ crictl_create_cc_container)
+ call_crictl_create_cc_container
+ ;;
+ crictl_delete_cc)
+ crictl_delete_cc
+ ;;
+ kubernetes_create_cc_pod)
+ call_kubernetes_create_cc_pod
+ ;;
+ kubernetes_delete_cc_pod)
+ call_kubernetes_delete_cc_pod
+ ;;
+ kubernetes_create_ssh_demo_pod)
+ call_kubernetes_create_ssh_demo_pod
+ ;;
+ connect_to_ssh_demo_pod)
+ call_connect_to_ssh_demo_pod
+ ;;
+ kubernetes_delete_ssh_demo_pod)
+ call_kubernetes_delete_ssh_demo_pod
+ ;;
+ test)
+ test_kata_runtime
+ ;;
+ test_capture_logs)
+ run_kata_and_capture_logs
+ ;;
+ open_kata_console)
+ open_kata_console
+ ;;
+ open_kata_shell)
+ open_kata_shell
+ ;;
+ agent_pull_image)
+ agent_pull_image
+ ;;
+ shim_pull_image)
+ shim_pull_image
+ ;;
+ agent_create_container)
+ agent_create_container
+ ;;
+ copy_signature_files_to_guest)
+ call_copy_signature_files_to_guest
+ ;;
+ *)
+ usage 1
+ ;;
+ esac
+}
+
+main $@
diff --git a/docs/how-to/containerd-kata.md b/docs/how-to/containerd-kata.md
index 1ec271416..71efa6754 100644
--- a/docs/how-to/containerd-kata.md
+++ b/docs/how-to/containerd-kata.md
@@ -77,8 +77,8 @@ $ command -v containerd
You can manually install CNI plugins as follows:
```bash
-$ go get github.com/containernetworking/plugins
-$ pushd $GOPATH/src/github.com/containernetworking/plugins
+$ git clone https://github.com/containernetworking/plugins.git
+$ pushd plugins
$ ./build_linux.sh
$ sudo mkdir /opt/cni
$ sudo cp -r bin /opt/cni/
@@ -93,8 +93,8 @@ $ popd
You can install the `cri-tools` from source code:
```bash
-$ go get github.com/kubernetes-sigs/cri-tools
-$ pushd $GOPATH/src/github.com/kubernetes-sigs/cri-tools
+$ git clone https://github.com/kubernetes-sigs/cri-tools.git
+$ pushd cri-tools
$ make
$ sudo -E make install
$ popd
@@ -257,6 +257,48 @@ This launches a BusyBox container named `hello`, and it will be removed by `--rm
The `--cni` flag enables CNI networking for the container. Without this flag, a container with just a
loopback interface is created.
+### Launch containers using `ctr` command line with rootfs bundle
+
+#### Get rootfs
+Use the script to create rootfs
+```bash
+ctr i pull quay.io/prometheus/busybox:latest
+ctr i export rootfs.tar quay.io/prometheus/busybox:latest
+
+rootfs_tar=rootfs.tar
+bundle_dir="./bundle"
+mkdir -p "${bundle_dir}"
+
+# extract busybox rootfs
+rootfs_dir="${bundle_dir}/rootfs"
+mkdir -p "${rootfs_dir}"
+layers_dir="$(mktemp -d)"
+tar -C "${layers_dir}" -pxf "${rootfs_tar}"
+for ((i=0;i<$(cat ${layers_dir}/manifest.json | jq -r ".[].Layers | length");i++)); do
+ tar -C ${rootfs_dir} -xf ${layers_dir}/$(cat ${layers_dir}/manifest.json | jq -r ".[].Layers[${i}]")
+done
+```
+#### Get `config.json`
+Use runc spec to generate `config.json`
+```bash
+cd ./bundle/rootfs
+runc spec
+mv config.json ../
+```
+Change the root `path` in `config.json` to the absolute path of rootfs
+
+```JSON
+"root":{
+ "path":"/root/test/bundle/rootfs",
+ "readonly": false
+},
+```
+
+#### Run container
+```bash
+sudo ctr run -d --runtime io.containerd.run.kata.v2 --config bundle/config.json hello
+sudo ctr t exec --exec-id ${ID} -t hello sh
+```
### Launch Pods with `crictl` command line
With the `crictl` command line of `cri-tools`, you can specify runtime class with `-r` or `--runtime` flag.
diff --git a/docs/how-to/data/confidential-agent-config.toml.in b/docs/how-to/data/confidential-agent-config.toml.in
new file mode 100644
index 000000000..29c727744
--- /dev/null
+++ b/docs/how-to/data/confidential-agent-config.toml.in
@@ -0,0 +1,45 @@
+# Copyright (c) 2021 IBM Corp.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+aa_kbc_params = "$AA_KBC_PARAMS"
+https_proxy = "$HTTPS_PROXY"
+[endpoints]
+allowed = [
+"AddARPNeighborsRequest",
+"AddSwapRequest",
+"CloseStdinRequest",
+"CopyFileRequest",
+"CreateContainerRequest",
+"CreateSandboxRequest",
+"DestroySandboxRequest",
+#"ExecProcessRequest",
+"GetMetricsRequest",
+"GetOOMEventRequest",
+"GuestDetailsRequest",
+"ListInterfacesRequest",
+"ListRoutesRequest",
+"MemHotplugByProbeRequest",
+"OnlineCPUMemRequest",
+"PauseContainerRequest",
+"PullImageRequest",
+"ReadStreamRequest",
+"RemoveContainerRequest",
+#"ReseedRandomDevRequest",
+"ResizeVolumeRequest",
+"ResumeContainerRequest",
+"SetGuestDateTimeRequest",
+"SignalProcessRequest",
+"StartContainerRequest",
+"StartTracingRequest",
+"StatsContainerRequest",
+"StopTracingRequest",
+"TtyWinResizeRequest",
+"UpdateContainerRequest",
+"UpdateInterfaceRequest",
+"UpdateRoutesRequest",
+"VolumeStatsRequest",
+"WaitProcessRequest",
+"WriteStreamRequest"
+]
diff --git a/docs/how-to/how-to-build-and-test-ccv0.md b/docs/how-to/how-to-build-and-test-ccv0.md
new file mode 100644
index 000000000..64792205a
--- /dev/null
+++ b/docs/how-to/how-to-build-and-test-ccv0.md
@@ -0,0 +1,479 @@
+# How to build, run and test Kata CCv0
+
+## Introduction and Background
+
+In order to try and make building (locally) and demoing the Kata Containers `CCv0` code base as simple as possible I've
+shared a script [`ccv0.sh`](./ccv0.sh). This script was originally my attempt to automate the steps of the
+[Developer Guide](https://github.com/kata-containers/kata-containers/blob/main/docs/Developer-Guide.md) so that I could do
+different sections of them repeatedly and reliably as I was playing around with make changes to different parts of the
+Kata code base. I then tried to weave in some of the [`tests/.ci`](https://github.com/kata-containers/tests/tree/main/.ci)
+scripts in order to have less duplicated code.
+As we're progress on the confidential containers journey I hope to add more features to demonstrate the functionality
+we have working.
+
+*Disclaimer: This script has mostly just been used and tested by me ([@stevenhorsman](https://github.com/stevenhorsman)),*
+*so there might be issues with it. I'm happy to try and help solve these if possible, but this shouldn't be considered a*
+*fully supported process by the Kata Containers community.*
+
+### Basic script set-up and optional environment variables
+
+In order to build, configure and demo the CCv0 functionality, these are the set-up steps I take:
+- Provision a new VM
+ - *I choose a Ubuntu 20.04 8GB VM for this as I had one available. There are some dependences on apt-get installed*
+ *packages, so these will need re-working to be compatible with other platforms.*
+- Copy the script over to your VM *(I put it in the home directory)* and ensure it has execute permission by running
+```bash
+$ chmod u+x ccv0.sh
+```
+- Optionally set up some environment variables
+ - By default the script checks out the `CCv0` branches of the `kata-containers/kata-containers` and
+ `kata-containers/tests` repositories, but it is designed to be used to test of personal forks and branches as well.
+ If you want to build and run these you can export the `katacontainers_repo`, `katacontainers_branch`, `tests_repo`
+ and `tests_branch` variables e.g.
+ ```bash
+ $ export katacontainers_repo=github.com/stevenhorsman/kata-containers
+ $ export katacontainers_branch=stevenh/agent-pull-image-endpoint
+ $ export tests_repo=github.com/stevenhorsman/tests
+ $ export tests_branch=stevenh/add-ccv0-changes-to-build
+ ```
+ before running the script.
+ - By default the build and configuration are using `QEMU` as the hypervisor. In order to use `Cloud Hypervisor` instead
+ set:
+ ```
+ $ export KATA_HYPERVISOR="cloud-hypervisor"
+ ```
+ before running the build.
+
+- At this point you can provision a Kata confidential containers pod and container with either
+ [`crictl`](#using-crictl-for-end-to-end-provisioning-of-a-kata-confidential-containers-pod-with-an-unencrypted-image),
+ or [Kubernetes](#using-kubernetes-for-end-to-end-provisioning-of-a-kata-confidential-containers-pod-with-an-unencrypted-image)
+ and then test and use it.
+
+### Using crictl for end-to-end provisioning of a Kata confidential containers pod with an unencrypted image
+
+- Run the full build process with Kubernetes turned off, so its configuration doesn't interfere with `crictl` using:
+ ```bash
+ $ export KUBERNETES="no"
+ $ export KATA_HYPERVISOR="qemu"
+ $ ~/ccv0.sh -d build_and_install_all
+ ```
+ > **Note**: Much of this script has to be run as `sudo`, so you are likely to get prompted for your password.
+ - *I run this script sourced just so that the required installed components are accessible on the `PATH` to the rest*
+ *of the process without having to reload the session.*
+ - The steps that `build_and_install_all` takes is:
+ - Checkout the git repos for the `tests` and `kata-containers` repos as specified by the environment variables
+ (default to `CCv0` branches if they are not supplied)
+ - Use the `tests/.ci` scripts to install the build dependencies
+ - Build and install the Kata runtime
+ - Configure Kata to use containerd and for debug and confidential containers features to be enabled (including
+ enabling console access to the Kata guest shell, which should only be done in development)
+ - Create, build and install a rootfs for the Kata hypervisor to use. For 'CCv0' this is currently based on Ubuntu
+ 20.04 and has extra packages like `umoci` added.
+ - Build the Kata guest kernel
+ - Install the hypervisor (in order to select which hypervisor will be used, the `KATA_HYPERVISOR` environment
+ variable can be used to select between `qemu` or `cloud-hypervisor`)
+ > **Note**: Depending on how where your VMs are hosted and how IPs are shared you might get an error from docker
+ during matching `ERROR: toomanyrequests: Too Many Requests`. To get past
+ this, login into Docker Hub and pull the images used with:
+ > ```bash
+ > $ sudo docker login
+ > $ sudo docker pull ubuntu
+ > ```
+ > then re-run the command.
+ - The first time this runs it may take a while, but subsequent runs will be quicker as more things are already
+ installed and they can be further cut down by not running all the above steps
+ [see "Additional script usage" below](#additional-script-usage)
+
+- Create a new Kata sandbox pod using `crictl` with:
+ ```bash
+ $ ~/ccv0.sh crictl_create_cc_pod
+ ```
+ - This creates a pod configuration file, creates the pod from this using
+ `sudo crictl runp -r kata ~/pod-config.yaml` and runs `sudo crictl pods` to show the pod
+- Create a new Kata confidential container with:
+ ```bash
+ $ ~/ccv0.sh crictl_create_cc_container
+ ```
+ - This creates a container (based on `busybox:1.33.1`) in the Kata cc sandbox and prints a list of containers.
+ This will have been created based on an image pulled in the Kata pod sandbox/guest, not on the host machine.
+
+As this point you should have a `crictl` pod and container that is using the Kata confidential containers runtime.
+You can [validate that the container image was pulled on the guest](#validate-that-the-container-image-was-pulled-on-the-guest)
+or [using the Kata pod sandbox for testing with `agent-ctl` or `ctr shim`](#using-a-kata-pod-sandbox-for-testing-with-agent-ctl-or-ctr-shim)
+
+#### Clean up the `crictl` pod sandbox and container
+- When the testing is complete you can delete the container and pod by running:
+ ```bash
+ $ ~/ccv0.sh crictl_delete_cc
+ ```
+### Using Kubernetes for end-to-end provisioning of a Kata confidential containers pod with an unencrypted image
+
+- Run the full build process with the Kubernetes environment variable set to `"yes"`, so the Kubernetes cluster is
+ configured and created using the VM
+ as a single node cluster:
+ ```bash
+ $ export KUBERNETES="yes"
+ $ ~/ccv0.sh build_and_install_all
+ ```
+ > **Note**: Depending on how where your VMs are hosted and how IPs are shared you might get an error from docker
+ during matching `ERROR: toomanyrequests: Too Many Requests`. To get past
+ this, login into Docker Hub and pull the images used with:
+ > ```bash
+ > $ sudo docker login
+ > $ sudo docker pull registry:2
+ > $ sudo docker pull ubuntu:20.04
+ > ```
+ > then re-run the command.
+- Check that your Kubernetes cluster has been correctly set-up by running :
+ ```bash
+ $ kubectl get nodes
+ ```
+ and checking that you see a single node e.g.
+ ```text
+ NAME STATUS ROLES AGE VERSION
+ stevenh-ccv0-k8s1.fyre.ibm.com Ready control-plane,master 43s v1.22.0
+ ```
+- Create a Kata confidential containers pod by running:
+ ```bash
+ $ ~/ccv0.sh kubernetes_create_cc_pod
+ ```
+- Wait a few seconds for pod to start then check that the pod's status is `Running` with
+ ```bash
+ $ kubectl get pods
+ ```
+ which should show something like:
+ ```text
+ NAME READY STATUS RESTARTS AGE
+ busybox-cc 1/1 Running 0 54s
+ ```
+
+- As this point you should have a Kubernetes pod and container running, that is using the Kata
+confidential containers runtime.
+You can [validate that the container image was pulled on the guest](#validate-that-the-container-image-was-pulled-on-the-guest)
+or [using the Kata pod sandbox for testing with `agent-ctl` or `ctr shim`](#using-a-kata-pod-sandbox-for-testing-with-agent-ctl-or-ctr-shim)
+
+#### Clean up the Kubernetes pod sandbox and container
+- When the testing is complete you can delete the container and pod by running:
+ ```bash
+ $ ~/ccv0.sh kubernetes_delete_cc_pod
+ ```
+
+### Validate that the container image was pulled on the guest
+
+There are a couple of ways we can check that the container pull image action was offloaded to the guest, by checking
+the guest's file system for the unpacked bundle and checking the host's directories to ensure it wasn't also pulled
+there.
+- To check the guest's file system:
+ - Open a shell into the Kata guest with:
+ ```bash
+ $ ~/ccv0.sh open_kata_shell
+ ```
+ - List the files in the directory that the container image bundle should have been unpacked to with:
+ ```bash
+ $ ls -ltr /run/kata-containers/confidential-containers_signed/
+ ```
+ - This should give something like
+ ```
+ total 72
+ -rw-r--r-- 1 root root 2977 Jan 20 10:03 config.json
+ -rw-r--r-- 1 root root 372 Jan 20 10:03 umoci.json
+ -rw-r--r-- 1 root root 63584 Jan 20 10:03 sha256_be9faa75035c20288cde7d2cdeb6cd1f5f4dbcd845d3f86f7feab61c4eff9eb5.mtree
+ drwxr-xr-x 12 root root 240 Jan 20 10:03 rootfs
+ ```
+ which shows how the image has been pulled and then unbundled on the guest.
+ - Leave the Kata guest shell by running:
+ ```bash
+ $ exit
+ ```
+- To verify that the image wasn't pulled on the host system we can look at the shared sandbox on the host and we
+ should only see a single bundle for the pause container as the `busybox` based container image should have been
+ pulled on the guest:
+ - Find all the `rootfs` directories under in the pod's shared directory with:
+ ```bash
+ $ pod_id=$(ps -ef | grep containerd-shim-kata-v2 | egrep -o "id [^,][^,].* " | awk '{print $2}')
+ $ sudo find /run/kata-containers/shared/sandboxes/${pod_id}/shared -name rootfs
+ ```
+ which should only show a single `rootfs` directory if the container image was pulled on the guest, not the host
+ - Looking that `rootfs` directory with
+ ```bash
+ $ sudo ls -ltr $(sudo find /run/kata-containers/shared/sandboxes/${pod_id}/shared -name rootfs)
+ ```
+ shows something similar to
+ ```
+ total 668
+ -rwxr-xr-x 1 root root 682696 Aug 25 13:58 pause
+ drwxr-xr-x 2 root root 6 Jan 20 02:01 proc
+ drwxr-xr-x 2 root root 6 Jan 20 02:01 dev
+ drwxr-xr-x 2 root root 6 Jan 20 02:01 sys
+ drwxr-xr-x 2 root root 25 Jan 20 02:01 etc
+ ```
+ which is clearly the pause container indicating that the `busybox` based container image is not exposed to the host.
+
+### Using a Kata pod sandbox for testing with `agent-ctl` or `ctr shim`
+
+Once you have a kata pod sandbox created as described above, either using
+[`crictl`](#using-crictl-for-end-to-end-provisioning-of-a-kata-confidential-containers-pod-with-an-unencrypted-image), or [Kubernetes](#using-kubernetes-for-end-to-end-provisioning-of-a-kata-confidential-containers-pod-with-an-unencrypted-image)
+, you can use this to test specific components of the Kata confidential
+containers architecture. This can be useful for development and debugging to isolate and test features
+that aren't broadly supported end-to-end. Here are some examples:
+
+- In the first terminal run the pull image on guest command against the Kata agent, via the shim (`containerd-shim-kata-v2`).
+This can be achieved using the [containerd](https://github.com/containerd/containerd) CLI tool, `ctr`, which can be used to
+interact with the shim directly. The command takes the form
+`ctr --namespace k8s.io shim --id <sandbox-id> pull-image <image> <new-container-id>` and can been run directly, or through
+the `ccv0.sh` script to automatically fill in the variables:
+ - Optionally, set up some environment variables to set the image and credentials used:
+ - By default the shim pull image test in `ccv0.sh` will use the `busybox:1.33.1` based test image
+ `quay.io/kata-containers/confidential-containers:signed` which requires no authentication. To use a different
+ image, set the `PULL_IMAGE` environment variable e.g.
+ ```bash
+ $ export PULL_IMAGE="docker.io/library/busybox:latest"
+ ```
+ Currently the containerd shim pull image
+ code doesn't support using a container registry that requires authentication, so if this is required, see the
+ below steps to run the pull image command against the agent directly.
+ - Run the pull image agent endpoint with:
+ ```bash
+ $ ~/ccv0.sh shim_pull_image
+ ```
+ which we print the `ctr shim` command for reference
+- Alternatively you can issue the command directly to the `kata-agent` pull image endpoint, which also supports
+ credentials in order to pull from an authenticated registry:
+ - Optionally set up some environment variables to set the image and credentials used:
+ - Set the `PULL_IMAGE` environment variable e.g. `export PULL_IMAGE="docker.io/library/busybox:latest"`
+ if a specific container image is required.
+ - If the container registry for the image requires authentication then this can be set with an environment
+ variable `SOURCE_CREDS`. For example to use Docker Hub (`docker.io`) as an authenticated user first run
+ `export SOURCE_CREDS="<dockerhub username>:<dockerhub api key>"`
+ > **Note**: the credentials support on the agent request is a tactical solution for the short-term
+ proof of concept to allow more images to be pulled and tested. Once we have support for getting
+ keys into the Kata guest image using the attestation-agent and/or KBS I'd expect container registry
+ credentials to be looked up using that mechanism.
+ - Run the pull image agent endpoint with
+ ```bash
+ $ ~/ccv0.sh agent_pull_image
+ ```
+ and you should see output which includes `Command PullImage (1 of 1) returned (Ok(()), false)` to indicate
+ that the `PullImage` request was successful e.g.
+ ```
+ Finished release [optimized] target(s) in 0.21s
+ {"msg":"announce","level":"INFO","ts":"2021-09-15T08:40:14.189360410-07:00","subsystem":"rpc","name":"kata-agent-ctl","pid":"830920","version":"0.1.0","source":"kata-agent-ctl","config":"Config { server_address: \"vsock://1970354082:1024\", bundle_dir: \"/tmp/bundle\", timeout_nano: 0, interactive: false, ignore_errors: false }"}
+ {"msg":"client setup complete","level":"INFO","ts":"2021-09-15T08:40:14.193639057-07:00","pid":"830920","source":"kata-agent-ctl","name":"kata-agent-ctl","subsystem":"rpc","version":"0.1.0","server-address":"vsock://1970354082:1024"}
+ {"msg":"Run command PullImage (1 of 1)","level":"INFO","ts":"2021-09-15T08:40:14.196643765-07:00","pid":"830920","source":"kata-agent-ctl","subsystem":"rpc","name":"kata-agent-ctl","version":"0.1.0"}
+ {"msg":"response received","level":"INFO","ts":"2021-09-15T08:40:43.828200633-07:00","source":"kata-agent-ctl","name":"kata-agent-ctl","subsystem":"rpc","version":"0.1.0","pid":"830920","response":""}
+ {"msg":"Command PullImage (1 of 1) returned (Ok(()), false)","level":"INFO","ts":"2021-09-15T08:40:43.828261708-07:00","subsystem":"rpc","pid":"830920","source":"kata-agent-ctl","version":"0.1.0","name":"kata-agent-ctl"}
+ ```
+ > **Note**: The first time that `~/ccv0.sh agent_pull_image` is run, the `agent-ctl` tool will be built
+ which may take a few minutes.
+- To validate that the image pull was successful, you can open a shell into the Kata guest with:
+ ```bash
+ $ ~/ccv0.sh open_kata_shell
+ ```
+- Check the `/run/kata-containers/` directory to verify that the container image bundle has been created in a directory
+ named either `01234556789` (for the container id), or the container image name, e.g.
+ ```bash
+ $ ls -ltr /run/kata-containers/confidential-containers_signed/
+ ```
+ which should show something like
+ ```
+ total 72
+ drwxr-xr-x 10 root root 200 Jan 1 1970 rootfs
+ -rw-r--r-- 1 root root 2977 Jan 20 16:45 config.json
+ -rw-r--r-- 1 root root 372 Jan 20 16:45 umoci.json
+ -rw-r--r-- 1 root root 63584 Jan 20 16:45 sha256_be9faa75035c20288cde7d2cdeb6cd1f5f4dbcd845d3f86f7feab61c4eff9eb5.mtree
+ ```
+- Leave the Kata shell by running:
+ ```bash
+ $ exit
+ ```
+
+## Verifying signed images
+
+For this sample demo, we use local attestation to pass through the required
+configuration to do container image signature verification. Due to this, the ability to verify images is limited
+to a pre-created selection of test images in our test
+repository [`quay.io/kata-containers/confidential-containers`](https://quay.io/repository/kata-containers/confidential-containers?tab=tags).
+For pulling images not in this test repository (called an *unprotected* registry below), we fall back to the behaviour
+of not enforcing signatures. More documentation on how to customise this to match your own containers through local,
+or remote attestation will be available in future.
+
+In our test repository there are three tagged images:
+
+| Test Image | Base Image used | Signature status | GPG key status |
+| --- | --- | --- | --- |
+| `quay.io/kata-containers/confidential-containers:signed` | `busybox:1.33.1` | [signature](https://github.com/kata-containers/tests/tree/CCv0/integration/confidential/fixtures/quay_verification/signatures.tar) embedded in kata rootfs | [public key](https://github.com/kata-containers/tests/tree/CCv0/integration/confidential/fixtures/quay_verification/public.gpg) embedded in kata rootfs |
+| `quay.io/kata-containers/confidential-containers:unsigned` | `busybox:1.33.1` | not signed | not signed |
+| `quay.io/kata-containers/confidential-containers:other_signed` | `nginx:1.21.3` | [signature](https://github.com/kata-containers/tests/tree/CCv0/integration/confidential/fixtures/quay_verification/signatures.tar) embedded in kata rootfs | GPG key not kept |
+
+Using a standard unsigned `busybox` image that can be pulled from another, *unprotected*, `quay.io` repository we can
+test a few scenarios.
+
+In this sample, with local attestation, we pass in the the public GPG key and signature files, and the [`offline_fs_kbc`
+configuration](https://github.com/confidential-containers/attestation-agent/blob/main/src/kbc_modules/offline_fs_kbc/README.md)
+into the guest image which specifies that any container image from `quay.io/kata-containers`
+must be signed with the embedded GPG key and the agent configuration needs updating to enable this.
+With this policy set a few tests of image verification can be done to test different scenarios by attempting
+to create containers from these images using `crictl`:
+
+- If you don't already have the Kata Containers CC code built and configured for `crictl`, then follow the
+[instructions above](#using-crictl-for-end-to-end-provisioning-of-a-kata-confidential-containers-pod-with-an-unencrypted-image)
+up to the `~/ccv0.sh crictl_create_cc_pod` command.
+
+- In order to enable the guest image, you will need to setup the required configuration, policy and signature files
+needed by running
+`~/ccv0.sh copy_signature_files_to_guest` and then run `~/ccv0.sh crictl_create_cc_pod` which will delete and recreate
+your pod - adding in the new files.
+
+- To test the fallback behaviour works using an unsigned image from an *unprotected* registry we can pull the `busybox`
+image by running:
+ ```bash
+ $ export CONTAINER_CONFIG_FILE=container-config_unsigned-unprotected.yaml
+ $ ~/ccv0.sh crictl_create_cc_container
+ ```
+ - This finishes showing the running container e.g.
+ ```text
+ CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
+ 98c70fefe997a quay.io/prometheus/busybox:latest Less than a second ago Running prometheus-busybox-signed 0 70119e0539238
+ ```
+- To test that an unsigned image from our *protected* test container registry is rejected we can run:
+ ```bash
+ $ export CONTAINER_CONFIG_FILE=container-config_unsigned-protected.yaml
+ $ ~/ccv0.sh crictl_create_cc_container
+ ```
+ - This correctly results in an error message from `crictl`:
+ `PullImage from image service failed" err="rpc error: code = Internal desc = Security validate failed: Validate image failed: The signatures do not satisfied! Reject reason: [Match reference failed.]" image="quay.io/kata-containers/confidential-containers:unsigned"`
+- To test that the signed image our *protected* test container registry is accepted we can run:
+ ```bash
+ $ export CONTAINER_CONFIG_FILE=container-config.yaml
+ $ ~/ccv0.sh crictl_create_cc_container
+ ```
+ - This finishes by showing a new `kata-cc-busybox-signed` running container e.g.
+ ```text
+ CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
+ b4d85c2132ed9 quay.io/kata-containers/confidential-containers:signed Less than a second ago Running kata-cc-busybox-signed 0 70119e0539238
+ ...
+ ```
+- Finally to check the image with a valid signature, but invalid GPG key (the real trusted piece of information we really
+want to protect with the attestation agent in future) fails we can run:
+ ```bash
+ $ export CONTAINER_CONFIG_FILE=container-config_signed-protected-other.yaml
+ $ ~/ccv0.sh crictl_create_cc_container
+ ```
+ - Again this results in an error message from `crictl`:
+ `"PullImage from image service failed" err="rpc error: code = Internal desc = Security validate failed: Validate image failed: The signatures do not satisfied! Reject reason: [signature verify failed! There is no pubkey can verify the signature!]" image="quay.io/kata-containers/confidential-containers:other_signed"`
+
+### Using Kubernetes to create a Kata confidential containers pod from the encrypted ssh demo sample image
+
+The [ssh-demo](https://github.com/confidential-containers/documentation/tree/main/demos/ssh-demo) explains how to
+demonstrate creating a Kata confidential containers pod from an encrypted image with the runtime created by the
+[confidential-containers operator](https://github.com/confidential-containers/documentation/blob/main/demos/operator-demo).
+To be fully confidential, this should be run on a Trusted Execution Environment, but it can be tested on generic
+hardware as well.
+
+If you wish to build the Kata confidential containers runtime to do this yourself, then you can using the following
+steps:
+
+- Run the full build process with the Kubernetes environment variable set to `"yes"`, so the Kubernetes cluster is
+ configured and created using the VM as a single node cluster and with `AA_KBC` set to `offline_fs_kbc`.
+ ```bash
+ $ export KUBERNETES="yes"
+ $ export AA_KBC=offline_fs_kbc
+ $ ~/ccv0.sh build_and_install_all
+ ```
+ - The `AA_KBC=offline_fs_kbc` mode will ensure that, when creating the rootfs of the Kata guest, the
+ [attestation-agent](https://github.com/confidential-containers/attestation-agent) will be added along with the
+ [sample offline KBC](https://github.com/confidential-containers/documentation/blob/main/demos/ssh-demo/aa-offline_fs_kbc-keys.json)
+ and an agent configuration file
+ > **Note**: Depending on how where your VMs are hosted and how IPs are shared you might get an error from docker
+ during matching `ERROR: toomanyrequests: Too Many Requests`. To get past
+ this, login into Docker Hub and pull the images used with:
+ > ```bash
+ > $ sudo docker login
+ > $ sudo docker pull registry:2
+ > $ sudo docker pull ubuntu:20.04
+ > ```
+ > then re-run the command.
+- Check that your Kubernetes cluster has been correctly set-up by running :
+ ```bash
+ $ kubectl get nodes
+ ```
+ and checking that you see a single node e.g.
+ ```text
+ NAME STATUS ROLES AGE VERSION
+ stevenh-ccv0-k8s1.fyre.ibm.com Ready control-plane,master 43s v1.22.0
+ ```
+- Create a sample Kata confidential containers ssh pod by running:
+ ```bash
+ $ ~/ccv0.sh kubernetes_create_ssh_demo_pod
+ ```
+- As this point you should have a Kubernetes pod running the Kata confidential containers runtime that has pulled
+the [sample image](https://hub.docker.com/r/katadocker/ccv0-ssh) which was encrypted by the key file that we included
+in the rootfs.
+During the pod deployment the image was pulled and then decrypted using the key file, on the Kata guest image, without
+it ever being available to the host.
+
+- To validate that the container is working you, can connect to the image via SSH by running:
+ ```bash
+ $ ~/ccv0.sh connect_to_ssh_demo_pod
+ ```
+ - During this connection the host key fingerprint is shown and should match:
+ `ED25519 key fingerprint is SHA256:wK7uOpqpYQczcgV00fGCh+X97sJL3f6G1Ku4rvlwtR0.`
+ - After you are finished connecting then run:
+ ```bash
+ $ exit
+ ```
+
+- To delete the sample SSH demo pod run:
+ ```bash
+ $ ~/ccv0.sh kubernetes_delete_ssh_demo_pod
+ ```
+
+## Additional script usage
+
+As well as being able to use the script as above to build all of `kata-containers` from scratch it can be used to just
+re-build bits of it by running the script with different parameters. For example after the first build you will often
+not need to re-install the dependencies, the hypervisor or the Guest kernel, but just test code changes made to the
+runtime and agent. This can be done by running `~/ccv0.sh rebuild_and_install_kata`. (*Note this does a hard checkout*
+*from git, so if your changes are only made locally it is better to do the individual steps e.g.*
+`~/ccv0.sh build_kata_runtime && ~/ccv0.sh build_and_add_agent_to_rootfs && ~/ccv0.sh build_and_install_rootfs`).
+There are commands for a lot of steps in building, setting up and testing and the full list can be seen by running
+`~/ccv0.sh help`:
+```
+$ ~/ccv0.sh help
+Overview:
+ Build and test kata containers from source
+ Optionally set kata-containers and tests repo and branch as exported variables before running
+ e.g. export katacontainers_repo=github.com/stevenhorsman/kata-containers && export katacontainers_branch=kata-ci-from-fork && export tests_repo=github.com/stevenhorsman/tests && export tests_branch=kata-ci-from-fork && ~/ccv0.sh build_and_install_all
+Usage:
+ ccv0.sh [options] <command>
+Commands:
+- help: Display this help
+- all: Build and install everything, test kata with containerd and capture the logs
+- build_and_install_all: Build and install everything
+- initialize: Install dependencies and check out kata-containers source
+- rebuild_and_install_kata: Rebuild the kata runtime and agent and build and install the image
+- build_kata_runtime: Build and install the kata runtime
+- configure: Configure Kata to use rootfs and enable debug
+- create_rootfs: Create a local rootfs
+- build_and_add_agent_to_rootfs:Builds the kata-agent and adds it to the rootfs
+- build_and_install_rootfs: Builds and installs the rootfs image
+- install_guest_kernel: Setup, build and install the guest kernel
+- build_cloud_hypervisor Checkout, patch, build and install Cloud Hypervisor
+- build_qemu: Checkout, patch, build and install QEMU
+- init_kubernetes: initialize a Kubernetes cluster on this system
+- crictl_create_cc_pod Use crictl to create a new kata cc pod
+- crictl_create_cc_container Use crictl to create a new busybox container in the kata cc pod
+- crictl_delete_cc Use crictl to delete the kata cc pod sandbox and container in it
+- kubernetes_create_cc_pod: Create a Kata CC runtime busybox-based pod in Kubernetes
+- kubernetes_delete_cc_pod: Delete the Kata CC runtime busybox-based pod in Kubernetes
+- open_kata_shell: Open a shell into the kata runtime
+- agent_pull_image: Run PullImage command against the agent with agent-ctl
+- shim_pull_image: Run PullImage command against the shim with ctr
+- agent_create_container: Run CreateContainer command against the agent with agent-ctl
+- test: Test using kata with containerd
+- test_capture_logs: Test using kata with containerd and capture the logs in the user's home directory
+
+Options:
+ -d: Enable debug
+ -h: Display this help
+```
diff --git a/docs/how-to/how-to-generate-a-kata-containers-payload-for-the-confidential-containers-operator.md b/docs/how-to/how-to-generate-a-kata-containers-payload-for-the-confidential-containers-operator.md
new file mode 100644
index 000000000..40451aa97
--- /dev/null
+++ b/docs/how-to/how-to-generate-a-kata-containers-payload-for-the-confidential-containers-operator.md
@@ -0,0 +1,44 @@
+# Generating a Kata Containers payload for the Confidential Containers Operator
+
+[Confidential Containers
+Operator](https://github.com/confidential-containers/operator) consumes a Kata
+Containers payload, generated from the `CCv0` branch, and here one can find all
+the necessary info on how to build such a payload.
+
+## Requirements
+
+* `make` installed in the machine
+* Docker installed in the machine
+* `sudo` access to the machine
+
+## Process
+
+* Clone [Kata Containers](https://github.com/kata-containers/kata-containers)
+ ```sh
+ git clone --branch CCv0 https://github.com/kata-containers/kata-containers
+ ```
+ * In case you've already cloned the repo, make sure to switch to the `CCv0` branch
+ ```sh
+ git checkout CCv0
+ ```
+ * Ensure your tree is clean and in sync with upstream `CCv0`
+ ```sh
+ git clean -xfd
+ git reset --hard <upstream>/CCv0
+ ```
+* Make sure you're authenticated to `quay.io`
+ ```sh
+ sudo docker login quay.io
+ ```
+* From the top repo directory, run:
+ ```sh
+ sudo make cc-payload
+ ```
+* Make sure the image was upload to the [Confidential Containers
+ runtime-payload
+registry](https://quay.io/repository/confidential-containers/runtime-payload?tab=tags)
+
+## Notes
+
+Make sure to run it on a machine that's not the one you're hacking on, prepare a
+cup of tea, and get back to it an hour later (at least).
diff --git a/docs/how-to/how-to-run-kata-containers-with-SNP-VMs.md b/docs/how-to/how-to-run-kata-containers-with-SNP-VMs.md
new file mode 100644
index 000000000..a87c9be62
--- /dev/null
+++ b/docs/how-to/how-to-run-kata-containers-with-SNP-VMs.md
@@ -0,0 +1,159 @@
+# Kata Containers with AMD SEV-SNP VMs
+
+## Disclaimer
+
+This guide is designed for developers and is - same as the Developer Guide - not intended for production systems or end users. It is advisable to only follow this guide on non-critical development systems.
+
+## Prerequisites
+
+To run Kata Containers in SNP-VMs, the following software stack is used.
+
+![Kubernetes integration with shimv2](./images/SNP-stack.svg)
+
+The host BIOS and kernel must be capable of supporting AMD SEV-SNP and configured accordingly. For Kata Containers, the host kernel with branch [`sev-snp-iommu-avic_5.19-rc6_v3`](https://github.com/AMDESE/linux/tree/sev-snp-iommu-avic_5.19-rc6_v3) and commit [`3a88547`](https://github.com/AMDESE/linux/commit/3a885471cf89156ea555341f3b737ad2a8d9d3d0) is known to work in conjunction with SEV Firmware version 1.51.3 (0xh\_1.33.03) available on AMD's [SEV developer website](https://developer.amd.com/sev/). See [AMD's guide](https://github.com/AMDESE/AMDSEV/tree/sev-snp-devel) to configure the host accordingly. Verify that you are able to run SEV-SNP encrypted VMs first. The guest components required for Kata Containers are built as described below.
+
+**Tip**: It is easiest to first have Kata Containers running on your system and then modify it to run containers in SNP-VMs. Follow the [Developer guide](../Developer-Guide.md#warning) and then follow the below steps. Nonetheless, you can just follow this guide from the start.
+
+## How to build
+
+Follow all of the below steps to install Kata Containers with SNP-support from scratch. These steps mostly follow the developer guide with modifications to support SNP
+
+__Steps from the Developer Guide:__
+- Get all the [required components](../Developer-Guide.md#requirements-to-build-individual-components) for building the kata-runtime
+- [Build the and install kata-runtime](../Developer-Guide.md#build-and-install-the-kata-containers-runtime)
+- [Build a custom agent](../Developer-Guide.md#build-a-custom-kata-agent---optional)
+- [Create an initrd image](../Developer-Guide.md#create-an-initrd-image---optional) by first building a rootfs, then building the initrd based on the rootfs, use a custom agent and install. `ubuntu` works as the distribution of choice.
+- Get the [required components](../../tools/packaging/kernel/README.md#requirements) to build a custom kernel
+
+__SNP-specific steps:__
+- Build the SNP-specific kernel as shown below (see this [guide](../../tools/packaging/kernel/README.md#build-kata-containers-kernel) for more information)
+```bash
+$ pushd kata-containers/tools/packaging/kernel/
+$ ./build-kernel.sh -a x86_64 -x snp setup
+$ ./build-kernel.sh -a x86_64 -x snp build
+$ sudo -E PATH="${PATH}" ./build-kernel.sh -x snp install
+$ popd
+```
+- Build a current OVMF capable of SEV-SNP:
+```bash
+$ pushd kata-containers/tools/packaging/static-build/ovmf
+$ ./build.sh
+$ tar -xvf edk2-x86_64.tar.gz
+$ popd
+```
+- Build a custom QEMU
+```bash
+$ source kata-containers/tools/packaging/scripts/lib.sh
+$ qemu_url="$(get_from_kata_deps "assets.hypervisor.qemu.snp.url")"
+$ qemu_branch="$(get_from_kata_deps "assets.hypervisor.qemu.snp.branch")"
+$ qemu_commit="$(get_from_kata_deps "assets.hypervisor.qemu.snp.commit")"
+$ git clone -b "${qemu_branch}" "${qemu_url}"
+$ pushd qemu
+$ git checkout "${qemu_commit}"
+$ ./configure --enable-virtfs --target-list=x86_64-softmmu --enable-debug
+$ make -j "$(nproc)"
+$ popd
+```
+
+### Kata Containers Configuration for SNP
+
+The configuration file located at `/etc/kata-containers/configuration.toml` must be adapted as follows to support SNP-VMs:
+- Use the SNP-specific kernel for the guest VM (change path)
+```toml
+kernel = "/usr/share/kata-containers/vmlinuz-snp.container"
+```
+- Enable the use of an initrd (uncomment)
+```toml
+initrd = "/usr/share/kata-containers/kata-containers-initrd.img"
+```
+- Disable the use of a rootfs (comment out)
+```toml
+# image = "/usr/share/kata-containers/kata-containers.img"
+```
+- Use the custom QEMU capable of SNP (change path)
+```toml
+path = "/path/to/qemu/build/qemu-system-x86_64"
+```
+- Use `virtio-9p` device since `virtio-fs` is unsupported due to bugs / shortcomings in QEMU version [`snp-v3`](https://github.com/AMDESE/qemu/tree/snp-v3) for SEV and SEV-SNP (change value)
+```toml
+shared_fs = "virtio-9p"
+```
+- Disable `virtiofsd` since it is no longer required (comment out)
+```toml
+# virtio_fs_daemon = "/usr/libexec/virtiofsd"
+```
+- Disable NVDIMM (uncomment)
+```toml
+disable_image_nvdimm = true
+```
+- Disable shared memory (uncomment)
+```toml
+file_mem_backend = ""
+```
+- Enable confidential guests (uncomment)
+```toml
+confidential_guest = true
+```
+- Enable SNP-VMs (uncomment)
+```toml
+sev_snp_guest = true
+```
+ - Configure an OVMF (add path)
+```toml
+firmware = "/path/to/kata-containers/tools/packaging/static-build/ovmf/opt/kata/share/ovmf/OVMF.fd"
+```
+
+## Test Kata Containers with Containerd
+
+With Kata Containers configured to support SNP-VMs, we use containerd to test and deploy containers in these VMs.
+
+### Install Containerd
+If not already present, follow [this guide](./containerd-kata.md#install) to install containerd and its related components including `CNI` and the `cri-tools` (skip Kata Containers since we already installed it)
+
+### Containerd Configuration
+
+Follow [this guide](./containerd-kata.md#configuration) to configure containerd to use Kata Containers
+
+## Run Kata Containers in SNP-VMs
+
+Run the below commands to start a container. See [this guide](./containerd-kata.md#run) for more information
+```bash
+$ sudo ctr image pull docker.io/library/busybox:latest
+$ sudo ctr run --cni --runtime io.containerd.run.kata.v2 -t --rm docker.io/library/busybox:latest hello sh
+```
+
+### Check for active SNP:
+
+Inside the running container, run the following commands to check if SNP is active. It should look something like this:
+```
+/ # dmesg | grep -i sev
+[ 0.299242] Memory Encryption Features active: AMD SEV SEV-ES SEV-SNP
+[ 0.472286] SEV: Using SNP CPUID table, 31 entries present.
+[ 0.514574] SEV: SNP guest platform device initialized.
+[ 0.885425] sev-guest sev-guest: Initialized SEV guest driver (using vmpck_id 0)
+```
+
+### Obtain an SNP Attestation Report
+
+To obtain an attestation report inside the container, the `/dev/sev-guest` must first be configured. As of now, the VM does not perform this step, however it can be performed inside the container, either in the terminal or in code.
+
+Example for shell:
+```
+/ # SNP_MAJOR=$(cat /sys/devices/virtual/misc/sev-guest/dev | awk -F: '{print $1}')
+/ # SNP_MINOR=$(cat /sys/devices/virtual/misc/sev-guest/dev | awk -F: '{print $2}')
+/ # mknod -m 600 /dev/sev-guest c "${SNP_MAJOR}" "${SNP_MINOR}"
+```
+
+## Known Issues
+
+- Support for cgroups v2 is still [work in progress](https://github.com/kata-containers/kata-containers/issues/927). If issues occur due to cgroups v2 becoming the default in newer systems, one possible solution is to downgrade cgroups to v1:
+```bash
+sudo sed -i 's/^\(GRUB_CMDLINE_LINUX=".*\)"/\1 systemd.unified_cgroup_hierarchy=0"/' /etc/default/grub
+sudo update-grub
+sudo reboot
+```
+- If both SEV and SEV-SNP are supported by the host, Kata Containers uses SEV-SNP by default. You can verify what features are enabled by checking `/sys/module/kvm_amd/parameters/sev` and `sev_snp`. This means that Kata Containers can not run both SEV-SNP-VMs and SEV-VMs at the same time. If SEV is to be used by Kata Containers instead, reload the `kvm_amd` kernel module without SNP-support, this will disable SNP-support for the entire platform.
+```bash
+sudo rmmod kvm_amd && sudo modprobe kvm_amd sev_snp=0
+```
+
diff --git a/docs/how-to/how-to-setup-swap-devices-in-guest-kernel.md b/docs/how-to/how-to-setup-swap-devices-in-guest-kernel.md
index 8ab9e89e5..70bbbf6b3 100644
--- a/docs/how-to/how-to-setup-swap-devices-in-guest-kernel.md
+++ b/docs/how-to/how-to-setup-swap-devices-in-guest-kernel.md
@@ -17,9 +17,9 @@ Enable setup swap device in guest kernel as follows:
$ sudo sed -i -e 's/^#enable_guest_swap.*$/enable_guest_swap = true/g' /etc/kata-containers/configuration.toml
```
-## Run a Kata Container utilizing swap device
+## Run a Kata Containers utilizing swap device
-Use following command to start a Kata Container with swappiness 60 and 1GB swap device (swap_in_bytes - memory_limit_in_bytes).
+Use following command to start a Kata Containers with swappiness 60 and 1GB swap device (swap_in_bytes - memory_limit_in_bytes).
```
$ pod_yaml=pod.yaml
$ container_yaml=container.yaml
@@ -27,6 +27,8 @@ $ image="quay.io/prometheus/busybox:latest"
$ cat << EOF > "${pod_yaml}"
metadata:
name: busybox-sandbox1
+ uid: $(uuidgen)
+ namespace: default
EOF
$ cat << EOF > "${container_yaml}"
metadata:
@@ -43,12 +45,12 @@ command:
- top
EOF
$ sudo crictl pull $image
-$ podid=$(sudo crictl runp $pod_yaml)
+$ podid=$(sudo crictl runp --runtime kata $pod_yaml)
$ cid=$(sudo crictl create $podid $container_yaml $pod_yaml)
$ sudo crictl start $cid
```
-Kata Container setups swap device for this container only when `io.katacontainers.container.resource.swappiness` is set.
+Kata Containers setups swap device for this container only when `io.katacontainers.container.resource.swappiness` is set.
The following table shows the swap size how to decide if `io.katacontainers.container.resource.swappiness` is set.
|`io.katacontainers.container.resource.swap_in_bytes`|`memory_limit_in_bytes`|swap size|
diff --git a/docs/how-to/how-to-use-kata-containers-with-firecracker.md b/docs/how-to/how-to-use-kata-containers-with-firecracker.md
index 03f533ef7..d2bd362c1 100644
--- a/docs/how-to/how-to-use-kata-containers-with-firecracker.md
+++ b/docs/how-to/how-to-use-kata-containers-with-firecracker.md
@@ -212,7 +212,7 @@ Next, we need to configure containerd. Add a file in your path (e.g. `/usr/local
```
#!/bin/bash
-KATA_CONF_FILE=/etc/containers/configuration-fc.toml /usr/local/bin/containerd-shim-kata-v2 $@
+KATA_CONF_FILE=/etc/kata-containers/configuration-fc.toml /usr/local/bin/containerd-shim-kata-v2 $@
```
> **Note:** You may need to edit the paths of the configuration file and the `containerd-shim-kata-v2` to correspond to your setup.
diff --git a/docs/how-to/how-to-use-virtio-fs-nydus-with-kata.md b/docs/how-to/how-to-use-virtio-fs-nydus-with-kata.md
index 9b04d49cf..0ea8bf73f 100644
--- a/docs/how-to/how-to-use-virtio-fs-nydus-with-kata.md
+++ b/docs/how-to/how-to-use-virtio-fs-nydus-with-kata.md
@@ -32,6 +32,7 @@ The `nydus-sandbox.yaml` looks like below:
metadata:
attempt: 1
name: nydus-sandbox
+ uid: nydus-uid
namespace: default
log_directory: /tmp
linux:
diff --git a/docs/how-to/how-to-use-virtio-mem-with-kata.md b/docs/how-to/how-to-use-virtio-mem-with-kata.md
index 0c838927a..40465bbe5 100644
--- a/docs/how-to/how-to-use-virtio-mem-with-kata.md
+++ b/docs/how-to/how-to-use-virtio-mem-with-kata.md
@@ -42,6 +42,8 @@ $ image="quay.io/prometheus/busybox:latest"
$ cat << EOF > "${pod_yaml}"
metadata:
name: busybox-sandbox1
+ uid: $(uuidgen)
+ namespace: default
EOF
$ cat << EOF > "${container_yaml}"
metadata:
diff --git a/docs/how-to/images/SNP-stack.svg b/docs/how-to/images/SNP-stack.svg
new file mode 100644
index 000000000..9d32557f2
--- /dev/null
+++ b/docs/how-to/images/SNP-stack.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Do not edit this file with editors other than diagrams.net -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="286px" height="191px" viewBox="-0.5 -0.5 286 191" content="&lt;mxfile host=&quot;app.diagrams.net&quot; modified=&quot;2022-08-16T08:26:44.733Z&quot; agent=&quot;5.0 (X11)&quot; etag=&quot;izD69OelRpKtQ7Zpm1PX&quot; version=&quot;20.2.4&quot; type=&quot;device&quot;&gt;&lt;diagram id=&quot;xHKSCp4wEPVfmf964Gn7&quot; name=&quot;Page-1&quot;&gt;3ZdNc5swEIZ/DcfOgGQMPtauE6etm2bcpmcZbUBjgRghCu6vrzAiQKDjZGrXaWY4SO+uvp5dVmDhRVxeS5JGa0GBW8impYU/WAg5E4Ss6rHpvla8Ga6FUDJqnFphw36BEW2j5oxC1nNUQnDF0r4YiCSBQPU0IqUo+m4PgvdXTUkIA2ETED5UfzCqolr1XbvVV8DCqFnZsY0lJo2zEbKIUFF0JLy08EIKoepWXC6AV/AaLvW4qz9YHzcmIVHPGVB+ieZbb+fcfcXbb/mNl32U3jszy0/Cc3PgzyzJSy19ApkcYlnNqLv3a3MMtW/YSJEnFKrpbQvPi4gp2KQkqKyFzgatRSrmuufo5nC7zdogFZQdyWz/GkQMSu61i7Gihq3JJeSZftFGxvGNFnWigo1GTDKEj1O3vHTDIHsBPjTAd7dcf399oPClQeEBqPnN7ebVgcLOpUFNBqBu79dXfwfqgXG+EFzIw1hMXfDpROuZkmIHHYuPtng6PQ9aZ3ZptO7RWvf/Q3YvDdkbQB5g1RdhWjWDXPL9XJJgB+o43zYYB9qcpavT1YGJ7R4tmGgEo+Oci6M/4LgSmRqw1OdTfU79fEtEAk+S00iEszCpoqCpgdbnFS2mP3zeG0PMKK2WGQ1M/9U4RQTQkwiM3O3Tf5nIszeRyGMFYSyRvXNhbF6QDseRL8k3lMbHC/KJ0lh325+Hg63zC4aXvwE=&lt;/diagram&gt;&lt;/mxfile&gt;"><defs/><g><rect x="0" y="120" width="180" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 135px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Linux Kernel / KVM</div></div></div></foreignObject><text x="90" y="139" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Linux Kernel / KVM</text></switch></g><rect x="0" y="80" width="180" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 95px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">QEMU</div></div></div></foreignObject><text x="90" y="99" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">QEMU</text></switch></g><rect x="0" y="160" width="180" height="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 175px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">BIOS</div></div></div></foreignObject><text x="90" y="179" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">BIOS</text></switch></g><rect x="0" y="40" width="180" height="30" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 55px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">OVMF</div></div></div></foreignObject><text x="90" y="59" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">OVMF</text></switch></g><rect x="0" y="0" width="180" height="30" fill="#d5e8d4" stroke="#82b366" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 15px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Linux Kernel</div></div></div></foreignObject><text x="90" y="19" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Linux Kernel</text></switch></g><path d="M 225 80 L 220 80 Q 215 80 215 90 L 215 125 Q 215 135 210 135 L 207.5 135 Q 205 135 210 135 L 212.5 135 Q 215 135 215 145 L 215 180 Q 215 190 220 190 L 225 190" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" transform="translate(215,0)scale(-1,1)translate(-215,0)" pointer-events="all"/><rect x="225" y="120" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 135px; margin-left: 226px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Host</div></div></div></foreignObject><text x="255" y="139" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">Host</text></switch></g><path d="M 225 0 L 220 0 Q 215 0 215 10 L 215 25 Q 215 35 210 35 L 207.5 35 Q 205 35 210 35 L 212.5 35 Q 215 35 215 45 L 215 60 Q 215 70 220 70 L 225 70" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" transform="translate(215,0)scale(-1,1)translate(-215,0)" pointer-events="all"/><rect x="220" y="0" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 15px; margin-left: 221px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">VM</div></div></div></foreignObject><text x="250" y="19" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">VM</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg>
\ No newline at end of file
diff --git a/docs/install/kata-containers-3.0-rust-runtime-installation-guide.md b/docs/install/kata-containers-3.0-rust-runtime-installation-guide.md
index 2675a5599..d8150bf3d 100644
--- a/docs/install/kata-containers-3.0-rust-runtime-installation-guide.md
+++ b/docs/install/kata-containers-3.0-rust-runtime-installation-guide.md
@@ -24,7 +24,7 @@ architectures:
| Installation method | Description | Automatic updates | Use case | Availability
|------------------------------------------------------|----------------------------------------------------------------------------------------------|-------------------|-----------------------------------------------------------------------------------------------|----------- |
-| [Using kata-deploy](#kata-deploy-installation) | The preferred way to deploy the Kata Containers distributed binaries on a Kubernetes cluster | **No!** | Best way to give it a try on kata-containers on an already up and running Kubernetes cluster. | No |
+| [Using kata-deploy](#kata-deploy-installation) | The preferred way to deploy the Kata Containers distributed binaries on a Kubernetes cluster | **No!** | Best way to give it a try on kata-containers on an already up and running Kubernetes cluster. | Yes |
| [Using official distro packages](#official-packages) | Kata packages provided by Linux distributions official repositories | yes | Recommended for most users. | No |
| [Using snap](#snap-installation) | Easy to install | yes | Good alternative to official distro packages. | No |
| [Automatic](#automatic-installation) | Run a single command to install a full system | **No!** | For those wanting the latest release quickly. | No |
@@ -32,7 +32,8 @@ architectures:
| [Build from source](#build-from-source-installation) | Build the software components manually | **No!** | Power users and developers only. | Yes |
### Kata Deploy Installation
-`ToDo`
+
+Follow the [`kata-deploy`](../../tools/packaging/kata-deploy/README.md).
### Official packages
`ToDo`
### Snap Installation
@@ -48,14 +49,14 @@ architectures:
* Download `Rustup` and install `Rust`
> **Notes:**
- > Rust version 1.58 is needed
+ > Rust version 1.62.0 is needed
Example for `x86_64`
```
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ source $HOME/.cargo/env
- $ rustup install 1.58
- $ rustup default 1.58-x86_64-unknown-linux-gnu
+ $ rustup install 1.62.0
+ $ rustup default 1.62.0-x86_64-unknown-linux-gnu
```
* Musl support for fully static binary
@@ -83,7 +84,7 @@ $ git clone https://github.com/kata-containers/kata-containers.git
$ cd kata-containers/src/runtime-rs
$ make && sudo make install
```
-After running the command above, the default config file `configuration.toml` will be installed under `/usr/share/defaults/kata-containers/`, the binary file `containerd-shim-kata-v2` will be installed under `/user/local/bin` .
+After running the command above, the default config file `configuration.toml` will be installed under `/usr/share/defaults/kata-containers/`, the binary file `containerd-shim-kata-v2` will be installed under `/usr/local/bin/` .
### Build Kata Containers Kernel
Follow the [Kernel installation guide](/tools/packaging/kernel/README.md).
diff --git a/docs/install/minikube-installation-guide.md b/docs/install/minikube-installation-guide.md
index 299e5fa59..c49e2bac9 100644
--- a/docs/install/minikube-installation-guide.md
+++ b/docs/install/minikube-installation-guide.md
@@ -71,12 +71,6 @@ To use containerd, modify the `--container-runtime` argument:
> **Notes:**
> - Adjust the `--memory 6144` line to suit your environment and requirements. Kata Containers default to
> requesting 2048MB per container. We recommended you supply more than that to the Minikube node.
-> - Prior to Minikube/Kubernetes v1.14, the beta `RuntimeClass` feature also needed enabling with
-> the following.
->
-> | what | why |
-> | ---- | --- |
-> | `--feature-gates=RuntimeClass=true` | Kata needs to use the `RuntimeClass` Kubernetes feature |
The full command is therefore:
@@ -138,17 +132,9 @@ $ kubectl -n kube-system exec ${podname} -- ps -ef | fgrep infinity
## Enabling Kata Containers
-> **Note:** Only Minikube/Kubernetes versions <= 1.13 require this step. Since version
-> v1.14, the `RuntimeClass` is enabled by default. Performing this step on Kubernetes > v1.14 is
-> however benign.
-
Now you have installed the Kata Containers components in the Minikube node. Next, you need to configure
Kubernetes `RuntimeClass` to know when to use Kata Containers to run a pod.
-```sh
-$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/node-api/master/manifests/runtimeclass_crd.yaml > runtimeclass_crd.yaml
-```
-
### Register the runtime
Now register the `kata qemu` runtime with that class. This should result in no errors:
diff --git a/docs/use-cases/NVIDIA-GPU-passthrough-and-Kata.md b/docs/use-cases/NVIDIA-GPU-passthrough-and-Kata.md
index 18a75bde7..e1b5af76e 100644
--- a/docs/use-cases/NVIDIA-GPU-passthrough-and-Kata.md
+++ b/docs/use-cases/NVIDIA-GPU-passthrough-and-Kata.md
@@ -545,6 +545,12 @@ Create the hook execution file for Kata:
/usr/bin/nvidia-container-toolkit -debug $@
```
+Make sure the hook shell is executable:
+
+```sh
+chmod +x $ROOTFS_DIR/usr/share/oci/hooks/prestart/nvidia-container-toolkit.sh
+```
+
As the last step one can do some cleanup of files or package caches. Build the
rootfs and configure it for use with Kata according to the development guide.
diff --git a/docs/use-cases/using-Intel-SGX-and-kata.md b/docs/use-cases/using-Intel-SGX-and-kata.md
index 9b721f1bc..29635e6ae 100644
--- a/docs/use-cases/using-Intel-SGX-and-kata.md
+++ b/docs/use-cases/using-Intel-SGX-and-kata.md
@@ -61,6 +61,9 @@ spec:
name: eosgx-demo-job-1
image: oeciteam/oe-helloworld:latest
imagePullPolicy: IfNotPresent
+ volumeMounts:
+ - mountPath: /dev
+ name: dev-mount
securityContext:
readOnlyRootFilesystem: true
capabilities:
diff --git a/docs/use-cases/using-SPDK-vhostuser-and-kata.md b/docs/use-cases/using-SPDK-vhostuser-and-kata.md
index 4b091d420..ae75930ae 100644
--- a/docs/use-cases/using-SPDK-vhostuser-and-kata.md
+++ b/docs/use-cases/using-SPDK-vhostuser-and-kata.md
@@ -197,11 +197,6 @@ vhost_user_store_path = "<Path of the base directory for vhost-user device>"
> under `[hypervisor.qemu]` section.
-For the subdirectories of `vhost_user_store_path`: `block` is used for block
-device; `block/sockets` is where we expect UNIX domain sockets for vhost-user
-block devices to live; `block/devices` is where simulated block device nodes
-for vhost-user block devices are created.
-
For the subdirectories of `vhost_user_store_path`:
- `block` is used for block device;
- `block/sockets` is where we expect UNIX domain sockets for vhost-user
diff --git a/src/agent/Cargo.lock b/src/agent/Cargo.lock
index 4f6ccd958..7eaa58a4f 100644
--- a/src/agent/Cargo.lock
+++ b/src/agent/Cargo.lock
@@ -9,309 +9,310 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
-name = "aho-corasick"
-version = "0.7.18"
+name = "aead"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331"
dependencies = [
- "memchr",
+ "generic-array",
]
[[package]]
-name = "android_system_properties"
-version = "0.1.5"
+name = "aead"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
dependencies = [
- "libc",
+ "generic-array",
]
[[package]]
-name = "ansi_term"
-version = "0.12.1"
+name = "aead"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8"
dependencies = [
- "winapi",
+ "crypto-common",
+ "generic-array",
]
[[package]]
-name = "anyhow"
-version = "1.0.58"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
-
-[[package]]
-name = "arc-swap"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5d78ce20460b82d3fa150275ed9d55e21064fc7951177baacf86a145c4a4b1f"
-
-[[package]]
-name = "async-recursion"
-version = "0.3.2"
+name = "aes"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2"
+checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561"
dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "aes-soft",
+ "aesni",
+ "cipher 0.2.5",
]
[[package]]
-name = "async-trait"
-version = "0.1.56"
+name = "aes"
+version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716"
+checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "cfg-if 1.0.0",
+ "cipher 0.3.0",
+ "cpufeatures",
+ "opaque-debug",
]
[[package]]
-name = "atty"
-version = "0.2.14"
+name = "aes"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241"
dependencies = [
- "hermit-abi",
- "libc",
- "winapi",
+ "cfg-if 1.0.0",
+ "cipher 0.4.3",
+ "cpufeatures",
]
[[package]]
-name = "autocfg"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
-
-[[package]]
-name = "bincode"
-version = "1.3.3"
+name = "aes-gcm"
+version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
dependencies = [
- "serde",
+ "aead 0.4.3",
+ "aes 0.7.5",
+ "cipher 0.3.0",
+ "ctr 0.8.0",
+ "ghash 0.4.4",
+ "subtle",
]
[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "bumpalo"
-version = "3.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
-
-[[package]]
-name = "byte-unit"
-version = "3.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "415301c9de11005d4b92193c0eb7ac7adc37e5a49e0ac9bed0a42343512744b8"
-
-[[package]]
-name = "byteorder"
-version = "1.4.3"
+name = "aes-gcm"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+checksum = "82e1366e0c69c9f927b1fa5ce2c7bf9eafc8f9268c0b9800729e8b267612447c"
+dependencies = [
+ "aead 0.5.1",
+ "aes 0.8.2",
+ "cipher 0.4.3",
+ "ctr 0.9.2",
+ "ghash 0.5.0",
+ "subtle",
+]
[[package]]
-name = "bytes"
-version = "0.4.12"
+name = "aes-soft"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
+checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072"
dependencies = [
- "byteorder",
- "iovec",
+ "cipher 0.2.5",
+ "opaque-debug",
]
[[package]]
-name = "bytes"
-version = "1.1.0"
+name = "aesni"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
+checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce"
+dependencies = [
+ "cipher 0.2.5",
+ "opaque-debug",
+]
[[package]]
-name = "capctl"
-version = "0.2.1"
+name = "aho-corasick"
+version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "526c6a8746a7cfb052c15d20259c4f5c021966affdc7c960c71ca640f824c801"
+checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
dependencies = [
- "bitflags",
- "cfg-if 1.0.0",
- "libc",
+ "memchr",
]
[[package]]
-name = "caps"
-version = "0.5.3"
+name = "android_system_properties"
+version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61bf7211aad104ce2769ec05efcdfabf85ee84ac92461d142f22cf8badd0e54c"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
- "errno",
"libc",
- "thiserror",
]
[[package]]
-name = "cc"
-version = "1.0.73"
+name = "ansi_term"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+dependencies = [
+ "winapi",
+]
[[package]]
-name = "cfg-if"
-version = "0.1.10"
+name = "anyhow"
+version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
[[package]]
-name = "cfg-if"
-version = "1.0.0"
+name = "arc-swap"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
[[package]]
-name = "cgroups-rs"
-version = "0.2.10"
+name = "ascii-canvas"
+version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf5525f2cf84d5113ab26bfb6474180eb63224b4b1e4be31ee87be4098f11399"
+checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6"
dependencies = [
- "libc",
- "log",
- "nix 0.24.2",
- "regex",
+ "term",
]
[[package]]
-name = "chrono"
-version = "0.4.22"
+name = "asn1-rs"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
+checksum = "cf6690c370453db30743b373a60ba498fc0d6d83b11f4abfd87a84a075db5dd4"
dependencies = [
- "iana-time-zone",
- "js-sys",
- "num-integer",
+ "asn1-rs-derive",
+ "asn1-rs-impl",
+ "displaydoc",
+ "nom",
"num-traits",
- "time 0.1.44",
- "wasm-bindgen",
- "winapi",
+ "rusticata-macros",
+ "thiserror",
+ "time 0.3.17",
]
[[package]]
-name = "clap"
-version = "3.2.6"
+name = "asn1-rs-derive"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f1fe12880bae935d142c8702d500c63a4e8634b6c3c57ad72bf978fc7b6249a"
+checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c"
dependencies = [
- "atty",
- "bitflags",
- "clap_derive",
- "clap_lex",
- "indexmap",
- "once_cell",
- "strsim",
- "termcolor",
- "textwrap",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
]
[[package]]
-name = "clap_derive"
-version = "3.2.6"
+name = "asn1-rs-impl"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed6db9e867166a43a53f7199b5e4d1f522a1e5bd626654be263c999ce59df39a"
+checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed"
dependencies = [
- "heck 0.4.0",
- "proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
-name = "clap_lex"
-version = "0.2.3"
+name = "async-broadcast"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87eba3c8c7f42ef17f6c659fc7416d0f4758cd3e58861ee63c5fa4a4dde649e4"
+checksum = "6d26004fe83b2d1cd3a97609b21e39f9a31535822210fe83205d2ce48866ea61"
dependencies = [
- "os_str_bytes",
+ "event-listener",
+ "futures-core",
+ "parking_lot 0.12.1",
]
[[package]]
-name = "common-path"
-version = "1.0.0"
+name = "async-channel"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101"
+checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833"
+dependencies = [
+ "concurrent-queue",
+ "event-listener",
+ "futures-core",
+]
[[package]]
-name = "core-foundation-sys"
-version = "0.8.3"
+name = "async-compression"
+version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a"
+dependencies = [
+ "flate2",
+ "futures-core",
+ "futures-io",
+ "memchr",
+ "pin-project-lite",
+ "tokio",
+ "zstd 0.11.2+zstd.1.5.2",
+ "zstd-safe 5.0.2+zstd.1.5.2",
+]
[[package]]
-name = "crc32fast"
-version = "1.3.2"
+name = "async-executor"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b"
dependencies = [
- "cfg-if 1.0.0",
+ "async-lock",
+ "async-task",
+ "concurrent-queue",
+ "fastrand",
+ "futures-lite",
+ "slab",
]
[[package]]
-name = "crossbeam-channel"
-version = "0.5.5"
+name = "async-io"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c"
+checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794"
dependencies = [
- "cfg-if 1.0.0",
- "crossbeam-utils",
+ "async-lock",
+ "autocfg 1.1.0",
+ "concurrent-queue",
+ "futures-lite",
+ "libc",
+ "log",
+ "parking",
+ "polling",
+ "slab",
+ "socket2",
+ "waker-fn",
+ "windows-sys 0.42.0",
]
[[package]]
-name = "crossbeam-deque"
-version = "0.8.1"
+name = "async-lock"
+version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
+checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685"
dependencies = [
- "cfg-if 1.0.0",
- "crossbeam-epoch",
- "crossbeam-utils",
+ "event-listener",
+ "futures-lite",
]
[[package]]
-name = "crossbeam-epoch"
-version = "0.9.9"
+name = "async-recursion"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d"
+checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2"
dependencies = [
- "autocfg",
- "cfg-if 1.0.0",
- "crossbeam-utils",
- "memoffset",
- "once_cell",
- "scopeguard",
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
-name = "crossbeam-utils"
-version = "0.8.10"
+name = "async-stream"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83"
+checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e"
dependencies = [
- "cfg-if 1.0.0",
- "once_cell",
+ "async-stream-impl",
+ "futures-core",
]
[[package]]
-name = "derive-new"
-version = "0.5.9"
+name = "async-stream-impl"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535"
+checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
dependencies = [
"proc-macro2",
"quote",
@@ -319,1286 +320,4268 @@ dependencies = [
]
[[package]]
-name = "either"
-version = "1.6.1"
+name = "async-task"
+version = "4.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524"
[[package]]
-name = "errno"
-version = "0.2.8"
+name = "async-trait"
+version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
+checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3"
dependencies = [
- "errno-dragonfly",
- "libc",
- "winapi",
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
-name = "errno-dragonfly"
-version = "0.1.2"
+name = "async_once"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
-dependencies = [
- "cc",
- "libc",
-]
+checksum = "2ce4f10ea3abcd6617873bae9f91d1c5332b4a778bd9ce34d0cd517474c1de82"
[[package]]
-name = "fail"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec3245a0ca564e7f3c797d20d833a6870f57a728ac967d5225b3ffdef4465011"
+name = "attestation_agent"
+version = "0.1.0"
+source = "git+https://github.com/confidential-containers/attestation-agent?rev=cbdd744#cbdd7440f6d2715e9ba192895c66baf41eccbf61"
dependencies = [
- "lazy_static",
+ "aes-gcm 0.10.1",
+ "anyhow",
+ "async-trait",
+ "base64",
+ "env_logger",
+ "foreign-types 0.5.0",
+ "futures",
+ "futures-util",
"log",
"rand 0.8.5",
+ "rsa 0.6.1",
+ "serde",
+ "serde_json",
+ "sha2 0.10.6",
+ "shadow-rs 0.16.3",
+ "strum",
+ "tonic-build 0.8.4",
]
[[package]]
-name = "fastrand"
-version = "1.7.0"
+name = "atty"
+version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
- "instant",
+ "hermit-abi 0.1.19",
+ "libc",
+ "winapi",
]
[[package]]
-name = "fixedbitset"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
-
-[[package]]
-name = "flate2"
-version = "1.0.24"
+name = "autocfg"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
+checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
dependencies = [
- "crc32fast",
- "miniz_oxide",
+ "autocfg 1.1.0",
]
[[package]]
-name = "fnv"
-version = "1.0.7"
+name = "autocfg"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
-name = "futures"
-version = "0.3.21"
+name = "axum"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e"
+checksum = "08b108ad2665fa3f6e6a517c3d80ec3e77d224c47d605167aefaa5d7ef97fa48"
dependencies = [
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-io",
- "futures-sink",
- "futures-task",
+ "async-trait",
+ "axum-core",
+ "bitflags",
+ "bytes 1.3.0",
"futures-util",
+ "http",
+ "http-body",
+ "hyper",
+ "itoa",
+ "matchit",
+ "memchr",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustversion",
+ "serde",
+ "sync_wrapper",
+ "tower",
+ "tower-http",
+ "tower-layer",
+ "tower-service",
]
[[package]]
-name = "futures-channel"
-version = "0.3.21"
+name = "axum-core"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
+checksum = "79b8558f5a0581152dc94dcd289132a1d377494bdeafcd41869b3258e3e2ad92"
dependencies = [
- "futures-core",
- "futures-sink",
+ "async-trait",
+ "bytes 1.3.0",
+ "futures-util",
+ "http",
+ "http-body",
+ "mime",
+ "rustversion",
+ "tower-layer",
+ "tower-service",
]
[[package]]
-name = "futures-core"
-version = "0.3.21"
+name = "base64"
+version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
-name = "futures-executor"
-version = "0.3.21"
+name = "base64-serde"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
+checksum = "2e964e3e0a930303c7c0bdb28ebf691dd98d9eee4b8b68019d2c995710b58a18"
dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
+ "base64",
+ "serde",
]
[[package]]
-name = "futures-io"
-version = "0.3.21"
+name = "base64ct"
+version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
+checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf"
[[package]]
-name = "futures-macro"
-version = "0.3.21"
+name = "bincode"
+version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "serde",
]
[[package]]
-name = "futures-sink"
-version = "0.3.21"
+name = "bit-set"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
+dependencies = [
+ "bit-vec",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
+checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
[[package]]
-name = "futures-task"
-version = "0.3.21"
+name = "bitflags"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
-name = "futures-util"
-version = "0.3.21"
+name = "bitmask-enum"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
+checksum = "fd9e32d7420c85055e8107e5b2463c4eeefeaac18b52359fe9f9c08a18f342b2"
dependencies = [
- "futures-channel",
- "futures-core",
- "futures-io",
- "futures-macro",
- "futures-sink",
- "futures-task",
- "memchr",
- "pin-project-lite",
- "pin-utils",
- "slab",
+ "quote",
+ "syn",
]
[[package]]
-name = "getrandom"
-version = "0.1.16"
+name = "bitvec"
+version = "0.20.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+checksum = "7774144344a4faa177370406a7ff5f1da24303817368584c6206c8303eb07848"
dependencies = [
- "cfg-if 1.0.0",
- "libc",
- "wasi 0.9.0+wasi-snapshot-preview1",
+ "funty",
+ "radium",
+ "tap",
+ "wyz",
]
[[package]]
-name = "getrandom"
-version = "0.2.7"
+name = "block-buffer"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
- "cfg-if 1.0.0",
- "libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
+ "generic-array",
]
[[package]]
-name = "glob"
-version = "0.3.0"
+name = "block-buffer"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
+dependencies = [
+ "generic-array",
+]
[[package]]
-name = "hashbrown"
-version = "0.12.1"
+name = "block-modes"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3"
+checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0"
+dependencies = [
+ "block-padding",
+ "cipher 0.2.5",
+]
[[package]]
-name = "heck"
-version = "0.3.3"
+name = "block-padding"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
+
+[[package]]
+name = "blowfish"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32fa6a061124e37baba002e496d203e23ba3d7b73750be82dbfbc92913048a5b"
dependencies = [
- "unicode-segmentation",
+ "byteorder",
+ "cipher 0.2.5",
+ "opaque-debug",
]
[[package]]
-name = "heck"
-version = "0.4.0"
+name = "bstr"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
+checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
+dependencies = [
+ "memchr",
+]
[[package]]
-name = "hermit-abi"
-version = "0.1.19"
+name = "buffered-reader"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+checksum = "e9f82920285502602088677aeb65df0909b39c347b38565e553ba0363c242f65"
dependencies = [
+ "bzip2",
+ "flate2",
"libc",
]
[[package]]
-name = "hex"
-version = "0.4.3"
+name = "bumpalo"
+version = "3.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
[[package]]
-name = "iana-time-zone"
-version = "0.1.46"
+name = "byte-unit"
+version = "3.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "415301c9de11005d4b92193c0eb7ac7adc37e5a49e0ac9bed0a42343512744b8"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "bytes"
+version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad2bfd338099682614d3ee3fe0cd72e0b6a41ca6a87f6a74a3bd593c91650501"
+checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
dependencies = [
- "android_system_properties",
- "core-foundation-sys",
- "js-sys",
- "wasm-bindgen",
- "winapi",
+ "byteorder",
+ "iovec",
]
[[package]]
-name = "indexmap"
-version = "1.9.1"
+name = "bytes"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
+
+[[package]]
+name = "bzip2"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
+checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0"
dependencies = [
- "autocfg",
- "hashbrown",
+ "bzip2-sys",
+ "libc",
]
[[package]]
-name = "inotify"
-version = "0.9.6"
+name = "bzip2-sys"
+version = "0.1.11+1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
+checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
dependencies = [
- "bitflags",
- "futures-core",
- "inotify-sys",
+ "cc",
"libc",
+ "pkg-config",
+]
+
+[[package]]
+name = "cached"
+version = "0.38.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "27e6092f8c7ba6e65a46f6f26d7d7997201d3a6f0e69ff5d2440b930d7c0513a"
+dependencies = [
+ "async-trait",
+ "async_once",
+ "cached_proc_macro",
+ "cached_proc_macro_types",
+ "futures",
+ "hashbrown",
+ "instant",
+ "lazy_static",
+ "once_cell",
+ "thiserror",
"tokio",
]
[[package]]
-name = "inotify-sys"
-version = "0.1.5"
+name = "cached_proc_macro"
+version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
+checksum = "751f7f4e7a091545e7f6c65bacc404eaee7e87bfb1f9ece234a1caa173dc16f2"
dependencies = [
- "libc",
+ "cached_proc_macro_types",
+ "darling 0.13.4",
+ "quote",
+ "syn",
]
[[package]]
-name = "instant"
-version = "0.1.12"
+name = "cached_proc_macro_types"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+checksum = "3a4f925191b4367301851c6d99b09890311d74b0d43f274c0b34c86d308a3663"
+
+[[package]]
+name = "capctl"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbdc32a78afc325d71a48d13084f1c3ddf67cc5dc06c6e5439a8630b14612cad"
dependencies = [
+ "bitflags",
"cfg-if 1.0.0",
+ "libc",
]
[[package]]
-name = "iovec"
-version = "0.1.4"
+name = "caps"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
+checksum = "190baaad529bcfbde9e1a19022c42781bdb6ff9de25721abdb8fd98c0807730b"
dependencies = [
"libc",
+ "thiserror",
]
[[package]]
-name = "ipnetwork"
-version = "0.17.0"
+name = "cast5"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02c3eaab3ac0ede60ffa41add21970a7df7d91772c03383aac6c2c3d53cc716b"
+checksum = "1285caf81ea1f1ece6b24414c521e625ad0ec94d880625c20f2e65d8d3f78823"
dependencies = [
- "serde",
+ "byteorder",
+ "cipher 0.2.5",
+ "opaque-debug",
]
[[package]]
-name = "itertools"
-version = "0.10.3"
+name = "cc"
+version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
+checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
dependencies = [
- "either",
+ "jobserver",
]
[[package]]
-name = "itoa"
-version = "1.0.2"
+name = "cfg-if"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
+checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
-name = "js-sys"
-version = "0.3.58"
+name = "cfg-if"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27"
-dependencies = [
- "wasm-bindgen",
-]
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
-name = "kata-agent"
-version = "0.1.0"
+name = "cgroups-rs"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3845d8ddaca63e9975f07b7a32262afe284561c2f0f620aa968913a65f671fd2"
dependencies = [
- "anyhow",
- "async-recursion",
- "async-trait",
- "capctl",
- "cgroups-rs",
- "clap",
- "futures",
- "ipnetwork",
- "kata-sys-util",
- "kata-types",
- "lazy_static",
"libc",
"log",
- "logging",
- "netlink-packet-utils",
- "netlink-sys",
- "nix 0.24.2",
- "oci",
- "opentelemetry",
- "procfs",
- "prometheus",
- "protobuf",
- "protocols",
+ "nix 0.24.3",
"regex",
- "rtnetlink",
- "rustjail",
- "scan_fmt",
- "scopeguard",
- "serde",
- "serde_json",
- "serial_test",
- "slog",
- "slog-scope",
- "slog-stdlog",
- "sysinfo",
- "tempfile",
- "test-utils",
- "thiserror",
- "tokio",
- "tokio-vsock",
- "toml",
- "tracing",
- "tracing-opentelemetry",
- "tracing-subscriber",
- "ttrpc",
- "vsock-exporter",
]
[[package]]
-name = "kata-sys-util"
-version = "0.1.0"
+name = "chrono"
+version = "0.4.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
dependencies = [
- "byteorder",
- "cgroups-rs",
- "chrono",
- "common-path",
- "fail",
- "kata-types",
- "lazy_static",
- "libc",
- "nix 0.24.2",
- "oci",
- "once_cell",
- "rand 0.7.3",
- "serde_json",
- "slog",
- "slog-scope",
- "subprocess",
- "thiserror",
+ "iana-time-zone",
+ "js-sys",
+ "num-integer",
+ "num-traits",
+ "serde",
+ "time 0.1.45",
+ "wasm-bindgen",
+ "winapi",
]
[[package]]
-name = "kata-types"
-version = "0.1.0"
+name = "cipher"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801"
dependencies = [
- "byte-unit",
- "glob",
- "lazy_static",
- "num_cpus",
- "oci",
- "regex",
- "serde",
- "serde_json",
- "slog",
- "slog-scope",
- "thiserror",
- "toml",
+ "generic-array",
]
[[package]]
-name = "lazy_static"
-version = "1.4.0"
+name = "cipher"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
+dependencies = [
+ "generic-array",
+]
[[package]]
-name = "libc"
-version = "0.2.126"
+name = "cipher"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
+checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e"
+dependencies = [
+ "crypto-common",
+ "inout",
+]
[[package]]
-name = "libseccomp"
-version = "0.2.3"
+name = "clap"
+version = "3.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49bda1fbf25c42ac8942ff7df1eb6172a3bc36299e84be0dba8c888a7db68c80"
+checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5"
dependencies = [
- "libc",
- "libseccomp-sys",
- "pkg-config",
+ "atty",
+ "bitflags",
+ "clap_derive",
+ "clap_lex",
+ "indexmap",
+ "once_cell",
+ "strsim",
+ "termcolor",
+ "textwrap",
]
[[package]]
-name = "libseccomp-sys"
-version = "0.2.1"
+name = "clap_derive"
+version = "3.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a7cbbd4ad467251987c6e5b47d53b11a5a05add08f2447a9e2d70aef1e0d138"
+checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
+dependencies = [
+ "heck 0.4.0",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
[[package]]
-name = "lock_api"
-version = "0.4.7"
+name = "clap_lex"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
+checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [
- "autocfg",
- "scopeguard",
+ "os_str_bytes",
]
[[package]]
-name = "log"
-version = "0.4.17"
+name = "cmac"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+checksum = "73d4de4f7724e5fe70addfb2bd37c2abd2f95084a429d7773b0b9645499b4272"
dependencies = [
- "cfg-if 1.0.0",
+ "crypto-mac 0.10.1",
+ "dbl",
]
[[package]]
-name = "logging"
-version = "0.1.0"
+name = "codespan-reporting"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
dependencies = [
- "serde_json",
- "slog",
- "slog-async",
- "slog-json",
- "slog-scope",
+ "termcolor",
+ "unicode-width",
]
[[package]]
-name = "matchers"
-version = "0.0.1"
+name = "common-path"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
+checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101"
+
+[[package]]
+name = "concurrent-queue"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b"
dependencies = [
- "regex-automata",
+ "crossbeam-utils",
]
[[package]]
-name = "memchr"
-version = "2.5.0"
+name = "const-oid"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+checksum = "279bc8fc53f788a75c7804af68237d1fce02cde1e275a886a4b320604dc2aeda"
[[package]]
-name = "memoffset"
-version = "0.6.5"
+name = "const-oid"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
+
+[[package]]
+name = "const_fn"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935"
+
+[[package]]
+name = "const_format"
+version = "0.2.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e"
dependencies = [
- "autocfg",
+ "const_format_proc_macros",
]
[[package]]
-name = "miniz_oxide"
-version = "0.5.3"
+name = "const_format_proc_macros"
+version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
+checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650"
dependencies = [
- "adler",
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
]
[[package]]
-name = "mio"
-version = "0.8.4"
+name = "core-foundation"
+version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
+checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
dependencies = [
+ "core-foundation-sys",
"libc",
- "log",
- "wasi 0.11.0+wasi-snapshot-preview1",
- "windows-sys",
]
[[package]]
-name = "multimap"
+name = "core-foundation-sys"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
+checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
-name = "netlink-packet-core"
-version = "0.2.4"
+name = "cpufeatures"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac48279d5062bdf175bdbcb6b58ff1d6b0ecd54b951f7a0ff4bc0550fe903ccb"
+checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
dependencies = [
- "anyhow",
- "byteorder",
"libc",
- "netlink-packet-utils",
]
[[package]]
-name = "netlink-packet-route"
-version = "0.8.0"
+name = "crc32fast"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76aed5d3b6e3929713bf1e1334a11fd65180b6d9f5d7c8572664c48b122604f8"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
- "anyhow",
- "bitflags",
- "byteorder",
- "libc",
- "netlink-packet-core",
- "netlink-packet-utils",
+ "cfg-if 1.0.0",
]
[[package]]
-name = "netlink-packet-utils"
-version = "0.4.1"
+name = "crossbeam"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fcfb6f758b66e964b2339596d94078218d96aad5b32003e8e2a1d23c27a6784"
+checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c"
dependencies = [
- "anyhow",
- "byteorder",
- "paste",
- "thiserror",
+ "cfg-if 1.0.0",
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-epoch",
+ "crossbeam-queue",
+ "crossbeam-utils",
]
[[package]]
-name = "netlink-proto"
-version = "0.7.0"
+name = "crossbeam-channel"
+version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddd06e90449ae973fe3888c1ff85949604ef5189b4ac9a2ae39518da1e00762d"
+checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
dependencies = [
- "bytes 1.1.0",
- "futures",
- "log",
- "netlink-packet-core",
- "netlink-sys",
- "tokio",
- "tokio-util",
+ "cfg-if 1.0.0",
+ "crossbeam-utils",
]
[[package]]
-name = "netlink-sys"
-version = "0.7.0"
+name = "crossbeam-deque"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f48ea34ea0678719815c3753155067212f853ad2d8ef4a49167bae7f7c254188"
+checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
dependencies = [
- "futures",
- "libc",
- "log",
- "tokio",
+ "cfg-if 1.0.0",
+ "crossbeam-epoch",
+ "crossbeam-utils",
]
[[package]]
-name = "nix"
-version = "0.22.3"
+name = "crossbeam-epoch"
+version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf"
+checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
- "bitflags",
- "cc",
+ "autocfg 1.1.0",
"cfg-if 1.0.0",
- "libc",
- "memoffset",
+ "crossbeam-utils",
+ "memoffset 0.7.1",
+ "scopeguard",
]
[[package]]
-name = "nix"
-version = "0.23.1"
+name = "crossbeam-queue"
+version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
+checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
dependencies = [
- "bitflags",
- "cc",
"cfg-if 1.0.0",
- "libc",
- "memoffset",
+ "crossbeam-utils",
]
[[package]]
-name = "nix"
-version = "0.24.2"
+name = "crossbeam-utils"
+version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc"
+checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
- "bitflags",
"cfg-if 1.0.0",
- "libc",
- "memoffset",
]
[[package]]
-name = "ntapi"
-version = "0.3.7"
+name = "crunchy"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
-dependencies = [
- "winapi",
-]
+checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
-name = "num-integer"
-version = "0.1.45"
+name = "crypto-bigint"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
+checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21"
dependencies = [
- "autocfg",
- "num-traits",
+ "generic-array",
+ "subtle",
]
[[package]]
-name = "num-traits"
-version = "0.2.15"
+name = "crypto-common"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
- "autocfg",
+ "generic-array",
+ "rand_core 0.6.4",
+ "typenum",
]
[[package]]
-name = "num_cpus"
-version = "1.13.1"
+name = "crypto-mac"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a"
dependencies = [
- "hermit-abi",
- "libc",
+ "cipher 0.2.5",
+ "generic-array",
+ "subtle",
]
[[package]]
-name = "num_threads"
-version = "0.1.6"
+name = "crypto-mac"
+version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
+checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714"
dependencies = [
- "libc",
+ "generic-array",
+ "subtle",
]
[[package]]
-name = "oci"
-version = "0.1.0"
+name = "ctr"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f"
dependencies = [
- "libc",
- "serde",
- "serde_derive",
- "serde_json",
+ "cipher 0.2.5",
]
[[package]]
-name = "once_cell"
-version = "1.12.0"
+name = "ctr"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
+checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea"
+dependencies = [
+ "cipher 0.3.0",
+]
[[package]]
-name = "opentelemetry"
-version = "0.14.0"
+name = "ctr"
+version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "492848ff47f11b7f9de0443b404e2c5775f695e1af6b7076ca25f999581d547a"
+checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
dependencies = [
- "async-trait",
- "crossbeam-channel",
- "futures",
- "js-sys",
- "lazy_static",
- "percent-encoding",
- "pin-project",
- "rand 0.8.5",
- "serde",
- "thiserror",
- "tokio",
- "tokio-stream",
+ "cipher 0.4.3",
]
[[package]]
-name = "os_str_bytes"
-version = "6.1.0"
+name = "curve25519-dalek"
+version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa"
-
-[[package]]
-name = "parking_lot"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61"
dependencies = [
- "instant",
- "lock_api",
- "parking_lot_core 0.8.5",
+ "byteorder",
+ "digest 0.9.0",
+ "rand_core 0.5.1",
+ "subtle",
+ "zeroize",
]
[[package]]
-name = "parking_lot"
-version = "0.12.1"
+name = "cxx"
+version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd"
dependencies = [
- "lock_api",
- "parking_lot_core 0.9.3",
+ "cc",
+ "cxxbridge-flags",
+ "cxxbridge-macro",
+ "link-cplusplus",
]
[[package]]
-name = "parking_lot_core"
-version = "0.8.5"
+name = "cxx-build"
+version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
+checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0"
dependencies = [
- "cfg-if 1.0.0",
- "instant",
- "libc",
- "redox_syscall",
- "smallvec",
- "winapi",
+ "cc",
+ "codespan-reporting",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "scratch",
+ "syn",
]
[[package]]
-name = "parking_lot_core"
-version = "0.9.3"
+name = "cxxbridge-flags"
+version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
-dependencies = [
- "cfg-if 1.0.0",
- "libc",
- "redox_syscall",
- "smallvec",
- "windows-sys",
-]
+checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59"
[[package]]
-name = "paste"
-version = "1.0.7"
+name = "cxxbridge-macro"
+version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc"
+checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
[[package]]
-name = "path-absolutize"
-version = "1.2.1"
+name = "darling"
+version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ceeedc827d9a758b4641457683ced2f02d4252cc1bd8794c415ed20256114290"
+checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
dependencies = [
- "path-dedot",
- "slash-formatter",
+ "darling_core 0.13.4",
+ "darling_macro 0.13.4",
]
[[package]]
-name = "path-dedot"
-version = "1.2.4"
+name = "darling"
+version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45c58ab1edb03f77d0bb3f08e4a179dd43ce9bc8eab9867ec53a78285ea3039b"
+checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa"
dependencies = [
- "lazy_static",
+ "darling_core 0.14.2",
+ "darling_macro 0.14.2",
]
[[package]]
-name = "percent-encoding"
-version = "2.1.0"
+name = "darling_core"
+version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn",
+]
[[package]]
-name = "petgraph"
-version = "0.5.1"
+name = "darling_core"
+version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
+checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f"
dependencies = [
- "fixedbitset",
- "indexmap",
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn",
]
[[package]]
-name = "pin-project"
-version = "1.0.10"
+name = "darling_macro"
+version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e"
+checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
dependencies = [
- "pin-project-internal",
+ "darling_core 0.13.4",
+ "quote",
+ "syn",
]
[[package]]
-name = "pin-project-internal"
-version = "1.0.10"
+name = "darling_macro"
+version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb"
+checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e"
dependencies = [
- "proc-macro2",
+ "darling_core 0.14.2",
"quote",
"syn",
]
[[package]]
-name = "pin-project-lite"
-version = "0.2.9"
+name = "data-encoding"
+version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb"
[[package]]
-name = "pin-utils"
-version = "0.1.0"
+name = "dbl"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+checksum = "bd2735a791158376708f9347fe8faba9667589d82427ef3aed6794a8981de3d9"
+dependencies = [
+ "generic-array",
+]
[[package]]
-name = "pkg-config"
-version = "0.3.25"
+name = "der"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
+checksum = "2eeb9d92785d1facb50567852ce75d0858630630e7eabea59cf7eb7474051087"
+dependencies = [
+ "const-oid 0.5.2",
+ "typenum",
+]
[[package]]
-name = "ppv-lite86"
-version = "0.2.16"
+name = "der"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c"
+dependencies = [
+ "const-oid 0.7.1",
+ "crypto-bigint",
+ "pem-rfc7468",
+]
[[package]]
-name = "proc-macro-error"
-version = "1.0.4"
+name = "der-parser"
+version = "8.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+checksum = "42d4bc9b0db0a0df9ae64634ac5bdefb7afcb534e182275ca0beadbe486701c1"
+dependencies = [
+ "asn1-rs",
+ "displaydoc",
+ "nom",
+ "num-bigint 0.4.3",
+ "num-traits",
+ "rusticata-macros",
+]
+
+[[package]]
+name = "derivative"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
dependencies = [
- "proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
- "version_check",
]
[[package]]
-name = "proc-macro-error-attr"
-version = "1.0.4"
+name = "derive-new"
+version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535"
dependencies = [
"proc-macro2",
"quote",
- "version_check",
+ "syn",
]
[[package]]
-name = "proc-macro2"
-version = "1.0.40"
+name = "derive_builder"
+version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
+checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8"
dependencies = [
- "unicode-ident",
+ "derive_builder_macro",
]
[[package]]
-name = "procfs"
+name = "derive_builder_core"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0941606b9934e2d98a3677759a971756eb821f75764d0e0d26946d08e74d9104"
+checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f"
dependencies = [
- "bitflags",
- "byteorder",
- "chrono",
- "flate2",
- "hex",
- "lazy_static",
- "libc",
+ "darling 0.14.2",
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
-name = "prometheus"
-version = "0.13.1"
+name = "derive_builder_macro"
+version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cface98dfa6d645ea4c789839f176e4b072265d085bfcc48eaa8d137f58d3c39"
+checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e"
dependencies = [
- "cfg-if 1.0.0",
- "fnv",
- "lazy_static",
- "libc",
- "memchr",
- "parking_lot 0.12.1",
- "procfs",
- "protobuf",
- "thiserror",
+ "derive_builder_core",
+ "syn",
]
[[package]]
-name = "prost"
-version = "0.8.0"
+name = "des"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020"
+checksum = "b24e7c748888aa2fa8bce21d8c64a52efc810663285315ac7476f7197a982fae"
dependencies = [
- "bytes 1.1.0",
- "prost-derive",
+ "byteorder",
+ "cipher 0.2.5",
+ "opaque-debug",
]
[[package]]
-name = "prost-build"
-version = "0.8.0"
+name = "diff"
+version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603"
+checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
+
+[[package]]
+name = "digest"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
- "bytes 1.1.0",
- "heck 0.3.3",
- "itertools",
- "log",
- "multimap",
- "petgraph",
- "prost",
- "prost-types",
- "tempfile",
- "which",
+ "generic-array",
]
[[package]]
-name = "prost-derive"
-version = "0.8.0"
+name = "digest"
+version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba"
+checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
dependencies = [
- "anyhow",
- "itertools",
- "proc-macro2",
- "quote",
- "syn",
+ "block-buffer 0.10.3",
+ "crypto-common",
+ "subtle",
]
[[package]]
-name = "prost-types"
-version = "0.8.0"
+name = "dircpy"
+version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b"
+checksum = "73ff6269b47c0c5220a0ff5eb140424340276ec89a10e58cbd4cf366de52dfa9"
dependencies = [
- "bytes 1.1.0",
- "prost",
+ "jwalk",
+ "log",
+ "walkdir",
]
[[package]]
-name = "protobuf"
-version = "2.27.1"
+name = "dirs"
+version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf7e6d18738ecd0902d30d1ad232c9125985a3422929b16c65517b38adc14f96"
+checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
dependencies = [
- "serde",
- "serde_derive",
+ "dirs-sys",
]
[[package]]
-name = "protobuf-codegen"
-version = "2.27.1"
+name = "dirs-next"
+version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aec1632b7c8f2e620343439a7dfd1f3c47b18906c4be58982079911482b5d707"
+checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
dependencies = [
- "protobuf",
+ "cfg-if 1.0.0",
+ "dirs-sys-next",
]
[[package]]
-name = "protobuf-codegen-pure"
-version = "2.27.1"
+name = "dirs-sys"
+version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f8122fdb18e55190c796b088a16bdb70cd7acdcd48f7a8b796b58c62e532cc6"
+checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
dependencies = [
- "protobuf",
- "protobuf-codegen",
+ "libc",
+ "redox_users",
+ "winapi",
]
[[package]]
-name = "protocols"
-version = "0.1.0"
+name = "dirs-sys-next"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
dependencies = [
- "async-trait",
- "oci",
- "protobuf",
- "ttrpc",
- "ttrpc-codegen",
+ "libc",
+ "redox_users",
+ "winapi",
]
[[package]]
-name = "quote"
-version = "1.0.20"
+name = "displaydoc"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
+checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
dependencies = [
"proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
-name = "rand"
-version = "0.7.3"
+name = "doc-comment"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
+
+[[package]]
+name = "dyn-clone"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9b0705efd4599c15a38151f4721f7bc388306f61084d3bfd50bd07fbca5cb60"
+
+[[package]]
+name = "eax"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1f76e7a5e594b299a0fa9a99de627530725e341df41376aa342aecb2c5eb76e"
dependencies = [
- "getrandom 0.1.16",
- "libc",
- "rand_chacha 0.2.2",
- "rand_core 0.5.1",
- "rand_hc",
+ "aead 0.3.2",
+ "cipher 0.2.5",
+ "cmac",
+ "ctr 0.6.0",
+ "subtle",
]
[[package]]
-name = "rand"
-version = "0.8.5"
+name = "ecdsa"
+version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+checksum = "34d33b390ab82f2e1481e331dbd0530895640179d2128ef9a79cc690b78d1eba"
dependencies = [
- "libc",
- "rand_chacha 0.3.1",
- "rand_core 0.6.3",
+ "der 0.3.5",
+ "elliptic-curve",
+ "hmac 0.11.0",
+ "signature",
]
[[package]]
-name = "rand_chacha"
-version = "0.2.2"
+name = "ed25519"
+version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369"
dependencies = [
- "ppv-lite86",
- "rand_core 0.5.1",
+ "signature",
]
[[package]]
-name = "rand_chacha"
-version = "0.3.1"
+name = "ed25519-dalek"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d"
dependencies = [
- "ppv-lite86",
- "rand_core 0.6.3",
+ "curve25519-dalek",
+ "ed25519",
+ "rand 0.7.3",
+ "sha2 0.9.9",
+ "zeroize",
]
[[package]]
-name = "rand_core"
-version = "0.5.1"
+name = "either"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
+
+[[package]]
+name = "elliptic-curve"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c13e9b0c3c4170dcc2a12783746c4205d98e18957f57854251eea3f9750fe005"
dependencies = [
- "getrandom 0.1.16",
+ "bitvec",
+ "ff",
+ "generic-array",
+ "group",
+ "pkcs8 0.6.1",
+ "rand_core 0.6.4",
+ "subtle",
+ "zeroize",
]
[[package]]
-name = "rand_core"
-version = "0.6.3"
+name = "ena"
+version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3"
dependencies = [
- "getrandom 0.2.7",
+ "log",
]
[[package]]
-name = "rand_hc"
-version = "0.2.0"
+name = "encoding_rs"
+version = "0.8.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b"
dependencies = [
- "rand_core 0.5.1",
+ "cfg-if 1.0.0",
]
[[package]]
-name = "rayon"
-version = "1.5.3"
+name = "enumflags2"
+version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
+checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb"
dependencies = [
- "autocfg",
- "crossbeam-deque",
- "either",
- "rayon-core",
+ "enumflags2_derive",
+ "serde",
]
[[package]]
-name = "rayon-core"
-version = "1.9.3"
+name = "enumflags2_derive"
+version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
+checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae"
dependencies = [
- "crossbeam-channel",
- "crossbeam-deque",
- "crossbeam-utils",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
+dependencies = [
+ "atty",
+ "humantime",
+ "log",
+ "regex",
+ "termcolor",
+]
+
+[[package]]
+name = "errno"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "event-listener"
+version = "2.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
+
+[[package]]
+name = "fail"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe5e43d0f78a42ad591453aedb1d7ae631ce7ee445c7643691055a9ed8d3b01c"
+dependencies = [
+ "log",
+ "once_cell",
+ "rand 0.8.5",
+]
+
+[[package]]
+name = "fastrand"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
+dependencies = [
+ "instant",
+]
+
+[[package]]
+name = "ff"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72a4d941a5b7c2a75222e2d44fcdf634a67133d9db31e177ae5ff6ecda852bfe"
+dependencies = [
+ "bitvec",
+ "rand_core 0.6.4",
+ "subtle",
+]
+
+[[package]]
+name = "filetime"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "redox_syscall",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "fixedbitset"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
+
+[[package]]
+name = "fixedbitset"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
+
+[[package]]
+name = "flate2"
+version = "1.0.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "flume"
+version = "0.10.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+ "nanorand",
+ "pin-project",
+ "spin 0.9.4",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared 0.1.1",
+]
+
+[[package]]
+name = "foreign-types"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
+dependencies = [
+ "foreign-types-macros",
+ "foreign-types-shared 0.3.1",
+]
+
+[[package]]
+name = "foreign-types-macros"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8469d0d40519bc608ec6863f1cc88f3f1deee15913f2f3b3e573d81ed38cccc"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "fs_extra"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394"
+
+[[package]]
+name = "funty"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
+
+[[package]]
+name = "futures"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"
+
+[[package]]
+name = "futures-lite"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48"
+dependencies = [
+ "fastrand",
+ "futures-core",
+ "futures-io",
+ "memchr",
+ "parking",
+ "pin-project-lite",
+ "waker-fn",
+]
+
+[[package]]
+name = "futures-macro"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"
+
+[[package]]
+name = "futures-task"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea"
+
+[[package]]
+name = "futures-util"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+dependencies = [
+ "cfg-if 1.0.0",
+ "js-sys",
+ "libc",
+ "wasi 0.9.0+wasi-snapshot-preview1",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
+dependencies = [
+ "cfg-if 1.0.0",
+ "js-sys",
+ "libc",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "getset"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9"
+dependencies = [
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "ghash"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
+dependencies = [
+ "opaque-debug",
+ "polyval 0.5.3",
+]
+
+[[package]]
+name = "ghash"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
+dependencies = [
+ "opaque-debug",
+ "polyval 0.6.0",
+]
+
+[[package]]
+name = "git2"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2994bee4a3a6a51eb90c218523be382fd7ea09b16380b9312e9dbe955ff7c7d1"
+dependencies = [
+ "bitflags",
+ "libc",
+ "libgit2-sys",
+ "log",
+ "url",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+
+[[package]]
+name = "globset"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a"
+dependencies = [
+ "aho-corasick",
+ "bstr",
+ "fnv",
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "group"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61b3c1e8b4f1ca07e6605ea1be903a5f6956aec5c8a67fd44d56076631675ed8"
+dependencies = [
+ "ff",
+ "rand_core 0.6.4",
+ "subtle",
+]
+
+[[package]]
+name = "h2"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4"
+dependencies = [
+ "bytes 1.3.0",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util 0.7.4",
+ "tracing",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+
+[[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "heck"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "hmac"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
+dependencies = [
+ "crypto-mac 0.11.1",
+ "digest 0.9.0",
+]
+
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest 0.10.6",
+]
+
+[[package]]
+name = "http"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
+dependencies = [
+ "bytes 1.3.0",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-auth"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0b40b39d66c28829a0cf4d09f7e139ff8201f7500a5083732848ed3b4b4d850"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "http-body"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
+dependencies = [
+ "bytes 1.3.0",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "http-range-header"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29"
+
+[[package]]
+name = "httparse"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
+
+[[package]]
+name = "httpdate"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
+[[package]]
+name = "hyper"
+version = "0.14.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c"
+dependencies = [
+ "bytes 1.3.0",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-timeout"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
+dependencies = [
+ "hyper",
+ "pin-project-lite",
+ "tokio",
+ "tokio-io-timeout",
+]
+
+[[package]]
+name = "hyper-tls"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
+dependencies = [
+ "bytes 1.3.0",
+ "hyper",
+ "native-tls",
+ "tokio",
+ "tokio-native-tls",
+]
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.53"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "winapi",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
+dependencies = [
+ "cxx",
+ "cxx-build",
+]
+
+[[package]]
+name = "idea"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcdd4b114cf2265123bbdc5d32a39f96a343fbdf141267d2b5232b7e14caacb3"
+dependencies = [
+ "cipher 0.2.5",
+ "opaque-debug",
+]
+
+[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
+[[package]]
+name = "idna"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "image-rs"
+version = "0.1.0"
+source = "git+https://github.com/confidential-containers/image-rs?rev=v0.3.0#cf1f7f96eb60ec4cc4aaa671c04d574a4ea0e441"
+dependencies = [
+ "anyhow",
+ "async-compression",
+ "async-trait",
+ "attestation_agent",
+ "base64",
+ "dircpy",
+ "flate2",
+ "flume",
+ "fs_extra",
+ "futures-util",
+ "hex",
+ "libc",
+ "log",
+ "nix 0.23.2",
+ "oci-distribution",
+ "oci-spec",
+ "ocicrypt-rs",
+ "prost 0.8.0",
+ "sequoia-openpgp",
+ "serde",
+ "serde_json",
+ "serde_yaml",
+ "sha2 0.10.6",
+ "shadow-rs 0.17.1",
+ "sigstore",
+ "strum",
+ "strum_macros",
+ "tar",
+ "tokio",
+ "tonic 0.5.2",
+ "tonic-build 0.5.2",
+ "url",
+ "walkdir",
+ "zstd 0.12.1+zstd.1.5.2",
+]
+
+[[package]]
+name = "indexmap"
+version = "1.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
+dependencies = [
+ "autocfg 1.1.0",
+ "hashbrown",
+]
+
+[[package]]
+name = "inotify"
+version = "0.9.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
+dependencies = [
+ "bitflags",
+ "futures-core",
+ "inotify-sys",
+ "libc",
+ "tokio",
+]
+
+[[package]]
+name = "inotify-sys"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "inout"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
+name = "io-lifetimes"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
+dependencies = [
+ "libc",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "iovec"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "ipnet"
+version = "2.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11b0d96e660696543b251e58030cf9787df56da39dab19ad60eae7353040917e"
+
+[[package]]
+name = "ipnetwork"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02c3eaab3ac0ede60ffa41add21970a7df7d91772c03383aac6c2c3d53cc716b"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "is_debug"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06d198e9919d9822d5f7083ba8530e04de87841eaf21ead9af8f2304efd57c89"
+
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
+
+[[package]]
+name = "jobserver"
+version = "0.1.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "josekit"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dee6af62ad98bdf699ad2ecc8323479a1fdc7aa5faa6043d93119d83f6c5fca8"
+dependencies = [
+ "anyhow",
+ "base64",
+ "flate2",
+ "once_cell",
+ "openssl",
+ "regex",
+ "serde",
+ "serde_json",
+ "thiserror",
+ "time 0.3.17",
+]
+
+[[package]]
+name = "js-sys"
+version = "0.3.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "jwalk"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dbcda57db8b6dc067e589628b7348639014e793d9e8137d8cf215e8b133a0bd"
+dependencies = [
+ "crossbeam",
+ "rayon",
+]
+
+[[package]]
+name = "jwt"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6204285f77fe7d9784db3fdc449ecce1a0114927a51d5a41c4c7a292011c015f"
+dependencies = [
+ "base64",
+ "crypto-common",
+ "digest 0.10.6",
+ "hmac 0.12.1",
+ "serde",
+ "serde_json",
+ "sha2 0.10.6",
+]
+
+[[package]]
+name = "kata-agent"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "async-recursion",
+ "async-trait",
+ "capctl",
+ "cgroups-rs",
+ "clap",
+ "futures",
+ "image-rs",
+ "ipnetwork",
+ "kata-sys-util",
+ "kata-types",
+ "lazy_static",
+ "libc",
+ "log",
+ "logging",
+ "netlink-packet-utils",
+ "netlink-sys",
+ "nix 0.24.3",
+ "oci",
+ "openssl",
+ "opentelemetry",
+ "procfs 0.12.0",
+ "prometheus",
+ "protobuf",
+ "protocols",
+ "regex",
+ "rtnetlink",
+ "rustjail",
+ "scan_fmt",
+ "scopeguard",
+ "serde",
+ "serde_json",
+ "serial_test",
+ "slog",
+ "slog-scope",
+ "slog-stdlog",
+ "tempfile",
+ "test-utils",
+ "thiserror",
+ "tokio",
+ "tokio-vsock",
+ "toml",
+ "tracing",
+ "tracing-opentelemetry",
+ "tracing-subscriber",
+ "ttrpc",
+ "url",
+ "vsock-exporter",
+ "which",
+]
+
+[[package]]
+name = "kata-sys-util"
+version = "0.1.0"
+dependencies = [
+ "byteorder",
+ "cgroups-rs",
+ "chrono",
+ "common-path",
+ "fail",
+ "kata-types",
+ "lazy_static",
+ "libc",
+ "nix 0.24.3",
+ "oci",
+ "once_cell",
+ "rand 0.7.3",
+ "serde_json",
+ "slog",
+ "slog-scope",
+ "subprocess",
+ "thiserror",
+]
+
+[[package]]
+name = "kata-types"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "base64",
+ "bitmask-enum",
+ "byte-unit",
+ "glob",
+ "lazy_static",
+ "num_cpus",
+ "oci",
+ "regex",
+ "serde",
+ "serde_json",
+ "slog",
+ "slog-scope",
+ "thiserror",
+ "toml",
+]
+
+[[package]]
+name = "keccak"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768"
+dependencies = [
+ "cpufeatures",
+]
+
+[[package]]
+name = "lalrpop"
+version = "0.19.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b30455341b0e18f276fa64540aff54deafb54c589de6aca68659c63dd2d5d823"
+dependencies = [
+ "ascii-canvas",
+ "atty",
+ "bit-set",
+ "diff",
+ "ena",
+ "itertools",
+ "lalrpop-util",
+ "petgraph 0.6.2",
+ "regex",
+ "regex-syntax",
+ "string_cache",
+ "term",
+ "tiny-keccak",
+ "unicode-xid",
+]
+
+[[package]]
+name = "lalrpop-util"
+version = "0.19.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcf796c978e9b4d983414f4caedc9273aa33ee214c5b887bd55fde84c85d2dc4"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+dependencies = [
+ "spin 0.5.2",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.139"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
+
+[[package]]
+name = "libgit2-sys"
+version = "0.14.0+1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47a00859c70c8a4f7218e6d1cc32875c4b55f6799445b842b0d8ed5e4c3d959b"
+dependencies = [
+ "cc",
+ "libc",
+ "libz-sys",
+ "pkg-config",
+]
+
+[[package]]
+name = "libm"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
+
+[[package]]
+name = "libseccomp"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21c57fd8981a80019807b7b68118618d29a87177c63d704fc96e6ecd003ae5b3"
+dependencies = [
+ "bitflags",
+ "libc",
+ "libseccomp-sys",
+ "pkg-config",
+]
+
+[[package]]
+name = "libseccomp-sys"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a7cbbd4ad467251987c6e5b47d53b11a5a05add08f2447a9e2d70aef1e0d138"
+
+[[package]]
+name = "libz-sys"
+version = "1.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "link-cplusplus"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
+
+[[package]]
+name = "lock_api"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
+dependencies = [
+ "autocfg 1.1.0",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
+name = "logging"
+version = "0.1.0"
+dependencies = [
+ "serde_json",
+ "slog",
+ "slog-async",
+ "slog-json",
+ "slog-scope",
+]
+
+[[package]]
+name = "matchers"
+version = "0.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
+dependencies = [
+ "regex-automata",
+]
+
+[[package]]
+name = "matchit"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40"
+
+[[package]]
+name = "md-5"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15"
+dependencies = [
+ "block-buffer 0.9.0",
+ "digest 0.9.0",
+ "opaque-debug",
+]
+
+[[package]]
+name = "md-5"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca"
+dependencies = [
+ "digest 0.10.6",
+]
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "memoffset"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+dependencies = [
+ "autocfg 1.1.0",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
+dependencies = [
+ "autocfg 1.1.0",
+]
+
+[[package]]
+name = "memsec"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ac78937f19a0c7807e45a931eac41f766f210173ec664ec046d58e6d388a5cb"
+
+[[package]]
+name = "mime"
+version = "0.3.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "mio"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
+dependencies = [
+ "libc",
+ "log",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "multimap"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
+
+[[package]]
+name = "nanorand"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
+dependencies = [
+ "getrandom 0.2.8",
+]
+
+[[package]]
+name = "native-tls"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
+dependencies = [
+ "lazy_static",
+ "libc",
+ "log",
+ "openssl",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "security-framework",
+ "security-framework-sys",
+ "tempfile",
+]
+
+[[package]]
+name = "netlink-packet-core"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac48279d5062bdf175bdbcb6b58ff1d6b0ecd54b951f7a0ff4bc0550fe903ccb"
+dependencies = [
+ "anyhow",
+ "byteorder",
+ "libc",
+ "netlink-packet-utils",
+]
+
+[[package]]
+name = "netlink-packet-route"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76aed5d3b6e3929713bf1e1334a11fd65180b6d9f5d7c8572664c48b122604f8"
+dependencies = [
+ "anyhow",
+ "bitflags",
+ "byteorder",
+ "libc",
+ "netlink-packet-core",
+ "netlink-packet-utils",
+]
+
+[[package]]
+name = "netlink-packet-utils"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fcfb6f758b66e964b2339596d94078218d96aad5b32003e8e2a1d23c27a6784"
+dependencies = [
+ "anyhow",
+ "byteorder",
+ "paste",
+ "thiserror",
+]
+
+[[package]]
+name = "netlink-proto"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddd06e90449ae973fe3888c1ff85949604ef5189b4ac9a2ae39518da1e00762d"
+dependencies = [
+ "bytes 1.3.0",
+ "futures",
+ "log",
+ "netlink-packet-core",
+ "netlink-sys",
+ "tokio",
+ "tokio-util 0.6.10",
+]
+
+[[package]]
+name = "netlink-sys"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f48ea34ea0678719815c3753155067212f853ad2d8ef4a49167bae7f7c254188"
+dependencies = [
+ "futures",
+ "libc",
+ "log",
+ "tokio",
+]
+
+[[package]]
+name = "new_debug_unreachable"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
+
+[[package]]
+name = "nix"
+version = "0.22.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf"
+dependencies = [
+ "bitflags",
+ "cc",
+ "cfg-if 1.0.0",
+ "libc",
+ "memoffset 0.6.5",
+]
+
+[[package]]
+name = "nix"
+version = "0.23.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c"
+dependencies = [
+ "bitflags",
+ "cc",
+ "cfg-if 1.0.0",
+ "libc",
+ "memoffset 0.6.5",
+]
+
+[[package]]
+name = "nix"
+version = "0.24.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"
+dependencies = [
+ "bitflags",
+ "cfg-if 1.0.0",
+ "libc",
+ "memoffset 0.6.5",
+]
+
+[[package]]
+name = "nom"
+version = "7.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5507769c4919c998e69e49c839d9dc6e693ede4cc4290d6ad8b41d4f09c548c"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
+dependencies = [
+ "autocfg 1.1.0",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-bigint"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
+dependencies = [
+ "autocfg 1.1.0",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-bigint-dig"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d51546d704f52ef14b3c962b5776e53d5b862e5790e40a350d366c209bd7f7a"
+dependencies = [
+ "autocfg 0.1.8",
+ "byteorder",
+ "lazy_static",
+ "libm",
+ "num-integer",
+ "num-iter",
+ "num-traits",
+ "rand 0.7.3",
+ "serde",
+ "smallvec",
+ "zeroize",
+]
+
+[[package]]
+name = "num-bigint-dig"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2399c9463abc5f909349d8aa9ba080e0b88b3ce2885389b60b993f39b1a56905"
+dependencies = [
+ "byteorder",
+ "lazy_static",
+ "libm",
+ "num-integer",
+ "num-iter",
+ "num-traits",
+ "rand 0.8.5",
+ "serde",
+ "smallvec",
+ "zeroize",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
+dependencies = [
+ "autocfg 1.1.0",
+ "num-traits",
+]
+
+[[package]]
+name = "num-iter"
+version = "0.1.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
+dependencies = [
+ "autocfg 1.1.0",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+dependencies = [
+ "autocfg 1.1.0",
+ "libm",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
+dependencies = [
+ "hermit-abi 0.2.6",
+ "libc",
+]
+
+[[package]]
+name = "num_threads"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "oauth2"
+version = "4.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eeaf26a72311c087f8c5ba617c96fac67a5c04f430e716ac8d8ab2de62e23368"
+dependencies = [
+ "base64",
+ "chrono",
+ "getrandom 0.2.8",
+ "http",
+ "rand 0.8.5",
+ "reqwest",
+ "serde",
+ "serde_json",
+ "serde_path_to_error",
+ "sha2 0.10.6",
+ "thiserror",
+ "url",
+]
+
+[[package]]
+name = "oci"
+version = "0.1.0"
+dependencies = [
+ "libc",
+ "serde",
+ "serde_derive",
+ "serde_json",
+]
+
+[[package]]
+name = "oci-distribution"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ac5b780ce1bd6c3c2ff72a3013f4b2d56d53ae03b20d424e99d2f6556125138"
+dependencies = [
+ "futures",
+ "futures-util",
+ "http",
+ "http-auth",
+ "jwt",
+ "lazy_static",
+ "olpc-cjson",
+ "regex",
+ "reqwest",
+ "serde",
+ "serde_json",
+ "sha2 0.10.6",
+ "thiserror",
+ "tokio",
+ "tokio-util 0.7.4",
+ "tracing",
+ "unicase",
+]
+
+[[package]]
+name = "oci-spec"
+version = "0.5.8"
+source = "git+https://github.com/containers/oci-spec-rs#4614d7c3b5b28184bd10cb42adf7b4ec907b5e93"
+dependencies = [
+ "derive_builder",
+ "getset",
+ "serde",
+ "serde_json",
+ "thiserror",
+]
+
+[[package]]
+name = "ocicrypt-rs"
+version = "0.1.0"
+source = "git+https://github.com/confidential-containers/ocicrypt-rs?rev=6c84dde#6c84dde2698175e6b9d2c7db6882ca35bafb20a9"
+dependencies = [
+ "aes 0.8.2",
+ "aes-gcm 0.9.4",
+ "anyhow",
+ "attestation_agent",
+ "base64",
+ "base64-serde",
+ "ctr 0.9.2",
+ "futures",
+ "hmac 0.12.1",
+ "josekit",
+ "lazy_static",
+ "oci-distribution",
+ "openssl",
+ "pin-project-lite",
+ "prost 0.11.5",
+ "serde",
+ "serde_json",
+ "sha2 0.10.6",
+ "tokio",
+ "tonic 0.8.3",
+ "tonic-build 0.8.4",
+]
+
+[[package]]
+name = "oid"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c19903c598813dba001b53beeae59bb77ad4892c5c1b9b3500ce4293a0d06c2"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "oid-registry"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff"
+dependencies = [
+ "asn1-rs",
+]
+
+[[package]]
+name = "olpc-cjson"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87dc75cf72208cd853671c1abccc5d5d1e43b1e378dde67340ef933219a8c13c"
+dependencies = [
+ "serde",
+ "serde_json",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
+
+[[package]]
+name = "opaque-debug"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+
+[[package]]
+name = "open"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2078c0039e6a54a0c42c28faa984e115fb4c2d5bf2208f77d1961002df8576f8"
+dependencies = [
+ "pathdiff",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "openidconnect"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87af7097640fedbe64718ac1c9b0549d72da747a3f527cd089215f96c6f691d5"
+dependencies = [
+ "base64",
+ "chrono",
+ "http",
+ "itertools",
+ "log",
+ "num-bigint 0.4.3",
+ "oauth2",
+ "rand 0.8.5",
+ "ring",
+ "serde",
+ "serde-value",
+ "serde_derive",
+ "serde_json",
+ "serde_path_to_error",
+ "thiserror",
+ "url",
+]
+
+[[package]]
+name = "openssl"
+version = "0.10.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1"
+dependencies = [
+ "bitflags",
+ "cfg-if 1.0.0",
+ "foreign-types 0.3.2",
+ "libc",
+ "once_cell",
+ "openssl-macros",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+
+[[package]]
+name = "openssl-src"
+version = "111.24.0+1.1.1s"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3498f259dab01178c6228c6b00dcef0ed2a2d5e20d648c017861227773ea4abd"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.80"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7"
+dependencies = [
+ "autocfg 1.1.0",
+ "cc",
+ "libc",
+ "openssl-src",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "opentelemetry"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "492848ff47f11b7f9de0443b404e2c5775f695e1af6b7076ca25f999581d547a"
+dependencies = [
+ "async-trait",
+ "crossbeam-channel",
+ "futures",
+ "js-sys",
+ "lazy_static",
+ "percent-encoding",
+ "pin-project",
+ "rand 0.8.5",
+ "serde",
+ "thiserror",
+ "tokio",
+ "tokio-stream",
+]
+
+[[package]]
+name = "ordered-float"
+version = "2.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "ordered-stream"
+version = "0.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44630c059eacfd6e08bdaa51b1db2ce33119caa4ddc1235e923109aa5f25ccb1"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "os_str_bytes"
+version = "6.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
+
+[[package]]
+name = "p256"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f05f5287453297c4c16af5e2b04df8fd2a3008d70f252729650bc6d7ace5844"
+dependencies = [
+ "ecdsa",
+ "elliptic-curve",
+ "sha2 0.9.9",
+]
+
+[[package]]
+name = "parking"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
+
+[[package]]
+name = "parking_lot"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core 0.8.6",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core 0.9.5",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
+dependencies = [
+ "cfg-if 1.0.0",
+ "instant",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "paste"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
+
+[[package]]
+name = "path-absolutize"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ceeedc827d9a758b4641457683ced2f02d4252cc1bd8794c415ed20256114290"
+dependencies = [
+ "path-dedot 1.2.4",
+ "slash-formatter",
+]
+
+[[package]]
+name = "path-absolutize"
+version = "3.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f1d4993b16f7325d90c18c3c6a3327db7808752db8d208cea0acee0abd52c52"
+dependencies = [
+ "path-dedot 3.0.18",
+]
+
+[[package]]
+name = "path-dedot"
+version = "1.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45c58ab1edb03f77d0bb3f08e4a179dd43ce9bc8eab9867ec53a78285ea3039b"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "path-dedot"
+version = "3.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a81540d94551664b72b72829b12bd167c73c9d25fbac0e04fafa8023f7e4901"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "pathdiff"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+
+[[package]]
+name = "pem"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb"
+dependencies = [
+ "base64",
+ "once_cell",
+ "regex",
+]
+
+[[package]]
+name = "pem"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03c64931a1a212348ec4f3b4362585eca7159d0d09cbdf4a7f74f02173596fd4"
+dependencies = [
+ "base64",
+]
+
+[[package]]
+name = "pem-rfc7468"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01de5d978f34aa4b2296576379fcc416034702fd94117c56ffd8a1a767cefb30"
+dependencies = [
+ "base64ct",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
+
+[[package]]
+name = "petgraph"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
+dependencies = [
+ "fixedbitset 0.2.0",
+ "indexmap",
+]
+
+[[package]]
+name = "petgraph"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143"
+dependencies = [
+ "fixedbitset 0.4.2",
+ "indexmap",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
+name = "picky"
+version = "7.0.0-rc.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b467d8082dcc552d4ca8c9aecdc94a09b0e092b961c542bb78b6feff8f1b3ea"
+dependencies = [
+ "base64",
+ "digest 0.10.6",
+ "md-5 0.10.5",
+ "num-bigint-dig 0.8.2",
+ "oid",
+ "picky-asn1 0.6.0",
+ "picky-asn1-der",
+ "picky-asn1-x509",
+ "rand 0.8.5",
+ "ring",
+ "rsa 0.6.1",
+ "serde",
+ "sha-1 0.10.1",
+ "sha2 0.10.6",
+ "sha3",
+ "thiserror",
+]
+
+[[package]]
+name = "picky-asn1"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1088a7f82ee21e534da0f62b074b559d2a0717b0d5104ba7a47c1f5bc6c83f69"
+dependencies = [
+ "oid",
+ "serde",
+ "serde_bytes",
+]
+
+[[package]]
+name = "picky-asn1"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b7a3f07db0e5b22727979a992df18c78170c7c30279ab4149a395c0c3843832"
+dependencies = [
+ "oid",
+ "serde",
+ "serde_bytes",
+ "zeroize",
+]
+
+[[package]]
+name = "picky-asn1-der"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de76bf631e2f2064f78d7f1ea8a57cb0445d83138cd5fac67274d50b0f6053c2"
+dependencies = [
+ "picky-asn1 0.5.0",
+ "serde",
+ "serde_bytes",
+]
+
+[[package]]
+name = "picky-asn1-x509"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25ffcd92e3f788f0f76506f3b86310876cc0014ade835d68a6365ee0fd1009dc"
+dependencies = [
+ "base64",
+ "num-bigint-dig 0.8.2",
+ "oid",
+ "picky-asn1 0.6.0",
+ "picky-asn1-der",
+ "serde",
+ "zeroize",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "pkcs1"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a78f66c04ccc83dd4486fd46c33896f4e17b24a7a3a6400dedc48ed0ddd72320"
+dependencies = [
+ "der 0.5.1",
+ "pkcs8 0.8.0",
+ "zeroize",
+]
+
+[[package]]
+name = "pkcs8"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9c2f795bc591cb3384cb64082a578b89207ac92bb89c9d98c1ea2ace7cd8110"
+dependencies = [
+ "der 0.3.5",
+ "spki 0.3.0",
+]
+
+[[package]]
+name = "pkcs8"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0"
+dependencies = [
+ "der 0.5.1",
+ "spki 0.5.4",
+ "zeroize",
+]
+
+[[package]]
+name = "pkg-config"
+version = "0.3.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
+
+[[package]]
+name = "polling"
+version = "2.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6"
+dependencies = [
+ "autocfg 1.1.0",
+ "cfg-if 1.0.0",
+ "libc",
+ "log",
+ "wepoll-ffi",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "polyval"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
+dependencies = [
+ "cfg-if 1.0.0",
+ "cpufeatures",
+ "opaque-debug",
+ "universal-hash 0.4.1",
+]
+
+[[package]]
+name = "polyval"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6"
+dependencies = [
+ "cfg-if 1.0.0",
+ "cpufeatures",
+ "opaque-debug",
+ "universal-hash 0.5.0",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+[[package]]
+name = "precomputed-hash"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
+
+[[package]]
+name = "prettyplease"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c8992a85d8e93a28bdf76137db888d3874e3b230dee5ed8bebac4c9f7617773"
+dependencies = [
+ "proc-macro2",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro-crate"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9"
+dependencies = [
+ "once_cell",
+ "thiserror",
+ "toml",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.49"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "procfs"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0941606b9934e2d98a3677759a971756eb821f75764d0e0d26946d08e74d9104"
+dependencies = [
+ "bitflags",
+ "byteorder",
+ "chrono",
+ "flate2",
+ "hex",
+ "lazy_static",
+ "libc",
+]
+
+[[package]]
+name = "procfs"
+version = "0.14.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1de8dacb0873f77e6aefc6d71e044761fcc68060290f5b1089fcdf84626bb69"
+dependencies = [
+ "bitflags",
+ "byteorder",
+ "hex",
+ "lazy_static",
+ "rustix",
+]
+
+[[package]]
+name = "prometheus"
+version = "0.13.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c"
+dependencies = [
+ "cfg-if 1.0.0",
+ "fnv",
+ "lazy_static",
+ "libc",
+ "memchr",
+ "parking_lot 0.12.1",
+ "procfs 0.14.2",
+ "protobuf",
+ "thiserror",
+]
+
+[[package]]
+name = "prost"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de5e2533f59d08fcf364fd374ebda0692a70bd6d7e66ef97f306f45c6c5d8020"
+dependencies = [
+ "bytes 1.3.0",
+ "prost-derive 0.8.0",
+]
+
+[[package]]
+name = "prost"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c01db6702aa05baa3f57dec92b8eeeeb4cb19e894e73996b32a4093289e54592"
+dependencies = [
+ "bytes 1.3.0",
+ "prost-derive 0.11.5",
+]
+
+[[package]]
+name = "prost-build"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "355f634b43cdd80724ee7848f95770e7e70eefa6dcf14fea676216573b8fd603"
+dependencies = [
+ "bytes 1.3.0",
+ "heck 0.3.3",
+ "itertools",
+ "log",
+ "multimap",
+ "petgraph 0.5.1",
+ "prost 0.8.0",
+ "prost-types 0.8.0",
+ "tempfile",
+ "which",
+]
+
+[[package]]
+name = "prost-build"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb5320c680de74ba083512704acb90fe00f28f79207286a848e730c45dd73ed6"
+dependencies = [
+ "bytes 1.3.0",
+ "heck 0.4.0",
+ "itertools",
+ "lazy_static",
+ "log",
+ "multimap",
+ "petgraph 0.6.2",
+ "prettyplease",
+ "prost 0.11.5",
+ "prost-types 0.11.5",
+ "regex",
+ "syn",
+ "tempfile",
+ "which",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "600d2f334aa05acb02a755e217ef1ab6dea4d51b58b7846588b747edec04efba"
+dependencies = [
+ "anyhow",
+ "itertools",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8842bad1a5419bca14eac663ba798f6bc19c413c2fdceb5f3ba3b0932d96720"
+dependencies = [
+ "anyhow",
+ "itertools",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "603bbd6394701d13f3f25aada59c7de9d35a6a5887cfc156181234a44002771b"
+dependencies = [
+ "bytes 1.3.0",
+ "prost 0.8.0",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.11.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "017f79637768cde62820bc2d4fe0e45daaa027755c323ad077767c6c5f173091"
+dependencies = [
+ "bytes 1.3.0",
+ "prost 0.11.5",
+]
+
+[[package]]
+name = "protobuf"
+version = "2.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94"
+dependencies = [
+ "serde",
+ "serde_derive",
+]
+
+[[package]]
+name = "protobuf-codegen"
+version = "2.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "033460afb75cf755fcfc16dfaed20b86468082a2ea24e05ac35ab4a099a017d6"
+dependencies = [
+ "protobuf",
+]
+
+[[package]]
+name = "protobuf-codegen-pure"
+version = "2.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95a29399fc94bcd3eeaa951c715f7bea69409b2445356b00519740bcd6ddd865"
+dependencies = [
+ "protobuf",
+ "protobuf-codegen",
+]
+
+[[package]]
+name = "protobuf-codegen-pure3"
+version = "2.28.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0a3cf0a7de7570cb67bfb9a9a585b5841b49790a1be0ef104340a2110b91135"
+dependencies = [
+ "protobuf",
+ "protobuf-codegen",
+]
+
+[[package]]
+name = "protocols"
+version = "0.1.0"
+dependencies = [
+ "async-trait",
+ "oci",
+ "protobuf",
+ "ttrpc",
+ "ttrpc-codegen",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "radium"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb"
+
+[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+dependencies = [
+ "getrandom 0.1.16",
+ "libc",
+ "rand_chacha 0.2.2",
+ "rand_core 0.5.1",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha 0.3.1",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.5.1",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom 0.1.16",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom 0.2.8",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+dependencies = [
+ "rand_core 0.5.1",
+]
+
+[[package]]
+name = "rayon"
+version = "1.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
"num_cpus",
]
[[package]]
-name = "redox_syscall"
-version = "0.2.13"
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom 0.2.8",
+ "redox_syscall",
+ "thiserror",
+]
+
+[[package]]
+name = "regex"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+dependencies = [
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "reqwest"
+version = "0.11.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c"
+dependencies = [
+ "base64",
+ "bytes 1.3.0",
+ "encoding_rs",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-tls",
+ "ipnet",
+ "js-sys",
+ "log",
+ "mime",
+ "native-tls",
+ "once_cell",
+ "percent-encoding",
+ "pin-project-lite",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "tokio",
+ "tokio-native-tls",
+ "tokio-util 0.7.4",
+ "tower-service",
+ "url",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+ "winreg",
+]
+
+[[package]]
+name = "ring"
+version = "0.16.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
+dependencies = [
+ "cc",
+ "libc",
+ "once_cell",
+ "spin 0.5.2",
+ "untrusted",
+ "web-sys",
+ "winapi",
+]
+
+[[package]]
+name = "ripemd160"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2eca4ecc81b7f313189bf73ce724400a07da2a6dac19588b03c8bd76a2dcc251"
+dependencies = [
+ "block-buffer 0.9.0",
+ "digest 0.9.0",
+ "opaque-debug",
+]
+
+[[package]]
+name = "rlimit"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81a9ed03edbed449d6897c2092c71ab5f7b5fb80f6f0b1a3ed6d40a6f9fc0720"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "rsa"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3648b669b10afeab18972c105e284a7b953a669b0be3514c27f9b17acab2f9cd"
+dependencies = [
+ "byteorder",
+ "digest 0.9.0",
+ "lazy_static",
+ "num-bigint-dig 0.6.1",
+ "num-integer",
+ "num-iter",
+ "num-traits",
+ "pem 0.8.3",
+ "rand 0.7.3",
+ "sha2 0.9.9",
+ "simple_asn1",
+ "subtle",
+ "thiserror",
+ "zeroize",
+]
+
+[[package]]
+name = "rsa"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b"
+dependencies = [
+ "byteorder",
+ "digest 0.10.6",
+ "num-bigint-dig 0.8.2",
+ "num-integer",
+ "num-iter",
+ "num-traits",
+ "pkcs1",
+ "pkcs8 0.8.0",
+ "rand_core 0.6.4",
+ "smallvec",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "rtnetlink"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c9a6200d18ec1acfc218ce71363dcc9b6075f399220f903fdfeacd476a876ef"
+dependencies = [
+ "futures",
+ "log",
+ "netlink-packet-route",
+ "netlink-proto",
+ "nix 0.22.3",
+ "thiserror",
+ "tokio",
+]
+
+[[package]]
+name = "rusticata-macros"
+version = "4.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
+dependencies = [
+ "nom",
+]
+
+[[package]]
+name = "rustix"
+version = "0.36.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "rustjail"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "async-trait",
+ "bit-vec",
+ "capctl",
+ "caps",
+ "cfg-if 0.1.10",
+ "cgroups-rs",
+ "futures",
+ "inotify",
+ "kata-sys-util",
+ "lazy_static",
+ "libc",
+ "libseccomp",
+ "nix 0.24.3",
+ "oci",
+ "path-absolutize 1.2.1",
+ "protobuf",
+ "protocols",
+ "regex",
+ "rlimit",
+ "scan_fmt",
+ "scopeguard",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "serial_test",
+ "slog",
+ "slog-scope",
+ "tempfile",
+ "test-utils",
+ "tokio",
+ "xattr",
+ "zbus",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
+
+[[package]]
+name = "ryu"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "scan_fmt"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b53b0a5db882a8e2fdaae0a43f7b39e7e9082389e978398bdf223a55b581248"
+dependencies = [
+ "regex",
+]
+
+[[package]]
+name = "schannel"
+version = "0.1.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2"
+dependencies = [
+ "lazy_static",
+ "windows-sys 0.36.1",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "scratch"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
+
+[[package]]
+name = "security-framework"
+version = "2.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c"
+dependencies = [
+ "bitflags",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "sequoia-openpgp"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6aab653aad177cc40f34dbbc119127715f609d7e28481595506f1645bc67cd53"
+dependencies = [
+ "aes 0.6.0",
+ "anyhow",
+ "base64",
+ "block-modes",
+ "block-padding",
+ "blowfish",
+ "buffered-reader",
+ "bzip2",
+ "cast5",
+ "chrono",
+ "cipher 0.2.5",
+ "des",
+ "digest 0.9.0",
+ "dyn-clone",
+ "eax",
+ "ecdsa",
+ "ed25519-dalek",
+ "flate2",
+ "generic-array",
+ "getrandom 0.2.8",
+ "idea",
+ "idna",
+ "lalrpop",
+ "lalrpop-util",
+ "lazy_static",
+ "libc",
+ "md-5 0.9.1",
+ "memsec",
+ "num-bigint-dig 0.6.1",
+ "p256",
+ "rand 0.7.3",
+ "rand_core 0.6.4",
+ "regex",
+ "regex-syntax",
+ "ripemd160",
+ "rsa 0.3.0",
+ "sha-1 0.9.8",
+ "sha1collisiondetection",
+ "sha2 0.9.9",
+ "thiserror",
+ "twofish",
+ "typenum",
+ "x25519-dalek",
+ "xxhash-rust",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.152"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde-value"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
+dependencies = [
+ "ordered-float",
+ "serde",
+]
+
+[[package]]
+name = "serde_bytes"
+version = "0.11.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "718dc5fff5b36f99093fc49b280cfc96ce6fc824317783bff5a1fed0c7a64819"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.152"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.91"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
+dependencies = [
+ "indexmap",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_path_to_error"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26b04f22b563c91331a10074bda3dd5492e3cc39d56bd557e91c0af42b6c7341"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_plain"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6018081315db179d0ce57b1fe4b62a12a0028c9cf9bbef868c9cf477b3c34ae"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "serde_repr"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
+checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e"
dependencies = [
- "bitflags",
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
-name = "regex"
-version = "1.5.6"
+name = "serde_urlencoded"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
+ "form_urlencoded",
+ "itoa",
+ "ryu",
+ "serde",
]
[[package]]
-name = "regex-automata"
-version = "0.1.10"
+name = "serde_yaml"
+version = "0.8.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b"
dependencies = [
- "regex-syntax",
+ "indexmap",
+ "ryu",
+ "serde",
+ "yaml-rust",
]
[[package]]
-name = "regex-syntax"
-version = "0.6.26"
+name = "serial_test"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
+checksum = "e0bccbcf40c8938196944a3da0e133e031a33f4d6b72db3bda3cc556e361905d"
+dependencies = [
+ "lazy_static",
+ "parking_lot 0.11.2",
+ "serial_test_derive",
+]
[[package]]
-name = "remove_dir_all"
-version = "0.5.3"
+name = "serial_test_derive"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5"
dependencies = [
- "winapi",
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
-name = "rlimit"
-version = "0.5.4"
+name = "sha-1"
+version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81a9ed03edbed449d6897c2092c71ab5f7b5fb80f6f0b1a3ed6d40a6f9fc0720"
+checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6"
dependencies = [
- "libc",
+ "block-buffer 0.9.0",
+ "cfg-if 1.0.0",
+ "cpufeatures",
+ "digest 0.9.0",
+ "opaque-debug",
]
[[package]]
-name = "rtnetlink"
-version = "0.8.1"
+name = "sha-1"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c9a6200d18ec1acfc218ce71363dcc9b6075f399220f903fdfeacd476a876ef"
+checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c"
dependencies = [
- "futures",
- "log",
- "netlink-packet-route",
- "netlink-proto",
- "nix 0.22.3",
- "thiserror",
- "tokio",
+ "cfg-if 1.0.0",
+ "cpufeatures",
+ "digest 0.10.6",
]
[[package]]
-name = "rustjail"
-version = "0.1.0"
+name = "sha1"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770"
dependencies = [
- "anyhow",
- "async-trait",
- "capctl",
- "caps",
- "cfg-if 0.1.10",
- "cgroups-rs",
- "futures",
- "inotify",
- "lazy_static",
- "libc",
- "libseccomp",
- "nix 0.24.2",
- "oci",
- "path-absolutize",
- "protobuf",
- "protocols",
- "regex",
- "rlimit",
- "scan_fmt",
- "scopeguard",
- "serde",
- "serde_derive",
- "serde_json",
- "serial_test",
- "slog",
- "slog-scope",
- "tempfile",
- "test-utils",
- "tokio",
+ "sha1_smol",
]
[[package]]
-name = "ryu"
-version = "1.0.10"
+name = "sha1_smol"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
+checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
[[package]]
-name = "scan_fmt"
+name = "sha1collisiondetection"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b53b0a5db882a8e2fdaae0a43f7b39e7e9082389e978398bdf223a55b581248"
+checksum = "c66558a774ef5044cb4a834db5f5c7f95e139d2341d7f502fe6034afa7082461"
dependencies = [
- "regex",
+ "digest 0.9.0",
+ "generic-array",
]
[[package]]
-name = "scopeguard"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
-
-[[package]]
-name = "serde"
-version = "1.0.137"
+name = "sha2"
+version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
+checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
dependencies = [
- "serde_derive",
+ "block-buffer 0.9.0",
+ "cfg-if 1.0.0",
+ "cpufeatures",
+ "digest 0.9.0",
+ "opaque-debug",
]
[[package]]
-name = "serde_derive"
-version = "1.0.137"
+name = "sha2"
+version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
+checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "cfg-if 1.0.0",
+ "cpufeatures",
+ "digest 0.10.6",
]
[[package]]
-name = "serde_json"
-version = "1.0.81"
+name = "sha3"
+version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
+checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9"
dependencies = [
- "itoa",
- "ryu",
- "serde",
+ "digest 0.10.6",
+ "keccak",
]
[[package]]
-name = "serial_test"
-version = "0.5.1"
+name = "shadow-rs"
+version = "0.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0bccbcf40c8938196944a3da0e133e031a33f4d6b72db3bda3cc556e361905d"
+checksum = "8c0ea0c68418544f725eba5401a5b965a2263254c92458d04aeae74e9d88ff4e"
dependencies = [
- "lazy_static",
- "parking_lot 0.11.2",
- "serial_test_derive",
+ "const_format",
+ "git2",
+ "is_debug",
+ "time 0.3.17",
+ "tzdb",
]
[[package]]
-name = "serial_test_derive"
-version = "0.5.1"
+name = "shadow-rs"
+version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5"
+checksum = "f679e51942d1dbd5a7ebfb442d30855fa951152512176bb21f5f55ed0fd2f53b"
dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "const_format",
+ "git2",
+ "is_debug",
+ "time 0.3.17",
+ "tzdb",
]
[[package]]
@@ -1619,11 +4602,69 @@ dependencies = [
"libc",
]
+[[package]]
+name = "signature"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2807892cfa58e081aa1f1111391c7a0649d4fa127a4ffbe34bcbfb35a1171a4"
+dependencies = [
+ "digest 0.9.0",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "sigstore"
+version = "0.3.3"
+source = "git+https://github.com/sigstore/sigstore-rs?rev=6dd3281c25270f0d82550368abfb399ed3da7b41#6dd3281c25270f0d82550368abfb399ed3da7b41"
+dependencies = [
+ "async-trait",
+ "base64",
+ "cached",
+ "lazy_static",
+ "oci-distribution",
+ "olpc-cjson",
+ "open",
+ "openidconnect",
+ "pem 1.1.0",
+ "picky",
+ "regex",
+ "ring",
+ "serde",
+ "serde_json",
+ "sha2 0.10.6",
+ "thiserror",
+ "tokio",
+ "tough",
+ "tracing",
+ "url",
+ "x509-parser",
+]
+
+[[package]]
+name = "simple_asn1"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b"
+dependencies = [
+ "chrono",
+ "num-bigint 0.2.6",
+ "num-traits",
+]
+
+[[package]]
+name = "siphasher"
+version = "0.3.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
+
[[package]]
name = "slab"
-version = "0.4.6"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
+checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
+dependencies = [
+ "autocfg 1.1.0",
+]
[[package]]
name = "slash-formatter"
@@ -1658,7 +4699,7 @@ dependencies = [
"serde",
"serde_json",
"slog",
- "time 0.3.11",
+ "time 0.3.17",
]
[[package]]
@@ -1685,26 +4726,123 @@ dependencies = [
[[package]]
name = "smallvec"
-version = "1.8.0"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
+name = "snafu"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb0656e7e3ffb70f6c39b3c2a86332bb74aa3c679da781642590f3c1118c5045"
+dependencies = [
+ "doc-comment",
+ "snafu-derive",
+]
+
+[[package]]
+name = "snafu-derive"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "475b3bbe5245c26f2d8a6f62d67c1f30eb9fffeccee721c45d162c3ebbdf81b2"
+dependencies = [
+ "heck 0.4.0",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
[[package]]
name = "socket2"
-version = "0.4.4"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
+checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd"
dependencies = [
"libc",
"winapi",
]
+[[package]]
+name = "spin"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
+[[package]]
+name = "spin"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09"
+dependencies = [
+ "lock_api",
+]
+
+[[package]]
+name = "spki"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dae7e047abc519c96350e9484a96c6bf1492348af912fd3446dd2dc323f6268"
+dependencies = [
+ "der 0.3.5",
+]
+
+[[package]]
+name = "spki"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27"
+dependencies = [
+ "base64ct",
+ "der 0.5.1",
+]
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "string_cache"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08"
+dependencies = [
+ "new_debug_unreachable",
+ "once_cell",
+ "parking_lot 0.12.1",
+ "phf_shared",
+ "precomputed-hash",
+]
+
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+[[package]]
+name = "strum"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
+dependencies = [
+ "strum_macros",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.24.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
+dependencies = [
+ "heck 0.4.0",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+]
+
[[package]]
name = "subprocess"
version = "0.2.9"
@@ -1715,11 +4853,17 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "subtle"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+
[[package]]
name = "syn"
-version = "1.0.98"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
@@ -1727,18 +4871,21 @@ dependencies = [
]
[[package]]
-name = "sysinfo"
-version = "0.23.13"
+name = "sync_wrapper"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8"
+
+[[package]]
+name = "synstructure"
+version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3977ec2e0520829be45c8a2df70db2bf364714d8a748316a10c3c35d4d2b01c9"
+checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
- "cfg-if 1.0.0",
- "core-foundation-sys",
- "libc",
- "ntapi",
- "once_cell",
- "rayon",
- "winapi",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unicode-xid",
]
[[package]]
@@ -1747,6 +4894,23 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
+[[package]]
+name = "tap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+
+[[package]]
+name = "tar"
+version = "0.4.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6"
+dependencies = [
+ "filetime",
+ "libc",
+ "xattr",
+]
+
[[package]]
name = "tempfile"
version = "3.3.0"
@@ -1761,6 +4925,17 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "term"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
+dependencies = [
+ "dirs-next",
+ "rustversion",
+ "winapi",
+]
+
[[package]]
name = "termcolor"
version = "1.1.3"
@@ -1774,29 +4949,29 @@ dependencies = [
name = "test-utils"
version = "0.1.0"
dependencies = [
- "nix 0.24.2",
+ "nix 0.24.3",
]
[[package]]
name = "textwrap"
-version = "0.15.0"
+version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
+checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
[[package]]
name = "thiserror"
-version = "1.0.31"
+version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
+checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.31"
+version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
+checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [
"proc-macro2",
"quote",
@@ -1814,9 +4989,9 @@ dependencies = [
[[package]]
name = "time"
-version = "0.1.44"
+version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
+checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
dependencies = [
"libc",
"wasi 0.10.0+wasi-snapshot-preview1",
@@ -1825,51 +5000,113 @@ dependencies = [
[[package]]
name = "time"
-version = "0.3.11"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217"
+checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
dependencies = [
"itoa",
"libc",
"num_threads",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
+
+[[package]]
+name = "time-macros"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2"
+dependencies = [
+ "time-core",
+]
+
+[[package]]
+name = "tiny-keccak"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
+dependencies = [
+ "crunchy",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
]
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
+
[[package]]
name = "tokio"
-version = "1.19.2"
+version = "1.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439"
+checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
dependencies = [
- "bytes 1.1.0",
+ "autocfg 1.1.0",
+ "bytes 1.3.0",
"libc",
"memchr",
"mio",
"num_cpus",
- "once_cell",
"parking_lot 0.12.1",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
- "winapi",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "tokio-io-timeout"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
+dependencies = [
+ "pin-project-lite",
+ "tokio",
]
[[package]]
name = "tokio-macros"
-version = "1.8.0"
+version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
+checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
+[[package]]
+name = "tokio-native-tls"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
+dependencies = [
+ "native-tls",
+ "tokio",
+]
+
[[package]]
name = "tokio-stream"
-version = "0.1.9"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9"
+checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce"
dependencies = [
"futures-core",
"pin-project-lite",
@@ -1882,7 +5119,7 @@ version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
dependencies = [
- "bytes 1.1.0",
+ "bytes 1.3.0",
"futures-core",
"futures-sink",
"log",
@@ -1890,11 +5127,26 @@ dependencies = [
"tokio",
]
+[[package]]
+name = "tokio-util"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740"
+dependencies = [
+ "bytes 1.3.0",
+ "futures-core",
+ "futures-io",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+ "tracing",
+]
+
[[package]]
name = "tokio-vsock"
-version = "0.3.1"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e0723fc001950a3b018947b05eeb45014fd2b7c6e8f292502193ab74486bdb6"
+checksum = "3d2ad075b54bbb450ae2e3770211d7954362a488fcd386085c9fbb6d787ade8b"
dependencies = [
"bytes 0.4.12",
"futures",
@@ -1905,20 +5157,187 @@ dependencies = [
[[package]]
name = "toml"
-version = "0.5.9"
+version = "0.5.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "tonic"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "796c5e1cd49905e65dd8e700d4cb1dffcbfdb4fc9d017de08c1a537afd83627c"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "base64",
+ "bytes 1.3.0",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost 0.8.0",
+ "prost-derive 0.8.0",
+ "tokio",
+ "tokio-stream",
+ "tokio-util 0.6.10",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "tonic"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "axum",
+ "base64",
+ "bytes 1.3.0",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost 0.11.5",
+ "prost-derive 0.11.5",
+ "tokio",
+ "tokio-stream",
+ "tokio-util 0.7.4",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "tonic-build"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12b52d07035516c2b74337d2ac7746075e7dcae7643816c1b12c5ff8a7484c08"
+dependencies = [
+ "proc-macro2",
+ "prost-build 0.8.0",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tonic-build"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4"
+dependencies = [
+ "prettyplease",
+ "proc-macro2",
+ "prost-build 0.11.5",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tough"
+version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
+checksum = "dc636dd1ee889a366af6731f1b63b60baf19528b46df5a7c2d4b3bf8b60bca2d"
dependencies = [
+ "chrono",
+ "dyn-clone",
+ "globset",
+ "hex",
+ "log",
+ "olpc-cjson",
+ "path-absolutize 3.0.14",
+ "pem 1.1.0",
+ "percent-encoding",
+ "reqwest",
+ "ring",
"serde",
+ "serde_json",
+ "serde_plain",
+ "snafu",
+ "tempfile",
+ "untrusted",
+ "url",
+ "walkdir",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "indexmap",
+ "pin-project",
+ "pin-project-lite",
+ "rand 0.8.5",
+ "slab",
+ "tokio",
+ "tokio-util 0.7.4",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-http"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858"
+dependencies = [
+ "bitflags",
+ "bytes 1.3.0",
+ "futures-core",
+ "futures-util",
+ "http",
+ "http-body",
+ "http-range-header",
+ "pin-project-lite",
+ "tower",
+ "tower-layer",
+ "tower-service",
]
+[[package]]
+name = "tower-layer"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
+
+[[package]]
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
[[package]]
name = "tracing"
-version = "0.1.35"
+version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
+checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
dependencies = [
"cfg-if 1.0.0",
+ "log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
@@ -1926,9 +5345,9 @@ dependencies = [
[[package]]
name = "tracing-attributes"
-version = "0.1.21"
+version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c"
+checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
dependencies = [
"proc-macro2",
"quote",
@@ -1937,14 +5356,24 @@ dependencies = [
[[package]]
name = "tracing-core"
-version = "0.1.28"
+version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7"
+checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
dependencies = [
"once_cell",
"valuable",
]
+[[package]]
+name = "tracing-futures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
+dependencies = [
+ "pin-project",
+ "tracing",
+]
+
[[package]]
name = "tracing-log"
version = "0.1.3"
@@ -2002,62 +5431,206 @@ dependencies = [
]
[[package]]
-name = "ttrpc"
-version = "0.6.1"
+name = "try-lock"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
+
+[[package]]
+name = "ttrpc"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ecfff459a859c6ba6668ff72b34c2f1d94d9d58f7088414c2674ad0f31cc7d8"
+dependencies = [
+ "async-trait",
+ "byteorder",
+ "futures",
+ "libc",
+ "log",
+ "nix 0.23.2",
+ "protobuf",
+ "protobuf-codegen-pure",
+ "thiserror",
+ "tokio",
+ "tokio-vsock",
+]
+
+[[package]]
+name = "ttrpc-codegen"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df80affc2cf8c589172b05ba2b8e8a88722ebf4e28b86604615497a8b6fb78c0"
+dependencies = [
+ "protobuf",
+ "protobuf-codegen",
+ "protobuf-codegen-pure3",
+ "ttrpc-compiler",
+]
+
+[[package]]
+name = "ttrpc-compiler"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8db19ce6af25713061dd805d6733b6f0c45904bd63526ce5d2568c858b7edc71"
+dependencies = [
+ "derive-new",
+ "prost 0.8.0",
+ "prost-build 0.8.0",
+ "prost-types 0.8.0",
+ "protobuf",
+ "protobuf-codegen",
+ "tempfile",
+]
+
+[[package]]
+name = "twofish"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0028f5982f23ecc9a1bc3008ead4c664f843ed5d78acd3d213b99ff50c441bc2"
+dependencies = [
+ "byteorder",
+ "cipher 0.2.5",
+ "opaque-debug",
+]
+
+[[package]]
+name = "typenum"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+
+[[package]]
+name = "tz-rs"
+version = "0.6.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33851b15c848fad2cf4b105c6bb66eb9512b6f6c44a4b13f57c53c73c707e2b4"
+dependencies = [
+ "const_fn",
+]
+
+[[package]]
+name = "tzdb"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce4a3d7fb81f606dc80b01d8149cddb45950df6dd1b38bace8fb4ea767c5d65"
+dependencies = [
+ "iana-time-zone",
+ "tz-rs",
+ "utcnow",
+]
+
+[[package]]
+name = "uds_windows"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d"
+dependencies = [
+ "tempfile",
+ "winapi",
+]
+
+[[package]]
+name = "unicase"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
+dependencies = [
+ "version_check",
+]
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
+
+[[package]]
+name = "universal-hash"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ecfff459a859c6ba6668ff72b34c2f1d94d9d58f7088414c2674ad0f31cc7d8"
+checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
dependencies = [
- "async-trait",
- "byteorder",
- "futures",
- "libc",
- "log",
- "nix 0.23.1",
- "protobuf",
- "protobuf-codegen-pure",
- "thiserror",
- "tokio",
- "tokio-vsock",
+ "generic-array",
+ "subtle",
]
[[package]]
-name = "ttrpc-codegen"
-version = "0.2.0"
+name = "universal-hash"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809eda4e459820237104e4b61d6b41bbe6c9e1ce6adf4057955e6e6722a90408"
+checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5"
dependencies = [
- "protobuf",
- "protobuf-codegen",
- "protobuf-codegen-pure",
- "ttrpc-compiler",
+ "crypto-common",
+ "subtle",
]
[[package]]
-name = "ttrpc-compiler"
-version = "0.4.1"
+name = "untrusted"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2978ed3fa047d8fd55cbeb4d4a61d461fb3021a90c9618519c73ce7e5bb66c15"
-dependencies = [
- "derive-new",
- "prost",
- "prost-build",
- "prost-types",
- "protobuf",
- "protobuf-codegen",
- "tempfile",
-]
+checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
-name = "unicode-ident"
-version = "1.0.1"
+name = "url"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
+checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+ "serde",
+]
[[package]]
-name = "unicode-segmentation"
-version = "1.9.0"
+name = "utcnow"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
+checksum = "77ae4d1062f1d56fc96c80de4900b71d7036f0b51cc905a20093bef2438e0b0c"
+dependencies = [
+ "autocfg 1.1.0",
+ "const_fn",
+ "errno",
+ "js-sys",
+ "libc",
+ "rustix",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasm-bindgen",
+ "winapi",
+]
[[package]]
name = "valuable"
@@ -2065,6 +5638,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
[[package]]
name = "version_check"
version = "0.9.4"
@@ -2078,7 +5657,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e32675ee2b3ce5df274c0ab52d19b28789632406277ca26bffee79a8e27dc133"
dependencies = [
"libc",
- "nix 0.23.1",
+ "nix 0.23.2",
]
[[package]]
@@ -2089,7 +5668,7 @@ dependencies = [
"bincode",
"byteorder",
"libc",
- "nix 0.24.2",
+ "nix 0.24.3",
"opentelemetry",
"serde",
"slog",
@@ -2098,6 +5677,33 @@ dependencies = [
"tokio-vsock",
]
+[[package]]
+name = "waker-fn"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
+
+[[package]]
+name = "walkdir"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
+dependencies = [
+ "same-file",
+ "winapi",
+ "winapi-util",
+]
+
+[[package]]
+name = "want"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+dependencies = [
+ "log",
+ "try-lock",
+]
+
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
@@ -2118,9 +5724,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
-version = "0.2.81"
+version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994"
+checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
@@ -2128,24 +5734,36 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.81"
+version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a"
+checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
dependencies = [
"bumpalo",
- "lazy_static",
"log",
+ "once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
+[[package]]
+name = "wasm-bindgen-futures"
+version = "0.4.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
+dependencies = [
+ "cfg-if 1.0.0",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.81"
+version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa"
+checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -2153,9 +5771,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.81"
+version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048"
+checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [
"proc-macro2",
"quote",
@@ -2166,19 +5784,38 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.81"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
+
+[[package]]
+name = "web-sys"
+version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
+checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "wepoll-ffi"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb"
+dependencies = [
+ "cc",
+]
[[package]]
name = "which"
-version = "4.2.5"
+version = "4.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae"
+checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b"
dependencies = [
"either",
- "lazy_static",
"libc",
+ "once_cell",
]
[[package]]
@@ -2218,39 +5855,324 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_msvc",
+ "windows_aarch64_msvc 0.36.1",
+ "windows_i686_gnu 0.36.1",
+ "windows_i686_msvc 0.36.1",
+ "windows_x86_64_gnu 0.36.1",
+ "windows_x86_64_msvc 0.36.1",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc 0.42.0",
+ "windows_i686_gnu 0.42.0",
+ "windows_i686_msvc 0.42.0",
+ "windows_x86_64_gnu 0.42.0",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc 0.42.0",
]
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
+
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
+
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
+
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
+
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
+
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
+
+[[package]]
+name = "winreg"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "wyz"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
+
+[[package]]
+name = "x25519-dalek"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f"
+dependencies = [
+ "curve25519-dalek",
+ "rand_core 0.5.1",
+ "zeroize",
+]
+
+[[package]]
+name = "x509-parser"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8"
+dependencies = [
+ "asn1-rs",
+ "base64",
+ "data-encoding",
+ "der-parser",
+ "lazy_static",
+ "nom",
+ "oid-registry",
+ "ring",
+ "rusticata-macros",
+ "thiserror",
+ "time 0.3.17",
+]
+
+[[package]]
+name = "xattr"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "xxhash-rust"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "735a71d46c4d68d71d4b24d03fdc2b98e38cea81730595801db779c04fe80d70"
+
+[[package]]
+name = "yaml-rust"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
+dependencies = [
+ "linked-hash-map",
+]
+
+[[package]]
+name = "zbus"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d8f1a037b2c4a67d9654dc7bdfa8ff2e80555bbefdd3c1833c1d1b27c963a6b"
+dependencies = [
+ "async-broadcast",
+ "async-channel",
+ "async-executor",
+ "async-io",
+ "async-lock",
+ "async-recursion",
+ "async-task",
+ "async-trait",
+ "byteorder",
+ "derivative",
+ "dirs",
+ "enumflags2",
+ "event-listener",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "hex",
+ "lazy_static",
+ "nix 0.23.2",
+ "once_cell",
+ "ordered-stream",
+ "rand 0.8.5",
+ "serde",
+ "serde_repr",
+ "sha1",
+ "static_assertions",
+ "tracing",
+ "uds_windows",
+ "winapi",
+ "zbus_macros",
+ "zbus_names",
+ "zvariant",
+]
+
+[[package]]
+name = "zbus_macros"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f8fb5186d1c87ae88cf234974c240671238b4a679158ad3b94ec465237349a6"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "syn",
+]
+
+[[package]]
+name = "zbus_names"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c737644108627748a660d038974160e0cbb62605536091bdfa28fd7f64d43c8"
+dependencies = [
+ "serde",
+ "static_assertions",
+ "zvariant",
+]
+
+[[package]]
+name = "zeroize"
+version = "1.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
+dependencies = [
+ "zeroize_derive",
+]
+
+[[package]]
+name = "zeroize_derive"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zstd"
+version = "0.11.2+zstd.1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4"
+dependencies = [
+ "zstd-safe 5.0.2+zstd.1.5.2",
+]
+
+[[package]]
+name = "zstd"
+version = "0.12.1+zstd.1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c947d2adc84ff9a59f2e3c03b81aa4128acf28d6ad7d56273f7e8af14e47bea"
+dependencies = [
+ "zstd-safe 6.0.2+zstd.1.5.2",
+]
+
+[[package]]
+name = "zstd-safe"
+version = "5.0.2+zstd.1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db"
+dependencies = [
+ "libc",
+ "zstd-sys",
+]
+
+[[package]]
+name = "zstd-safe"
+version = "6.0.2+zstd.1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6cf39f730b440bab43da8fb5faf5f254574462f73f260f85f7987f32154ff17"
+dependencies = [
+ "libc",
+ "zstd-sys",
+]
+
+[[package]]
+name = "zstd-sys"
+version = "2.0.4+zstd.1.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fa202f2ef00074143e219d15b62ffc317d17cc33909feac471c044087cad7b0"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "zvariant"
+version = "3.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56f8c89c183461e11867ded456db252eae90874bc6769b7adbea464caa777e51"
+dependencies = [
+ "byteorder",
+ "enumflags2",
+ "libc",
+ "serde",
+ "static_assertions",
+ "zvariant_derive",
+]
+
+[[package]]
+name = "zvariant_derive"
+version = "3.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "155247a5d1ab55e335421c104ccd95d64f17cebbd02f50cdbc1c33385f9c4d81"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/src/agent/Cargo.toml b/src/agent/Cargo.toml
index b0e2ec8cc..fc7bed62a 100644
--- a/src/agent/Cargo.toml
+++ b/src/agent/Cargo.toml
@@ -23,7 +23,7 @@ regex = "1.5.6"
serial_test = "0.5.1"
kata-sys-util = { path = "../libs/kata-sys-util" }
kata-types = { path = "../libs/kata-types" }
-sysinfo = "0.23.0"
+url = "2.2.2"
# Async helpers
async-trait = "0.1.42"
@@ -31,7 +31,7 @@ async-recursion = "0.3.2"
futures = "0.3.17"
# Async runtime
-tokio = { version = "1.14.0", features = ["full"] }
+tokio = { version = "1.21.2", features = ["full"] }
tokio-vsock = "0.3.1"
netlink-sys = { version = "0.7.0", features = ["tokio_socket",]}
@@ -66,11 +66,23 @@ serde = { version = "1.0.129", features = ["derive"] }
toml = "0.5.8"
clap = { version = "3.0.1", features = ["derive"] }
+# "vendored" feature for openssl is required by musl build
+openssl = { version = "0.10.38", features = ["vendored"] }
+
+# Image pull/decrypt
+[target.'cfg(target_arch = "s390x")'.dependencies]
+image-rs = { git = "https://github.com/confidential-containers/image-rs", rev = "v0.3.0", default-features = false, features = ["default_s390x"] }
+
+[target.'cfg(not(target_arch = "s390x"))'.dependencies]
+image-rs = { git = "https://github.com/confidential-containers/image-rs", rev = "v0.3.0", default-features = true }
+
[dev-dependencies]
tempfile = "3.1.0"
test-utils = { path = "../libs/test-utils" }
+which = "4.3.0"
[workspace]
+resolver = "2"
members = [
"rustjail",
]
diff --git a/src/agent/Makefile b/src/agent/Makefile
index f0e86fd6b..51da58d3a 100644
--- a/src/agent/Makefile
+++ b/src/agent/Makefile
@@ -107,6 +107,8 @@ endef
##TARGET default: build code
default: $(TARGET) show-header
+static-checks-build: $(GENERATED_CODE)
+
$(TARGET): $(GENERATED_CODE) $(TARGET_PATH)
$(TARGET_PATH): show-summary
diff --git a/src/agent/rustjail/Cargo.toml b/src/agent/rustjail/Cargo.toml
index 324f540e1..25511157d 100644
--- a/src/agent/rustjail/Cargo.toml
+++ b/src/agent/rustjail/Cargo.toml
@@ -11,6 +11,7 @@ serde_json = "1.0.39"
serde_derive = "1.0.91"
oci = { path = "../../libs/oci" }
protocols = { path ="../../libs/protocols" }
+kata-sys-util = { path = "../../libs/kata-sys-util" }
caps = "0.5.0"
nix = "0.24.2"
scopeguard = "1.0.0"
@@ -32,7 +33,10 @@ tokio = { version = "1.2.0", features = ["sync", "io-util", "process", "time", "
futures = "0.3.17"
async-trait = "0.1.31"
inotify = "0.9.2"
-libseccomp = { version = "0.2.3", optional = true }
+libseccomp = { version = "0.3.0", optional = true }
+zbus = "2.3.0"
+bit-vec= "0.6.3"
+xattr = "0.2.3"
[dev-dependencies]
serial_test = "0.5.0"
diff --git a/src/agent/rustjail/src/cgroups/fs/mod.rs b/src/agent/rustjail/src/cgroups/fs/mod.rs
index b24d6b327..80a9649be 100644
--- a/src/agent/rustjail/src/cgroups/fs/mod.rs
+++ b/src/agent/rustjail/src/cgroups/fs/mod.rs
@@ -32,6 +32,7 @@ use protocols::agent::{
BlkioStats, BlkioStatsEntry, CgroupStats, CpuStats, CpuUsage, HugetlbStats, MemoryData,
MemoryStats, PidsStats, ThrottlingData,
};
+use std::any::Any;
use std::collections::HashMap;
use std::fs;
use std::path::Path;
@@ -193,6 +194,79 @@ impl CgroupManager for Manager {
Ok(result)
}
+
+ fn update_cpuset_path(&self, guest_cpuset: &str, container_cpuset: &str) -> Result<()> {
+ if guest_cpuset.is_empty() {
+ return Ok(());
+ }
+ info!(sl!(), "update_cpuset_path to: {}", guest_cpuset);
+
+ let h = cgroups::hierarchies::auto();
+ let root_cg = h.root_control_group();
+
+ let root_cpuset_controller: &CpuSetController = root_cg.controller_of().unwrap();
+ let path = root_cpuset_controller.path();
+ let root_path = Path::new(path);
+ info!(sl!(), "root cpuset path: {:?}", &path);
+
+ let container_cpuset_controller: &CpuSetController = self.cgroup.controller_of().unwrap();
+ let path = container_cpuset_controller.path();
+ let container_path = Path::new(path);
+ info!(sl!(), "container cpuset path: {:?}", &path);
+
+ let mut paths = vec![];
+ for ancestor in container_path.ancestors() {
+ if ancestor == root_path {
+ break;
+ }
+ paths.push(ancestor);
+ }
+ info!(sl!(), "parent paths to update cpuset: {:?}", &paths);
+
+ let mut i = paths.len();
+ loop {
+ if i == 0 {
+ break;
+ }
+ i -= 1;
+
+ // remove cgroup root from path
+ let r_path = &paths[i]
+ .to_str()
+ .unwrap()
+ .trim_start_matches(root_path.to_str().unwrap());
+ info!(sl!(), "updating cpuset for parent path {:?}", &r_path);
+ let cg = new_cgroup(cgroups::hierarchies::auto(), r_path);
+ let cpuset_controller: &CpuSetController = cg.controller_of().unwrap();
+ cpuset_controller.set_cpus(guest_cpuset)?;
+ }
+
+ if !container_cpuset.is_empty() {
+ info!(
+ sl!(),
+ "updating cpuset for container path: {:?} cpuset: {}",
+ &container_path,
+ container_cpuset
+ );
+ container_cpuset_controller.set_cpus(container_cpuset)?;
+ }
+
+ Ok(())
+ }
+
+ fn get_cgroup_path(&self, cg: &str) -> Result<String> {
+ if cgroups::hierarchies::is_cgroup2_unified_mode() {
+ let cg_path = format!("/sys/fs/cgroup/{}", self.cpath);
+ return Ok(cg_path);
+ }
+
+ // for cgroup v1
+ Ok(self.paths.get(cg).map(|s| s.to_string()).unwrap())
+ }
+
+ fn as_any(&self) -> Result<&dyn Any> {
+ Ok(self)
+ }
}
fn set_network_resources(
@@ -252,19 +326,28 @@ fn set_devices_resources(
}
fn set_hugepages_resources(
- _cg: &cgroups::Cgroup,
+ cg: &cgroups::Cgroup,
hugepage_limits: &[LinuxHugepageLimit],
res: &mut cgroups::Resources,
) {
info!(sl!(), "cgroup manager set hugepage");
let mut limits = vec![];
+ let hugetlb_controller = cg.controller_of::<HugeTlbController>();
for l in hugepage_limits.iter() {
- let hr = HugePageResource {
- size: l.page_size.clone(),
- limit: l.limit,
- };
- limits.push(hr);
+ if hugetlb_controller.is_some() && hugetlb_controller.unwrap().size_supported(&l.page_size)
+ {
+ let hr = HugePageResource {
+ size: l.page_size.clone(),
+ limit: l.limit,
+ };
+ limits.push(hr);
+ } else {
+ warn!(
+ sl!(),
+ "{} page size support cannot be verified, dropping requested limit", l.page_size
+ );
+ }
}
res.hugepages.limits = limits;
}
@@ -458,8 +541,11 @@ fn linux_device_to_cgroup_device(d: &LinuxDevice) -> Option<DeviceResource> {
}
fn linux_device_group_to_cgroup_device(d: &LinuxDeviceCgroup) -> Option<DeviceResource> {
- let dev_type = match DeviceType::from_char(d.r#type.chars().next()) {
- Some(t) => t,
+ let dev_type = match &d.r#type {
+ Some(t_s) => match DeviceType::from_char(t_s.chars().next()) {
+ Some(t_c) => t_c,
+ None => return None,
+ },
None => return None,
};
@@ -516,7 +602,7 @@ lazy_static! {
// all mknod to all char devices
LinuxDeviceCgroup {
allow: true,
- r#type: "c".to_string(),
+ r#type: Some("c".to_string()),
major: Some(WILDCARD),
minor: Some(WILDCARD),
access: "m".to_string(),
@@ -525,7 +611,7 @@ lazy_static! {
// all mknod to all block devices
LinuxDeviceCgroup {
allow: true,
- r#type: "b".to_string(),
+ r#type: Some("b".to_string()),
major: Some(WILDCARD),
minor: Some(WILDCARD),
access: "m".to_string(),
@@ -534,7 +620,7 @@ lazy_static! {
// all read/write/mknod to char device /dev/console
LinuxDeviceCgroup {
allow: true,
- r#type: "c".to_string(),
+ r#type: Some("c".to_string()),
major: Some(5),
minor: Some(1),
access: "rwm".to_string(),
@@ -543,7 +629,7 @@ lazy_static! {
// all read/write/mknod to char device /dev/pts/<N>
LinuxDeviceCgroup {
allow: true,
- r#type: "c".to_string(),
+ r#type: Some("c".to_string()),
major: Some(136),
minor: Some(WILDCARD),
access: "rwm".to_string(),
@@ -552,7 +638,7 @@ lazy_static! {
// all read/write/mknod to char device /dev/ptmx
LinuxDeviceCgroup {
allow: true,
- r#type: "c".to_string(),
+ r#type: Some("c".to_string()),
major: Some(5),
minor: Some(2),
access: "rwm".to_string(),
@@ -561,7 +647,7 @@ lazy_static! {
// all read/write/mknod to char device /dev/net/tun
LinuxDeviceCgroup {
allow: true,
- r#type: "c".to_string(),
+ r#type: Some("c".to_string()),
major: Some(10),
minor: Some(200),
access: "rwm".to_string(),
@@ -972,75 +1058,6 @@ impl Manager {
cgroup: new_cgroup(cgroups::hierarchies::auto(), cpath),
})
}
-
- pub fn update_cpuset_path(&self, guest_cpuset: &str, container_cpuset: &str) -> Result<()> {
- if guest_cpuset.is_empty() {
- return Ok(());
- }
- info!(sl!(), "update_cpuset_path to: {}", guest_cpuset);
-
- let h = cgroups::hierarchies::auto();
- let root_cg = h.root_control_group();
-
- let root_cpuset_controller: &CpuSetController = root_cg.controller_of().unwrap();
- let path = root_cpuset_controller.path();
- let root_path = Path::new(path);
- info!(sl!(), "root cpuset path: {:?}", &path);
-
- let container_cpuset_controller: &CpuSetController = self.cgroup.controller_of().unwrap();
- let path = container_cpuset_controller.path();
- let container_path = Path::new(path);
- info!(sl!(), "container cpuset path: {:?}", &path);
-
- let mut paths = vec![];
- for ancestor in container_path.ancestors() {
- if ancestor == root_path {
- break;
- }
- paths.push(ancestor);
- }
- info!(sl!(), "parent paths to update cpuset: {:?}", &paths);
-
- let mut i = paths.len();
- loop {
- if i == 0 {
- break;
- }
- i -= 1;
-
- // remove cgroup root from path
- let r_path = &paths[i]
- .to_str()
- .unwrap()
- .trim_start_matches(root_path.to_str().unwrap());
- info!(sl!(), "updating cpuset for parent path {:?}", &r_path);
- let cg = new_cgroup(cgroups::hierarchies::auto(), r_path);
- let cpuset_controller: &CpuSetController = cg.controller_of().unwrap();
- cpuset_controller.set_cpus(guest_cpuset)?;
- }
-
- if !container_cpuset.is_empty() {
- info!(
- sl!(),
- "updating cpuset for container path: {:?} cpuset: {}",
- &container_path,
- container_cpuset
- );
- container_cpuset_controller.set_cpus(container_cpuset)?;
- }
-
- Ok(())
- }
-
- pub fn get_cg_path(&self, cg: &str) -> Option<String> {
- if cgroups::hierarchies::is_cgroup2_unified_mode() {
- let cg_path = format!("/sys/fs/cgroup/{}", self.cpath);
- return Some(cg_path);
- }
-
- // for cgroup v1
- self.paths.get(cg).map(|s| s.to_string())
- }
}
// get the guest's online cpus.
diff --git a/src/agent/rustjail/src/cgroups/mock.rs b/src/agent/rustjail/src/cgroups/mock.rs
index e1603c846..fbad6d664 100644
--- a/src/agent/rustjail/src/cgroups/mock.rs
+++ b/src/agent/rustjail/src/cgroups/mock.rs
@@ -11,6 +11,7 @@ use anyhow::Result;
use cgroups::freezer::FreezerState;
use libc::{self, pid_t};
use oci::LinuxResources;
+use std::any::Any;
use std::collections::HashMap;
use std::string::String;
@@ -53,6 +54,18 @@ impl CgroupManager for Manager {
fn get_pids(&self) -> Result<Vec<pid_t>> {
Ok(Vec::new())
}
+
+ fn update_cpuset_path(&self, _: &str, _: &str) -> Result<()> {
+ Ok(())
+ }
+
+ fn get_cgroup_path(&self, _: &str) -> Result<String> {
+ Ok("".to_string())
+ }
+
+ fn as_any(&self) -> Result<&dyn Any> {
+ Ok(self)
+ }
}
impl Manager {
@@ -63,12 +76,4 @@ impl Manager {
cpath: cpath.to_string(),
})
}
-
- pub fn update_cpuset_path(&self, _: &str, _: &str) -> Result<()> {
- Ok(())
- }
-
- pub fn get_cg_path(&self, _: &str) -> Option<String> {
- Some("".to_string())
- }
}
diff --git a/src/agent/rustjail/src/cgroups/mod.rs b/src/agent/rustjail/src/cgroups/mod.rs
index 389ff79fa..24275c314 100644
--- a/src/agent/rustjail/src/cgroups/mod.rs
+++ b/src/agent/rustjail/src/cgroups/mod.rs
@@ -4,8 +4,10 @@
//
use anyhow::{anyhow, Result};
+use core::fmt::Debug;
use oci::LinuxResources;
use protocols::agent::CgroupStats;
+use std::any::Any;
use cgroups::freezer::FreezerState;
@@ -38,4 +40,22 @@ pub trait Manager {
fn set(&self, _container: &LinuxResources, _update: bool) -> Result<()> {
Err(anyhow!("not supported!"))
}
+
+ fn update_cpuset_path(&self, _: &str, _: &str) -> Result<()> {
+ Err(anyhow!("not supported!"))
+ }
+
+ fn get_cgroup_path(&self, _: &str) -> Result<String> {
+ Err(anyhow!("not supported!"))
+ }
+
+ fn as_any(&self) -> Result<&dyn Any> {
+ Err(anyhow!("not supported!"))
+ }
+}
+
+impl Debug for dyn Manager + Send + Sync {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ write!(f, "CgroupManager")
+ }
}
diff --git a/src/agent/rustjail/src/cgroups/systemd.rs b/src/agent/rustjail/src/cgroups/systemd.rs
deleted file mode 100644
index 669f6d5bb..000000000
--- a/src/agent/rustjail/src/cgroups/systemd.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2019 Ant Financial
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-
-use crate::cgroups::Manager as CgroupManager;
-
-pub struct Manager {}
-
-impl CgroupManager for Manager {}
diff --git a/src/agent/rustjail/src/cgroups/systemd/cgroups_path.rs b/src/agent/rustjail/src/cgroups/systemd/cgroups_path.rs
new file mode 100644
index 000000000..696c0ece0
--- /dev/null
+++ b/src/agent/rustjail/src/cgroups/systemd/cgroups_path.rs
@@ -0,0 +1,95 @@
+// Copyright 2021-2022 Kata Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+use anyhow::{anyhow, Result};
+
+use super::common::{DEFAULT_SLICE, SCOPE_SUFFIX, SLICE_SUFFIX};
+use std::string::String;
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct CgroupsPath {
+ pub slice: String,
+ pub prefix: String,
+ pub name: String,
+}
+
+impl CgroupsPath {
+ pub fn new(cgroups_path_str: &str) -> Result<Self> {
+ let path_vec: Vec<&str> = cgroups_path_str.split(':').collect();
+ if path_vec.len() != 3 {
+ return Err(anyhow!("invalid cpath: {:?}", cgroups_path_str));
+ }
+
+ Ok(CgroupsPath {
+ slice: if path_vec[0].is_empty() {
+ DEFAULT_SLICE.to_string()
+ } else {
+ path_vec[0].to_owned()
+ },
+ prefix: path_vec[1].to_owned(),
+ name: path_vec[2].to_owned(),
+ })
+ }
+
+ // ref: https://github.com/opencontainers/runc/blob/main/docs/systemd.md
+ // return: (parent_slice, unit_name)
+ pub fn parse(&self) -> Result<(String, String)> {
+ Ok((
+ parse_parent(self.slice.to_owned())?,
+ get_unit_name(self.prefix.to_owned(), self.name.to_owned()),
+ ))
+ }
+}
+
+fn parse_parent(slice: String) -> Result<String> {
+ if !slice.ends_with(SLICE_SUFFIX) || slice.contains('/') {
+ return Err(anyhow!("invalid slice name: {}", slice));
+ } else if slice == "-.slice" {
+ return Ok(String::new());
+ }
+
+ let mut slice_path = String::new();
+ let mut prefix = String::new();
+ for subslice in slice.trim_end_matches(SLICE_SUFFIX).split('-') {
+ if subslice.is_empty() {
+ return Err(anyhow!("invalid slice name: {}", slice));
+ }
+ slice_path = format!("{}/{}{}{}", slice_path, prefix, subslice, SLICE_SUFFIX);
+ prefix = format!("{}{}-", prefix, subslice);
+ }
+ slice_path.remove(0);
+ Ok(slice_path)
+}
+
+fn get_unit_name(prefix: String, name: String) -> String {
+ if name.ends_with(SLICE_SUFFIX) {
+ name
+ } else if prefix.is_empty() {
+ format!("{}{}", name, SCOPE_SUFFIX)
+ } else {
+ format!("{}-{}{}", prefix, name, SCOPE_SUFFIX)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::CgroupsPath;
+
+ #[test]
+ fn test_cgroup_path_parse() {
+ let slice = "system.slice";
+ let prefix = "kata_agent";
+ let name = "123";
+ let cgroups_path =
+ CgroupsPath::new(format!("{}:{}:{}", slice, prefix, name).as_str()).unwrap();
+ assert_eq!(slice, cgroups_path.slice.as_str());
+ assert_eq!(prefix, cgroups_path.prefix.as_str());
+ assert_eq!(name, cgroups_path.name.as_str());
+
+ let (parent_slice, unit_name) = cgroups_path.parse().unwrap();
+ assert_eq!(format!("{}", slice), parent_slice);
+ assert_eq!(format!("{}-{}.scope", prefix, name), unit_name);
+ }
+}
diff --git a/src/agent/rustjail/src/cgroups/systemd/common.rs b/src/agent/rustjail/src/cgroups/systemd/common.rs
new file mode 100644
index 000000000..a39e41c7c
--- /dev/null
+++ b/src/agent/rustjail/src/cgroups/systemd/common.rs
@@ -0,0 +1,17 @@
+// Copyright 2021-2022 Kata Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+pub const DEFAULT_SLICE: &str = "system.slice";
+pub const SLICE_SUFFIX: &str = ".slice";
+pub const SCOPE_SUFFIX: &str = ".scope";
+pub const UNIT_MODE: &str = "replace";
+
+pub type Properties<'a> = Vec<(&'a str, zbus::zvariant::Value<'a>)>;
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub enum CgroupHierarchy {
+ Legacy,
+ Unified,
+}
diff --git a/src/agent/rustjail/src/cgroups/systemd/dbus_client.rs b/src/agent/rustjail/src/cgroups/systemd/dbus_client.rs
new file mode 100644
index 000000000..09c46f24d
--- /dev/null
+++ b/src/agent/rustjail/src/cgroups/systemd/dbus_client.rs
@@ -0,0 +1,126 @@
+// Copyright 2021-2022 Kata Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+use std::vec;
+
+use super::common::CgroupHierarchy;
+use super::common::{Properties, SLICE_SUFFIX, UNIT_MODE};
+use super::interface::system::ManagerProxyBlocking as SystemManager;
+use anyhow::{Context, Result};
+use zbus::zvariant::Value;
+
+pub trait SystemdInterface {
+ fn start_unit(
+ &self,
+ pid: i32,
+ parent: &str,
+ unit_name: &str,
+ cg_hierarchy: &CgroupHierarchy,
+ ) -> Result<()>;
+
+ fn set_properties(&self, unit_name: &str, properties: &Properties) -> Result<()>;
+
+ fn stop_unit(&self, unit_name: &str) -> Result<()>;
+
+ fn get_version(&self) -> Result<String>;
+
+ fn unit_exist(&self, unit_name: &str) -> Result<bool>;
+
+ fn add_process(&self, pid: i32, unit_name: &str) -> Result<()>;
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct DBusClient {}
+
+impl DBusClient {
+ fn build_proxy(&self) -> Result<SystemManager<'static>> {
+ let connection = zbus::blocking::Connection::system()?;
+ let proxy = SystemManager::new(&connection)?;
+ Ok(proxy)
+ }
+}
+
+impl SystemdInterface for DBusClient {
+ fn start_unit(
+ &self,
+ pid: i32,
+ parent: &str,
+ unit_name: &str,
+ cg_hierarchy: &CgroupHierarchy,
+ ) -> Result<()> {
+ let proxy = self.build_proxy()?;
+
+ // enable CPUAccounting & MemoryAccounting & (Block)IOAccounting by default
+ let mut properties: Properties = vec![
+ ("CPUAccounting", Value::Bool(true)),
+ ("DefaultDependencies", Value::Bool(false)),
+ ("MemoryAccounting", Value::Bool(true)),
+ ("TasksAccounting", Value::Bool(true)),
+ ("Description", Value::Str("kata-agent container".into())),
+ ("PIDs", Value::Array(vec![pid as u32].into())),
+ ];
+
+ match *cg_hierarchy {
+ CgroupHierarchy::Legacy => properties.push(("IOAccounting", Value::Bool(true))),
+ CgroupHierarchy::Unified => properties.push(("BlockIOAccounting", Value::Bool(true))),
+ }
+
+ if unit_name.ends_with(SLICE_SUFFIX) {
+ properties.push(("Wants", Value::Str(parent.into())));
+ } else {
+ properties.push(("Slice", Value::Str(parent.into())));
+ properties.push(("Delegate", Value::Bool(true)));
+ }
+
+ proxy
+ .start_transient_unit(unit_name, UNIT_MODE, &properties, &[])
+ .with_context(|| format!("failed to start transient unit {}", unit_name))?;
+ Ok(())
+ }
+
+ fn set_properties(&self, unit_name: &str, properties: &Properties) -> Result<()> {
+ let proxy = self.build_proxy()?;
+
+ proxy
+ .set_unit_properties(unit_name, true, properties)
+ .with_context(|| format!("failed to set unit properties {}", unit_name))?;
+
+ Ok(())
+ }
+
+ fn stop_unit(&self, unit_name: &str) -> Result<()> {
+ let proxy = self.build_proxy()?;
+
+ proxy
+ .stop_unit(unit_name, UNIT_MODE)
+ .with_context(|| format!("failed to stop unit {}", unit_name))?;
+ Ok(())
+ }
+
+ fn get_version(&self) -> Result<String> {
+ let proxy = self.build_proxy()?;
+
+ let systemd_version = proxy
+ .version()
+ .with_context(|| "failed to get systemd version".to_string())?;
+ Ok(systemd_version)
+ }
+
+ fn unit_exist(&self, unit_name: &str) -> Result<bool> {
+ let proxy = self.build_proxy()?;
+
+ Ok(proxy.get_unit(unit_name).is_ok())
+ }
+
+ fn add_process(&self, pid: i32, unit_name: &str) -> Result<()> {
+ let proxy = self.build_proxy()?;
+
+ proxy
+ .attach_processes_to_unit(unit_name, "/", &[pid as u32])
+ .with_context(|| format!("failed to add process {}", unit_name))?;
+
+ Ok(())
+ }
+}
diff --git a/src/agent/rustjail/src/cgroups/systemd/interface/mod.rs b/src/agent/rustjail/src/cgroups/systemd/interface/mod.rs
new file mode 100644
index 000000000..d0ac62111
--- /dev/null
+++ b/src/agent/rustjail/src/cgroups/systemd/interface/mod.rs
@@ -0,0 +1,7 @@
+// Copyright 2021-2022 Kata Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+pub(crate) mod session;
+pub(crate) mod system;
diff --git a/src/agent/rustjail/src/cgroups/systemd/interface/session.rs b/src/agent/rustjail/src/cgroups/systemd/interface/session.rs
new file mode 100644
index 000000000..648303ad3
--- /dev/null
+++ b/src/agent/rustjail/src/cgroups/systemd/interface/session.rs
@@ -0,0 +1,1004 @@
+// Copyright 2021-2022 Kata Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#![allow(unknown_lints)]
+#![allow(clippy::all)]
+
+//! # DBus interface proxy for: `org.freedesktop.systemd1.Manager`
+//!
+//! This code was generated by `zbus-xmlgen` `2.0.1` from DBus introspection data.
+//! Source: `Interface '/org/freedesktop/systemd1' from service 'org.freedesktop.systemd1' on session bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the
+//! [Writing a client proxy](https://dbus.pages.freedesktop.org/zbus/client.html)
+//! section of the zbus documentation.
+//!
+//! This DBus object implements
+//! [standard DBus interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html),
+//! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used:
+//!
+//! * [`zbus::fdo::PeerProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//!
+//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
+
+use zbus::dbus_proxy;
+
+#[dbus_proxy(
+ interface = "org.freedesktop.systemd1.Manager",
+ default_service = "org.freedesktop.systemd1",
+ default_path = "/org/freedesktop/systemd1"
+)]
+trait Manager {
+ /// AbandonScope method
+ fn abandon_scope(&self, name: &str) -> zbus::Result<()>;
+
+ /// AddDependencyUnitFiles method
+ fn add_dependency_unit_files(
+ &self,
+ files: &[&str],
+ target: &str,
+ type_: &str,
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// AttachProcessesToUnit method
+ fn attach_processes_to_unit(
+ &self,
+ unit_name: &str,
+ subcgroup: &str,
+ pids: &[u32],
+ ) -> zbus::Result<()>;
+
+ /// BindMountUnit method
+ fn bind_mount_unit(
+ &self,
+ name: &str,
+ source: &str,
+ destination: &str,
+ read_only: bool,
+ mkdir: bool,
+ ) -> zbus::Result<()>;
+
+ /// CancelJob method
+ fn cancel_job(&self, id: u32) -> zbus::Result<()>;
+
+ /// CleanUnit method
+ fn clean_unit(&self, name: &str, mask: &[&str]) -> zbus::Result<()>;
+
+ /// ClearJobs method
+ fn clear_jobs(&self) -> zbus::Result<()>;
+
+ /// DisableUnitFiles method
+ fn disable_unit_files(
+ &self,
+ files: &[&str],
+ runtime: bool,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// DisableUnitFilesWithFlags method
+ fn disable_unit_files_with_flags(
+ &self,
+ files: &[&str],
+ flags: u64,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// Dump method
+ fn dump(&self) -> zbus::Result<String>;
+
+ /// DumpByFileDescriptor method
+ fn dump_by_file_descriptor(&self) -> zbus::Result<zbus::zvariant::OwnedFd>;
+
+ /// EnableUnitFiles method
+ fn enable_unit_files(
+ &self,
+ files: &[&str],
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<(bool, Vec<(String, String, String)>)>;
+
+ /// EnableUnitFilesWithFlags method
+ fn enable_unit_files_with_flags(
+ &self,
+ files: &[&str],
+ flags: u64,
+ ) -> zbus::Result<(bool, Vec<(String, String, String)>)>;
+
+ /// EnqueueMarkedJobs method
+ fn enqueue_marked_jobs(&self) -> zbus::Result<Vec<zbus::zvariant::OwnedObjectPath>>;
+
+ /// EnqueueUnitJob method
+ fn enqueue_unit_job(
+ &self,
+ name: &str,
+ job_type: &str,
+ job_mode: &str,
+ ) -> zbus::Result<(
+ u32,
+ zbus::zvariant::OwnedObjectPath,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ String,
+ Vec<(
+ u32,
+ zbus::zvariant::OwnedObjectPath,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ String,
+ )>,
+ )>;
+
+ /// Exit method
+ fn exit(&self) -> zbus::Result<()>;
+
+ /// FreezeUnit method
+ fn freeze_unit(&self, name: &str) -> zbus::Result<()>;
+
+ /// GetDefaultTarget method
+ fn get_default_target(&self) -> zbus::Result<String>;
+
+ /// GetDynamicUsers method
+ fn get_dynamic_users(&self) -> zbus::Result<Vec<(u32, String)>>;
+
+ /// GetJob method
+ fn get_job(&self, id: u32) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// GetJobAfter method
+ fn get_job_after(
+ &self,
+ id: u32,
+ ) -> zbus::Result<
+ Vec<(
+ u32,
+ String,
+ String,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ zbus::zvariant::OwnedObjectPath,
+ )>,
+ >;
+
+ /// GetJobBefore method
+ fn get_job_before(
+ &self,
+ id: u32,
+ ) -> zbus::Result<
+ Vec<(
+ u32,
+ String,
+ String,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ zbus::zvariant::OwnedObjectPath,
+ )>,
+ >;
+
+ /// GetUnit method
+ fn get_unit(&self, name: &str) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// GetUnitByControlGroup method
+ fn get_unit_by_control_group(
+ &self,
+ cgroup: &str,
+ ) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// GetUnitByInvocationID method
+ fn get_unit_by_invocation_id(
+ &self,
+ invocation_id: &[u8],
+ ) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// GetUnitByPID method
+ fn get_unit_by_pid(&self, pid: u32) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// GetUnitFileLinks method
+ fn get_unit_file_links(&self, name: &str, runtime: bool) -> zbus::Result<Vec<String>>;
+
+ /// GetUnitFileState method
+ fn get_unit_file_state(&self, file: &str) -> zbus::Result<String>;
+
+ /// GetUnitProcesses method
+ fn get_unit_processes(&self, name: &str) -> zbus::Result<Vec<(String, u32, String)>>;
+
+ /// Halt method
+ fn halt(&self) -> zbus::Result<()>;
+
+ /// KExec method
+ fn kexec(&self) -> zbus::Result<()>;
+
+ /// KillUnit method
+ fn kill_unit(&self, name: &str, whom: &str, signal: i32) -> zbus::Result<()>;
+
+ /// LinkUnitFiles method
+ fn link_unit_files(
+ &self,
+ files: &[&str],
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// ListJobs method
+ fn list_jobs(
+ &self,
+ ) -> zbus::Result<
+ Vec<(
+ u32,
+ String,
+ String,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ zbus::zvariant::OwnedObjectPath,
+ )>,
+ >;
+
+ /// ListUnitFiles method
+ fn list_unit_files(&self) -> zbus::Result<Vec<(String, String)>>;
+
+ /// ListUnitFilesByPatterns method
+ fn list_unit_files_by_patterns(
+ &self,
+ states: &[&str],
+ patterns: &[&str],
+ ) -> zbus::Result<Vec<(String, String)>>;
+
+ /// ListUnits method
+ fn list_units(
+ &self,
+ ) -> zbus::Result<
+ Vec<(
+ String,
+ String,
+ String,
+ String,
+ String,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ u32,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ )>,
+ >;
+
+ /// ListUnitsByNames method
+ fn list_units_by_names(
+ &self,
+ names: &[&str],
+ ) -> zbus::Result<
+ Vec<(
+ String,
+ String,
+ String,
+ String,
+ String,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ u32,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ )>,
+ >;
+
+ /// ListUnitsByPatterns method
+ fn list_units_by_patterns(
+ &self,
+ states: &[&str],
+ patterns: &[&str],
+ ) -> zbus::Result<
+ Vec<(
+ String,
+ String,
+ String,
+ String,
+ String,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ u32,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ )>,
+ >;
+
+ /// ListUnitsFiltered method
+ fn list_units_filtered(
+ &self,
+ states: &[&str],
+ ) -> zbus::Result<
+ Vec<(
+ String,
+ String,
+ String,
+ String,
+ String,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ u32,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ )>,
+ >;
+
+ /// LoadUnit method
+ fn load_unit(&self, name: &str) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// LookupDynamicUserByName method
+ fn lookup_dynamic_user_by_name(&self, name: &str) -> zbus::Result<u32>;
+
+ /// LookupDynamicUserByUID method
+ fn lookup_dynamic_user_by_uid(&self, uid: u32) -> zbus::Result<String>;
+
+ /// MaskUnitFiles method
+ fn mask_unit_files(
+ &self,
+ files: &[&str],
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// MountImageUnit method
+ fn mount_image_unit(
+ &self,
+ name: &str,
+ source: &str,
+ destination: &str,
+ read_only: bool,
+ mkdir: bool,
+ options: &[(&str, &str)],
+ ) -> zbus::Result<()>;
+
+ /// PowerOff method
+ fn power_off(&self) -> zbus::Result<()>;
+
+ /// PresetAllUnitFiles method
+ fn preset_all_unit_files(
+ &self,
+ mode: &str,
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// PresetUnitFiles method
+ fn preset_unit_files(
+ &self,
+ files: &[&str],
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<(bool, Vec<(String, String, String)>)>;
+
+ /// PresetUnitFilesWithMode method
+ fn preset_unit_files_with_mode(
+ &self,
+ files: &[&str],
+ mode: &str,
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<(bool, Vec<(String, String, String)>)>;
+
+ /// Reboot method
+ fn reboot(&self) -> zbus::Result<()>;
+
+ /// ReenableUnitFiles method
+ fn reenable_unit_files(
+ &self,
+ files: &[&str],
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<(bool, Vec<(String, String, String)>)>;
+
+ /// Reexecute method
+ fn reexecute(&self) -> zbus::Result<()>;
+
+ /// RefUnit method
+ fn ref_unit(&self, name: &str) -> zbus::Result<()>;
+
+ /// Reload method
+ fn reload(&self) -> zbus::Result<()>;
+
+ /// ReloadOrRestartUnit method
+ fn reload_or_restart_unit(
+ &self,
+ name: &str,
+ mode: &str,
+ ) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// ReloadOrTryRestartUnit method
+ fn reload_or_try_restart_unit(
+ &self,
+ name: &str,
+ mode: &str,
+ ) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// ReloadUnit method
+ fn reload_unit(&self, name: &str, mode: &str) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// ResetFailed method
+ fn reset_failed(&self) -> zbus::Result<()>;
+
+ /// ResetFailedUnit method
+ fn reset_failed_unit(&self, name: &str) -> zbus::Result<()>;
+
+ /// RestartUnit method
+ fn restart_unit(&self, name: &str, mode: &str)
+ -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// RevertUnitFiles method
+ fn revert_unit_files(&self, files: &[&str]) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// SetDefaultTarget method
+ fn set_default_target(
+ &self,
+ name: &str,
+ force: bool,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// SetEnvironment method
+ fn set_environment(&self, assignments: &[&str]) -> zbus::Result<()>;
+
+ /// SetExitCode method
+ fn set_exit_code(&self, number: u8) -> zbus::Result<()>;
+
+ /// SetShowStatus method
+ fn set_show_status(&self, mode: &str) -> zbus::Result<()>;
+
+ /// SetUnitProperties method
+ fn set_unit_properties(
+ &self,
+ name: &str,
+ runtime: bool,
+ properties: &[(&str, zbus::zvariant::Value<'_>)],
+ ) -> zbus::Result<()>;
+
+ /// StartTransientUnit method
+ fn start_transient_unit(
+ &self,
+ name: &str,
+ mode: &str,
+ properties: &[(&str, zbus::zvariant::Value<'_>)],
+ aux: &[(&str, &[(&str, zbus::zvariant::Value<'_>)])],
+ ) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// StartUnit method
+ fn start_unit(&self, name: &str, mode: &str) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// StartUnitReplace method
+ fn start_unit_replace(
+ &self,
+ old_unit: &str,
+ new_unit: &str,
+ mode: &str,
+ ) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// StopUnit method
+ fn stop_unit(&self, name: &str, mode: &str) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// Subscribe method
+ fn subscribe(&self) -> zbus::Result<()>;
+
+ /// SwitchRoot method
+ fn switch_root(&self, new_root: &str, init: &str) -> zbus::Result<()>;
+
+ /// ThawUnit method
+ fn thaw_unit(&self, name: &str) -> zbus::Result<()>;
+
+ /// TryRestartUnit method
+ fn try_restart_unit(
+ &self,
+ name: &str,
+ mode: &str,
+ ) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// UnmaskUnitFiles method
+ fn unmask_unit_files(
+ &self,
+ files: &[&str],
+ runtime: bool,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// UnrefUnit method
+ fn unref_unit(&self, name: &str) -> zbus::Result<()>;
+
+ /// UnsetAndSetEnvironment method
+ fn unset_and_set_environment(&self, names: &[&str], assignments: &[&str]) -> zbus::Result<()>;
+
+ /// UnsetEnvironment method
+ fn unset_environment(&self, names: &[&str]) -> zbus::Result<()>;
+
+ /// Unsubscribe method
+ fn unsubscribe(&self) -> zbus::Result<()>;
+
+ /// JobNew signal
+ #[dbus_proxy(signal)]
+ fn job_new(&self, id: u32, job: zbus::zvariant::ObjectPath<'_>, unit: &str)
+ -> zbus::Result<()>;
+
+ /// JobRemoved signal
+ #[dbus_proxy(signal)]
+ fn job_removed(
+ &self,
+ id: u32,
+ job: zbus::zvariant::ObjectPath<'_>,
+ unit: &str,
+ result: &str,
+ ) -> zbus::Result<()>;
+
+ /// Reloading signal
+ #[dbus_proxy(signal)]
+ fn reloading(&self, active: bool) -> zbus::Result<()>;
+
+ /// StartupFinished signal
+ #[dbus_proxy(signal)]
+ fn startup_finished(
+ &self,
+ firmware: u64,
+ loader: u64,
+ kernel: u64,
+ initrd: u64,
+ userspace: u64,
+ total: u64,
+ ) -> zbus::Result<()>;
+
+ /// UnitFilesChanged signal
+ #[dbus_proxy(signal)]
+ fn unit_files_changed(&self) -> zbus::Result<()>;
+
+ /// UnitNew signal
+ #[dbus_proxy(signal)]
+ fn unit_new(&self, id: &str, unit: zbus::zvariant::ObjectPath<'_>) -> zbus::Result<()>;
+
+ /// UnitRemoved signal
+ #[dbus_proxy(signal)]
+ fn unit_removed(&self, id: &str, unit: zbus::zvariant::ObjectPath<'_>) -> zbus::Result<()>;
+
+ /// Architecture property
+ #[dbus_proxy(property)]
+ fn architecture(&self) -> zbus::Result<String>;
+
+ /// ConfirmSpawn property
+ #[dbus_proxy(property)]
+ fn confirm_spawn(&self) -> zbus::Result<bool>;
+
+ /// ControlGroup property
+ #[dbus_proxy(property)]
+ fn control_group(&self) -> zbus::Result<String>;
+
+ /// CtrlAltDelBurstAction property
+ #[dbus_proxy(property)]
+ fn ctrl_alt_del_burst_action(&self) -> zbus::Result<String>;
+
+ /// DefaultBlockIOAccounting property
+ #[dbus_proxy(property)]
+ fn default_block_ioaccounting(&self) -> zbus::Result<bool>;
+
+ /// DefaultCPUAccounting property
+ #[dbus_proxy(property)]
+ fn default_cpuaccounting(&self) -> zbus::Result<bool>;
+
+ /// DefaultLimitAS property
+ #[dbus_proxy(property)]
+ fn default_limit_as(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitASSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_assoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitCORE property
+ #[dbus_proxy(property)]
+ fn default_limit_core(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitCORESoft property
+ #[dbus_proxy(property)]
+ fn default_limit_coresoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitCPU property
+ #[dbus_proxy(property)]
+ fn default_limit_cpu(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitCPUSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_cpusoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitDATA property
+ #[dbus_proxy(property)]
+ fn default_limit_data(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitDATASoft property
+ #[dbus_proxy(property)]
+ fn default_limit_datasoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitFSIZE property
+ #[dbus_proxy(property)]
+ fn default_limit_fsize(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitFSIZESoft property
+ #[dbus_proxy(property)]
+ fn default_limit_fsizesoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitLOCKS property
+ #[dbus_proxy(property)]
+ fn default_limit_locks(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitLOCKSSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_lockssoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitMEMLOCK property
+ #[dbus_proxy(property)]
+ fn default_limit_memlock(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitMEMLOCKSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_memlocksoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitMSGQUEUE property
+ #[dbus_proxy(property)]
+ fn default_limit_msgqueue(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitMSGQUEUESoft property
+ #[dbus_proxy(property)]
+ fn default_limit_msgqueuesoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitNICE property
+ #[dbus_proxy(property)]
+ fn default_limit_nice(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitNICESoft property
+ #[dbus_proxy(property)]
+ fn default_limit_nicesoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitNOFILE property
+ #[dbus_proxy(property)]
+ fn default_limit_nofile(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitNOFILESoft property
+ #[dbus_proxy(property)]
+ fn default_limit_nofilesoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitNPROC property
+ #[dbus_proxy(property)]
+ fn default_limit_nproc(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitNPROCSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_nprocsoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitRSS property
+ #[dbus_proxy(property)]
+ fn default_limit_rss(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitRSSSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_rsssoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitRTPRIO property
+ #[dbus_proxy(property)]
+ fn default_limit_rtprio(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitRTPRIOSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_rtpriosoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitRTTIME property
+ #[dbus_proxy(property)]
+ fn default_limit_rttime(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitRTTIMESoft property
+ #[dbus_proxy(property)]
+ fn default_limit_rttimesoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitSIGPENDING property
+ #[dbus_proxy(property)]
+ fn default_limit_sigpending(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitSIGPENDINGSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_sigpendingsoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitSTACK property
+ #[dbus_proxy(property)]
+ fn default_limit_stack(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitSTACKSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_stacksoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultMemoryAccounting property
+ #[dbus_proxy(property)]
+ fn default_memory_accounting(&self) -> zbus::Result<bool>;
+
+ /// DefaultOOMPolicy property
+ #[dbus_proxy(property)]
+ fn default_oompolicy(&self) -> zbus::Result<String>;
+
+ /// DefaultRestartUSec property
+ #[dbus_proxy(property)]
+ fn default_restart_usec(&self) -> zbus::Result<u64>;
+
+ /// DefaultStandardError property
+ #[dbus_proxy(property)]
+ fn default_standard_error(&self) -> zbus::Result<String>;
+
+ /// DefaultStandardOutput property
+ #[dbus_proxy(property)]
+ fn default_standard_output(&self) -> zbus::Result<String>;
+
+ /// DefaultStartLimitBurst property
+ #[dbus_proxy(property)]
+ fn default_start_limit_burst(&self) -> zbus::Result<u32>;
+
+ /// DefaultStartLimitIntervalUSec property
+ #[dbus_proxy(property)]
+ fn default_start_limit_interval_usec(&self) -> zbus::Result<u64>;
+
+ /// DefaultTasksAccounting property
+ #[dbus_proxy(property)]
+ fn default_tasks_accounting(&self) -> zbus::Result<bool>;
+
+ /// DefaultTasksMax property
+ #[dbus_proxy(property)]
+ fn default_tasks_max(&self) -> zbus::Result<u64>;
+
+ /// DefaultTimeoutAbortUSec property
+ #[dbus_proxy(property)]
+ fn default_timeout_abort_usec(&self) -> zbus::Result<u64>;
+
+ /// DefaultTimeoutStartUSec property
+ #[dbus_proxy(property)]
+ fn default_timeout_start_usec(&self) -> zbus::Result<u64>;
+
+ /// DefaultTimeoutStopUSec property
+ #[dbus_proxy(property)]
+ fn default_timeout_stop_usec(&self) -> zbus::Result<u64>;
+
+ /// DefaultTimerAccuracyUSec property
+ #[dbus_proxy(property)]
+ fn default_timer_accuracy_usec(&self) -> zbus::Result<u64>;
+
+ /// Environment property
+ #[dbus_proxy(property)]
+ fn environment(&self) -> zbus::Result<Vec<String>>;
+
+ /// ExitCode property
+ #[dbus_proxy(property)]
+ fn exit_code(&self) -> zbus::Result<u8>;
+
+ /// Features property
+ #[dbus_proxy(property)]
+ fn features(&self) -> zbus::Result<String>;
+
+ /// FinishTimestamp property
+ #[dbus_proxy(property)]
+ fn finish_timestamp(&self) -> zbus::Result<u64>;
+
+ /// FinishTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn finish_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// FirmwareTimestamp property
+ #[dbus_proxy(property)]
+ fn firmware_timestamp(&self) -> zbus::Result<u64>;
+
+ /// FirmwareTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn firmware_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// GeneratorsFinishTimestamp property
+ #[dbus_proxy(property)]
+ fn generators_finish_timestamp(&self) -> zbus::Result<u64>;
+
+ /// GeneratorsFinishTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn generators_finish_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// GeneratorsStartTimestamp property
+ #[dbus_proxy(property)]
+ fn generators_start_timestamp(&self) -> zbus::Result<u64>;
+
+ /// GeneratorsStartTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn generators_start_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// InitRDGeneratorsFinishTimestamp property
+ #[dbus_proxy(property)]
+ fn init_rdgenerators_finish_timestamp(&self) -> zbus::Result<u64>;
+
+ /// InitRDGeneratorsFinishTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn init_rdgenerators_finish_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// InitRDGeneratorsStartTimestamp property
+ #[dbus_proxy(property)]
+ fn init_rdgenerators_start_timestamp(&self) -> zbus::Result<u64>;
+
+ /// InitRDGeneratorsStartTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn init_rdgenerators_start_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// InitRDSecurityFinishTimestamp property
+ #[dbus_proxy(property)]
+ fn init_rdsecurity_finish_timestamp(&self) -> zbus::Result<u64>;
+
+ /// InitRDSecurityFinishTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn init_rdsecurity_finish_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// InitRDSecurityStartTimestamp property
+ #[dbus_proxy(property)]
+ fn init_rdsecurity_start_timestamp(&self) -> zbus::Result<u64>;
+
+ /// InitRDSecurityStartTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn init_rdsecurity_start_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// InitRDTimestamp property
+ #[dbus_proxy(property)]
+ fn init_rdtimestamp(&self) -> zbus::Result<u64>;
+
+ /// InitRDTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn init_rdtimestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// InitRDUnitsLoadFinishTimestamp property
+ #[dbus_proxy(property)]
+ fn init_rdunits_load_finish_timestamp(&self) -> zbus::Result<u64>;
+
+ /// InitRDUnitsLoadFinishTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn init_rdunits_load_finish_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// InitRDUnitsLoadStartTimestamp property
+ #[dbus_proxy(property)]
+ fn init_rdunits_load_start_timestamp(&self) -> zbus::Result<u64>;
+
+ /// InitRDUnitsLoadStartTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn init_rdunits_load_start_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// KExecWatchdogUSec property
+ #[dbus_proxy(property)]
+ fn kexec_watchdog_usec(&self) -> zbus::Result<u64>;
+ #[dbus_proxy(property)]
+ fn set_kexec_watchdog_usec(&self, value: u64) -> zbus::Result<()>;
+
+ /// KernelTimestamp property
+ #[dbus_proxy(property)]
+ fn kernel_timestamp(&self) -> zbus::Result<u64>;
+
+ /// KernelTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn kernel_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// LoaderTimestamp property
+ #[dbus_proxy(property)]
+ fn loader_timestamp(&self) -> zbus::Result<u64>;
+
+ /// LoaderTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn loader_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// LogLevel property
+ #[dbus_proxy(property)]
+ fn log_level(&self) -> zbus::Result<String>;
+ #[dbus_proxy(property)]
+ fn set_log_level(&self, value: &str) -> zbus::Result<()>;
+
+ /// LogTarget property
+ #[dbus_proxy(property)]
+ fn log_target(&self) -> zbus::Result<String>;
+ #[dbus_proxy(property)]
+ fn set_log_target(&self, value: &str) -> zbus::Result<()>;
+
+ /// NFailedJobs property
+ #[dbus_proxy(property)]
+ fn nfailed_jobs(&self) -> zbus::Result<u32>;
+
+ /// NFailedUnits property
+ #[dbus_proxy(property)]
+ fn nfailed_units(&self) -> zbus::Result<u32>;
+
+ /// NInstalledJobs property
+ #[dbus_proxy(property)]
+ fn ninstalled_jobs(&self) -> zbus::Result<u32>;
+
+ /// NJobs property
+ #[dbus_proxy(property)]
+ fn njobs(&self) -> zbus::Result<u32>;
+
+ /// NNames property
+ #[dbus_proxy(property)]
+ fn nnames(&self) -> zbus::Result<u32>;
+
+ /// Progress property
+ #[dbus_proxy(property)]
+ fn progress(&self) -> zbus::Result<f64>;
+
+ /// RebootWatchdogUSec property
+ #[dbus_proxy(property)]
+ fn reboot_watchdog_usec(&self) -> zbus::Result<u64>;
+ #[dbus_proxy(property)]
+ fn set_reboot_watchdog_usec(&self, value: u64) -> zbus::Result<()>;
+
+ /// RuntimeWatchdogUSec property
+ #[dbus_proxy(property)]
+ fn runtime_watchdog_usec(&self) -> zbus::Result<u64>;
+ #[dbus_proxy(property)]
+ fn set_runtime_watchdog_usec(&self, value: u64) -> zbus::Result<()>;
+
+ /// SecurityFinishTimestamp property
+ #[dbus_proxy(property)]
+ fn security_finish_timestamp(&self) -> zbus::Result<u64>;
+
+ /// SecurityFinishTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn security_finish_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// SecurityStartTimestamp property
+ #[dbus_proxy(property)]
+ fn security_start_timestamp(&self) -> zbus::Result<u64>;
+
+ /// SecurityStartTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn security_start_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// ServiceWatchdogs property
+ #[dbus_proxy(property)]
+ fn service_watchdogs(&self) -> zbus::Result<bool>;
+ #[dbus_proxy(property)]
+ fn set_service_watchdogs(&self, value: bool) -> zbus::Result<()>;
+
+ /// ShowStatus property
+ #[dbus_proxy(property)]
+ fn show_status(&self) -> zbus::Result<bool>;
+
+ /// SystemState property
+ #[dbus_proxy(property)]
+ fn system_state(&self) -> zbus::Result<String>;
+
+ /// Tainted property
+ #[dbus_proxy(property)]
+ fn tainted(&self) -> zbus::Result<String>;
+
+ /// TimerSlackNSec property
+ #[dbus_proxy(property)]
+ fn timer_slack_nsec(&self) -> zbus::Result<u64>;
+
+ /// UnitPath property
+ #[dbus_proxy(property)]
+ fn unit_path(&self) -> zbus::Result<Vec<String>>;
+
+ /// UnitsLoadFinishTimestamp property
+ #[dbus_proxy(property)]
+ fn units_load_finish_timestamp(&self) -> zbus::Result<u64>;
+
+ /// UnitsLoadFinishTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn units_load_finish_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// UnitsLoadStartTimestamp property
+ #[dbus_proxy(property)]
+ fn units_load_start_timestamp(&self) -> zbus::Result<u64>;
+
+ /// UnitsLoadStartTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn units_load_start_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// UserspaceTimestamp property
+ #[dbus_proxy(property)]
+ fn userspace_timestamp(&self) -> zbus::Result<u64>;
+
+ /// UserspaceTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn userspace_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// Version property
+ #[dbus_proxy(property)]
+ fn version(&self) -> zbus::Result<String>;
+
+ /// Virtualization property
+ #[dbus_proxy(property)]
+ fn virtualization(&self) -> zbus::Result<String>;
+}
diff --git a/src/agent/rustjail/src/cgroups/systemd/interface/system.rs b/src/agent/rustjail/src/cgroups/systemd/interface/system.rs
new file mode 100644
index 000000000..7a4ef199e
--- /dev/null
+++ b/src/agent/rustjail/src/cgroups/systemd/interface/system.rs
@@ -0,0 +1,1004 @@
+// Copyright 2021-2022 Kata Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#![allow(unknown_lints)]
+#![allow(clippy::all)]
+
+//! # DBus interface proxy for: `org.freedesktop.systemd1.Manager`
+//!
+//! This code was generated by `zbus-xmlgen` `2.0.1` from DBus introspection data.
+//! Source: `Interface '/org/freedesktop/systemd1' from service 'org.freedesktop.systemd1' on system bus`.
+//!
+//! You may prefer to adapt it, instead of using it verbatim.
+//!
+//! More information can be found in the
+//! [Writing a client proxy](https://dbus.pages.freedesktop.org/zbus/client.html)
+//! section of the zbus documentation.
+//!
+//! This DBus object implements
+//! [standard DBus interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html),
+//! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used:
+//!
+//! * [`zbus::fdo::PeerProxy`]
+//! * [`zbus::fdo::IntrospectableProxy`]
+//! * [`zbus::fdo::PropertiesProxy`]
+//!
+//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
+
+use zbus::dbus_proxy;
+
+#[dbus_proxy(
+ interface = "org.freedesktop.systemd1.Manager",
+ default_service = "org.freedesktop.systemd1",
+ default_path = "/org/freedesktop/systemd1"
+)]
+trait Manager {
+ /// AbandonScope method
+ fn abandon_scope(&self, name: &str) -> zbus::Result<()>;
+
+ /// AddDependencyUnitFiles method
+ fn add_dependency_unit_files(
+ &self,
+ files: &[&str],
+ target: &str,
+ type_: &str,
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// AttachProcessesToUnit method
+ fn attach_processes_to_unit(
+ &self,
+ unit_name: &str,
+ subcgroup: &str,
+ pids: &[u32],
+ ) -> zbus::Result<()>;
+
+ /// BindMountUnit method
+ fn bind_mount_unit(
+ &self,
+ name: &str,
+ source: &str,
+ destination: &str,
+ read_only: bool,
+ mkdir: bool,
+ ) -> zbus::Result<()>;
+
+ /// CancelJob method
+ fn cancel_job(&self, id: u32) -> zbus::Result<()>;
+
+ /// CleanUnit method
+ fn clean_unit(&self, name: &str, mask: &[&str]) -> zbus::Result<()>;
+
+ /// ClearJobs method
+ fn clear_jobs(&self) -> zbus::Result<()>;
+
+ /// DisableUnitFiles method
+ fn disable_unit_files(
+ &self,
+ files: &[&str],
+ runtime: bool,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// DisableUnitFilesWithFlags method
+ fn disable_unit_files_with_flags(
+ &self,
+ files: &[&str],
+ flags: u64,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// Dump method
+ fn dump(&self) -> zbus::Result<String>;
+
+ /// DumpByFileDescriptor method
+ fn dump_by_file_descriptor(&self) -> zbus::Result<zbus::zvariant::OwnedFd>;
+
+ /// EnableUnitFiles method
+ fn enable_unit_files(
+ &self,
+ files: &[&str],
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<(bool, Vec<(String, String, String)>)>;
+
+ /// EnableUnitFilesWithFlags method
+ fn enable_unit_files_with_flags(
+ &self,
+ files: &[&str],
+ flags: u64,
+ ) -> zbus::Result<(bool, Vec<(String, String, String)>)>;
+
+ /// EnqueueMarkedJobs method
+ fn enqueue_marked_jobs(&self) -> zbus::Result<Vec<zbus::zvariant::OwnedObjectPath>>;
+
+ /// EnqueueUnitJob method
+ fn enqueue_unit_job(
+ &self,
+ name: &str,
+ job_type: &str,
+ job_mode: &str,
+ ) -> zbus::Result<(
+ u32,
+ zbus::zvariant::OwnedObjectPath,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ String,
+ Vec<(
+ u32,
+ zbus::zvariant::OwnedObjectPath,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ String,
+ )>,
+ )>;
+
+ /// Exit method
+ fn exit(&self) -> zbus::Result<()>;
+
+ /// FreezeUnit method
+ fn freeze_unit(&self, name: &str) -> zbus::Result<()>;
+
+ /// GetDefaultTarget method
+ fn get_default_target(&self) -> zbus::Result<String>;
+
+ /// GetDynamicUsers method
+ fn get_dynamic_users(&self) -> zbus::Result<Vec<(u32, String)>>;
+
+ /// GetJob method
+ fn get_job(&self, id: u32) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// GetJobAfter method
+ fn get_job_after(
+ &self,
+ id: u32,
+ ) -> zbus::Result<
+ Vec<(
+ u32,
+ String,
+ String,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ zbus::zvariant::OwnedObjectPath,
+ )>,
+ >;
+
+ /// GetJobBefore method
+ fn get_job_before(
+ &self,
+ id: u32,
+ ) -> zbus::Result<
+ Vec<(
+ u32,
+ String,
+ String,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ zbus::zvariant::OwnedObjectPath,
+ )>,
+ >;
+
+ /// GetUnit method
+ fn get_unit(&self, name: &str) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// GetUnitByControlGroup method
+ fn get_unit_by_control_group(
+ &self,
+ cgroup: &str,
+ ) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// GetUnitByInvocationID method
+ fn get_unit_by_invocation_id(
+ &self,
+ invocation_id: &[u8],
+ ) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// GetUnitByPID method
+ fn get_unit_by_pid(&self, pid: u32) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// GetUnitFileLinks method
+ fn get_unit_file_links(&self, name: &str, runtime: bool) -> zbus::Result<Vec<String>>;
+
+ /// GetUnitFileState method
+ fn get_unit_file_state(&self, file: &str) -> zbus::Result<String>;
+
+ /// GetUnitProcesses method
+ fn get_unit_processes(&self, name: &str) -> zbus::Result<Vec<(String, u32, String)>>;
+
+ /// Halt method
+ fn halt(&self) -> zbus::Result<()>;
+
+ /// KExec method
+ fn kexec(&self) -> zbus::Result<()>;
+
+ /// KillUnit method
+ fn kill_unit(&self, name: &str, whom: &str, signal: i32) -> zbus::Result<()>;
+
+ /// LinkUnitFiles method
+ fn link_unit_files(
+ &self,
+ files: &[&str],
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// ListJobs method
+ fn list_jobs(
+ &self,
+ ) -> zbus::Result<
+ Vec<(
+ u32,
+ String,
+ String,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ zbus::zvariant::OwnedObjectPath,
+ )>,
+ >;
+
+ /// ListUnitFiles method
+ fn list_unit_files(&self) -> zbus::Result<Vec<(String, String)>>;
+
+ /// ListUnitFilesByPatterns method
+ fn list_unit_files_by_patterns(
+ &self,
+ states: &[&str],
+ patterns: &[&str],
+ ) -> zbus::Result<Vec<(String, String)>>;
+
+ /// ListUnits method
+ fn list_units(
+ &self,
+ ) -> zbus::Result<
+ Vec<(
+ String,
+ String,
+ String,
+ String,
+ String,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ u32,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ )>,
+ >;
+
+ /// ListUnitsByNames method
+ fn list_units_by_names(
+ &self,
+ names: &[&str],
+ ) -> zbus::Result<
+ Vec<(
+ String,
+ String,
+ String,
+ String,
+ String,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ u32,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ )>,
+ >;
+
+ /// ListUnitsByPatterns method
+ fn list_units_by_patterns(
+ &self,
+ states: &[&str],
+ patterns: &[&str],
+ ) -> zbus::Result<
+ Vec<(
+ String,
+ String,
+ String,
+ String,
+ String,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ u32,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ )>,
+ >;
+
+ /// ListUnitsFiltered method
+ fn list_units_filtered(
+ &self,
+ states: &[&str],
+ ) -> zbus::Result<
+ Vec<(
+ String,
+ String,
+ String,
+ String,
+ String,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ u32,
+ String,
+ zbus::zvariant::OwnedObjectPath,
+ )>,
+ >;
+
+ /// LoadUnit method
+ fn load_unit(&self, name: &str) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// LookupDynamicUserByName method
+ fn lookup_dynamic_user_by_name(&self, name: &str) -> zbus::Result<u32>;
+
+ /// LookupDynamicUserByUID method
+ fn lookup_dynamic_user_by_uid(&self, uid: u32) -> zbus::Result<String>;
+
+ /// MaskUnitFiles method
+ fn mask_unit_files(
+ &self,
+ files: &[&str],
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// MountImageUnit method
+ fn mount_image_unit(
+ &self,
+ name: &str,
+ source: &str,
+ destination: &str,
+ read_only: bool,
+ mkdir: bool,
+ options: &[(&str, &str)],
+ ) -> zbus::Result<()>;
+
+ /// PowerOff method
+ fn power_off(&self) -> zbus::Result<()>;
+
+ /// PresetAllUnitFiles method
+ fn preset_all_unit_files(
+ &self,
+ mode: &str,
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// PresetUnitFiles method
+ fn preset_unit_files(
+ &self,
+ files: &[&str],
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<(bool, Vec<(String, String, String)>)>;
+
+ /// PresetUnitFilesWithMode method
+ fn preset_unit_files_with_mode(
+ &self,
+ files: &[&str],
+ mode: &str,
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<(bool, Vec<(String, String, String)>)>;
+
+ /// Reboot method
+ fn reboot(&self) -> zbus::Result<()>;
+
+ /// ReenableUnitFiles method
+ fn reenable_unit_files(
+ &self,
+ files: &[&str],
+ runtime: bool,
+ force: bool,
+ ) -> zbus::Result<(bool, Vec<(String, String, String)>)>;
+
+ /// Reexecute method
+ fn reexecute(&self) -> zbus::Result<()>;
+
+ /// RefUnit method
+ fn ref_unit(&self, name: &str) -> zbus::Result<()>;
+
+ /// Reload method
+ fn reload(&self) -> zbus::Result<()>;
+
+ /// ReloadOrRestartUnit method
+ fn reload_or_restart_unit(
+ &self,
+ name: &str,
+ mode: &str,
+ ) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// ReloadOrTryRestartUnit method
+ fn reload_or_try_restart_unit(
+ &self,
+ name: &str,
+ mode: &str,
+ ) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// ReloadUnit method
+ fn reload_unit(&self, name: &str, mode: &str) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// ResetFailed method
+ fn reset_failed(&self) -> zbus::Result<()>;
+
+ /// ResetFailedUnit method
+ fn reset_failed_unit(&self, name: &str) -> zbus::Result<()>;
+
+ /// RestartUnit method
+ fn restart_unit(&self, name: &str, mode: &str)
+ -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// RevertUnitFiles method
+ fn revert_unit_files(&self, files: &[&str]) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// SetDefaultTarget method
+ fn set_default_target(
+ &self,
+ name: &str,
+ force: bool,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// SetEnvironment method
+ fn set_environment(&self, assignments: &[&str]) -> zbus::Result<()>;
+
+ /// SetExitCode method
+ fn set_exit_code(&self, number: u8) -> zbus::Result<()>;
+
+ /// SetShowStatus method
+ fn set_show_status(&self, mode: &str) -> zbus::Result<()>;
+
+ /// SetUnitProperties method
+ fn set_unit_properties(
+ &self,
+ name: &str,
+ runtime: bool,
+ properties: &[(&str, zbus::zvariant::Value<'_>)],
+ ) -> zbus::Result<()>;
+
+ /// StartTransientUnit method
+ fn start_transient_unit(
+ &self,
+ name: &str,
+ mode: &str,
+ properties: &[(&str, zbus::zvariant::Value<'_>)],
+ aux: &[(&str, &[(&str, zbus::zvariant::Value<'_>)])],
+ ) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// StartUnit method
+ fn start_unit(&self, name: &str, mode: &str) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// StartUnitReplace method
+ fn start_unit_replace(
+ &self,
+ old_unit: &str,
+ new_unit: &str,
+ mode: &str,
+ ) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// StopUnit method
+ fn stop_unit(&self, name: &str, mode: &str) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// Subscribe method
+ fn subscribe(&self) -> zbus::Result<()>;
+
+ /// SwitchRoot method
+ fn switch_root(&self, new_root: &str, init: &str) -> zbus::Result<()>;
+
+ /// ThawUnit method
+ fn thaw_unit(&self, name: &str) -> zbus::Result<()>;
+
+ /// TryRestartUnit method
+ fn try_restart_unit(
+ &self,
+ name: &str,
+ mode: &str,
+ ) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+
+ /// UnmaskUnitFiles method
+ fn unmask_unit_files(
+ &self,
+ files: &[&str],
+ runtime: bool,
+ ) -> zbus::Result<Vec<(String, String, String)>>;
+
+ /// UnrefUnit method
+ fn unref_unit(&self, name: &str) -> zbus::Result<()>;
+
+ /// UnsetAndSetEnvironment method
+ fn unset_and_set_environment(&self, names: &[&str], assignments: &[&str]) -> zbus::Result<()>;
+
+ /// UnsetEnvironment method
+ fn unset_environment(&self, names: &[&str]) -> zbus::Result<()>;
+
+ /// Unsubscribe method
+ fn unsubscribe(&self) -> zbus::Result<()>;
+
+ /// JobNew signal
+ #[dbus_proxy(signal)]
+ fn job_new(&self, id: u32, job: zbus::zvariant::ObjectPath<'_>, unit: &str)
+ -> zbus::Result<()>;
+
+ /// JobRemoved signal
+ #[dbus_proxy(signal)]
+ fn job_removed(
+ &self,
+ id: u32,
+ job: zbus::zvariant::ObjectPath<'_>,
+ unit: &str,
+ result: &str,
+ ) -> zbus::Result<()>;
+
+ /// Reloading signal
+ #[dbus_proxy(signal)]
+ fn reloading(&self, active: bool) -> zbus::Result<()>;
+
+ /// StartupFinished signal
+ #[dbus_proxy(signal)]
+ fn startup_finished(
+ &self,
+ firmware: u64,
+ loader: u64,
+ kernel: u64,
+ initrd: u64,
+ userspace: u64,
+ total: u64,
+ ) -> zbus::Result<()>;
+
+ /// UnitFilesChanged signal
+ #[dbus_proxy(signal)]
+ fn unit_files_changed(&self) -> zbus::Result<()>;
+
+ /// UnitNew signal
+ #[dbus_proxy(signal)]
+ fn unit_new(&self, id: &str, unit: zbus::zvariant::ObjectPath<'_>) -> zbus::Result<()>;
+
+ /// UnitRemoved signal
+ #[dbus_proxy(signal)]
+ fn unit_removed(&self, id: &str, unit: zbus::zvariant::ObjectPath<'_>) -> zbus::Result<()>;
+
+ /// Architecture property
+ #[dbus_proxy(property)]
+ fn architecture(&self) -> zbus::Result<String>;
+
+ /// ConfirmSpawn property
+ #[dbus_proxy(property)]
+ fn confirm_spawn(&self) -> zbus::Result<bool>;
+
+ /// ControlGroup property
+ #[dbus_proxy(property)]
+ fn control_group(&self) -> zbus::Result<String>;
+
+ /// CtrlAltDelBurstAction property
+ #[dbus_proxy(property)]
+ fn ctrl_alt_del_burst_action(&self) -> zbus::Result<String>;
+
+ /// DefaultBlockIOAccounting property
+ #[dbus_proxy(property)]
+ fn default_block_ioaccounting(&self) -> zbus::Result<bool>;
+
+ /// DefaultCPUAccounting property
+ #[dbus_proxy(property)]
+ fn default_cpuaccounting(&self) -> zbus::Result<bool>;
+
+ /// DefaultLimitAS property
+ #[dbus_proxy(property)]
+ fn default_limit_as(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitASSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_assoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitCORE property
+ #[dbus_proxy(property)]
+ fn default_limit_core(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitCORESoft property
+ #[dbus_proxy(property)]
+ fn default_limit_coresoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitCPU property
+ #[dbus_proxy(property)]
+ fn default_limit_cpu(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitCPUSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_cpusoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitDATA property
+ #[dbus_proxy(property)]
+ fn default_limit_data(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitDATASoft property
+ #[dbus_proxy(property)]
+ fn default_limit_datasoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitFSIZE property
+ #[dbus_proxy(property)]
+ fn default_limit_fsize(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitFSIZESoft property
+ #[dbus_proxy(property)]
+ fn default_limit_fsizesoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitLOCKS property
+ #[dbus_proxy(property)]
+ fn default_limit_locks(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitLOCKSSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_lockssoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitMEMLOCK property
+ #[dbus_proxy(property)]
+ fn default_limit_memlock(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitMEMLOCKSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_memlocksoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitMSGQUEUE property
+ #[dbus_proxy(property)]
+ fn default_limit_msgqueue(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitMSGQUEUESoft property
+ #[dbus_proxy(property)]
+ fn default_limit_msgqueuesoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitNICE property
+ #[dbus_proxy(property)]
+ fn default_limit_nice(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitNICESoft property
+ #[dbus_proxy(property)]
+ fn default_limit_nicesoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitNOFILE property
+ #[dbus_proxy(property)]
+ fn default_limit_nofile(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitNOFILESoft property
+ #[dbus_proxy(property)]
+ fn default_limit_nofilesoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitNPROC property
+ #[dbus_proxy(property)]
+ fn default_limit_nproc(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitNPROCSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_nprocsoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitRSS property
+ #[dbus_proxy(property)]
+ fn default_limit_rss(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitRSSSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_rsssoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitRTPRIO property
+ #[dbus_proxy(property)]
+ fn default_limit_rtprio(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitRTPRIOSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_rtpriosoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitRTTIME property
+ #[dbus_proxy(property)]
+ fn default_limit_rttime(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitRTTIMESoft property
+ #[dbus_proxy(property)]
+ fn default_limit_rttimesoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitSIGPENDING property
+ #[dbus_proxy(property)]
+ fn default_limit_sigpending(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitSIGPENDINGSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_sigpendingsoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitSTACK property
+ #[dbus_proxy(property)]
+ fn default_limit_stack(&self) -> zbus::Result<u64>;
+
+ /// DefaultLimitSTACKSoft property
+ #[dbus_proxy(property)]
+ fn default_limit_stacksoft(&self) -> zbus::Result<u64>;
+
+ /// DefaultMemoryAccounting property
+ #[dbus_proxy(property)]
+ fn default_memory_accounting(&self) -> zbus::Result<bool>;
+
+ /// DefaultOOMPolicy property
+ #[dbus_proxy(property)]
+ fn default_oompolicy(&self) -> zbus::Result<String>;
+
+ /// DefaultRestartUSec property
+ #[dbus_proxy(property)]
+ fn default_restart_usec(&self) -> zbus::Result<u64>;
+
+ /// DefaultStandardError property
+ #[dbus_proxy(property)]
+ fn default_standard_error(&self) -> zbus::Result<String>;
+
+ /// DefaultStandardOutput property
+ #[dbus_proxy(property)]
+ fn default_standard_output(&self) -> zbus::Result<String>;
+
+ /// DefaultStartLimitBurst property
+ #[dbus_proxy(property)]
+ fn default_start_limit_burst(&self) -> zbus::Result<u32>;
+
+ /// DefaultStartLimitIntervalUSec property
+ #[dbus_proxy(property)]
+ fn default_start_limit_interval_usec(&self) -> zbus::Result<u64>;
+
+ /// DefaultTasksAccounting property
+ #[dbus_proxy(property)]
+ fn default_tasks_accounting(&self) -> zbus::Result<bool>;
+
+ /// DefaultTasksMax property
+ #[dbus_proxy(property)]
+ fn default_tasks_max(&self) -> zbus::Result<u64>;
+
+ /// DefaultTimeoutAbortUSec property
+ #[dbus_proxy(property)]
+ fn default_timeout_abort_usec(&self) -> zbus::Result<u64>;
+
+ /// DefaultTimeoutStartUSec property
+ #[dbus_proxy(property)]
+ fn default_timeout_start_usec(&self) -> zbus::Result<u64>;
+
+ /// DefaultTimeoutStopUSec property
+ #[dbus_proxy(property)]
+ fn default_timeout_stop_usec(&self) -> zbus::Result<u64>;
+
+ /// DefaultTimerAccuracyUSec property
+ #[dbus_proxy(property)]
+ fn default_timer_accuracy_usec(&self) -> zbus::Result<u64>;
+
+ /// Environment property
+ #[dbus_proxy(property)]
+ fn environment(&self) -> zbus::Result<Vec<String>>;
+
+ /// ExitCode property
+ #[dbus_proxy(property)]
+ fn exit_code(&self) -> zbus::Result<u8>;
+
+ /// Features property
+ #[dbus_proxy(property)]
+ fn features(&self) -> zbus::Result<String>;
+
+ /// FinishTimestamp property
+ #[dbus_proxy(property)]
+ fn finish_timestamp(&self) -> zbus::Result<u64>;
+
+ /// FinishTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn finish_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// FirmwareTimestamp property
+ #[dbus_proxy(property)]
+ fn firmware_timestamp(&self) -> zbus::Result<u64>;
+
+ /// FirmwareTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn firmware_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// GeneratorsFinishTimestamp property
+ #[dbus_proxy(property)]
+ fn generators_finish_timestamp(&self) -> zbus::Result<u64>;
+
+ /// GeneratorsFinishTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn generators_finish_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// GeneratorsStartTimestamp property
+ #[dbus_proxy(property)]
+ fn generators_start_timestamp(&self) -> zbus::Result<u64>;
+
+ /// GeneratorsStartTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn generators_start_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// InitRDGeneratorsFinishTimestamp property
+ #[dbus_proxy(property)]
+ fn init_rdgenerators_finish_timestamp(&self) -> zbus::Result<u64>;
+
+ /// InitRDGeneratorsFinishTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn init_rdgenerators_finish_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// InitRDGeneratorsStartTimestamp property
+ #[dbus_proxy(property)]
+ fn init_rdgenerators_start_timestamp(&self) -> zbus::Result<u64>;
+
+ /// InitRDGeneratorsStartTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn init_rdgenerators_start_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// InitRDSecurityFinishTimestamp property
+ #[dbus_proxy(property)]
+ fn init_rdsecurity_finish_timestamp(&self) -> zbus::Result<u64>;
+
+ /// InitRDSecurityFinishTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn init_rdsecurity_finish_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// InitRDSecurityStartTimestamp property
+ #[dbus_proxy(property)]
+ fn init_rdsecurity_start_timestamp(&self) -> zbus::Result<u64>;
+
+ /// InitRDSecurityStartTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn init_rdsecurity_start_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// InitRDTimestamp property
+ #[dbus_proxy(property)]
+ fn init_rdtimestamp(&self) -> zbus::Result<u64>;
+
+ /// InitRDTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn init_rdtimestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// InitRDUnitsLoadFinishTimestamp property
+ #[dbus_proxy(property)]
+ fn init_rdunits_load_finish_timestamp(&self) -> zbus::Result<u64>;
+
+ /// InitRDUnitsLoadFinishTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn init_rdunits_load_finish_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// InitRDUnitsLoadStartTimestamp property
+ #[dbus_proxy(property)]
+ fn init_rdunits_load_start_timestamp(&self) -> zbus::Result<u64>;
+
+ /// InitRDUnitsLoadStartTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn init_rdunits_load_start_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// KExecWatchdogUSec property
+ #[dbus_proxy(property)]
+ fn kexec_watchdog_usec(&self) -> zbus::Result<u64>;
+ #[dbus_proxy(property)]
+ fn set_kexec_watchdog_usec(&self, value: u64) -> zbus::Result<()>;
+
+ /// KernelTimestamp property
+ #[dbus_proxy(property)]
+ fn kernel_timestamp(&self) -> zbus::Result<u64>;
+
+ /// KernelTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn kernel_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// LoaderTimestamp property
+ #[dbus_proxy(property)]
+ fn loader_timestamp(&self) -> zbus::Result<u64>;
+
+ /// LoaderTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn loader_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// LogLevel property
+ #[dbus_proxy(property)]
+ fn log_level(&self) -> zbus::Result<String>;
+ #[dbus_proxy(property)]
+ fn set_log_level(&self, value: &str) -> zbus::Result<()>;
+
+ /// LogTarget property
+ #[dbus_proxy(property)]
+ fn log_target(&self) -> zbus::Result<String>;
+ #[dbus_proxy(property)]
+ fn set_log_target(&self, value: &str) -> zbus::Result<()>;
+
+ /// NFailedJobs property
+ #[dbus_proxy(property)]
+ fn nfailed_jobs(&self) -> zbus::Result<u32>;
+
+ /// NFailedUnits property
+ #[dbus_proxy(property)]
+ fn nfailed_units(&self) -> zbus::Result<u32>;
+
+ /// NInstalledJobs property
+ #[dbus_proxy(property)]
+ fn ninstalled_jobs(&self) -> zbus::Result<u32>;
+
+ /// NJobs property
+ #[dbus_proxy(property)]
+ fn njobs(&self) -> zbus::Result<u32>;
+
+ /// NNames property
+ #[dbus_proxy(property)]
+ fn nnames(&self) -> zbus::Result<u32>;
+
+ /// Progress property
+ #[dbus_proxy(property)]
+ fn progress(&self) -> zbus::Result<f64>;
+
+ /// RebootWatchdogUSec property
+ #[dbus_proxy(property)]
+ fn reboot_watchdog_usec(&self) -> zbus::Result<u64>;
+ #[dbus_proxy(property)]
+ fn set_reboot_watchdog_usec(&self, value: u64) -> zbus::Result<()>;
+
+ /// RuntimeWatchdogUSec property
+ #[dbus_proxy(property)]
+ fn runtime_watchdog_usec(&self) -> zbus::Result<u64>;
+ #[dbus_proxy(property)]
+ fn set_runtime_watchdog_usec(&self, value: u64) -> zbus::Result<()>;
+
+ /// SecurityFinishTimestamp property
+ #[dbus_proxy(property)]
+ fn security_finish_timestamp(&self) -> zbus::Result<u64>;
+
+ /// SecurityFinishTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn security_finish_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// SecurityStartTimestamp property
+ #[dbus_proxy(property)]
+ fn security_start_timestamp(&self) -> zbus::Result<u64>;
+
+ /// SecurityStartTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn security_start_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// ServiceWatchdogs property
+ #[dbus_proxy(property)]
+ fn service_watchdogs(&self) -> zbus::Result<bool>;
+ #[dbus_proxy(property)]
+ fn set_service_watchdogs(&self, value: bool) -> zbus::Result<()>;
+
+ /// ShowStatus property
+ #[dbus_proxy(property)]
+ fn show_status(&self) -> zbus::Result<bool>;
+
+ /// SystemState property
+ #[dbus_proxy(property)]
+ fn system_state(&self) -> zbus::Result<String>;
+
+ /// Tainted property
+ #[dbus_proxy(property)]
+ fn tainted(&self) -> zbus::Result<String>;
+
+ /// TimerSlackNSec property
+ #[dbus_proxy(property)]
+ fn timer_slack_nsec(&self) -> zbus::Result<u64>;
+
+ /// UnitPath property
+ #[dbus_proxy(property)]
+ fn unit_path(&self) -> zbus::Result<Vec<String>>;
+
+ /// UnitsLoadFinishTimestamp property
+ #[dbus_proxy(property)]
+ fn units_load_finish_timestamp(&self) -> zbus::Result<u64>;
+
+ /// UnitsLoadFinishTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn units_load_finish_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// UnitsLoadStartTimestamp property
+ #[dbus_proxy(property)]
+ fn units_load_start_timestamp(&self) -> zbus::Result<u64>;
+
+ /// UnitsLoadStartTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn units_load_start_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// UserspaceTimestamp property
+ #[dbus_proxy(property)]
+ fn userspace_timestamp(&self) -> zbus::Result<u64>;
+
+ /// UserspaceTimestampMonotonic property
+ #[dbus_proxy(property)]
+ fn userspace_timestamp_monotonic(&self) -> zbus::Result<u64>;
+
+ /// Version property
+ #[dbus_proxy(property)]
+ fn version(&self) -> zbus::Result<String>;
+
+ /// Virtualization property
+ #[dbus_proxy(property)]
+ fn virtualization(&self) -> zbus::Result<String>;
+}
diff --git a/src/agent/rustjail/src/cgroups/systemd/manager.rs b/src/agent/rustjail/src/cgroups/systemd/manager.rs
new file mode 100644
index 000000000..481ef1e60
--- /dev/null
+++ b/src/agent/rustjail/src/cgroups/systemd/manager.rs
@@ -0,0 +1,129 @@
+// Copyright 2021-2022 Kata Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+use crate::cgroups::Manager as CgroupManager;
+use crate::protocols::agent::CgroupStats;
+use anyhow::Result;
+use cgroups::freezer::FreezerState;
+use libc::{self, pid_t};
+use oci::LinuxResources;
+use std::any::Any;
+use std::collections::HashMap;
+use std::convert::TryInto;
+use std::string::String;
+use std::vec;
+
+use super::super::fs::Manager as FsManager;
+
+use super::cgroups_path::CgroupsPath;
+use super::common::{CgroupHierarchy, Properties};
+use super::dbus_client::{DBusClient, SystemdInterface};
+use super::subsystem::transformer::Transformer;
+use super::subsystem::{cpu::Cpu, cpuset::CpuSet, memory::Memory, pids::Pids};
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct Manager {
+ pub paths: HashMap<String, String>,
+ pub mounts: HashMap<String, String>,
+ pub cgroups_path: CgroupsPath,
+ pub cpath: String,
+ pub unit_name: String,
+ // dbus client for set properties
+ dbus_client: DBusClient,
+ // fs manager for get properties
+ fs_manager: FsManager,
+ // cgroup version for different dbus properties
+ cg_hierarchy: CgroupHierarchy,
+}
+
+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() {
+ self.dbus_client.add_process(pid, self.unit_name.as_str())?;
+ } else {
+ self.dbus_client.start_unit(
+ (pid as u32).try_into().unwrap(),
+ self.cgroups_path.slice.as_str(),
+ self.unit_name.as_str(),
+ &self.cg_hierarchy,
+ )?;
+ }
+
+ Ok(())
+ }
+
+ fn set(&self, r: &LinuxResources, _: bool) -> Result<()> {
+ let mut properties: Properties = vec![];
+
+ let systemd_version = self.dbus_client.get_version()?;
+ let systemd_version_str = systemd_version.as_str();
+
+ Cpu::apply(r, &mut properties, &self.cg_hierarchy, systemd_version_str)?;
+ Memory::apply(r, &mut properties, &self.cg_hierarchy, systemd_version_str)?;
+ Pids::apply(r, &mut properties, &self.cg_hierarchy, systemd_version_str)?;
+ CpuSet::apply(r, &mut properties, &self.cg_hierarchy, systemd_version_str)?;
+
+ self.dbus_client
+ .set_properties(self.unit_name.as_str(), &properties)?;
+
+ Ok(())
+ }
+
+ fn get_stats(&self) -> Result<CgroupStats> {
+ self.fs_manager.get_stats()
+ }
+
+ fn freeze(&self, state: FreezerState) -> Result<()> {
+ self.fs_manager.freeze(state)
+ }
+
+ fn destroy(&mut self) -> Result<()> {
+ self.dbus_client.stop_unit(self.unit_name.as_str())?;
+ self.fs_manager.destroy()
+ }
+
+ fn get_pids(&self) -> Result<Vec<pid_t>> {
+ self.fs_manager.get_pids()
+ }
+
+ fn update_cpuset_path(&self, guest_cpuset: &str, container_cpuset: &str) -> Result<()> {
+ self.fs_manager
+ .update_cpuset_path(guest_cpuset, container_cpuset)
+ }
+
+ fn get_cgroup_path(&self, cg: &str) -> Result<String> {
+ self.fs_manager.get_cgroup_path(cg)
+ }
+
+ fn as_any(&self) -> Result<&dyn Any> {
+ Ok(self)
+ }
+}
+
+impl Manager {
+ pub fn new(cgroups_path_str: &str) -> Result<Self> {
+ let cgroups_path = CgroupsPath::new(cgroups_path_str)?;
+ let (parent_slice, unit_name) = cgroups_path.parse()?;
+ let cpath = parent_slice + "/" + &unit_name;
+
+ let fs_manager = FsManager::new(cpath.as_str())?;
+
+ Ok(Manager {
+ paths: fs_manager.paths.clone(),
+ mounts: fs_manager.mounts.clone(),
+ cgroups_path,
+ cpath,
+ unit_name,
+ dbus_client: DBusClient {},
+ fs_manager,
+ cg_hierarchy: if cgroups::hierarchies::is_cgroup2_unified_mode() {
+ CgroupHierarchy::Unified
+ } else {
+ CgroupHierarchy::Legacy
+ },
+ })
+ }
+}
diff --git a/src/agent/rustjail/src/cgroups/systemd/mod.rs b/src/agent/rustjail/src/cgroups/systemd/mod.rs
new file mode 100644
index 000000000..1bfb49a36
--- /dev/null
+++ b/src/agent/rustjail/src/cgroups/systemd/mod.rs
@@ -0,0 +1,12 @@
+// Copyright 2021-2022 Kata Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+pub mod manager;
+
+mod cgroups_path;
+mod common;
+mod dbus_client;
+mod interface;
+mod subsystem;
diff --git a/src/agent/rustjail/src/cgroups/systemd/subsystem/cpu.rs b/src/agent/rustjail/src/cgroups/systemd/subsystem/cpu.rs
new file mode 100644
index 000000000..6735b4d3c
--- /dev/null
+++ b/src/agent/rustjail/src/cgroups/systemd/subsystem/cpu.rs
@@ -0,0 +1,139 @@
+// Copyright 2021-2022 Kata Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+use super::super::common::{CgroupHierarchy, Properties};
+use super::transformer::Transformer;
+
+use anyhow::Result;
+use oci::{LinuxCpu, LinuxResources};
+use zbus::zvariant::Value;
+
+const BASIC_SYSTEMD_VERSION: &str = "242";
+const DEFAULT_CPUQUOTAPERIOD: u64 = 100 * 1000;
+const SEC2MICROSEC: u64 = 1000 * 1000;
+const BASIC_INTERVAL: u64 = 10 * 1000;
+
+pub struct Cpu {}
+
+impl Transformer for Cpu {
+ fn apply(
+ r: &LinuxResources,
+ properties: &mut Properties,
+ cgroup_hierarchy: &CgroupHierarchy,
+ systemd_version: &str,
+ ) -> Result<()> {
+ if let Some(cpu_resources) = &r.cpu {
+ match cgroup_hierarchy {
+ CgroupHierarchy::Legacy => {
+ Self::legacy_apply(cpu_resources, properties, systemd_version)?
+ }
+ CgroupHierarchy::Unified => {
+ Self::unified_apply(cpu_resources, properties, systemd_version)?
+ }
+ }
+ }
+
+ Ok(())
+ }
+}
+
+impl Cpu {
+ // v1:
+ // cpu.shares <-> CPUShares
+ // cpu.period <-> CPUQuotaPeriodUSec
+ // cpu.period & cpu.quota <-> CPUQuotaPerSecUSec
+ fn legacy_apply(
+ cpu_resources: &LinuxCpu,
+ properties: &mut Properties,
+ systemd_version: &str,
+ ) -> Result<()> {
+ if let Some(shares) = cpu_resources.shares {
+ properties.push(("CPUShares", Value::U64(shares)));
+ }
+
+ if let Some(period) = cpu_resources.period {
+ if period != 0 && systemd_version >= BASIC_SYSTEMD_VERSION {
+ properties.push(("CPUQuotaPeriodUSec", Value::U64(period)));
+ }
+ }
+
+ if let Some(quota) = cpu_resources.quota {
+ let period = cpu_resources.period.unwrap_or(DEFAULT_CPUQUOTAPERIOD);
+ if period != 0 {
+ let cpu_quota_per_sec_usec = resolve_cpuquota(quota, period);
+ properties.push(("CPUQuotaPerSecUSec", Value::U64(cpu_quota_per_sec_usec)));
+ }
+ }
+
+ Ok(())
+ }
+
+ // v2:
+ // cpu.shares <-> CPUShares
+ // cpu.period <-> CPUQuotaPeriodUSec
+ // cpu.period & cpu.quota <-> CPUQuotaPerSecUSec
+ fn unified_apply(
+ cpu_resources: &LinuxCpu,
+ properties: &mut Properties,
+ systemd_version: &str,
+ ) -> Result<()> {
+ if let Some(shares) = cpu_resources.shares {
+ let unified_shares = get_unified_cpushares(shares);
+ properties.push(("CPUShares", Value::U64(unified_shares)));
+ }
+
+ if let Some(period) = cpu_resources.period {
+ if period != 0 && systemd_version >= BASIC_SYSTEMD_VERSION {
+ properties.push(("CPUQuotaPeriodUSec", Value::U64(period)));
+ }
+ }
+
+ if let Some(quota) = cpu_resources.quota {
+ let period = cpu_resources.period.unwrap_or(DEFAULT_CPUQUOTAPERIOD);
+ if period != 0 {
+ let cpu_quota_per_sec_usec = resolve_cpuquota(quota, period);
+ properties.push(("CPUQuotaPerSecUSec", Value::U64(cpu_quota_per_sec_usec)));
+ }
+ }
+
+ Ok(())
+ }
+}
+
+// ref: https://github.com/containers/crun/blob/main/crun.1.md#cgroup-v2
+// [2-262144] to [1-10000]
+fn get_unified_cpushares(shares: u64) -> u64 {
+ if shares == 0 {
+ return 100;
+ }
+
+ 1 + ((shares - 2) * 9999) / 262142
+}
+
+fn resolve_cpuquota(quota: i64, period: u64) -> u64 {
+ let mut cpu_quota_per_sec_usec = u64::MAX;
+ if quota > 0 {
+ cpu_quota_per_sec_usec = (quota as u64) * SEC2MICROSEC / period;
+ if cpu_quota_per_sec_usec % BASIC_INTERVAL != 0 {
+ cpu_quota_per_sec_usec =
+ ((cpu_quota_per_sec_usec / BASIC_INTERVAL) + 1) * BASIC_INTERVAL;
+ }
+ }
+ cpu_quota_per_sec_usec
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::cgroups::systemd::subsystem::cpu::resolve_cpuquota;
+
+ #[test]
+ fn test_unified_cpuquota() {
+ let quota: i64 = 1000000;
+ let period: u64 = 500000;
+ let cpu_quota_per_sec_usec = resolve_cpuquota(quota, period);
+
+ assert_eq!(2000000, cpu_quota_per_sec_usec);
+ }
+}
diff --git a/src/agent/rustjail/src/cgroups/systemd/subsystem/cpuset.rs b/src/agent/rustjail/src/cgroups/systemd/subsystem/cpuset.rs
new file mode 100644
index 000000000..3f05cdc7c
--- /dev/null
+++ b/src/agent/rustjail/src/cgroups/systemd/subsystem/cpuset.rs
@@ -0,0 +1,124 @@
+// Copyright 2021-2022 Kata Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+use super::super::common::{CgroupHierarchy, Properties};
+
+use super::transformer::Transformer;
+
+use anyhow::{bail, Result};
+use bit_vec::BitVec;
+use oci::{LinuxCpu, LinuxResources};
+use std::convert::{TryFrom, TryInto};
+use zbus::zvariant::Value;
+
+const BASIC_SYSTEMD_VERSION: &str = "244";
+
+pub struct CpuSet {}
+
+impl Transformer for CpuSet {
+ fn apply(
+ r: &LinuxResources,
+ properties: &mut Properties,
+ _: &CgroupHierarchy,
+ systemd_version: &str,
+ ) -> Result<()> {
+ if let Some(cpuset_resources) = &r.cpu {
+ Self::apply(cpuset_resources, properties, systemd_version)?;
+ }
+
+ Ok(())
+ }
+}
+
+// v1 & v2:
+// cpuset.cpus <-> AllowedCPUs (v244)
+// cpuset.mems <-> AllowedMemoryNodes (v244)
+impl CpuSet {
+ fn apply(
+ cpuset_resources: &LinuxCpu,
+ properties: &mut Properties,
+ systemd_version: &str,
+ ) -> Result<()> {
+ if systemd_version < BASIC_SYSTEMD_VERSION {
+ return Ok(());
+ }
+
+ let cpus = cpuset_resources.cpus.as_str();
+ if !cpus.is_empty() {
+ let cpus_vec: BitMask = cpus.try_into()?;
+ properties.push(("AllowedCPUs", Value::Array(cpus_vec.0.into())));
+ }
+
+ let mems = cpuset_resources.mems.as_str();
+ if !mems.is_empty() {
+ let mems_vec: BitMask = mems.try_into()?;
+ properties.push(("AllowedMemoryNodes", Value::Array(mems_vec.0.into())));
+ }
+
+ Ok(())
+ }
+}
+
+struct BitMask(Vec<u8>);
+
+impl TryFrom<&str> for BitMask {
+ type Error = anyhow::Error;
+
+ fn try_from(bitmask_str: &str) -> Result<Self, Self::Error> {
+ let mut bitmask_vec = BitVec::from_elem(8, false);
+ let bitmask_str_vec: Vec<&str> = bitmask_str.split(',').collect();
+ for bitmask in bitmask_str_vec.iter() {
+ let range: Vec<&str> = bitmask.split('-').collect();
+ match range.len() {
+ 1 => {
+ let idx: usize = range[0].parse()?;
+ while idx >= bitmask_vec.len() {
+ bitmask_vec.grow(8, false);
+ }
+ bitmask_vec.set(adjust_index(idx), true);
+ }
+ 2 => {
+ let left_index = range[0].parse()?;
+ let right_index = range[1].parse()?;
+ while right_index >= bitmask_vec.len() {
+ bitmask_vec.grow(8, false);
+ }
+ for idx in left_index..=right_index {
+ bitmask_vec.set(adjust_index(idx), true);
+ }
+ }
+ _ => bail!("invalid bitmask str {}", bitmask_str),
+ }
+ }
+ let mut result_vec = bitmask_vec.to_bytes();
+ result_vec.reverse();
+
+ Ok(BitMask(result_vec))
+ }
+}
+
+#[inline(always)]
+fn adjust_index(idx: usize) -> usize {
+ idx / 8 * 8 + 7 - idx % 8
+}
+
+#[cfg(test)]
+mod tests {
+ use std::convert::TryInto;
+
+ use crate::cgroups::systemd::subsystem::cpuset::BitMask;
+
+ #[test]
+ fn test_bitmask_conversion() {
+ let cpus_vec: BitMask = "2-4".try_into().unwrap();
+ assert_eq!(vec![0b11100 as u8], cpus_vec.0);
+
+ let cpus_vec: BitMask = "1,7".try_into().unwrap();
+ assert_eq!(vec![0b10000010 as u8], cpus_vec.0);
+
+ let cpus_vec: BitMask = "0,2-3,7".try_into().unwrap();
+ assert_eq!(vec![0b10001101 as u8], cpus_vec.0);
+ }
+}
diff --git a/src/agent/rustjail/src/cgroups/systemd/subsystem/memory.rs b/src/agent/rustjail/src/cgroups/systemd/subsystem/memory.rs
new file mode 100644
index 000000000..e2ec5343c
--- /dev/null
+++ b/src/agent/rustjail/src/cgroups/systemd/subsystem/memory.rs
@@ -0,0 +1,117 @@
+// Copyright 2021-2022 Kata Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+use super::super::common::{CgroupHierarchy, Properties};
+
+use super::transformer::Transformer;
+
+use anyhow::{bail, Result};
+use oci::{LinuxMemory, LinuxResources};
+use zbus::zvariant::Value;
+
+pub struct Memory {}
+
+impl Transformer for Memory {
+ fn apply(
+ r: &LinuxResources,
+ properties: &mut Properties,
+ cgroup_hierarchy: &CgroupHierarchy,
+ _: &str,
+ ) -> Result<()> {
+ if let Some(memory_resources) = &r.memory {
+ match cgroup_hierarchy {
+ CgroupHierarchy::Legacy => Self::legacy_apply(memory_resources, properties)?,
+ CgroupHierarchy::Unified => Self::unified_apply(memory_resources, properties)?,
+ }
+ }
+
+ Ok(())
+ }
+}
+
+impl Memory {
+ // v1:
+ // memory.limit <-> MemoryLimit
+ fn legacy_apply(memory_resources: &LinuxMemory, properties: &mut Properties) -> Result<()> {
+ if let Some(limit) = memory_resources.limit {
+ let limit = match limit {
+ 1..=i64::MAX => limit as u64,
+ 0 => u64::MAX,
+ _ => bail!("invalid memory.limit"),
+ };
+ properties.push(("MemoryLimit", Value::U64(limit)));
+ }
+
+ Ok(())
+ }
+
+ // v2:
+ // memory.low <-> MemoryLow
+ // memory.max <-> MemoryMax
+ // memory.swap & memory.limit <-> MemorySwapMax
+ fn unified_apply(memory_resources: &LinuxMemory, properties: &mut Properties) -> Result<()> {
+ if let Some(limit) = memory_resources.limit {
+ let limit = match limit {
+ 1..=i64::MAX => limit as u64,
+ 0 => u64::MAX,
+ _ => bail!("invalid memory.limit: {}", limit),
+ };
+ properties.push(("MemoryMax", Value::U64(limit)));
+ }
+
+ if let Some(reservation) = memory_resources.reservation {
+ let reservation = match reservation {
+ 1..=i64::MAX => reservation as u64,
+ 0 => u64::MAX,
+ _ => bail!("invalid memory.reservation: {}", reservation),
+ };
+ properties.push(("MemoryLow", Value::U64(reservation)));
+ }
+
+ let swap = match memory_resources.swap {
+ Some(0) => u64::MAX,
+ Some(1..=i64::MAX) => match memory_resources.limit {
+ Some(1..=i64::MAX) => {
+ (memory_resources.limit.unwrap() - memory_resources.swap.unwrap()) as u64
+ }
+ _ => bail!("invalid memory.limit when memory.swap specified"),
+ },
+ None => u64::MAX,
+ _ => bail!("invalid memory.swap"),
+ };
+
+ properties.push(("MemorySwapMax", Value::U64(swap)));
+
+ Ok(())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::Memory;
+ use super::Properties;
+ use super::Value;
+
+ #[test]
+ fn test_unified_memory() {
+ let memory_resources = oci::LinuxMemory {
+ limit: Some(736870912),
+ reservation: Some(536870912),
+ swap: Some(536870912),
+ kernel: Some(0),
+ kernel_tcp: Some(0),
+ swappiness: Some(0),
+ disable_oom_killer: Some(false),
+ };
+ let mut properties: Properties = vec![];
+
+ assert_eq!(
+ true,
+ Memory::unified_apply(&memory_resources, &mut properties).is_ok()
+ );
+
+ assert_eq!(Value::U64(200000000), properties[2].1);
+ }
+}
diff --git a/src/agent/rustjail/src/cgroups/systemd/subsystem/mod.rs b/src/agent/rustjail/src/cgroups/systemd/subsystem/mod.rs
new file mode 100644
index 000000000..6810040a2
--- /dev/null
+++ b/src/agent/rustjail/src/cgroups/systemd/subsystem/mod.rs
@@ -0,0 +1,10 @@
+// Copyright 2021-2022 Kata Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+pub mod cpu;
+pub mod cpuset;
+pub mod memory;
+pub mod pids;
+pub mod transformer;
diff --git a/src/agent/rustjail/src/cgroups/systemd/subsystem/pids.rs b/src/agent/rustjail/src/cgroups/systemd/subsystem/pids.rs
new file mode 100644
index 000000000..7ff1ee7c6
--- /dev/null
+++ b/src/agent/rustjail/src/cgroups/systemd/subsystem/pids.rs
@@ -0,0 +1,60 @@
+// Copyright 2021-2022 Kata Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+use super::super::common::{CgroupHierarchy, Properties};
+
+use super::transformer::Transformer;
+
+use anyhow::Result;
+use oci::{LinuxPids, LinuxResources};
+use zbus::zvariant::Value;
+
+pub struct Pids {}
+
+impl Transformer for Pids {
+ fn apply(
+ r: &LinuxResources,
+ properties: &mut Properties,
+ _: &CgroupHierarchy,
+ _: &str,
+ ) -> Result<()> {
+ if let Some(pids_resources) = &r.pids {
+ Self::apply(pids_resources, properties)?;
+ }
+
+ Ok(())
+ }
+}
+
+// pids.limit <-> TasksMax
+impl Pids {
+ fn apply(pids_resources: &LinuxPids, properties: &mut Properties) -> Result<()> {
+ let limit = if pids_resources.limit > 0 {
+ pids_resources.limit as u64
+ } else {
+ u64::MAX
+ };
+
+ properties.push(("TasksMax", Value::U64(limit)));
+ Ok(())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::Pids;
+ use super::Properties;
+ use super::Value;
+
+ #[test]
+ fn test_subsystem_workflow() {
+ let pids_resources = oci::LinuxPids { limit: 0 };
+ let mut properties: Properties = vec![];
+
+ assert_eq!(true, Pids::apply(&pids_resources, &mut properties).is_ok());
+
+ assert_eq!(Value::U64(u64::MAX), properties[0].1);
+ }
+}
diff --git a/src/agent/rustjail/src/cgroups/systemd/subsystem/transformer.rs b/src/agent/rustjail/src/cgroups/systemd/subsystem/transformer.rs
new file mode 100644
index 000000000..952ed4dd2
--- /dev/null
+++ b/src/agent/rustjail/src/cgroups/systemd/subsystem/transformer.rs
@@ -0,0 +1,17 @@
+// Copyright 2021-2022 Kata Contributors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+use super::super::common::{CgroupHierarchy, Properties};
+use anyhow::Result;
+use oci::LinuxResources;
+
+pub trait Transformer {
+ fn apply(
+ r: &LinuxResources,
+ properties: &mut Properties,
+ cgroup_hierarchy: &CgroupHierarchy,
+ systemd_version: &str,
+ ) -> Result<()>;
+}
diff --git a/src/agent/rustjail/src/container.rs b/src/agent/rustjail/src/container.rs
index afa374bc2..f75b6e6d5 100644
--- a/src/agent/rustjail/src/container.rs
+++ b/src/agent/rustjail/src/container.rs
@@ -6,7 +6,7 @@
use anyhow::{anyhow, Context, Result};
use libc::pid_t;
use oci::{ContainerState, LinuxDevice, LinuxIdMapping};
-use oci::{Hook, Linux, LinuxNamespace, LinuxResources, Spec};
+use oci::{Linux, LinuxNamespace, LinuxResources, Spec};
use std::clone::Clone;
use std::ffi::CString;
use std::fmt::Display;
@@ -22,6 +22,7 @@ use crate::capabilities;
use crate::cgroups::fs::Manager as FsManager;
#[cfg(test)]
use crate::cgroups::mock::Manager as FsManager;
+use crate::cgroups::systemd::manager::Manager as SystemdManager;
use crate::cgroups::Manager;
#[cfg(feature = "standard-oci-runtime")]
use crate::console;
@@ -29,6 +30,7 @@ use crate::log_child;
use crate::process::Process;
#[cfg(feature = "seccomp")]
use crate::seccomp;
+use crate::selinux;
use crate::specconv::CreateOpts;
use crate::{mount, validator};
@@ -49,6 +51,7 @@ use std::os::unix::io::AsRawFd;
use protobuf::SingularPtrField;
use oci::State as OCIState;
+use regex::Regex;
use std::collections::HashMap;
use std::os::unix::io::FromRawFd;
use std::str::FromStr;
@@ -64,6 +67,9 @@ use rlimit::{setrlimit, Resource, Rlim};
use tokio::io::AsyncBufReadExt;
use tokio::sync::Mutex;
+use kata_sys_util::hooks::HookStates;
+use kata_sys_util::validate::valid_env;
+
pub const EXEC_FIFO_FILENAME: &str = "exec.fifo";
const INIT: &str = "INIT";
@@ -107,7 +113,6 @@ impl Default for ContainerStatus {
}
// We might want to change this to thiserror in the future
-const MissingCGroupManager: &str = "failed to get container's cgroup Manager";
const MissingLinux: &str = "no linux config";
const InvalidNamespace: &str = "invalid namespace type";
@@ -201,6 +206,8 @@ lazy_static! {
},
]
};
+
+ pub static ref SYSTEMD_CGROUP_PATH_FORMAT:Regex = Regex::new(r"^[\w\-.]*:[\w\-.]*:[\w\-.]*$").unwrap();
}
#[derive(Serialize, Deserialize, Debug)]
@@ -239,7 +246,7 @@ pub struct LinuxContainer {
pub id: String,
pub root: String,
pub config: Config,
- pub cgroup_manager: Option<FsManager>,
+ pub cgroup_manager: Box<dyn Manager + Send + Sync>,
pub init_process_pid: pid_t,
pub init_process_start_time: u64,
pub uid_map_path: String,
@@ -288,16 +295,11 @@ impl Container for LinuxContainer {
));
}
- if self.cgroup_manager.is_some() {
- self.cgroup_manager
- .as_ref()
- .unwrap()
- .freeze(FreezerState::Frozen)?;
+ self.cgroup_manager.as_ref().freeze(FreezerState::Frozen)?;
- self.status.transition(ContainerState::Paused);
- return Ok(());
- }
- Err(anyhow!(MissingCGroupManager))
+ self.status.transition(ContainerState::Paused);
+
+ Ok(())
}
fn resume(&mut self) -> Result<()> {
@@ -306,16 +308,11 @@ impl Container for LinuxContainer {
return Err(anyhow!("container status is: {:?}, not paused", status));
}
- if self.cgroup_manager.is_some() {
- self.cgroup_manager
- .as_ref()
- .unwrap()
- .freeze(FreezerState::Thawed)?;
+ self.cgroup_manager.as_ref().freeze(FreezerState::Thawed)?;
- self.status.transition(ContainerState::Running);
- return Ok(());
- }
- Err(anyhow!(MissingCGroupManager))
+ self.status.transition(ContainerState::Running);
+
+ Ok(())
}
}
@@ -390,7 +387,9 @@ fn do_init_child(cwfd: RawFd) -> Result<()> {
let buf = read_sync(crfd)?;
let cm_str = std::str::from_utf8(&buf)?;
- let cm: FsManager = serde_json::from_str(cm_str)?;
+ // deserialize cm_str into FsManager and SystemdManager separately
+ let fs_cm: Result<FsManager, serde_json::Error> = serde_json::from_str(cm_str);
+ let systemd_cm: Result<SystemdManager, serde_json::Error> = serde_json::from_str(cm_str);
#[cfg(feature = "standard-oci-runtime")]
let csocket_fd = console::setup_console_socket(&std::env::var(CONSOLE_SOCKET_FD)?)?;
@@ -531,6 +530,8 @@ fn do_init_child(cwfd: RawFd) -> Result<()> {
}
}
+ let selinux_enabled = selinux::is_enabled()?;
+
sched::unshare(to_new & !CloneFlags::CLONE_NEWUSER)?;
if userns {
@@ -548,7 +549,18 @@ fn do_init_child(cwfd: RawFd) -> Result<()> {
if to_new.contains(CloneFlags::CLONE_NEWNS) {
// setup rootfs
- mount::init_rootfs(cfd_log, &spec, &cm.paths, &cm.mounts, bind_device)?;
+ if let Ok(systemd_cm) = systemd_cm {
+ mount::init_rootfs(
+ cfd_log,
+ &spec,
+ &systemd_cm.paths,
+ &systemd_cm.mounts,
+ bind_device,
+ )?;
+ } else {
+ let fs_cm = fs_cm.unwrap();
+ mount::init_rootfs(cfd_log, &spec, &fs_cm.paths, &fs_cm.mounts, bind_device)?;
+ }
}
if init {
@@ -621,6 +633,18 @@ fn do_init_child(cwfd: RawFd) -> Result<()> {
capctl::prctl::set_no_new_privs().map_err(|_| anyhow!("cannot set no new privileges"))?;
}
+ // Set SELinux label
+ if !oci_process.selinux_label.is_empty() {
+ if !selinux_enabled {
+ return Err(anyhow!(
+ "SELinux label for the process is provided but SELinux is not enabled on the running kernel"
+ ));
+ }
+
+ log_child!(cfd_log, "Set SELinux label to the container process");
+ selinux::set_exec_label(&oci_process.selinux_label)?;
+ }
+
// Log unknown seccomp system calls in advance before the log file descriptor closes.
#[cfg(feature = "seccomp")]
if let Some(ref scmp) = linux.seccomp {
@@ -830,22 +854,17 @@ impl BaseContainer for LinuxContainer {
}
fn stats(&self) -> Result<StatsContainerResponse> {
- let mut r = StatsContainerResponse::default();
-
- if self.cgroup_manager.is_some() {
- r.cgroup_stats =
- SingularPtrField::some(self.cgroup_manager.as_ref().unwrap().get_stats()?);
- }
-
// what about network interface stats?
- Ok(r)
+ Ok(StatsContainerResponse {
+ cgroup_stats: SingularPtrField::some(self.cgroup_manager.as_ref().get_stats()?),
+ ..Default::default()
+ })
}
fn set(&mut self, r: LinuxResources) -> Result<()> {
- if self.cgroup_manager.is_some() {
- self.cgroup_manager.as_ref().unwrap().set(&r, true)?;
- }
+ self.cgroup_manager.as_ref().set(&r, true)?;
+
self.config
.spec
.as_mut()
@@ -1018,7 +1037,8 @@ impl BaseContainer for LinuxContainer {
&logger,
spec,
&p,
- self.cgroup_manager.as_ref().unwrap(),
+ self.cgroup_manager.as_ref(),
+ self.config.use_systemd_cgroup,
&st,
&mut pipe_w,
&mut pipe_r,
@@ -1081,12 +1101,14 @@ impl BaseContainer for LinuxContainer {
}
}
- if spec.hooks.is_some() {
- info!(self.logger, "poststop");
- let hooks = spec.hooks.as_ref().unwrap();
- for h in hooks.poststop.iter() {
- execute_hook(&self.logger, h, &st).await?;
- }
+ // guest Poststop hook
+ // * should be executed after the container is deleted but before the delete operation returns
+ // * the executable file is in agent namespace
+ // * should also be executed in agent namespace.
+ if let Some(hooks) = spec.hooks.as_ref() {
+ info!(self.logger, "guest Poststop hook");
+ let mut hook_states = HookStates::new();
+ hook_states.execute_hooks(&hooks.poststop, Some(st))?;
}
self.status.transition(ContainerState::Stopped);
@@ -1096,19 +1118,19 @@ impl BaseContainer for LinuxContainer {
)?;
fs::remove_dir_all(&self.root)?;
- if let Some(cgm) = self.cgroup_manager.as_mut() {
- // Kill all of the processes created in this container to prevent
- // the leak of some daemon process when this container shared pidns
- // with the sandbox.
- let pids = cgm.get_pids().context("get cgroup pids")?;
- for i in pids {
- if let Err(e) = signal::kill(Pid::from_raw(i), Signal::SIGKILL) {
- warn!(self.logger, "kill the process {} error: {:?}", i, e);
- }
+ let cgm = self.cgroup_manager.as_mut();
+ // Kill all of the processes created in this container to prevent
+ // the leak of some daemon process when this container shared pidns
+ // with the sandbox.
+ let pids = cgm.get_pids().context("get cgroup pids")?;
+ for i in pids {
+ if let Err(e) = signal::kill(Pid::from_raw(i), Signal::SIGKILL) {
+ warn!(self.logger, "kill the process {} error: {:?}", i, e);
}
-
- cgm.destroy().context("destroy cgroups")?;
}
+
+ cgm.destroy().context("destroy cgroups")?;
+
Ok(())
}
@@ -1132,16 +1154,14 @@ impl BaseContainer for LinuxContainer {
.ok_or_else(|| anyhow!("OCI spec was not found"))?;
let st = self.oci_state()?;
- // run poststart hook
- if spec.hooks.is_some() {
- info!(self.logger, "poststart hook");
- let hooks = spec
- .hooks
- .as_ref()
- .ok_or_else(|| anyhow!("OCI hooks were not found"))?;
- for h in hooks.poststart.iter() {
- execute_hook(&self.logger, h, &st).await?;
- }
+ // guest Poststart hook
+ // * should be executed after the container is started but before the delete operation returns
+ // * the executable file is in agent namespace
+ // * should also be executed in agent namespace.
+ if let Some(hooks) = spec.hooks.as_ref() {
+ info!(self.logger, "guest Poststart hook");
+ let mut hook_states = HookStates::new();
+ hook_states.execute_hooks(&hooks.poststart, Some(st))?;
}
unistd::close(fd)?;
@@ -1280,11 +1300,13 @@ pub fn setup_child_logger(fd: RawFd, child_logger: Logger) -> tokio::task::JoinH
})
}
+#[allow(clippy::too_many_arguments)]
async fn join_namespaces(
logger: &Logger,
spec: &Spec,
p: &Process,
- cm: &FsManager,
+ cm: &(dyn Manager + Send + Sync),
+ use_systemd_cgroup: bool,
st: &OCIState,
pipe_w: &mut PipeStream,
pipe_r: &mut PipeStream,
@@ -1311,7 +1333,11 @@ async fn join_namespaces(
info!(logger, "wait child received oci process");
read_async(pipe_r).await?;
- let cm_str = serde_json::to_string(cm)?;
+ let cm_str = if use_systemd_cgroup {
+ serde_json::to_string(cm.as_any()?.downcast_ref::<SystemdManager>().unwrap())
+ } else {
+ serde_json::to_string(cm.as_any()?.downcast_ref::<FsManager>().unwrap())
+ }?;
write_async(pipe_w, SYNC_DATA, cm_str.as_str()).await?;
// wait child setup user namespace
@@ -1334,15 +1360,18 @@ async fn join_namespaces(
}
// apply cgroups
- if p.init && res.is_some() {
- info!(logger, "apply cgroups!");
- cm.set(res.unwrap(), false)?;
- }
-
+ // For FsManger, it's no matter about the order of apply and set.
+ // For SystemdManger, apply must be precede set because we can only create a systemd unit with specific processes(pids).
if res.is_some() {
+ info!(logger, "apply processes to cgroups!");
cm.apply(p.pid)?;
}
+ if p.init && res.is_some() {
+ info!(logger, "set properties to cgroups!");
+ cm.set(res.unwrap(), false)?;
+ }
+
info!(logger, "notify child to continue");
// notify child to continue
write_async(pipe_w, SYNC_SUCCESS, "").await?;
@@ -1353,13 +1382,14 @@ async fn join_namespaces(
info!(logger, "get ready to run prestart hook!");
- // run prestart hook
- if spec.hooks.is_some() {
- info!(logger, "prestart hook");
- let hooks = spec.hooks.as_ref().unwrap();
- for h in hooks.prestart.iter() {
- execute_hook(&logger, h, st).await?;
- }
+ // guest Prestart hook
+ // * should be executed during the start operation, and before the container command is executed
+ // * the executable file is in agent namespace
+ // * should also be executed in agent namespace.
+ if let Some(hooks) = spec.hooks.as_ref() {
+ info!(logger, "guest Prestart hook");
+ let mut hook_states = HookStates::new();
+ hook_states.execute_hooks(&hooks.prestart, Some(st.clone()))?;
}
// notify child run prestart hooks completed
@@ -1419,7 +1449,7 @@ impl LinuxContainer {
pub fn new<T: Into<String> + Display + Clone>(
id: T,
base: T,
- config: Config,
+ mut config: Config,
logger: &Logger,
) -> Result<Self> {
let base = base.into();
@@ -1448,24 +1478,46 @@ impl LinuxContainer {
let linux = spec.linux.as_ref().unwrap();
- let cpath = if linux.cgroups_path.is_empty() {
- format!("/{}", id.as_str())
+ // determine which cgroup driver to take and then assign to config.use_systemd_cgroup
+ // systemd: "[slice]:[prefix]:[name]"
+ // fs: "/path_a/path_b"
+ let cpath = if SYSTEMD_CGROUP_PATH_FORMAT.is_match(linux.cgroups_path.as_str()) {
+ config.use_systemd_cgroup = true;
+ if linux.cgroups_path.len() == 2 {
+ format!("system.slice:kata_agent:{}", id.as_str())
+ } else {
+ linux.cgroups_path.clone()
+ }
} else {
- linux.cgroups_path.clone()
+ config.use_systemd_cgroup = false;
+ if linux.cgroups_path.is_empty() {
+ format!("/{}", id.as_str())
+ } else {
+ linux.cgroups_path.clone()
+ }
};
- let cgroup_manager = FsManager::new(cpath.as_str()).map_err(|e| {
- anyhow!(format!(
- "fail to create cgroup manager with path {}: {:}",
- cpath, e
- ))
- })?;
+ let cgroup_manager: Box<dyn Manager + Send + Sync> = if config.use_systemd_cgroup {
+ Box::new(SystemdManager::new(cpath.as_str()).map_err(|e| {
+ anyhow!(format!(
+ "fail to create cgroup manager with path {}: {:}",
+ cpath, e
+ ))
+ })?)
+ } else {
+ Box::new(FsManager::new(cpath.as_str()).map_err(|e| {
+ anyhow!(format!(
+ "fail to create cgroup manager with path {}: {:}",
+ cpath, e
+ ))
+ })?)
+ };
info!(logger, "new cgroup_manager {:?}", &cgroup_manager);
Ok(LinuxContainer {
id: id.clone(),
root,
- cgroup_manager: Some(cgroup_manager),
+ cgroup_manager,
status: ContainerStatus::new(),
uid_map_path: String::from(""),
gid_map_path: "".to_string(),
@@ -1517,143 +1569,6 @@ fn set_sysctls(sysctls: &HashMap<String, String>) -> Result<()> {
Ok(())
}
-use std::process::Stdio;
-use std::time::Duration;
-use tokio::io::{AsyncReadExt, AsyncWriteExt};
-
-pub async fn execute_hook(logger: &Logger, h: &Hook, st: &OCIState) -> Result<()> {
- let logger = logger.new(o!("action" => "execute-hook"));
-
- let binary = PathBuf::from(h.path.as_str());
- let path = binary.canonicalize()?;
- if !path.exists() {
- return Err(anyhow!("Path {:?} does not exist", path));
- }
-
- let mut args = h.args.clone();
- // the hook.args[0] is the hook binary name which shouldn't be included
- // in the Command.args
- if args.len() > 1 {
- args.remove(0);
- }
-
- // all invalid envs will be omitted, only valid envs will be passed to hook.
- let env: HashMap<&str, &str> = h.env.iter().filter_map(|e| valid_env(e)).collect();
-
- // Avoid the exit signal to be reaped by the global reaper.
- let _wait_locker = WAIT_PID_LOCKER.lock().await;
- let mut child = tokio::process::Command::new(path)
- .args(args.iter())
- .envs(env.iter())
- .kill_on_drop(true)
- .stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .stderr(Stdio::piped())
- .spawn()?;
-
- // default timeout 10s
- let mut timeout: u64 = 10;
-
- // if timeout is set if hook, then use the specified value
- if let Some(t) = h.timeout {
- if t > 0 {
- timeout = t as u64;
- }
- }
-
- let state = serde_json::to_string(st)?;
- let path = h.path.clone();
-
- let join_handle = tokio::spawn(async move {
- if let Some(mut stdin) = child.stdin.take() {
- match stdin.write_all(state.as_bytes()).await {
- Ok(_) => {}
- Err(e) => {
- info!(logger, "write to child stdin failed: {:?}", e);
- }
- }
- }
-
- // read something from stdout and stderr for debug
- if let Some(stdout) = child.stdout.as_mut() {
- let mut out = String::new();
- match stdout.read_to_string(&mut out).await {
- Ok(_) => {
- info!(logger, "child stdout: {}", out.as_str());
- }
- Err(e) => {
- info!(logger, "read from child stdout failed: {:?}", e);
- }
- }
- }
-
- let mut err = String::new();
- if let Some(stderr) = child.stderr.as_mut() {
- match stderr.read_to_string(&mut err).await {
- Ok(_) => {
- info!(logger, "child stderr: {}", err.as_str());
- }
- Err(e) => {
- info!(logger, "read from child stderr failed: {:?}", e);
- }
- }
- }
-
- match child.wait().await {
- Ok(exit) => {
- let code = exit
- .code()
- .ok_or_else(|| anyhow!("hook exit status has no status code"))?;
-
- if code != 0 {
- error!(
- logger,
- "hook {} exit status is {}, error message is {}", &path, code, err
- );
- return Err(anyhow!(nix::Error::UnknownErrno));
- }
-
- debug!(logger, "hook {} exit status is 0", &path);
- Ok(())
- }
- Err(e) => Err(anyhow!(
- "wait child error: {} {}",
- e,
- e.raw_os_error().unwrap()
- )),
- }
- });
-
- match tokio::time::timeout(Duration::new(timeout, 0), join_handle).await {
- Ok(r) => r.unwrap(),
- Err(_) => Err(anyhow!(nix::Error::ETIMEDOUT)),
- }
-}
-
-// valid environment variables according to https://doc.rust-lang.org/std/env/fn.set_var.html#panics
-fn valid_env(e: &str) -> Option<(&str, &str)> {
- // wherther key or value will contain NULL char.
- if e.as_bytes().contains(&b'\0') {
- return None;
- }
-
- let v: Vec<&str> = e.splitn(2, '=').collect();
-
- // key can't hold an `equal` sign, but value can
- if v.len() != 2 {
- return None;
- }
-
- let (key, value) = (v[0].trim(), v[1].trim());
-
- // key can't be empty
- if key.is_empty() {
- return None;
- }
-
- Some((key, value))
-}
-
#[cfg(test)]
mod tests {
use super::*;
@@ -1664,7 +1579,6 @@ mod tests {
use std::os::unix::io::AsRawFd;
use tempfile::tempdir;
use test_utils::skip_if_not_root;
- use tokio::process::Command;
macro_rules! sl {
() => {
@@ -1672,113 +1586,6 @@ mod tests {
};
}
- async fn which(cmd: &str) -> String {
- let output: std::process::Output = Command::new("which")
- .arg(cmd)
- .output()
- .await
- .expect("which command failed to run");
-
- match String::from_utf8(output.stdout) {
- Ok(v) => v.trim_end_matches('\n').to_string(),
- Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
- }
- }
-
- #[tokio::test]
- async fn test_execute_hook() {
- let temp_file = "/tmp/test_execute_hook";
-
- let touch = which("touch").await;
-
- defer!(fs::remove_file(temp_file).unwrap(););
- let invalid_str = vec![97, b'\0', 98];
- let invalid_string = std::str::from_utf8(&invalid_str).unwrap();
- let invalid_env = format!("{}=value", invalid_string);
-
- execute_hook(
- &slog_scope::logger(),
- &Hook {
- path: touch,
- args: vec!["touch".to_string(), temp_file.to_string()],
- env: vec![invalid_env],
- timeout: Some(10),
- },
- &OCIState {
- version: "1.2.3".to_string(),
- id: "321".to_string(),
- status: ContainerState::Running,
- pid: 2,
- bundle: "".to_string(),
- annotations: Default::default(),
- },
- )
- .await
- .unwrap();
-
- assert_eq!(Path::new(&temp_file).exists(), true);
- }
-
- #[tokio::test]
- async fn test_execute_hook_with_error() {
- let ls = which("ls").await;
-
- let res = execute_hook(
- &slog_scope::logger(),
- &Hook {
- path: ls,
- args: vec!["ls".to_string(), "/tmp/not-exist".to_string()],
- env: vec![],
- timeout: None,
- },
- &OCIState {
- version: "1.2.3".to_string(),
- id: "321".to_string(),
- status: ContainerState::Running,
- pid: 2,
- bundle: "".to_string(),
- annotations: Default::default(),
- },
- )
- .await;
-
- let expected_err = nix::Error::UnknownErrno;
- assert_eq!(
- res.unwrap_err().downcast::<nix::Error>().unwrap(),
- expected_err
- );
- }
-
- #[tokio::test]
- async fn test_execute_hook_with_timeout() {
- let sleep = which("sleep").await;
-
- let res = execute_hook(
- &slog_scope::logger(),
- &Hook {
- path: sleep,
- args: vec!["sleep".to_string(), "2".to_string()],
- env: vec![],
- timeout: Some(1),
- },
- &OCIState {
- version: "1.2.3".to_string(),
- id: "321".to_string(),
- status: ContainerState::Running,
- pid: 2,
- bundle: "".to_string(),
- annotations: Default::default(),
- },
- )
- .await;
-
- let expected_err = nix::Error::ETIMEDOUT;
- assert_eq!(
- res.unwrap_err().downcast::<nix::Error>().unwrap(),
- expected_err
- );
- }
-
#[test]
fn test_status_transtition() {
let mut status = ContainerStatus::new();
@@ -1931,20 +1738,12 @@ mod tests {
assert!(format!("{:?}", ret).contains("failed to pause container"))
}
- #[test]
- fn test_linuxcontainer_pause_cgroupmgr_is_none() {
- let ret = new_linux_container_and_then(|mut c: LinuxContainer| {
- c.cgroup_manager = None;
- c.pause().map_err(|e| anyhow!(e))
- });
-
- assert!(ret.is_err(), "Expecting error, Got {:?}", ret);
- }
-
#[test]
fn test_linuxcontainer_pause() {
let ret = new_linux_container_and_then(|mut c: LinuxContainer| {
- c.cgroup_manager = FsManager::new("").ok();
+ c.cgroup_manager = Box::new(FsManager::new("").map_err(|e| {
+ anyhow!(format!("fail to create cgroup manager with path: {:}", e))
+ })?);
c.pause().map_err(|e| anyhow!(e))
});
@@ -1963,21 +1762,12 @@ mod tests {
assert!(format!("{:?}", ret).contains("not paused"))
}
- #[test]
- fn test_linuxcontainer_resume_cgroupmgr_is_none() {
- let ret = new_linux_container_and_then(|mut c: LinuxContainer| {
- c.status.transition(ContainerState::Paused);
- c.cgroup_manager = None;
- c.resume().map_err(|e| anyhow!(e))
- });
-
- assert!(ret.is_err(), "Expecting error, Got {:?}", ret);
- }
-
#[test]
fn test_linuxcontainer_resume() {
let ret = new_linux_container_and_then(|mut c: LinuxContainer| {
- c.cgroup_manager = FsManager::new("").ok();
+ c.cgroup_manager = Box::new(FsManager::new("").map_err(|e| {
+ anyhow!(format!("fail to create cgroup manager with path: {:}", e))
+ })?);
// Change status to paused, this way we can resume it
c.status.transition(ContainerState::Paused);
c.resume().map_err(|e| anyhow!(e))
@@ -2110,49 +1900,4 @@ mod tests {
let ret = do_init_child(std::io::stdin().as_raw_fd());
assert!(ret.is_err(), "Expecting Err, Got {:?}", ret);
}
-
- #[test]
- fn test_valid_env() {
- let env = valid_env("a=b=c");
- assert_eq!(Some(("a", "b=c")), env);
-
- let env = valid_env("a=b");
- assert_eq!(Some(("a", "b")), env);
- let env = valid_env("a =b");
- assert_eq!(Some(("a", "b")), env);
-
- let env = valid_env(" a =b");
- assert_eq!(Some(("a", "b")), env);
-
- let env = valid_env("a= b");
- assert_eq!(Some(("a", "b")), env);
-
- let env = valid_env("a=b ");
- assert_eq!(Some(("a", "b")), env);
- let env = valid_env("a=b c ");
- assert_eq!(Some(("a", "b c")), env);
-
- let env = valid_env("=b");
- assert_eq!(None, env);
-
- let env = valid_env("a=");
- assert_eq!(Some(("a", "")), env);
-
- let env = valid_env("a==");
- assert_eq!(Some(("a", "=")), env);
-
- let env = valid_env("a");
- assert_eq!(None, env);
-
- let invalid_str = vec![97, b'\0', 98];
- let invalid_string = std::str::from_utf8(&invalid_str).unwrap();
-
- let invalid_env = format!("{}=value", invalid_string);
- let env = valid_env(&invalid_env);
- assert_eq!(None, env);
-
- let invalid_env = format!("key={}", invalid_string);
- let env = valid_env(&invalid_env);
- assert_eq!(None, env);
- }
}
diff --git a/src/agent/rustjail/src/lib.rs b/src/agent/rustjail/src/lib.rs
index fb51d9f39..1c757fd6b 100644
--- a/src/agent/rustjail/src/lib.rs
+++ b/src/agent/rustjail/src/lib.rs
@@ -38,6 +38,7 @@ pub mod pipestream;
pub mod process;
#[cfg(feature = "seccomp")]
pub mod seccomp;
+pub mod selinux;
pub mod specconv;
pub mod sync;
pub mod sync_with_async;
@@ -236,6 +237,12 @@ pub fn resources_grpc_to_oci(res: &grpc::LinuxResources) -> oci::LinuxResources
let devices = {
let mut d = Vec::new();
for dev in res.Devices.iter() {
+ let dev_type = if dev.Type.is_empty() {
+ None
+ } else {
+ Some(dev.Type.clone())
+ };
+
let major = if dev.Major == -1 {
None
} else {
@@ -249,7 +256,7 @@ pub fn resources_grpc_to_oci(res: &grpc::LinuxResources) -> oci::LinuxResources
};
d.push(oci::LinuxDeviceCgroup {
allow: dev.Allow,
- r#type: dev.Type.clone(),
+ r#type: dev_type,
major,
minor,
access: dev.Access.clone(),
diff --git a/src/agent/rustjail/src/mount.rs b/src/agent/rustjail/src/mount.rs
index d3f87a8b4..76922024d 100644
--- a/src/agent/rustjail/src/mount.rs
+++ b/src/agent/rustjail/src/mount.rs
@@ -25,6 +25,7 @@ use std::fs::File;
use std::io::{BufRead, BufReader};
use crate::container::DEFAULT_DEVICES;
+use crate::selinux;
use crate::sync::write_count;
use std::string::ToString;
@@ -181,6 +182,8 @@ pub fn init_rootfs(
None => flags |= MsFlags::MS_SLAVE,
}
+ let label = &linux.mount_label;
+
let root = spec
.root
.as_ref()
@@ -244,7 +247,7 @@ pub fn init_rootfs(
}
}
- mount_from(cfd_log, m, rootfs, flags, &data, "")?;
+ mount_from(cfd_log, m, rootfs, flags, &data, label)?;
// bind mount won't change mount options, we need remount to make mount options
// effective.
// first check that we have non-default options required before attempting a
@@ -524,7 +527,6 @@ pub fn pivot_rootfs<P: ?Sized + NixPath + std::fmt::Debug>(path: &P) -> Result<(
fn rootfs_parent_mount_private(path: &str) -> Result<()> {
let mount_infos = parse_mount_table(MOUNTINFO_PATH)?;
-
let mut max_len = 0;
let mut mount_point = String::from("");
let mut options = String::from("");
@@ -767,9 +769,9 @@ fn mount_from(
rootfs: &str,
flags: MsFlags,
data: &str,
- _label: &str,
+ label: &str,
) -> Result<()> {
- let d = String::from(data);
+ let mut d = String::from(data);
let dest = secure_join(rootfs, &m.destination);
let src = if m.r#type.as_str() == "bind" {
@@ -780,7 +782,7 @@ fn mount_from(
Path::new(&dest).parent().unwrap()
};
- fs::create_dir_all(&dir).map_err(|e| {
+ fs::create_dir_all(dir).map_err(|e| {
log_child!(
cfd_log,
"create dir {}: {}",
@@ -822,6 +824,37 @@ fn mount_from(
e
})?;
+ // Set the SELinux context for the mounts
+ let mut use_xattr = false;
+ if !label.is_empty() {
+ if selinux::is_enabled()? {
+ let device = Path::new(&m.source)
+ .file_name()
+ .ok_or_else(|| anyhow!("invalid device source path: {}", &m.source))?
+ .to_str()
+ .ok_or_else(|| anyhow!("failed to convert device source path: {}", &m.source))?;
+
+ match device {
+ // SELinux does not support labeling of /proc or /sys
+ "proc" | "sysfs" => (),
+ // SELinux does not support mount labeling against /dev/mqueue,
+ // so we use setxattr instead
+ "mqueue" => {
+ use_xattr = true;
+ }
+ _ => {
+ log_child!(cfd_log, "add SELinux mount label to {}", dest.as_str());
+ selinux::add_mount_label(&mut d, label);
+ }
+ }
+ } else {
+ log_child!(
+ cfd_log,
+ "SELinux label for the mount is provided but SELinux is not enabled on the running kernel"
+ );
+ }
+ }
+
mount(
Some(src.as_str()),
dest.as_str(),
@@ -834,6 +867,10 @@ fn mount_from(
e
})?;
+ if !label.is_empty() && selinux::is_enabled()? && use_xattr {
+ xattr::set(dest.as_str(), "security.selinux", label.as_bytes())?;
+ }
+
if flags.contains(MsFlags::MS_BIND)
&& flags.intersects(
!(MsFlags::MS_REC
diff --git a/src/agent/rustjail/src/seccomp.rs b/src/agent/rustjail/src/seccomp.rs
index d8edbcd00..4b0c89515 100644
--- a/src/agent/rustjail/src/seccomp.rs
+++ b/src/agent/rustjail/src/seccomp.rs
@@ -63,7 +63,7 @@ pub fn get_unknown_syscalls(scmp: &LinuxSeccomp) -> Option<Vec<String>> {
// init_seccomp creates a seccomp filter and loads it for the current process
// including all the child processes.
pub fn init_seccomp(scmp: &LinuxSeccomp) -> Result<()> {
- let def_action = ScmpAction::from_str(scmp.default_action.as_str(), Some(libc::EPERM as i32))?;
+ let def_action = ScmpAction::from_str(scmp.default_action.as_str(), Some(libc::EPERM))?;
// Create a new filter context
let mut filter = ScmpFilterContext::new_filter(def_action)?;
diff --git a/src/agent/rustjail/src/selinux.rs b/src/agent/rustjail/src/selinux.rs
new file mode 100644
index 000000000..5a647e3cc
--- /dev/null
+++ b/src/agent/rustjail/src/selinux.rs
@@ -0,0 +1,80 @@
+// Copyright 2022 Sony Group Corporation
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+use anyhow::{Context, Result};
+use nix::unistd::gettid;
+use std::fs::{self, OpenOptions};
+use std::io::prelude::*;
+use std::path::Path;
+
+pub fn is_enabled() -> Result<bool> {
+ let buf = fs::read_to_string("/proc/mounts")?;
+ let enabled = buf.contains("selinuxfs");
+
+ Ok(enabled)
+}
+
+pub fn add_mount_label(data: &mut String, label: &str) {
+ if data.is_empty() {
+ let context = format!("context=\"{}\"", label);
+ data.push_str(&context);
+ } else {
+ let context = format!(",context=\"{}\"", label);
+ data.push_str(&context);
+ }
+}
+
+pub fn set_exec_label(label: &str) -> Result<()> {
+ let mut attr_path = Path::new("/proc/thread-self/attr/exec").to_path_buf();
+ if !attr_path.exists() {
+ // Fall back to the old convention
+ attr_path = Path::new("/proc/self/task")
+ .join(gettid().to_string())
+ .join("attr/exec")
+ }
+
+ let mut file = OpenOptions::new()
+ .write(true)
+ .truncate(true)
+ .open(attr_path)?;
+ file.write_all(label.as_bytes())
+ .with_context(|| "failed to apply SELinux label")?;
+
+ Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ const TEST_LABEL: &str = "system_u:system_r:unconfined_t:s0";
+
+ #[test]
+ fn test_is_enabled() {
+ let ret = is_enabled();
+ assert!(ret.is_ok(), "Expecting Ok, Got {:?}", ret);
+ }
+
+ #[test]
+ fn test_add_mount_label() {
+ let mut data = String::new();
+ add_mount_label(&mut data, TEST_LABEL);
+ assert_eq!(data, format!("context=\"{}\"", TEST_LABEL));
+
+ let mut data = String::from("defaults");
+ add_mount_label(&mut data, TEST_LABEL);
+ assert_eq!(data, format!("defaults,context=\"{}\"", TEST_LABEL));
+ }
+
+ #[test]
+ fn test_set_exec_label() {
+ let ret = set_exec_label(TEST_LABEL);
+ if is_enabled().unwrap() {
+ assert!(ret.is_ok(), "Expecting Ok, Got {:?}", ret);
+ } else {
+ assert!(ret.is_err(), "Expecting error, Got {:?}", ret);
+ }
+ }
+}
diff --git a/src/agent/rustjail/src/validator.rs b/src/agent/rustjail/src/validator.rs
index aea0f8f06..4955fbf46 100644
--- a/src/agent/rustjail/src/validator.rs
+++ b/src/agent/rustjail/src/validator.rs
@@ -6,6 +6,7 @@
use crate::container::Config;
use anyhow::{anyhow, Context, Result};
use oci::{Linux, LinuxIdMapping, LinuxNamespace, Spec};
+use regex::Regex;
use std::collections::HashMap;
use std::path::{Component, PathBuf};
@@ -86,6 +87,23 @@ fn hostname(oci: &Spec) -> Result<()> {
fn security(oci: &Spec) -> Result<()> {
let linux = get_linux(oci)?;
+ let label_pattern = r".*_u:.*_r:.*_t:s[0-9]|1[0-5].*";
+ let label_regex = Regex::new(label_pattern)?;
+
+ if let Some(ref process) = oci.process {
+ if !process.selinux_label.is_empty() && !label_regex.is_match(&process.selinux_label) {
+ return Err(anyhow!(
+ "SELinux label for the process is invalid format: {}",
+ &process.selinux_label
+ ));
+ }
+ }
+ if !linux.mount_label.is_empty() && !label_regex.is_match(&linux.mount_label) {
+ return Err(anyhow!(
+ "SELinux label for the mount is invalid format: {}",
+ &linux.mount_label
+ ));
+ }
if linux.masked_paths.is_empty() && linux.readonly_paths.is_empty() {
return Ok(());
@@ -95,8 +113,6 @@ fn security(oci: &Spec) -> Result<()> {
return Err(anyhow!("Linux namespace does not contain mount"));
}
- // don't care about selinux at present
-
Ok(())
}
@@ -285,7 +301,7 @@ pub fn validate(conf: &Config) -> Result<()> {
#[cfg(test)]
mod tests {
use super::*;
- use oci::Mount;
+ use oci::{Mount, Process};
#[test]
fn test_namespace() {
@@ -388,6 +404,29 @@ mod tests {
];
spec.linux = Some(linux);
security(&spec).unwrap();
+
+ // SELinux
+ let valid_label = "system_u:system_r:container_t:s0:c123,c456";
+ let mut process = Process::default();
+ process.selinux_label = valid_label.to_string();
+ spec.process = Some(process);
+ security(&spec).unwrap();
+
+ let mut linux = Linux::default();
+ linux.mount_label = valid_label.to_string();
+ spec.linux = Some(linux);
+ security(&spec).unwrap();
+
+ let invalid_label = "system_u:system_r:container_t";
+ let mut process = Process::default();
+ process.selinux_label = invalid_label.to_string();
+ spec.process = Some(process);
+ security(&spec).unwrap_err();
+
+ let mut linux = Linux::default();
+ linux.mount_label = invalid_label.to_string();
+ spec.linux = Some(linux);
+ security(&spec).unwrap_err();
}
#[test]
diff --git a/src/agent/src/config.rs b/src/agent/src/config.rs
index 15bef0dc8..ac580384f 100644
--- a/src/agent/src/config.rs
+++ b/src/agent/src/config.rs
@@ -11,6 +11,7 @@ use std::fs;
use std::str::FromStr;
use std::time;
use tracing::instrument;
+use url::Url;
use kata_types::config::default::DEFAULT_AGENT_VSOCK_PORT;
@@ -25,6 +26,12 @@ const LOG_VPORT_OPTION: &str = "agent.log_vport";
const CONTAINER_PIPE_SIZE_OPTION: &str = "agent.container_pipe_size";
const UNIFIED_CGROUP_HIERARCHY_OPTION: &str = "agent.unified_cgroup_hierarchy";
const CONFIG_FILE: &str = "agent.config_file";
+const CONTAINER_POLICY_FILE: &str = "agent.container_policy_file";
+const AA_KBC_PARAMS: &str = "agent.aa_kbc_params";
+const HTTPS_PROXY: &str = "agent.https_proxy";
+const NO_PROXY: &str = "agent.no_proxy";
+const ENABLE_DATA_INTEGRITY: &str = "agent.data_integrity";
+const ENABLE_SIGNATURE_VERIFICATION: &str = "agent.enable_signature_verification";
const DEFAULT_LOG_LEVEL: slog::Level = slog::Level::Info;
const DEFAULT_HOTPLUG_TIMEOUT: time::Duration = time::Duration::from_secs(3);
@@ -52,6 +59,11 @@ const ERR_INVALID_CONTAINER_PIPE_SIZE_PARAM: &str = "unable to parse container p
const ERR_INVALID_CONTAINER_PIPE_SIZE_KEY: &str = "invalid container pipe size key name";
const ERR_INVALID_CONTAINER_PIPE_NEGATIVE: &str = "container pipe size should not be negative";
+const ERR_INVALID_CONTAINER_POLICY_PATH_VALUE: &str = "invalid container_policy_file value";
+const ERR_INVALID_CONTAINER_POLICY_PATH_KEY: &str = "invalid container_policy_file key";
+const ERR_INVALID_CONTAINER_POLICY_ABSOLUTE: &str =
+ "container_policy_file path must be an absolute file path";
+
#[derive(Debug, Default, Deserialize)]
pub struct EndpointsConfig {
pub allowed: Vec<String>,
@@ -77,6 +89,12 @@ pub struct AgentConfig {
pub tracing: bool,
pub endpoints: AgentEndpoints,
pub supports_seccomp: bool,
+ pub container_policy_path: String,
+ pub aa_kbc_params: String,
+ pub https_proxy: String,
+ pub no_proxy: String,
+ pub data_integrity: bool,
+ pub enable_signature_verification: bool,
}
#[derive(Debug, Deserialize)]
@@ -92,6 +110,12 @@ pub struct AgentConfigBuilder {
pub unified_cgroup_hierarchy: Option<bool>,
pub tracing: Option<bool>,
pub endpoints: Option<EndpointsConfig>,
+ pub container_policy_path: Option<String>,
+ pub aa_kbc_params: Option<String>,
+ pub https_proxy: Option<String>,
+ pub no_proxy: Option<String>,
+ pub data_integrity: Option<bool>,
+ pub enable_signature_verification: Option<bool>,
}
macro_rules! config_override {
@@ -153,6 +177,12 @@ impl Default for AgentConfig {
tracing: false,
endpoints: Default::default(),
supports_seccomp: rpc::have_seccomp(),
+ container_policy_path: String::from(""),
+ aa_kbc_params: String::from(""),
+ https_proxy: String::from(""),
+ no_proxy: String::from(""),
+ data_integrity: false,
+ enable_signature_verification: true,
}
}
}
@@ -181,6 +211,16 @@ impl FromStr for AgentConfig {
config_override!(agent_config_builder, agent_config, server_addr);
config_override!(agent_config_builder, agent_config, unified_cgroup_hierarchy);
config_override!(agent_config_builder, agent_config, tracing);
+ config_override!(agent_config_builder, agent_config, container_policy_path);
+ config_override!(agent_config_builder, agent_config, aa_kbc_params);
+ config_override!(agent_config_builder, agent_config, https_proxy);
+ config_override!(agent_config_builder, agent_config, no_proxy);
+ config_override!(agent_config_builder, agent_config, data_integrity);
+ config_override!(
+ agent_config_builder,
+ agent_config,
+ enable_signature_verification
+ );
// Populate the allowed endpoints hash set, if we got any from the config file.
if let Some(endpoints) = agent_config_builder.endpoints {
@@ -209,6 +249,10 @@ impl AgentConfig {
let mut config: AgentConfig = Default::default();
let cmdline = fs::read_to_string(file)?;
let params: Vec<&str> = cmdline.split_ascii_whitespace().collect();
+
+ let mut using_config_file = false;
+ // Check if there is config file before parsing params that might
+ // override values from the config file.
for param in params.iter() {
// If we get a configuration file path from the command line, we
// generate our config from it.
@@ -216,9 +260,13 @@ impl AgentConfig {
// or if it can't be parsed properly.
if param.starts_with(format!("{}=", CONFIG_FILE).as_str()) {
let config_file = get_string_value(param)?;
- return AgentConfig::from_config_file(&config_file);
+ config = AgentConfig::from_config_file(&config_file)?;
+ using_config_file = true;
+ break;
}
+ }
+ for param in params.iter() {
// parse cmdline flags
parse_cmdline_param!(param, DEBUG_CONSOLE_FLAG, config.debug_console);
parse_cmdline_param!(param, DEV_MODE_FLAG, config.dev_mode);
@@ -278,6 +326,30 @@ impl AgentConfig {
config.unified_cgroup_hierarchy,
get_bool_value
);
+
+ parse_cmdline_param!(
+ param,
+ CONTAINER_POLICY_FILE,
+ config.container_policy_path,
+ get_container_policy_path_value
+ );
+
+ parse_cmdline_param!(param, AA_KBC_PARAMS, config.aa_kbc_params, get_string_value);
+ parse_cmdline_param!(param, HTTPS_PROXY, config.https_proxy, get_url_value);
+ parse_cmdline_param!(param, NO_PROXY, config.no_proxy, get_string_value);
+ parse_cmdline_param!(
+ param,
+ ENABLE_DATA_INTEGRITY,
+ config.data_integrity,
+ get_bool_value
+ );
+
+ parse_cmdline_param!(
+ param,
+ ENABLE_SIGNATURE_VERIFICATION,
+ config.enable_signature_verification,
+ get_bool_value
+ );
}
if let Ok(addr) = env::var(SERVER_ADDR_ENV_VAR) {
@@ -297,7 +369,9 @@ impl AgentConfig {
}
// We did not get a configuration file: allow all endpoints.
- config.endpoints.all_allowed = true;
+ if !using_config_file {
+ config.endpoints.all_allowed = true;
+ }
Ok(config)
}
@@ -431,6 +505,35 @@ fn get_container_pipe_size(param: &str) -> Result<i32> {
Ok(value)
}
+#[instrument]
+fn get_container_policy_path_value(param: &str) -> Result<String> {
+ let fields: Vec<&str> = param.split('=').collect();
+
+ ensure!(!fields[0].is_empty(), ERR_INVALID_CONTAINER_POLICY_PATH_KEY);
+ ensure!(fields.len() == 2, ERR_INVALID_CONTAINER_POLICY_PATH_VALUE);
+
+ let key = fields[0];
+ ensure!(
+ key == CONTAINER_POLICY_FILE,
+ ERR_INVALID_CONTAINER_POLICY_PATH_KEY
+ );
+
+ let value = String::from(fields[1]);
+ ensure!(!value.is_empty(), ERR_INVALID_CONTAINER_POLICY_PATH_VALUE);
+ ensure!(
+ value.starts_with('/'),
+ ERR_INVALID_CONTAINER_POLICY_ABSOLUTE
+ );
+ ensure!(!value.contains(".."), ERR_INVALID_CONTAINER_POLICY_ABSOLUTE);
+ Ok(value)
+}
+
+#[instrument]
+fn get_url_value(param: &str) -> Result<String> {
+ let value = get_string_value(param)?;
+ Ok(Url::parse(&value)?.to_string())
+}
+
#[cfg(test)]
mod tests {
use test_utils::assert_result;
@@ -449,6 +552,8 @@ mod tests {
assert!(!config.dev_mode);
assert_eq!(config.log_level, DEFAULT_LOG_LEVEL);
assert_eq!(config.hotplug_timeout, DEFAULT_HOTPLUG_TIMEOUT);
+ assert_eq!(config.container_policy_path, "");
+ assert!(config.enable_signature_verification);
}
#[test]
@@ -467,6 +572,12 @@ mod tests {
server_addr: &'a str,
unified_cgroup_hierarchy: bool,
tracing: bool,
+ container_policy_path: &'a str,
+ aa_kbc_params: &'a str,
+ https_proxy: &'a str,
+ no_proxy: &'a str,
+ data_integrity: bool,
+ enable_signature_verification: bool,
}
impl Default for TestData<'_> {
@@ -482,6 +593,12 @@ mod tests {
server_addr: TEST_SERVER_ADDR,
unified_cgroup_hierarchy: false,
tracing: false,
+ container_policy_path: "",
+ aa_kbc_params: "",
+ https_proxy: "",
+ no_proxy: "",
+ data_integrity: false,
+ enable_signature_verification: true,
}
}
}
@@ -851,6 +968,86 @@ mod tests {
tracing: true,
..Default::default()
},
+ TestData {
+ contents: "agent.container_policy_file=/etc/containers/policy.json",
+ container_policy_path: "/etc/containers/policy.json",
+ ..Default::default()
+ },
+ TestData {
+ contents: "agent.aa_kbc_params=offline_fs_kbc::null",
+ aa_kbc_params: "offline_fs_kbc::null",
+ ..Default::default()
+ },
+ TestData {
+ contents: "agent.aa_kbc_params=eaa_kbc::127.0.0.1:50000",
+ aa_kbc_params: "eaa_kbc::127.0.0.1:50000",
+ ..Default::default()
+ },
+ TestData {
+ contents: "agent.https_proxy=http://proxy.url.com:81/",
+ https_proxy: "http://proxy.url.com:81/",
+ ..Default::default()
+ },
+ TestData {
+ contents: "agent.https_proxy=http://192.168.1.100:81/",
+ https_proxy: "http://192.168.1.100:81/",
+ ..Default::default()
+ },
+ TestData {
+ contents: "agent.no_proxy=*.internal.url.com",
+ no_proxy: "*.internal.url.com",
+ ..Default::default()
+ },
+ TestData {
+ contents: "agent.no_proxy=192.168.1.0/24,172.16.0.0/12",
+ no_proxy: "192.168.1.0/24,172.16.0.0/12",
+ ..Default::default()
+ },
+ TestData {
+ contents: "",
+ data_integrity: false,
+ ..Default::default()
+ },
+ TestData {
+ contents: "agent.data_integrity=true",
+ data_integrity: true,
+ ..Default::default()
+ },
+ TestData {
+ contents: "agent.data_integrity=false",
+ data_integrity: false,
+ ..Default::default()
+ },
+ TestData {
+ contents: "agent.data_integrity=1",
+ data_integrity: true,
+ ..Default::default()
+ },
+ TestData {
+ contents: "agent.data_integrity=0",
+ data_integrity: false,
+ ..Default::default()
+ },
+ TestData {
+ contents: "agent.enable_signature_verification=false",
+ enable_signature_verification: false,
+ ..Default::default()
+ },
+ TestData {
+ contents: "agent.enable_signature_verification=0",
+ enable_signature_verification: false,
+ ..Default::default()
+ },
+ TestData {
+ contents: "agent.enable_signature_verification=1",
+ enable_signature_verification: true,
+ ..Default::default()
+ },
+ TestData {
+ contents: "agent.enable_signature_verification=foo",
+ enable_signature_verification: false,
+ ..Default::default()
+ },
];
let dir = tempdir().expect("failed to create tmpdir");
@@ -898,6 +1095,20 @@ mod tests {
assert_eq!(d.container_pipe_size, config.container_pipe_size, "{}", msg);
assert_eq!(d.server_addr, config.server_addr, "{}", msg);
assert_eq!(d.tracing, config.tracing, "{}", msg);
+ assert_eq!(
+ d.container_policy_path, config.container_policy_path,
+ "{}",
+ msg
+ );
+ assert_eq!(d.aa_kbc_params, config.aa_kbc_params, "{}", msg);
+ assert_eq!(d.https_proxy, config.https_proxy, "{}", msg);
+ assert_eq!(d.no_proxy, config.no_proxy, "{}", msg);
+ assert_eq!(d.data_integrity, config.data_integrity, "{}", msg);
+ assert_eq!(
+ d.enable_signature_verification, config.enable_signature_verification,
+ "{}",
+ msg
+ );
for v in vars_to_unset {
env::remove_var(v);
@@ -1369,6 +1580,72 @@ Caused by:
}
}
+ #[test]
+ fn test_get_container_policy_path_value() {
+ #[derive(Debug)]
+ struct TestData<'a> {
+ param: &'a str,
+ result: Result<String>,
+ }
+
+ let tests = &[
+ TestData {
+ param: "",
+ result: Err(anyhow!(ERR_INVALID_CONTAINER_POLICY_PATH_KEY)),
+ },
+ TestData {
+ param: "agent.container_policy_file",
+ result: Err(anyhow!(ERR_INVALID_CONTAINER_POLICY_PATH_VALUE)),
+ },
+ TestData {
+ param: "agent.container_policy_file=",
+ result: Err(anyhow!(ERR_INVALID_CONTAINER_POLICY_PATH_VALUE)),
+ },
+ TestData {
+ param: "foo=bar",
+ result: Err(anyhow!(ERR_INVALID_CONTAINER_POLICY_PATH_KEY)),
+ },
+ TestData {
+ param: "agent.policy_path=/another/absolute/path.json",
+ result: Err(anyhow!(ERR_INVALID_CONTAINER_POLICY_PATH_KEY)),
+ },
+ TestData {
+ param: "agent.container_policy_file=/etc/container/policy.json",
+ result: Ok("/etc/container/policy.json".into()),
+ },
+ TestData {
+ param: "agent.container_policy_file=/another/absolute/path.json",
+ result: Ok("/another/absolute/path.json".into()),
+ },
+ TestData {
+ param: "agent.container_policy_file=./relative/path.json",
+ result: Err(anyhow!(ERR_INVALID_CONTAINER_POLICY_ABSOLUTE)),
+ },
+ TestData {
+ param: "agent.container_policy_file=./relative/path.json",
+ result: Err(anyhow!(ERR_INVALID_CONTAINER_POLICY_ABSOLUTE)),
+ },
+ TestData {
+ param: "agent.container_policy_file=../../relative/path.json",
+ result: Err(anyhow!(ERR_INVALID_CONTAINER_POLICY_ABSOLUTE)),
+ },
+ TestData {
+ param: "agent.container_policy_file=junk_string",
+ result: Err(anyhow!(ERR_INVALID_CONTAINER_POLICY_ABSOLUTE)),
+ },
+ ];
+
+ for (i, d) in tests.iter().enumerate() {
+ let msg = format!("test[{}]: {:?}", i, d);
+
+ let result = get_container_policy_path_value(d.param);
+
+ let msg = format!("{}: result: {:?}", msg, result);
+
+ assert_result!(d.result, result, msg);
+ }
+ }
+
#[test]
fn test_config_builder_from_string() {
let config = AgentConfig::from_str(
@@ -1399,4 +1676,50 @@ Caused by:
// Verify that the default values are valid
assert_eq!(config.hotplug_timeout, DEFAULT_HOTPLUG_TIMEOUT);
}
+
+ #[test]
+ fn test_config_from_cmdline_and_config_file() {
+ let dir = tempdir().expect("failed to create tmpdir");
+
+ let agent_config = r#"
+ dev_mode = false
+ server_addr = 'vsock://8:2048'
+
+ [endpoints]
+ allowed = ["CreateContainer", "StartContainer"]
+ "#;
+
+ let config_path = dir.path().join("agent-config.toml");
+ let config_filename = config_path.to_str().expect("failed to get config filename");
+
+ fs::write(config_filename, agent_config).expect("failed to write agen config");
+
+ let cmdline = format!("agent.devmode agent.config_file={}", config_filename);
+
+ let cmdline_path = dir.path().join("cmdline");
+ let cmdline_filename = cmdline_path
+ .to_str()
+ .expect("failed to get cmdline filename");
+
+ fs::write(cmdline_filename, cmdline).expect("failed to write agen config");
+
+ let config = AgentConfig::from_cmdline(cmdline_filename, vec![])
+ .expect("failed to parse command line");
+
+ // Should be overwritten by cmdline
+ assert!(config.dev_mode);
+
+ // Should be from agent config
+ assert_eq!(config.server_addr, "vsock://8:2048");
+
+ // Should be from agent config
+ assert_eq!(
+ config.endpoints.allowed,
+ vec!["CreateContainer".to_string(), "StartContainer".to_string()]
+ .iter()
+ .cloned()
+ .collect()
+ );
+ assert!(!config.endpoints.all_allowed);
+ }
}
diff --git a/src/agent/src/device.rs b/src/agent/src/device.rs
index 7d89d0124..2dcef740a 100644
--- a/src/agent/src/device.rs
+++ b/src/agent/src/device.rs
@@ -414,7 +414,7 @@ fn scan_scsi_bus(scsi_addr: &str) -> Result<()> {
// Scan scsi host passing in the channel, SCSI id and LUN.
// Channel is always 0 because we have only one SCSI controller.
- let scan_data = format!("0 {} {}", tokens[0], tokens[1]);
+ let scan_data = &format!("0 {} {}", tokens[0], tokens[1]);
for entry in fs::read_dir(SYSFS_SCSI_HOST_PATH)? {
let host = entry?.file_name();
@@ -428,7 +428,7 @@ fn scan_scsi_bus(scsi_addr: &str) -> Result<()> {
let scan_path = PathBuf::from(&format!("{}/{}/{}", SYSFS_SCSI_HOST_PATH, host_str, "scan"));
- fs::write(scan_path, &scan_data)?;
+ fs::write(scan_path, scan_data)?;
}
Ok(())
@@ -571,13 +571,15 @@ fn update_spec_devices(spec: &mut Spec, mut updates: HashMap<&str, DevUpdate>) -
if let Some(resources) = linux.resources.as_mut() {
for r in &mut resources.devices {
- if let (Some(host_major), Some(host_minor)) = (r.major, r.minor) {
- if let Some(update) = res_updates.get(&(r.r#type.as_str(), host_major, host_minor))
+ if let (Some(host_type), Some(host_major), Some(host_minor)) =
+ (r.r#type.as_ref(), r.major, r.minor)
+ {
+ if let Some(update) = res_updates.get(&(host_type.as_str(), host_major, host_minor))
{
info!(
sl!(),
"update_spec_devices() updating resource";
- "type" => &r.r#type,
+ "type" => &host_type,
"host_major" => host_major,
"host_minor" => host_minor,
"guest_major" => update.guest_major,
@@ -854,7 +856,7 @@ pub fn update_device_cgroup(spec: &mut Spec) -> Result<()> {
allow: false,
major: Some(major),
minor: Some(minor),
- r#type: String::from("b"),
+ r#type: Some(String::from("b")),
access: String::from("rw"),
});
@@ -1017,13 +1019,13 @@ mod tests {
resources: Some(LinuxResources {
devices: vec![
oci::LinuxDeviceCgroup {
- r#type: "c".to_string(),
+ r#type: Some("c".to_string()),
major: Some(host_major_a),
minor: Some(host_minor_a),
..oci::LinuxDeviceCgroup::default()
},
oci::LinuxDeviceCgroup {
- r#type: "c".to_string(),
+ r#type: Some("c".to_string()),
major: Some(host_major_b),
minor: Some(host_minor_b),
..oci::LinuxDeviceCgroup::default()
@@ -1116,13 +1118,13 @@ mod tests {
resources: Some(LinuxResources {
devices: vec![
LinuxDeviceCgroup {
- r#type: "c".to_string(),
+ r#type: Some("c".to_string()),
major: Some(host_major),
minor: Some(host_minor),
..LinuxDeviceCgroup::default()
},
LinuxDeviceCgroup {
- r#type: "b".to_string(),
+ r#type: Some("b".to_string()),
major: Some(host_major),
minor: Some(host_minor),
..LinuxDeviceCgroup::default()
@@ -1531,7 +1533,7 @@ mod tests {
pci_driver_override(syspci, dev0, "drv_b").unwrap();
assert_eq!(fs::read_to_string(&dev0override).unwrap(), "drv_b");
assert_eq!(fs::read_to_string(&probepath).unwrap(), dev0.to_string());
- assert_eq!(fs::read_to_string(&drvaunbind).unwrap(), dev0.to_string());
+ assert_eq!(fs::read_to_string(drvaunbind).unwrap(), dev0.to_string());
}
#[test]
@@ -1543,7 +1545,7 @@ mod tests {
let dev0 = pci::Address::new(0, 0, pci::SlotFn::new(0, 0).unwrap());
let dev0path = syspci.join("devices").join(dev0.to_string());
- fs::create_dir_all(&dev0path).unwrap();
+ fs::create_dir_all(dev0path).unwrap();
// Test dev0
assert!(pci_iommu_group(&syspci, dev0).unwrap().is_none());
@@ -1554,7 +1556,7 @@ mod tests {
let dev1group = dev1path.join("iommu_group");
fs::create_dir_all(&dev1path).unwrap();
- std::os::unix::fs::symlink("../../../kernel/iommu_groups/12", &dev1group).unwrap();
+ std::os::unix::fs::symlink("../../../kernel/iommu_groups/12", dev1group).unwrap();
// Test dev1
assert_eq!(
@@ -1567,7 +1569,7 @@ mod tests {
let dev2path = syspci.join("devices").join(dev2.to_string());
let dev2group = dev2path.join("iommu_group");
- fs::create_dir_all(&dev2group).unwrap();
+ fs::create_dir_all(dev2group).unwrap();
// Test dev2
assert!(pci_iommu_group(&syspci, dev2).is_err());
diff --git a/src/agent/src/image_rpc.rs b/src/agent/src/image_rpc.rs
new file mode 100644
index 000000000..0a66987cb
--- /dev/null
+++ b/src/agent/src/image_rpc.rs
@@ -0,0 +1,427 @@
+// Copyright (c) 2021 Alibaba Cloud
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+use std::env;
+use std::fmt::Write as _;
+use std::fs;
+use std::path::Path;
+use std::process::{Command, ExitStatus};
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::Arc;
+
+use anyhow::{anyhow, ensure, Result};
+use async_trait::async_trait;
+use protocols::image;
+use tokio::sync::Mutex;
+use ttrpc::{self, error::get_rpc_status as ttrpc_error};
+
+use crate::rpc::{verify_cid, CONTAINER_BASE};
+use crate::sandbox::Sandbox;
+use crate::AGENT_CONFIG;
+
+use image_rs::image::ImageClient;
+use std::io::Write;
+
+const SKOPEO_PATH: &str = "/usr/bin/skopeo";
+const UMOCI_PATH: &str = "/usr/local/bin/umoci";
+const IMAGE_OCI: &str = "image_oci";
+const AA_PATH: &str = "/usr/local/bin/attestation-agent";
+const AA_KEYPROVIDER_PORT: &str = "127.0.0.1:50000";
+const AA_GETRESOURCE_PORT: &str = "127.0.0.1:50001";
+const OCICRYPT_CONFIG_PATH: &str = "/tmp/ocicrypt_config.json";
+// kata rootfs is readonly, use tmpfs before CC storage is implemented.
+const KATA_CC_IMAGE_WORK_DIR: &str = "/run/image/";
+const KATA_CC_PAUSE_BUNDLE: &str = "/pause_bundle";
+const CONFIG_JSON: &str = "config.json";
+
+// Convenience macro to obtain the scope logger
+macro_rules! sl {
+ () => {
+ slog_scope::logger()
+ };
+}
+
+pub struct ImageService {
+ sandbox: Arc<Mutex<Sandbox>>,
+ attestation_agent_started: AtomicBool,
+ image_client: Arc<Mutex<ImageClient>>,
+}
+
+impl ImageService {
+ pub fn new(sandbox: Arc<Mutex<Sandbox>>) -> Self {
+ env::set_var("CC_IMAGE_WORK_DIR", KATA_CC_IMAGE_WORK_DIR);
+ Self {
+ sandbox,
+ attestation_agent_started: AtomicBool::new(false),
+ image_client: Arc::new(Mutex::new(ImageClient::default())),
+ }
+ }
+
+ fn pull_image_from_registry(
+ image: &str,
+ cid: &str,
+ source_creds: Option<&str>,
+ policy_path: Option<&str>,
+ aa_kbc_params: &str,
+ ) -> Result<()> {
+ let source_image = format!("{}{}", "docker://", image);
+
+ let tmp_cid_path = Path::new("/tmp/").join(cid);
+ let oci_path = tmp_cid_path.join(IMAGE_OCI);
+ let target_path_oci = format!("oci://{}:latest", oci_path.to_string_lossy());
+
+ fs::create_dir_all(&oci_path)?;
+
+ let mut pull_command = Command::new(SKOPEO_PATH);
+ pull_command
+ .arg("copy")
+ .arg(source_image)
+ .arg(&target_path_oci)
+ .arg("--remove-signatures"); //umoci requires signatures to be removed
+
+ // If source credentials were passed (so not using an anonymous registry), pass them through
+ if let Some(source_creds) = source_creds {
+ pull_command.arg("--src-creds").arg(source_creds);
+ }
+
+ // If a policy_path provided, use it, otherwise fall back to allow all image registries
+ if let Some(policy_path) = policy_path {
+ pull_command.arg("--policy").arg(policy_path);
+ } else {
+ info!(
+ sl!(),
+ "No policy path was supplied, so revert to allow all images to be pulled."
+ );
+ pull_command.arg("--insecure-policy");
+ }
+
+ debug!(sl!(), "skopeo command: {:?}", &pull_command);
+ if !aa_kbc_params.is_empty() {
+ // Skopeo will copy an unencrypted image even if the decryption key argument is provided.
+ // Thus, this does not guarantee that the image was encrypted.
+ pull_command
+ .arg("--decryption-key")
+ .arg(format!("provider:attestation-agent:{}", aa_kbc_params))
+ .env("OCICRYPT_KEYPROVIDER_CONFIG", OCICRYPT_CONFIG_PATH);
+ }
+
+ let status: ExitStatus = pull_command.status()?;
+
+ if !status.success() {
+ let mut error_message = format!("failed to pull image: {:?}", status);
+
+ if let Err(e) = fs::remove_dir_all(&tmp_cid_path) {
+ let _ = write!(
+ error_message,
+ " and clean up of temporary container directory {:?} failed with error {:?}",
+ tmp_cid_path, e
+ );
+ };
+ return Err(anyhow!(error_message));
+ }
+ Ok(())
+ }
+
+ fn unpack_image(cid: &str) -> Result<()> {
+ let tmp_cid_path = Path::new("/tmp/").join(cid);
+ let source_path_oci = tmp_cid_path.join(IMAGE_OCI);
+
+ let target_path_bundle = Path::new(CONTAINER_BASE).join(cid);
+
+ info!(sl!(), "unpack image {:?} to {:?}", cid, target_path_bundle);
+
+ // Unpack image
+ let status: ExitStatus = Command::new(UMOCI_PATH)
+ .arg("unpack")
+ .arg("--image")
+ .arg(&source_path_oci)
+ .arg(&target_path_bundle)
+ .status()?;
+
+ ensure!(status.success(), "failed to unpack image: {:?}", status);
+
+ // To save space delete the oci image after unpack
+ fs::remove_dir_all(&tmp_cid_path)?;
+
+ Ok(())
+ }
+
+ // pause image is packaged in rootfs for CC
+ fn unpack_pause_image(cid: &str) -> Result<()> {
+ let cc_pause_bundle = Path::new(KATA_CC_PAUSE_BUNDLE);
+ if !cc_pause_bundle.exists() {
+ return Err(anyhow!("Pause image not present in rootfs"));
+ }
+
+ info!(sl!(), "use guest pause image cid {:?}", cid);
+ let pause_bundle = Path::new(CONTAINER_BASE).join(cid);
+ let pause_rootfs = pause_bundle.join("rootfs");
+ let pause_config = pause_bundle.join(CONFIG_JSON);
+ let pause_binary = pause_rootfs.join("pause");
+ fs::create_dir_all(&pause_rootfs)?;
+ if !pause_config.exists() {
+ fs::copy(
+ cc_pause_bundle.join(CONFIG_JSON),
+ pause_bundle.join(CONFIG_JSON),
+ )?;
+ }
+ if !pause_binary.exists() {
+ fs::copy(cc_pause_bundle.join("rootfs").join("pause"), pause_binary)?;
+ }
+
+ Ok(())
+ }
+
+ // If we fail to start the AA, Skopeo/ocicrypt won't be able to unwrap keys
+ // and container decryption will fail.
+ fn init_attestation_agent() -> Result<()> {
+ let config_path = OCICRYPT_CONFIG_PATH;
+
+ // The image will need to be encrypted using a keyprovider
+ // that has the same name (at least according to the config).
+ let ocicrypt_config = serde_json::json!({
+ "key-providers": {
+ "attestation-agent":{
+ "grpc":AA_KEYPROVIDER_PORT
+ }
+ }
+ });
+
+ let mut config_file = fs::File::create(config_path)?;
+ config_file.write_all(ocicrypt_config.to_string().as_bytes())?;
+
+ // The Attestation Agent will run for the duration of the guest.
+ Command::new(AA_PATH)
+ .arg("--keyprovider_sock")
+ .arg(AA_KEYPROVIDER_PORT)
+ .arg("--getresource_sock")
+ .arg(AA_GETRESOURCE_PORT)
+ .spawn()?;
+ Ok(())
+ }
+
+ /// Determines the container id (cid) to use for a given request.
+ ///
+ /// 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(req: &image::PullImageRequest) -> Result<String> {
+ let req_cid = req.get_container_id();
+ let cid = if !req_cid.is_empty() {
+ req_cid.to_string()
+ } else if let Some(last) = req.get_image().rsplit('/').next() {
+ // ':' have special meaning for umoci during upack
+ last.replace(':', "_")
+ } else {
+ return Err(anyhow!("Invalid image name. {}", req.get_image()));
+ };
+ verify_cid(&cid)?;
+ Ok(cid)
+ }
+
+ async fn pull_image(&self, req: &image::PullImageRequest) -> Result<String> {
+ env::set_var("OCICRYPT_KEYPROVIDER_CONFIG", OCICRYPT_CONFIG_PATH);
+
+ let https_proxy = &AGENT_CONFIG.read().await.https_proxy;
+ if !https_proxy.is_empty() {
+ env::set_var("HTTPS_PROXY", https_proxy);
+ }
+
+ let no_proxy = &AGENT_CONFIG.read().await.no_proxy;
+ if !no_proxy.is_empty() {
+ env::set_var("NO_PROXY", no_proxy);
+ }
+
+ let cid = Self::cid_from_request(req)?;
+ let image = req.get_image();
+ // Can switch to use cid directly when we remove umoci
+ let v: Vec<&str> = image.rsplit('/').collect();
+ if !v[0].is_empty() && v[0].starts_with("pause:") {
+ Self::unpack_pause_image(&cid)?;
+
+ let mut sandbox = self.sandbox.lock().await;
+ sandbox.images.insert(String::from(image), cid);
+ return Ok(image.to_owned());
+ }
+
+ let aa_kbc_params = &AGENT_CONFIG.read().await.aa_kbc_params;
+ if !aa_kbc_params.is_empty() {
+ match self.attestation_agent_started.compare_exchange_weak(
+ false,
+ true,
+ Ordering::SeqCst,
+ Ordering::SeqCst,
+ ) {
+ Ok(_) => Self::init_attestation_agent()?,
+ Err(_) => info!(sl!(), "Attestation Agent already running"),
+ }
+ }
+
+ let source_creds = (!req.get_source_creds().is_empty()).then(|| req.get_source_creds());
+
+ if Path::new(SKOPEO_PATH).exists() {
+ // Read the policy path from the agent config
+ let config_policy_path = &AGENT_CONFIG.read().await.container_policy_path;
+ let policy_path =
+ (!config_policy_path.is_empty()).then_some(config_policy_path.as_str());
+ Self::pull_image_from_registry(image, &cid, source_creds, policy_path, aa_kbc_params)?;
+ Self::unpack_image(&cid)?;
+ } else {
+ // Read enable signature verification from the agent config and set it in the image_client
+ let enable_signature_verification =
+ &AGENT_CONFIG.read().await.enable_signature_verification;
+ info!(
+ sl!(),
+ "enable_signature_verification set to: {}", enable_signature_verification
+ );
+ self.image_client.lock().await.config.security_validate =
+ *enable_signature_verification;
+
+ // If the attestation-agent is being used, then enable the authenticated credentials support
+ //TODO tidy logic once skopeo is removed to combine with aa_kbc_params check above
+ info!(
+ sl!(),
+ "image_client.config.auth set to: {}",
+ !aa_kbc_params.is_empty()
+ );
+ self.image_client.lock().await.config.auth = !aa_kbc_params.is_empty();
+
+ let bundle_path = Path::new(CONTAINER_BASE).join(&cid);
+ fs::create_dir_all(&bundle_path)?;
+
+ let decrypt_config = format!("provider:attestation-agent:{}", aa_kbc_params);
+
+ info!(sl!(), "pull image {:?}, bundle path {:?}", cid, bundle_path);
+ // Image layers will store at KATA_CC_IMAGE_WORK_DIR, generated bundles
+ // with rootfs and config.json will store under CONTAINER_BASE/cid.
+ self.image_client
+ .lock()
+ .await
+ .pull_image(image, &bundle_path, &source_creds, &Some(&decrypt_config))
+ .await?;
+
+ info!(
+ sl!(),
+ "pull and unpack image {:?}, with image-rs succeeded ", cid
+ );
+ }
+
+ let mut sandbox = self.sandbox.lock().await;
+ sandbox.images.insert(String::from(image), cid);
+ Ok(image.to_owned())
+ }
+}
+
+#[async_trait]
+impl protocols::image_ttrpc_async::Image for ImageService {
+ async fn pull_image(
+ &self,
+ _ctx: &ttrpc::r#async::TtrpcContext,
+ req: image::PullImageRequest,
+ ) -> ttrpc::Result<image::PullImageResponse> {
+ match self.pull_image(&req).await {
+ Ok(r) => {
+ let mut resp = image::PullImageResponse::new();
+ resp.image_ref = r;
+ return Ok(resp);
+ }
+ Err(e) => {
+ return Err(ttrpc_error(ttrpc::Code::INTERNAL, e.to_string()));
+ }
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::ImageService;
+ use protocols::image;
+
+ #[test]
+ fn test_cid_from_request() {
+ struct Case {
+ cid: &'static str,
+ image: &'static str,
+ result: Option<&'static str>,
+ }
+
+ let cases = [
+ Case {
+ cid: "",
+ image: "",
+ result: None,
+ },
+ Case {
+ cid: "..",
+ image: "",
+ result: None,
+ },
+ Case {
+ cid: "",
+ image: "..",
+ result: None,
+ },
+ Case {
+ cid: "",
+ image: "abc/..",
+ result: None,
+ },
+ Case {
+ cid: "",
+ image: "abc/",
+ result: None,
+ },
+ Case {
+ cid: "",
+ image: "../abc",
+ result: Some("abc"),
+ },
+ Case {
+ cid: "",
+ image: "../9abc",
+ result: Some("9abc"),
+ },
+ Case {
+ cid: "some-string.1_2",
+ image: "",
+ result: Some("some-string.1_2"),
+ },
+ Case {
+ cid: "0some-string.1_2",
+ image: "",
+ result: Some("0some-string.1_2"),
+ },
+ Case {
+ cid: "a:b",
+ image: "",
+ result: None,
+ },
+ Case {
+ cid: "",
+ image: "prefix/a:b",
+ result: Some("a_b"),
+ },
+ Case {
+ cid: "",
+ image: "/a/b/c/d:e",
+ result: Some("d_e"),
+ },
+ ];
+
+ for case in &cases {
+ let mut req = image::PullImageRequest::new();
+ req.set_image(case.image.to_string());
+ req.set_container_id(case.cid.to_string());
+ let ret = ImageService::cid_from_request(&req);
+ match (case.result, ret) {
+ (Some(expected), Ok(actual)) => assert_eq!(expected, actual),
+ (None, Err(_)) => (),
+ (None, Ok(r)) => panic!("Expected an error, got {}", r),
+ (Some(expected), Err(e)) => {
+ panic!("Expected {} but got an error ({})", expected, e)
+ }
+ }
+ }
+ }
+}
diff --git a/src/agent/src/main.rs b/src/agent/src/main.rs
index 2c1f41def..d211d2a8a 100644
--- a/src/agent/src/main.rs
+++ b/src/agent/src/main.rs
@@ -71,6 +71,7 @@ use tokio::{
task::JoinHandle,
};
+mod image_rpc;
mod rpc;
mod tracer;
diff --git a/src/agent/src/mount.rs b/src/agent/src/mount.rs
index 1db16343e..17ea3859c 100644
--- a/src/agent/src/mount.rs
+++ b/src/agent/src/mount.rs
@@ -648,7 +648,7 @@ pub fn recursive_ownership_change(
) -> Result<()> {
let mut mask = if read_only { RO_MASK } else { RW_MASK };
if path.is_dir() {
- for entry in fs::read_dir(&path)? {
+ for entry in fs::read_dir(path)? {
recursive_ownership_change(entry?.path().as_path(), uid, gid, read_only)?;
}
mask |= EXEC_MASK;
@@ -894,7 +894,7 @@ pub fn get_cgroup_mounts(
}]);
}
- let file = File::open(&cg_path)?;
+ let file = File::open(cg_path)?;
let reader = BufReader::new(file);
let mut has_device_cgroup = false;
@@ -1777,7 +1777,7 @@ mod tests {
let tempdir = tempdir().unwrap();
let src = if d.mask_src {
- tempdir.path().join(&d.src)
+ tempdir.path().join(d.src)
} else {
Path::new(d.src).to_path_buf()
};
diff --git a/src/agent/src/namespace.rs b/src/agent/src/namespace.rs
index 876e3d6fd..a3ad26616 100644
--- a/src/agent/src/namespace.rs
+++ b/src/agent/src/namespace.rs
@@ -78,6 +78,7 @@ impl Namespace {
// setup creates persistent namespace without switching to it.
// Note, pid namespaces cannot be persisted.
#[instrument]
+ #[allow(clippy::question_mark)]
pub async fn setup(mut self) -> Result<Self> {
fs::create_dir_all(&self.persistent_ns_dir)?;
@@ -88,7 +89,7 @@ impl Namespace {
}
let logger = self.logger.clone();
- let new_ns_path = ns_path.join(&ns_type.get());
+ let new_ns_path = ns_path.join(ns_type.get());
File::create(new_ns_path.as_path())?;
@@ -102,7 +103,7 @@ impl Namespace {
let source = Path::new(&origin_ns_path);
let destination = new_ns_path.as_path();
- File::open(&source)?;
+ File::open(source)?;
// Create a new netns on the current thread.
let cf = ns_type.get_flags();
diff --git a/src/agent/src/netlink.rs b/src/agent/src/netlink.rs
index 4d6a26e14..29785fc43 100644
--- a/src/agent/src/netlink.rs
+++ b/src/agent/src/netlink.rs
@@ -529,7 +529,9 @@ impl Handle {
.map_err(|e| anyhow!("Failed to parse IP {}: {:?}", ip_address, e))?;
// Import rtnetlink objects that make sense only for this function
- use packet::constants::{NDA_UNSPEC, NLM_F_ACK, NLM_F_CREATE, NLM_F_EXCL, NLM_F_REQUEST};
+ use packet::constants::{
+ NDA_UNSPEC, NLM_F_ACK, NLM_F_CREATE, NLM_F_REPLACE, NLM_F_REQUEST,
+ };
use packet::neighbour::{NeighbourHeader, NeighbourMessage};
use packet::nlas::neighbour::Nla;
use packet::{NetlinkMessage, NetlinkPayload, RtnlMessage};
@@ -572,7 +574,7 @@ impl Handle {
// Send request and ACK
let mut req = NetlinkMessage::from(RtnlMessage::NewNeighbour(message));
- req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE;
+ req.header.flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_REPLACE;
let mut response = self.handle.request(req)?;
while let Some(message) = response.next().await {
@@ -944,13 +946,13 @@ mod tests {
fn clean_env_for_test_add_one_arp_neighbor(dummy_name: &str, ip: &str) {
// ip link delete dummy
Command::new("ip")
- .args(&["link", "delete", dummy_name])
+ .args(["link", "delete", dummy_name])
.output()
.expect("prepare: failed to delete dummy");
// ip neigh del dev dummy ip
Command::new("ip")
- .args(&["neigh", "del", dummy_name, ip])
+ .args(["neigh", "del", dummy_name, ip])
.output()
.expect("prepare: failed to delete neigh");
}
@@ -965,19 +967,19 @@ mod tests {
// ip link add dummy type dummy
Command::new("ip")
- .args(&["link", "add", dummy_name, "type", "dummy"])
+ .args(["link", "add", dummy_name, "type", "dummy"])
.output()
.expect("failed to add dummy interface");
// ip addr add 192.168.0.2/16 dev dummy
Command::new("ip")
- .args(&["addr", "add", "192.168.0.2/16", "dev", dummy_name])
+ .args(["addr", "add", "192.168.0.2/16", "dev", dummy_name])
.output()
.expect("failed to add ip for dummy");
// ip link set dummy up;
Command::new("ip")
- .args(&["link", "set", dummy_name, "up"])
+ .args(["link", "set", dummy_name, "up"])
.output()
.expect("failed to up dummy");
}
@@ -1009,7 +1011,7 @@ mod tests {
// ip neigh show dev dummy ip
let stdout = Command::new("ip")
- .args(&["neigh", "show", "dev", dummy_name, to_ip])
+ .args(["neigh", "show", "dev", dummy_name, to_ip])
.output()
.expect("failed to show neigh")
.stdout;
diff --git a/src/agent/src/network.rs b/src/agent/src/network.rs
index 194795a6f..451b5064d 100644
--- a/src/agent/src/network.rs
+++ b/src/agent/src/network.rs
@@ -64,7 +64,7 @@ fn do_setup_guest_dns(logger: Logger, dns_list: Vec<String>, src: &str, dst: &st
.map(|x| x.trim())
.collect::<Vec<&str>>()
.join("\n");
- fs::write(src, &content)?;
+ fs::write(src, content)?;
// bind mount to /etc/resolv.conf
mount::mount(Some(src), dst, Some("bind"), MsFlags::MS_BIND, None::<&str>)
diff --git a/src/agent/src/rpc.rs b/src/agent/src/rpc.rs
index bf6420e9b..b9b44b715 100644
--- a/src/agent/src/rpc.rs
+++ b/src/agent/src/rpc.rs
@@ -34,7 +34,10 @@ use protocols::health::{
HealthCheckResponse, HealthCheckResponse_ServingStatus, VersionCheckResponse,
};
use protocols::types::Interface;
-use protocols::{agent_ttrpc_async as agent_ttrpc, health_ttrpc_async as health_ttrpc};
+use protocols::{
+ agent_ttrpc_async as agent_ttrpc, health_ttrpc_async as health_ttrpc,
+ image_ttrpc_async as image_ttrpc,
+};
use rustjail::cgroups::notifier;
use rustjail::container::{BaseContainer, Container, LinuxContainer};
use rustjail::process::Process;
@@ -44,12 +47,12 @@ use nix::errno::Errno;
use nix::mount::MsFlags;
use nix::sys::{stat, statfs};
use nix::unistd::{self, Pid};
-use rustjail::cgroups::Manager;
use rustjail::process::ProcessOperations;
use crate::device::{
add_devices, get_virtio_blk_pci_device_name, update_device_cgroup, update_env_pci,
};
+use crate::image_rpc;
use crate::linux_abi::*;
use crate::metrics::get_metrics;
use crate::mount::{add_storages, baremount, STORAGE_HANDLER_LIST};
@@ -81,12 +84,22 @@ use std::io::{BufRead, BufReader, Write};
use std::os::unix::fs::FileExt;
use std::path::PathBuf;
-const CONTAINER_BASE: &str = "/run/kata-containers";
+pub const CONTAINER_BASE: &str = "/run/kata-containers";
const MODPROBE_PATH: &str = "/sbin/modprobe";
-
+const ANNO_K8S_IMAGE_NAME: &str = "io.kubernetes.cri.image-name";
+const CONFIG_JSON: &str = "config.json";
+const INIT_TRUSTED_STORAGE: &str = "/usr/bin/kata-init-trusted-storage";
+const TRUSTED_STORAGE_DEVICE: &str = "/dev/trusted_store";
+
+/// the iptables seriers binaries could appear either in /sbin
+/// or /usr/sbin, we need to check both of them
+const USR_IPTABLES_SAVE: &str = "/usr/sbin/iptables-save";
const IPTABLES_SAVE: &str = "/sbin/iptables-save";
+const USR_IPTABLES_RESTORE: &str = "/usr/sbin/iptables-store";
const IPTABLES_RESTORE: &str = "/sbin/iptables-restore";
+const USR_IP6TABLES_SAVE: &str = "/usr/sbin/ip6tables-save";
const IP6TABLES_SAVE: &str = "/sbin/ip6tables-save";
+const USR_IP6TABLES_RESTORE: &str = "/usr/sbin/ip6tables-save";
const IP6TABLES_RESTORE: &str = "/sbin/ip6tables-restore";
const ERR_CANNOT_GET_WRITER: &str = "Cannot get writer";
@@ -134,6 +147,41 @@ pub struct AgentService {
sandbox: Arc<Mutex<Sandbox>>,
}
+// A container ID must match this regex:
+//
+// ^[a-zA-Z0-9][a-zA-Z0-9_.-]+$
+//
+pub fn verify_cid(id: &str) -> Result<()> {
+ let mut chars = id.chars();
+
+ let valid = matches!(chars.next(), Some(first) if first.is_alphanumeric()
+ && id.len() > 1
+ && chars.all(|c| c.is_alphanumeric() || ['.', '-', '_'].contains(&c)));
+
+ match valid {
+ true => Ok(()),
+ false => Err(anyhow!("invalid container ID: {:?}", id)),
+ }
+}
+
+// Partially merge an OCI process specification into another one.
+fn merge_oci_process(target: &mut oci::Process, source: &oci::Process) {
+ if target.args.is_empty() && !source.args.is_empty() {
+ target.args.append(&mut source.args.clone());
+ }
+
+ if target.cwd == "/" && source.cwd != "/" {
+ target.cwd = String::from(&source.cwd);
+ }
+
+ for source_env in &source.env {
+ let variable_name: Vec<&str> = source_env.split('=').collect();
+ if !target.env.iter().any(|i| i.contains(variable_name[0])) {
+ target.env.push(source_env.to_string());
+ }
+ }
+}
+
impl AgentService {
#[instrument]
async fn do_create_container(
@@ -164,6 +212,9 @@ impl AgentService {
"receive createcontainer, storages: {:?}", &req.storages
);
+ // Merge the image bundle OCI spec into the container creation request OCI spec.
+ self.merge_bundle_oci(&mut oci).await?;
+
// Some devices need some extra processing (the ones invoked with
// --device for instance), and that's what this call is doing. It
// updates the devices listed in the OCI spec, so that they actually
@@ -171,6 +222,30 @@ impl AgentService {
// cannot predict everything from the caller.
add_devices(&req.devices.to_vec(), &mut oci, &self.sandbox).await?;
+ let linux = oci
+ .linux
+ .as_mut()
+ .ok_or_else(|| anyhow!("Spec didn't contain linux field"))?;
+
+ for specdev in &mut linux.devices {
+ let dev_major_minor = format!("{}:{}", specdev.major, specdev.minor);
+
+ if specdev.path == TRUSTED_STORAGE_DEVICE {
+ let data_integrity = AGENT_CONFIG.read().await.data_integrity;
+ info!(
+ sl!(),
+ "trusted_store device major:min {}, enable data integrity {}",
+ dev_major_minor,
+ data_integrity.to_string()
+ );
+
+ Command::new(INIT_TRUSTED_STORAGE)
+ .args([&dev_major_minor, &data_integrity.to_string()])
+ .output()
+ .expect("Failed to initialize confidential storage");
+ }
+ }
+
// Both rootfs and volumes (invoked with --volume for instance) will
// be processed the same way. The idea is to always mount any provided
// storage to the specified MountPoint, so that it will match what's
@@ -266,14 +341,13 @@ impl AgentService {
}
// start oom event loop
- if let Some(ref ctr) = ctr.cgroup_manager {
- let cg_path = ctr.get_cg_path("memory");
- if let Some(cg_path) = cg_path {
- let rx = notifier::notify_oom(cid.as_str(), cg_path.to_string()).await?;
+ let cg_path = ctr.cgroup_manager.as_ref().get_cgroup_path("memory");
- s.run_oom_event_monitor(rx, cid.clone()).await;
- }
+ if let Ok(cg_path) = cg_path {
+ let rx = notifier::notify_oom(cid.as_str(), cg_path.to_string()).await?;
+
+ s.run_oom_event_monitor(rx, cid.clone()).await;
}
Ok(())
@@ -377,6 +451,7 @@ impl AgentService {
"signal process";
"container-id" => cid.clone(),
"exec-id" => eid.clone(),
+ "signal" => req.signal,
);
let mut sig: libc::c_int = req.signal as libc::c_int;
@@ -459,11 +534,7 @@ impl AgentService {
let ctr = sandbox
.get_container(cid)
.ok_or_else(|| anyhow!("Invalid container id {}", cid))?;
- let cm = ctr
- .cgroup_manager
- .as_ref()
- .ok_or_else(|| anyhow!("cgroup manager not exist"))?;
- cm.freeze(state)?;
+ ctr.cgroup_manager.as_ref().freeze(state)?;
Ok(())
}
@@ -473,11 +544,7 @@ impl AgentService {
let ctr = sandbox
.get_container(cid)
.ok_or_else(|| anyhow!("Invalid container id {}", cid))?;
- let cm = ctr
- .cgroup_manager
- .as_ref()
- .ok_or_else(|| anyhow!("cgroup manager not exist"))?;
- let pids = cm.get_pids()?;
+ let pids = ctr.cgroup_manager.as_ref().get_pids()?;
Ok(pids)
}
@@ -629,6 +696,54 @@ impl AgentService {
}
}
}
+
+ // When being passed an image name through a container annotation, merge its
+ // corresponding bundle OCI specification into the passed container creation one.
+ async fn merge_bundle_oci(&self, container_oci: &mut oci::Spec) -> Result<()> {
+ if let Some(image_name) = container_oci
+ .annotations
+ .get(&ANNO_K8S_IMAGE_NAME.to_string())
+ {
+ if let Some(container_id) = self.sandbox.clone().lock().await.images.get(image_name) {
+ let image_oci_config_path = Path::new(CONTAINER_BASE)
+ .join(container_id)
+ .join(CONFIG_JSON);
+ debug!(
+ sl!(),
+ "Image bundle config path: {:?}", image_oci_config_path
+ );
+
+ let image_oci =
+ oci::Spec::load(image_oci_config_path.to_str().ok_or_else(|| {
+ anyhow!(
+ "Invalid container image OCI config path {:?}",
+ image_oci_config_path
+ )
+ })?)
+ .context("load image bundle")?;
+
+ if let Some(container_root) = container_oci.root.as_mut() {
+ if let Some(image_root) = image_oci.root.as_ref() {
+ let root_path = Path::new(CONTAINER_BASE)
+ .join(container_id)
+ .join(image_root.path.clone());
+ container_root.path =
+ String::from(root_path.to_str().ok_or_else(|| {
+ anyhow!("Invalid container image root path {:?}", root_path)
+ })?);
+ }
+ }
+
+ if let Some(container_process) = container_oci.process.as_mut() {
+ if let Some(image_process) = image_oci.process.as_ref() {
+ merge_oci_process(container_process, image_process);
+ }
+ }
+ }
+ }
+
+ Ok(())
+ }
}
#[async_trait]
@@ -998,8 +1113,18 @@ impl agent_ttrpc::AgentService for AgentService {
info!(sl!(), "get_ip_tables: request received");
+ // the binary could exists in either /usr/sbin or /sbin
+ // here check both of the places and return the one exists
+ // if none exists, return the /sbin one, and the rpc will
+ // returns an internal error
let cmd = if req.is_ipv6 {
- IP6TABLES_SAVE
+ if Path::new(USR_IP6TABLES_SAVE).exists() {
+ USR_IP6TABLES_SAVE
+ } else {
+ IP6TABLES_SAVE
+ }
+ } else if Path::new(USR_IPTABLES_SAVE).exists() {
+ USR_IPTABLES_SAVE
} else {
IPTABLES_SAVE
}
@@ -1027,8 +1152,18 @@ impl agent_ttrpc::AgentService for AgentService {
info!(sl!(), "set_ip_tables request received");
+ // the binary could exists in both /usr/sbin and /sbin
+ // here check both of the places and return the one exists
+ // if none exists, return the /sbin one, and the rpc will
+ // returns an internal error
let cmd = if req.is_ipv6 {
- IP6TABLES_RESTORE
+ if Path::new(USR_IP6TABLES_RESTORE).exists() {
+ USR_IP6TABLES_RESTORE
+ } else {
+ IP6TABLES_RESTORE
+ }
+ } else if Path::new(USR_IPTABLES_RESTORE).exists() {
+ USR_IPTABLES_RESTORE
} else {
IPTABLES_RESTORE
}
@@ -1657,22 +1792,27 @@ async fn read_stream(reader: Arc<Mutex<ReadHalf<PipeStream>>>, l: usize) -> Resu
}
pub fn start(s: Arc<Mutex<Sandbox>>, server_address: &str) -> Result<TtrpcServer> {
- let agent_service =
- Box::new(AgentService { sandbox: s }) as Box<dyn agent_ttrpc::AgentService + Send + Sync>;
-
+ let agent_service = Box::new(AgentService { sandbox: s.clone() })
+ as Box<dyn agent_ttrpc::AgentService + Send + Sync>;
let agent_worker = Arc::new(agent_service);
let health_service = Box::new(HealthService {}) as Box<dyn health_ttrpc::Health + Send + Sync>;
let health_worker = Arc::new(health_service);
+ let image_service =
+ Box::new(image_rpc::ImageService::new(s)) as Box<dyn image_ttrpc::Image + Send + Sync>;
+
let aservice = agent_ttrpc::create_agent_service(agent_worker);
let hservice = health_ttrpc::create_health(health_worker);
+ let iservice = image_ttrpc::create_image(Arc::new(image_service));
+
let server = TtrpcServer::new()
.bind(server_address)?
.register_service(aservice)
- .register_service(hservice);
+ .register_service(hservice)
+ .register_service(iservice);
info!(sl!(), "ttRPC server started"; "address" => server_address);
@@ -1878,6 +2018,38 @@ fn do_copy_file(req: &CopyFileRequest) -> Result<()> {
std::fs::set_permissions(&dir, std::fs::Permissions::from_mode(req.dir_mode))?;
+ let sflag = stat::SFlag::from_bits_truncate(req.file_mode);
+
+ if sflag.contains(stat::SFlag::S_IFDIR) {
+ fs::create_dir(path.clone()).or_else(|e| {
+ if e.kind() != std::io::ErrorKind::AlreadyExists {
+ return Err(e);
+ }
+ Ok(())
+ })?;
+
+ std::fs::set_permissions(path.clone(), std::fs::Permissions::from_mode(req.file_mode))?;
+
+ unistd::chown(
+ &path,
+ Some(Uid::from_raw(req.uid as u32)),
+ Some(Gid::from_raw(req.gid as u32)),
+ )?;
+
+ return Ok(());
+ }
+
+ if sflag.contains(stat::SFlag::S_IFLNK) {
+ let src = PathBuf::from(String::from_utf8(req.data.clone()).unwrap());
+
+ unistd::symlinkat(&src, None, &path)?;
+ let path_str = CString::new(path.to_str().unwrap())?;
+ let ret = unsafe { libc::lchown(path_str.as_ptr(), req.uid as u32, req.gid as u32) };
+ Errno::result(ret).map(drop)?;
+
+ return Ok(());
+ }
+
let mut tmpfile = path.clone();
tmpfile.set_extension("tmp");
@@ -1943,18 +2115,26 @@ pub fn setup_bundle(cid: &str, spec: &mut Spec) -> Result<PathBuf> {
let spec_root_path = Path::new(&spec_root.path);
let bundle_path = Path::new(CONTAINER_BASE).join(cid);
- let config_path = bundle_path.join("config.json");
+ let config_path = bundle_path.join(CONFIG_JSON);
let rootfs_path = bundle_path.join("rootfs");
- fs::create_dir_all(&rootfs_path)?;
- baremount(
- spec_root_path,
- &rootfs_path,
- "bind",
- MsFlags::MS_BIND,
- "",
- &sl!(),
- )?;
+ let rootfs_exists = Path::new(&rootfs_path).exists();
+ info!(
+ sl!(),
+ "The rootfs_path is {:?} and exists: {}", rootfs_path, rootfs_exists
+ );
+
+ if !rootfs_exists {
+ fs::create_dir_all(&rootfs_path)?;
+ baremount(
+ spec_root_path,
+ &rootfs_path,
+ "bind",
+ MsFlags::MS_BIND,
+ "",
+ &sl!(),
+ )?;
+ }
let rootfs_path_name = rootfs_path
.to_str()
@@ -2032,6 +2212,11 @@ mod tests {
use tempfile::{tempdir, TempDir};
use test_utils::{assert_result, skip_if_not_root};
use ttrpc::{r#async::TtrpcContext, MessageHeader};
+ use which::which;
+
+ fn check_command(cmd: &str) -> bool {
+ which(cmd).is_ok()
+ }
fn mk_ttrpc_context() -> TtrpcContext {
TtrpcContext {
@@ -2751,6 +2936,27 @@ OtherField:other
async fn test_ip_tables() {
skip_if_not_root!();
+ let iptables_cmd_list = [
+ USR_IPTABLES_SAVE,
+ USR_IP6TABLES_SAVE,
+ USR_IPTABLES_RESTORE,
+ USR_IP6TABLES_RESTORE,
+ IPTABLES_SAVE,
+ IP6TABLES_SAVE,
+ IPTABLES_RESTORE,
+ IP6TABLES_RESTORE,
+ ];
+
+ for cmd in iptables_cmd_list {
+ if !check_command(cmd) {
+ warn!(
+ sl!(),
+ "one or more commands for ip tables test are missing, skip it"
+ );
+ return;
+ }
+ }
+
let logger = slog::Logger::root(slog::Discard, o!());
let sandbox = Sandbox::new(&logger).unwrap();
let agent_service = Box::new(AgentService {
@@ -2860,7 +3066,7 @@ COMMIT
.unwrap();
assert!(!result.data.is_empty(), "we should have non-zero output:");
assert!(
- std::str::from_utf8(&*result.data).unwrap().contains(
+ std::str::from_utf8(&result.data).unwrap().contains(
"PREROUTING -d 192.168.103.153/32 -j DNAT --to-destination 192.168.188.153"
),
"We should see the resulting rule"
@@ -2898,10 +3104,141 @@ COMMIT
.unwrap();
assert!(!result.data.is_empty(), "we should have non-zero output:");
assert!(
- std::str::from_utf8(&*result.data)
+ std::str::from_utf8(&result.data)
.unwrap()
.contains("INPUT -s 2001:db8:100::1/128 -i sit+ -p tcp -m tcp --sport 512:65535"),
"We should see the resulting rule"
);
}
+
+ #[tokio::test]
+ async fn test_merge_cwd() {
+ #[derive(Debug)]
+ struct TestData<'a> {
+ container_process_cwd: &'a str,
+ image_process_cwd: &'a str,
+ expected: &'a str,
+ }
+
+ let tests = &[
+ // Image cwd should override blank container cwd
+ // TODO - how can we tell the user didn't specifically set it to `/` vs not setting at all? Is that scenario valid?
+ TestData {
+ container_process_cwd: "/",
+ image_process_cwd: "/imageDir",
+ expected: "/imageDir",
+ },
+ // Container cwd should override image cwd
+ TestData {
+ container_process_cwd: "/containerDir",
+ image_process_cwd: "/imageDir",
+ expected: "/containerDir",
+ },
+ // Container cwd should override blank image cwd
+ TestData {
+ container_process_cwd: "/containerDir",
+ image_process_cwd: "/",
+ expected: "/containerDir",
+ },
+ ];
+
+ for (i, d) in tests.iter().enumerate() {
+ let msg = format!("test[{}]: {:?}", i, d);
+
+ let mut container_process = oci::Process {
+ cwd: d.container_process_cwd.to_string(),
+ ..Default::default()
+ };
+
+ let image_process = oci::Process {
+ cwd: d.image_process_cwd.to_string(),
+ ..Default::default()
+ };
+
+ merge_oci_process(&mut container_process, &image_process);
+
+ assert_eq!(d.expected, container_process.cwd, "{}", msg);
+ }
+ }
+
+ #[tokio::test]
+ async fn test_merge_env() {
+ #[derive(Debug)]
+ struct TestData {
+ container_process_env: Vec<String>,
+ image_process_env: Vec<String>,
+ expected: Vec<String>,
+ }
+
+ let tests = &[
+ // Test that the pods environment overrides the images
+ TestData {
+ container_process_env: vec!["ISPRODUCTION=true".to_string()],
+ image_process_env: vec!["ISPRODUCTION=false".to_string()],
+ expected: vec!["ISPRODUCTION=true".to_string()],
+ },
+ // Test that multiple environment variables can be overrided
+ TestData {
+ container_process_env: vec![
+ "ISPRODUCTION=true".to_string(),
+ "ISDEVELOPMENT=false".to_string(),
+ ],
+ image_process_env: vec![
+ "ISPRODUCTION=false".to_string(),
+ "ISDEVELOPMENT=true".to_string(),
+ ],
+ expected: vec![
+ "ISPRODUCTION=true".to_string(),
+ "ISDEVELOPMENT=false".to_string(),
+ ],
+ },
+ // Test that when none of the variables match do not override them
+ TestData {
+ container_process_env: vec!["ANOTHERENV=TEST".to_string()],
+ image_process_env: vec![
+ "ISPRODUCTION=false".to_string(),
+ "ISDEVELOPMENT=true".to_string(),
+ ],
+ expected: vec![
+ "ANOTHERENV=TEST".to_string(),
+ "ISPRODUCTION=false".to_string(),
+ "ISDEVELOPMENT=true".to_string(),
+ ],
+ },
+ // Test a mix of both overriding and not
+ TestData {
+ container_process_env: vec![
+ "ANOTHERENV=TEST".to_string(),
+ "ISPRODUCTION=true".to_string(),
+ ],
+ image_process_env: vec![
+ "ISPRODUCTION=false".to_string(),
+ "ISDEVELOPMENT=true".to_string(),
+ ],
+ expected: vec![
+ "ANOTHERENV=TEST".to_string(),
+ "ISPRODUCTION=true".to_string(),
+ "ISDEVELOPMENT=true".to_string(),
+ ],
+ },
+ ];
+
+ for (i, d) in tests.iter().enumerate() {
+ let msg = format!("test[{}]: {:?}", i, d);
+
+ let mut container_process = oci::Process {
+ env: d.container_process_env.clone(),
+ ..Default::default()
+ };
+
+ let image_process = oci::Process {
+ env: d.image_process_env.clone(),
+ ..Default::default()
+ };
+
+ merge_oci_process(&mut container_process, &image_process);
+
+ assert_eq!(d.expected, container_process.env, "{}", msg);
+ }
+ }
}
diff --git a/src/agent/src/sandbox.rs b/src/agent/src/sandbox.rs
index 8f93fdd5b..9ed7f9720 100644
--- a/src/agent/src/sandbox.rs
+++ b/src/agent/src/sandbox.rs
@@ -60,6 +60,7 @@ pub struct Sandbox {
pub event_tx: Option<Sender<String>>,
pub bind_watcher: BindWatcher,
pub pcimap: HashMap<pci::Address, pci::Address>,
+ pub images: HashMap<String, String>,
}
impl Sandbox {
@@ -93,6 +94,7 @@ impl Sandbox {
event_tx: Some(tx),
bind_watcher: BindWatcher::new(),
pcimap: HashMap::new(),
+ images: HashMap::new(),
})
}
@@ -296,7 +298,6 @@ impl Sandbox {
info!(self.logger, "updating {}", ctr.id.as_str());
ctr.cgroup_manager
.as_ref()
- .unwrap()
.update_cpuset_path(guest_cpuset.as_str(), container_cpust)?;
}
@@ -327,7 +328,7 @@ impl Sandbox {
// Reject non-file, symlinks and non-executable files
if !entry.file_type()?.is_file()
|| entry.file_type()?.is_symlink()
- || entry.metadata()?.permissions().mode() & 0o777 & 0o111 == 0
+ || entry.metadata()?.permissions().mode() & 0o111 == 0
{
continue;
}
@@ -1073,7 +1074,7 @@ mod tests {
fs::create_dir(&subdir_path).unwrap();
for file in j.files {
let subfile_path = format!("{}/{}", subdir_path, file.name);
- let mut subfile = File::create(&subfile_path).unwrap();
+ let mut subfile = File::create(subfile_path).unwrap();
subfile.write_all(file.content.as_bytes()).unwrap();
}
}
diff --git a/src/agent/src/signal.rs b/src/agent/src/signal.rs
index 79dea3b08..a22892db3 100644
--- a/src/agent/src/signal.rs
+++ b/src/agent/src/signal.rs
@@ -24,7 +24,7 @@ async fn handle_sigchild(logger: Logger, sandbox: Arc<Mutex<Sandbox>>) -> Result
loop {
// Avoid reaping the undesirable child's signal, e.g., execute_hook's
// The lock should be released immediately.
- rustjail::container::WAIT_PID_LOCKER.lock().await;
+ let _ = rustjail::container::WAIT_PID_LOCKER.lock().await;
let result = wait::waitpid(
Some(Pid::from_raw(-1)),
Some(WaitPidFlag::WNOHANG | WaitPidFlag::__WALL),
diff --git a/src/agent/src/watcher.rs b/src/agent/src/watcher.rs
index 0a6a72f39..468684a43 100644
--- a/src/agent/src/watcher.rs
+++ b/src/agent/src/watcher.rs
@@ -11,7 +11,7 @@ use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::SystemTime;
-use anyhow::{ensure, Context, Result};
+use anyhow::{anyhow, ensure, Context, Result};
use async_recursion::async_recursion;
use nix::mount::{umount, MsFlags};
use nix::unistd::{Gid, Uid};
@@ -34,9 +34,13 @@ const MAX_SIZE_PER_WATCHABLE_MOUNT: u64 = 1024 * 1024;
/// How often to check for modified files.
const WATCH_INTERVAL_SECS: u64 = 2;
-/// Destination path for tmpfs
+/// Destination path for tmpfs, which used by the golang runtime
const WATCH_MOUNT_POINT_PATH: &str = "/run/kata-containers/shared/containers/watchable/";
+/// Destination path for tmpfs for runtime-rs passthrough file sharing
+const WATCH_MOUNT_POINT_PATH_PASSTHROUGH: &str =
+ "/run/kata-containers/shared/containers/passthrough/watchable/";
+
/// Represents a single watched storage entry which may have multiple files to watch.
#[derive(Default, Debug, Clone)]
struct Storage {
@@ -120,7 +124,7 @@ impl Storage {
// if we are creating a directory: just create it, nothing more to do
if metadata.file_type().is_dir() {
- let dest_file_path = self.make_target_path(&source_file_path)?;
+ let dest_file_path = self.make_target_path(source_file_path)?;
fs::create_dir_all(&dest_file_path)
.await
@@ -148,7 +152,7 @@ impl Storage {
// Assume target mount is a file path
self.target_mount_point.clone()
} else {
- let dest_file_path = self.make_target_path(&source_file_path)?;
+ let dest_file_path = self.make_target_path(source_file_path)?;
if let Some(path) = dest_file_path.parent() {
debug!(logger, "Creating destination directory: {}", path.display());
@@ -451,7 +455,7 @@ impl BindWatcher {
) -> Result<()> {
if self.watch_thread.is_none() {
// Virtio-fs shared path is RO by default, so we back the target-mounts by tmpfs.
- self.mount(logger).await?;
+ self.mount(logger).await.context("mount watch directory")?;
// Spawn background thread to monitor changes
self.watch_thread = Some(Self::spawn_watcher(
@@ -500,16 +504,28 @@ impl BindWatcher {
}
async fn mount(&self, logger: &Logger) -> Result<()> {
- fs::create_dir_all(WATCH_MOUNT_POINT_PATH).await?;
+ // the watchable directory is created on the host side.
+ // here we can only check if it exist.
+ // first we will check the default WATCH_MOUNT_POINT_PATH,
+ // and then check WATCH_MOUNT_POINT_PATH_PASSTHROUGH
+ // in turn which are introduced by runtime-rs file sharing.
+ let watchable_dir = if Path::new(WATCH_MOUNT_POINT_PATH).is_dir() {
+ WATCH_MOUNT_POINT_PATH
+ } else if Path::new(WATCH_MOUNT_POINT_PATH_PASSTHROUGH).is_dir() {
+ WATCH_MOUNT_POINT_PATH_PASSTHROUGH
+ } else {
+ return Err(anyhow!("watchable mount source not found"));
+ };
baremount(
Path::new("tmpfs"),
- Path::new(WATCH_MOUNT_POINT_PATH),
+ Path::new(watchable_dir),
"tmpfs",
MsFlags::empty(),
"",
logger,
- )?;
+ )
+ .context("baremount watchable mount path")?;
Ok(())
}
@@ -520,7 +536,12 @@ impl BindWatcher {
handle.abort();
}
- let _ = umount(WATCH_MOUNT_POINT_PATH);
+ // try umount watchable mount path in turn
+ if Path::new(WATCH_MOUNT_POINT_PATH).is_dir() {
+ let _ = umount(WATCH_MOUNT_POINT_PATH);
+ } else if Path::new(WATCH_MOUNT_POINT_PATH_PASSTHROUGH).is_dir() {
+ let _ = umount(WATCH_MOUNT_POINT_PATH_PASSTHROUGH);
+ }
}
}
@@ -529,6 +550,7 @@ mod tests {
use super::*;
use crate::mount::is_mounted;
use nix::unistd::{Gid, Uid};
+ use scopeguard::defer;
use std::fs;
use std::thread;
use test_utils::skip_if_not_root;
@@ -756,7 +778,7 @@ mod tests {
22
);
assert_eq!(
- fs::read_to_string(&entries.0[0].target_mount_point.as_path().join("1.txt")).unwrap(),
+ fs::read_to_string(entries.0[0].target_mount_point.as_path().join("1.txt")).unwrap(),
"updated"
);
@@ -801,7 +823,7 @@ mod tests {
2
);
assert_eq!(
- fs::read_to_string(&entries.0[1].target_mount_point.as_path().join("foo.txt")).unwrap(),
+ fs::read_to_string(entries.0[1].target_mount_point.as_path().join("foo.txt")).unwrap(),
"updated"
);
@@ -978,7 +1000,7 @@ mod tests {
// create a path we'll remove later
fs::create_dir_all(source_dir.path().join("tmp")).unwrap();
- fs::write(&source_dir.path().join("tmp/test-file"), "foo").unwrap();
+ fs::write(source_dir.path().join("tmp/test-file"), "foo").unwrap();
assert_eq!(entry.scan(&logger).await.unwrap(), 3); // root, ./tmp, test-file
// Verify expected directory, file:
@@ -1275,13 +1297,19 @@ mod tests {
let logger = slog::Logger::root(slog::Discard, o!());
let mut watcher = BindWatcher::default();
- watcher.mount(&logger).await.unwrap();
- assert!(is_mounted(WATCH_MOUNT_POINT_PATH).unwrap());
+ for mount_point in [WATCH_MOUNT_POINT_PATH, WATCH_MOUNT_POINT_PATH_PASSTHROUGH] {
+ fs::create_dir_all(mount_point).unwrap();
+ // ensure the watchable directory is deleted.
+ defer!(fs::remove_dir_all(mount_point).unwrap());
- thread::sleep(Duration::from_millis(20));
+ watcher.mount(&logger).await.unwrap();
+ assert!(is_mounted(mount_point).unwrap());
+
+ thread::sleep(Duration::from_millis(20));
- watcher.cleanup();
- assert!(!is_mounted(WATCH_MOUNT_POINT_PATH).unwrap());
+ watcher.cleanup();
+ assert!(!is_mounted(mount_point).unwrap());
+ }
}
#[tokio::test]
@@ -1289,6 +1317,10 @@ mod tests {
async fn spawn_thread() {
skip_if_not_root!();
+ fs::create_dir_all(WATCH_MOUNT_POINT_PATH).unwrap();
+ // ensure the watchable directory is deleted.
+ defer!(fs::remove_dir_all(WATCH_MOUNT_POINT_PATH).unwrap());
+
let source_dir = tempfile::tempdir().unwrap();
fs::write(source_dir.path().join("1.txt"), "one").unwrap();
@@ -1319,6 +1351,10 @@ mod tests {
async fn verify_container_cleanup_watching() {
skip_if_not_root!();
+ fs::create_dir_all(WATCH_MOUNT_POINT_PATH).unwrap();
+ // ensure the watchable directory is deleted.
+ defer!(fs::remove_dir_all(WATCH_MOUNT_POINT_PATH).unwrap());
+
let source_dir = tempfile::tempdir().unwrap();
fs::write(source_dir.path().join("1.txt"), "one").unwrap();
diff --git a/src/dragonball/Cargo.toml b/src/dragonball/Cargo.toml
index df8286bfe..9ef43a3e2 100644
--- a/src/dragonball/Cargo.toml
+++ b/src/dragonball/Cargo.toml
@@ -12,21 +12,21 @@ edition = "2018"
[dependencies]
arc-swap = "1.5.0"
bytes = "1.1.0"
-dbs-address-space = "0.1.0"
+dbs-address-space = "0.2.0"
dbs-allocator = "0.1.0"
-dbs-arch = "0.1.0"
-dbs-boot = "0.2.0"
-dbs-device = "0.1.0"
-dbs-interrupt = { version = "0.1.0", features = ["kvm-irq"] }
+dbs-arch = "0.2.0"
+dbs-boot = "0.3.0"
+dbs-device = "0.2.0"
+dbs-interrupt = { version = "0.2.0", features = ["kvm-irq"] }
dbs-legacy-devices = "0.1.0"
dbs-upcall = { version = "0.1.0", optional = true }
-dbs-utils = "0.1.0"
+dbs-utils = "0.2.0"
dbs-virtio-devices = { version = "0.1.0", optional = true, features = ["virtio-mmio"] }
kvm-bindings = "0.5.0"
kvm-ioctls = "0.11.0"
lazy_static = "1.2"
libc = "0.2.39"
-linux-loader = "0.4.0"
+linux-loader = "0.6.0"
log = "0.4.14"
nix = "0.24.2"
seccompiler = "0.2.0"
@@ -36,30 +36,21 @@ serde_json = "1.0.9"
slog = "2.5.2"
slog-scope = "4.4.0"
thiserror = "1"
-vmm-sys-util = "0.9.0"
-virtio-queue = { version = "0.1.0", optional = true }
-vm-memory = { version = "0.7.0", features = ["backend-mmap"] }
+vmm-sys-util = "0.11.0"
+virtio-queue = { version = "0.4.0", optional = true }
+vm-memory = { version = "0.9.0", features = ["backend-mmap"] }
[dev-dependencies]
slog-term = "2.9.0"
slog-async = "2.7.0"
+test-utils = { path = "../libs/test-utils" }
[features]
acpi = []
-atomic-guest-memory = []
+atomic-guest-memory = [ "vm-memory/backend-atomic" ]
hotplug = ["virtio-vsock"]
virtio-vsock = ["dbs-virtio-devices/virtio-vsock", "virtio-queue"]
virtio-blk = ["dbs-virtio-devices/virtio-blk", "virtio-queue"]
virtio-net = ["dbs-virtio-devices/virtio-net", "virtio-queue"]
# virtio-fs only work on atomic-guest-memory
virtio-fs = ["dbs-virtio-devices/virtio-fs", "virtio-queue", "atomic-guest-memory"]
-
-[patch.'crates-io']
-dbs-device = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
-dbs-interrupt = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
-dbs-legacy-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
-dbs-upcall = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
-dbs-utils = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
-dbs-virtio-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
-dbs-boot = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
-dbs-arch = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
diff --git a/src/dragonball/Makefile b/src/dragonball/Makefile
index 8acd29de5..ab8e5b694 100644
--- a/src/dragonball/Makefile
+++ b/src/dragonball/Makefile
@@ -2,12 +2,22 @@
# Copyright (c) 2019-2022 Ant Group. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
+include ../../utils.mk
+
+ifeq ($(ARCH), s390x)
+default build check test clippy:
+ @echo "s390x not support currently"
+ exit 0
+else
+
default: build
build:
- # FIXME: This line will be removed when we solve the vm-memory dependency problem in Dragonball Sandbox
- cargo update -p vm-memory:0.8.0 --precise 0.7.0
- cargo build --all-features
+ @echo "INFO: cargo build..."
+ cargo build --all-features --target $(TRIPLE)
+
+static-checks-build:
+ @echo "INFO: static-checks-build do nothing.."
check: clippy format
@@ -17,6 +27,9 @@ clippy:
-- \
-D warnings
+vendor:
+ @echo "INFO: vendor do nothing.."
+
format:
@echo "INFO: cargo fmt..."
cargo fmt -- --check
@@ -25,5 +38,13 @@ clean:
cargo clean
test:
- @echo "INFO: testing dragonball for development build"
- cargo test --all-features -- --nocapture
+ifdef SUPPORT_VIRTUALIZATION
+ cargo test --all-features --target $(TRIPLE) -- --nocapture
+else
+ @echo "INFO: skip testing dragonball, it need virtualization support."
+ exit 0
+endif
+
+endif # ifeq ($(ARCH), s390x)
+
+.DEFAULT_GOAL := default
diff --git a/src/dragonball/src/address_space_manager.rs b/src/dragonball/src/address_space_manager.rs
index 9992833e0..0e9ac91d7 100644
--- a/src/dragonball/src/address_space_manager.rs
+++ b/src/dragonball/src/address_space_manager.rs
@@ -33,10 +33,10 @@ use log::{debug, error, info, warn};
use nix::sys::mman;
use nix::unistd::dup;
#[cfg(feature = "atomic-guest-memory")]
-use vm_memory::atomic::GuestMemoryAtomic;
+use vm_memory::GuestMemoryAtomic;
use vm_memory::{
- Address, FileOffset, GuestAddress, GuestAddressSpace, GuestMemoryMmap, GuestMemoryRegion,
- GuestRegionMmap, GuestUsize, MemoryRegionAddress, MmapRegion,
+ address::Address, FileOffset, GuestAddress, GuestAddressSpace, GuestMemoryMmap,
+ GuestMemoryRegion, GuestRegionMmap, GuestUsize, MemoryRegionAddress, MmapRegion,
};
use crate::resource_manager::ResourceManager;
@@ -270,7 +270,7 @@ impl AddressSpaceMgr {
let size = info
.size
.checked_shl(20)
- .ok_or_else(|| AddressManagerError::InvalidOperation)?;
+ .ok_or(AddressManagerError::InvalidOperation)?;
// Guest memory does not intersect with the MMIO hole.
// TODO: make it work for ARM (issue #4307)
@@ -281,13 +281,13 @@ impl AddressSpaceMgr {
regions.push(region);
start_addr = start_addr
.checked_add(size)
- .ok_or_else(|| AddressManagerError::InvalidOperation)?;
+ .ok_or(AddressManagerError::InvalidOperation)?;
} else {
// Add guest memory below the MMIO hole, avoid splitting the memory region
// if the available address region is small than MINIMAL_SPLIT_SPACE MiB.
let mut below_size = dbs_boot::layout::MMIO_LOW_START
.checked_sub(start_addr)
- .ok_or_else(|| AddressManagerError::InvalidOperation)?;
+ .ok_or(AddressManagerError::InvalidOperation)?;
if below_size < (MINIMAL_SPLIT_SPACE) {
below_size = 0;
} else {
@@ -299,12 +299,12 @@ impl AddressSpaceMgr {
let above_start = dbs_boot::layout::MMIO_LOW_END + 1;
let above_size = size
.checked_sub(below_size)
- .ok_or_else(|| AddressManagerError::InvalidOperation)?;
+ .ok_or(AddressManagerError::InvalidOperation)?;
let region = self.create_region(above_start, above_size, info, &mut param)?;
regions.push(region);
start_addr = above_start
.checked_add(above_size)
- .ok_or_else(|| AddressManagerError::InvalidOperation)?;
+ .ok_or(AddressManagerError::InvalidOperation)?;
}
}
@@ -401,9 +401,9 @@ impl AddressSpaceMgr {
let flags = 0u32;
let mem_region = kvm_userspace_memory_region {
- slot: slot as u32,
+ slot,
guest_phys_addr: reg.start_addr().raw_value(),
- memory_size: reg.len() as u64,
+ memory_size: reg.len(),
userspace_addr: host_addr as u64,
flags,
};
@@ -421,7 +421,7 @@ impl AddressSpaceMgr {
self.base_to_slot
.lock()
.unwrap()
- .insert(reg.start_addr().raw_value(), slot as u32);
+ .insert(reg.start_addr().raw_value(), slot);
Ok(())
}
@@ -502,7 +502,7 @@ impl AddressSpaceMgr {
fn configure_numa(&self, mmap_reg: &MmapRegion, node_id: u32) -> Result<()> {
let nodemask = 1_u64
.checked_shl(node_id)
- .ok_or_else(|| AddressManagerError::InvalidOperation)?;
+ .ok_or(AddressManagerError::InvalidOperation)?;
let res = unsafe {
libc::syscall(
libc::SYS_mbind,
diff --git a/src/dragonball/src/api/v1/boot_source.rs b/src/dragonball/src/api/v1/boot_source.rs
index 8ff7e030d..612de04a1 100644
--- a/src/dragonball/src/api/v1/boot_source.rs
+++ b/src/dragonball/src/api/v1/boot_source.rs
@@ -18,7 +18,7 @@ pub const DEFAULT_KERNEL_CMDLINE: &str = "reboot=k panic=1 pci=off nomodules 825
i8042.noaux i8042.nomux i8042.nopnp i8042.dumbkbd";
/// Strongly typed data structure used to configure the boot source of the microvm.
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Default)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, Default)]
#[serde(deny_unknown_fields)]
pub struct BootSourceConfig {
/// Path of the kernel image.
diff --git a/src/dragonball/src/api/v1/instance_info.rs b/src/dragonball/src/api/v1/instance_info.rs
index ae159aa61..86174a2fd 100644
--- a/src/dragonball/src/api/v1/instance_info.rs
+++ b/src/dragonball/src/api/v1/instance_info.rs
@@ -10,7 +10,7 @@ use serde_derive::{Deserialize, Serialize};
/// When Dragonball starts, the instance state is Uninitialized. Once start_microvm method is
/// called, the state goes from Uninitialized to Starting. The state is changed to Running until
/// the start_microvm method ends. Halting and Halted are currently unsupported.
-#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)]
+#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub enum InstanceState {
/// Microvm is not initialized.
Uninitialized,
@@ -29,7 +29,7 @@ pub enum InstanceState {
}
/// The state of async actions
-#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
+#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub enum AsyncState {
/// Uninitialized
Uninitialized,
diff --git a/src/dragonball/src/api/v1/machine_config.rs b/src/dragonball/src/api/v1/machine_config.rs
index e4ae22867..7d78f3e44 100644
--- a/src/dragonball/src/api/v1/machine_config.rs
+++ b/src/dragonball/src/api/v1/machine_config.rs
@@ -10,7 +10,7 @@ pub const MAX_SUPPORTED_VCPUS: u8 = 254;
pub const MEMORY_HOTPLUG_ALIGHMENT: u8 = 64;
/// Errors associated with configuring the microVM.
-#[derive(Debug, PartialEq, thiserror::Error)]
+#[derive(Debug, PartialEq, Eq, thiserror::Error)]
pub enum VmConfigError {
/// Cannot update the configuration of the microvm post boot.
#[error("update operation is not allowed after boot")]
diff --git a/src/dragonball/src/api/v1/vmm_action.rs b/src/dragonball/src/api/v1/vmm_action.rs
index 06004f3f0..45591e7ed 100644
--- a/src/dragonball/src/api/v1/vmm_action.rs
+++ b/src/dragonball/src/api/v1/vmm_action.rs
@@ -83,13 +83,13 @@ pub enum VmmActionError {
#[cfg(feature = "virtio-fs")]
/// The action `InsertFsDevice` failed either because of bad user input or an internal error.
- #[error("virtio-fs device: {0}")]
+ #[error("virtio-fs device error: {0}")]
FsDevice(#[source] FsDeviceError),
}
/// This enum represents the public interface of the VMM. Each action contains various
/// bits of information (ids, paths, etc.).
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
pub enum VmmAction {
/// Configure the boot source of the microVM using `BootSourceConfig`.
/// This action can only be called before the microVM has booted.
@@ -298,7 +298,6 @@ impl VmmService {
let mut cmdline = linux_loader::cmdline::Cmdline::new(dbs_boot::layout::CMDLINE_MAX_SIZE);
let boot_args = boot_source_config
.boot_args
- .clone()
.unwrap_or_else(|| String::from(DEFAULT_KERNEL_CMDLINE));
cmdline
.insert_str(boot_args)
@@ -407,19 +406,10 @@ impl VmmService {
}
config.vpmu_feature = machine_config.vpmu_feature;
- let vm_id = vm.shared_info().read().unwrap().id.clone();
- let serial_path = match machine_config.serial_path {
- Some(value) => value,
- None => {
- if config.serial_path.is_none() {
- String::from("/run/dragonball/") + &vm_id + "_com1"
- } else {
- // Safe to unwrap() because we have checked it has a value.
- config.serial_path.as_ref().unwrap().clone()
- }
- }
- };
- config.serial_path = Some(serial_path);
+ // If serial_path is:
+ // - None, legacy_manager will create_stdio_console.
+ // - Some(path), legacy_manager will create_socket_console on that path.
+ config.serial_path = machine_config.serial_path;
vm.set_vm_config(config.clone());
self.machine_config = config;
@@ -634,3 +624,783 @@ fn handle_cpu_topology(
Ok(cpu_topology)
}
+
+#[cfg(test)]
+mod tests {
+ use std::sync::mpsc::channel;
+ use std::sync::{Arc, Mutex};
+
+ use dbs_utils::epoll_manager::EpollManager;
+ use test_utils::skip_if_not_root;
+ use vmm_sys_util::tempfile::TempFile;
+
+ use super::*;
+ use crate::vmm::tests::create_vmm_instance;
+
+ struct TestData<'a> {
+ req: Option<VmmAction>,
+ vm_state: InstanceState,
+ f: &'a dyn Fn(VmmRequestResult),
+ }
+
+ impl<'a> TestData<'a> {
+ fn new(req: VmmAction, vm_state: InstanceState, f: &'a dyn Fn(VmmRequestResult)) -> Self {
+ Self {
+ req: Some(req),
+ vm_state,
+ f,
+ }
+ }
+
+ fn check_request(&mut self) {
+ let (to_vmm, from_api) = channel();
+ let (to_api, from_vmm) = channel();
+
+ let vmm = Arc::new(Mutex::new(create_vmm_instance()));
+ let mut vservice = VmmService::new(from_api, to_api);
+
+ let epoll_mgr = EpollManager::default();
+ let mut event_mgr = EventManager::new(&vmm, epoll_mgr).unwrap();
+ let mut v = vmm.lock().unwrap();
+
+ let vm = v.get_vm_mut().unwrap();
+ vm.set_instance_state(self.vm_state);
+
+ to_vmm.send(Box::new(self.req.take().unwrap())).unwrap();
+ assert!(vservice.run_vmm_action(&mut v, &mut event_mgr).is_ok());
+
+ let response = from_vmm.try_recv();
+ assert!(response.is_ok());
+ (self.f)(*response.unwrap());
+ }
+ }
+
+ #[test]
+ fn test_vmm_action_receive_unknown() {
+ skip_if_not_root!();
+
+ let (_to_vmm, from_api) = channel();
+ let (to_api, _from_vmm) = channel();
+ let vmm = Arc::new(Mutex::new(create_vmm_instance()));
+ let mut vservice = VmmService::new(from_api, to_api);
+ let epoll_mgr = EpollManager::default();
+ let mut event_mgr = EventManager::new(&vmm, epoll_mgr).unwrap();
+ let mut v = vmm.lock().unwrap();
+
+ assert!(vservice.run_vmm_action(&mut v, &mut event_mgr).is_ok());
+ }
+
+ #[should_panic]
+ #[test]
+ fn test_vmm_action_disconnected() {
+ let (to_vmm, from_api) = channel();
+ let (to_api, _from_vmm) = channel();
+ let vmm = Arc::new(Mutex::new(create_vmm_instance()));
+ let mut vservice = VmmService::new(from_api, to_api);
+ let epoll_mgr = EpollManager::default();
+ let mut event_mgr = EventManager::new(&vmm, epoll_mgr).unwrap();
+ let mut v = vmm.lock().unwrap();
+
+ drop(to_vmm);
+ vservice.run_vmm_action(&mut v, &mut event_mgr).unwrap();
+ }
+
+ #[test]
+ fn test_vmm_action_config_boot_source() {
+ skip_if_not_root!();
+
+ let kernel_file = TempFile::new().unwrap();
+
+ let tests = &mut [
+ // invalid state
+ TestData::new(
+ VmmAction::ConfigureBootSource(BootSourceConfig::default()),
+ InstanceState::Running,
+ &|result| {
+ if let Err(VmmActionError::BootSource(
+ BootSourceConfigError::UpdateNotAllowedPostBoot,
+ )) = result
+ {
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "failed to configure boot source for VM: \
+ the update operation is not allowed after boot",
+ );
+ assert_eq!(err_string, expected_err);
+ } else {
+ panic!();
+ }
+ },
+ ),
+ // invalid kernel file path
+ TestData::new(
+ VmmAction::ConfigureBootSource(BootSourceConfig::default()),
+ InstanceState::Uninitialized,
+ &|result| {
+ if let Err(VmmActionError::BootSource(
+ BootSourceConfigError::InvalidKernelPath(_),
+ )) = result
+ {
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "failed to configure boot source for VM: \
+ the kernel file cannot be opened due to invalid kernel path or invalid permissions: \
+ No such file or directory (os error 2)");
+ assert_eq!(err_string, expected_err);
+ } else {
+ panic!();
+ }
+ },
+ ),
+ //success
+ TestData::new(
+ VmmAction::ConfigureBootSource(BootSourceConfig {
+ kernel_path: kernel_file.as_path().to_str().unwrap().to_string(),
+ ..Default::default()
+ }),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(result.is_ok());
+ },
+ ),
+ ];
+
+ for t in tests.iter_mut() {
+ t.check_request();
+ }
+ }
+
+ #[test]
+ fn test_vmm_action_set_vm_configuration() {
+ skip_if_not_root!();
+
+ let tests = &mut [
+ // invalid state
+ TestData::new(
+ VmmAction::SetVmConfiguration(VmConfigInfo::default()),
+ InstanceState::Running,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::MachineConfig(
+ VmConfigError::UpdateNotAllowedPostBoot
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "failed to set configuration for the VM: \
+ update operation is not allowed after boot",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ // invalid cpu count (0)
+ TestData::new(
+ VmmAction::SetVmConfiguration(VmConfigInfo {
+ vcpu_count: 0,
+ ..Default::default()
+ }),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::MachineConfig(
+ VmConfigError::InvalidVcpuCount(0)
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "failed to set configuration for the VM: \
+ the vCPU number '0' can only be 1 or an even number when hyperthreading is enabled");
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ // invalid max cpu count (too small)
+ TestData::new(
+ VmmAction::SetVmConfiguration(VmConfigInfo {
+ vcpu_count: 4,
+ max_vcpu_count: 2,
+ ..Default::default()
+ }),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::MachineConfig(
+ VmConfigError::InvalidMaxVcpuCount(2)
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "failed to set configuration for the VM: \
+ the max vCPU number '2' shouldn't less than vCPU count and can only be 1 or an even number when hyperthreading is enabled");
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ // invalid cpu topology (larger than 254)
+ TestData::new(
+ VmmAction::SetVmConfiguration(VmConfigInfo {
+ vcpu_count: 254,
+ cpu_topology: CpuTopology {
+ threads_per_core: 2,
+ cores_per_die: 128,
+ dies_per_socket: 1,
+ sockets: 1,
+ },
+ ..Default::default()
+ }),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::MachineConfig(
+ VmConfigError::VcpuCountExceedsMaximum
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "failed to set configuration for the VM: \
+ the vCPU number shouldn't large than 254",
+ );
+
+ assert_eq!(err_string, expected_err)
+ },
+ ),
+ // cpu topology and max_vcpu_count are not matched - success
+ TestData::new(
+ VmmAction::SetVmConfiguration(VmConfigInfo {
+ vcpu_count: 16,
+ max_vcpu_count: 32,
+ cpu_topology: CpuTopology {
+ threads_per_core: 1,
+ cores_per_die: 128,
+ dies_per_socket: 1,
+ sockets: 1,
+ },
+ ..Default::default()
+ }),
+ InstanceState::Uninitialized,
+ &|result| {
+ result.unwrap();
+ },
+ ),
+ // invalid threads_per_core
+ TestData::new(
+ VmmAction::SetVmConfiguration(VmConfigInfo {
+ vcpu_count: 4,
+ max_vcpu_count: 4,
+ cpu_topology: CpuTopology {
+ threads_per_core: 4,
+ cores_per_die: 1,
+ dies_per_socket: 1,
+ sockets: 1,
+ },
+ ..Default::default()
+ }),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::MachineConfig(
+ VmConfigError::InvalidThreadsPerCore(4)
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "failed to set configuration for the VM: \
+ the threads_per_core number '4' can only be 1 or 2",
+ );
+
+ assert_eq!(err_string, expected_err)
+ },
+ ),
+ // invalid mem size
+ TestData::new(
+ VmmAction::SetVmConfiguration(VmConfigInfo {
+ mem_size_mib: 3,
+ ..Default::default()
+ }),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::MachineConfig(
+ VmConfigError::InvalidMemorySize(3)
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "failed to set configuration for the VM: \
+ the memory size 0x3MiB is invalid",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ // invalid mem path
+ TestData::new(
+ VmmAction::SetVmConfiguration(VmConfigInfo {
+ mem_type: String::from("hugetlbfs"),
+ mem_file_path: String::from(""),
+ ..Default::default()
+ }),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::MachineConfig(
+ VmConfigError::InvalidMemFilePath(_)
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "failed to set configuration for the VM: \
+ the memory file path is invalid",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ // success
+ TestData::new(
+ VmmAction::SetVmConfiguration(VmConfigInfo::default()),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(result.is_ok());
+ },
+ ),
+ ];
+
+ for t in tests.iter_mut() {
+ t.check_request();
+ }
+ }
+
+ #[test]
+ fn test_vmm_action_start_microvm() {
+ skip_if_not_root!();
+
+ let tests = &mut [
+ // invalid state (running)
+ TestData::new(VmmAction::StartMicroVm, InstanceState::Running, &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::StartMicroVm(
+ StartMicroVmError::MicroVMAlreadyRunning
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "failed to boot the VM: \
+ the virtual machine is already running",
+ );
+ assert_eq!(err_string, expected_err);
+ }),
+ // no kernel configuration
+ TestData::new(
+ VmmAction::StartMicroVm,
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::StartMicroVm(
+ StartMicroVmError::MissingKernelConfig
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "failed to boot the VM: \
+ cannot start the virtual machine without kernel configuration",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ ];
+
+ for t in tests.iter_mut() {
+ t.check_request();
+ }
+ }
+
+ #[test]
+ fn test_vmm_action_shutdown_microvm() {
+ skip_if_not_root!();
+
+ let tests = &mut [
+ // success
+ TestData::new(
+ VmmAction::ShutdownMicroVm,
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(result.is_ok());
+ },
+ ),
+ ];
+
+ for t in tests.iter_mut() {
+ t.check_request();
+ }
+ }
+
+ #[cfg(feature = "virtio-blk")]
+ #[test]
+ fn test_vmm_action_insert_block_device() {
+ skip_if_not_root!();
+
+ let dummy_file = TempFile::new().unwrap();
+ let dummy_path = dummy_file.as_path().to_owned();
+
+ let tests = &mut [
+ // invalid state
+ TestData::new(
+ VmmAction::InsertBlockDevice(BlockDeviceConfigInfo::default()),
+ InstanceState::Running,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::Block(
+ BlockDeviceError::UpdateNotAllowedPostBoot
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "virtio-blk device error: \
+ block device does not support runtime update",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ // success
+ TestData::new(
+ VmmAction::InsertBlockDevice(BlockDeviceConfigInfo {
+ path_on_host: dummy_path,
+ device_type: crate::device_manager::blk_dev_mgr::BlockDeviceType::RawBlock,
+ is_root_device: true,
+ part_uuid: None,
+ is_read_only: false,
+ is_direct: false,
+ no_drop: false,
+ drive_id: String::from("1"),
+ rate_limiter: None,
+ num_queues: BlockDeviceConfigInfo::default_num_queues(),
+ queue_size: 256,
+ use_shared_irq: None,
+ use_generic_irq: None,
+ }),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(result.is_ok());
+ },
+ ),
+ ];
+
+ for t in tests.iter_mut() {
+ t.check_request();
+ }
+ }
+
+ #[cfg(feature = "virtio-blk")]
+ #[test]
+ fn test_vmm_action_update_block_device() {
+ skip_if_not_root!();
+
+ let tests = &mut [
+ // invalid id
+ TestData::new(
+ VmmAction::UpdateBlockDevice(BlockDeviceConfigUpdateInfo {
+ drive_id: String::from("1"),
+ rate_limiter: None,
+ }),
+ InstanceState::Running,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::Block(BlockDeviceError::InvalidDeviceId(_)))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "virtio-blk device error: \
+ invalid block device id '1'",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ ];
+
+ for t in tests.iter_mut() {
+ t.check_request();
+ }
+ }
+
+ #[cfg(feature = "virtio-blk")]
+ #[test]
+ fn test_vmm_action_remove_block_device() {
+ skip_if_not_root!();
+
+ let tests = &mut [
+ // invalid state
+ TestData::new(
+ VmmAction::RemoveBlockDevice(String::from("1")),
+ InstanceState::Running,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::Block(
+ BlockDeviceError::UpdateNotAllowedPostBoot
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "virtio-blk device error: \
+ block device does not support runtime update",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ // invalid id
+ TestData::new(
+ VmmAction::RemoveBlockDevice(String::from("1")),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::Block(BlockDeviceError::InvalidDeviceId(_)))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "virtio-blk device error: \
+ invalid block device id '1'",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ ];
+
+ for t in tests.iter_mut() {
+ t.check_request();
+ }
+ }
+
+ #[cfg(feature = "virtio-fs")]
+ #[test]
+ fn test_vmm_action_insert_fs_device() {
+ skip_if_not_root!();
+
+ let tests = &mut [
+ // invalid state
+ TestData::new(
+ VmmAction::InsertFsDevice(FsDeviceConfigInfo::default()),
+ InstanceState::Running,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::FsDevice(
+ FsDeviceError::UpdateNotAllowedPostBoot
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "virtio-fs device error: \
+ update operation is not allowed after boot",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ // success
+ TestData::new(
+ VmmAction::InsertFsDevice(FsDeviceConfigInfo::default()),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(result.is_ok());
+ },
+ ),
+ ];
+
+ for t in tests.iter_mut() {
+ t.check_request();
+ }
+ }
+
+ #[cfg(feature = "virtio-fs")]
+ #[test]
+ fn test_vmm_action_manipulate_fs_device() {
+ skip_if_not_root!();
+
+ let tests = &mut [
+ // invalid state
+ TestData::new(
+ VmmAction::ManipulateFsBackendFs(FsMountConfigInfo::default()),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::FsDevice(FsDeviceError::MicroVMNotRunning))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "virtio-fs device error: \
+ vm is not running when attaching a backend fs",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ // invalid backend
+ TestData::new(
+ VmmAction::ManipulateFsBackendFs(FsMountConfigInfo::default()),
+ InstanceState::Running,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::FsDevice(
+ FsDeviceError::AttachBackendFailed(_)
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ println!("{}", err_string);
+ let expected_err = String::from(
+ "virtio-fs device error: \
+ Fs device attach a backend fs failed",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ ];
+ for t in tests.iter_mut() {
+ t.check_request();
+ }
+ }
+
+ #[cfg(feature = "virtio-net")]
+ #[test]
+ fn test_vmm_action_insert_network_device() {
+ skip_if_not_root!();
+
+ let tests = &mut [
+ // hotplug unready
+ TestData::new(
+ VmmAction::InsertNetworkDevice(VirtioNetDeviceConfigInfo::default()),
+ InstanceState::Running,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::StartMicroVm(
+ StartMicroVmError::UpcallMissVsock
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "failed to boot the VM: \
+ the upcall client needs a virtio-vsock device for communication",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ // success
+ TestData::new(
+ VmmAction::InsertNetworkDevice(VirtioNetDeviceConfigInfo::default()),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(result.is_ok());
+ },
+ ),
+ ];
+
+ for t in tests.iter_mut() {
+ t.check_request();
+ }
+ }
+
+ #[cfg(feature = "virtio-net")]
+ #[test]
+ fn test_vmm_action_update_network_interface() {
+ skip_if_not_root!();
+
+ let tests = &mut [
+ // invalid id
+ TestData::new(
+ VmmAction::UpdateNetworkInterface(VirtioNetDeviceConfigUpdateInfo {
+ iface_id: String::from("1"),
+ rx_rate_limiter: None,
+ tx_rate_limiter: None,
+ }),
+ InstanceState::Running,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::VirtioNet(
+ VirtioNetDeviceError::InvalidIfaceId(_)
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "virtio-net device error: \
+ invalid virtio-net iface id '1'",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ ];
+
+ for t in tests.iter_mut() {
+ t.check_request();
+ }
+ }
+
+ #[cfg(feature = "virtio-vsock")]
+ #[test]
+ fn test_vmm_action_insert_vsock_device() {
+ skip_if_not_root!();
+
+ let tests = &mut [
+ // invalid state
+ TestData::new(
+ VmmAction::InsertVsockDevice(VsockDeviceConfigInfo::default()),
+ InstanceState::Running,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::Vsock(
+ VsockDeviceError::UpdateNotAllowedPostBoot
+ ))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "failed to add virtio-vsock device: \
+ update operation is not allowed after boot",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ // invalid guest_cid
+ TestData::new(
+ VmmAction::InsertVsockDevice(VsockDeviceConfigInfo::default()),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(matches!(
+ result,
+ Err(VmmActionError::Vsock(VsockDeviceError::GuestCIDInvalid(0)))
+ ));
+ let err_string = format!("{}", result.unwrap_err());
+ let expected_err = String::from(
+ "failed to add virtio-vsock device: \
+ the guest CID 0 is invalid",
+ );
+ assert_eq!(err_string, expected_err);
+ },
+ ),
+ // success
+ TestData::new(
+ VmmAction::InsertVsockDevice(VsockDeviceConfigInfo {
+ guest_cid: 3,
+ ..Default::default()
+ }),
+ InstanceState::Uninitialized,
+ &|result| {
+ assert!(result.is_ok());
+ },
+ ),
+ ];
+
+ for t in tests.iter_mut() {
+ t.check_request();
+ }
+ }
+}
diff --git a/src/dragonball/src/config_manager.rs b/src/dragonball/src/config_manager.rs
index fbb66611c..34a2af2e0 100644
--- a/src/dragonball/src/config_manager.rs
+++ b/src/dragonball/src/config_manager.rs
@@ -46,7 +46,7 @@ pub trait ConfigItem {
}
/// Struct to manage a group of configuration items.
-#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
+#[derive(Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
pub struct ConfigInfos<T>
where
T: ConfigItem + Clone,
@@ -316,7 +316,7 @@ where
}
/// Configuration information for RateLimiter token bucket.
-#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
+#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
pub struct TokenBucketConfigInfo {
/// The size for the token bucket. A TokenBucket of `size` total capacity will take `refill_time`
/// milliseconds to go from zero tokens to total capacity.
@@ -349,7 +349,7 @@ impl From<&TokenBucketConfigInfo> for TokenBucket {
}
/// Configuration information for RateLimiter objects.
-#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
+#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
pub struct RateLimiterConfigInfo {
/// Data used to initialize the RateLimiter::bandwidth bucket.
pub bandwidth: TokenBucketConfigInfo,
diff --git a/src/dragonball/src/device_manager/blk_dev_mgr.rs b/src/dragonball/src/device_manager/blk_dev_mgr.rs
index e4688b4f6..0493a818a 100644
--- a/src/dragonball/src/device_manager/blk_dev_mgr.rs
+++ b/src/dragonball/src/device_manager/blk_dev_mgr.rs
@@ -106,7 +106,7 @@ pub enum BlockDeviceError {
}
/// Type of low level storage device/protocol for virtio-blk devices.
-#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum BlockDeviceType {
/// Unknown low level device type.
Unknown,
@@ -131,7 +131,7 @@ impl BlockDeviceType {
}
/// Configuration information for a block device.
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub struct BlockDeviceConfigUpdateInfo {
/// Unique identifier of the drive.
pub drive_id: String,
@@ -151,7 +151,7 @@ impl BlockDeviceConfigUpdateInfo {
}
/// Configuration information for a block device.
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub struct BlockDeviceConfigInfo {
/// Unique identifier of the drive.
pub drive_id: String,
@@ -285,7 +285,6 @@ impl std::fmt::Debug for BlockDeviceInfo {
pub type BlockDeviceInfo = DeviceConfigInfo<BlockDeviceConfigInfo>;
/// Wrapper for the collection that holds all the Block Devices Configs
-//#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[derive(Clone)]
pub struct BlockDeviceMgr {
/// A list of `BlockDeviceInfo` objects.
@@ -577,7 +576,13 @@ impl BlockDeviceMgr {
) -> std::result::Result<(), DeviceMgrError> {
// Respect user configuration if kernel_cmdline contains "root=",
// special attention for the case when kernel command line starting with "root=xxx"
- let old_kernel_cmdline = format!(" {}", kernel_config.kernel_cmdline().as_str());
+ let old_kernel_cmdline = format!(
+ " {:?}",
+ kernel_config
+ .kernel_cmdline()
+ .as_cstring()
+ .map_err(DeviceMgrError::Cmdline)?
+ );
if !old_kernel_cmdline.contains(" root=") && self.has_root_block {
let cmdline = kernel_config.kernel_cmdline_mut();
if let Some(ref uuid) = self.part_uuid {
@@ -619,7 +624,7 @@ impl BlockDeviceMgr {
// we need to satisfy the condition by which a VMM can only have on root device
if block_device_config.is_root_device {
if self.has_root_block {
- return Err(BlockDeviceError::RootBlockDeviceAlreadyAdded);
+ Err(BlockDeviceError::RootBlockDeviceAlreadyAdded)
} else {
self.has_root_block = true;
self.read_only_root = block_device_config.is_read_only;
diff --git a/src/dragonball/src/device_manager/console_manager.rs b/src/dragonball/src/device_manager/console_manager.rs
index 1e3b2a2f2..23cf6886f 100644
--- a/src/dragonball/src/device_manager/console_manager.rs
+++ b/src/dragonball/src/device_manager/console_manager.rs
@@ -74,11 +74,20 @@ impl ConsoleManager {
/// Create a console backend device by using stdio streams.
pub fn create_stdio_console(&mut self, device: Arc<Mutex<SerialDevice>>) -> Result<()> {
+ device
+ .lock()
+ .unwrap()
+ .set_output_stream(Some(Box::new(std::io::stdout())));
let stdin_handle = std::io::stdin();
stdin_handle
.lock()
.set_raw_mode()
.map_err(|e| DeviceMgrError::ConsoleManager(ConsoleManagerError::StdinHandle(e)))?;
+ stdin_handle
+ .lock()
+ .set_non_block(true)
+ .map_err(ConsoleManagerError::StdinHandle)
+ .map_err(DeviceMgrError::ConsoleManager)?;
let handler = ConsoleEpollHandler::new(device, Some(stdin_handle), None, &self.logger);
self.subscriber_id = Some(self.epoll_mgr.add_subscriber(Box::new(handler)));
diff --git a/src/dragonball/src/device_manager/fs_dev_mgr.rs b/src/dragonball/src/device_manager/fs_dev_mgr.rs
index 088dc980f..dca0e649e 100644
--- a/src/dragonball/src/device_manager/fs_dev_mgr.rs
+++ b/src/dragonball/src/device_manager/fs_dev_mgr.rs
@@ -89,7 +89,7 @@ pub enum FsDeviceError {
}
/// Configuration information for a vhost-user-fs device.
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub struct FsDeviceConfigInfo {
/// vhost-user socket path.
pub sock_path: String,
@@ -201,7 +201,7 @@ impl FsDeviceConfigInfo {
}
/// Configuration information for virtio-fs.
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub struct FsDeviceConfigUpdateInfo {
/// virtiofs mount tag name used inside the guest.
/// used as the device name during mount.
@@ -242,7 +242,7 @@ impl ConfigItem for FsDeviceConfigInfo {
}
/// Configuration information of manipulating backend fs for a virtiofs device.
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, Default)]
pub struct FsMountConfigInfo {
/// Mount operations, mount, update, umount
pub ops: String,
diff --git a/src/dragonball/src/device_manager/mod.rs b/src/dragonball/src/device_manager/mod.rs
index 43c237d4c..06f6ea6ab 100644
--- a/src/dragonball/src/device_manager/mod.rs
+++ b/src/dragonball/src/device_manager/mod.rs
@@ -147,13 +147,17 @@ pub type Result<T> = ::std::result::Result<T, DeviceMgrError>;
/// Type of the dragonball virtio devices.
#[cfg(feature = "dbs-virtio-devices")]
pub type DbsVirtioDevice = Box<
- dyn VirtioDevice<GuestAddressSpaceImpl, virtio_queue::QueueState, vm_memory::GuestRegionMmap>,
+ dyn VirtioDevice<
+ GuestAddressSpaceImpl,
+ virtio_queue::QueueStateSync,
+ vm_memory::GuestRegionMmap,
+ >,
>;
/// Type of the dragonball virtio mmio devices.
#[cfg(feature = "dbs-virtio-devices")]
pub type DbsMmioV2Device =
- MmioV2Device<GuestAddressSpaceImpl, virtio_queue::QueueState, vm_memory::GuestRegionMmap>;
+ MmioV2Device<GuestAddressSpaceImpl, virtio_queue::QueueStateSync, vm_memory::GuestRegionMmap>;
/// Struct to support transactional operations for device management.
pub struct DeviceManagerTx {
@@ -591,18 +595,17 @@ impl DeviceManager {
.map_err(|_| StartMicroVmError::EventFd)?;
info!(self.logger, "init console path: {:?}", com1_sock_path);
- if let Some(path) = com1_sock_path {
- if let Some(legacy_manager) = self.legacy_manager.as_ref() {
- let com1 = legacy_manager.get_com1_serial();
+ if let Some(legacy_manager) = self.legacy_manager.as_ref() {
+ let com1 = legacy_manager.get_com1_serial();
+ if let Some(path) = com1_sock_path {
self.con_manager
.create_socket_console(com1, path)
.map_err(StartMicroVmError::DeviceManager)?;
+ } else {
+ self.con_manager
+ .create_stdio_console(com1)
+ .map_err(StartMicroVmError::DeviceManager)?;
}
- } else if let Some(legacy_manager) = self.legacy_manager.as_ref() {
- let com1 = legacy_manager.get_com1_serial();
- self.con_manager
- .create_stdio_console(com1)
- .map_err(StartMicroVmError::DeviceManager)?;
}
Ok(())
@@ -786,13 +789,14 @@ impl DeviceManager {
fn allocate_mmio_device_resource(
&self,
) -> std::result::Result<DeviceResources, StartMicroVmError> {
- let mut requests = Vec::new();
- requests.push(ResourceConstraint::MmioAddress {
- range: None,
- align: MMIO_DEFAULT_CFG_SIZE,
- size: MMIO_DEFAULT_CFG_SIZE,
- });
- requests.push(ResourceConstraint::LegacyIrq { irq: None });
+ let requests = vec![
+ ResourceConstraint::MmioAddress {
+ range: None,
+ align: MMIO_DEFAULT_CFG_SIZE,
+ size: MMIO_DEFAULT_CFG_SIZE,
+ },
+ ResourceConstraint::LegacyIrq { irq: None },
+ ];
self.res_manager
.allocate_device_resources(&requests, false)
@@ -992,7 +996,7 @@ impl DeviceManager {
{
self.vsock_manager
.get_default_connector()
- .map(|d| Some(d))
+ .map(Some)
.unwrap_or(None)
}
#[cfg(not(feature = "virtio-vsock"))]
@@ -1001,3 +1005,168 @@ impl DeviceManager {
}
}
}
+
+#[cfg(test)]
+mod tests {
+ use std::sync::{Arc, Mutex};
+
+ use kvm_ioctls::Kvm;
+ use test_utils::skip_if_not_root;
+ use vm_memory::{GuestAddress, MmapRegion};
+
+ use super::*;
+ use crate::vm::CpuTopology;
+
+ impl DeviceManager {
+ pub fn new_test_mgr() -> Self {
+ let kvm = Kvm::new().unwrap();
+ let vm = kvm.create_vm().unwrap();
+ let vm_fd = Arc::new(vm);
+ let epoll_manager = EpollManager::default();
+ let res_manager = Arc::new(ResourceManager::new(None));
+ let logger = slog_scope::logger().new(slog::o!());
+
+ DeviceManager {
+ vm_fd: Arc::clone(&vm_fd),
+ con_manager: ConsoleManager::new(epoll_manager, &logger),
+ io_manager: Arc::new(ArcSwap::new(Arc::new(IoManager::new()))),
+ io_lock: Arc::new(Mutex::new(())),
+ irq_manager: Arc::new(KvmIrqManager::new(vm_fd.clone())),
+ res_manager,
+
+ legacy_manager: None,
+ #[cfg(feature = "virtio-blk")]
+ block_manager: BlockDeviceMgr::default(),
+ #[cfg(feature = "virtio-fs")]
+ fs_manager: Arc::new(Mutex::new(FsDeviceMgr::default())),
+ #[cfg(feature = "virtio-net")]
+ virtio_net_manager: VirtioNetDeviceMgr::default(),
+ #[cfg(feature = "virtio-vsock")]
+ vsock_manager: VsockDeviceMgr::default(),
+ #[cfg(target_arch = "aarch64")]
+ mmio_device_info: HashMap::new(),
+
+ logger,
+ }
+ }
+ }
+
+ #[test]
+ fn test_create_device_manager() {
+ skip_if_not_root!();
+ let mgr = DeviceManager::new_test_mgr();
+ let _ = mgr.io_manager();
+ }
+
+ #[cfg(target_arch = "x86_64")]
+ #[test]
+ fn test_create_devices() {
+ skip_if_not_root!();
+ use crate::vm::VmConfigInfo;
+
+ let epoll_manager = EpollManager::default();
+ let vmm = Arc::new(Mutex::new(crate::vmm::tests::create_vmm_instance()));
+ let event_mgr = crate::event_manager::EventManager::new(&vmm, epoll_manager).unwrap();
+ let mut vm = crate::vm::tests::create_vm_instance();
+ let vm_config = VmConfigInfo {
+ vcpu_count: 1,
+ max_vcpu_count: 1,
+ cpu_pm: "off".to_string(),
+ mem_type: "shmem".to_string(),
+ mem_file_path: "".to_string(),
+ mem_size_mib: 16,
+ serial_path: None,
+ cpu_topology: CpuTopology {
+ threads_per_core: 1,
+ cores_per_die: 1,
+ dies_per_socket: 1,
+ sockets: 1,
+ },
+ vpmu_feature: 0,
+ };
+ vm.set_vm_config(vm_config);
+ vm.init_guest_memory().unwrap();
+ vm.setup_interrupt_controller().unwrap();
+ let vm_as = vm.vm_as().cloned().unwrap();
+ let kernel_temp_file = vmm_sys_util::tempfile::TempFile::new().unwrap();
+ let kernel_file = kernel_temp_file.into_file();
+ let mut cmdline = crate::vm::KernelConfigInfo::new(
+ kernel_file,
+ None,
+ linux_loader::cmdline::Cmdline::new(0x1000),
+ );
+
+ let address_space = vm.vm_address_space().cloned();
+ let mgr = vm.device_manager_mut();
+ let guard = mgr.io_manager.load();
+ let mut lcr = [0u8];
+ // 0x3f8 is the adddress of serial device
+ guard.pio_read(0x3f8 + 3, &mut lcr).unwrap_err();
+ assert_eq!(lcr[0], 0x0);
+
+ mgr.create_interrupt_manager().unwrap();
+ mgr.create_devices(
+ vm_as,
+ event_mgr.epoll_manager(),
+ &mut cmdline,
+ None,
+ None,
+ address_space.as_ref(),
+ )
+ .unwrap();
+ let guard = mgr.io_manager.load();
+ guard.pio_read(0x3f8 + 3, &mut lcr).unwrap();
+ assert_eq!(lcr[0], 0x3);
+ }
+
+ #[cfg(feature = "virtio-fs")]
+ #[test]
+ fn test_handler_insert_region() {
+ skip_if_not_root!();
+
+ use dbs_virtio_devices::VirtioRegionHandler;
+ use lazy_static::__Deref;
+ use vm_memory::{GuestAddressSpace, GuestMemory, GuestMemoryRegion};
+
+ let vm = crate::test_utils::tests::create_vm_for_test();
+ let ctx = DeviceOpContext::new(
+ Some(vm.epoll_manager().clone()),
+ vm.device_manager(),
+ Some(vm.vm_as().unwrap().clone()),
+ vm.vm_address_space().cloned(),
+ true,
+ );
+ let guest_addr = GuestAddress(0x200000000000);
+
+ let cache_len = 1024 * 1024 * 1024;
+ let mmap_region = MmapRegion::build(
+ None,
+ cache_len as usize,
+ libc::PROT_NONE,
+ libc::MAP_ANONYMOUS | libc::MAP_NORESERVE | libc::MAP_PRIVATE,
+ )
+ .unwrap();
+
+ let guest_mmap_region =
+ Arc::new(vm_memory::GuestRegionMmap::new(mmap_region, guest_addr).unwrap());
+
+ let mut handler = DeviceVirtioRegionHandler {
+ vm_as: ctx.get_vm_as().unwrap(),
+ address_space: ctx.address_space.as_ref().unwrap().clone(),
+ };
+ handler.insert_region(guest_mmap_region).unwrap();
+ let mut find_region = false;
+ let find_region_ptr = &mut find_region;
+
+ let guard = vm.vm_as().unwrap().clone().memory();
+
+ let mem = guard.deref();
+ for region in mem.iter() {
+ if region.start_addr() == guest_addr && region.len() == cache_len {
+ *find_region_ptr = true;
+ }
+ }
+
+ assert!(find_region);
+ }
+}
diff --git a/src/dragonball/src/device_manager/virtio_net_dev_mgr.rs b/src/dragonball/src/device_manager/virtio_net_dev_mgr.rs
index 3e81f2948..c0b0f62da 100644
--- a/src/dragonball/src/device_manager/virtio_net_dev_mgr.rs
+++ b/src/dragonball/src/device_manager/virtio_net_dev_mgr.rs
@@ -93,7 +93,7 @@ pub enum VirtioNetDeviceError {
}
/// Configuration information for virtio net devices.
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub struct VirtioNetDeviceConfigUpdateInfo {
/// ID of the guest network interface.
pub iface_id: String,
@@ -123,7 +123,7 @@ impl VirtioNetDeviceConfigUpdateInfo {
}
/// Configuration information for virtio net devices.
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Default)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize, Default)]
pub struct VirtioNetDeviceConfigInfo {
/// ID of the guest network interface.
pub iface_id: String,
@@ -264,7 +264,7 @@ impl VirtioNetDeviceMgr {
config.use_generic_irq.unwrap_or(USE_GENERIC_IRQ),
)
.map_err(VirtioNetDeviceError::DeviceManager)?;
- ctx.insert_hotplug_mmio_device(&dev.clone(), None)
+ ctx.insert_hotplug_mmio_device(&dev, None)
.map_err(VirtioNetDeviceError::DeviceManager)?;
// live-upgrade need save/restore device from info.device.
mgr.info_list[device_index].set_device(dev);
@@ -320,7 +320,7 @@ impl VirtioNetDeviceMgr {
}
}
- /// Attach all configured vsock device to the virtual machine instance.
+ /// Attach all configured net device to the virtual machine instance.
pub fn attach_devices(
&mut self,
ctx: &mut DeviceOpContext,
diff --git a/src/dragonball/src/device_manager/vsock_dev_mgr.rs b/src/dragonball/src/device_manager/vsock_dev_mgr.rs
index 4f0f07413..8588471b7 100644
--- a/src/dragonball/src/device_manager/vsock_dev_mgr.rs
+++ b/src/dragonball/src/device_manager/vsock_dev_mgr.rs
@@ -70,7 +70,7 @@ pub enum VsockDeviceError {
}
/// Configuration information for a vsock device.
-#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
pub struct VsockDeviceConfigInfo {
/// ID of the vsock device.
pub id: String,
diff --git a/src/dragonball/src/error.rs b/src/dragonball/src/error.rs
index 35cf639bb..9ad0b0792 100644
--- a/src/dragonball/src/error.rs
+++ b/src/dragonball/src/error.rs
@@ -127,6 +127,10 @@ pub enum StartMicroVmError {
#[error("failure while configuring guest kernel commandline: {0}")]
LoadCommandline(#[source] linux_loader::loader::Error),
+ /// Cannot process command line string.
+ #[error("failure while processing guest kernel commandline: {0}.")]
+ ProcessCommandlne(#[source] linux_loader::cmdline::Error),
+
/// The device manager was not configured.
#[error("the device manager failed to manage devices: {0}")]
DeviceManager(#[source] device_manager::DeviceMgrError),
diff --git a/src/dragonball/src/event_manager.rs b/src/dragonball/src/event_manager.rs
index f07b78650..69bf4dab4 100644
--- a/src/dragonball/src/event_manager.rs
+++ b/src/dragonball/src/event_manager.rs
@@ -101,7 +101,6 @@ impl EventManager {
/// Poll pending events and invoke registered event handler.
///
/// # Arguments:
- /// * max_events: maximum number of pending events to handle
/// * timeout: maximum time in milliseconds to wait
pub fn handle_events(&self, timeout: i32) -> std::result::Result<usize, EpollError> {
self.epoll_mgr
diff --git a/src/dragonball/src/kvm_context.rs b/src/dragonball/src/kvm_context.rs
index f160b264b..ce4583458 100644
--- a/src/dragonball/src/kvm_context.rs
+++ b/src/dragonball/src/kvm_context.rs
@@ -210,20 +210,25 @@ mod x86_64 {
#[cfg(test)]
mod tests {
- use super::*;
- use kvm_ioctls::Kvm;
use std::fs::File;
use std::os::unix::fs::MetadataExt;
use std::os::unix::io::{AsRawFd, FromRawFd};
+ use kvm_ioctls::Kvm;
+ use test_utils::skip_if_not_root;
+
+ use super::*;
+
#[test]
fn test_create_kvm_context() {
+ skip_if_not_root!();
+
let c = KvmContext::new(None).unwrap();
assert!(c.max_memslots >= 32);
let kvm = Kvm::new().unwrap();
- let f = unsafe { File::from_raw_fd(kvm.as_raw_fd()) };
+ let f = std::mem::ManuallyDrop::new(unsafe { File::from_raw_fd(kvm.as_raw_fd()) });
let m1 = f.metadata().unwrap();
let m2 = File::open("/dev/kvm").unwrap().metadata().unwrap();
@@ -234,6 +239,8 @@ mod tests {
#[cfg(target_arch = "x86_64")]
#[test]
fn test_get_supported_cpu_id() {
+ skip_if_not_root!();
+
let c = KvmContext::new(None).unwrap();
let _ = c
@@ -244,6 +251,8 @@ mod tests {
#[test]
fn test_create_vm() {
+ skip_if_not_root!();
+
let c = KvmContext::new(None).unwrap();
let _ = c.create_vm().unwrap();
diff --git a/src/dragonball/src/lib.rs b/src/dragonball/src/lib.rs
index 7371e8213..5c0685326 100644
--- a/src/dragonball/src/lib.rs
+++ b/src/dragonball/src/lib.rs
@@ -34,6 +34,9 @@ pub mod vm;
mod event_manager;
mod io_manager;
+
+mod test_utils;
+
mod vmm;
pub use self::error::StartMicroVmError;
diff --git a/src/dragonball/src/resource_manager.rs b/src/dragonball/src/resource_manager.rs
index 2cb32c054..b0f96e252 100644
--- a/src/dragonball/src/resource_manager.rs
+++ b/src/dragonball/src/resource_manager.rs
@@ -36,7 +36,7 @@ const PIO_MAX: u16 = 0xFFFF;
const MMIO_SPACE_RESERVED: u64 = 0x400_0000;
/// Errors associated with resource management operations
-#[derive(Debug, PartialEq, thiserror::Error)]
+#[derive(Debug, PartialEq, Eq, thiserror::Error)]
pub enum ResourceError {
/// Unknown/unsupported resource type.
#[error("unsupported resource type")]
@@ -420,6 +420,7 @@ impl ResourceManager {
}
/// Allocate requested resources for a device.
+ #[allow(clippy::question_mark)]
pub fn allocate_device_resources(
&self,
requests: &[ResourceConstraint],
@@ -435,10 +436,7 @@ impl ResourceManager {
constraint.max = r.1 as u64;
}
match self.allocate_pio_address(&constraint) {
- Some(base) => Resource::PioAddressRange {
- base: base as u16,
- size: *size,
- },
+ Some(base) => Resource::PioAddressRange { base, size: *size },
None => {
if let Err(e) = self.free_device_resources(&resources) {
return Err(e);
@@ -569,9 +567,7 @@ impl ResourceManager {
Resource::KvmMemSlot(slot) => self.free_kvm_mem_slot(*slot),
Resource::MacAddresss(_) => Ok(()),
};
- if result.is_err() {
- return result;
- }
+ result?;
}
Ok(())
}
@@ -588,9 +584,9 @@ mod tests {
// Allocate/free shared IRQs multiple times.
assert_eq!(mgr.allocate_legacy_irq(true, None).unwrap(), SHARED_IRQ);
assert_eq!(mgr.allocate_legacy_irq(true, None).unwrap(), SHARED_IRQ);
- mgr.free_legacy_irq(SHARED_IRQ);
- mgr.free_legacy_irq(SHARED_IRQ);
- mgr.free_legacy_irq(SHARED_IRQ);
+ mgr.free_legacy_irq(SHARED_IRQ).unwrap();
+ mgr.free_legacy_irq(SHARED_IRQ).unwrap();
+ mgr.free_legacy_irq(SHARED_IRQ).unwrap();
// Allocate specified IRQs.
assert_eq!(
@@ -598,7 +594,7 @@ mod tests {
.unwrap(),
LEGACY_IRQ_BASE + 10
);
- mgr.free_legacy_irq(LEGACY_IRQ_BASE + 10);
+ mgr.free_legacy_irq(LEGACY_IRQ_BASE + 10).unwrap();
assert_eq!(
mgr.allocate_legacy_irq(false, Some(LEGACY_IRQ_BASE + 10))
.unwrap(),
@@ -635,19 +631,19 @@ mod tests {
let mgr = ResourceManager::new(None);
let msi = mgr.allocate_msi_irq(3).unwrap();
- mgr.free_msi_irq(msi, 3);
+ mgr.free_msi_irq(msi, 3).unwrap();
let msi = mgr.allocate_msi_irq(3).unwrap();
- mgr.free_msi_irq(msi, 3);
+ mgr.free_msi_irq(msi, 3).unwrap();
let irq = mgr.allocate_msi_irq_aligned(8).unwrap();
assert_eq!(irq & 0x7, 0);
- mgr.free_msi_irq(msi, 8);
+ mgr.free_msi_irq(msi, 8).unwrap();
let irq = mgr.allocate_msi_irq_aligned(8).unwrap();
assert_eq!(irq & 0x7, 0);
let irq = mgr.allocate_msi_irq_aligned(512).unwrap();
assert_eq!(irq, 512);
- mgr.free_msi_irq(irq, 512);
+ mgr.free_msi_irq(irq, 512).unwrap();
let irq = mgr.allocate_msi_irq_aligned(512).unwrap();
assert_eq!(irq, 512);
@@ -690,9 +686,9 @@ mod tests {
},
];
let resources = mgr.allocate_device_resources(&requests, false).unwrap();
- mgr.free_device_resources(&resources);
+ mgr.free_device_resources(&resources).unwrap();
let resources = mgr.allocate_device_resources(&requests, false).unwrap();
- mgr.free_device_resources(&resources);
+ mgr.free_device_resources(&resources).unwrap();
requests.push(ResourceConstraint::PioAddress {
range: Some((0xc000, 0xc000)),
align: 0x1000,
@@ -702,7 +698,7 @@ mod tests {
let resources = mgr
.allocate_device_resources(&requests[0..requests.len() - 1], false)
.unwrap();
- mgr.free_device_resources(&resources);
+ mgr.free_device_resources(&resources).unwrap();
}
#[test]
@@ -721,7 +717,7 @@ mod tests {
let mgr = ResourceManager::new(None);
assert_eq!(mgr.allocate_kvm_mem_slot(1, None).unwrap(), 0);
assert_eq!(mgr.allocate_kvm_mem_slot(1, Some(200)).unwrap(), 200);
- mgr.free_kvm_mem_slot(200);
+ mgr.free_kvm_mem_slot(200).unwrap();
assert_eq!(mgr.allocate_kvm_mem_slot(1, Some(200)).unwrap(), 200);
assert_eq!(
mgr.allocate_kvm_mem_slot(1, Some(KVM_USER_MEM_SLOTS))
diff --git a/src/dragonball/src/signal_handler.rs b/src/dragonball/src/signal_handler.rs
index 23e9ff397..f6b7bfe46 100644
--- a/src/dragonball/src/signal_handler.rs
+++ b/src/dragonball/src/signal_handler.rs
@@ -41,7 +41,7 @@ extern "C" fn sigsys_handler(num: c_int, info: *mut siginfo_t, _unused: *mut c_v
let si_code = unsafe { (*info).si_code };
// Sanity check. The condition should never be true.
- if num != si_signo || num != SIGSYS || si_code != SYS_SECCOMP_CODE as i32 {
+ if num != si_signo || num != SIGSYS || si_code != SYS_SECCOMP_CODE {
// Safe because we're terminating the process anyway.
unsafe { _exit(i32::from(super::EXIT_CODE_UNEXPECTED_ERROR)) };
}
diff --git a/src/dragonball/src/test_utils.rs b/src/dragonball/src/test_utils.rs
new file mode 100644
index 000000000..577b5df86
--- /dev/null
+++ b/src/dragonball/src/test_utils.rs
@@ -0,0 +1,47 @@
+// Copyright (C) 2022 Alibaba Cloud. All rights reserved.
+//
+// SPDX-License-Identifier: Apache-2.0
+
+#[cfg(test)]
+pub mod tests {
+ use crate::api::v1::InstanceInfo;
+ use crate::vm::{CpuTopology, KernelConfigInfo, Vm, VmConfigInfo};
+ use dbs_utils::epoll_manager::EpollManager;
+ use linux_loader::cmdline::Cmdline;
+ use std::sync::{Arc, RwLock};
+ use vmm_sys_util::tempfile::TempFile;
+
+ pub fn create_vm_for_test() -> Vm {
+ // Call for kvm too frequently would cause error in some host kernel.
+ let instance_info = Arc::new(RwLock::new(InstanceInfo::default()));
+ let epoll_manager = EpollManager::default();
+ let mut vm = Vm::new(None, instance_info, epoll_manager).unwrap();
+ let kernel_file = TempFile::new().unwrap();
+ let cmd_line = Cmdline::new(64);
+ vm.set_kernel_config(KernelConfigInfo::new(
+ kernel_file.into_file(),
+ None,
+ cmd_line,
+ ));
+
+ let vm_config = VmConfigInfo {
+ vcpu_count: 1,
+ max_vcpu_count: 1,
+ cpu_pm: "off".to_string(),
+ mem_type: "shmem".to_string(),
+ mem_file_path: "".to_string(),
+ mem_size_mib: 1,
+ serial_path: None,
+ cpu_topology: CpuTopology {
+ threads_per_core: 1,
+ cores_per_die: 1,
+ dies_per_socket: 1,
+ sockets: 1,
+ },
+ vpmu_feature: 0,
+ };
+ vm.set_vm_config(vm_config);
+ vm.init_guest_memory().unwrap();
+ vm
+ }
+}
diff --git a/src/dragonball/src/vcpu/aarch64.rs b/src/dragonball/src/vcpu/aarch64.rs
index 054a1f65d..dc4b9c61a 100644
--- a/src/dragonball/src/vcpu/aarch64.rs
+++ b/src/dragonball/src/vcpu/aarch64.rs
@@ -39,6 +39,7 @@ impl Vcpu {
/// vcpu thread to vmm thread.
/// * `create_ts` - A timestamp used by the vcpu to calculate its lifetime.
/// * `support_immediate_exit` - whether kvm uses supports immediate_exit flag.
+ #[allow(clippy::too_many_arguments)]
pub fn new_aarch64(
id: u8,
vcpu_fd: Arc<VcpuFd>,
diff --git a/src/dragonball/src/vcpu/vcpu_impl.rs b/src/dragonball/src/vcpu/vcpu_impl.rs
index 513fa435f..f6c1c2d4c 100644
--- a/src/dragonball/src/vcpu/vcpu_impl.rs
+++ b/src/dragonball/src/vcpu/vcpu_impl.rs
@@ -533,16 +533,11 @@ impl Vcpu {
fn check_io_port_info(&self, addr: u16, data: &[u8]) -> Result<bool> {
let mut checked = false;
- match addr {
- // debug info signal
- MAGIC_IOPORT_DEBUG_INFO => {
- if data.len() == 4 {
- let data = unsafe { std::ptr::read(data.as_ptr() as *const u32) };
- log::warn!("KDBG: guest kernel debug info: 0x{:x}", data);
- checked = true;
- }
- }
- _ => {}
+ // debug info signal
+ if addr == MAGIC_IOPORT_DEBUG_INFO && data.len() == 4 {
+ let data = unsafe { std::ptr::read(data.as_ptr() as *const u32) };
+ log::warn!("KDBG: guest kernel debug info: 0x{:x}", data);
+ checked = true;
};
Ok(checked)
@@ -763,14 +758,13 @@ impl Drop for Vcpu {
#[cfg(test)]
pub mod tests {
- use std::os::unix::io::AsRawFd;
use std::sync::mpsc::{channel, Receiver};
use std::sync::Mutex;
use arc_swap::ArcSwap;
use dbs_device::device_manager::IoManager;
- use kvm_ioctls::Kvm;
use lazy_static::lazy_static;
+ use test_utils::skip_if_not_root;
use super::*;
use crate::kvm_context::KvmContext;
@@ -816,12 +810,8 @@ pub mod tests {
#[cfg(target_arch = "x86_64")]
fn create_vcpu() -> (Vcpu, Receiver<VcpuStateEvent>) {
- // Call for kvm too frequently would cause error in some host kernel.
- std::thread::sleep(std::time::Duration::from_millis(5));
-
- let kvm = Kvm::new().unwrap();
- let vm = Arc::new(kvm.create_vm().unwrap());
- let kvm_context = KvmContext::new(Some(kvm.as_raw_fd())).unwrap();
+ let kvm_context = KvmContext::new(None).unwrap();
+ let vm = kvm_context.kvm().create_vm().unwrap();
let vcpu_fd = Arc::new(vm.create_vcpu(0).unwrap());
let io_manager = IoManagerCached::new(Arc::new(ArcSwap::new(Arc::new(IoManager::new()))));
let supported_cpuid = kvm_context
@@ -855,7 +845,7 @@ pub mod tests {
let kvm = Kvm::new().unwrap();
let vm = Arc::new(kvm.create_vm().unwrap());
- let kvm_context = KvmContext::new(Some(kvm.as_raw_fd())).unwrap();
+ let _kvm_context = KvmContext::new(Some(kvm.as_raw_fd())).unwrap();
let vcpu_fd = Arc::new(vm.create_vcpu(0).unwrap());
let io_manager = IoManagerCached::new(Arc::new(ArcSwap::new(Arc::new(IoManager::new()))));
let reset_event_fd = EventFd::new(libc::EFD_NONBLOCK).unwrap();
@@ -880,6 +870,8 @@ pub mod tests {
#[test]
fn test_vcpu_run_emulation() {
+ skip_if_not_root!();
+
let (mut vcpu, _) = create_vcpu();
#[cfg(target_arch = "x86_64")]
@@ -964,6 +956,8 @@ pub mod tests {
#[cfg(target_arch = "x86_64")]
#[test]
fn test_vcpu_check_io_port_info() {
+ skip_if_not_root!();
+
let (vcpu, _receiver) = create_vcpu();
// debug info signal
diff --git a/src/dragonball/src/vcpu/vcpu_manager.rs b/src/dragonball/src/vcpu/vcpu_manager.rs
index f6f3e93ff..2b076cd5b 100644
--- a/src/dragonball/src/vcpu/vcpu_manager.rs
+++ b/src/dragonball/src/vcpu/vcpu_manager.rs
@@ -774,7 +774,7 @@ impl VcpuManager {
self.reset_event_fd.as_ref().unwrap().try_clone().unwrap(),
self.vcpu_state_event.try_clone().unwrap(),
self.vcpu_state_sender.clone(),
- request_ts.clone(),
+ request_ts,
self.support_immediate_exit,
)
.map_err(VcpuManagerError::Vcpu)
@@ -1041,3 +1041,376 @@ impl MutEventSubscriber for VcpuEpollHandler {
ops.add(Events::new(&self.eventfd, EventSet::IN)).unwrap();
}
}
+
+#[cfg(test)]
+mod tests {
+ use std::os::unix::io::AsRawFd;
+ use std::sync::{Arc, RwLock};
+
+ use dbs_utils::epoll_manager::EpollManager;
+ #[cfg(feature = "hotplug")]
+ use dbs_virtio_devices::vsock::backend::VsockInnerBackend;
+ use seccompiler::BpfProgram;
+ use test_utils::skip_if_not_root;
+ use vmm_sys_util::eventfd::EventFd;
+
+ use super::*;
+ use crate::api::v1::InstanceInfo;
+ use crate::vcpu::vcpu_impl::tests::{EmulationCase, EMULATE_RES};
+ use crate::vm::{CpuTopology, Vm, VmConfigInfo};
+
+ fn get_vm() -> Vm {
+ let instance_info = Arc::new(RwLock::new(InstanceInfo::default()));
+ let epoll_manager = EpollManager::default();
+ let mut vm = Vm::new(None, instance_info, epoll_manager).unwrap();
+ let vm_config = VmConfigInfo {
+ vcpu_count: 1,
+ max_vcpu_count: 3,
+ cpu_pm: "off".to_string(),
+ mem_type: "shmem".to_string(),
+ mem_file_path: "".to_string(),
+ mem_size_mib: 100,
+ serial_path: None,
+ cpu_topology: CpuTopology {
+ threads_per_core: 1,
+ cores_per_die: 3,
+ dies_per_socket: 1,
+ sockets: 1,
+ },
+ vpmu_feature: 0,
+ };
+ vm.set_vm_config(vm_config);
+ vm.init_guest_memory().unwrap();
+
+ vm.init_vcpu_manager(vm.vm_as().unwrap().clone(), BpfProgram::default())
+ .unwrap();
+
+ vm.vcpu_manager()
+ .unwrap()
+ .set_reset_event_fd(EventFd::new(libc::EFD_NONBLOCK).unwrap())
+ .unwrap();
+
+ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+ {
+ vm.setup_interrupt_controller().unwrap();
+ }
+
+ vm
+ }
+
+ fn get_present_unstart_vcpus(vcpu_manager: &std::sync::MutexGuard<'_, VcpuManager>) -> u8 {
+ vcpu_manager
+ .vcpu_infos
+ .iter()
+ .fold(0, |sum, info| sum + info.vcpu.is_some() as u8)
+ }
+
+ #[test]
+ fn test_vcpu_manager_config() {
+ skip_if_not_root!();
+ let instance_info = Arc::new(RwLock::new(InstanceInfo::default()));
+ let epoll_manager = EpollManager::default();
+ let mut vm = Vm::new(None, instance_info, epoll_manager).unwrap();
+ let vm_config = VmConfigInfo {
+ vcpu_count: 1,
+ max_vcpu_count: 2,
+ cpu_pm: "off".to_string(),
+ mem_type: "shmem".to_string(),
+ mem_file_path: "".to_string(),
+ mem_size_mib: 1,
+ serial_path: None,
+ cpu_topology: CpuTopology {
+ threads_per_core: 1,
+ cores_per_die: 2,
+ dies_per_socket: 1,
+ sockets: 1,
+ },
+ vpmu_feature: 0,
+ };
+ vm.set_vm_config(vm_config.clone());
+ vm.init_guest_memory().unwrap();
+
+ vm.init_vcpu_manager(vm.vm_as().unwrap().clone(), BpfProgram::default())
+ .unwrap();
+
+ let mut vcpu_manager = vm.vcpu_manager().unwrap();
+
+ // test the vcpu_config
+ assert_eq!(
+ vcpu_manager.vcpu_infos.len(),
+ vm_config.max_vcpu_count as usize
+ );
+ assert_eq!(
+ vcpu_manager.vcpu_config.boot_vcpu_count,
+ vm_config.vcpu_count
+ );
+ assert_eq!(
+ vcpu_manager.vcpu_config.max_vcpu_count,
+ vm_config.max_vcpu_count
+ );
+
+ let reset_event_fd = EventFd::new(libc::EFD_NONBLOCK).unwrap();
+ let reset_event_fd_raw = reset_event_fd.as_raw_fd();
+ vcpu_manager.set_reset_event_fd(reset_event_fd).unwrap();
+
+ // test the reset_event_fd
+ assert_eq!(
+ vcpu_manager.reset_event_fd.as_ref().unwrap().as_raw_fd(),
+ reset_event_fd_raw
+ );
+ }
+
+ #[test]
+ fn test_vcpu_manager_boot_vcpus() {
+ skip_if_not_root!();
+ let vm = get_vm();
+ let mut vcpu_manager = vm.vcpu_manager().unwrap();
+
+ // test create boot vcpu
+ assert!(vcpu_manager
+ .create_boot_vcpus(TimestampUs::default(), GuestAddress(0))
+ .is_ok());
+ assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 1);
+
+ // test start boot vcpus
+ assert!(vcpu_manager.start_boot_vcpus(BpfProgram::default()).is_ok());
+ }
+
+ #[test]
+ fn test_vcpu_manager_operate_vcpus() {
+ skip_if_not_root!();
+ let vm = get_vm();
+ let mut vcpu_manager = vm.vcpu_manager().unwrap();
+
+ // test create vcpu more than max
+ let res = vcpu_manager.create_vcpus(20, None, None);
+ assert!(matches!(res, Err(VcpuManagerError::ExpectedVcpuExceedMax)));
+
+ // test create vcpus
+ assert!(vcpu_manager.create_vcpus(2, None, None).is_ok());
+ assert_eq!(vcpu_manager.present_vcpus_count(), 0);
+ assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 2);
+ assert_eq!(vcpu_manager.vcpus().len(), 2);
+ assert_eq!(vcpu_manager.vcpus_mut().len(), 2);
+
+ // test start vcpus
+ assert!(vcpu_manager
+ .start_vcpus(1, BpfProgram::default(), false)
+ .is_ok());
+ assert_eq!(vcpu_manager.present_vcpus_count(), 1);
+ assert_eq!(vcpu_manager.present_vcpus(), vec![0]);
+ assert!(vcpu_manager
+ .start_vcpus(2, BpfProgram::default(), false)
+ .is_ok());
+ assert_eq!(vcpu_manager.present_vcpus_count(), 2);
+ assert_eq!(vcpu_manager.present_vcpus(), vec![0, 1]);
+
+ // test start vcpus more than created
+ let res = vcpu_manager.start_vcpus(3, BpfProgram::default(), false);
+ assert!(matches!(res, Err(VcpuManagerError::VcpuNotCreate)));
+
+ // test start vcpus less than started
+ assert!(vcpu_manager
+ .start_vcpus(1, BpfProgram::default(), false)
+ .is_ok());
+ }
+ #[test]
+ fn test_vcpu_manager_pause_resume_vcpus() {
+ skip_if_not_root!();
+ *(EMULATE_RES.lock().unwrap()) = EmulationCase::Error(libc::EINTR);
+
+ let vm = get_vm();
+ let mut vcpu_manager = vm.vcpu_manager().unwrap();
+ assert!(vcpu_manager
+ .create_boot_vcpus(TimestampUs::default(), GuestAddress(0))
+ .is_ok());
+ assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 1);
+ assert!(vcpu_manager.start_boot_vcpus(BpfProgram::default()).is_ok());
+
+ // invalid cpuid for pause
+ let cpu_indexes = vec![2];
+ let res = vcpu_manager.pause_vcpus(&cpu_indexes);
+ assert!(matches!(res, Err(VcpuManagerError::VcpuNotFound(_))));
+
+ // pause success
+ let cpu_indexes = vec![0];
+ assert!(vcpu_manager.pause_vcpus(&cpu_indexes).is_ok());
+
+ // invalid cpuid for resume
+ let cpu_indexes = vec![2];
+ let res = vcpu_manager.resume_vcpus(&cpu_indexes);
+ assert!(matches!(res, Err(VcpuManagerError::VcpuNotFound(_))));
+
+ // success resume
+ let cpu_indexes = vec![0];
+ assert!(vcpu_manager.resume_vcpus(&cpu_indexes).is_ok());
+
+ // pause and resume all
+ assert!(vcpu_manager.pause_all_vcpus().is_ok());
+ assert!(vcpu_manager.resume_all_vcpus().is_ok());
+ }
+
+ #[test]
+ fn test_vcpu_manager_exit_vcpus() {
+ skip_if_not_root!();
+ *(EMULATE_RES.lock().unwrap()) = EmulationCase::Error(libc::EINTR);
+
+ let vm = get_vm();
+ let mut vcpu_manager = vm.vcpu_manager().unwrap();
+
+ assert!(vcpu_manager
+ .create_boot_vcpus(TimestampUs::default(), GuestAddress(0))
+ .is_ok());
+ assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 1);
+
+ assert!(vcpu_manager.start_boot_vcpus(BpfProgram::default()).is_ok());
+
+ // invalid cpuid for exit
+ let cpu_indexes = vec![2];
+
+ let res = vcpu_manager.exit_vcpus(&cpu_indexes);
+ assert!(matches!(res, Err(VcpuManagerError::VcpuNotFound(_))));
+
+ // exit success
+ let cpu_indexes = vec![0];
+ assert!(vcpu_manager.exit_vcpus(&cpu_indexes).is_ok());
+ }
+
+ #[test]
+ fn test_vcpu_manager_exit_all_vcpus() {
+ skip_if_not_root!();
+ *(EMULATE_RES.lock().unwrap()) = EmulationCase::Error(libc::EINTR);
+
+ let vm = get_vm();
+ let mut vcpu_manager = vm.vcpu_manager().unwrap();
+
+ assert!(vcpu_manager
+ .create_boot_vcpus(TimestampUs::default(), GuestAddress(0))
+ .is_ok());
+ assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 1);
+
+ assert!(vcpu_manager.start_boot_vcpus(BpfProgram::default()).is_ok());
+
+ // exit all success
+ assert!(vcpu_manager.exit_all_vcpus().is_ok());
+ assert_eq!(vcpu_manager.vcpu_infos.len(), 0);
+ assert!(vcpu_manager.io_manager.is_none());
+ }
+
+ #[test]
+ fn test_vcpu_manager_revalidate_vcpus_cache() {
+ skip_if_not_root!();
+ *(EMULATE_RES.lock().unwrap()) = EmulationCase::Error(libc::EINTR);
+
+ let vm = get_vm();
+ let mut vcpu_manager = vm.vcpu_manager().unwrap();
+
+ assert!(vcpu_manager
+ .create_boot_vcpus(TimestampUs::default(), GuestAddress(0))
+ .is_ok());
+ assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 1);
+
+ assert!(vcpu_manager.start_boot_vcpus(BpfProgram::default()).is_ok());
+
+ // invalid cpuid for exit
+ let cpu_indexes = vec![2];
+
+ let res = vcpu_manager.revalidate_vcpus_cache(&cpu_indexes);
+ assert!(matches!(res, Err(VcpuManagerError::VcpuNotFound(_))));
+
+ // revalidate success
+ let cpu_indexes = vec![0];
+ assert!(vcpu_manager.revalidate_vcpus_cache(&cpu_indexes).is_ok());
+ }
+
+ #[test]
+ fn test_vcpu_manager_revalidate_all_vcpus_cache() {
+ skip_if_not_root!();
+ *(EMULATE_RES.lock().unwrap()) = EmulationCase::Error(libc::EINTR);
+
+ let vm = get_vm();
+ let mut vcpu_manager = vm.vcpu_manager().unwrap();
+
+ assert!(vcpu_manager
+ .create_boot_vcpus(TimestampUs::default(), GuestAddress(0))
+ .is_ok());
+ assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 1);
+
+ assert!(vcpu_manager.start_boot_vcpus(BpfProgram::default()).is_ok());
+
+ // revalidate all success
+ assert!(vcpu_manager.revalidate_all_vcpus_cache().is_ok());
+ }
+
+ #[test]
+ #[cfg(feature = "hotplug")]
+ fn test_vcpu_manager_resize_cpu() {
+ skip_if_not_root!();
+ let vm = get_vm();
+ let mut vcpu_manager = vm.vcpu_manager().unwrap();
+
+ assert!(vcpu_manager
+ .create_boot_vcpus(TimestampUs::default(), GuestAddress(0))
+ .is_ok());
+ assert_eq!(get_present_unstart_vcpus(&vcpu_manager), 1);
+
+ assert!(vcpu_manager.start_boot_vcpus(BpfProgram::default()).is_ok());
+
+ // set vcpus in hotplug action
+ let cpu_ids = vec![0];
+ vcpu_manager.set_vcpus_action(VcpuAction::Hotplug, cpu_ids);
+
+ // vcpu is already in hotplug process
+ let res = vcpu_manager.resize_vcpu(1, None);
+ assert!(matches!(
+ res,
+ Err(VcpuManagerError::VcpuResize(
+ VcpuResizeError::VcpuIsHotplugging
+ ))
+ ));
+
+ // clear vcpus action
+ let cpu_ids = vec![0];
+ vcpu_manager.set_vcpus_action(VcpuAction::None, cpu_ids);
+
+ // no upcall channel
+ let res = vcpu_manager.resize_vcpu(1, None);
+ assert!(matches!(
+ res,
+ Err(VcpuManagerError::VcpuResize(
+ VcpuResizeError::UpdateNotAllowedPostBoot
+ ))
+ ));
+
+ // init upcall channel
+ let dev_mgr_service = DevMgrService {};
+ let vsock_backend = VsockInnerBackend::new().unwrap();
+ let connector = vsock_backend.get_connector();
+ let epoll_manager = EpollManager::default();
+ let mut upcall_client =
+ UpcallClient::new(connector, epoll_manager, dev_mgr_service).unwrap();
+ assert!(upcall_client.connect().is_ok());
+ vcpu_manager.set_upcall_channel(Some(Arc::new(upcall_client)));
+
+ // success: no need to resize
+ vcpu_manager.resize_vcpu(1, None).unwrap();
+
+ // exceeed max vcpu count
+ let res = vcpu_manager.resize_vcpu(4, None);
+ assert!(matches!(
+ res,
+ Err(VcpuManagerError::VcpuResize(
+ VcpuResizeError::ExpectedVcpuExceedMax
+ ))
+ ));
+
+ // remove vcpu 0
+ let res = vcpu_manager.resize_vcpu(0, None);
+ assert!(matches!(
+ res,
+ Err(VcpuManagerError::VcpuResize(
+ VcpuResizeError::Vcpu0CanNotBeRemoved
+ ))
+ ));
+ }
+}
diff --git a/src/dragonball/src/vcpu/x86_64.rs b/src/dragonball/src/vcpu/x86_64.rs
index 738d574bb..f5616066c 100644
--- a/src/dragonball/src/vcpu/x86_64.rs
+++ b/src/dragonball/src/vcpu/x86_64.rs
@@ -96,14 +96,14 @@ impl Vcpu {
if let Some(start_addr) = kernel_start_addr {
dbs_arch::regs::setup_regs(
&self.fd,
- start_addr.raw_value() as u64,
+ start_addr.raw_value(),
dbs_boot::layout::BOOT_STACK_POINTER,
dbs_boot::layout::BOOT_STACK_POINTER,
dbs_boot::layout::ZERO_PAGE_START,
)
.map_err(VcpuError::REGSConfiguration)?;
dbs_arch::regs::setup_fpu(&self.fd).map_err(VcpuError::FPUConfiguration)?;
- let gdt_table: [u64; dbs_boot::layout::BOOT_GDT_MAX as usize] = [
+ let gdt_table: [u64; dbs_boot::layout::BOOT_GDT_MAX] = [
gdt_entry(0, 0, 0), // NULL
gdt_entry(0xa09b, 0, 0xfffff), // CODE
gdt_entry(0xc093, 0, 0xfffff), // DATA
@@ -129,7 +129,7 @@ impl Vcpu {
fn set_cpuid(&mut self, vcpu_config: &VcpuConfig) -> Result<()> {
let cpuid_vm_spec = VmSpec::new(
self.id,
- vcpu_config.max_vcpu_count as u8,
+ vcpu_config.max_vcpu_count,
vcpu_config.threads_per_core,
vcpu_config.cores_per_die,
vcpu_config.dies_per_socket,
diff --git a/src/dragonball/src/vm/aarch64.rs b/src/dragonball/src/vm/aarch64.rs
index 7e249f501..fddbf9516 100644
--- a/src/dragonball/src/vm/aarch64.rs
+++ b/src/dragonball/src/vm/aarch64.rs
@@ -35,6 +35,7 @@ use crate::event_manager::EventManager;
/// * `device_info` - A hashmap containing the attached devices for building FDT device nodes.
/// * `gic_device` - The GIC device.
/// * `initrd` - Information about an optional initrd.
+#[allow(clippy::borrowed_box)]
fn configure_system<T: DeviceInfoForFDT + Clone + Debug, M: GuestMemory>(
guest_mem: &M,
cmdline: &str,
@@ -58,8 +59,9 @@ fn configure_system<T: DeviceInfoForFDT + Clone + Debug, M: GuestMemory>(
#[cfg(target_arch = "aarch64")]
impl Vm {
/// Gets a reference to the irqchip of the VM
+ #[allow(clippy::borrowed_box)]
pub fn get_irqchip(&self) -> &Box<dyn GICDevice> {
- &self.irqchip_handle.as_ref().unwrap()
+ self.irqchip_handle.as_ref().unwrap()
}
/// Creates the irq chip in-kernel device model.
@@ -136,7 +138,7 @@ impl Vm {
configure_system(
guest_memory,
- cmdline.as_str(),
+ cmdline.as_cstring().unwrap().to_str().unwrap(),
vcpu_mpidr,
self.device_manager.get_mmio_device_info(),
self.get_irqchip(),
diff --git a/src/dragonball/src/vm/kernel_config.rs b/src/dragonball/src/vm/kernel_config.rs
index 4798d8da3..34516266a 100644
--- a/src/dragonball/src/vm/kernel_config.rs
+++ b/src/dragonball/src/vm/kernel_config.rs
@@ -66,7 +66,7 @@ mod tests {
cmdline.insert_str("ro").unwrap();
let mut info = KernelConfigInfo::new(kernel.into_file(), Some(initrd.into_file()), cmdline);
- assert_eq!(info.cmdline.as_str(), "ro");
+ assert_eq!(info.cmdline.as_cstring().unwrap().as_bytes(), b"ro");
assert!(info.initrd_file_mut().is_some());
}
}
diff --git a/src/dragonball/src/vm/mod.rs b/src/dragonball/src/vm/mod.rs
index f5f62a040..d573080ae 100644
--- a/src/dragonball/src/vm/mod.rs
+++ b/src/dragonball/src/vm/mod.rs
@@ -67,7 +67,7 @@ pub enum VmError {
}
/// Configuration information for user defined NUMA nodes.
-#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
+#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
pub struct NumaRegionInfo {
/// memory size for this region (unit: MiB)
pub size: u64,
@@ -80,7 +80,7 @@ pub struct NumaRegionInfo {
}
/// Information for cpu topology to guide guest init
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct CpuTopology {
/// threads per core to indicate hyperthreading is enabled or not
pub threads_per_core: u8,
@@ -104,7 +104,7 @@ impl Default for CpuTopology {
}
/// Configuration information for virtual machine instance.
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VmConfigInfo {
/// Number of vcpu to start.
pub vcpu_count: u8,
@@ -492,6 +492,13 @@ impl Vm {
.map_err(StopMicrovmError::DeviceManager)
}
+ /// Remove upcall client when the VM is destoryed.
+ #[cfg(feature = "dbs-upcall")]
+ pub fn remove_upcall(&mut self) -> std::result::Result<(), StopMicrovmError> {
+ self.upcall_client = None;
+ Ok(())
+ }
+
/// Reset the console into canonical mode.
pub fn reset_console(&self) -> std::result::Result<(), DeviceMgrError> {
self.device_manager.reset_console()
@@ -520,6 +527,7 @@ impl Vm {
let mem_type = self.vm_config.mem_type.clone();
let mut mem_file_path = String::from("");
if mem_type == "hugetlbfs" {
+ mem_file_path = self.vm_config.mem_file_path.clone();
let shared_info = self.shared_info.read()
.expect("Failed to determine if instance is initialized because shared info couldn't be read due to poisoned lock");
mem_file_path.push_str("/dragonball/");
@@ -814,3 +822,23 @@ impl Vm {
Err(StartMicroVmError::MicroVMAlreadyRunning)
}
}
+
+#[cfg(test)]
+pub mod tests {
+ use super::*;
+
+ impl Vm {
+ pub fn set_instance_state(&mut self, mstate: InstanceState) {
+ self.shared_info
+ .write()
+ .expect("Failed to start microVM because shared info couldn't be written due to poisoned lock")
+ .state = mstate;
+ }
+ }
+
+ pub fn create_vm_instance() -> Vm {
+ let instance_info = Arc::new(RwLock::new(InstanceInfo::default()));
+ let epoll_manager = EpollManager::default();
+ Vm::new(None, instance_info, epoll_manager).unwrap()
+ }
+}
diff --git a/src/dragonball/src/vm/x86_64.rs b/src/dragonball/src/vm/x86_64.rs
index 96ca0acb1..04cf4605c 100644
--- a/src/dragonball/src/vm/x86_64.rs
+++ b/src/dragonball/src/vm/x86_64.rs
@@ -81,10 +81,10 @@ fn configure_system<M: GuestMemory>(
if mem_end < mmio_start {
add_e820_entry(
&mut params.0,
- himem_start.raw_value() as u64,
+ himem_start.raw_value(),
// it's safe to use unchecked_offset_from because
// mem_end > himem_start
- mem_end.unchecked_offset_from(himem_start) as u64 + 1,
+ mem_end.unchecked_offset_from(himem_start) + 1,
bootparam::E820_RAM,
)
.map_err(Error::BootSystem)?;
@@ -103,7 +103,7 @@ fn configure_system<M: GuestMemory>(
&mut params.0,
mmio_end.raw_value() + 1,
// it's safe to use unchecked_offset_from because mem_end > mmio_end
- mem_end.unchecked_offset_from(mmio_end) as u64,
+ mem_end.unchecked_offset_from(mmio_end),
bootparam::E820_RAM,
)
.map_err(Error::BootSystem)?;
@@ -217,11 +217,17 @@ impl Vm {
linux_loader::loader::load_cmdline(vm_memory, cmdline_addr, cmdline)
.map_err(StartMicroVmError::LoadCommandline)?;
+ let cmdline_size = cmdline
+ .as_cstring()
+ .map_err(StartMicroVmError::ProcessCommandlne)?
+ .as_bytes_with_nul()
+ .len();
+
configure_system(
vm_memory,
self.address_space.address_space(),
cmdline_addr,
- cmdline.as_str().len() + 1,
+ cmdline_size,
&initrd,
self.vm_config.vcpu_count,
self.vm_config.max_vcpu_count,
diff --git a/src/dragonball/src/vmm.rs b/src/dragonball/src/vmm.rs
index a25543e34..b15e66fef 100644
--- a/src/dragonball/src/vmm.rs
+++ b/src/dragonball/src/vmm.rs
@@ -162,6 +162,11 @@ impl Vmm {
warn!("failed to remove devices: {:?}", e);
}
+ #[cfg(feature = "dbs-upcall")]
+ if let Err(e) = vm.remove_upcall() {
+ warn!("failed to remove upcall: {:?}", e);
+ }
+
if let Err(e) = vm.reset_console() {
warn!("Cannot set canonical mode for the terminal. {:?}", e);
}
@@ -174,6 +179,8 @@ impl Vmm {
if let Err(e) = mgr.exit_all_vcpus() {
warn!("Failed to exit vcpu thread. {:?}", e);
}
+ #[cfg(feature = "dbs-upcall")]
+ mgr.set_upcall_channel(None);
}
Err(e) => warn!("Failed to get vcpu manager {:?}", e),
}
@@ -189,6 +196,8 @@ impl Vmm {
#[cfg(test)]
pub(crate) mod tests {
+ use test_utils::skip_if_not_root;
+
use super::*;
pub fn create_vmm_instance() -> Vmm {
@@ -210,6 +219,8 @@ pub(crate) mod tests {
#[test]
fn test_create_vmm_instance() {
+ skip_if_not_root!();
+
create_vmm_instance();
}
}
diff --git a/src/libs/Cargo.lock b/src/libs/Cargo.lock
index 3822058e5..c1f73d21b 100644
--- a/src/libs/Cargo.lock
+++ b/src/libs/Cargo.lock
@@ -40,12 +40,28 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+[[package]]
+name = "base64"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+[[package]]
+name = "bitmask-enum"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd9e32d7420c85055e8107e5b2463c4eeefeaac18b52359fe9f9c08a18f342b2"
+dependencies = [
+ "quote",
+ "syn",
+]
+
[[package]]
name = "bumpalo"
version = "3.11.0"
@@ -187,6 +203,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
[[package]]
name = "futures"
version = "0.3.21"
@@ -328,6 +350,82 @@ dependencies = [
"libc",
]
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "http"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
+dependencies = [
+ "bytes 1.1.0",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
+dependencies = [
+ "bytes 1.1.0",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
+
+[[package]]
+name = "httpdate"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+
+[[package]]
+name = "hyper"
+version = "0.14.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c"
+dependencies = [
+ "bytes 1.1.0",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyperlocal"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c"
+dependencies = [
+ "futures-util",
+ "hex",
+ "hyper",
+ "pin-project",
+ "tokio",
+]
+
[[package]]
name = "indexmap"
version = "1.8.1"
@@ -410,9 +508,13 @@ dependencies = [
name = "kata-types"
version = "0.1.0"
dependencies = [
+ "anyhow",
+ "base64",
+ "bitmask-enum",
"byte-unit",
"glob",
"lazy_static",
+ "nix 0.24.2",
"num_cpus",
"oci",
"regex",
@@ -421,6 +523,7 @@ dependencies = [
"slog",
"slog-scope",
"tempfile",
+ "test-utils",
"thiserror",
"toml",
]
@@ -626,6 +729,26 @@ dependencies = [
"indexmap",
]
+[[package]]
+name = "pin-project"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "pin-project-lite"
version = "0.2.8"
@@ -934,6 +1057,16 @@ dependencies = [
"syn",
]
+[[package]]
+name = "shim-interface"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "hyper",
+ "hyperlocal",
+ "tokio",
+]
+
[[package]]
name = "slab"
version = "0.4.6"
@@ -989,9 +1122,9 @@ checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
[[package]]
name = "socket2"
-version = "0.4.4"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
+checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd"
dependencies = [
"libc",
"winapi",
@@ -1094,6 +1227,7 @@ dependencies = [
"libc",
"memchr",
"mio",
+ "num_cpus",
"pin-project-lite",
"socket2",
"tokio-macros",
@@ -1133,6 +1267,38 @@ dependencies = [
"serde",
]
+[[package]]
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
+[[package]]
+name = "tracing"
+version = "0.1.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09"
+dependencies = [
+ "cfg-if",
+ "pin-project-lite",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
+
[[package]]
name = "ttrpc"
version = "0.6.1"
@@ -1201,6 +1367,16 @@ dependencies = [
"nix 0.23.1",
]
+[[package]]
+name = "want"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+dependencies = [
+ "log",
+ "try-lock",
+]
+
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
diff --git a/src/libs/Cargo.toml b/src/libs/Cargo.toml
index 62372e816..698c44a5b 100644
--- a/src/libs/Cargo.toml
+++ b/src/libs/Cargo.toml
@@ -6,6 +6,7 @@ members = [
"oci",
"protocols",
"safe-path",
+ "shim-interface",
"test-utils",
]
resolver = "2"
diff --git a/src/libs/Makefile b/src/libs/Makefile
index 9ce0be19d..aabaa3391 100644
--- a/src/libs/Makefile
+++ b/src/libs/Makefile
@@ -16,6 +16,9 @@ default: build
build:
cargo build --all-features
+static-checks-build:
+ @echo "INFO: static-checks-build do nothing.."
+
check: clippy format
clippy:
diff --git a/src/libs/kata-sys-util/src/fs.rs b/src/libs/kata-sys-util/src/fs.rs
index 1d85fa61c..bec806c46 100644
--- a/src/libs/kata-sys-util/src/fs.rs
+++ b/src/libs/kata-sys-util/src/fs.rs
@@ -8,7 +8,7 @@ use std::ffi::OsString;
use std::fs::{self, File};
use std::io::{Error, Result};
use std::os::unix::io::AsRawFd;
-use std::path::{Path, PathBuf};
+use std::path::Path;
use std::process::Command;
use crate::{eother, sl};
@@ -29,11 +29,6 @@ const FUSE_SUPER_MAGIC: FsType = 0x65735546;
// from linux.git/include/uapi/linux/magic.h
const OVERLAYFS_SUPER_MAGIC: FsType = 0x794c7630;
-/// Get bundle path (current working directory).
-pub fn get_bundle_path() -> Result<PathBuf> {
- std::env::current_dir()
-}
-
/// Get the basename of the canonicalized path
pub fn get_base_name<P: AsRef<Path>>(src: P) -> Result<OsString> {
let s = src.as_ref().canonicalize()?;
@@ -150,7 +145,7 @@ pub fn reflink_copy<S: AsRef<Path>, D: AsRef<Path>>(src: S, dst: D) -> Result<()
// Copy file using cp command, which handles sparse file copy.
fn do_regular_copy(src: &str, dst: &str) -> Result<()> {
let mut cmd = Command::new("/bin/cp");
- cmd.args(&["--sparse=auto", src, dst]);
+ cmd.args(["--sparse=auto", src, dst]);
match cmd.output() {
Ok(output) => match output.status.success() {
diff --git a/src/libs/kata-sys-util/src/hooks.rs b/src/libs/kata-sys-util/src/hooks.rs
index 78e3ae662..8a36e606e 100644
--- a/src/libs/kata-sys-util/src/hooks.rs
+++ b/src/libs/kata-sys-util/src/hooks.rs
@@ -13,6 +13,7 @@ use std::time::Duration;
use subprocess::{ExitStatus, Popen, PopenConfig, PopenError, Redirection};
+use crate::validate::valid_env;
use crate::{eother, sl};
const DEFAULT_HOOK_TIMEOUT_SEC: i32 = 10;
@@ -206,9 +207,8 @@ impl<'a> HookExecutor<'a> {
let mut envs: Vec<(OsString, OsString)> = Vec::new();
for e in hook.env.iter() {
- match e.split_once('=') {
- Some((key, value)) => envs.push((OsString::from(key), OsString::from(value))),
- None => warn!(sl!(), "env {} of hook {:?} is invalid", e, hook),
+ if let Some((key, value)) = valid_env(e) {
+ envs.push((OsString::from(key), OsString::from(value)));
}
}
diff --git a/src/libs/kata-sys-util/src/k8s.rs b/src/libs/kata-sys-util/src/k8s.rs
index be95d5d33..4ae31921e 100644
--- a/src/libs/kata-sys-util/src/k8s.rs
+++ b/src/libs/kata-sys-util/src/k8s.rs
@@ -49,7 +49,7 @@ pub fn is_host_empty_dir(path: &str) -> bool {
false
}
-// set_ephemeral_storage_type sets the mount type to 'ephemeral'
+// update_ephemeral_storage_type sets the mount type to 'ephemeral'
// if the mount source path is provisioned by k8s for ephemeral storage.
// For the given pod ephemeral volume is created only once
// backed by tmpfs inside the VM. For successive containers
@@ -63,6 +63,8 @@ pub fn update_ephemeral_storage_type(oci_spec: &mut Spec) {
if is_ephemeral_volume(&m.source) {
m.r#type = String::from(mount::KATA_EPHEMERAL_VOLUME_TYPE);
} else if is_host_empty_dir(&m.source) {
+ // FIXME support disable_guest_empty_dir
+ // https://github.com/kata-containers/kata-containers/blob/02a51e75a7e0c6fce5e8abe3b991eeac87e09645/src/runtime/pkg/katautils/create.go#L105
m.r#type = String::from(mount::KATA_HOST_DIR_VOLUME_TYPE);
}
}
diff --git a/src/libs/kata-sys-util/src/mount.rs b/src/libs/kata-sys-util/src/mount.rs
index 2bc8c07a5..3c6f5f261 100644
--- a/src/libs/kata-sys-util/src/mount.rs
+++ b/src/libs/kata-sys-util/src/mount.rs
@@ -43,8 +43,6 @@
use std::fmt::Debug;
use std::fs;
use std::io::{self, BufRead};
-use std::os::raw::c_char;
-use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt};
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
@@ -62,7 +60,7 @@ use crate::sl;
/// Default permission for directories created for mountpoint.
const MOUNT_PERM: u32 = 0o755;
-const PROC_MOUNTS_FILE: &str = "/proc/mounts";
+pub const PROC_MOUNTS_FILE: &str = "/proc/mounts";
const PROC_FIELDS_PER_LINE: usize = 6;
const PROC_DEVICE_INDEX: usize = 0;
const PROC_PATH_INDEX: usize = 1;
@@ -213,11 +211,11 @@ pub fn create_mount_destination<S: AsRef<Path>, D: AsRef<Path>, R: AsRef<Path>>(
}
}
-/// Remount a bind mount into readonly mode.
+/// Remount a bind mount
///
/// # Safety
/// Caller needs to ensure safety of the `dst` to avoid possible file path based attacks.
-pub fn bind_remount_read_only<P: AsRef<Path>>(dst: P) -> Result<()> {
+pub fn bind_remount<P: AsRef<Path>>(dst: P, readonly: bool) -> Result<()> {
let dst = dst.as_ref();
if dst.is_empty() {
return Err(Error::NullMountPointPath);
@@ -226,7 +224,7 @@ pub fn bind_remount_read_only<P: AsRef<Path>>(dst: P) -> Result<()> {
.canonicalize()
.map_err(|_e| Error::InvalidPath(dst.to_path_buf()))?;
- do_rebind_mount_read_only(dst, MsFlags::empty())
+ do_rebind_mount(dst, readonly, MsFlags::empty())
}
/// Bind mount `src` to `dst` in slave mode, optionally in readonly mode if `readonly` is true.
@@ -239,7 +237,7 @@ pub fn bind_remount_read_only<P: AsRef<Path>>(dst: P) -> Result<()> {
pub fn bind_mount_unchecked<S: AsRef<Path>, D: AsRef<Path>>(
src: S,
dst: D,
- read_only: bool,
+ readonly: bool,
) -> Result<()> {
fail::fail_point!("bind_mount", |_| {
Err(Error::FailureInject(
@@ -275,8 +273,8 @@ pub fn bind_mount_unchecked<S: AsRef<Path>, D: AsRef<Path>>(
.map_err(|e| Error::Mount(PathBuf::new(), dst.to_path_buf(), e))?;
// Optionally rebind into readonly mode.
- if read_only {
- do_rebind_mount_read_only(dst, MsFlags::empty())?;
+ if readonly {
+ do_rebind_mount(dst, readonly, MsFlags::empty())?;
}
Ok(())
@@ -356,7 +354,7 @@ impl Mounter for kata_types::mount::Mount {
// Bind mount readonly.
let bro_flag = MsFlags::MS_BIND | MsFlags::MS_RDONLY;
if (o_flag & bro_flag) == bro_flag {
- do_rebind_mount_read_only(target, o_flag)?;
+ do_rebind_mount(target, true, o_flag)?;
}
Ok(())
@@ -364,12 +362,16 @@ impl Mounter for kata_types::mount::Mount {
}
#[inline]
-fn do_rebind_mount_read_only<P: AsRef<Path>>(path: P, flags: MsFlags) -> Result<()> {
+fn do_rebind_mount<P: AsRef<Path>>(path: P, readonly: bool, flags: MsFlags) -> Result<()> {
mount(
Some(""),
path.as_ref(),
Some(""),
- flags | MsFlags::MS_BIND | MsFlags::MS_REMOUNT | MsFlags::MS_RDONLY,
+ if readonly {
+ flags | MsFlags::MS_BIND | MsFlags::MS_REMOUNT | MsFlags::MS_RDONLY
+ } else {
+ flags | MsFlags::MS_BIND | MsFlags::MS_REMOUNT
+ },
Some(""),
)
.map_err(|e| Error::Remount(path.as_ref().to_path_buf(), e))
@@ -590,7 +592,7 @@ fn compact_lowerdir_option(opts: &[String]) -> (Option<PathBuf>, Vec<String>) {
}
};
- let idx = idx as usize;
+ let idx = idx;
let common_dir = match get_longest_common_prefix(&lower_opts) {
None => return (None, n_opts),
Some(v) => {
@@ -618,7 +620,7 @@ fn compact_lowerdir_option(opts: &[String]) -> (Option<PathBuf>, Vec<String>) {
.iter()
.map(|c| c.replace(&common_prefix, ""))
.collect();
- n_opts[idx as usize] = format!("lowerdir={}", lower.join(":"));
+ n_opts[idx] = format!("lowerdir={}", lower.join(":"));
(Some(common_dir), n_opts)
}
@@ -756,18 +758,11 @@ pub fn umount_all<P: AsRef<Path>>(mountpoint: P, lazy_umount: bool) -> Result<()
// Counterpart of nix::umount2, with support of `UMOUNT_FOLLOW`.
fn umount2<P: AsRef<Path>>(path: P, lazy_umount: bool) -> std::io::Result<()> {
- let path_ptr = path.as_ref().as_os_str().as_bytes().as_ptr() as *const c_char;
- let mut flags = MntFlags::UMOUNT_NOFOLLOW.bits();
+ let mut flags = MntFlags::UMOUNT_NOFOLLOW;
if lazy_umount {
- flags |= MntFlags::MNT_DETACH.bits();
- }
-
- // Safe because parameter is valid and we have checked the reuslt.
- if unsafe { libc::umount2(path_ptr, flags) } < 0 {
- Err(io::Error::last_os_error())
- } else {
- Ok(())
+ flags |= MntFlags::MNT_DETACH;
}
+ nix::mount::umount2(path.as_ref(), flags).map_err(io::Error::from)
}
#[cfg(test)]
@@ -820,21 +815,21 @@ mod tests {
#[test]
#[ignore]
- fn test_bind_remount_read_only() {
+ fn test_bind_remount() {
let tmpdir = tempfile::tempdir().unwrap();
let tmpdir2 = tempfile::tempdir().unwrap();
assert!(matches!(
- bind_remount_read_only(&PathBuf::from("")),
+ bind_remount(PathBuf::from(""), true),
Err(Error::NullMountPointPath)
));
assert!(matches!(
- bind_remount_read_only(&PathBuf::from("../______doesn't____exist____nnn")),
+ bind_remount(PathBuf::from("../______doesn't____exist____nnn"), true),
Err(Error::InvalidPath(_))
));
bind_mount_unchecked(tmpdir2.path(), tmpdir.path(), true).unwrap();
- bind_remount_read_only(tmpdir.path()).unwrap();
+ bind_remount(tmpdir.path(), true).unwrap();
umount_timeout(tmpdir.path().to_str().unwrap(), 0).unwrap();
}
@@ -1071,7 +1066,7 @@ mod tests {
.unwrap_err();
let src = path.join("src");
- fs::write(&src, "test").unwrap();
+ fs::write(src, "test").unwrap();
let dst = path.join("dst");
fs::write(&dst, "test1").unwrap();
mount_at(
diff --git a/src/libs/kata-sys-util/src/numa.rs b/src/libs/kata-sys-util/src/numa.rs
index ece5cd8e7..4a6b2e576 100644
--- a/src/libs/kata-sys-util/src/numa.rs
+++ b/src/libs/kata-sys-util/src/numa.rs
@@ -37,9 +37,9 @@ pub type Result<T> = std::result::Result<T, Error>;
lazy_static! {
static ref SYS_FS_PREFIX: PathBuf = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("test/texture");
// numa node file for UT, we can mock data
- static ref NUMA_NODE_PATH: PathBuf = (&*SYS_FS_PREFIX).join("sys/devices/system/node");
+ static ref NUMA_NODE_PATH: PathBuf = (*SYS_FS_PREFIX).join("sys/devices/system/node");
// sysfs directory for CPU devices
- static ref NUMA_CPU_PATH: PathBuf = (&*SYS_FS_PREFIX).join("sys/devices/system/cpu");
+ static ref NUMA_CPU_PATH: PathBuf = (*SYS_FS_PREFIX).join("sys/devices/system/cpu");
}
// global config in release
diff --git a/src/libs/kata-sys-util/src/spec.rs b/src/libs/kata-sys-util/src/spec.rs
index 1d41900f6..b606d1194 100644
--- a/src/libs/kata-sys-util/src/spec.rs
+++ b/src/libs/kata-sys-util/src/spec.rs
@@ -49,7 +49,7 @@ pub enum ShimIdInfo {
}
/// get container type
-pub fn get_contaier_type(spec: &oci::Spec) -> Result<ContainerType, Error> {
+pub fn get_container_type(spec: &oci::Spec) -> Result<ContainerType, Error> {
for k in CRI_CONTAINER_TYPE_KEY_LIST.iter() {
if let Some(type_value) = spec.annotations.get(*k) {
match type_value.as_str() {
@@ -67,7 +67,7 @@ pub fn get_contaier_type(spec: &oci::Spec) -> Result<ContainerType, Error> {
/// get shim id info
pub fn get_shim_id_info() -> Result<ShimIdInfo, Error> {
let spec = load_oci_spec()?;
- match get_contaier_type(&spec)? {
+ match get_container_type(&spec)? {
ContainerType::PodSandbox => Ok(ShimIdInfo::Sandbox),
ContainerType::PodContainer => {
for k in CRI_SANDBOX_ID_KEY_LIST {
diff --git a/src/libs/kata-sys-util/src/validate.rs b/src/libs/kata-sys-util/src/validate.rs
index 0847398ce..1ad843c0c 100644
--- a/src/libs/kata-sys-util/src/validate.rs
+++ b/src/libs/kata-sys-util/src/validate.rs
@@ -17,16 +17,9 @@ pub enum Error {
pub fn verify_id(id: &str) -> Result<(), Error> {
let mut chars = id.chars();
- let valid = match chars.next() {
- Some(first)
- if first.is_alphanumeric()
+ let valid = matches!(chars.next(), Some(first) if first.is_alphanumeric()
&& id.len() > 1
- && chars.all(|c| c.is_alphanumeric() || ['.', '-', '_'].contains(&c)) =>
- {
- true
- }
- _ => false,
- };
+ && chars.all(|c| c.is_alphanumeric() || ['.', '-', '_'].contains(&c)));
match valid {
true => Ok(()),
@@ -34,6 +27,27 @@ pub fn verify_id(id: &str) -> Result<(), Error> {
}
}
+// check and reserve valid environment variables
+// invalid env var may cause panic, refer to https://doc.rust-lang.org/std/env/fn.set_var.html#panics
+// key should not:
+// * contain NUL character '\0'
+// * contain ASCII equal sign '='
+// * be empty
+// value should not:
+// * contain NUL character '\0'
+pub fn valid_env(e: &str) -> Option<(&str, &str)> {
+ // split the env str by '=' at the first time to ensure there is no '=' in key,
+ // and also to ensure there is at least '=' in env str
+ if let Some((key, value)) = e.split_once('=') {
+ if !key.is_empty() && !key.as_bytes().contains(&b'\0') && !value.as_bytes().contains(&b'\0')
+ {
+ return Some((key.trim(), value.trim()));
+ }
+ }
+
+ None
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -264,4 +278,49 @@ mod tests {
}
}
}
+
+ #[test]
+ fn test_valid_env() {
+ let env = valid_env("a=b=c");
+ assert_eq!(Some(("a", "b=c")), env);
+
+ let env = valid_env("a=b");
+ assert_eq!(Some(("a", "b")), env);
+ let env = valid_env("a =b");
+ assert_eq!(Some(("a", "b")), env);
+
+ let env = valid_env(" a =b");
+ assert_eq!(Some(("a", "b")), env);
+
+ let env = valid_env("a= b");
+ assert_eq!(Some(("a", "b")), env);
+
+ let env = valid_env("a=b ");
+ assert_eq!(Some(("a", "b")), env);
+ let env = valid_env("a=b c ");
+ assert_eq!(Some(("a", "b c")), env);
+
+ let env = valid_env("=b");
+ assert_eq!(None, env);
+
+ let env = valid_env("a=");
+ assert_eq!(Some(("a", "")), env);
+
+ let env = valid_env("a==");
+ assert_eq!(Some(("a", "=")), env);
+
+ let env = valid_env("a");
+ assert_eq!(None, env);
+
+ let invalid_str = vec![97, b'\0', 98];
+ let invalid_string = std::str::from_utf8(&invalid_str).unwrap();
+
+ let invalid_env = format!("{}=value", invalid_string);
+ let env = valid_env(&invalid_env);
+ assert_eq!(None, env);
+
+ let invalid_env = format!("key={}", invalid_string);
+ let env = valid_env(&invalid_env);
+ assert_eq!(None, env);
+ }
}
diff --git a/src/libs/kata-types/Cargo.toml b/src/libs/kata-types/Cargo.toml
index 68450aff9..598cde620 100644
--- a/src/libs/kata-types/Cargo.toml
+++ b/src/libs/kata-types/Cargo.toml
@@ -11,6 +11,9 @@ license = "Apache-2.0"
edition = "2018"
[dependencies]
+bitmask-enum = "2.1.0"
+anyhow = "1.0"
+base64 = "0.13.0"
byte-unit = "3.1.4"
glob = "0.3.0"
lazy_static = "1.4.0"
@@ -27,6 +30,8 @@ oci = { path = "../oci" }
[dev-dependencies]
tempfile = "3"
+test-utils = { path = "../test-utils" }
+nix = "0.24.2"
[features]
default = []
diff --git a/src/libs/kata-types/src/capabilities.rs b/src/libs/kata-types/src/capabilities.rs
new file mode 100644
index 000000000..15207e613
--- /dev/null
+++ b/src/libs/kata-types/src/capabilities.rs
@@ -0,0 +1,107 @@
+// Copyright (c) 2019-2022 Alibaba Cloud
+// Copyright (c) 2019-2022 Ant Group
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+use bitmask_enum::bitmask;
+
+/// CapabilityBits
+#[bitmask(u8)]
+pub enum CapabilityBits {
+ /// hypervisor supports use block device
+ BlockDeviceSupport,
+ /// hypervisor supports block device hotplug
+ BlockDeviceHotplugSupport,
+ /// hypervisor supports multi queue
+ MultiQueueSupport,
+ /// hypervisor supports filesystem share
+ FsSharingSupport,
+}
+
+/// Capabilities describe a virtcontainers hypervisor capabilities through a bit mask.
+#[derive(Debug, Clone)]
+pub struct Capabilities {
+ /// Capability flags
+ flags: CapabilityBits,
+}
+
+impl Default for Capabilities {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl Capabilities {
+ /// new Capabilities struct
+ pub fn new() -> Self {
+ Capabilities {
+ flags: CapabilityBits { bits: 0 },
+ }
+ }
+
+ /// set CapabilityBits
+ pub fn set(&mut self, flags: CapabilityBits) {
+ self.flags = flags;
+ }
+
+ /// is_block_device_supported tells if an hypervisor supports block devices.
+ pub fn is_block_device_supported(&self) -> bool {
+ self.flags.and(CapabilityBits::BlockDeviceSupport) != 0
+ }
+
+ /// is_block_device_hotplug_supported tells if an hypervisor supports block devices.
+ pub fn is_block_device_hotplug_supported(&self) -> bool {
+ self.flags.and(CapabilityBits::BlockDeviceHotplugSupport) != 0
+ }
+
+ /// is_multi_queue_supported tells if an hypervisor supports device multi queue support.
+ pub fn is_multi_queue_supported(&self) -> bool {
+ self.flags.and(CapabilityBits::MultiQueueSupport) != 0
+ }
+
+ /// is_fs_sharing_supported tells if an hypervisor supports host filesystem sharing.
+ pub fn is_fs_sharing_supported(&self) -> bool {
+ self.flags.and(CapabilityBits::FsSharingSupport) != 0
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::capabilities::CapabilityBits;
+
+ use super::Capabilities;
+
+ #[test]
+ fn test_set_hypervisor_capabilities() {
+ let mut cap = Capabilities::new();
+ assert!(!cap.is_block_device_supported());
+
+ // test set block device support
+ cap.set(CapabilityBits::BlockDeviceSupport);
+ assert!(cap.is_block_device_supported());
+ assert!(!cap.is_block_device_hotplug_supported());
+
+ // test set block device hotplug support
+ cap.set(CapabilityBits::BlockDeviceSupport | CapabilityBits::BlockDeviceHotplugSupport);
+ assert!(cap.is_block_device_hotplug_supported());
+ assert!(!cap.is_multi_queue_supported());
+
+ // test set multi queue support
+ cap.set(
+ CapabilityBits::BlockDeviceSupport
+ | CapabilityBits::BlockDeviceHotplugSupport
+ | CapabilityBits::MultiQueueSupport,
+ );
+ assert!(cap.is_multi_queue_supported());
+
+ // test set host filesystem sharing support
+ cap.set(
+ CapabilityBits::BlockDeviceSupport
+ | CapabilityBits::BlockDeviceHotplugSupport
+ | CapabilityBits::MultiQueueSupport
+ | CapabilityBits::FsSharingSupport,
+ );
+ assert!(cap.is_fs_sharing_supported())
+ }
+}
diff --git a/src/libs/kata-types/src/config/agent.rs b/src/libs/kata-types/src/config/agent.rs
index fb06de46c..875e1835a 100644
--- a/src/libs/kata-types/src/config/agent.rs
+++ b/src/libs/kata-types/src/config/agent.rs
@@ -10,6 +10,7 @@ use crate::config::{ConfigOps, TomlConfig};
pub use vendor::AgentVendor;
use super::default::{DEFAULT_AGENT_LOG_PORT, DEFAULT_AGENT_VSOCK_PORT};
+use crate::eother;
/// agent name of Kata agent.
pub const AGENT_NAME_KATA: &str = "kata";
@@ -108,6 +109,16 @@ fn default_health_check_timeout() -> u32 {
90_000
}
+impl Agent {
+ fn validate(&self) -> Result<()> {
+ if self.dial_timeout_ms == 0 {
+ return Err(eother!("dial_timeout_ms couldn't be 0."));
+ }
+
+ Ok(())
+ }
+}
+
impl ConfigOps for Agent {
fn adjust_config(conf: &mut TomlConfig) -> Result<()> {
AgentVendor::adjust_config(conf)?;
@@ -116,6 +127,9 @@ impl ConfigOps for Agent {
fn validate(conf: &TomlConfig) -> Result<()> {
AgentVendor::validate(conf)?;
+ for (_, agent_config) in conf.agent.iter() {
+ agent_config.validate()?;
+ }
Ok(())
}
}
diff --git a/src/libs/kata-types/src/config/default.rs b/src/libs/kata-types/src/config/default.rs
index 4bf9e6089..bf6b36a40 100644
--- a/src/libs/kata-types/src/config/default.rs
+++ b/src/libs/kata-types/src/config/default.rs
@@ -18,9 +18,11 @@ lazy_static! {
"/usr/share/defaults/kata-containers/configuration.toml",
];
}
+
pub const DEFAULT_AGENT_NAME: &str = "kata-agent";
pub const DEFAULT_AGENT_VSOCK_PORT: u32 = 1024;
pub const DEFAULT_AGENT_LOG_PORT: u32 = 1025;
+pub const DEFAULT_AGENT_DBG_CONSOLE_PORT: u32 = 1026;
pub const DEFAULT_AGENT_TYPE_NAME: &str = AGENT_NAME_KATA;
pub const DEFAULT_RUNTIME_NAME: &str = RUNTIME_NAME_VIRTCONTAINER;
@@ -33,7 +35,7 @@ pub const DEFAULT_VHOST_USER_STORE_PATH: &str = "/var/run/vhost-user";
pub const DEFAULT_BLOCK_NVDIMM_MEM_OFFSET: u64 = 0;
pub const DEFAULT_SHARED_FS_TYPE: &str = "virtio-fs";
-pub const DEFAULT_VIRTIO_FS_CACHE_MODE: &str = "none";
+pub const DEFAULT_VIRTIO_FS_CACHE_MODE: &str = "never";
pub const DEFAULT_VIRTIO_FS_DAX_SIZE_MB: u32 = 1024;
pub const DEFAULT_SHARED_9PFS_SIZE_MB: u32 = 128 * 1024;
pub const MIN_SHARED_9PFS_SIZE_MB: u32 = 4 * 1024;
diff --git a/src/libs/kata-types/src/config/drop_in.rs b/src/libs/kata-types/src/config/drop_in.rs
index 015e284b6..208ea72fd 100644
--- a/src/libs/kata-types/src/config/drop_in.rs
+++ b/src/libs/kata-types/src/config/drop_in.rs
@@ -240,7 +240,7 @@ mod drop_in_directory_handling {
"drop-in cfg file can only be a regular file or a symlink",
));
}
- let dropin_contents = fs::read_to_string(&dropin_file.path())?;
+ let dropin_contents = fs::read_to_string(dropin_file.path())?;
let dropin_config: toml::Value = toml::from_str(&dropin_contents)?;
super::toml_tree_ops::merge(base_config, dropin_config);
Ok(())
@@ -267,7 +267,7 @@ mod drop_in_directory_handling {
}
pub fn load(base_cfg_file_path: &Path) -> Result<TomlConfig> {
- let base_toml_str = fs::read_to_string(&base_cfg_file_path)?;
+ let base_toml_str = fs::read_to_string(base_cfg_file_path)?;
let mut base_config: toml::Value = toml::from_str(&base_toml_str)?;
let dropin_dir = get_dropin_dir_path(base_cfg_file_path)?;
@@ -324,7 +324,7 @@ mod drop_in_directory_handling {
create_file(&config_path, BASE_CONFIG_DATA.as_bytes()).unwrap();
let dropin_dir = tmpdir.path().join("config.d");
- fs::create_dir(&dropin_dir).unwrap();
+ fs::create_dir(dropin_dir).unwrap();
let config = load(&config_path).unwrap();
check_base_config(&config);
diff --git a/src/libs/kata-types/src/config/hypervisor/mod.rs b/src/libs/kata-types/src/config/hypervisor/mod.rs
index 0df669322..b7dd9f68c 100644
--- a/src/libs/kata-types/src/config/hypervisor/mod.rs
+++ b/src/libs/kata-types/src/config/hypervisor/mod.rs
@@ -50,6 +50,8 @@ const VIRTIO_FS: &str = "virtio-fs";
const VIRTIO_FS_INLINE: &str = "inline-virtio-fs";
const MAX_BRIDGE_SIZE: u32 = 5;
+const KERNEL_PARAM_DELIMITER: &str = " ";
+
lazy_static! {
static ref HYPERVISOR_PLUGINS: Mutex<HashMap<String, Arc<dyn ConfigPlugin>>> =
Mutex::new(HashMap::new());
@@ -237,6 +239,16 @@ impl BootInfo {
Ok(())
}
+ /// Add kernel parameters to bootinfo. It is always added before the original
+ /// to let the original one takes priority
+ pub fn add_kernel_params(&mut self, params: Vec<String>) {
+ let mut p = params;
+ if !self.kernel_params.is_empty() {
+ p.push(self.kernel_params.clone()); // [new_params0, new_params1, ..., original_params]
+ }
+ self.kernel_params = p.join(KERNEL_PARAM_DELIMITER);
+ }
+
/// Validate guest kernel image annotaion
pub fn validate_boot_path(&self, path: &str) -> Result<()> {
validate_path!(path, "path {} is invalid{}")?;
@@ -289,34 +301,38 @@ impl CpuInfo {
pub fn adjust_config(&mut self) -> Result<()> {
let features: Vec<&str> = self.cpu_features.split(',').map(|v| v.trim()).collect();
self.cpu_features = features.join(",");
- Ok(())
- }
-
- /// Validate the configuration information.
- pub fn validate(&self) -> Result<()> {
- Ok(())
- }
- /// Get default number of guest vCPUs.
- pub fn get_default_vcpus(&self) -> u32 {
let cpus = num_cpus::get() as u32;
+
+ // adjust default_maxvcpus
+ if self.default_maxvcpus == 0 || self.default_maxvcpus > cpus {
+ self.default_maxvcpus = cpus;
+ }
+
+ // adjust default_vcpus
if self.default_vcpus < 0 || self.default_vcpus as u32 > cpus {
- cpus
+ self.default_vcpus = cpus as i32;
} else if self.default_vcpus == 0 {
- default::DEFAULT_GUEST_VCPUS
- } else {
- self.default_vcpus as u32
+ self.default_vcpus = default::DEFAULT_GUEST_VCPUS as i32;
+ }
+
+ if self.default_vcpus > self.default_maxvcpus as i32 {
+ self.default_vcpus = self.default_maxvcpus as i32;
}
+
+ Ok(())
}
- /// Get default maximal number of guest vCPUs.
- pub fn get_default_max_vcpus(&self) -> u32 {
- let cpus = num_cpus::get() as u32;
- if self.default_maxvcpus == 0 || self.default_maxvcpus > cpus {
- cpus
- } else {
- self.default_maxvcpus
+ /// Validate the configuration information.
+ pub fn validate(&self) -> Result<()> {
+ if self.default_vcpus > self.default_maxvcpus as i32 {
+ return Err(eother!(
+ "The default_vcpus({}) is greater than default_maxvcpus({})",
+ self.default_vcpus,
+ self.default_maxvcpus
+ ));
}
+ Ok(())
}
}
@@ -848,7 +864,7 @@ impl SharedFsInfo {
)?;
}
- let l = ["none", "auto", "always"];
+ let l = ["never", "auto", "always"];
if !l.contains(&self.virtio_fs_cache.as_str()) {
return Err(eother!(
@@ -1067,4 +1083,107 @@ mod tests {
assert!(get_hypervisor_plugin("dragonball").is_some());
assert!(get_hypervisor_plugin("dragonball2").is_none());
}
+
+ #[test]
+ fn test_add_kernel_params() {
+ let mut boot_info = BootInfo {
+ ..Default::default()
+ };
+ let params = vec![
+ String::from("foo"),
+ String::from("bar"),
+ String::from("baz=faz"),
+ ];
+ boot_info.add_kernel_params(params);
+
+ assert_eq!(boot_info.kernel_params, String::from("foo bar baz=faz"));
+
+ let new_params = vec![
+ String::from("boo=far"),
+ String::from("a"),
+ String::from("b=c"),
+ ];
+ boot_info.add_kernel_params(new_params);
+
+ assert_eq!(
+ boot_info.kernel_params,
+ String::from("boo=far a b=c foo bar baz=faz")
+ );
+ }
+
+ #[test]
+ fn test_cpu_info_adjust_config() {
+ // get CPU cores of the test node
+ let node_cpus = num_cpus::get() as u32;
+ let default_vcpus = default::DEFAULT_GUEST_VCPUS as i32;
+
+ struct TestData<'a> {
+ desc: &'a str,
+ input: &'a mut CpuInfo,
+ output: CpuInfo,
+ }
+
+ let tests = &mut [
+ TestData {
+ desc: "all with default values",
+ input: &mut CpuInfo {
+ cpu_features: "".to_string(),
+ default_vcpus: 0,
+ default_maxvcpus: 0,
+ },
+ output: CpuInfo {
+ cpu_features: "".to_string(),
+ default_vcpus,
+ default_maxvcpus: node_cpus,
+ },
+ },
+ TestData {
+ desc: "all with big values",
+ input: &mut CpuInfo {
+ cpu_features: "a,b,c".to_string(),
+ default_vcpus: 9999999,
+ default_maxvcpus: 9999999,
+ },
+ output: CpuInfo {
+ cpu_features: "a,b,c".to_string(),
+ default_vcpus: node_cpus as i32,
+ default_maxvcpus: node_cpus,
+ },
+ },
+ TestData {
+ desc: "default_vcpus lager than default_maxvcpus",
+ input: &mut CpuInfo {
+ cpu_features: "a, b ,c".to_string(),
+ default_vcpus: -1,
+ default_maxvcpus: 1,
+ },
+ output: CpuInfo {
+ cpu_features: "a,b,c".to_string(),
+ default_vcpus: 1,
+ default_maxvcpus: 1,
+ },
+ },
+ ];
+
+ for (_, tc) in tests.iter_mut().enumerate() {
+ // we can ensure that unwrap will not panic
+ tc.input.adjust_config().unwrap();
+
+ assert_eq!(
+ tc.input.cpu_features, tc.output.cpu_features,
+ "test[{}] cpu_features",
+ tc.desc
+ );
+ assert_eq!(
+ tc.input.default_vcpus, tc.output.default_vcpus,
+ "test[{}] default_vcpus",
+ tc.desc
+ );
+ assert_eq!(
+ tc.input.default_maxvcpus, tc.output.default_maxvcpus,
+ "test[{}] default_maxvcpus",
+ tc.desc
+ );
+ }
+ }
}
diff --git a/src/libs/kata-types/src/config/mod.rs b/src/libs/kata-types/src/config/mod.rs
index e837e59c6..863dd7590 100644
--- a/src/libs/kata-types/src/config/mod.rs
+++ b/src/libs/kata-types/src/config/mod.rs
@@ -23,6 +23,7 @@ mod drop_in;
pub mod hypervisor;
pub use self::agent::Agent;
+use self::default::DEFAULT_AGENT_DBG_CONSOLE_PORT;
pub use self::hypervisor::{
BootInfo, DragonballConfig, Hypervisor, QemuConfig, HYPERVISOR_NAME_DRAGONBALL,
HYPERVISOR_NAME_QEMU,
@@ -33,6 +34,24 @@ pub use self::runtime::{Runtime, RuntimeVendor, RUNTIME_NAME_VIRTCONTAINER};
pub use self::agent::AGENT_NAME_KATA;
+// TODO: let agent use the constants here for consistency
+/// Debug console enabled flag for agent
+pub const DEBUG_CONSOLE_FLAG: &str = "agent.debug_console";
+/// Tracing enabled flag for agent
+pub const TRACE_MODE_OPTION: &str = "agent.trace";
+/// Tracing enabled
+pub const TRACE_MODE_ENABLE: &str = "true";
+/// Log level setting key for agent, if debugged mode on, set to debug
+pub const LOG_LEVEL_OPTION: &str = "agent.log";
+/// logging level: debug
+pub const LOG_LEVEL_DEBUG: &str = "debug";
+/// Option of which port will the debug console connect to
+pub const DEBUG_CONSOLE_VPORT_OPTION: &str = "agent.debug_console_vport";
+/// Option of which port the agent's log will connect to
+pub const LOG_VPORT_OPTION: &str = "agent.log_vport";
+/// Option of setting the container's pipe size
+pub const CONTAINER_PIPE_SIZE_OPTION: &str = "agent.container_pipe_size";
+
/// Trait to manipulate global Kata configuration information.
pub trait ConfigPlugin: Send + Sync {
/// Get the plugin name.
@@ -151,7 +170,32 @@ impl TomlConfig {
Ok(())
}
- /// Probe configuration file according to the default configuration file list.
+ /// Get agent-specfic kernel parameters for further Hypervisor config revision
+ pub fn get_agent_kernel_params(&self) -> Result<HashMap<String, String>> {
+ let mut kv = HashMap::new();
+ if let Some(cfg) = self.agent.get(&self.runtime.agent_name) {
+ if cfg.debug {
+ kv.insert(LOG_LEVEL_OPTION.to_string(), LOG_LEVEL_DEBUG.to_string());
+ }
+ if cfg.enable_tracing {
+ kv.insert(TRACE_MODE_OPTION.to_string(), TRACE_MODE_ENABLE.to_string());
+ }
+ if cfg.container_pipe_size > 0 {
+ let container_pipe_size = cfg.container_pipe_size.to_string();
+ kv.insert(CONTAINER_PIPE_SIZE_OPTION.to_string(), container_pipe_size);
+ }
+ if cfg.debug_console_enabled {
+ kv.insert(DEBUG_CONSOLE_FLAG.to_string(), "".to_string());
+ kv.insert(
+ DEBUG_CONSOLE_VPORT_OPTION.to_string(),
+ DEFAULT_AGENT_DBG_CONSOLE_PORT.to_string(),
+ );
+ }
+ }
+ Ok(kv)
+ }
+
+ /// Probe configuration file according to the default configuration file list.
fn get_default_config_file() -> Result<PathBuf> {
for f in default::DEFAULT_RUNTIME_CONFIGURATIONS.iter() {
if let Ok(path) = fs::canonicalize(f) {
@@ -303,4 +347,28 @@ mod tests {
let patterns = ["/usr/share".to_string(), "/bin/*".to_string()];
validate_path_pattern(&patterns, "/bin/ls").unwrap();
}
+
+ #[test]
+ fn test_get_agent_kernel_params() {
+ let mut config = TomlConfig {
+ ..Default::default()
+ };
+ let agent_config = Agent {
+ debug: true,
+ enable_tracing: true,
+ container_pipe_size: 20,
+ debug_console_enabled: true,
+ ..Default::default()
+ };
+ let agent_name = "test_agent";
+ config.runtime.agent_name = agent_name.to_string();
+ config.agent.insert(agent_name.to_owned(), agent_config);
+
+ let kv = config.get_agent_kernel_params().unwrap();
+ assert_eq!(kv.get("agent.log").unwrap(), "debug");
+ assert_eq!(kv.get("agent.trace").unwrap(), "true");
+ assert_eq!(kv.get("agent.container_pipe_size").unwrap(), "20");
+ kv.get("agent.debug_console").unwrap();
+ assert_eq!(kv.get("agent.debug_console_vport").unwrap(), "1026"); // 1026 is the default port
+ }
}
diff --git a/src/libs/kata-types/src/k8s.rs b/src/libs/kata-types/src/k8s.rs
index 7e53601b8..ee392a94a 100644
--- a/src/libs/kata-types/src/k8s.rs
+++ b/src/libs/kata-types/src/k8s.rs
@@ -10,20 +10,39 @@ use crate::annotations;
use crate::container::ContainerType;
use std::str::FromStr;
-// K8S_EMPTY_DIR is the k8s specific path for `empty-dir` volumes
+// K8S_EMPTY_DIR is the K8s specific path for `empty-dir` volumes
const K8S_EMPTY_DIR: &str = "kubernetes.io~empty-dir";
+// K8S_CONFIGMAP is the K8s specific path for `configmap` volumes
+const K8S_CONFIGMAP: &str = "kubernetes.io~configmap";
+// K8S_SECRET is the K8s specific path for `secret` volumes
+const K8S_SECRET: &str = "kubernetes.io~secret";
-/// Check whether the path is a K8S empty directory.
+/// Check whether the path is a K8s empty directory.
+pub fn is_empty_dir<P: AsRef<Path>>(path: P) -> bool {
+ is_special_dir(path, K8S_EMPTY_DIR)
+}
+
+/// Check whether the path is a K8s configmap.
+pub fn is_configmap<P: AsRef<Path>>(path: P) -> bool {
+ is_special_dir(path, K8S_CONFIGMAP)
+}
+
+/// Check whether the path is a K8s secret.
+pub fn is_secret<P: AsRef<Path>>(path: P) -> bool {
+ is_special_dir(path, K8S_SECRET)
+}
+
+/// Check whether the path is a K8s empty directory, configmap, or secret.
///
-/// For a K8S EmptyDir, Kubernetes mounts
+/// For example, given a K8s EmptyDir, Kubernetes mounts
/// "/var/lib/kubelet/pods/<id>/volumes/kubernetes.io~empty-dir/<volumeMount name>"
/// to "/<mount-point>".
-pub fn is_empty_dir<P: AsRef<Path>>(path: P) -> bool {
+pub fn is_special_dir<P: AsRef<Path>>(path: P, dir_type: &str) -> bool {
let path = path.as_ref();
if let Some(parent) = path.parent() {
if let Some(pname) = parent.file_name() {
- if pname == K8S_EMPTY_DIR && parent.parent().is_some() {
+ if pname == dir_type && parent.parent().is_some() {
return true;
}
}
@@ -77,10 +96,119 @@ pub fn container_type_with_id(spec: &oci::Spec) -> (ContainerType, Option<String
(container_type, sid)
}
+// count_files will return the number of files within a given path.
+// If the total number of
+// files observed is greater than limit, break and return -1
+fn count_files<P: AsRef<Path>>(path: P, limit: i32) -> std::io::Result<i32> {
+ // First, Check to see if the path exists
+ let src = std::fs::canonicalize(path)?;
+
+ // Special case if this is just a file, not a directory:
+ if !src.is_dir() {
+ return Ok(1);
+ }
+
+ let mut num_files = 0;
+
+ for entry in std::fs::read_dir(src)? {
+ let file = entry?;
+ let p = file.path();
+ if p.is_dir() {
+ num_files += count_files(&p, limit)?;
+ } else {
+ num_files += 1;
+ }
+
+ if num_files > limit {
+ return Ok(-1);
+ }
+ }
+
+ Ok(num_files)
+}
+
+/// Check if a volume should be processed as a watchable volume,
+/// which adds inotify-like function for virtio-fs.
+pub fn is_watchable_mount<P: AsRef<Path>>(path: P) -> bool {
+ if !is_secret(&path) && !is_configmap(&path) {
+ return false;
+ }
+
+ // we have a cap on number of FDs which can be present in mount
+ // to determine if watchable. A similar Check exists within the agent,
+ // which may or may not help handle case where extra files are added to
+ // a mount after the fact
+ let count = count_files(&path, 8).unwrap_or(0);
+ count > 0
+}
+
#[cfg(test)]
mod tests {
use super::*;
use crate::{annotations, container};
+ use std::fs;
+ use test_utils::skip_if_not_root;
+
+ #[test]
+ fn test_is_watchable_mount() {
+ skip_if_not_root!();
+
+ let result = is_watchable_mount("");
+ assert!(!result);
+
+ // path does not exist, failure expected:
+ let result = is_watchable_mount("/var/lib/kubelet/pods/5f0861a0-a987-4a3a-bb0f-1058ddb9678f/volumes/kubernetes.io~empty-dir/foobar");
+ assert!(!result);
+
+ let test_tmp_dir = tempfile::tempdir().expect("failed to create tempdir");
+
+ // Verify secret is successful (single file mount):
+ // /tmppath/kubernetes.io~secret/super-secret-thing
+ let secret_path = test_tmp_dir.path().join(K8S_SECRET);
+ let result = fs::create_dir_all(&secret_path);
+ assert!(result.is_ok());
+ let secret_file = &secret_path.join("super-secret-thing");
+ let result = fs::File::create(secret_file);
+ assert!(result.is_ok());
+
+ let result = is_watchable_mount(secret_file);
+ assert!(result);
+
+ // Verify that if we have too many files, it will no longer be watchable:
+ // /tmp/kubernetes.io~configmap/amazing-dir-of-configs/
+ // | - c0
+ // | - c1
+ // ...
+ // | - c7
+ // should be okay.
+ //
+ // 9 files should cause the mount to be deemed "not watchable"
+ let configmap_path = test_tmp_dir
+ .path()
+ .join(K8S_CONFIGMAP)
+ .join("amazing-dir-of-configs");
+ let result = fs::create_dir_all(&configmap_path);
+ assert!(result.is_ok());
+
+ // not a watchable mount if no files available.
+ let result = is_watchable_mount(&configmap_path);
+ assert!(!result);
+
+ for i in 0..8 {
+ let configmap_file = &configmap_path.join(format!("c{}", i));
+ let result = fs::File::create(configmap_file);
+ assert!(result.is_ok());
+
+ let result = is_watchable_mount(&configmap_path);
+ assert!(result);
+ }
+ let configmap_file = &configmap_path.join("too_much_files");
+ let result = fs::File::create(configmap_file);
+ assert!(result.is_ok());
+
+ let result = is_watchable_mount(&configmap_path);
+ assert!(!result);
+ }
#[test]
fn test_is_empty_dir() {
@@ -103,6 +231,36 @@ mod tests {
assert!(is_empty_dir(empty_dir));
}
+ #[test]
+ fn test_is_configmap() {
+ let path = "/volumes/kubernetes.io~configmap/cm";
+ assert!(is_configmap(path));
+
+ let path = "/volumes/kubernetes.io~configmap//cm";
+ assert!(is_configmap(path));
+
+ let path = "/volumes/kubernetes.io~configmap-test/cm";
+ assert!(!is_configmap(path));
+
+ let path = "/volumes/kubernetes.io~configmap";
+ assert!(!is_configmap(path));
+ }
+
+ #[test]
+ fn test_is_secret() {
+ let path = "/volumes/kubernetes.io~secret/test-serect";
+ assert!(is_secret(path));
+
+ let path = "/volumes/kubernetes.io~secret//test-serect";
+ assert!(is_secret(path));
+
+ let path = "/volumes/kubernetes.io~secret-test/test-serect";
+ assert!(!is_secret(path));
+
+ let path = "/volumes/kubernetes.io~secret";
+ assert!(!is_secret(path));
+ }
+
#[test]
fn test_container_type() {
let sid = "sid".to_string();
diff --git a/src/libs/kata-types/src/lib.rs b/src/libs/kata-types/src/lib.rs
index ce43d2960..5eb407561 100644
--- a/src/libs/kata-types/src/lib.rs
+++ b/src/libs/kata-types/src/lib.rs
@@ -31,6 +31,9 @@ pub mod mount;
pub(crate) mod utils;
+/// hypervisor capabilities
+pub mod capabilities;
+
/// Common error codes.
#[derive(thiserror::Error, Debug)]
pub enum Error {
diff --git a/src/libs/kata-types/src/mount.rs b/src/libs/kata-types/src/mount.rs
index 2ccc0feed..f66e828bd 100644
--- a/src/libs/kata-types/src/mount.rs
+++ b/src/libs/kata-types/src/mount.rs
@@ -4,7 +4,8 @@
// SPDX-License-Identifier: Apache-2.0
//
-use std::path::PathBuf;
+use anyhow::{anyhow, Context, Result};
+use std::{collections::HashMap, path::PathBuf};
/// Prefix to mark a volume as Kata special.
pub const KATA_VOLUME_TYPE_PREFIX: &str = "kata:";
@@ -13,11 +14,17 @@ pub const KATA_VOLUME_TYPE_PREFIX: &str = "kata:";
pub const KATA_GUEST_MOUNT_PREFIX: &str = "kata:guest-mount:";
/// KATA_EPHEMERAL_DEV_TYPE creates a tmpfs backed volume for sharing files between containers.
-pub const KATA_EPHEMERAL_VOLUME_TYPE: &str = "kata:ephemeral";
+pub const KATA_EPHEMERAL_VOLUME_TYPE: &str = "ephemeral";
/// KATA_HOST_DIR_TYPE use for host empty dir
pub const KATA_HOST_DIR_VOLUME_TYPE: &str = "kata:hostdir";
+/// KATA_MOUNT_INFO_FILE_NAME is used for the file that holds direct-volume mount info
+pub const KATA_MOUNT_INFO_FILE_NAME: &str = "mountInfo.json";
+
+/// KATA_DIRECT_VOLUME_ROOT_PATH is the root path used for concatenating with the direct-volume mount info file path
+pub const KATA_DIRECT_VOLUME_ROOT_PATH: &str = "/run/kata-containers/shared/direct-volumes";
+
/// Information about a mount.
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct Mount {
@@ -48,6 +55,22 @@ impl Mount {
}
}
+/// DirectVolumeMountInfo contains the information needed by Kata
+/// to consume a host block device and mount it as a filesystem inside the guest VM.
+#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
+pub struct DirectVolumeMountInfo {
+ /// The type of the volume (ie. block)
+ pub volume_type: String,
+ /// The device backing the volume.
+ pub device: String,
+ /// The filesystem type to be mounted on the volume.
+ pub fs_type: String,
+ /// Additional metadata to pass to the agent regarding this volume.
+ pub metadata: HashMap<String, String>,
+ /// Additional mount options.
+ pub options: Vec<String>,
+}
+
/// Check whether a mount type is a marker for Kata specific volume.
pub fn is_kata_special_volume(ty: &str) -> bool {
ty.len() > KATA_VOLUME_TYPE_PREFIX.len() && ty.starts_with(KATA_VOLUME_TYPE_PREFIX)
@@ -68,10 +91,46 @@ pub fn is_kata_host_dir_volume(ty: &str) -> bool {
ty == KATA_HOST_DIR_VOLUME_TYPE
}
+/// Nydus extra options
+#[derive(Debug, serde::Deserialize)]
+pub struct NydusExtraOptions {
+ /// source path
+ pub source: String,
+ /// nydus config
+ pub config: String,
+ /// snapshotter directory
+ #[serde(rename(deserialize = "snapshotdir"))]
+ pub snapshot_dir: String,
+ /// fs version
+ pub fs_version: String,
+}
+
+impl NydusExtraOptions {
+ /// Create Nydus extra options
+ pub fn new(mount: &Mount) -> Result<Self> {
+ let options: Vec<&str> = mount
+ .options
+ .iter()
+ .filter(|x| x.starts_with("extraoption="))
+ .map(|x| x.as_ref())
+ .collect();
+
+ if options.len() != 1 {
+ return Err(anyhow!(
+ "get_nydus_extra_options: Invalid nydus options: {:?}",
+ &mount.options
+ ));
+ }
+ let config_raw_data = options[0].trim_start_matches("extraoption=");
+ let extra_options_buf =
+ base64::decode(config_raw_data).context("decode the nydus's base64 extraoption")?;
+
+ serde_json::from_slice(&extra_options_buf).context("deserialize nydus's extraoption")
+ }
+}
#[cfg(test)]
mod tests {
use super::*;
-
#[test]
fn test_is_kata_special_volume() {
assert!(is_kata_special_volume("kata:guest-mount:nfs"));
@@ -85,4 +144,38 @@ mod tests {
assert!(!is_kata_guest_mount_volume("kata:guest-moun"));
assert!(!is_kata_guest_mount_volume("Kata:guest-mount:nfs"));
}
+
+ #[test]
+ fn test_get_nydus_extra_options_v5() {
+ let mut mount_info = Mount {
+ ..Default::default()
+ };
+ mount_info.options = vec!["extraoption=eyJzb3VyY2UiOiIvdmFyL2xpYi9jb250YWluZXJkL2lvLmNvbnRhaW5lcmQuc25hcHNob3R0ZXIudjEubnlkdXMvc25hcHNob3RzLzkvZnMvaW1hZ2UvaW1hZ2UuYm9vdCIsImNvbmZpZyI6IntcImRldmljZVwiOntcImJhY2tlbmRcIjp7XCJ0eXBlXCI6XCJyZWdpc3RyeVwiLFwiY29uZmlnXCI6e1wicmVhZGFoZWFkXCI6ZmFsc2UsXCJob3N0XCI6XCJsb2NhbGhvc3Q6NTAwMFwiLFwicmVwb1wiOlwidWJ1bnR1LW55ZHVzXCIsXCJzY2hlbWVcIjpcImh0dHBcIixcInNraXBfdmVyaWZ5XCI6dHJ1ZSxcInByb3h5XCI6e1wiZmFsbGJhY2tcIjpmYWxzZX0sXCJ0aW1lb3V0XCI6NSxcImNvbm5lY3RfdGltZW91dFwiOjUsXCJyZXRyeV9saW1pdFwiOjJ9fSxcImNhY2hlXCI6e1widHlwZVwiOlwiYmxvYmNhY2hlXCIsXCJjb25maWdcIjp7XCJ3b3JrX2RpclwiOlwiL3Zhci9saWIvbnlkdXMvY2FjaGVcIixcImRpc2FibGVfaW5kZXhlZF9tYXBcIjpmYWxzZX19fSxcIm1vZGVcIjpcImRpcmVjdFwiLFwiZGlnZXN0X3ZhbGlkYXRlXCI6ZmFsc2UsXCJlbmFibGVfeGF0dHJcIjp0cnVlLFwiZnNfcHJlZmV0Y2hcIjp7XCJlbmFibGVcIjp0cnVlLFwicHJlZmV0Y2hfYWxsXCI6ZmFsc2UsXCJ0aHJlYWRzX2NvdW50XCI6NCxcIm1lcmdpbmdfc2l6ZVwiOjAsXCJiYW5kd2lkdGhfcmF0ZVwiOjB9LFwidHlwZVwiOlwiXCIsXCJpZFwiOlwiXCIsXCJkb21haW5faWRcIjpcIlwiLFwiY29uZmlnXCI6e1wiaWRcIjpcIlwiLFwiYmFja2VuZF90eXBlXCI6XCJcIixcImJhY2tlbmRfY29uZmlnXCI6e1wicmVhZGFoZWFkXCI6ZmFsc2UsXCJwcm94eVwiOntcImZhbGxiYWNrXCI6ZmFsc2V9fSxcImNhY2hlX3R5cGVcIjpcIlwiLFwiY2FjaGVfY29uZmlnXCI6e1wid29ya19kaXJcIjpcIlwifSxcIm1ldGFkYXRhX3BhdGhcIjpcIlwifX0iLCJzbmFwc2hvdGRpciI6Ii92YXIvbGliL2NvbnRhaW5lcmQvaW8uY29udGFpbmVyZC5zbmFwc2hvdHRlci52MS5ueWR1cy9zbmFwc2hvdHMvMjU3IiwiZnNfdmVyc2lvbiI6InY1In0=".to_string()];
+ let extra_option_result = NydusExtraOptions::new(&mount_info);
+ assert!(extra_option_result.is_ok());
+ let extra_option = extra_option_result.unwrap();
+ assert_eq!(extra_option.source,"/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/9/fs/image/image.boot");
+ assert_eq!(
+ extra_option.snapshot_dir,
+ "/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/257"
+ );
+ assert_eq!(extra_option.fs_version, "v5");
+ }
+
+ #[test]
+ fn test_get_nydus_extra_options_v6() {
+ let mut mount_info = Mount {
+ ..Default::default()
+ };
+ mount_info.options = vec!["extraoption=eyJzb3VyY2UiOiIvdmFyL2xpYi9jb250YWluZXJkL2lvLmNvbnRhaW5lcmQuc25hcHNob3R0ZXIudjEubnlkdXMvc25hcHNob3RzLzIwMS9mcy9pbWFnZS9pbWFnZS5ib290IiwiY29uZmlnIjoie1wiZGV2aWNlXCI6e1wiYmFja2VuZFwiOntcInR5cGVcIjpcInJlZ2lzdHJ5XCIsXCJjb25maWdcIjp7XCJyZWFkYWhlYWRcIjpmYWxzZSxcImhvc3RcIjpcImxvY2FsaG9zdDo1MDAwXCIsXCJyZXBvXCI6XCJ1YnVudHUtbnlkdXMtdjZcIixcInNjaGVtZVwiOlwiaHR0cFwiLFwic2tpcF92ZXJpZnlcIjp0cnVlLFwicHJveHlcIjp7XCJmYWxsYmFja1wiOmZhbHNlfSxcInRpbWVvdXRcIjo1LFwiY29ubmVjdF90aW1lb3V0XCI6NSxcInJldHJ5X2xpbWl0XCI6Mn19LFwiY2FjaGVcIjp7XCJ0eXBlXCI6XCJibG9iY2FjaGVcIixcImNvbmZpZ1wiOntcIndvcmtfZGlyXCI6XCIvdmFyL2xpYi9ueWR1cy9jYWNoZVwiLFwiZGlzYWJsZV9pbmRleGVkX21hcFwiOmZhbHNlfX19LFwibW9kZVwiOlwiZGlyZWN0XCIsXCJkaWdlc3RfdmFsaWRhdGVcIjpmYWxzZSxcImVuYWJsZV94YXR0clwiOnRydWUsXCJmc19wcmVmZXRjaFwiOntcImVuYWJsZVwiOnRydWUsXCJwcmVmZXRjaF9hbGxcIjpmYWxzZSxcInRocmVhZHNfY291bnRcIjo0LFwibWVyZ2luZ19zaXplXCI6MCxcImJhbmR3aWR0aF9yYXRlXCI6MH0sXCJ0eXBlXCI6XCJcIixcImlkXCI6XCJcIixcImRvbWFpbl9pZFwiOlwiXCIsXCJjb25maWdcIjp7XCJpZFwiOlwiXCIsXCJiYWNrZW5kX3R5cGVcIjpcIlwiLFwiYmFja2VuZF9jb25maWdcIjp7XCJyZWFkYWhlYWRcIjpmYWxzZSxcInByb3h5XCI6e1wiZmFsbGJhY2tcIjpmYWxzZX19LFwiY2FjaGVfdHlwZVwiOlwiXCIsXCJjYWNoZV9jb25maWdcIjp7XCJ3b3JrX2RpclwiOlwiXCJ9LFwibWV0YWRhdGFfcGF0aFwiOlwiXCJ9fSIsInNuYXBzaG90ZGlyIjoiL3Zhci9saWIvY29udGFpbmVyZC9pby5jb250YWluZXJkLnNuYXBzaG90dGVyLnYxLm55ZHVzL3NuYXBzaG90cy8yNjEiLCJmc192ZXJzaW9uIjoidjYifQ==".to_string()];
+ let extra_option_result = NydusExtraOptions::new(&mount_info);
+ assert!(extra_option_result.is_ok());
+ let extra_option = extra_option_result.unwrap();
+ assert_eq!(extra_option.source,"/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/201/fs/image/image.boot");
+ assert_eq!(
+ extra_option.snapshot_dir,
+ "/var/lib/containerd/io.containerd.snapshotter.v1.nydus/snapshots/261"
+ );
+ assert_eq!(extra_option.fs_version, "v6");
+ }
}
diff --git a/src/libs/kata-types/tests/test_config.rs b/src/libs/kata-types/tests/test_config.rs
index b7d5f953b..800a05f70 100644
--- a/src/libs/kata-types/tests/test_config.rs
+++ b/src/libs/kata-types/tests/test_config.rs
@@ -340,7 +340,7 @@ mod tests {
let path = env!("CARGO_MANIFEST_DIR");
let path = Path::new(path).join("tests/texture/configuration-anno-0.toml");
- let content = fs::read_to_string(&path).unwrap();
+ let content = fs::read_to_string(path).unwrap();
let mut config = TomlConfig::load(&content).unwrap();
assert!(anno.update_config_by_annotation(&mut config).is_err());
}
@@ -349,7 +349,7 @@ mod tests {
fn test_fail_to_change_kernel_path_because_of_invalid_path() {
let path = env!("CARGO_MANIFEST_DIR");
let path = Path::new(path).join("tests/texture/configuration-anno-0.toml");
- let content = fs::read_to_string(&path).unwrap();
+ let content = fs::read_to_string(path).unwrap();
let qemu = QemuConfig::new();
qemu.register();
diff --git a/src/libs/logging/src/file_rotate.rs b/src/libs/logging/src/file_rotate.rs
index 444297e53..3cc8f5715 100644
--- a/src/libs/logging/src/file_rotate.rs
+++ b/src/libs/logging/src/file_rotate.rs
@@ -168,12 +168,12 @@ impl FileRotator {
#[cfg(test)]
if !self.fail_rename && self.path.exists() {
let rotated_path = self.rotated_path(1);
- let _ = fs::rename(&self.path, &rotated_path);
+ let _ = fs::rename(&self.path, rotated_path);
}
#[cfg(not(test))]
if self.path.exists() {
let rotated_path = self.rotated_path(1);
- let _ = fs::rename(&self.path, &rotated_path);
+ let _ = fs::rename(&self.path, rotated_path);
}
let delete_path = self.rotated_path(self.rotate_keep + 1);
diff --git a/src/libs/logging/src/lib.rs b/src/libs/logging/src/lib.rs
index d72292a2c..29325c6bd 100644
--- a/src/libs/logging/src/lib.rs
+++ b/src/libs/logging/src/lib.rs
@@ -499,6 +499,7 @@ mod tests {
let error_closure = |logger: &Logger, msg: String| error!(logger, "{}", msg);
let critical_closure = |logger: &Logger, msg: String| crit!(logger, "{}", msg);
+ #[allow(clippy::type_complexity)]
struct TestData<'a> {
slog_level: slog::Level,
slog_level_tag: &'a str,
diff --git a/src/libs/oci/src/lib.rs b/src/libs/oci/src/lib.rs
index 3bcaefa16..c2c53909d 100644
--- a/src/libs/oci/src/lib.rs
+++ b/src/libs/oci/src/lib.rs
@@ -494,8 +494,8 @@ pub struct LinuxDevice {
pub struct LinuxDeviceCgroup {
#[serde(default)]
pub allow: bool,
- #[serde(default, skip_serializing_if = "String::is_empty")]
- pub r#type: String,
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ pub r#type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub major: Option<i64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
@@ -1431,21 +1431,21 @@ mod tests {
devices: vec![
crate::LinuxDeviceCgroup {
allow: false,
- r#type: "".to_string(),
+ r#type: None,
major: None,
minor: None,
access: "rwm".to_string(),
},
crate::LinuxDeviceCgroup {
allow: true,
- r#type: "c".to_string(),
+ r#type: Some("c".to_string()),
major: Some(10),
minor: Some(229),
access: "rw".to_string(),
},
crate::LinuxDeviceCgroup {
allow: true,
- r#type: "b".to_string(),
+ r#type: Some("b".to_string()),
major: Some(8),
minor: Some(0),
access: "r".to_string(),
diff --git a/src/libs/protocols/.gitignore b/src/libs/protocols/.gitignore
index 0a83b1689..a9bf48131 100644
--- a/src/libs/protocols/.gitignore
+++ b/src/libs/protocols/.gitignore
@@ -7,5 +7,8 @@ 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
diff --git a/src/libs/protocols/build.rs b/src/libs/protocols/build.rs
index ebb6ef126..4fee17081 100644
--- a/src/libs/protocols/build.rs
+++ b/src/libs/protocols/build.rs
@@ -17,7 +17,7 @@ fn replace_text_in_file(file_name: &str, from: &str, to: &str) -> Result<(), std
let new_contents = contents.replace(from, to);
- let mut dst = File::create(&file_name)?;
+ let mut dst = File::create(file_name)?;
dst.write_all(new_contents.as_bytes())?;
Ok(())
@@ -67,7 +67,7 @@ fn handle_file(autogen_comment: &str, rust_filename: &str) -> Result<(), std::io
let pattern = "//! Generated file from";
- if line.starts_with(&pattern) {
+ if line.starts_with(pattern) {
new_contents.push(autogen_comment.into());
}
@@ -76,14 +76,14 @@ fn handle_file(autogen_comment: &str, rust_filename: &str) -> Result<(), std::io
// Although we've requested serde support via `Customize`, to
// allow the `kata-agent-ctl` tool to partially deserialise structures
// specified in JSON, we need this bit of additional magic.
- if line.starts_with(&struct_pattern) {
+ if line.starts_with(struct_pattern) {
new_contents.insert(new_contents.len() - 1, serde_default_code.trim().into());
}
}
let data = new_contents.join("\n");
- let mut dst = File::create(&rust_filename)?;
+ let mut dst = File::create(rust_filename)?;
dst.write_all(data.as_bytes())?;
@@ -157,13 +157,30 @@ fn real_main() -> Result<(), std::io::Error> {
// generate async
#[cfg(feature = "async")]
{
- codegen("src", &["protos/agent.proto", "protos/health.proto"], true)?;
+ codegen(
+ "src",
+ &[
+ "protos/agent.proto",
+ "protos/health.proto",
+ "protos/image.proto",
+ ],
+ true,
+ )?;
fs::rename("src/agent_ttrpc.rs", "src/agent_ttrpc_async.rs")?;
fs::rename("src/health_ttrpc.rs", "src/health_ttrpc_async.rs")?;
+ fs::rename("src/image_ttrpc.rs", "src/image_ttrpc_async.rs")?;
}
- codegen("src", &["protos/agent.proto", "protos/health.proto"], false)?;
+ codegen(
+ "src",
+ &[
+ "protos/agent.proto",
+ "protos/health.proto",
+ "protos/image.proto",
+ ],
+ false,
+ )?;
// There is a message named 'Box' in oci.proto
// so there is a struct named 'Box', we should replace Box<Self> to ::std::boxed::Box<Self>
diff --git a/src/libs/protocols/protos/image.proto b/src/libs/protocols/protos/image.proto
new file mode 100644
index 000000000..eb62837e6
--- /dev/null
+++ b/src/libs/protocols/protos/image.proto
@@ -0,0 +1,31 @@
+//
+// Copyright (c) 2021 Alibaba Inc.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+syntax = "proto3";
+
+option go_package = "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/agent/protocols/grpc";
+
+package grpc;
+
+// Image defines the public APIs for managing images.
+service Image {
+ // PullImage pulls an image with authentication config.
+ rpc PullImage(PullImageRequest) returns (PullImageResponse) {}
+}
+
+message PullImageRequest {
+ // Image name (e.g. docker.io/library/busybox:latest).
+ string image = 1;
+ // Unique image identifier, used to avoid duplication when unpacking the image layers.
+ string container_id = 2;
+ // Use USERNAME[:PASSWORD] for accessing the registry
+ string source_creds = 3;
+}
+
+message PullImageResponse {
+ // Reference to the image in use. For most runtimes, this should be an
+ // image ID or digest.
+ string image_ref = 1;
+}
diff --git a/src/libs/protocols/src/lib.rs b/src/libs/protocols/src/lib.rs
index 0c62b8a93..846878400 100644
--- a/src/libs/protocols/src/lib.rs
+++ b/src/libs/protocols/src/lib.rs
@@ -15,6 +15,10 @@ pub mod health;
pub mod health_ttrpc;
#[cfg(feature = "async")]
pub mod health_ttrpc_async;
+pub mod image;
+pub mod image_ttrpc;
+#[cfg(feature = "async")]
+pub mod image_ttrpc_async;
pub mod oci;
pub mod trans;
pub mod types;
diff --git a/src/libs/protocols/src/trans.rs b/src/libs/protocols/src/trans.rs
index e9ecfe785..ec8b38b91 100644
--- a/src/libs/protocols/src/trans.rs
+++ b/src/libs/protocols/src/trans.rs
@@ -105,9 +105,9 @@ impl From<oci::LinuxDeviceCgroup> for crate::oci::LinuxDeviceCgroup {
fn from(from: oci::LinuxDeviceCgroup) -> Self {
crate::oci::LinuxDeviceCgroup {
Allow: from.allow,
- Type: from.r#type,
- Major: from.major.map_or(0, |t| t as i64),
- Minor: from.minor.map_or(0, |t| t as i64),
+ Type: from.r#type.map_or("".to_string(), |t| t as String),
+ 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(),
@@ -123,7 +123,7 @@ impl From<oci::LinuxMemory> for crate::oci::LinuxMemory {
Swap: from.swap.map_or(0, |t| t),
Kernel: from.kernel.map_or(0, |t| t),
KernelTCP: from.kernel_tcp.map_or(0, |t| t),
- Swappiness: from.swappiness.map_or(0, |t| t as u64),
+ 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(),
@@ -332,7 +332,7 @@ impl From<oci::LinuxDevice> for crate::oci::LinuxDevice {
Type: from.r#type,
Major: from.major,
Minor: from.minor,
- FileMode: from.file_mode.map_or(0, |v| v as u32),
+ 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(),
@@ -468,17 +468,17 @@ 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() as i64);
+ major = Some(from.get_Major());
}
let mut minor = None;
if from.get_Minor() > 0 {
- minor = Some(from.get_Minor() as i64)
+ minor = Some(from.get_Minor())
}
oci::LinuxDeviceCgroup {
allow: from.get_Allow(),
- r#type: from.take_Type(),
+ r#type: Some(from.take_Type()),
major,
minor,
access: from.take_Access(),
diff --git a/src/libs/safe-path/src/pinned_path_buf.rs b/src/libs/safe-path/src/pinned_path_buf.rs
index d1816f450..15c80f4ce 100644
--- a/src/libs/safe-path/src/pinned_path_buf.rs
+++ b/src/libs/safe-path/src/pinned_path_buf.rs
@@ -295,7 +295,7 @@ mod tests {
barrier2.wait();
});
- let path = scoped_join(&root_path, "s").unwrap();
+ let path = scoped_join(root_path, "s").unwrap();
let data = fs::read_to_string(&path).unwrap();
assert_eq!(&data, "a");
assert!(path.is_file());
@@ -306,7 +306,7 @@ mod tests {
assert_eq!(&data, "b");
PinnedPathBuf::from_path(&path).unwrap_err();
- let pinned_path = PinnedPathBuf::new(&root_path, "s").unwrap();
+ let pinned_path = PinnedPathBuf::new(root_path, "s").unwrap();
let data = fs::read_to_string(&pinned_path).unwrap();
assert_eq!(&data, "b");
diff --git a/src/libs/safe-path/src/scoped_dir_builder.rs b/src/libs/safe-path/src/scoped_dir_builder.rs
index 1a4ba189f..2d231c62f 100644
--- a/src/libs/safe-path/src/scoped_dir_builder.rs
+++ b/src/libs/safe-path/src/scoped_dir_builder.rs
@@ -173,7 +173,7 @@ mod tests {
fs::write(rootfs_path.join("txt"), "test").unwrap();
ScopedDirBuilder::new(rootfs_path.join("txt")).unwrap_err();
- let mut builder = ScopedDirBuilder::new(&rootfs_path).unwrap();
+ let mut builder = ScopedDirBuilder::new(rootfs_path).unwrap();
// file with the same name already exists.
builder
@@ -268,7 +268,7 @@ mod tests {
symlink(rootfs_dir.path().join("b"), rootfs_dir.path().join("a")).unwrap();
let rootfs_path = &rootfs_dir.path().join("a");
- let mut builder = ScopedDirBuilder::new(&rootfs_path).unwrap();
+ let mut builder = ScopedDirBuilder::new(rootfs_path).unwrap();
builder.create_with_unscoped_path("/").unwrap_err();
builder
.create_with_unscoped_path(rootfs_path.join("../__xxxx___xxx__"))
@@ -278,13 +278,13 @@ mod tests {
.unwrap_err();
// Return `AlreadyExist` when recursive is false
- builder.create_with_unscoped_path(&rootfs_path).unwrap_err();
+ builder.create_with_unscoped_path(rootfs_path).unwrap_err();
builder
.create_with_unscoped_path(rootfs_path.join("."))
.unwrap_err();
builder.recursive(true);
- builder.create_with_unscoped_path(&rootfs_path).unwrap();
+ builder.create_with_unscoped_path(rootfs_path).unwrap();
builder
.create_with_unscoped_path(rootfs_path.join("."))
.unwrap();
diff --git a/src/libs/safe-path/src/scoped_path_resolver.rs b/src/libs/safe-path/src/scoped_path_resolver.rs
index 59b06bfe7..4d06f0062 100644
--- a/src/libs/safe-path/src/scoped_path_resolver.rs
+++ b/src/libs/safe-path/src/scoped_path_resolver.rs
@@ -329,31 +329,31 @@ mod tests {
let rootfs_path = &rootfs_dir.path();
assert_eq!(
- scoped_join(&rootfs_path, "a").unwrap(),
+ scoped_join(rootfs_path, "a").unwrap(),
rootfs_path.join("a")
);
assert_eq!(
- scoped_join(&rootfs_path, "./a").unwrap(),
+ scoped_join(rootfs_path, "./a").unwrap(),
rootfs_path.join("a")
);
assert_eq!(
- scoped_join(&rootfs_path, "././a").unwrap(),
+ scoped_join(rootfs_path, "././a").unwrap(),
rootfs_path.join("a")
);
assert_eq!(
- scoped_join(&rootfs_path, "c/d/../../a").unwrap(),
+ scoped_join(rootfs_path, "c/d/../../a").unwrap(),
rootfs_path.join("a")
);
assert_eq!(
- scoped_join(&rootfs_path, "c/d/../../../.././a").unwrap(),
+ scoped_join(rootfs_path, "c/d/../../../.././a").unwrap(),
rootfs_path.join("a")
);
assert_eq!(
- scoped_join(&rootfs_path, "../../a").unwrap(),
+ scoped_join(rootfs_path, "../../a").unwrap(),
rootfs_path.join("a")
);
assert_eq!(
- scoped_join(&rootfs_path, "./../a").unwrap(),
+ scoped_join(rootfs_path, "./../a").unwrap(),
rootfs_path.join("a")
);
}
@@ -370,18 +370,18 @@ mod tests {
fs::symlink("b/c", rootfs_dir.path().join("a")).unwrap();
let target = rootfs_path.join("b/c");
- assert_eq!(scoped_join(&rootfs_path, "a").unwrap(), target);
- assert_eq!(scoped_join(&rootfs_path, "./a").unwrap(), target);
- assert_eq!(scoped_join(&rootfs_path, "././a").unwrap(), target);
- assert_eq!(scoped_join(&rootfs_path, "b/c/../../a").unwrap(), target);
+ assert_eq!(scoped_join(rootfs_path, "a").unwrap(), target);
+ assert_eq!(scoped_join(rootfs_path, "./a").unwrap(), target);
+ assert_eq!(scoped_join(rootfs_path, "././a").unwrap(), target);
+ assert_eq!(scoped_join(rootfs_path, "b/c/../../a").unwrap(), target);
assert_eq!(
- scoped_join(&rootfs_path, "b/c/../../../.././a").unwrap(),
+ scoped_join(rootfs_path, "b/c/../../../.././a").unwrap(),
target
);
- assert_eq!(scoped_join(&rootfs_path, "../../a").unwrap(), target);
- assert_eq!(scoped_join(&rootfs_path, "./../a").unwrap(), target);
- assert_eq!(scoped_join(&rootfs_path, "a/../../../a").unwrap(), target);
- assert_eq!(scoped_join(&rootfs_path, "a/../../../b/c").unwrap(), target);
+ assert_eq!(scoped_join(rootfs_path, "../../a").unwrap(), target);
+ assert_eq!(scoped_join(rootfs_path, "./../a").unwrap(), target);
+ assert_eq!(scoped_join(rootfs_path, "a/../../../a").unwrap(), target);
+ assert_eq!(scoped_join(rootfs_path, "a/../../../b/c").unwrap(), target);
}
#[test]
diff --git a/src/libs/shim-interface/Cargo.toml b/src/libs/shim-interface/Cargo.toml
new file mode 100644
index 000000000..bd6cc6e0a
--- /dev/null
+++ b/src/libs/shim-interface/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "shim-interface"
+version = "0.1.0"
+description = "A library to provide service interface of Kata Containers"
+keywords = ["kata", "container", "http"]
+categories = ["services"]
+authors = ["The Kata Containers community <[email protected]>"]
+repository = "https://github.com/kata-containers/kata-containers.git"
+homepage = "https://katacontainers.io/"
+readme = "README.md"
+license = "Apache-2.0"
+edition = "2018"
+
+[dependencies]
+anyhow = "^1.0"
+tokio = { version = "1.8.0", features = ["rt-multi-thread"] }
+hyper = { version = "0.14.20", features = ["stream", "server", "http1"] }
+hyperlocal = "0.8"
diff --git a/src/libs/shim-interface/src/lib.rs b/src/libs/shim-interface/src/lib.rs
new file mode 100644
index 000000000..bbc96c09f
--- /dev/null
+++ b/src/libs/shim-interface/src/lib.rs
@@ -0,0 +1,66 @@
+// Copyright (c) 2022 Alibaba Cloud
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+//! shim-interface is a common library for different components of Kata Containers
+//! to make function call through services inside the runtime(runtime-rs runtime).
+//!
+//! Shim management:
+//! Currently, inside the shim, there is a shim management server running as the shim
+//! starts, working as a RESTful server. To make function call in runtime from another
+//! binary, using the utilities provided in this library is one of the methods.
+//!
+//! You may construct clients by construct a MgmtClient and let is make specific
+//! HTTP request to the server. The server inside shim will multiplex the request
+//! to its corresponding handler and run certain methods.
+
+use std::path::Path;
+
+use anyhow::{anyhow, Result};
+
+pub mod shim_mgmt;
+
+pub const KATA_PATH: &str = "/run/kata";
+pub const SHIM_MGMT_SOCK_NAME: &str = "shim-monitor.sock";
+
+// return sandbox's storage path
+pub fn sb_storage_path() -> String {
+ String::from(KATA_PATH)
+}
+
+// returns the address of the unix domain socket(UDS) for communication with shim
+// management service using http
+// normally returns "unix:///run/kata/{sid}/shim_monitor.sock"
+pub fn mgmt_socket_addr(sid: &str) -> Result<String> {
+ if sid.is_empty() {
+ return Err(anyhow!(
+ "Empty sandbox id for acquiring socket address for shim_mgmt"
+ ));
+ }
+
+ let p = Path::new(&sb_storage_path())
+ .join(sid)
+ .join(SHIM_MGMT_SOCK_NAME);
+
+ if let Some(p) = p.to_str() {
+ Ok(format!("unix://{}", p))
+ } else {
+ Err(anyhow!("Bad socket path"))
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_mgmt_socket_addr() {
+ let sid = "414123";
+ let addr = mgmt_socket_addr(sid).unwrap();
+ assert_eq!(addr, "unix:///run/kata/414123/shim-monitor.sock");
+
+ let sid = "";
+ assert!(mgmt_socket_addr(sid).is_err());
+ }
+}
diff --git a/src/libs/shim-interface/src/shim_mgmt/client.rs b/src/libs/shim-interface/src/shim_mgmt/client.rs
new file mode 100644
index 000000000..ace72c1d6
--- /dev/null
+++ b/src/libs/shim-interface/src/shim_mgmt/client.rs
@@ -0,0 +1,100 @@
+#![allow(dead_code)]
+// Copyright (c) 2019-2022 Alibaba Cloud
+// Copyright (c) 2019-2022 Ant Group
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+// Defines the general client functions used by other components acting like
+// clients. To be specific, a client first connect to the socket, then send
+// request to destined URL, and finally handle the request(or not)
+
+use std::{path::Path, path::PathBuf, time::Duration};
+
+use crate::mgmt_socket_addr;
+use anyhow::{anyhow, Context, Result};
+use hyper::{Body, Client, Method, Request, Response};
+use hyperlocal::{UnixClientExt, UnixConnector, Uri};
+
+/// Shim management client with timeout
+pub struct MgmtClient {
+ /// The socket *file path* on host file system
+ sock_path: PathBuf,
+
+ /// The http client connect to the long standing shim mgmt server
+ client: Client<UnixConnector, Body>,
+
+ /// Timeout value for each dial, usually 200ms will be enough
+ /// For heavier workload, you may want longer timeout
+ timeout: Option<Duration>,
+}
+
+impl MgmtClient {
+ /// Construct a new client connecting to shim mgmt server
+ pub fn new(sid: &str, timeout: Option<Duration>) -> Result<Self> {
+ let unix_socket_path = mgmt_socket_addr(sid).context("Failed to get unix socket path")?;
+ let s_addr = unix_socket_path
+ .strip_prefix("unix:")
+ .context("failed to strip prefix")?;
+ let sock_path = Path::new("/").join(s_addr).as_path().to_owned();
+ let client = Client::unix();
+ Ok(Self {
+ sock_path,
+ client,
+ timeout,
+ })
+ }
+
+ /// The http GET method for client, return a raw response. Further handling should be done by caller.
+ /// Parameter uri should be like "/agent-url" etc.
+ pub async fn get(&self, uri: &str) -> Result<Response<Body>> {
+ let url: hyper::Uri = Uri::new(&self.sock_path, uri).into();
+ let req = Request::builder()
+ .method(Method::GET)
+ .uri(url)
+ .body(Body::empty())?;
+ return self.send_request(req).await;
+ }
+
+ /// The HTTP Post method for client
+ pub async fn post(
+ &self,
+ uri: &str,
+ content_type: &str,
+ content: &str,
+ ) -> Result<Response<Body>> {
+ let url: hyper::Uri = Uri::new(&self.sock_path, uri).into();
+
+ // build body from content
+ let body = Body::from(content.to_string());
+ let req = Request::builder()
+ .method(Method::POST)
+ .uri(url)
+ .header("content-type", content_type)
+ .body(body)?;
+ return self.send_request(req).await;
+ }
+
+ /// The http PUT method for client
+ pub async fn put(&self, uri: &str, data: Vec<u8>) -> Result<Response<Body>> {
+ let url: hyper::Uri = Uri::new(&self.sock_path, uri).into();
+ let req = Request::builder()
+ .method(Method::PUT)
+ .uri(url)
+ .body(Body::from(data))?;
+ return self.send_request(req).await;
+ }
+
+ async fn send_request(&self, req: Request<Body>) -> Result<Response<Body>> {
+ let msg = format!("Request ({:?}) to uri {:?}", req.method(), req.uri());
+ let resp = self.client.request(req);
+ match self.timeout {
+ Some(timeout) => match tokio::time::timeout(timeout, resp).await {
+ Ok(result) => result.map_err(|e| anyhow!(e)),
+ Err(_) => Err(anyhow!("{:?} timeout after {:?}", msg, self.timeout)),
+ },
+ // if client timeout is not set, request waits with no deadline
+ None => resp.await.context(format!("{:?} failed", msg)),
+ }
+ }
+}
diff --git a/src/libs/shim-interface/src/shim_mgmt/mod.rs b/src/libs/shim-interface/src/shim_mgmt/mod.rs
new file mode 100644
index 000000000..0f9abf562
--- /dev/null
+++ b/src/libs/shim-interface/src/shim_mgmt/mod.rs
@@ -0,0 +1,24 @@
+// Copyright (c) 2022 Alibaba Cloud
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+/// The shim management client module
+pub mod client;
+
+/// The key for direct volume path
+pub const DIRECT_VOLUME_PATH_KEY: &str = "path";
+/// URL for stats direct volume
+pub const DIRECT_VOLUME_STATS_URL: &str = "/direct-volume/stats";
+/// URL for resizing direct volume
+pub const DIRECT_VOLUME_RESIZE_URL: &str = "/direct-volume/resize";
+/// URL for querying agent's socket
+pub const AGENT_URL: &str = "/agent-url";
+/// URL for operation on guest iptable (ipv4)
+pub const IP_TABLE_URL: &str = "/iptables";
+/// URL for operation on guest iptable (ipv6)
+pub const IP6_TABLE_URL: &str = "/ip6tables";
+/// URL for querying metrics inside shim
+pub const METRICS_URL: &str = "/metrics";
+
+pub const ERR_NO_SHIM_SERVER: &str = "Failed to create shim management server";
diff --git a/src/runtime-rs/Cargo.lock b/src/runtime-rs/Cargo.lock
index b70e39030..ea373c644 100644
--- a/src/runtime-rs/Cargo.lock
+++ b/src/runtime-rs/Cargo.lock
@@ -48,6 +48,7 @@ dependencies = [
"kata-types",
"log",
"logging",
+ "nix 0.24.2",
"oci",
"protobuf",
"protocols",
@@ -84,12 +85,6 @@ version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
-[[package]]
-name = "arc-swap"
-version = "0.4.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dabe5a181f83789739c194cbe5a897dde195078fac08568d09221fd6137a7ba8"
-
[[package]]
name = "arc-swap"
version = "1.5.0"
@@ -254,12 +249,28 @@ dependencies = [
"rustc-demangle",
]
+[[package]]
+name = "base64"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+[[package]]
+name = "bitmask-enum"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd9e32d7420c85055e8107e5b2463c4eeefeaac18b52359fe9f9c08a18f342b2"
+dependencies = [
+ "quote",
+ "syn",
+]
+
[[package]]
name = "blake3"
version = "1.3.1"
@@ -274,23 +285,6 @@ dependencies = [
"digest 0.10.3",
]
-[[package]]
-name = "blobfs"
-version = "0.1.0"
-source = "git+https://github.com/dragonflyoss/image-service.git?rev=316380792092f73c99f832c4cb44ef4319d6f76b#316380792092f73c99f832c4cb44ef4319d6f76b"
-dependencies = [
- "fuse-backend-rs",
- "libc",
- "log",
- "nydus-error",
- "rafs",
- "serde",
- "serde_json",
- "serde_with",
- "storage",
- "vm-memory",
-]
-
[[package]]
name = "block-buffer"
version = "0.9.0"
@@ -335,6 +329,16 @@ version = "3.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "415301c9de11005d4b92193c0eb7ac7adc37e5a49e0ac9bed0a42343512744b8"
+[[package]]
+name = "byte-unit"
+version = "4.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "581ad4b3d627b0c09a0ccb2912148f839acaca0b93cf54cbe42b6c674e86079c"
+dependencies = [
+ "serde",
+ "utf8-width",
+]
+
[[package]]
name = "byteorder"
version = "1.4.3"
@@ -480,18 +484,18 @@ dependencies = [
[[package]]
name = "core-foundation-sys"
-version = "0.2.3"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d"
-dependencies = [
- "libc",
-]
+checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
-name = "core-foundation-sys"
-version = "0.8.3"
+name = "cpufeatures"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
+dependencies = [
+ "libc",
+]
[[package]]
name = "cpuid-bool"
@@ -548,64 +552,28 @@ dependencies = [
"syn",
]
-[[package]]
-name = "darling"
-version = "0.13.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
-dependencies = [
- "darling_core",
- "darling_macro",
-]
-
-[[package]]
-name = "darling_core"
-version = "0.13.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
-dependencies = [
- "fnv",
- "ident_case",
- "proc-macro2",
- "quote",
- "strsim",
- "syn",
-]
-
-[[package]]
-name = "darling_macro"
-version = "0.13.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
-dependencies = [
- "darling_core",
- "quote",
- "syn",
-]
-
[[package]]
name = "dashmap"
-version = "5.2.0"
+version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c8858831f7781322e539ea39e72449c46b059638250c14344fec8d0aa6e539c"
+checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c"
dependencies = [
"cfg-if 1.0.0",
"num_cpus",
- "parking_lot 0.12.1",
]
[[package]]
name = "dbs-address-space"
-version = "0.1.0"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9acd47f8b1ad8a6a62450d2d83ced5452dbf9549e2b98709d945554b22a45ed7"
+checksum = "6bcc37dc0b8ffae1c5911d13ae630dc7a9020fa0de0edd178d6ab71daf56c8fc"
dependencies = [
- "arc-swap 1.5.0",
+ "arc-swap",
"libc",
"nix 0.23.1",
"thiserror",
"vm-memory",
- "vmm-sys-util",
+ "vmm-sys-util 0.11.0",
]
[[package]]
@@ -619,21 +587,23 @@ dependencies = [
[[package]]
name = "dbs-arch"
-version = "0.1.0"
-source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f89357fc97fb3608473073be037ea0b22787b1fa4c68b8eb3dd51f3c5fd6b41"
dependencies = [
"kvm-bindings",
"kvm-ioctls",
"libc",
"memoffset",
"vm-memory",
- "vmm-sys-util",
+ "vmm-sys-util 0.11.0",
]
[[package]]
name = "dbs-boot"
-version = "0.2.0"
-source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e6930547e688d8527705d1b7c4163c090c8535b8dd526d8251aa4dfdcbf2f82"
dependencies = [
"dbs-arch",
"kvm-bindings",
@@ -647,51 +617,69 @@ dependencies = [
[[package]]
name = "dbs-device"
-version = "0.1.0"
-source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14ecea44b4bc861c0c2ccb51868bea781286dc70e40ae46b54d4511e690a654a"
dependencies = [
"thiserror",
]
[[package]]
name = "dbs-interrupt"
-version = "0.1.0"
-source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15f217820329cea9d8d2870f9cdda426c5ca4379e33283c39338841a86bdc36c"
dependencies = [
"dbs-device",
"kvm-bindings",
"kvm-ioctls",
"libc",
- "vmm-sys-util",
+ "vmm-sys-util 0.11.0",
]
[[package]]
name = "dbs-legacy-devices"
-version = "0.1.0"
-source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4d089ac1c4d186c8133be59de09462e9793f7add10017c5b040318a3a7f431f"
dependencies = [
"dbs-device",
"dbs-utils",
"log",
"serde",
"vm-superio",
- "vmm-sys-util",
+ "vmm-sys-util 0.11.0",
]
[[package]]
name = "dbs-uhttp"
-version = "0.2.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b773f7f1b9088438e9746890c7c0836b133b07935812867a33e06e81c92c0cdc"
+checksum = "6fd0544fe7ba81fa8deb8800843836d279a81b051e2e8ab046fe1b0cb096c1cc"
dependencies = [
"libc",
"mio",
]
[[package]]
-name = "dbs-utils"
+name = "dbs-upcall"
version = "0.1.0"
-source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2fa8b67657cd71779eaceea1b5fa989b62a1be629a07be8498417772e5a8d35"
+dependencies = [
+ "anyhow",
+ "dbs-utils",
+ "dbs-virtio-devices",
+ "log",
+ "thiserror",
+ "timerfd",
+]
+
+[[package]]
+name = "dbs-utils"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cb6ff873451b76e22789af7fbe1d0478c42c717f817e66908be7a3a2288068c"
dependencies = [
"anyhow",
"event-manager",
@@ -700,15 +688,15 @@ dependencies = [
"serde",
"thiserror",
"timerfd",
- "vmm-sys-util",
+ "vmm-sys-util 0.11.0",
]
[[package]]
name = "dbs-virtio-devices"
-version = "0.1.0"
-source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f70cc3a62fa1c169beca6921ef0d3cf38fdfe7cd732ac76c8517bc8a3df9338"
dependencies = [
- "blobfs",
"byteorder",
"caps",
"dbs-device",
@@ -722,7 +710,8 @@ dependencies = [
"libc",
"log",
"nix 0.23.1",
- "rafs",
+ "nydus-blobfs",
+ "nydus-rafs",
"rlimit",
"serde",
"serde_json",
@@ -731,7 +720,7 @@ dependencies = [
"virtio-bindings",
"virtio-queue",
"vm-memory",
- "vmm-sys-util",
+ "vmm-sys-util 0.11.0",
]
[[package]]
@@ -765,21 +754,11 @@ dependencies = [
"subtle",
]
-[[package]]
-name = "diskarbitration-sys"
-version = "0.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f82432ae94d42f160b6e17389d6e1c1eee29827b99ad32d35a0a96bb98bedb5"
-dependencies = [
- "core-foundation-sys 0.2.3",
- "libc",
-]
-
[[package]]
name = "dragonball"
version = "0.1.0"
dependencies = [
- "arc-swap 1.5.0",
+ "arc-swap",
"bytes 1.1.0",
"dbs-address-space",
"dbs-allocator",
@@ -788,6 +767,7 @@ dependencies = [
"dbs-device",
"dbs-interrupt",
"dbs-legacy-devices",
+ "dbs-upcall",
"dbs-utils",
"dbs-virtio-devices",
"kvm-bindings",
@@ -806,7 +786,7 @@ dependencies = [
"thiserror",
"virtio-queue",
"vm-memory",
- "vmm-sys-util",
+ "vmm-sys-util 0.11.0",
]
[[package]]
@@ -859,7 +839,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "377fa591135fbe23396a18e2655a6d5481bf7c5823cdfa3cc81b01a229cbe640"
dependencies = [
"libc",
- "vmm-sys-util",
+ "vmm-sys-util 0.11.0",
]
[[package]]
@@ -922,23 +902,27 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "fuse-backend-rs"
-version = "0.9.0"
+version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a96ec48cd39ee2504eaa4a31b88262b7d13151a4da0b53af8fd212c7c9ffa5d"
+checksum = "994a3bfb694ee52bf8f3bca80d784b723f150810998219337e429cc5dbe92717"
dependencies = [
- "arc-swap 1.5.0",
+ "arc-swap",
"bitflags",
"caps",
- "core-foundation-sys 0.2.3",
- "diskarbitration-sys",
+ "core-foundation-sys",
+ "io-uring",
"lazy_static",
"libc",
"log",
"mio",
- "nix 0.23.1",
+ "nix 0.24.2",
+ "scoped-tls",
+ "slab",
+ "socket2",
+ "tokio-uring",
"virtio-queue",
"vm-memory",
- "vmm-sys-util",
+ "vmm-sys-util 0.10.0",
]
[[package]]
@@ -1124,16 +1108,16 @@ dependencies = [
[[package]]
name = "governor"
-version = "0.4.2"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19775995ee20209163239355bc3ad2f33f83da35d9ef72dea26e5af753552c87"
+checksum = "7df0ee4b237afb71e99f7e2fbd840ffec2d6c4bb569f69b2af18aa1f63077d38"
dependencies = [
"dashmap",
"futures 0.3.21",
"futures-timer",
"no-std-compat",
"nonzero_ext",
- "parking_lot 0.12.1",
+ "parking_lot 0.11.2",
"quanta",
"rand 0.8.5",
"smallvec",
@@ -1169,12 +1153,82 @@ dependencies = [
"libc",
]
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
+name = "http"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
+dependencies = [
+ "bytes 1.1.0",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
+dependencies = [
+ "bytes 1.1.0",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
+
[[package]]
name = "httpdate"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+[[package]]
+name = "hyper"
+version = "0.14.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac"
+dependencies = [
+ "bytes 1.1.0",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyperlocal"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fafdf7b2b2de7c9784f76e02c0935e65a8117ec3b768644379983ab333ac98c"
+dependencies = [
+ "futures-util",
+ "hex",
+ "hyper",
+ "pin-project",
+ "tokio",
+]
+
[[package]]
name = "hypervisor"
version = "0.1.0"
@@ -1190,14 +1244,16 @@ dependencies = [
"logging",
"nix 0.24.2",
"persist",
+ "rand 0.8.5",
"seccompiler",
"serde",
"serde_json",
+ "shim-interface",
"slog",
"slog-scope",
"thiserror",
"tokio",
- "vmm-sys-util",
+ "vmm-sys-util 0.11.0",
]
[[package]]
@@ -1207,18 +1263,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad2bfd338099682614d3ee3fe0cd72e0b6a41ca6a87f6a74a3bd593c91650501"
dependencies = [
"android_system_properties",
- "core-foundation-sys 0.8.3",
+ "core-foundation-sys",
"js-sys",
"wasm-bindgen",
"winapi",
]
-[[package]]
-name = "ident_case"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
-
[[package]]
name = "idna"
version = "0.2.3"
@@ -1334,7 +1384,10 @@ dependencies = [
name = "kata-types"
version = "0.1.0"
dependencies = [
- "byte-unit",
+ "anyhow",
+ "base64",
+ "bitmask-enum",
+ "byte-unit 3.1.4",
"glob",
"lazy_static",
"num_cpus",
@@ -1363,7 +1416,7 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a78c049190826fff959994b7c1d8a2930d0a348f1b8f3aa4f9bb34cd5d7f2952"
dependencies = [
- "vmm-sys-util",
+ "vmm-sys-util 0.11.0",
]
[[package]]
@@ -1374,7 +1427,7 @@ checksum = "97422ba48d7ffb66fd4d18130f72ab66f9bbbf791fb7a87b9291cdcfec437593"
dependencies = [
"kvm-bindings",
"libc",
- "vmm-sys-util",
+ "vmm-sys-util 0.11.0",
]
[[package]]
@@ -1391,9 +1444,9 @@ checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "linux-loader"
-version = "0.4.0"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a5e77493808403a6bd56a301a64ea6b9342e36ea845044bf0dfdf56fe52fa08"
+checksum = "62a2f912deca034ec34b0a43a390059ea98daac40e440ebe8bea88f3315fe168"
dependencies = [
"vm-memory",
]
@@ -1654,10 +1707,49 @@ dependencies = [
"libc",
]
+[[package]]
+name = "nydus-api"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61fbfbdb58ff07bed50b412d4315b3c5808979bb5decb56706ac66d53daf2cf3"
+dependencies = [
+ "dbs-uhttp",
+ "http",
+ "lazy_static",
+ "libc",
+ "log",
+ "mio",
+ "nydus-error",
+ "nydus-utils",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "url",
+ "vmm-sys-util 0.10.0",
+]
+
+[[package]]
+name = "nydus-blobfs"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ef818ecadc217f49ce8d48506b885d8d26f877d26b0108d90d8b82547663d95"
+dependencies = [
+ "fuse-backend-rs",
+ "libc",
+ "log",
+ "nydus-error",
+ "nydus-rafs",
+ "nydus-storage",
+ "serde",
+ "serde_json",
+ "vm-memory",
+]
+
[[package]]
name = "nydus-error"
-version = "0.2.0"
-source = "git+https://github.com/dragonflyoss/image-service.git?rev=316380792092f73c99f832c4cb44ef4319d6f76b#316380792092f73c99f832c4cb44ef4319d6f76b"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90960fb7268286328d11f18e747bed58d8e3bbea6f401bd316e91fe39f4f7213"
dependencies = [
"backtrace",
"httpdate",
@@ -1667,22 +1759,80 @@ dependencies = [
"serde_json",
]
+[[package]]
+name = "nydus-rafs"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4a06e8b0b4a90acc2d128d2f3b1ab6ae5d325116f1f69754bd3628dbd4499f4"
+dependencies = [
+ "anyhow",
+ "arc-swap",
+ "bitflags",
+ "blake3",
+ "fuse-backend-rs",
+ "futures 0.3.21",
+ "lazy_static",
+ "libc",
+ "log",
+ "lz4-sys",
+ "nix 0.24.2",
+ "nydus-api",
+ "nydus-error",
+ "nydus-storage",
+ "nydus-utils",
+ "serde",
+ "serde_json",
+ "sha2 0.10.5",
+ "spmc",
+ "vm-memory",
+]
+
+[[package]]
+name = "nydus-storage"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5dd10c443f47a0ac7d71021f7658a605c2be5b46576a91f3238babbaf3f459e"
+dependencies = [
+ "anyhow",
+ "arc-swap",
+ "bitflags",
+ "dbs-uhttp",
+ "fuse-backend-rs",
+ "futures 0.3.21",
+ "governor",
+ "lazy_static",
+ "libc",
+ "log",
+ "nix 0.24.2",
+ "nydus-api",
+ "nydus-error",
+ "nydus-utils",
+ "serde",
+ "serde_json",
+ "sha2 0.10.5",
+ "tokio",
+ "vm-memory",
+ "vmm-sys-util 0.10.0",
+]
+
[[package]]
name = "nydus-utils"
-version = "0.1.0"
-source = "git+https://github.com/dragonflyoss/image-service.git?rev=316380792092f73c99f832c4cb44ef4319d6f76b#316380792092f73c99f832c4cb44ef4319d6f76b"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b7e976c67052c3ff63372e2a07701923796d25a77eac605824b26d406ab0918"
dependencies = [
"blake3",
"flate2",
- "fuse-backend-rs",
"lazy_static",
"libc",
"log",
"lz4-sys",
+ "nix 0.24.2",
"nydus-error",
"serde",
"serde_json",
- "sha2",
+ "sha2 0.10.5",
+ "tokio",
"zstd",
]
@@ -1795,6 +1945,7 @@ dependencies = [
"safe-path",
"serde",
"serde_json",
+ "shim-interface",
]
[[package]]
@@ -1807,6 +1958,26 @@ dependencies = [
"indexmap",
]
+[[package]]
+name = "pin-project"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "pin-project-lite"
version = "0.2.9"
@@ -1964,34 +2135,6 @@ dependencies = [
"proc-macro2",
]
-[[package]]
-name = "rafs"
-version = "0.1.0"
-source = "git+https://github.com/dragonflyoss/image-service.git?rev=316380792092f73c99f832c4cb44ef4319d6f76b#316380792092f73c99f832c4cb44ef4319d6f76b"
-dependencies = [
- "anyhow",
- "arc-swap 0.4.8",
- "bitflags",
- "blake3",
- "flate2",
- "fuse-backend-rs",
- "futures 0.3.21",
- "lazy_static",
- "libc",
- "log",
- "lz4-sys",
- "nix 0.23.1",
- "nydus-error",
- "nydus-utils",
- "serde",
- "serde_json",
- "serde_with",
- "sha2",
- "spmc",
- "storage",
- "vm-memory",
-]
-
[[package]]
name = "rand"
version = "0.3.23"
@@ -2163,6 +2306,7 @@ dependencies = [
"anyhow",
"async-trait",
"bitflags",
+ "byte-unit 4.0.17",
"cgroups-rs",
"futures 0.3.21",
"hypervisor",
@@ -2180,8 +2324,11 @@ dependencies = [
"rtnetlink",
"scopeguard",
"serde",
+ "serde_json",
"slog",
"slog-scope",
+ "tempfile",
+ "test-utils",
"tokio",
"uuid",
]
@@ -2216,12 +2363,16 @@ version = "0.1.0"
dependencies = [
"anyhow",
"common",
+ "hyper",
+ "hyperlocal",
+ "hypervisor",
"kata-types",
"lazy_static",
"linux_container",
"logging",
"oci",
"persist",
+ "shim-interface",
"slog",
"slog-scope",
"tokio",
@@ -2268,6 +2419,12 @@ dependencies = [
"libc",
]
+[[package]]
+name = "scoped-tls"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
+
[[package]]
name = "scopeguard"
version = "1.1.0"
@@ -2314,28 +2471,6 @@ dependencies = [
"serde",
]
-[[package]]
-name = "serde_with"
-version = "1.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff"
-dependencies = [
- "serde",
- "serde_with_macros",
-]
-
-[[package]]
-name = "serde_with_macros"
-version = "1.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082"
-dependencies = [
- "darling",
- "proc-macro2",
- "quote",
- "syn",
-]
-
[[package]]
name = "serial_test"
version = "0.5.1"
@@ -2369,6 +2504,7 @@ dependencies = [
"logging",
"persist",
"runtimes",
+ "shim-interface",
"slog",
"slog-scope",
"tokio",
@@ -2388,6 +2524,17 @@ dependencies = [
"opaque-debug",
]
+[[package]]
+name = "sha2"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf9db03534dff993187064c4e0c05a5708d2a9728ace9a8959b77bedf415dac5"
+dependencies = [
+ "cfg-if 1.0.0",
+ "cpufeatures",
+ "digest 0.10.3",
+]
+
[[package]]
name = "shim"
version = "0.1.0"
@@ -2407,7 +2554,7 @@ dependencies = [
"rand 0.8.5",
"serial_test",
"service",
- "sha2",
+ "sha2 0.9.3",
"slog",
"slog-async",
"slog-scope",
@@ -2419,6 +2566,27 @@ dependencies = [
"unix_socket2",
]
+[[package]]
+name = "shim-ctl"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "common",
+ "logging",
+ "runtimes",
+ "tokio",
+]
+
+[[package]]
+name = "shim-interface"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "hyper",
+ "hyperlocal",
+ "tokio",
+]
+
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
@@ -2470,7 +2638,7 @@ version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f95a4b4c3274cd2869549da82b57ccc930859bdbf5bcea0424bc5f140b3c786"
dependencies = [
- "arc-swap 1.5.0",
+ "arc-swap",
"lazy_static",
"slog",
]
@@ -2508,40 +2676,6 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02a8428da277a8e3a15271d79943e80ccc2ef254e78813a166a08d65e4c3ece5"
-[[package]]
-name = "storage"
-version = "0.5.0"
-source = "git+https://github.com/dragonflyoss/image-service.git?rev=316380792092f73c99f832c4cb44ef4319d6f76b#316380792092f73c99f832c4cb44ef4319d6f76b"
-dependencies = [
- "anyhow",
- "arc-swap 0.4.8",
- "bitflags",
- "dbs-uhttp",
- "fuse-backend-rs",
- "futures 0.3.21",
- "governor",
- "lazy_static",
- "libc",
- "log",
- "nix 0.23.1",
- "nydus-error",
- "nydus-utils",
- "serde",
- "serde_json",
- "serde_with",
- "sha2",
- "spmc",
- "tokio",
- "vm-memory",
- "vmm-sys-util",
-]
-
-[[package]]
-name = "strsim"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
-
[[package]]
name = "strum"
version = "0.24.0"
@@ -2611,6 +2745,13 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "test-utils"
+version = "0.1.0"
+dependencies = [
+ "nix 0.24.2",
+]
+
[[package]]
name = "tests_utils"
version = "0.1.0"
@@ -2732,6 +2873,20 @@ dependencies = [
"syn",
]
+[[package]]
+name = "tokio-uring"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3ad494f39874984d990ade7f6319dafbcd3301ff0b1841f8a55a1ebb3e742c8"
+dependencies = [
+ "io-uring",
+ "libc",
+ "scoped-tls",
+ "slab",
+ "socket2",
+ "tokio",
+]
+
[[package]]
name = "tokio-vsock"
version = "0.3.1"
@@ -2763,6 +2918,38 @@ dependencies = [
"serde",
]
+[[package]]
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
+[[package]]
+name = "tracing"
+version = "0.1.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
+dependencies = [
+ "cfg-if 1.0.0",
+ "pin-project-lite",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
+
[[package]]
name = "ttrpc"
version = "0.6.1"
@@ -2863,6 +3050,12 @@ dependencies = [
"percent-encoding",
]
+[[package]]
+name = "utf8-width"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1"
+
[[package]]
name = "uuid"
version = "0.4.0"
@@ -2929,13 +3122,13 @@ checksum = "3ff512178285488516ed85f15b5d0113a7cdb89e9e8a760b269ae4f02b84bd6b"
[[package]]
name = "virtio-queue"
-version = "0.1.0"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f90da9e627f6aaf667cc7b6548a28be332d3e1f058f4ceeb46ab6bcee5c4b74d"
+checksum = "519c0a333c871650269cba303bc108075d52a0c0d64f9b91fae61829b53725af"
dependencies = [
"log",
"vm-memory",
- "vmm-sys-util",
+ "vmm-sys-util 0.11.0",
]
[[package]]
@@ -2946,11 +3139,11 @@ checksum = "f43fb5a6bd1a7d423ad72802801036719b7546cf847a103f8fe4575f5b0d45a6"
[[package]]
name = "vm-memory"
-version = "0.7.0"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "339d4349c126fdcd87e034631d7274370cf19eb0e87b33166bcd956589fc72c5"
+checksum = "583f213899e8a5eea23d9c507252d4bed5bc88f0ecbe0783262f80034630744b"
dependencies = [
- "arc-swap 1.5.0",
+ "arc-swap",
"libc",
"winapi",
]
@@ -2963,9 +3156,19 @@ checksum = "a4b5231d334edbc03b22704caa1a022e4c07491d6df736593f26094df8b04a51"
[[package]]
name = "vmm-sys-util"
-version = "0.9.0"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "733537bded03aaa93543f785ae997727b30d1d9f4a03b7861d23290474242e11"
+checksum = "08604d7be03eb26e33b3cee3ed4aef2bf550b305d1cca60e84da5d28d3790b62"
+dependencies = [
+ "bitflags",
+ "libc",
+]
+
+[[package]]
+name = "vmm-sys-util"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc06a16ee8ebf0d9269aed304030b0d20a866b8b3dd3d4ce532596ac567a0d24"
dependencies = [
"bitflags",
"libc",
@@ -2987,6 +3190,16 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
+[[package]]
+name = "want"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+dependencies = [
+ "log",
+ "try-lock",
+]
+
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
@@ -3205,8 +3418,3 @@ dependencies = [
"cc",
"libc",
]
-
-[[patch.unused]]
-name = "dbs-upcall"
-version = "0.1.0"
-source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
diff --git a/src/runtime-rs/Cargo.toml b/src/runtime-rs/Cargo.toml
index 470b29a64..185912145 100644
--- a/src/runtime-rs/Cargo.toml
+++ b/src/runtime-rs/Cargo.toml
@@ -1,14 +1,5 @@
[workspace]
members = [
"crates/shim",
+ "crates/shim-ctl",
]
-
-[patch.'crates-io']
-dbs-device = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
-dbs-utils = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
-dbs-interrupt = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
-dbs-legacy-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
-dbs-virtio-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
-dbs-boot = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
-dbs-arch = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
-dbs-upcall = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "7a8e832b53d66994d6a16f0513d69f540583dcd0" }
diff --git a/src/runtime-rs/Makefile b/src/runtime-rs/Makefile
index 58d4b11d1..ea9751738 100644
--- a/src/runtime-rs/Makefile
+++ b/src/runtime-rs/Makefile
@@ -31,7 +31,7 @@ test:
else
##TARGET default: build code
default: runtime show-header
-#TARGET test: run cargo tests
+##TARGET test: run cargo tests
test:
@cargo test --all --target $(TRIPLE) $(EXTRA_RUSTFEATURES) -- --nocapture
endif
@@ -50,7 +50,6 @@ EXEC_PREFIX := $(PREFIX)/local
BINDIR := $(EXEC_PREFIX)/bin
else
EXEC_PREFIX := $(PREFIX)
-##VAR BINDIR=<path> is a directory for installing executable programs
# when creating the kata-deploy image, the default installation path for go runtime is $(EXEC_PREFIX)/bin, so we put it here for multiple runtime
BINDIR := $(EXEC_PREFIX)/runtime-rs/bin/
endif
@@ -73,7 +72,7 @@ HYPERVISOR_CLH = cloud-hypervisor
DEFAULT_HYPERVISOR ?= $(HYPERVISOR_DB)
-# List of hypervisors this build system can generate configuration for.
+##VAR HYPERVISOR=<hypervisor_name> List of hypervisors this build system can generate configuration for.
HYPERVISORS := $(HYPERVISOR_DB) $(HYPERVISOR_ACRN) $(HYPERVISOR_FC) $(HYPERVISOR_QEMU) $(HYPERVISOR_CLH)
DBVALIDHYPERVISORPATHS := []
@@ -84,28 +83,28 @@ PKGLIBEXECDIR := $(LIBEXECDIR)/$(PROJECT_DIR)
FIRMWAREPATH :=
FIRMWAREVOLUMEPATH :=
-# Default number of vCPUs
+##VAR DEFVCPUS=<number> Default number of vCPUs
DEFVCPUS := 1
-# Default maximum number of vCPUs
+##VAR DEFMAXVCPUS=<number> Default maximum number of vCPUs
DEFMAXVCPUS := 0
-# Default memory size in MiB
+##VAR DEFMEMSZ=<number> Default memory size in MiB
DEFMEMSZ := 2048
-# Default memory slots
+##VAR DEFMEMSLOTS=<number> Default memory slots
# Cases to consider :
# - nvdimm rootfs image
# - preallocated memory
# - vm template memory
# - hugepage memory
DEFMEMSLOTS := 10
-#Default number of bridges
-DEFBRIDGES := 1
+##VAR DEFBRIDGES=<number> Default number of bridges
+DEFBRIDGES := 0
DEFENABLEANNOTATIONS := []
DEFDISABLEGUESTSECCOMP := true
DEFDISABLEGUESTEMPTYDIR := false
-#Default experimental features enabled
+##VAR DEFAULTEXPFEATURES=[features] Default experimental features enabled
DEFAULTEXPFEATURES := []
DEFDISABLESELINUX := false
-#Default entropy source
+##VAR DEFENTROPYSOURCE=[entropy_source] Default entropy source
DEFENTROPYSOURCE := /dev/urandom
DEFVALIDENTROPYSOURCES := [\"/dev/urandom\",\"/dev/random\",\"\"]
DEFDISABLEBLOCK := false
@@ -116,8 +115,8 @@ ifeq ($(ARCH),x86_64)
DEFVIRTIOFSDAEMON := $(LIBEXECDIR)/virtiofsd
endif
DEFVALIDVIRTIOFSDAEMONPATHS := [\"$(DEFVIRTIOFSDAEMON)\"]
-# Default DAX mapping cache size in MiB
-#if value is 0, DAX is not enabled
+##VAR DEFVIRTIOFSCACHESIZE=<cache_size> Default DAX mapping cache size in MiB
+# if value is 0, DAX is not enabled
DEFVIRTIOFSCACHESIZE ?= 0
DEFVIRTIOFSCACHE ?= auto
# Format example:
@@ -134,7 +133,7 @@ DEFFILEMEMBACKEND := ""
DEFVALIDFILEMEMBACKENDS := [\"$(DEFFILEMEMBACKEND)\"]
DEFMSIZE9P := 8192
DEFVFIOMODE := guest-kernel
-# Default cgroup model
+##VAR DEFSANDBOXCGROUPONLY=<bool> Default cgroup model
DEFSANDBOXCGROUPONLY ?= false
DEFSTATICRESOURCEMGMT_DB ?= false
DEFBINDMOUNTS := []
@@ -160,9 +159,9 @@ KNOWN_HYPERVISORS =
CONFDIR := $(DEFAULTSDIR)/$(PROJECT_DIR)
SYSCONFDIR := $(SYSCONFDIR)/$(PROJECT_DIR)
-# Main configuration file location for stateless systems
+##VAR CONFIG_PATH=<path> Main configuration file location for stateless systems
CONFIG_PATH := $(abspath $(CONFDIR)/$(CONFIG_FILE))
-# Secondary configuration file location. Note that this takes precedence
+##VAR SYSCONFIG=<path> Secondary configuration file location. Note that this takes precedence
# over CONFIG_PATH.
SYSCONFIG := $(abspath $(SYSCONFDIR)/$(CONFIG_FILE))
SHAREDIR := $(SHAREDIR)
@@ -177,7 +176,7 @@ ifneq (,$(DBCMD))
SYSCONFIG_DB = $(abspath $(SYSCONFDIR)/$(CONFIG_FILE_DB))
SYSCONFIG_PATHS += $(SYSCONFIG_DB)
CONFIGS += $(CONFIG_DB)
- # dragonball-specific options (all should be suffixed by "_dragonball")
+ # dragonball-specific options (all should be suffixed by "_DB")
DEFMAXVCPUS_DB := 1
DEFBLOCKSTORAGEDRIVER_DB := virtio-blk
DEFNETWORKMODEL_DB := tcfilter
@@ -291,9 +290,6 @@ COMMIT_NO := $(shell git rev-parse HEAD 2>/dev/null || true)
COMMIT := $(if $(shell git status --porcelain --untracked-files=no 2>/dev/null || true),${COMMIT_NO}-dirty,${COMMIT_NO})
COMMIT_MSG = $(if $(COMMIT),$(COMMIT),unknown)
-# Exported to allow cargo to see it
-export VERSION_COMMIT := $(if $(COMMIT),$(VERSION)-$(COMMIT),$(VERSION))
-
EXTRA_RUSTFEATURES :=
ifneq ($(EXTRA_RUSTFEATURES),)
@@ -323,8 +319,8 @@ GENERATED_REPLACEMENTS= \
CONTAINERD_RUNTIME_NAME \
RUNTIME_VERSION \
BINDIR \
- COMMIT \
- VERSION_COMMIT
+ COMMIT
+
GENERATED_FILES :=
GENERATED_FILES += $(GENERATED_CODE)
@@ -358,15 +354,17 @@ endef
.DEFAULT_GOAL := default
+GENERATED_FILES += $(CONFIGS)
+
runtime: $(TARGET)
-$(TARGET): $(GENERATED_CODE) $(TARGET_PATH)
+static-checks-build: $(GENERATED_FILES)
+
+$(TARGET): $(GENERATED_FILES) $(TARGET_PATH)
$(TARGET_PATH): $(SOURCES) | show-summary
@RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings" cargo build --target $(TRIPLE) --$(BUILD_TYPE) $(EXTRA_RUSTFEATURES)
-GENERATED_FILES += $(CONFIGS)
-
$(GENERATED_FILES): %: %.in
@sed \
$(foreach r,$(GENERATED_REPLACEMENTS),-e 's|@$r@|$($r)|g') \
@@ -454,7 +452,7 @@ endif
@printf "\tassets path (PKGDATADIR) : %s\n" $(abspath $(PKGDATADIR))
@printf "\tshim path (PKGLIBEXECDIR) : %s\n" $(abspath $(PKGLIBEXECDIR))
@printf "\n"
-## help: Show help comments that start with `##VAR` and `##TARGET`
+##TARGET help: Show help comments that start with `##VAR` and `##TARGET` in runtime-rs makefile
help: Makefile show-summary
@echo "========================== Help ============================="
@echo "Variables:"
@@ -491,7 +489,7 @@ install-runtime: runtime
install-configs: $(CONFIGS)
$(foreach f,$(CONFIGS),$(call INSTALL_FILE,$f,$(dir $(CONFIG_PATH)))) \
- sudo ln -sf $(DEFAULT_HYPERVISOR_CONFIG) $(DESTDIR)/$(CONFIG_PATH)
+ ln -sf $(DEFAULT_HYPERVISOR_CONFIG) $(DESTDIR)/$(CONFIG_PATH)
.PHONY: \
help \
diff --git a/src/runtime-rs/README.md b/src/runtime-rs/README.md
index a9f85e45d..973439975 100644
--- a/src/runtime-rs/README.md
+++ b/src/runtime-rs/README.md
@@ -97,12 +97,15 @@ Currently, only built-in `Dragonball` has been implemented.
Persist defines traits and functions to help different components save state to disk and load state from disk.
+### helper libraries
+
+Some helper libraries are maintained in [the library directory](../libs) so that they can be shared with other rust components.
+
## Build and install
-```bash
-$ make
-$ sudo make install
-```
+See the
+[build from the source section of the rust runtime installation guide](../../docs/install/kata-containers-3.0-rust-runtime-installation-guide.md#build-from-source-installation).
+
## Configuration
`runtime-rs` has the same [configuration as `runtime`](../runtime/README.md#configuration) with some [limitations](#limitations).
@@ -117,6 +120,8 @@ See the
See the
[debugging section of the developer guide](../../docs/Developer-Guide.md#troubleshoot-kata-containers).
+An [experimental alternative binary](crates/shim-ctl/README.md) is available that removes containerd dependencies and makes it easier to run the shim proper outside of the runtime's usual deployment environment (i.e. on a developer machine).
+
## Limitations
For Kata Containers limitations, see the
diff --git a/src/runtime-rs/config/configuration-dragonball.toml.in b/src/runtime-rs/config/configuration-dragonball.toml.in
index cb8d7aeee..ca1db2681 100644
--- a/src/runtime-rs/config/configuration-dragonball.toml.in
+++ b/src/runtime-rs/config/configuration-dragonball.toml.in
@@ -136,6 +136,14 @@ block_device_driver = "@DEFBLOCKSTORAGEDRIVER_DB@"
# of shim, does not need an external virtiofsd process.
shared_fs = "@DBSHAREDFS@"
+# 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
+
[agent.@PROJECT_TYPE@]
container_pipe_size=@PIPESIZE@
# If enabled, make the agent display debug-level messages.
diff --git a/src/runtime-rs/crates/agent/Cargo.toml b/src/runtime-rs/crates/agent/Cargo.toml
index 69dd2b753..0deca014d 100644
--- a/src/runtime-rs/crates/agent/Cargo.toml
+++ b/src/runtime-rs/crates/agent/Cargo.toml
@@ -20,6 +20,7 @@ slog-scope = "4.4.0"
ttrpc = { version = "0.6.1" }
tokio = { version = "1.8.0", features = ["fs", "rt"] }
url = "2.2.2"
+nix = "0.24.2"
kata-types = { path = "../../../libs/kata-types"}
logging = { path = "../../../libs/logging"}
diff --git a/src/runtime-rs/crates/agent/src/kata/agent.rs b/src/runtime-rs/crates/agent/src/kata/agent.rs
index 31b3d6635..b403f0f44 100644
--- a/src/runtime-rs/crates/agent/src/kata/agent.rs
+++ b/src/runtime-rs/crates/agent/src/kata/agent.rs
@@ -40,6 +40,10 @@ impl AgentManager for KataAgent {
self.stop_log_forwarder().await;
}
+ async fn agent_sock(&self) -> Result<String> {
+ self.agent_sock().await
+ }
+
async fn agent_config(&self) -> AgentConfig {
self.agent_config().await
}
@@ -109,5 +113,7 @@ impl_agent!(
create_sandbox | crate::CreateSandboxRequest | crate::Empty | None,
destroy_sandbox | crate::Empty | crate::Empty | None,
copy_file | crate::CopyFileRequest | crate::Empty | None,
- get_oom_event | crate::Empty | crate::OomEventResponse | Some(0)
+ get_oom_event | crate::Empty | crate::OomEventResponse | Some(0),
+ get_ip_tables | crate::GetIPTablesRequest | crate::GetIPTablesResponse | None,
+ set_ip_tables | crate::SetIPTablesRequest | crate::SetIPTablesResponse | None
);
diff --git a/src/runtime-rs/crates/agent/src/kata/mod.rs b/src/runtime-rs/crates/agent/src/kata/mod.rs
index 2a9283c99..d87965f61 100644
--- a/src/runtime-rs/crates/agent/src/kata/mod.rs
+++ b/src/runtime-rs/crates/agent/src/kata/mod.rs
@@ -7,12 +7,15 @@
mod agent;
mod trans;
-use std::os::unix::io::{IntoRawFd, RawFd};
+use std::{
+ os::unix::io::{IntoRawFd, RawFd},
+ sync::Arc,
+};
use anyhow::{Context, Result};
use kata_types::config::Agent as AgentConfig;
use protocols::{agent_ttrpc_async as agent_ttrpc, health_ttrpc_async as health_ttrpc};
-use tokio::sync::Mutex;
+use tokio::sync::RwLock;
use ttrpc::asynchronous::Client;
use crate::{log_forwarder::LogForwarder, sock};
@@ -41,27 +44,25 @@ pub(crate) struct KataAgentInner {
log_forwarder: LogForwarder,
}
-unsafe impl Send for KataAgent {}
-unsafe impl Sync for KataAgent {}
pub struct KataAgent {
- pub(crate) inner: Mutex<KataAgentInner>,
+ pub(crate) inner: Arc<RwLock<KataAgentInner>>,
}
impl KataAgent {
pub fn new(config: AgentConfig) -> Self {
KataAgent {
- inner: Mutex::new(KataAgentInner {
+ inner: Arc::new(RwLock::new(KataAgentInner {
client: None,
client_fd: -1,
socket_address: "".to_string(),
config,
log_forwarder: LogForwarder::new(),
- }),
+ })),
}
}
pub async fn get_health_client(&self) -> Option<(health_ttrpc::HealthClient, i64, RawFd)> {
- let inner = self.inner.lock().await;
+ let inner = self.inner.read().await;
inner.client.as_ref().map(|c| {
(
health_ttrpc::HealthClient::new(c.clone()),
@@ -72,7 +73,7 @@ impl KataAgent {
}
pub async fn get_agent_client(&self) -> Option<(agent_ttrpc::AgentServiceClient, i64, RawFd)> {
- let inner = self.inner.lock().await;
+ let inner = self.inner.read().await;
inner.client.as_ref().map(|c| {
(
agent_ttrpc::AgentServiceClient::new(c.clone()),
@@ -83,13 +84,13 @@ impl KataAgent {
}
pub(crate) async fn set_socket_address(&self, address: &str) -> Result<()> {
- let mut inner = self.inner.lock().await;
+ let mut inner = self.inner.write().await;
inner.socket_address = address.to_string();
Ok(())
}
pub(crate) async fn connect_agent_server(&self) -> Result<()> {
- let mut inner = self.inner.lock().await;
+ let mut inner = self.inner.write().await;
let config = sock::ConnectConfig::new(
inner.config.dial_timeout_ms as u64,
@@ -107,7 +108,7 @@ impl KataAgent {
}
pub(crate) async fn start_log_forwarder(&self) -> Result<()> {
- let mut inner = self.inner.lock().await;
+ let mut inner = self.inner.write().await;
let config = sock::ConnectConfig::new(
inner.config.dial_timeout_ms as u64,
inner.config.reconnect_timeout_ms as u64,
@@ -123,12 +124,21 @@ impl KataAgent {
}
pub(crate) async fn stop_log_forwarder(&self) {
- let mut inner = self.inner.lock().await;
+ let mut inner = self.inner.write().await;
inner.log_forwarder.stop();
}
+ pub(crate) async fn agent_sock(&self) -> Result<String> {
+ let inner = self.inner.read().await;
+ Ok(format!(
+ "{}:{}",
+ inner.socket_address.clone(),
+ inner.config.server_port
+ ))
+ }
+
pub(crate) async fn agent_config(&self) -> AgentConfig {
- let inner = self.inner.lock().await;
+ let inner = self.inner.read().await;
inner.config.clone()
}
}
diff --git a/src/runtime-rs/crates/agent/src/kata/trans.rs b/src/runtime-rs/crates/agent/src/kata/trans.rs
index e7fdaa944..4ac0c45ec 100644
--- a/src/runtime-rs/crates/agent/src/kata/trans.rs
+++ b/src/runtime-rs/crates/agent/src/kata/trans.rs
@@ -16,14 +16,15 @@ use crate::{
ARPNeighbor, ARPNeighbors, AddArpNeighborRequest, AgentDetails, BlkioStats,
BlkioStatsEntry, CgroupStats, CheckRequest, CloseStdinRequest, ContainerID,
CopyFileRequest, CpuStats, CpuUsage, CreateContainerRequest, CreateSandboxRequest, Device,
- Empty, ExecProcessRequest, FSGroup, FSGroupChangePolicy, GuestDetailsResponse,
- HealthCheckResponse, HugetlbStats, IPAddress, IPFamily, Interface, Interfaces,
- KernelModule, MemHotplugByProbeRequest, MemoryData, MemoryStats, NetworkStats,
- OnlineCPUMemRequest, PidsStats, ReadStreamRequest, ReadStreamResponse,
- RemoveContainerRequest, ReseedRandomDevRequest, Route, Routes, SetGuestDateTimeRequest,
- SignalProcessRequest, StatsContainerResponse, Storage, StringUser, ThrottlingData,
- TtyWinResizeRequest, UpdateContainerRequest, UpdateInterfaceRequest, UpdateRoutesRequest,
- VersionCheckResponse, WaitProcessRequest, WriteStreamRequest,
+ Empty, ExecProcessRequest, FSGroup, FSGroupChangePolicy, GetIPTablesRequest,
+ GetIPTablesResponse, GuestDetailsResponse, HealthCheckResponse, HugetlbStats, IPAddress,
+ IPFamily, Interface, Interfaces, KernelModule, MemHotplugByProbeRequest, MemoryData,
+ MemoryStats, NetworkStats, OnlineCPUMemRequest, PidsStats, ReadStreamRequest,
+ ReadStreamResponse, RemoveContainerRequest, ReseedRandomDevRequest, Route, Routes,
+ SetGuestDateTimeRequest, SetIPTablesRequest, SetIPTablesResponse, SignalProcessRequest,
+ StatsContainerResponse, Storage, StringUser, ThrottlingData, TtyWinResizeRequest,
+ UpdateContainerRequest, UpdateInterfaceRequest, UpdateRoutesRequest, VersionCheckResponse,
+ WaitProcessRequest, WriteStreamRequest,
},
OomEventResponse, WaitProcessResponse, WriteStreamResponse,
};
@@ -388,6 +389,41 @@ impl From<agent::WriteStreamResponse> for WriteStreamResponse {
}
}
+impl From<GetIPTablesRequest> for agent::GetIPTablesRequest {
+ fn from(from: GetIPTablesRequest) -> Self {
+ Self {
+ is_ipv6: from.is_ipv6,
+ ..Default::default()
+ }
+ }
+}
+
+impl From<agent::GetIPTablesResponse> for GetIPTablesResponse {
+ fn from(from: agent::GetIPTablesResponse) -> Self {
+ Self {
+ data: from.get_data().to_vec(),
+ }
+ }
+}
+
+impl From<SetIPTablesRequest> for agent::SetIPTablesRequest {
+ fn from(from: SetIPTablesRequest) -> Self {
+ Self {
+ is_ipv6: from.is_ipv6,
+ data: from.data,
+ ..Default::default()
+ }
+ }
+}
+
+impl From<agent::SetIPTablesResponse> for SetIPTablesResponse {
+ fn from(from: agent::SetIPTablesResponse) -> Self {
+ Self {
+ data: from.get_data().to_vec(),
+ }
+ }
+}
+
impl From<ExecProcessRequest> for agent::ExecProcessRequest {
fn from(from: ExecProcessRequest) -> Self {
Self {
diff --git a/src/runtime-rs/crates/agent/src/lib.rs b/src/runtime-rs/crates/agent/src/lib.rs
index 2fc1b1e28..a3d1da72a 100644
--- a/src/runtime-rs/crates/agent/src/lib.rs
+++ b/src/runtime-rs/crates/agent/src/lib.rs
@@ -16,11 +16,12 @@ pub mod types;
pub use types::{
ARPNeighbor, ARPNeighbors, AddArpNeighborRequest, BlkioStatsEntry, CheckRequest,
CloseStdinRequest, ContainerID, ContainerProcessID, CopyFileRequest, CreateContainerRequest,
- CreateSandboxRequest, Empty, ExecProcessRequest, GetGuestDetailsRequest, GuestDetailsResponse,
- HealthCheckResponse, IPAddress, IPFamily, Interface, Interfaces, ListProcessesRequest,
- MemHotplugByProbeRequest, OnlineCPUMemRequest, OomEventResponse, ReadStreamRequest,
- ReadStreamResponse, RemoveContainerRequest, ReseedRandomDevRequest, Route, Routes,
- SetGuestDateTimeRequest, SignalProcessRequest, StatsContainerResponse, Storage,
+ CreateSandboxRequest, Empty, ExecProcessRequest, GetGuestDetailsRequest, GetIPTablesRequest,
+ GetIPTablesResponse, GuestDetailsResponse, HealthCheckResponse, IPAddress, IPFamily, Interface,
+ Interfaces, ListProcessesRequest, MemHotplugByProbeRequest, OnlineCPUMemRequest,
+ OomEventResponse, ReadStreamRequest, ReadStreamResponse, RemoveContainerRequest,
+ ReseedRandomDevRequest, ResizeVolumeRequest, Route, Routes, SetGuestDateTimeRequest,
+ SetIPTablesRequest, SetIPTablesResponse, SignalProcessRequest, StatsContainerResponse, Storage,
TtyWinResizeRequest, UpdateContainerRequest, UpdateInterfaceRequest, UpdateRoutesRequest,
VersionCheckResponse, WaitProcessRequest, WaitProcessResponse, WriteStreamRequest,
WriteStreamResponse,
@@ -38,6 +39,7 @@ pub trait AgentManager: Send + Sync {
async fn start(&self, address: &str) -> Result<()>;
async fn stop(&self);
+ async fn agent_sock(&self) -> Result<String>;
async fn agent_config(&self) -> AgentConfig;
}
@@ -84,4 +86,6 @@ pub trait Agent: AgentManager + HealthService + Send + Sync {
// utils
async fn copy_file(&self, req: CopyFileRequest) -> Result<Empty>;
async fn get_oom_event(&self, req: Empty) -> Result<OomEventResponse>;
+ async fn get_ip_tables(&self, req: GetIPTablesRequest) -> Result<GetIPTablesResponse>;
+ async fn set_ip_tables(&self, req: SetIPTablesRequest) -> Result<SetIPTablesResponse>;
}
diff --git a/src/runtime-rs/crates/agent/src/sock/mod.rs b/src/runtime-rs/crates/agent/src/sock/mod.rs
index 371f62cd4..4e4d851a1 100644
--- a/src/runtime-rs/crates/agent/src/sock/mod.rs
+++ b/src/runtime-rs/crates/agent/src/sock/mod.rs
@@ -35,8 +35,8 @@ pub enum Stream {
// model, and mediates communication between AF_UNIX sockets (on the host end)
// and AF_VSOCK sockets (on the guest end).
Unix(UnixStream),
- // TODO: support vsock
// vsock://<cid>:<port>
+ Vsock(UnixStream),
}
impl Stream {
@@ -47,7 +47,7 @@ impl Stream {
) -> Poll<std::io::Result<()>> {
// Safety: `UnixStream::read` correctly handles reads into uninitialized memory
match self {
- Stream::Unix(stream) => Pin::new(stream).poll_read(cx, buf),
+ Stream::Unix(stream) | Stream::Vsock(stream) => Pin::new(stream).poll_read(cx, buf),
}
}
}
@@ -55,7 +55,7 @@ impl Stream {
impl IntoRawFd for Stream {
fn into_raw_fd(self) -> RawFd {
match self {
- Stream::Unix(stream) => match stream.into_std() {
+ Stream::Unix(stream) | Stream::Vsock(stream) => match stream.into_std() {
Ok(stream) => stream.into_raw_fd(),
Err(err) => {
error!(sl!(), "failed to into std unix stream {:?}", err);
diff --git a/src/runtime-rs/crates/agent/src/sock/vsock.rs b/src/runtime-rs/crates/agent/src/sock/vsock.rs
index 9b62bb976..52ec1eb0b 100644
--- a/src/runtime-rs/crates/agent/src/sock/vsock.rs
+++ b/src/runtime-rs/crates/agent/src/sock/vsock.rs
@@ -4,8 +4,15 @@
// SPDX-License-Identifier: Apache-2.0
//
-use anyhow::Result;
+use std::{
+ os::unix::prelude::{AsRawFd, FromRawFd},
+ time::Duration,
+};
+
+use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
+use nix::sys::socket::{connect, socket, AddressFamily, SockFlag, SockType, VsockAddr};
+use tokio::net::UnixStream;
use super::{ConnectConfig, Sock, Stream};
@@ -26,7 +33,50 @@ impl Vsock {
#[async_trait]
impl Sock for Vsock {
- async fn connect(&self, _config: &ConnectConfig) -> Result<Stream> {
- todo!()
+ async fn connect(&self, config: &ConnectConfig) -> Result<Stream> {
+ let retry_times = config.reconnect_timeout_ms / config.dial_timeout_ms;
+ let sock_addr = VsockAddr::new(self.vsock_cid, self.port);
+ let connect_once = || {
+ // Create socket fd
+ let socket = socket(
+ AddressFamily::Vsock,
+ SockType::Stream,
+ SockFlag::empty(),
+ None,
+ )
+ .context("failed to create vsock socket")?;
+
+ // Wrap the socket fd in a UnixStream, so that it is closed when
+ // anything fails.
+ // We MUST NOT reuse a vsock socket which has failed a connection
+ // attempt before, since a ECONNRESET error marks the whole socket as
+ // broken and non-reusable.
+ let socket = unsafe { std::os::unix::net::UnixStream::from_raw_fd(socket) };
+
+ // Connect the socket to vsock server.
+ connect(socket.as_raw_fd(), &sock_addr)
+ .with_context(|| format!("failed to connect to {}", sock_addr))?;
+
+ // Finally, convert the std UnixSocket to tokio's UnixSocket.
+ UnixStream::from_std(socket).context("from_std")
+ };
+
+ for i in 0..retry_times {
+ match connect_once() {
+ Ok(stream) => {
+ info!(
+ sl!(),
+ "connect vsock success on {} current client fd {}",
+ i,
+ stream.as_raw_fd()
+ );
+ return Ok(Stream::Vsock(stream));
+ }
+ Err(_) => {
+ tokio::time::sleep(Duration::from_millis(config.dial_timeout_ms)).await;
+ }
+ }
+ }
+ Err(anyhow!("cannot connect to agent ttrpc server {:?}", config))
}
}
diff --git a/src/runtime-rs/crates/agent/src/types.rs b/src/runtime-rs/crates/agent/src/types.rs
index eb5422e16..b8e79589a 100644
--- a/src/runtime-rs/crates/agent/src/types.rs
+++ b/src/runtime-rs/crates/agent/src/types.rs
@@ -7,7 +7,7 @@
use anyhow::{anyhow, Result};
use std::convert::TryFrom;
-use serde::Deserialize;
+use serde::{Deserialize, Serialize};
#[derive(PartialEq, Clone, Default)]
pub struct Empty {}
@@ -205,6 +205,27 @@ pub struct UpdateContainerRequest {
pub mounts: Vec<oci::Mount>,
}
+#[derive(PartialEq, Clone, Default, Debug)]
+pub struct GetIPTablesRequest {
+ pub is_ipv6: bool,
+}
+
+#[derive(PartialEq, Clone, Default, Debug)]
+pub struct GetIPTablesResponse {
+ pub data: Vec<u8>,
+}
+
+#[derive(PartialEq, Clone, Default, Debug)]
+pub struct SetIPTablesRequest {
+ pub is_ipv6: bool,
+ pub data: Vec<u8>,
+}
+
+#[derive(PartialEq, Clone, Default, Debug)]
+pub struct SetIPTablesResponse {
+ pub data: Vec<u8>,
+}
+
#[derive(PartialEq, Clone, Default)]
pub struct WriteStreamRequest {
pub process_id: ContainerProcessID,
@@ -540,6 +561,14 @@ pub struct OomEventResponse {
pub container_id: String,
}
+// ResizeVolumeRequest is also the common struct for serialization and deserialization with json
+// between shim-client HTTP calls to the shim-mgmt-server
+#[derive(Serialize, Deserialize, PartialEq, Clone, Default, Debug)]
+pub struct ResizeVolumeRequest {
+ pub volume_guest_path: String,
+ pub size: u64,
+}
+
#[cfg(test)]
mod test {
use std::convert::TryFrom;
diff --git a/src/runtime-rs/crates/hypervisor/Cargo.toml b/src/runtime-rs/crates/hypervisor/Cargo.toml
index 56a27ecb4..9c70f3914 100644
--- a/src/runtime-rs/crates/hypervisor/Cargo.toml
+++ b/src/runtime-rs/crates/hypervisor/Cargo.toml
@@ -10,7 +10,7 @@ license = "Apache-2.0"
[dependencies]
anyhow = "^1.0"
async-trait = "0.1.48"
-dbs-utils = "0.1.0"
+dbs-utils = "0.2.0"
go-flag = "0.1.0"
libc = ">=0.2.39"
nix = "0.24.2"
@@ -22,12 +22,14 @@ slog = "2.5.2"
slog-scope = "4.4.0"
thiserror = "1.0"
tokio = { version = "1.8.0", features = ["sync"] }
-vmm-sys-util = "0.9.0"
+vmm-sys-util = "0.11.0"
+rand = "0.8.4"
kata-sys-util = { path = "../../../libs/kata-sys-util" }
kata-types = { path = "../../../libs/kata-types" }
logging = { path = "../../../libs/logging" }
+shim-interface = { path = "../../../libs/shim-interface" }
-dragonball = { path = "../../../dragonball", features = ["atomic-guest-memory", "virtio-vsock", "hotplug", "virtio-blk", "virtio-net", "virtio-fs"] }
+dragonball = { path = "../../../dragonball", features = ["atomic-guest-memory", "virtio-vsock", "hotplug", "virtio-blk", "virtio-net", "virtio-fs","dbs-upcall"] }
[features]
diff --git a/src/runtime-rs/crates/hypervisor/README.md b/src/runtime-rs/crates/hypervisor/README.md
new file mode 100644
index 000000000..8d43baa70
--- /dev/null
+++ b/src/runtime-rs/crates/hypervisor/README.md
@@ -0,0 +1,94 @@
+# Multi-vmm support for runtime-rs
+Some key points for supporting multi-vmm in rust runtime.
+## 1. Hypervisor Config
+
+The diagram below gives an overview for the hypervisor config
+
+![hypervisor config](../../docs/images/hypervisor-config.svg)
+
+VMM's config info will be loaded when initialize the runtime instance, there are some important functions need to be focused on.
+### `VirtContainer::init()`
+
+This function initialize the runtime handler. It will register the plugins into the HYPERVISOR_PLUGINS. Different plugins are needed for different hypervisors.
+```rust
+#[async_trait]
+impl RuntimeHandler for VirtContainer {
+ fn init() -> Result<()> {
+ // register
+ let dragonball_config = Arc::new(DragonballConfig::new());
+ register_hypervisor_plugin("dragonball", dragonball_config);
+ Ok(())
+ }
+}
+```
+
+[This is the plugin method for QEMU. Other VMM plugin methods haven't support currently.](../../../libs/kata-types/src/config/hypervisor/qemu.rs)
+QEMU plugin defines the methods to adjust and validate the hypervisor config file, those methods could be modified if it is needed.
+
+After that, when loading the TOML config, the plugins will be called to adjust and validate the config file.
+```rust
+async fn try_init(&mut self, spec: &oci::Spec) -> Result<()> {、
+ ...
+ let config = load_config(spec).context("load config")?;
+ ...
+}
+```
+
+### new_instance
+
+This function will create a runtime_instance which include the operations for container and sandbox. At the same time, a hypervisor instance will be created. QEMU instance will be created here as well, and set the hypervisor config file
+```rust
+async fn new_hypervisor(toml_config: &TomlConfig) -> Result<Arc<dyn Hypervisor>> {
+ let hypervisor_name = &toml_config.runtime.hypervisor_name;
+ let hypervisor_config = toml_config
+ .hypervisor
+ .get(hypervisor_name)
+ .ok_or_else(|| anyhow!("failed to get hypervisor for {}", &hypervisor_name))
+ .context("get hypervisor")?;
+
+ // TODO: support other hypervisor
+ match hypervisor_name.as_str() {
+ HYPERVISOR_DRAGONBALL => {
+ let mut hypervisor = Dragonball::new();
+ hypervisor
+ .set_hypervisor_config(hypervisor_config.clone())
+ .await;
+ Ok(Arc::new(hypervisor))
+ }
+ _ => Err(anyhow!("Unsupported hypervisor {}", &hypervisor_name)),
+ }
+}
+```
+
+## 2. Hypervisor Trait
+
+[To support multi-vmm, the hypervisor trait need to be implemented.](./src/lib.rs)
+```rust
+pub trait Hypervisor: Send + Sync {
+ // vm manager
+ async fn prepare_vm(&self, id: &str, netns: Option<String>) -> Result<()>;
+ async fn start_vm(&self, timeout: i32) -> Result<()>;
+ async fn stop_vm(&self) -> Result<()>;
+ async fn pause_vm(&self) -> Result<()>;
+ async fn save_vm(&self) -> Result<()>;
+ async fn resume_vm(&self) -> Result<()>;
+
+ // device manager
+ async fn add_device(&self, device: device::Device) -> Result<()>;
+ async fn remove_device(&self, device: device::Device) -> Result<()>;
+
+ // utils
+ async fn get_agent_socket(&self) -> Result<String>;
+ async fn disconnect(&self);
+ async fn hypervisor_config(&self) -> HypervisorConfig;
+ async fn get_thread_ids(&self) -> Result<VcpuThreadIds>;
+ async fn get_pids(&self) -> Result<Vec<u32>>;
+ async fn cleanup(&self) -> Result<()>;
+ async fn check(&self) -> Result<()>;
+ async fn get_jailer_root(&self) -> Result<String>;
+ async fn save_state(&self) -> Result<HypervisorState>;
+ }
+```
+In current design, VM will be started in the following steps.
+
+![vmm start](../../docs/images/vm-start.svg)
diff --git a/src/runtime-rs/crates/hypervisor/src/device/mod.rs b/src/runtime-rs/crates/hypervisor/src/device/mod.rs
index 49215e0d1..bbd14fb1d 100644
--- a/src/runtime-rs/crates/hypervisor/src/device/mod.rs
+++ b/src/runtime-rs/crates/hypervisor/src/device/mod.rs
@@ -15,7 +15,7 @@ pub use vfio::{bind_device_to_host, bind_device_to_vfio, VfioBusMode, VfioConfig
mod share_fs_mount;
pub use share_fs_mount::{ShareFsMountConfig, ShareFsMountType, ShareFsOperation};
mod vsock;
-pub use vsock::VsockConfig;
+pub use vsock::{HybridVsockConfig, VsockConfig};
use std::fmt;
@@ -27,6 +27,7 @@ pub enum Device {
Vfio(VfioConfig),
ShareFsMount(ShareFsMountConfig),
Vsock(VsockConfig),
+ HybridVsock(HybridVsockConfig),
}
impl fmt::Display for Device {
diff --git a/src/runtime-rs/crates/hypervisor/src/device/vfio.rs b/src/runtime-rs/crates/hypervisor/src/device/vfio.rs
index fcbaeb19f..608091379 100644
--- a/src/runtime-rs/crates/hypervisor/src/device/vfio.rs
+++ b/src/runtime-rs/crates/hypervisor/src/device/vfio.rs
@@ -21,6 +21,7 @@ fn override_driver(bdf: &str, driver: &str) -> Result<()> {
const SYS_PCI_DEVICES_PATH: &str = "/sys/bus/pci/devices";
const PCI_DRIVER_PROBE: &str = "/sys/bus/pci/drivers_probe";
const VFIO_NEW_ID_PATH: &str = "/sys/bus/pci/drivers/vfio-pci/new_id";
+const VFIO_UNBIND_PATH: &str = "/sys/bus/pci/drivers/vfio-pci/unbind";
pub const VFIO_PCI: &str = "vfio-pci";
@@ -132,11 +133,10 @@ pub fn bind_device_to_host(bdf: &str, host_driver: &str, _vendor_device_id: &str
override_driver(bdf, host_driver).context("override driver")?;
- let unbind_path = "/sys/bus/pci/drivers/vfio-pci/unbind";
-
// echo bdf > /sys/bus/pci/drivers/vfio-pci/unbind"
- std::fs::write(unbind_path, bdf).with_context(|| format!("echo {}> {}", bdf, unbind_path))?;
- info!(sl!(), "echo {} > {}", bdf, unbind_path);
+ std::fs::write(VFIO_UNBIND_PATH, bdf)
+ .with_context(|| format!("echo {}> {}", bdf, VFIO_UNBIND_PATH))?;
+ info!(sl!(), "echo {} > {}", bdf, VFIO_UNBIND_PATH);
// echo bdf > /sys/bus/pci/drivers_probe
std::fs::write(PCI_DRIVER_PROBE, bdf)
diff --git a/src/runtime-rs/crates/hypervisor/src/device/vsock.rs b/src/runtime-rs/crates/hypervisor/src/device/vsock.rs
index 3a5b7c8b3..cd0553adf 100644
--- a/src/runtime-rs/crates/hypervisor/src/device/vsock.rs
+++ b/src/runtime-rs/crates/hypervisor/src/device/vsock.rs
@@ -4,8 +4,13 @@
// SPDX-License-Identifier: Apache-2.0
//
+use anyhow::{Context, Result};
+use rand::Rng;
+use std::os::unix::prelude::AsRawFd;
+use tokio::fs::{File, OpenOptions};
+
#[derive(Debug)]
-pub struct VsockConfig {
+pub struct HybridVsockConfig {
/// Unique identifier of the device
pub id: String,
@@ -15,3 +20,76 @@ pub struct VsockConfig {
/// unix domain socket path
pub uds_path: String,
}
+
+#[derive(Debug)]
+pub struct VsockConfig {
+ /// Unique identifier of the device
+ pub id: String,
+
+ /// A 32-bit Context Identifier (CID) used to identify the guest.
+ pub guest_cid: u32,
+
+ /// Vhost vsock fd. Hold to ensure CID is not used by other VM.
+ pub vhost_fd: File,
+}
+
+const VHOST_VSOCK_DEVICE: &str = "/dev/vhost-vsock";
+
+// From <linux/vhost.h>
+// Generate a wrapper function for VHOST_VSOCK_SET_GUEST_CID ioctl.
+// It set guest CID for vsock fd, and return error if CID is already
+// in use.
+const VHOST_VIRTIO_IOCTL: u8 = 0xAF;
+const VHOST_VSOCK_SET_GUEST_CID: u8 = 0x60;
+nix::ioctl_write_ptr!(
+ vhost_vsock_set_guest_cid,
+ VHOST_VIRTIO_IOCTL,
+ VHOST_VSOCK_SET_GUEST_CID,
+ u64
+);
+
+const CID_RETRY_COUNT: u32 = 50;
+
+impl VsockConfig {
+ pub async fn new(id: String) -> Result<Self> {
+ let vhost_fd = OpenOptions::new()
+ .read(true)
+ .write(true)
+ .open(VHOST_VSOCK_DEVICE)
+ .await
+ .context(format!(
+ "failed to open {}, try to run modprobe vhost_vsock.",
+ VHOST_VSOCK_DEVICE
+ ))?;
+ let mut rng = rand::thread_rng();
+
+ // Try 50 times to find a context ID that is not in use.
+ for _ in 0..CID_RETRY_COUNT {
+ // First usable CID above VMADDR_CID_HOST (see vsock(7))
+ let first_usable_cid = 3;
+ let rand_cid = rng.gen_range(first_usable_cid..=(u32::MAX));
+ let guest_cid =
+ unsafe { vhost_vsock_set_guest_cid(vhost_fd.as_raw_fd(), &(rand_cid as u64)) };
+ match guest_cid {
+ Ok(_) => {
+ return Ok(VsockConfig {
+ id,
+ guest_cid: rand_cid,
+ vhost_fd,
+ });
+ }
+ Err(nix::Error::EADDRINUSE) => {
+ // The CID is already in use. Try another one.
+ }
+ Err(err) => {
+ return Err(err).context("failed to set guest CID");
+ }
+ }
+ }
+
+ anyhow::bail!(
+ "failed to find a free vsock context ID after {} attempts",
+ CID_RETRY_COUNT
+ );
+ }
+}
diff --git a/src/runtime-rs/crates/hypervisor/src/dragonball/inner.rs b/src/runtime-rs/crates/hypervisor/src/dragonball/inner.rs
index 786088633..a74fe28f8 100644
--- a/src/runtime-rs/crates/hypervisor/src/dragonball/inner.rs
+++ b/src/runtime-rs/crates/hypervisor/src/dragonball/inner.rs
@@ -7,7 +7,7 @@
use super::vmm_instance::VmmInstance;
use crate::{
device::Device, hypervisor_persist::HypervisorState, kernel_param::KernelParams, VmmState,
- HYPERVISOR_DRAGONBALL, VM_ROOTFS_DRIVER_BLK,
+ DEV_HUGEPAGES, HUGETLBFS, HYPERVISOR_DRAGONBALL, SHMEM, VM_ROOTFS_DRIVER_BLK,
};
use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
@@ -16,8 +16,12 @@ use dragonball::{
vm::VmConfigInfo,
};
use kata_sys_util::mount;
-use kata_types::config::hypervisor::Hypervisor as HypervisorConfig;
-use persist::{sandbox_persist::Persist, KATA_PATH};
+use kata_types::{
+ capabilities::{Capabilities, CapabilityBits},
+ config::hypervisor::Hypervisor as HypervisorConfig,
+};
+use persist::sandbox_persist::Persist;
+use shim_interface::KATA_PATH;
use std::{collections::HashSet, fs::create_dir_all, path::PathBuf};
const DRAGONBALL_KERNEL: &str = "vmlinux";
@@ -58,10 +62,19 @@ pub struct DragonballInner {
/// cached block device
pub(crate) cached_block_devices: HashSet<String>,
+
+ /// dragonball capabilities
+ pub(crate) capabilities: Capabilities,
}
impl DragonballInner {
pub fn new() -> DragonballInner {
+ let mut capabilities = Capabilities::new();
+ capabilities.set(
+ CapabilityBits::BlockDeviceSupport
+ | CapabilityBits::BlockDeviceHotplugSupport
+ | CapabilityBits::FsSharingSupport,
+ );
DragonballInner {
id: "".to_string(),
vm_path: "".to_string(),
@@ -74,6 +87,7 @@ impl DragonballInner {
vmm_instance: VmmInstance::new(""),
run_dir: "".to_string(),
cached_block_devices: Default::default(),
+ capabilities,
}
}
@@ -91,6 +105,7 @@ impl DragonballInner {
kernel_params.append(&mut KernelParams::from_string(
&self.config.boot_info.kernel_params,
));
+ info!(sl!(), "prepared kernel_params={:?}", kernel_params);
// set boot source
let kernel_path = self.config.boot_info.kernel.clone();
@@ -172,11 +187,18 @@ impl DragonballInner {
fn set_vm_base_config(&mut self) -> Result<()> {
let serial_path = [&self.run_dir, "console.sock"].join("/");
+ let (mem_type, mem_file_path) = if self.config.memory_info.enable_hugepages {
+ (String::from(HUGETLBFS), String::from(DEV_HUGEPAGES))
+ } else {
+ (String::from(SHMEM), String::from(""))
+ };
let vm_config = VmConfigInfo {
serial_path: Some(serial_path),
mem_size_mib: self.config.memory_info.default_memory as usize,
vcpu_count: self.config.cpu_info.default_vcpus as u8,
max_vcpu_count: self.config.cpu_info.default_maxvcpus as u8,
+ mem_type,
+ mem_file_path,
..Default::default()
};
info!(sl!(), "vm config: {:?}", vm_config);
@@ -350,6 +372,7 @@ impl Persist for DragonballInner {
run_dir: hypervisor_state.run_dir,
pending_devices: vec![],
cached_block_devices: hypervisor_state.cached_block_devices,
+ capabilities: Capabilities::new(),
})
}
}
diff --git a/src/runtime-rs/crates/hypervisor/src/dragonball/inner_device.rs b/src/runtime-rs/crates/hypervisor/src/dragonball/inner_device.rs
index d47cac569..d6f7baecb 100644
--- a/src/runtime-rs/crates/hypervisor/src/dragonball/inner_device.rs
+++ b/src/runtime-rs/crates/hypervisor/src/dragonball/inner_device.rs
@@ -15,8 +15,8 @@ use dragonball::api::v1::{
use super::DragonballInner;
use crate::{
- device::Device, NetworkConfig, ShareFsDeviceConfig, ShareFsMountConfig, ShareFsMountType,
- ShareFsOperation, VmmState, VsockConfig,
+ device::Device, HybridVsockConfig, NetworkConfig, ShareFsDeviceConfig, ShareFsMountConfig,
+ ShareFsMountType, ShareFsOperation, VmmState,
};
const MB_TO_B: u32 = 1024 * 1024;
@@ -56,13 +56,16 @@ impl DragonballInner {
config.no_drop,
)
.context("add block device"),
- Device::Vsock(config) => self.add_vsock(&config).context("add vsock"),
+ Device::HybridVsock(config) => self.add_hvsock(&config).context("add vsock"),
Device::ShareFsDevice(config) => self
.add_share_fs_device(&config)
.context("add share fs device"),
Device::ShareFsMount(config) => self
.add_share_fs_mount(&config)
.context("add share fs mount"),
+ Device::Vsock(_) => {
+ todo!()
+ }
}
}
@@ -139,7 +142,7 @@ impl DragonballInner {
.context("insert network device")
}
- fn add_vsock(&mut self, config: &VsockConfig) -> Result<()> {
+ fn add_hvsock(&mut self, config: &HybridVsockConfig) -> Result<()> {
let vsock_cfg = VsockDeviceConfigInfo {
id: String::from("root"),
guest_cid: config.guest_cid,
@@ -223,6 +226,7 @@ impl DragonballInner {
},
cache_size: (self.config.shared_fs.virtio_fs_cache_size as u64)
.saturating_mul(MB_TO_B as u64),
+ xattr: true,
..Default::default()
};
self.do_add_fs_device(&config.fs_type, &mut fs_cfg)
@@ -264,7 +268,7 @@ impl DragonballInner {
fstype: Some(fstype.to_string()),
source: Some(config.source.clone()),
mountpoint: config.mount_point.clone(),
- config: None,
+ config: config.config.clone(),
tag: config.tag.clone(),
prefetch_list_path: config.prefetch_list_path.clone(),
dax_threshold_size_kb: None,
diff --git a/src/runtime-rs/crates/hypervisor/src/dragonball/inner_hypervisor.rs b/src/runtime-rs/crates/hypervisor/src/dragonball/inner_hypervisor.rs
index 3b5bd02af..d4d75e6ef 100644
--- a/src/runtime-rs/crates/hypervisor/src/dragonball/inner_hypervisor.rs
+++ b/src/runtime-rs/crates/hypervisor/src/dragonball/inner_hypervisor.rs
@@ -9,11 +9,12 @@ use std::{
iter::FromIterator,
};
-use anyhow::{Context, Result};
+use anyhow::{Context, Ok, Result};
+use kata_types::capabilities::Capabilities;
use super::inner::DragonballInner;
use crate::{utils, VcpuThreadIds, VmmState};
-use persist::KATA_PATH;
+use shim_interface::KATA_PATH;
const DEFAULT_HYBRID_VSOCK_NAME: &str = "kata.hvsock";
fn get_vsock_path(root: &str) -> String {
@@ -31,7 +32,7 @@ impl DragonballInner {
// prepare vsock
let uds_path = [&self.jailer_root, DEFAULT_HYBRID_VSOCK_NAME].join("/");
- let d = crate::device::Device::Vsock(crate::device::VsockConfig {
+ let d = crate::device::Device::HybridVsock(crate::device::HybridVsockConfig {
id: format!("vsock-{}", &self.id),
guest_cid: 3,
uds_path,
@@ -97,7 +98,7 @@ impl DragonballInner {
};
for tid in self.vmm_instance.get_vcpu_tids() {
- vcpu_thread_ids.vcpus.insert(tid.0 as u32, tid.1 as u32);
+ vcpu_thread_ids.vcpus.insert(tid.0 as u32, tid.1);
}
info!(sl!(), "get thread ids {:?}", vcpu_thread_ids);
Ok(vcpu_thread_ids)
@@ -133,4 +134,8 @@ impl DragonballInner {
pub(crate) async fn get_jailer_root(&self) -> Result<String> {
Ok(self.jailer_root.clone())
}
+
+ pub(crate) async fn capabilities(&self) -> Result<Capabilities> {
+ Ok(self.capabilities.clone())
+ }
}
diff --git a/src/runtime-rs/crates/hypervisor/src/dragonball/mod.rs b/src/runtime-rs/crates/hypervisor/src/dragonball/mod.rs
index aaadd068a..37ffd69b9 100644
--- a/src/runtime-rs/crates/hypervisor/src/dragonball/mod.rs
+++ b/src/runtime-rs/crates/hypervisor/src/dragonball/mod.rs
@@ -16,6 +16,7 @@ use std::sync::Arc;
use anyhow::{Context, Result};
use async_trait::async_trait;
+use kata_types::capabilities::Capabilities;
use kata_types::config::hypervisor::Hypervisor as HypervisorConfig;
use tokio::sync::RwLock;
@@ -131,6 +132,11 @@ impl Hypervisor for Dragonball {
async fn save_state(&self) -> Result<HypervisorState> {
self.save().await
}
+
+ async fn capabilities(&self) -> Result<Capabilities> {
+ let inner = self.inner.read().await;
+ inner.capabilities().await
+ }
}
#[async_trait]
diff --git a/src/runtime-rs/crates/hypervisor/src/dragonball/vmm_instance.rs b/src/runtime-rs/crates/hypervisor/src/dragonball/vmm_instance.rs
index 70172c73a..00829ad4c 100644
--- a/src/runtime-rs/crates/hypervisor/src/dragonball/vmm_instance.rs
+++ b/src/runtime-rs/crates/hypervisor/src/dragonball/vmm_instance.rs
@@ -327,9 +327,9 @@ impl VmmInstance {
}
}
}
- return Err(anyhow::anyhow!(
+ Err(anyhow::anyhow!(
"After {} attempts, it still doesn't work.",
REQUEST_RETRY
- ));
+ ))
}
}
diff --git a/src/runtime-rs/crates/hypervisor/src/kernel_param.rs b/src/runtime-rs/crates/hypervisor/src/kernel_param.rs
index d8b20b597..39bef9a64 100644
--- a/src/runtime-rs/crates/hypervisor/src/kernel_param.rs
+++ b/src/runtime-rs/crates/hypervisor/src/kernel_param.rs
@@ -7,6 +7,7 @@
use anyhow::{anyhow, Result};
use crate::{VM_ROOTFS_DRIVER_BLK, VM_ROOTFS_DRIVER_PMEM};
+use kata_types::config::LOG_VPORT_OPTION;
// Port where the agent will send the logs. Logs are sent through the vsock in cases
// where the hypervisor has no console.sock, i.e dragonball
@@ -28,6 +29,18 @@ impl Param {
value: value.to_owned(),
}
}
+
+ pub fn to_string(&self) -> Result<String> {
+ if self.key.is_empty() && self.value.is_empty() {
+ Err(anyhow!("Empty key and value"))
+ } else if self.key.is_empty() {
+ Err(anyhow!("Empty key"))
+ } else if self.value.is_empty() {
+ Ok(self.key.to_string())
+ } else {
+ Ok(format!("{}{}{}", self.key, KERNEL_KV_DELIMITER, self.value))
+ }
+ }
}
#[derive(Debug, PartialEq)]
@@ -48,7 +61,7 @@ impl KernelParams {
];
if debug {
- params.push(Param::new("agent.log_vport", VSOCK_LOGS_PORT));
+ params.push(Param::new(LOG_VPORT_OPTION, VSOCK_LOGS_PORT));
}
Self { params }
@@ -129,18 +142,7 @@ impl KernelParams {
let mut parameters: Vec<String> = Vec::new();
for param in &self.params {
- if param.key.is_empty() && param.value.is_empty() {
- return Err(anyhow!("Empty key and value"));
- } else if param.key.is_empty() {
- return Err(anyhow!("Empty key"));
- } else if param.value.is_empty() {
- parameters.push(param.key.to_string());
- } else {
- parameters.push(format!(
- "{}{}{}",
- param.key, KERNEL_KV_DELIMITER, param.value
- ));
- }
+ parameters.push(param.to_string()?);
}
Ok(parameters.join(KERNEL_PARAM_DELIMITER))
@@ -153,6 +155,20 @@ mod tests {
use super::*;
+ #[test]
+ fn test_params() {
+ let param1 = Param::new("", "");
+ let param2 = Param::new("", "foo");
+ let param3 = Param::new("foo", "");
+
+ assert!(param1.to_string().is_err());
+ assert!(param2.to_string().is_err());
+ assert_eq!(param3.to_string().unwrap(), String::from("foo"));
+
+ let param4 = Param::new("foo", "bar");
+ assert_eq!(param4.to_string().unwrap(), String::from("foo=bar"));
+ }
+
#[test]
fn test_kernel_params() -> Result<()> {
let expect_params_string = "k1=v1 k2=v2 k3=v3".to_string();
diff --git a/src/runtime-rs/crates/hypervisor/src/lib.rs b/src/runtime-rs/crates/hypervisor/src/lib.rs
index b9296d81e..2c3e8016f 100644
--- a/src/runtime-rs/crates/hypervisor/src/lib.rs
+++ b/src/runtime-rs/crates/hypervisor/src/lib.rs
@@ -14,6 +14,7 @@ pub mod hypervisor_persist;
pub use device::*;
pub mod dragonball;
mod kernel_param;
+pub mod qemu;
pub use kernel_param::Param;
mod utils;
use std::collections::HashMap;
@@ -21,13 +22,22 @@ use std::collections::HashMap;
use anyhow::Result;
use async_trait::async_trait;
use hypervisor_persist::HypervisorState;
+use kata_types::capabilities::Capabilities;
use kata_types::config::hypervisor::Hypervisor as HypervisorConfig;
-
// Config which driver to use as vm root dev
const VM_ROOTFS_DRIVER_BLK: &str = "virtio-blk";
const VM_ROOTFS_DRIVER_PMEM: &str = "virtio-pmem";
+// before using hugepages for VM, we need to mount hugetlbfs
+// /dev/hugepages will be the mount point
+// mkdir -p /dev/hugepages
+// mount -t hugetlbfs none /dev/hugepages
+const DEV_HUGEPAGES: &str = "/dev/hugepages";
+pub const HUGETLBFS: &str = "hugetlbfs";
+const SHMEM: &str = "shmem";
pub const HYPERVISOR_DRAGONBALL: &str = "dragonball";
+pub const HYPERVISOR_QEMU: &str = "qemu";
+
#[derive(PartialEq)]
pub(crate) enum VmmState {
NotReady,
@@ -65,4 +75,5 @@ pub trait Hypervisor: Send + Sync {
async fn check(&self) -> Result<()>;
async fn get_jailer_root(&self) -> Result<String>;
async fn save_state(&self) -> Result<HypervisorState>;
+ async fn capabilities(&self) -> Result<Capabilities>;
}
diff --git a/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs b/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs
new file mode 100644
index 000000000..d985ba724
--- /dev/null
+++ b/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs
@@ -0,0 +1,142 @@
+// Copyright (c) 2022 Red Hat
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+use anyhow::Result;
+
+use crate::{HypervisorConfig, VcpuThreadIds};
+use kata_types::capabilities::{Capabilities, CapabilityBits};
+
+const VSOCK_SCHEME: &str = "vsock";
+const VSOCK_AGENT_CID: u32 = 3;
+const VSOCK_AGENT_PORT: u32 = 1024;
+
+unsafe impl Send for QemuInner {}
+unsafe impl Sync for QemuInner {}
+
+pub struct QemuInner {
+ config: HypervisorConfig,
+}
+
+impl QemuInner {
+ pub fn new() -> QemuInner {
+ QemuInner {
+ config: Default::default(),
+ }
+ }
+
+ pub(crate) async fn prepare_vm(&mut self, _id: &str, _netns: Option<String>) -> Result<()> {
+ info!(sl!(), "Preparing QEMU VM");
+ Ok(())
+ }
+
+ pub(crate) async fn start_vm(&mut self, _timeout: i32) -> Result<()> {
+ info!(sl!(), "Starting QEMU VM");
+
+ let mut command = std::process::Command::new(&self.config.path);
+
+ command
+ .arg("-kernel")
+ .arg(&self.config.boot_info.kernel)
+ .arg("-m")
+ .arg(format!("{}M", &self.config.memory_info.default_memory))
+ .arg("-initrd")
+ .arg(&self.config.boot_info.initrd)
+ .arg("-vga")
+ .arg("none")
+ .arg("-nodefaults")
+ .arg("-nographic");
+
+ command.spawn()?;
+
+ Ok(())
+ }
+
+ pub(crate) fn stop_vm(&mut self) -> Result<()> {
+ info!(sl!(), "Stopping QEMU VM");
+ todo!()
+ }
+
+ pub(crate) fn pause_vm(&self) -> Result<()> {
+ info!(sl!(), "Pausing QEMU VM");
+ todo!()
+ }
+
+ pub(crate) fn resume_vm(&self) -> Result<()> {
+ info!(sl!(), "Resuming QEMU VM");
+ todo!()
+ }
+
+ pub(crate) async fn save_vm(&self) -> Result<()> {
+ todo!()
+ }
+
+ /// TODO: using a single hardcoded CID is clearly not adequate in the long
+ /// run. Use the recently added VsockConfig infrastructure to fix this.
+ pub(crate) async fn get_agent_socket(&self) -> Result<String> {
+ info!(sl!(), "QemuInner::get_agent_socket()");
+ Ok(format!(
+ "{}://{}:{}",
+ VSOCK_SCHEME, VSOCK_AGENT_CID, VSOCK_AGENT_PORT
+ ))
+ }
+
+ pub(crate) async fn disconnect(&mut self) {
+ info!(sl!(), "QemuInner::disconnect()");
+ todo!()
+ }
+
+ pub(crate) async fn get_thread_ids(&self) -> Result<VcpuThreadIds> {
+ info!(sl!(), "QemuInner::get_thread_ids()");
+ todo!()
+ }
+
+ pub(crate) async fn cleanup(&self) -> Result<()> {
+ info!(sl!(), "QemuInner::cleanup()");
+ todo!()
+ }
+
+ pub(crate) async fn get_pids(&self) -> Result<Vec<u32>> {
+ info!(sl!(), "QemuInner::get_pids()");
+ todo!()
+ }
+
+ pub(crate) async fn check(&self) -> Result<()> {
+ todo!()
+ }
+
+ pub(crate) async fn get_jailer_root(&self) -> Result<String> {
+ todo!()
+ }
+
+ pub(crate) async fn capabilities(&self) -> Result<Capabilities> {
+ let mut caps = Capabilities::default();
+ caps.set(CapabilityBits::FsSharingSupport);
+ Ok(caps)
+ }
+
+ pub fn set_hypervisor_config(&mut self, config: HypervisorConfig) {
+ self.config = config;
+ }
+
+ pub fn hypervisor_config(&self) -> HypervisorConfig {
+ info!(sl!(), "QemuInner::hypervisor_config()");
+ self.config.clone()
+ }
+}
+
+use crate::device::Device;
+
+// device manager part of Hypervisor
+impl QemuInner {
+ pub(crate) async fn add_device(&mut self, device: Device) -> Result<()> {
+ info!(sl!(), "QemuInner::add_device() {}", device);
+ todo!()
+ }
+
+ pub(crate) async fn remove_device(&mut self, device: Device) -> Result<()> {
+ info!(sl!(), "QemuInner::remove_device() {} ", device);
+ todo!()
+ }
+}
diff --git a/src/runtime-rs/crates/hypervisor/src/qemu/mod.rs b/src/runtime-rs/crates/hypervisor/src/qemu/mod.rs
new file mode 100644
index 000000000..6df386923
--- /dev/null
+++ b/src/runtime-rs/crates/hypervisor/src/qemu/mod.rs
@@ -0,0 +1,134 @@
+// Copyright (c) 2022 Red Hat
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+mod inner;
+
+use crate::device::Device;
+use crate::hypervisor_persist::HypervisorState;
+use crate::Hypervisor;
+use crate::{HypervisorConfig, VcpuThreadIds};
+use inner::QemuInner;
+use kata_types::capabilities::Capabilities;
+
+use anyhow::Result;
+use async_trait::async_trait;
+
+use std::sync::Arc;
+use tokio::sync::RwLock;
+
+pub struct Qemu {
+ inner: Arc<RwLock<QemuInner>>,
+}
+
+impl Default for Qemu {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl Qemu {
+ pub fn new() -> Self {
+ Self {
+ inner: Arc::new(RwLock::new(QemuInner::new())),
+ }
+ }
+
+ pub async fn set_hypervisor_config(&mut self, config: HypervisorConfig) {
+ let mut inner = self.inner.write().await;
+ inner.set_hypervisor_config(config)
+ }
+}
+
+#[async_trait]
+impl Hypervisor for Qemu {
+ async fn prepare_vm(&self, id: &str, netns: Option<String>) -> Result<()> {
+ let mut inner = self.inner.write().await;
+ inner.prepare_vm(id, netns).await
+ }
+
+ async fn start_vm(&self, timeout: i32) -> Result<()> {
+ let mut inner = self.inner.write().await;
+ inner.start_vm(timeout).await
+ }
+
+ async fn stop_vm(&self) -> Result<()> {
+ let mut inner = self.inner.write().await;
+ inner.stop_vm()
+ }
+
+ async fn pause_vm(&self) -> Result<()> {
+ let inner = self.inner.read().await;
+ inner.pause_vm()
+ }
+
+ async fn resume_vm(&self) -> Result<()> {
+ let inner = self.inner.read().await;
+ inner.resume_vm()
+ }
+
+ async fn save_vm(&self) -> Result<()> {
+ let inner = self.inner.read().await;
+ inner.save_vm().await
+ }
+
+ async fn add_device(&self, device: Device) -> Result<()> {
+ let mut inner = self.inner.write().await;
+ inner.add_device(device).await
+ }
+
+ async fn remove_device(&self, device: Device) -> Result<()> {
+ let mut inner = self.inner.write().await;
+ inner.remove_device(device).await
+ }
+
+ async fn get_agent_socket(&self) -> Result<String> {
+ let inner = self.inner.read().await;
+ inner.get_agent_socket().await
+ }
+
+ async fn disconnect(&self) {
+ let mut inner = self.inner.write().await;
+ inner.disconnect().await
+ }
+
+ async fn hypervisor_config(&self) -> HypervisorConfig {
+ let inner = self.inner.read().await;
+ inner.hypervisor_config()
+ }
+
+ async fn get_thread_ids(&self) -> Result<VcpuThreadIds> {
+ let inner = self.inner.read().await;
+ inner.get_thread_ids().await
+ }
+
+ async fn cleanup(&self) -> Result<()> {
+ let inner = self.inner.read().await;
+ inner.cleanup().await
+ }
+
+ async fn get_pids(&self) -> Result<Vec<u32>> {
+ let inner = self.inner.read().await;
+ inner.get_pids().await
+ }
+
+ async fn check(&self) -> Result<()> {
+ let inner = self.inner.read().await;
+ inner.check().await
+ }
+
+ async fn get_jailer_root(&self) -> Result<String> {
+ let inner = self.inner.read().await;
+ inner.get_jailer_root().await
+ }
+
+ async fn save_state(&self) -> Result<HypervisorState> {
+ todo!()
+ }
+
+ async fn capabilities(&self) -> Result<Capabilities> {
+ let inner = self.inner.read().await;
+ inner.capabilities().await
+ }
+}
diff --git a/src/runtime-rs/crates/persist/Cargo.toml b/src/runtime-rs/crates/persist/Cargo.toml
index 18c8bff3d..245480247 100644
--- a/src/runtime-rs/crates/persist/Cargo.toml
+++ b/src/runtime-rs/crates/persist/Cargo.toml
@@ -10,6 +10,7 @@ async-trait = "0.1.48"
anyhow = "^1.0"
kata-sys-util = { path = "../../../libs/kata-sys-util"}
kata-types = { path = "../../../libs/kata-types" }
+shim-interface = { path = "../../../libs/shim-interface" }
libc = "0.2"
serde = { version = "1.0.138", features = ["derive"] }
serde_json = "1.0.82"
diff --git a/src/runtime-rs/crates/persist/src/lib.rs b/src/runtime-rs/crates/persist/src/lib.rs
index ff61a2d4b..3b728c39c 100644
--- a/src/runtime-rs/crates/persist/src/lib.rs
+++ b/src/runtime-rs/crates/persist/src/lib.rs
@@ -7,9 +7,9 @@
pub mod sandbox_persist;
use anyhow::{anyhow, Context, Ok, Result};
use serde::de;
+use shim_interface::KATA_PATH;
use std::{fs::File, io::BufReader};
-pub const KATA_PATH: &str = "/run/kata";
pub const PERSIST_FILE: &str = "state.json";
use kata_sys_util::validate::verify_id;
use safe_path::scoped_join;
@@ -26,7 +26,7 @@ pub fn to_disk<T: serde::Serialize>(value: &T, sid: &str) -> Result<()> {
serde_json::to_writer_pretty(f, &j)?;
return Ok(());
}
- return Err(anyhow!("invalid sid {}", sid));
+ Err(anyhow!("invalid sid {}", sid))
}
pub fn from_disk<T>(sid: &str) -> Result<T>
@@ -41,7 +41,7 @@ where
let reader = BufReader::new(file);
return serde_json::from_reader(reader).map_err(|e| anyhow!(e.to_string()));
}
- return Err(anyhow!("invalid sid {}", sid));
+ Err(anyhow!("invalid sid {}", sid))
}
#[cfg(test)]
diff --git a/src/runtime-rs/crates/resource/Cargo.toml b/src/runtime-rs/crates/resource/Cargo.toml
index 754ec800b..f1957755c 100644
--- a/src/runtime-rs/crates/resource/Cargo.toml
+++ b/src/runtime-rs/crates/resource/Cargo.toml
@@ -5,10 +5,15 @@ authors = ["The Kata Containers community <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
+[dev-dependencies]
+test-utils = { path = "../../../libs/test-utils" }
+tempfile = "3.2.0"
+
[dependencies]
anyhow = "^1.0"
async-trait = "0.1.48"
bitflags = "1.2.1"
+byte-unit = "4.0.14"
cgroups-rs = "0.2.9"
futures = "0.3.11"
lazy_static = "1.4.0"
@@ -20,6 +25,7 @@ rand = "^0.7.2"
rtnetlink = "0.11.0"
scopeguard = "1.0.0"
serde = { version = "1.0.138", features = ["derive"] }
+serde_json = "1.0.82"
slog = "2.5.2"
slog-scope = "4.4.0"
tokio = { version = "1.8.0", features = ["process"] }
diff --git a/src/runtime-rs/crates/resource/src/cgroups/mod.rs b/src/runtime-rs/crates/resource/src/cgroups/mod.rs
index beb485008..7bcb39449 100644
--- a/src/runtime-rs/crates/resource/src/cgroups/mod.rs
+++ b/src/runtime-rs/crates/resource/src/cgroups/mod.rs
@@ -179,7 +179,7 @@ impl CgroupsResource {
// All vCPU threads move to the sandbox controller.
for tid in tids {
self.cgroup_manager
- .add_task_by_tgid(CgroupPid { pid: *tid as u64 })?
+ .add_task(CgroupPid { pid: *tid as u64 })?
}
Ok(())
diff --git a/src/runtime-rs/crates/resource/src/manager.rs b/src/runtime-rs/crates/resource/src/manager.rs
index 78b40380f..26cc2a26f 100644
--- a/src/runtime-rs/crates/resource/src/manager.rs
+++ b/src/runtime-rs/crates/resource/src/manager.rs
@@ -68,20 +68,23 @@ impl ResourceManager {
pub async fn handler_rootfs(
&self,
cid: &str,
+ root: &oci::Root,
bundle_path: &str,
rootfs_mounts: &[Mount],
) -> Result<Arc<dyn Rootfs>> {
let inner = self.inner.read().await;
- inner.handler_rootfs(cid, bundle_path, rootfs_mounts).await
+ inner
+ .handler_rootfs(cid, root, bundle_path, rootfs_mounts)
+ .await
}
pub async fn handler_volumes(
&self,
cid: &str,
- oci_mounts: &[oci::Mount],
+ spec: &oci::Spec,
) -> Result<Vec<Arc<dyn Volume>>> {
let inner = self.inner.read().await;
- inner.handler_volumes(cid, oci_mounts).await
+ inner.handler_volumes(cid, spec).await
}
pub async fn dump(&self) {
diff --git a/src/runtime-rs/crates/resource/src/manager_inner.rs b/src/runtime-rs/crates/resource/src/manager_inner.rs
index dac07d02b..7bdfddb6a 100644
--- a/src/runtime-rs/crates/resource/src/manager_inner.rs
+++ b/src/runtime-rs/crates/resource/src/manager_inner.rs
@@ -4,17 +4,18 @@
// SPDX-License-Identifier: Apache-2.0
//
-use std::sync::Arc;
+use std::{sync::Arc, thread};
use crate::resource_persist::ResourceState;
use agent::{Agent, Storage};
-use anyhow::{Context, Result};
+use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use hypervisor::Hypervisor;
use kata_types::config::TomlConfig;
use kata_types::mount::Mount;
use oci::LinuxResources;
use persist::sandbox_persist::Persist;
+use tokio::runtime;
use crate::{
cgroups::{CgroupArgs, CgroupsResource},
@@ -71,19 +72,49 @@ impl ResourceManagerInner {
for dc in device_configs {
match dc {
ResourceConfig::ShareFs(c) => {
- let share_fs = share_fs::new(&self.sid, &c).context("new share fs")?;
- share_fs
- .setup_device_before_start_vm(self.hypervisor.as_ref())
- .await
- .context("setup share fs device before start vm")?;
- self.share_fs = Some(share_fs);
+ self.share_fs = if self
+ .hypervisor
+ .capabilities()
+ .await?
+ .is_fs_sharing_supported()
+ {
+ let share_fs = share_fs::new(&self.sid, &c).context("new share fs")?;
+ share_fs
+ .setup_device_before_start_vm(self.hypervisor.as_ref())
+ .await
+ .context("setup share fs device before start vm")?;
+ Some(share_fs)
+ } else {
+ None
+ };
}
ResourceConfig::Network(c) => {
- let d = network::new(&c).await.context("new network")?;
- d.setup(self.hypervisor.as_ref())
- .await
- .context("setup network")?;
- self.network = Some(d)
+ // 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);
}
};
}
@@ -165,21 +196,30 @@ impl ResourceManagerInner {
pub async fn handler_rootfs(
&self,
cid: &str,
+ root: &oci::Root,
bundle_path: &str,
rootfs_mounts: &[Mount],
) -> Result<Arc<dyn Rootfs>> {
self.rootfs_resource
- .handler_rootfs(&self.share_fs, cid, bundle_path, rootfs_mounts)
+ .handler_rootfs(
+ &self.share_fs,
+ self.hypervisor.as_ref(),
+ &self.sid,
+ cid,
+ root,
+ bundle_path,
+ rootfs_mounts,
+ )
.await
}
pub async fn handler_volumes(
&self,
cid: &str,
- oci_mounts: &[oci::Mount],
+ spec: &oci::Spec,
) -> Result<Vec<Arc<dyn Volume>>> {
self.volume_resource
- .handler_volumes(&self.share_fs, cid, oci_mounts)
+ .handler_volumes(&self.share_fs, cid, spec)
.await
}
diff --git a/src/runtime-rs/crates/resource/src/network/endpoint/endpoints_test.rs b/src/runtime-rs/crates/resource/src/network/endpoint/endpoints_test.rs
index 90623d59c..92662a0d0 100644
--- a/src/runtime-rs/crates/resource/src/network/endpoint/endpoints_test.rs
+++ b/src/runtime-rs/crates/resource/src/network/endpoint/endpoints_test.rs
@@ -20,6 +20,7 @@ mod tests {
NetworkModelType, TC_FILTER_NET_MODEL_STR,
},
network_pair::{NetworkInterface, NetworkPair, TapInterface},
+ utils::link::net_test_utils::delete_link,
};
// this unit test tests the integrity of MacVlanEndpoint::new()
@@ -124,14 +125,10 @@ mod tests {
}
assert_eq!(manual.net_pair.network_qos, result.net_pair.network_qos);
}
- let link_index = fetch_index(&handle, manual_vlan_iface_name.as_str())
+ assert!(delete_link(&handle, manual_vlan_iface_name.as_str())
.await
- .expect("failed to fetch index");
- assert!(handle.link().del(link_index).execute().await.is_ok());
- let link_index = fetch_index(&handle, tap_iface_name.as_str())
- .await
- .expect("failed to fetch index");
- assert!(handle.link().del(link_index).execute().await.is_ok());
+ .is_ok());
+ assert!(delete_link(&handle, tap_iface_name.as_str()).await.is_ok());
assert!(handle.link().del(dummy_index).execute().await.is_ok());
}
}
@@ -253,14 +250,10 @@ mod tests {
assert_eq!(manual.net_pair.network_qos, result.net_pair.network_qos);
}
// delete the manually created links
- let link_index = fetch_index(&handle, manual_macvlan_iface_name.as_str())
- .await
- .expect("failed to fetch index");
- assert!(handle.link().del(link_index).execute().await.is_ok());
- let link_index = fetch_index(&handle, tap_iface_name.as_str())
+ assert!(delete_link(&handle, manual_macvlan_iface_name.as_str())
.await
- .expect("failed to fetch index");
- assert!(handle.link().del(link_index).execute().await.is_ok());
+ .is_ok());
+ assert!(delete_link(&handle, tap_iface_name.as_str()).await.is_ok());
assert!(handle.link().del(dummy_index).execute().await.is_ok());
}
}
@@ -355,14 +348,10 @@ mod tests {
}
assert_eq!(manual.net_pair.network_qos, result.net_pair.network_qos);
}
- let link_index = fetch_index(&handle, manual_virt_iface_name.as_str())
- .await
- .expect("failed to fetch index");
- assert!(handle.link().del(link_index).execute().await.is_ok());
- let link_index = fetch_index(&handle, tap_iface_name.as_str())
+ assert!(delete_link(&handle, manual_virt_iface_name.as_str())
.await
- .expect("failed to fetch index");
- assert!(handle.link().del(link_index).execute().await.is_ok());
+ .is_ok());
+ assert!(delete_link(&handle, tap_iface_name.as_str()).await.is_ok());
}
}
}
diff --git a/src/runtime-rs/crates/resource/src/network/network_pair.rs b/src/runtime-rs/crates/resource/src/network/network_pair.rs
index c96898619..1bee220fe 100644
--- a/src/runtime-rs/crates/resource/src/network/network_pair.rs
+++ b/src/runtime-rs/crates/resource/src/network/network_pair.rs
@@ -177,3 +177,85 @@ pub async fn get_link_by_name(
Ok(link::get_link_from_message(msg))
}
+
+#[cfg(test)]
+mod tests {
+ use scopeguard::defer;
+
+ use super::*;
+ use crate::network::network_model::TC_FILTER_NET_MODEL_STR;
+ use test_utils::skip_if_not_root;
+ use utils::link::net_test_utils::delete_link;
+
+ // this ut tests create_link() and get_link_by_name()
+ #[actix_rt::test]
+ async fn test_utils() {
+ skip_if_not_root!();
+
+ if let Ok((conn, handle, _)) =
+ rtnetlink::new_connection().context("failed to create netlink connection")
+ {
+ let thread_handler = tokio::spawn(conn);
+ defer!({
+ thread_handler.abort();
+ });
+
+ assert!(create_link(&handle, "kata_test_1", 2).await.is_ok());
+ assert!(create_link(&handle, "kata_test_2", 3).await.is_ok());
+ assert!(create_link(&handle, "kata_test_3", 4).await.is_ok());
+
+ assert!(get_link_by_name(&handle, "kata_test_1").await.is_ok());
+ assert!(get_link_by_name(&handle, "kata_test_2").await.is_ok());
+ assert!(get_link_by_name(&handle, "kata_test_3").await.is_ok());
+
+ assert!(delete_link(&handle, "kata_test_1").await.is_ok());
+ assert!(delete_link(&handle, "kata_test_2").await.is_ok());
+ assert!(delete_link(&handle, "kata_test_3").await.is_ok());
+
+ assert!(get_link_by_name(&handle, "kata_test_1").await.is_err());
+ assert!(get_link_by_name(&handle, "kata_test_2").await.is_err());
+ assert!(get_link_by_name(&handle, "kata_test_3").await.is_err());
+ }
+ }
+
+ #[actix_rt::test]
+ async fn test_network_pair() {
+ let idx = 123456;
+ let virt_iface_name = format!("eth{}", idx);
+ let tap_name = format!("tap{}{}", idx, TAP_SUFFIX);
+ let queues = 2;
+ let model = TC_FILTER_NET_MODEL_STR;
+
+ skip_if_not_root!();
+
+ if let Ok((conn, handle, _)) =
+ rtnetlink::new_connection().context("failed to create netlink connection")
+ {
+ let thread_handler = tokio::spawn(conn);
+ defer!({
+ thread_handler.abort();
+ });
+ // the network pair has not been created
+ assert!(get_link_by_name(&handle, virt_iface_name.as_str())
+ .await
+ .is_err());
+
+ // mock containerd to create one end of the network pair
+ assert!(create_link(&handle, virt_iface_name.as_str(), queues)
+ .await
+ .is_ok());
+
+ if let Ok(_pair) = NetworkPair::new(&handle, idx, "", model, queues).await {
+ // the pair is created, we can find the two ends of network pair
+ assert!(get_link_by_name(&handle, virt_iface_name.as_str())
+ .await
+ .is_ok());
+ assert!(get_link_by_name(&handle, tap_name.as_str()).await.is_ok());
+
+ //delete the link created in test
+ assert!(delete_link(&handle, virt_iface_name.as_str()).await.is_ok());
+ assert!(delete_link(&handle, tap_name.as_str()).await.is_ok());
+ }
+ }
+ }
+}
diff --git a/src/runtime-rs/crates/resource/src/network/utils/address.rs b/src/runtime-rs/crates/resource/src/network/utils/address.rs
index 0484c9f36..ef3b68278 100644
--- a/src/runtime-rs/crates/resource/src/network/utils/address.rs
+++ b/src/runtime-rs/crates/resource/src/network/utils/address.rs
@@ -85,3 +85,30 @@ pub(crate) fn parse_ip(ip: &[u8], family: u8) -> Result<IpAddr> {
}
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_parse_ip() {
+ let test_ipv4 = [10, 25, 64, 128];
+ let ipv4 = parse_ip(test_ipv4.as_slice(), AF_INET as u8).unwrap();
+ let expected_ipv4 = IpAddr::V4(Ipv4Addr::new(10, 25, 64, 128));
+ assert_eq!(ipv4, expected_ipv4);
+
+ let test_ipv6 = [0, 2, 4, 0, 0, 2, 4, 0, 0, 2, 4, 0, 0, 2, 4, 0];
+ let ipv6 = parse_ip(test_ipv6.as_slice(), AF_INET6 as u8).unwrap();
+ // two u8 => one u16, (0u8, 2u8 => 0x0002), (4u8, 0u8 => 0x0400)
+ let expected_ipv6 = IpAddr::V6(Ipv6Addr::new(
+ 0x0002, 0x0400, 0x0002, 0x0400, 0x0002, 0x0400, 0x0002, 0x0400,
+ ));
+ assert_eq!(ipv6, expected_ipv6);
+
+ let fail_ipv4 = [10, 22, 33, 44, 55];
+ assert!(parse_ip(fail_ipv4.as_slice(), AF_INET as u8).is_err());
+
+ let fail_ipv6 = [1, 2, 3, 4, 5, 6, 7, 8, 2, 3];
+ assert!(parse_ip(fail_ipv6.as_slice(), AF_INET6 as u8).is_err());
+ }
+}
diff --git a/src/runtime-rs/crates/resource/src/network/utils/link/create.rs b/src/runtime-rs/crates/resource/src/network/utils/link/create.rs
index 06bedf79b..10c7c7942 100644
--- a/src/runtime-rs/crates/resource/src/network/utils/link/create.rs
+++ b/src/runtime-rs/crates/resource/src/network/utils/link/create.rs
@@ -119,7 +119,7 @@ pub fn create_link(name: &str, link_type: LinkType, queues: usize) -> Result<()>
fn create_queue(name: &str, flags: libc::c_int) -> Result<(File, String)> {
let path = Path::new(DEVICE_PATH);
- let file = OpenOptions::new().read(true).write(true).open(&path)?;
+ let file = OpenOptions::new().read(true).write(true).open(path)?;
let mut req = CreateLinkReq::from_name(name)?;
unsafe {
req.set_raw_flags(flags as libc::c_short);
@@ -127,3 +127,63 @@ fn create_queue(name: &str, flags: libc::c_int) -> Result<(File, String)> {
};
Ok((file, req.get_name()?))
}
+
+#[cfg(test)]
+pub mod net_test_utils {
+ use crate::network::network_model::tc_filter_model::fetch_index;
+
+ // remove a link by its name
+ #[allow(dead_code)]
+ pub async fn delete_link(
+ handle: &rtnetlink::Handle,
+ name: &str,
+ ) -> Result<(), rtnetlink::Error> {
+ let link_index = fetch_index(handle, name)
+ .await
+ .expect("failed to fetch index");
+ // the ifindex of a link will not change during its lifetime, so the index
+ // remains the same between the query above and the deletion below
+ handle.link().del(link_index).execute().await
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use scopeguard::defer;
+ use test_utils::skip_if_not_root;
+
+ use crate::network::{
+ network_pair::get_link_by_name, utils::link::create::net_test_utils::delete_link,
+ };
+
+ use super::*;
+
+ #[actix_rt::test]
+ async fn test_create_link() {
+ let name_tun = "___test_tun";
+ let name_tap = "___test_tap";
+
+ // tests should be taken under root
+ skip_if_not_root!();
+
+ if let Ok((conn, handle, _)) =
+ rtnetlink::new_connection().context("failed to create netlink connection")
+ {
+ let thread_handler = tokio::spawn(conn);
+ defer!({
+ thread_handler.abort();
+ });
+
+ assert!(create_link(name_tun, LinkType::Tun, 2).is_ok());
+ assert!(create_link(name_tap, LinkType::Tap, 2).is_ok());
+ assert!(get_link_by_name(&handle, name_tap).await.is_ok());
+ assert!(get_link_by_name(&handle, name_tun).await.is_ok());
+ assert!(delete_link(&handle, name_tun).await.is_ok());
+ assert!(delete_link(&handle, name_tap).await.is_ok());
+
+ // link does not present
+ assert!(get_link_by_name(&handle, name_tun).await.is_err());
+ assert!(get_link_by_name(&handle, name_tap).await.is_err());
+ }
+ }
+}
diff --git a/src/runtime-rs/crates/resource/src/network/utils/link/manager.rs b/src/runtime-rs/crates/resource/src/network/utils/link/manager.rs
index efc43bb70..f628ec03f 100644
--- a/src/runtime-rs/crates/resource/src/network/utils/link/manager.rs
+++ b/src/runtime-rs/crates/resource/src/network/utils/link/manager.rs
@@ -11,6 +11,7 @@ use netlink_packet_route::{
use super::{Link, LinkAttrs};
+#[allow(clippy::box_default)]
pub fn get_link_from_message(mut msg: LinkMessage) -> Box<dyn Link> {
let mut base = LinkAttrs {
index: msg.header.index,
@@ -83,6 +84,7 @@ pub fn get_link_from_message(mut msg: LinkMessage) -> Box<dyn Link> {
ret
}
+#[allow(clippy::box_default)]
fn link_info(mut infos: Vec<Info>) -> Box<dyn Link> {
let mut link: Option<Box<dyn Link>> = None;
while let Some(info) = infos.pop() {
@@ -181,119 +183,40 @@ fn parse_bridge(mut ibs: Vec<InfoBridge>) -> Bridge {
}
bridge
}
-#[derive(Debug, PartialEq, Eq, Clone, Default)]
-pub struct Device {
- attrs: Option<LinkAttrs>,
-}
-
-impl Link for Device {
- fn attrs(&self) -> &LinkAttrs {
- self.attrs.as_ref().unwrap()
- }
- fn set_attrs(&mut self, attr: LinkAttrs) {
- self.attrs = Some(attr);
- }
- fn r#type(&self) -> &'static str {
- "device"
- }
-}
-
-#[derive(Debug, PartialEq, Eq, Clone, Default)]
-pub struct Tuntap {
- pub attrs: Option<LinkAttrs>,
-}
-
-impl Link for Tuntap {
- fn attrs(&self) -> &LinkAttrs {
- self.attrs.as_ref().unwrap()
- }
- fn set_attrs(&mut self, attr: LinkAttrs) {
- self.attrs = Some(attr);
- }
- fn r#type(&self) -> &'static str {
- "tuntap"
- }
-}
-
-#[derive(Debug, PartialEq, Eq, Clone, Default)]
-pub struct Veth {
- attrs: Option<LinkAttrs>,
-
- /// on create only
- pub peer_name: String,
-}
-
-impl Link for Veth {
- fn attrs(&self) -> &LinkAttrs {
- self.attrs.as_ref().unwrap()
- }
- fn set_attrs(&mut self, attr: LinkAttrs) {
- self.attrs = Some(attr);
- }
- fn r#type(&self) -> &'static str {
- "veth"
- }
-}
-
-#[derive(Debug, PartialEq, Eq, Clone, Default)]
-pub struct IpVlan {
- attrs: Option<LinkAttrs>,
-
- /// on create only
- pub peer_name: String,
-}
-impl Link for IpVlan {
- fn attrs(&self) -> &LinkAttrs {
- self.attrs.as_ref().unwrap()
- }
- fn set_attrs(&mut self, attr: LinkAttrs) {
- self.attrs = Some(attr);
- }
- fn r#type(&self) -> &'static str {
- "ipvlan"
- }
-}
-
-#[derive(Debug, PartialEq, Eq, Clone, Default)]
-pub struct MacVlan {
- attrs: Option<LinkAttrs>,
-
- /// on create only
- pub peer_name: String,
-}
-
-impl Link for MacVlan {
- fn attrs(&self) -> &LinkAttrs {
- self.attrs.as_ref().unwrap()
- }
- fn set_attrs(&mut self, attr: LinkAttrs) {
- self.attrs = Some(attr)
- }
- fn r#type(&self) -> &'static str {
- "macvlan"
- }
+macro_rules! impl_network_dev {
+ ($r_type: literal , $r_struct: ty) => {
+ impl Link for $r_struct {
+ fn attrs(&self) -> &LinkAttrs {
+ self.attrs.as_ref().unwrap()
+ }
+ fn set_attrs(&mut self, attr: LinkAttrs) {
+ self.attrs = Some(attr);
+ }
+ fn r#type(&self) -> &'static str {
+ $r_type
+ }
+ }
+ };
}
-#[derive(Debug, PartialEq, Eq, Clone, Default)]
-pub struct Vlan {
- attrs: Option<LinkAttrs>,
+macro_rules! define_and_impl_network_dev {
+ ($r_type: literal , $r_struct: tt) => {
+ #[derive(Debug, PartialEq, Eq, Clone, Default)]
+ pub struct $r_struct {
+ attrs: Option<LinkAttrs>,
+ }
- /// on create only
- pub peer_name: String,
+ impl_network_dev!($r_type, $r_struct);
+ };
}
-impl Link for Vlan {
- fn attrs(&self) -> &LinkAttrs {
- self.attrs.as_ref().unwrap()
- }
- fn set_attrs(&mut self, attr: LinkAttrs) {
- self.attrs = Some(attr);
- }
- fn r#type(&self) -> &'static str {
- "vlan"
- }
-}
+define_and_impl_network_dev!("device", Device);
+define_and_impl_network_dev!("tuntap", Tuntap);
+define_and_impl_network_dev!("veth", Veth);
+define_and_impl_network_dev!("ipvlan", IpVlan);
+define_and_impl_network_dev!("macvlan", MacVlan);
+define_and_impl_network_dev!("vlan", Vlan);
#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct Bridge {
@@ -303,14 +226,4 @@ pub struct Bridge {
pub vlan_filtering: bool,
}
-impl Link for Bridge {
- fn attrs(&self) -> &LinkAttrs {
- self.attrs.as_ref().unwrap()
- }
- fn set_attrs(&mut self, attr: LinkAttrs) {
- self.attrs = Some(attr);
- }
- fn r#type(&self) -> &'static str {
- "bridge"
- }
-}
+impl_network_dev!("bridge", Bridge);
diff --git a/src/runtime-rs/crates/resource/src/network/utils/link/mod.rs b/src/runtime-rs/crates/resource/src/network/utils/link/mod.rs
index 9fcc2b640..aa5c2631b 100644
--- a/src/runtime-rs/crates/resource/src/network/utils/link/mod.rs
+++ b/src/runtime-rs/crates/resource/src/network/utils/link/mod.rs
@@ -16,6 +16,9 @@ use std::os::unix::io::RawFd;
use netlink_packet_route::link::nlas::State;
+#[cfg(test)]
+pub use create::net_test_utils;
+
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Namespace {
NetNsPid(u32),
diff --git a/src/runtime-rs/crates/resource/src/network/utils/mod.rs b/src/runtime-rs/crates/resource/src/network/utils/mod.rs
index 574178c3d..74635a5d9 100644
--- a/src/runtime-rs/crates/resource/src/network/utils/mod.rs
+++ b/src/runtime-rs/crates/resource/src/network/utils/mod.rs
@@ -33,3 +33,34 @@ pub(crate) fn get_mac_addr(b: &[u8]) -> Result<String> {
))
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_get_mac_addr() {
+ // length is not 6
+ let fail_slice = vec![1, 2, 3];
+ assert!(get_mac_addr(&fail_slice).is_err());
+
+ let expected_slice = vec![10, 11, 128, 3, 4, 5];
+ let expected_mac = String::from("0a:0b:80:03:04:05");
+ let res = get_mac_addr(&expected_slice);
+ assert!(res.is_ok());
+ assert_eq!(expected_mac, res.unwrap());
+ }
+
+ #[test]
+ fn test_parse_mac() {
+ // length is not 6
+ let fail = "1:2:3";
+ assert!(parse_mac(fail).is_none());
+
+ let v = [10, 11, 128, 3, 4, 5];
+ let expected_addr = hypervisor::Address(v);
+ let addr = parse_mac("0a:0b:80:03:04:05");
+ assert!(addr.is_some());
+ assert_eq!(expected_addr.0, addr.unwrap().0);
+ }
+}
diff --git a/src/runtime-rs/crates/resource/src/network/utils/netns.rs b/src/runtime-rs/crates/resource/src/network/utils/netns.rs
index a2a29dc97..07584c641 100644
--- a/src/runtime-rs/crates/resource/src/network/utils/netns.rs
+++ b/src/runtime-rs/crates/resource/src/network/utils/netns.rs
@@ -20,7 +20,7 @@ impl NetnsGuard {
let current_netns_path = format!("/proc/{}/task/{}/ns/{}", getpid(), gettid(), "net");
let old_netns = File::open(&current_netns_path)
.with_context(|| format!("open current netns path {}", &current_netns_path))?;
- let new_netns = File::open(&new_netns_path)
+ let new_netns = File::open(new_netns_path)
.with_context(|| format!("open new netns path {}", &new_netns_path))?;
setns(new_netns.as_raw_fd(), CloneFlags::CLONE_NEWNET)
.with_context(|| "set netns to new netns")?;
@@ -49,3 +49,22 @@ impl Drop for NetnsGuard {
}
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use test_utils::skip_if_not_root;
+
+ #[test]
+ fn test_new_netns_guard() {
+ // test run under root
+ skip_if_not_root!();
+
+ let new_netns_path = "/proc/1/task/1/ns/net"; // systemd, always exists
+ let netns_guard = NetnsGuard::new(new_netns_path).unwrap();
+ drop(netns_guard);
+
+ let empty_path = "";
+ assert!(NetnsGuard::new(empty_path).unwrap().old_netns.is_none());
+ }
+}
diff --git a/src/runtime-rs/crates/resource/src/rootfs/mod.rs b/src/runtime-rs/crates/resource/src/rootfs/mod.rs
index 827809bc4..b18085ed8 100644
--- a/src/runtime-rs/crates/resource/src/rootfs/mod.rs
+++ b/src/runtime-rs/crates/resource/src/rootfs/mod.rs
@@ -4,23 +4,30 @@
// SPDX-License-Identifier: Apache-2.0
//
+mod nydus_rootfs;
mod share_fs_rootfs;
-use std::{sync::Arc, vec::Vec};
-
+use agent::Storage;
use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
+use hypervisor::Hypervisor;
use kata_types::mount::Mount;
+use std::{sync::Arc, vec::Vec};
use tokio::sync::RwLock;
use crate::share_fs::ShareFs;
-const ROOTFS: &str = "rootfs";
+use self::nydus_rootfs::NYDUS_ROOTFS_TYPE;
+const ROOTFS: &str = "rootfs";
+const HYBRID_ROOTFS_LOWER_DIR: &str = "rootfs_lower";
+const TYPE_OVERLAY_FS: &str = "overlay";
#[async_trait]
pub trait Rootfs: Send + Sync {
async fn get_guest_rootfs_path(&self) -> Result<String>;
async fn get_rootfs_mount(&self) -> Result<Vec<oci::Mount>>;
+ async fn get_storage(&self) -> Option<Storage>;
+ async fn cleanup(&self) -> Result<()>;
}
#[derive(Default)]
@@ -45,32 +52,67 @@ impl RootFsResource {
}
}
+ #[allow(clippy::too_many_arguments)]
pub async fn handler_rootfs(
&self,
share_fs: &Option<Arc<dyn ShareFs>>,
+ hypervisor: &dyn Hypervisor,
+ sid: &str,
cid: &str,
+ root: &oci::Root,
bundle_path: &str,
rootfs_mounts: &[Mount],
) -> Result<Arc<dyn Rootfs>> {
match rootfs_mounts {
+ // if rootfs_mounts is empty
+ mounts_vec if mounts_vec.is_empty() => {
+ if let Some(share_fs) = share_fs {
+ // share fs rootfs
+ Ok(Arc::new(
+ share_fs_rootfs::ShareFsRootfs::new(
+ share_fs,
+ cid,
+ root.path.as_str(),
+ None,
+ )
+ .await
+ .context("new share fs rootfs")?,
+ ))
+ } else {
+ return Err(anyhow!("share fs is unavailable"));
+ }
+ }
mounts_vec if is_single_layer_rootfs(mounts_vec) => {
// Safe as single_layer_rootfs must have one layer
let layer = &mounts_vec[0];
-
- let rootfs = if let Some(share_fs) = share_fs {
- // share fs rootfs
- let share_fs_mount = share_fs.get_share_fs_mount();
- share_fs_rootfs::ShareFsRootfs::new(&share_fs_mount, cid, bundle_path, layer)
- .await
- .context("new share fs rootfs")?
+ let rootfs: Arc<dyn Rootfs> = if let Some(share_fs) = share_fs {
+ // nydus rootfs
+ if layer.fs_type == NYDUS_ROOTFS_TYPE {
+ Arc::new(
+ nydus_rootfs::NydusRootfs::new(share_fs, hypervisor, sid, cid, layer)
+ .await
+ .context("new nydus rootfs")?,
+ )
+ } else {
+ // share fs rootfs
+ Arc::new(
+ share_fs_rootfs::ShareFsRootfs::new(
+ share_fs,
+ cid,
+ bundle_path,
+ Some(layer),
+ )
+ .await
+ .context("new share fs rootfs")?,
+ )
+ }
} else {
return Err(anyhow!("unsupported rootfs {:?}", &layer));
};
let mut inner = self.inner.write().await;
- let r = Arc::new(rootfs);
- inner.rootfs.push(r.clone());
- Ok(r)
+ inner.rootfs.push(Arc::clone(&rootfs));
+ Ok(rootfs)
}
_ => {
return Err(anyhow!(
diff --git a/src/runtime-rs/crates/resource/src/rootfs/nydus_rootfs.rs b/src/runtime-rs/crates/resource/src/rootfs/nydus_rootfs.rs
new file mode 100644
index 000000000..16f9c48dd
--- /dev/null
+++ b/src/runtime-rs/crates/resource/src/rootfs/nydus_rootfs.rs
@@ -0,0 +1,153 @@
+// Copyright (c) 2019-2022 Alibaba Cloud
+// Copyright (c) 2019-2022 Ant Group
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+use std::{fs, sync::Arc};
+
+use super::{Rootfs, TYPE_OVERLAY_FS};
+use crate::{
+ rootfs::{HYBRID_ROOTFS_LOWER_DIR, ROOTFS},
+ share_fs::{
+ do_get_guest_path, do_get_guest_share_path, get_host_rw_shared_path, rafs_mount, ShareFs,
+ ShareFsRootfsConfig, PASSTHROUGH_FS_DIR,
+ },
+};
+use agent::Storage;
+use anyhow::{anyhow, Context, Result};
+use async_trait::async_trait;
+use hypervisor::Hypervisor;
+use kata_types::mount::{Mount, NydusExtraOptions};
+
+// Used for nydus rootfs
+pub(crate) const NYDUS_ROOTFS_TYPE: &str = "fuse.nydus-overlayfs";
+// Used for Nydus v5 rootfs version
+const NYDUS_ROOTFS_V5: &str = "v5";
+// Used for Nydus v6 rootfs version
+const NYDUS_ROOTFS_V6: &str = "v6";
+
+const SNAPSHOT_DIR: &str = "snapshotdir";
+const KATA_OVERLAY_DEV_TYPE: &str = "overlayfs";
+
+pub(crate) struct NydusRootfs {
+ guest_path: String,
+ rootfs: Storage,
+}
+
+impl NydusRootfs {
+ pub async fn new(
+ share_fs: &Arc<dyn ShareFs>,
+ h: &dyn Hypervisor,
+ sid: &str,
+ cid: &str,
+ rootfs: &Mount,
+ ) -> Result<Self> {
+ let share_fs_mount = share_fs.get_share_fs_mount();
+ let extra_options =
+ NydusExtraOptions::new(rootfs).context("failed to parse nydus extra options")?;
+ info!(sl!(), "extra_option {:?}", &extra_options);
+ let rafs_meta = &extra_options.source;
+ let (rootfs_storage, rootfs_guest_path) = match extra_options.fs_version.as_str() {
+ // both nydus v5 and v6 can be handled by the builtin nydus in dragonball by using the rafs mode.
+ // nydus v6 could also be handled by the guest kernel as well, but some kernel patch is not support in the upstream community. We will add an option to let runtime-rs handle nydus v6 in the guest kernel optionally once the patch is ready
+ // see this issue (https://github.com/kata-containers/kata-containers/issues/5143)
+ NYDUS_ROOTFS_V5 | NYDUS_ROOTFS_V6 => {
+ // rafs mount the metadata of nydus rootfs
+ let rafs_mnt = do_get_guest_share_path(HYBRID_ROOTFS_LOWER_DIR, cid, true);
+ rafs_mount(
+ h,
+ rafs_meta.to_string(),
+ rafs_mnt,
+ extra_options.config.clone(),
+ None,
+ )
+ .await
+ .context("failed to do rafs mount")?;
+ // create rootfs under the share directory
+ let container_share_dir = get_host_rw_shared_path(sid)
+ .join(PASSTHROUGH_FS_DIR)
+ .join(cid);
+ let rootfs_dir = container_share_dir.join(ROOTFS);
+ fs::create_dir_all(rootfs_dir).context("failed to create directory")?;
+ // mount point inside the guest
+ let rootfs_guest_path = do_get_guest_path(ROOTFS, cid, false, false);
+ // bind mount the snapshot dir under the share directory
+ share_fs_mount
+ .share_rootfs(&ShareFsRootfsConfig {
+ cid: cid.to_string(),
+ source: extra_options.snapshot_dir.clone(),
+ target: SNAPSHOT_DIR.to_string(),
+ readonly: true,
+ is_rafs: false,
+ })
+ .await
+ .context("share nydus rootfs")?;
+ let mut options: Vec<String> = Vec::new();
+ options.push(
+ "lowerdir=".to_string()
+ + &do_get_guest_path(HYBRID_ROOTFS_LOWER_DIR, cid, false, true),
+ );
+ options.push(
+ "workdir=".to_string()
+ + &do_get_guest_path(
+ format!("{}/{}", SNAPSHOT_DIR, "work").as_str(),
+ cid,
+ false,
+ false,
+ ),
+ );
+ options.push(
+ "upperdir=".to_string()
+ + &do_get_guest_path(
+ format!("{}/{}", SNAPSHOT_DIR, "fs").as_str(),
+ cid,
+ false,
+ false,
+ ),
+ );
+ options.push("index=off".to_string());
+ Ok((
+ Storage {
+ driver: KATA_OVERLAY_DEV_TYPE.to_string(),
+ source: TYPE_OVERLAY_FS.to_string(),
+ fs_type: TYPE_OVERLAY_FS.to_string(),
+ options,
+ mount_point: rootfs_guest_path.clone(),
+ ..Default::default()
+ },
+ rootfs_guest_path,
+ ))
+ }
+ _ => {
+ let errstr: &str = "new_nydus_rootfs: invalid nydus rootfs type";
+ error!(sl!(), "{}", errstr);
+ Err(anyhow!(errstr))
+ }
+ }?;
+ Ok(NydusRootfs {
+ guest_path: rootfs_guest_path,
+ rootfs: rootfs_storage,
+ })
+ }
+}
+
+#[async_trait]
+impl Rootfs for NydusRootfs {
+ async fn get_guest_rootfs_path(&self) -> Result<String> {
+ Ok(self.guest_path.clone())
+ }
+
+ async fn get_rootfs_mount(&self) -> Result<Vec<oci::Mount>> {
+ Ok(vec![])
+ }
+
+ async fn get_storage(&self) -> Option<Storage> {
+ Some(self.rootfs.clone())
+ }
+
+ async fn cleanup(&self) -> Result<()> {
+ // TODO: Clean up NydusRootfs after the container is killed
+ warn!(sl!(), "Cleaning up NydusRootfs is still unimplemented.");
+ Ok(())
+ }
+}
diff --git a/src/runtime-rs/crates/resource/src/rootfs/share_fs_rootfs.rs b/src/runtime-rs/crates/resource/src/rootfs/share_fs_rootfs.rs
index 643af13fe..b5d4136c1 100644
--- a/src/runtime-rs/crates/resource/src/rootfs/share_fs_rootfs.rs
+++ b/src/runtime-rs/crates/resource/src/rootfs/share_fs_rootfs.rs
@@ -4,45 +4,58 @@
// SPDX-License-Identifier: Apache-2.0
//
-use std::sync::Arc;
-
+use agent::Storage;
use anyhow::{Context, Result};
use async_trait::async_trait;
-use kata_sys_util::mount::Mounter;
+use kata_sys_util::mount::{umount_timeout, Mounter};
use kata_types::mount::Mount;
+use std::sync::Arc;
use super::{Rootfs, ROOTFS};
-use crate::share_fs::{ShareFsMount, ShareFsRootfsConfig};
+use crate::share_fs::{ShareFs, ShareFsRootfsConfig};
pub(crate) struct ShareFsRootfs {
guest_path: String,
+ share_fs: Arc<dyn ShareFs>,
+ config: ShareFsRootfsConfig,
}
impl ShareFsRootfs {
pub async fn new(
- share_fs_mount: &Arc<dyn ShareFsMount>,
+ share_fs: &Arc<dyn ShareFs>,
cid: &str,
bundle_path: &str,
- rootfs: &Mount,
+ rootfs: Option<&Mount>,
) -> Result<Self> {
- let bundle_rootfs = format!("{}/{}", bundle_path, ROOTFS);
- rootfs.mount(&bundle_rootfs).context(format!(
- "mount rootfs from {:?} to {}",
- &rootfs, &bundle_rootfs
- ))?;
+ let bundle_rootfs = if let Some(rootfs) = rootfs {
+ let bundle_rootfs = format!("{}/{}", bundle_path, ROOTFS);
+ rootfs.mount(&bundle_rootfs).context(format!(
+ "mount rootfs from {:?} to {}",
+ &rootfs, &bundle_rootfs
+ ))?;
+ bundle_rootfs
+ } else {
+ bundle_path.to_string()
+ };
+
+ let share_fs_mount = share_fs.get_share_fs_mount();
+ let config = ShareFsRootfsConfig {
+ cid: cid.to_string(),
+ source: bundle_rootfs.to_string(),
+ target: ROOTFS.to_string(),
+ readonly: false,
+ is_rafs: false,
+ };
let mount_result = share_fs_mount
- .share_rootfs(ShareFsRootfsConfig {
- cid: cid.to_string(),
- source: bundle_rootfs.to_string(),
- target: ROOTFS.to_string(),
- readonly: false,
- })
+ .share_rootfs(&config)
.await
.context("share rootfs")?;
Ok(ShareFsRootfs {
guest_path: mount_result.guest_path,
+ share_fs: Arc::clone(share_fs),
+ config,
})
}
}
@@ -56,4 +69,21 @@ impl Rootfs for ShareFsRootfs {
async fn get_rootfs_mount(&self) -> Result<Vec<oci::Mount>> {
todo!()
}
+
+ async fn get_storage(&self) -> Option<Storage> {
+ None
+ }
+
+ async fn cleanup(&self) -> Result<()> {
+ // Umount the mount point shared to guest
+ let share_fs_mount = self.share_fs.get_share_fs_mount();
+ share_fs_mount
+ .umount_rootfs(&self.config)
+ .await
+ .context("umount shared rootfs")?;
+
+ // Umount the bundle rootfs
+ umount_timeout(&self.config.source, 0).context("umount bundle rootfs")?;
+ Ok(())
+ }
}
diff --git a/src/runtime-rs/crates/resource/src/share_fs/mod.rs b/src/runtime-rs/crates/resource/src/share_fs/mod.rs
index 36f4f1ec2..739fa0459 100644
--- a/src/runtime-rs/crates/resource/src/share_fs/mod.rs
+++ b/src/runtime-rs/crates/resource/src/share_fs/mod.rs
@@ -5,30 +5,39 @@
//
mod share_virtio_fs;
+pub use share_virtio_fs::rafs_mount;
mod share_virtio_fs_inline;
use share_virtio_fs_inline::ShareVirtioFsInline;
mod share_virtio_fs_standalone;
use share_virtio_fs_standalone::ShareVirtioFsStandalone;
mod utils;
+use tokio::sync::Mutex;
+pub use utils::{do_get_guest_path, do_get_guest_share_path, get_host_rw_shared_path};
mod virtio_fs_share_mount;
use virtio_fs_share_mount::VirtiofsShareMount;
+pub use virtio_fs_share_mount::EPHEMERAL_PATH;
-use std::sync::Arc;
+use std::{collections::HashMap, fmt::Debug, path::PathBuf, sync::Arc};
use agent::Storage;
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, Context, Ok, Result};
use async_trait::async_trait;
use hypervisor::Hypervisor;
use kata_types::config::hypervisor::SharedFsInfo;
const VIRTIO_FS: &str = "virtio-fs";
+const _VIRTIO_FS_NYDUS: &str = "virtio-fs-nydus";
const INLINE_VIRTIO_FS: &str = "inline-virtio-fs";
const KATA_HOST_SHARED_DIR: &str = "/run/kata-containers/shared/sandboxes/";
+
+/// share fs (for example virtio-fs) mount path in the guest
const KATA_GUEST_SHARE_DIR: &str = "/run/kata-containers/shared/containers/";
+
pub(crate) const DEFAULT_KATA_GUEST_SANDBOX_DIR: &str = "/run/kata-containers/sandbox/";
-const PASSTHROUGH_FS_DIR: &str = "passthrough";
+pub const PASSTHROUGH_FS_DIR: &str = "passthrough";
+const RAFS_DIR: &str = "rafs";
#[async_trait]
pub trait ShareFs: Send + Sync {
@@ -36,31 +45,92 @@ pub trait ShareFs: Send + Sync {
async fn setup_device_before_start_vm(&self, h: &dyn Hypervisor) -> Result<()>;
async fn setup_device_after_start_vm(&self, h: &dyn Hypervisor) -> Result<()>;
async fn get_storages(&self) -> Result<Vec<Storage>>;
+ fn mounted_info_set(&self) -> Arc<Mutex<HashMap<String, MountedInfo>>>;
}
+#[derive(Debug, Clone)]
pub struct ShareFsRootfsConfig {
// TODO: for nydus v5/v6 need to update ShareFsMount
pub cid: String,
pub source: String,
pub target: String,
pub readonly: bool,
+ pub is_rafs: bool,
}
+#[derive(Debug)]
pub struct ShareFsVolumeConfig {
pub cid: String,
pub source: String,
pub target: String,
pub readonly: bool,
+ pub mount_options: Vec<String>,
+ pub mount: oci::Mount,
+ pub is_rafs: bool,
}
pub struct ShareFsMountResult {
pub guest_path: String,
+ pub storages: Vec<agent::Storage>,
+}
+
+/// Save mounted info for sandbox-level shared files.
+#[derive(Clone, Debug)]
+pub struct MountedInfo {
+ // Guest path
+ pub guest_path: PathBuf,
+ // Ref count of containers that uses this volume with read only permission
+ pub ro_ref_count: usize,
+ // Ref count of containers that uses this volume with read write permission
+ pub rw_ref_count: usize,
+}
+
+impl MountedInfo {
+ pub fn new(guest_path: PathBuf, readonly: bool) -> Self {
+ Self {
+ guest_path,
+ ro_ref_count: readonly.into(),
+ rw_ref_count: (!readonly).into(),
+ }
+ }
+
+ /// Check if the mount has read only permission
+ pub fn readonly(&self) -> bool {
+ self.rw_ref_count == 0
+ }
+
+ /// Ref count for all permissions
+ pub fn ref_count(&self) -> usize {
+ self.ro_ref_count + self.rw_ref_count
+ }
+
+ // File/dir name in the form of "sandbox-<uuid>-<file/dir name>"
+ pub fn file_name(&self) -> Result<String> {
+ match self.guest_path.file_name() {
+ Some(file_name) => match file_name.to_str() {
+ Some(file_name) => Ok(file_name.to_owned()),
+ None => Err(anyhow!("failed to get string from {:?}", file_name)),
+ },
+ None => Err(anyhow!(
+ "failed to get file name from the guest_path {:?}",
+ self.guest_path
+ )),
+ }
+ }
}
#[async_trait]
pub trait ShareFsMount: Send + Sync {
- async fn share_rootfs(&self, config: ShareFsRootfsConfig) -> Result<ShareFsMountResult>;
- async fn share_volume(&self, config: ShareFsVolumeConfig) -> Result<ShareFsMountResult>;
+ async fn share_rootfs(&self, config: &ShareFsRootfsConfig) -> Result<ShareFsMountResult>;
+ async fn share_volume(&self, config: &ShareFsVolumeConfig) -> Result<ShareFsMountResult>;
+ /// Upgrade to readwrite permission
+ async fn upgrade_to_rw(&self, file_name: &str) -> Result<()>;
+ /// Downgrade to readonly permission
+ async fn downgrade_to_ro(&self, file_name: &str) -> Result<()>;
+ /// Umount the volume
+ async fn umount_volume(&self, file_name: &str) -> Result<()>;
+ /// Umount the rootfs
+ async fn umount_rootfs(&self, config: &ShareFsRootfsConfig) -> Result<()>;
}
pub fn new(id: &str, config: &SharedFsInfo) -> Result<Arc<dyn ShareFs>> {
diff --git a/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs.rs b/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs.rs
index f1a5bc5fe..4aed2cc19 100644
--- a/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs.rs
+++ b/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs.rs
@@ -7,13 +7,15 @@
use std::path::Path;
use anyhow::{Context, Result};
-use hypervisor::{device, Hypervisor};
+use hypervisor::{
+ device::{Device as HypervisorDevice, ShareFsMountConfig, ShareFsMountType, ShareFsOperation},
+ Hypervisor, ShareFsDeviceConfig,
+};
use kata_sys_util::mount;
-use super::utils;
+use super::{utils, PASSTHROUGH_FS_DIR};
pub(crate) const MOUNT_GUEST_TAG: &str = "kataShared";
-pub(crate) const PASSTHROUGH_FS_DIR: &str = "passthrough";
pub(crate) const FS_TYPE_VIRTIO_FS: &str = "virtiofs";
pub(crate) const KATA_VIRTIO_FS_DEV_TYPE: &str = "virtio-fs";
@@ -40,7 +42,7 @@ pub(crate) async fn prepare_virtiofs(
mount::bind_mount_unchecked(&host_rw_dest, &host_ro_dest, true)
.context("bind mount shared_fs directory")?;
- let share_fs_device = device::Device::ShareFsDevice(device::ShareFsDeviceConfig {
+ let share_fs_device = HypervisorDevice::ShareFsDevice(ShareFsDeviceConfig {
sock_path: generate_sock_path(root),
mount_tag: String::from(MOUNT_GUEST_TAG),
host_path: String::from(host_ro_dest.to_str().unwrap()),
@@ -51,3 +53,55 @@ pub(crate) async fn prepare_virtiofs(
h.add_device(share_fs_device).await.context("add device")?;
Ok(())
}
+
+pub(crate) async fn setup_inline_virtiofs(id: &str, h: &dyn Hypervisor) -> Result<()> {
+ // - source is the absolute path of PASSTHROUGH_FS_DIR on host, e.g.
+ // /run/kata-containers/shared/sandboxes/<sid>/passthrough
+ // - mount point is the path relative to KATA_GUEST_SHARE_DIR in guest
+ let mnt = format!("/{}", PASSTHROUGH_FS_DIR);
+
+ let rw_source = utils::get_host_rw_shared_path(id).join(PASSTHROUGH_FS_DIR);
+ utils::ensure_dir_exist(&rw_source).context("ensure directory exist")?;
+
+ let ro_source = utils::get_host_ro_shared_path(id).join(PASSTHROUGH_FS_DIR);
+ let source = String::from(ro_source.to_str().unwrap());
+
+ let virtio_fs = HypervisorDevice::ShareFsMount(ShareFsMountConfig {
+ source: source.clone(),
+ fstype: ShareFsMountType::PASSTHROUGH,
+ mount_point: mnt,
+ config: None,
+ tag: String::from(MOUNT_GUEST_TAG),
+ op: ShareFsOperation::Mount,
+ prefetch_list_path: None,
+ });
+ h.add_device(virtio_fs)
+ .await
+ .with_context(|| format!("fail to attach passthrough fs {:?}", source))
+}
+
+pub async fn rafs_mount(
+ h: &dyn Hypervisor,
+ rafs_meta: String,
+ rafs_mnt: String,
+ config_content: String,
+ prefetch_list_path: Option<String>,
+) -> Result<()> {
+ info!(
+ sl!(),
+ "Attaching rafs meta file {} to virtio-fs device, rafs mount point {}", rafs_meta, rafs_mnt
+ );
+ let virtio_fs = HypervisorDevice::ShareFsMount(ShareFsMountConfig {
+ source: rafs_meta.clone(),
+ fstype: ShareFsMountType::RAFS,
+ mount_point: rafs_mnt,
+ config: Some(config_content),
+ tag: String::from(MOUNT_GUEST_TAG),
+ op: ShareFsOperation::Mount,
+ prefetch_list_path,
+ });
+ h.add_device(virtio_fs)
+ .await
+ .with_context(|| format!("fail to attach rafs {:?}", rafs_meta))?;
+ Ok(())
+}
diff --git a/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_inline.rs b/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_inline.rs
index e3967b8ce..5dddefbfd 100644
--- a/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_inline.rs
+++ b/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_inline.rs
@@ -4,21 +4,21 @@
// SPDX-License-Identifier: Apache-2.0
//
+use std::collections::HashMap;
+
use agent::Storage;
use anyhow::{Context, Result};
use async_trait::async_trait;
-use hypervisor::{
- device::{Device as HypervisorDevice, ShareFsMountConfig, ShareFsMountType, ShareFsOperation},
- Hypervisor,
-};
+use hypervisor::Hypervisor;
use kata_types::config::hypervisor::SharedFsInfo;
+use tokio::sync::Mutex;
use super::{
share_virtio_fs::{
- prepare_virtiofs, FS_TYPE_VIRTIO_FS, KATA_VIRTIO_FS_DEV_TYPE, MOUNT_GUEST_TAG,
- PASSTHROUGH_FS_DIR,
+ prepare_virtiofs, setup_inline_virtiofs, FS_TYPE_VIRTIO_FS, KATA_VIRTIO_FS_DEV_TYPE,
+ MOUNT_GUEST_TAG,
},
- utils, ShareFs, *,
+ ShareFs, *,
};
lazy_static! {
@@ -33,6 +33,7 @@ pub struct ShareVirtioFsInlineConfig {
pub struct ShareVirtioFsInline {
config: ShareVirtioFsInlineConfig,
share_fs_mount: Arc<dyn ShareFsMount>,
+ mounted_info_set: Arc<Mutex<HashMap<String, MountedInfo>>>,
}
impl ShareVirtioFsInline {
@@ -40,6 +41,7 @@ impl ShareVirtioFsInline {
Ok(Self {
config: ShareVirtioFsInlineConfig { id: id.to_string() },
share_fs_mount: Arc::new(VirtiofsShareMount::new(id)),
+ mounted_info_set: Arc::new(Mutex::new(HashMap::new())),
})
}
}
@@ -80,30 +82,8 @@ impl ShareFs for ShareVirtioFsInline {
storages.push(shared_volume);
Ok(storages)
}
-}
-
-async fn setup_inline_virtiofs(id: &str, h: &dyn Hypervisor) -> Result<()> {
- // - source is the absolute path of PASSTHROUGH_FS_DIR on host, e.g.
- // /run/kata-containers/shared/sandboxes/<sid>/passthrough
- // - mount point is the path relative to KATA_GUEST_SHARE_DIR in guest
- let mnt = format!("/{}", PASSTHROUGH_FS_DIR);
- let rw_source = utils::get_host_rw_shared_path(id).join(PASSTHROUGH_FS_DIR);
- utils::ensure_dir_exist(&rw_source)?;
-
- let ro_source = utils::get_host_ro_shared_path(id).join(PASSTHROUGH_FS_DIR);
- let source = String::from(ro_source.to_str().unwrap());
-
- let virtio_fs = HypervisorDevice::ShareFsMount(ShareFsMountConfig {
- source: source.clone(),
- fstype: ShareFsMountType::PASSTHROUGH,
- mount_point: mnt,
- config: None,
- tag: String::from(MOUNT_GUEST_TAG),
- op: ShareFsOperation::Mount,
- prefetch_list_path: None,
- });
- h.add_device(virtio_fs)
- .await
- .context(format!("fail to attach passthrough fs {:?}", source))
+ fn mounted_info_set(&self) -> Arc<Mutex<HashMap<String, MountedInfo>>> {
+ self.mounted_info_set.clone()
+ }
}
diff --git a/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_standalone.rs b/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_standalone.rs
index 9c798d746..e663cc029 100644
--- a/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_standalone.rs
+++ b/src/runtime-rs/crates/resource/src/share_fs/share_virtio_fs_standalone.rs
@@ -4,8 +4,12 @@
// SPDX-License-Identifier: Apache-2.0
//
-use std::{process::Stdio, sync::Arc};
+use std::{collections::HashMap, process::Stdio, sync::Arc};
+use crate::share_fs::share_virtio_fs::{
+ prepare_virtiofs, FS_TYPE_VIRTIO_FS, KATA_VIRTIO_FS_DEV_TYPE, MOUNT_GUEST_TAG,
+};
+use crate::share_fs::{KATA_GUEST_SHARE_DIR, VIRTIO_FS};
use agent::Storage;
use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
@@ -16,19 +20,18 @@ use tokio::{
process::{Child, Command},
sync::{
mpsc::{channel, Receiver, Sender},
- RwLock,
+ Mutex, RwLock,
},
};
use super::{
- share_virtio_fs::generate_sock_path, utils::get_host_ro_shared_path,
- virtio_fs_share_mount::VirtiofsShareMount, ShareFs, ShareFsMount,
+ share_virtio_fs::generate_sock_path, utils::ensure_dir_exist, utils::get_host_ro_shared_path,
+ virtio_fs_share_mount::VirtiofsShareMount, MountedInfo, ShareFs, ShareFsMount,
};
#[derive(Debug, Clone)]
pub struct ShareVirtioFsStandaloneConfig {
id: String,
- jail_root: String,
// virtio_fs_daemon is the virtio-fs vhost-user daemon path
pub virtio_fs_daemon: String,
@@ -38,46 +41,51 @@ pub struct ShareVirtioFsStandaloneConfig {
pub virtio_fs_extra_args: Vec<String>,
}
-#[derive(Default)]
+#[derive(Default, Debug)]
struct ShareVirtioFsStandaloneInner {
pid: Option<u32>,
}
+
pub(crate) struct ShareVirtioFsStandalone {
inner: Arc<RwLock<ShareVirtioFsStandaloneInner>>,
config: ShareVirtioFsStandaloneConfig,
share_fs_mount: Arc<dyn ShareFsMount>,
+ mounted_info_set: Arc<Mutex<HashMap<String, MountedInfo>>>,
}
impl ShareVirtioFsStandalone {
- pub(crate) fn new(id: &str, _config: &SharedFsInfo) -> Result<Self> {
+ pub(crate) fn new(id: &str, config: &SharedFsInfo) -> Result<Self> {
Ok(Self {
inner: Arc::new(RwLock::new(ShareVirtioFsStandaloneInner::default())),
- // TODO: update with config
config: ShareVirtioFsStandaloneConfig {
id: id.to_string(),
- jail_root: "".to_string(),
- virtio_fs_daemon: "".to_string(),
- virtio_fs_cache: "".to_string(),
- virtio_fs_extra_args: vec![],
+ virtio_fs_daemon: config.virtio_fs_daemon.clone(),
+ virtio_fs_cache: config.virtio_fs_cache.clone(),
+ virtio_fs_extra_args: config.virtio_fs_extra_args.clone(),
},
share_fs_mount: Arc::new(VirtiofsShareMount::new(id)),
+ mounted_info_set: Arc::new(Mutex::new(HashMap::new())),
})
}
fn virtiofsd_args(&self, sock_path: &str) -> Result<Vec<String>> {
let source_path = get_host_ro_shared_path(&self.config.id);
- if !source_path.exists() {
- return Err(anyhow!("The virtiofs shared path didn't exist"));
- }
+ ensure_dir_exist(&source_path)?;
+ let shared_dir = source_path
+ .to_str()
+ .ok_or_else(|| anyhow!("convert source path {:?} to str failed", source_path))?;
let mut args: Vec<String> = vec![
- String::from("-f"),
- String::from("-o"),
- format!("vhost_user_socket={}", sock_path),
- String::from("-o"),
- format!("source={}", source_path.to_str().unwrap()),
- String::from("-o"),
- format!("cache={}", self.config.virtio_fs_cache),
+ String::from("--socket-path"),
+ String::from(sock_path),
+ String::from("--shared-dir"),
+ String::from(shared_dir),
+ String::from("--cache"),
+ self.config.virtio_fs_cache.clone(),
+ String::from("--sandbox"),
+ String::from("none"),
+ String::from("--seccomp"),
+ String::from("none"),
];
if !self.config.virtio_fs_extra_args.is_empty() {
@@ -88,8 +96,8 @@ impl ShareVirtioFsStandalone {
Ok(args)
}
- async fn setup_virtiofsd(&self) -> Result<()> {
- let sock_path = generate_sock_path(&self.config.jail_root);
+ async fn setup_virtiofsd(&self, h: &dyn Hypervisor) -> Result<()> {
+ let sock_path = generate_sock_path(&h.get_jailer_root().await?);
let args = self.virtiofsd_args(&sock_path).context("virtiofsd args")?;
let mut cmd = Command::new(&self.config.virtio_fs_daemon);
@@ -164,8 +172,11 @@ impl ShareFs for ShareVirtioFsStandalone {
self.share_fs_mount.clone()
}
- async fn setup_device_before_start_vm(&self, _h: &dyn Hypervisor) -> Result<()> {
- self.setup_virtiofsd().await.context("setup virtiofsd")?;
+ async fn setup_device_before_start_vm(&self, h: &dyn Hypervisor) -> Result<()> {
+ prepare_virtiofs(h, VIRTIO_FS, &self.config.id, &h.get_jailer_root().await?)
+ .await
+ .context("prepare virtiofs")?;
+ self.setup_virtiofsd(h).await.context("setup virtiofsd")?;
Ok(())
}
@@ -174,6 +185,23 @@ impl ShareFs for ShareVirtioFsStandalone {
}
async fn get_storages(&self) -> Result<Vec<Storage>> {
- Ok(vec![])
+ let mut storages: Vec<Storage> = Vec::new();
+
+ let shared_volume: Storage = Storage {
+ driver: String::from(KATA_VIRTIO_FS_DEV_TYPE),
+ driver_options: Vec::new(),
+ source: String::from(MOUNT_GUEST_TAG),
+ fs_type: String::from(FS_TYPE_VIRTIO_FS),
+ fs_group: None,
+ options: vec![String::from("nodev")],
+ mount_point: String::from(KATA_GUEST_SHARE_DIR),
+ };
+
+ storages.push(shared_volume);
+ Ok(storages)
+ }
+
+ fn mounted_info_set(&self) -> Arc<Mutex<HashMap<String, MountedInfo>>> {
+ self.mounted_info_set.clone()
}
}
diff --git a/src/runtime-rs/crates/resource/src/share_fs/utils.rs b/src/runtime-rs/crates/resource/src/share_fs/utils.rs
index fbdf93f78..6288e860e 100644
--- a/src/runtime-rs/crates/resource/src/share_fs/utils.rs
+++ b/src/runtime-rs/crates/resource/src/share_fs/utils.rs
@@ -18,6 +18,7 @@ pub(crate) fn ensure_dir_exist(path: &Path) -> Result<()> {
Ok(())
}
+/// Bind mount the original path to the runtime directory.
pub(crate) fn share_to_guest(
// absolute path for source
source: &str,
@@ -27,6 +28,7 @@ pub(crate) fn share_to_guest(
cid: &str,
readonly: bool,
is_volume: bool,
+ is_rafs: bool,
) -> Result<String> {
let host_dest = do_get_host_path(target, sid, cid, is_volume, false);
mount::bind_mount_unchecked(source, &host_dest, readonly)
@@ -36,22 +38,39 @@ pub(crate) fn share_to_guest(
// to remount the read only dir mount point directly.
if readonly {
let dst = do_get_host_path(target, sid, cid, is_volume, true);
- mount::bind_remount_read_only(&dst).context("bind remount readonly")?;
+ mount::bind_remount(dst, readonly).context("bind remount readonly")?;
}
- Ok(do_get_guest_path(target, cid, is_volume))
+ Ok(do_get_guest_path(target, cid, is_volume, is_rafs))
}
-
+// Shared path handling:
+// 1. create two directories for each sandbox:
+// -. /run/kata-containers/shared/sandboxes/$sbx_id/rw/, a host/guest shared directory which is rw
+// -. /run/kata-containers/shared/sandboxes/$sbx_id/ro/, a host/guest shared directory (virtiofs source dir) which is ro
+//
+// 2. /run/kata-containers/shared/sandboxes/$sbx_id/rw/ is bind mounted readonly to /run/kata-containers/shared/sandboxes/$sbx_id/ro/, so guest cannot modify it
+//
+// 3. host-guest shared files/directories are mounted one-level under /run/kata-containers/shared/sandboxes/$sbx_id/rw/passthrough and thus present to guest at one level under run/kata-containers/shared/containers/passthrough.
pub(crate) fn get_host_ro_shared_path(id: &str) -> PathBuf {
Path::new(KATA_HOST_SHARED_DIR).join(id).join("ro")
}
-pub(crate) fn get_host_rw_shared_path(id: &str) -> PathBuf {
- Path::new(KATA_HOST_SHARED_DIR).join(id).join("rw")
+pub fn get_host_rw_shared_path(sid: &str) -> PathBuf {
+ Path::new(KATA_HOST_SHARED_DIR).join(sid).join("rw")
}
-fn do_get_guest_any_path(target: &str, cid: &str, is_volume: bool, is_virtiofs: bool) -> String {
- let dir = PASSTHROUGH_FS_DIR;
+fn do_get_guest_any_path(
+ target: &str,
+ cid: &str,
+ is_volume: bool,
+ is_rafs: bool,
+ is_virtiofs: bool,
+) -> String {
+ let dir = if is_rafs {
+ RAFS_DIR
+ } else {
+ PASSTHROUGH_FS_DIR
+ };
let guest_share_dir = if is_virtiofs {
Path::new("/").to_path_buf()
} else {
@@ -66,11 +85,15 @@ fn do_get_guest_any_path(target: &str, cid: &str, is_volume: bool, is_virtiofs:
path.to_str().unwrap().to_string()
}
-fn do_get_guest_path(target: &str, cid: &str, is_volume: bool) -> String {
- do_get_guest_any_path(target, cid, is_volume, false)
+pub fn do_get_guest_path(target: &str, cid: &str, is_volume: bool, is_rafs: bool) -> String {
+ do_get_guest_any_path(target, cid, is_volume, is_rafs, false)
+}
+
+pub fn do_get_guest_share_path(target: &str, cid: &str, is_rafs: bool) -> String {
+ do_get_guest_any_path(target, cid, false, is_rafs, true)
}
-fn do_get_host_path(
+pub(crate) fn do_get_host_path(
target: &str,
sid: &str,
cid: &str,
diff --git a/src/runtime-rs/crates/resource/src/share_fs/virtio_fs_share_mount.rs b/src/runtime-rs/crates/resource/src/share_fs/virtio_fs_share_mount.rs
index 1f1abdb1c..27fb47972 100644
--- a/src/runtime-rs/crates/resource/src/share_fs/virtio_fs_share_mount.rs
+++ b/src/runtime-rs/crates/resource/src/share_fs/virtio_fs_share_mount.rs
@@ -4,11 +4,28 @@
// SPDX-License-Identifier: Apache-2.0
//
-use anyhow::{Context, Result};
+use agent::Storage;
+use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
+use kata_sys_util::mount::{bind_remount, umount_timeout};
+use kata_types::k8s::is_watchable_mount;
+use kata_types::mount;
+use nix::sys::stat::stat;
+use std::fs;
+use std::os::unix::fs::PermissionsExt;
+use std::path::Path;
-use super::{utils, ShareFsMount, ShareFsMountResult, ShareFsRootfsConfig, ShareFsVolumeConfig};
+const WATCHABLE_PATH_NAME: &str = "watchable";
+const WATCHABLE_BIND_DEV_TYPE: &str = "watchable-bind";
+pub const EPHEMERAL_PATH: &str = "/run/kata-containers/sandbox/ephemeral";
+use super::{
+ utils::{self, do_get_host_path},
+ ShareFsMount, ShareFsMountResult, ShareFsRootfsConfig, ShareFsVolumeConfig,
+ KATA_GUEST_SHARE_DIR, PASSTHROUGH_FS_DIR,
+};
+
+#[derive(Debug)]
pub struct VirtiofsShareMount {
id: String,
}
@@ -21,7 +38,7 @@ impl VirtiofsShareMount {
#[async_trait]
impl ShareFsMount for VirtiofsShareMount {
- async fn share_rootfs(&self, config: ShareFsRootfsConfig) -> Result<ShareFsMountResult> {
+ async fn share_rootfs(&self, config: &ShareFsRootfsConfig) -> Result<ShareFsMountResult> {
// TODO: select virtiofs or support nydus
let guest_path = utils::share_to_guest(
&config.source,
@@ -30,21 +47,181 @@ impl ShareFsMount for VirtiofsShareMount {
&config.cid,
config.readonly,
false,
+ config.is_rafs,
)
.context("share to guest")?;
- Ok(ShareFsMountResult { guest_path })
+ Ok(ShareFsMountResult {
+ guest_path,
+ storages: vec![],
+ })
}
- async fn share_volume(&self, config: ShareFsVolumeConfig) -> Result<ShareFsMountResult> {
- let guest_path = utils::share_to_guest(
+ async fn share_volume(&self, config: &ShareFsVolumeConfig) -> Result<ShareFsMountResult> {
+ let mut guest_path = utils::share_to_guest(
&config.source,
&config.target,
&self.id,
&config.cid,
config.readonly,
true,
+ config.is_rafs,
)
.context("share to guest")?;
- Ok(ShareFsMountResult { guest_path })
+
+ // watchable mounts
+ if is_watchable_mount(&config.source) {
+ // Create path in shared directory for creating watchable mount:
+ let host_rw_path = utils::get_host_rw_shared_path(&self.id);
+
+ // "/run/kata-containers/shared/sandboxes/$sid/rw/passthrough/watchable"
+ let watchable_host_path = Path::new(&host_rw_path)
+ .join(PASSTHROUGH_FS_DIR)
+ .join(WATCHABLE_PATH_NAME);
+
+ fs::create_dir_all(&watchable_host_path).context(format!(
+ "unable to create watchable path: {:?}",
+ &watchable_host_path,
+ ))?;
+
+ fs::set_permissions(watchable_host_path, fs::Permissions::from_mode(0o750))?;
+
+ // path: /run/kata-containers/shared/containers/passthrough/watchable/config-map-name
+ let file_name = Path::new(&guest_path)
+ .file_name()
+ .context("get file name from guest path")?;
+ let watchable_guest_mount = Path::new(KATA_GUEST_SHARE_DIR)
+ .join(PASSTHROUGH_FS_DIR)
+ .join(WATCHABLE_PATH_NAME)
+ .join(file_name)
+ .into_os_string()
+ .into_string()
+ .map_err(|e| anyhow!("failed to get watchable guest mount path {:?}", e))?;
+
+ let watchable_storage: Storage = Storage {
+ driver: String::from(WATCHABLE_BIND_DEV_TYPE),
+ driver_options: Vec::new(),
+ source: guest_path,
+ fs_type: String::from("bind"),
+ fs_group: None,
+ options: config.mount_options.clone(),
+ mount_point: watchable_guest_mount.clone(),
+ };
+
+ // Update the guest_path, in order to identify what will
+ // change in the OCI spec.
+ guest_path = watchable_guest_mount;
+
+ let storages = vec![watchable_storage];
+
+ return Ok(ShareFsMountResult {
+ guest_path,
+ storages,
+ });
+ } else if config.mount.r#type == mount::KATA_EPHEMERAL_VOLUME_TYPE {
+ // refer to the golang `handleEphemeralStorage` code at
+ // https://github.com/kata-containers/kata-containers/blob/9516286f6dd5cfd6b138810e5d7c9e01cf6fc043/src/runtime/virtcontainers/kata_agent.go#L1354
+
+ let source = &config.mount.source;
+ let file_stat =
+ stat(Path::new(source)).with_context(|| format!("mount source {}", source))?;
+
+ // if volume's gid isn't root group(default group), this means there's
+ // an specific fsGroup is set on this local volume, then it should pass
+ // to guest.
+ let dir_options = if file_stat.st_gid != 0 {
+ vec![format!("fsgid={}", file_stat.st_gid)]
+ } else {
+ vec![]
+ };
+
+ let file_name = Path::new(source)
+ .file_name()
+ .context("get file name from mount.source")?;
+ let source = Path::new(EPHEMERAL_PATH)
+ .join(file_name)
+ .into_os_string()
+ .into_string()
+ .map_err(|e| anyhow!("failed to get ephemeral path {:?}", e))?;
+
+ // Create a storage struct so that kata agent is able to create
+ // tmpfs backed volume inside the VM
+ let ephemeral_storage = agent::Storage {
+ driver: String::from(mount::KATA_EPHEMERAL_VOLUME_TYPE),
+ driver_options: Vec::new(),
+ source: String::from("tmpfs"),
+ fs_type: String::from("tmpfs"),
+ fs_group: None,
+ options: dir_options,
+ mount_point: source.clone(),
+ };
+
+ guest_path = source;
+ let storages = vec![ephemeral_storage];
+
+ return Ok(ShareFsMountResult {
+ guest_path,
+ storages,
+ });
+ }
+
+ Ok(ShareFsMountResult {
+ guest_path,
+ storages: vec![],
+ })
+ }
+
+ async fn upgrade_to_rw(&self, file_name: &str) -> Result<()> {
+ // Remount readonly directory with readwrite permission
+ let host_dest = do_get_host_path(file_name, &self.id, "", true, true);
+ bind_remount(host_dest, false)
+ .context("remount readonly directory with readwrite permission")?;
+ // Remount readwrite directory with readwrite permission
+ let host_dest = do_get_host_path(file_name, &self.id, "", true, false);
+ bind_remount(host_dest, false)
+ .context("remount readwrite directory with readwrite permission")?;
+ Ok(())
+ }
+
+ async fn downgrade_to_ro(&self, file_name: &str) -> Result<()> {
+ // Remount readwrite directory with readonly permission
+ let host_dest = do_get_host_path(file_name, &self.id, "", true, false);
+ bind_remount(host_dest, true)
+ .context("remount readwrite directory with readonly permission")?;
+ // Remount readonly directory with readonly permission
+ let host_dest = do_get_host_path(file_name, &self.id, "", true, true);
+ bind_remount(host_dest, true)
+ .context("remount readonly directory with readonly permission")?;
+ Ok(())
+ }
+
+ async fn umount_volume(&self, file_name: &str) -> Result<()> {
+ let host_dest = do_get_host_path(file_name, &self.id, "", true, false);
+ umount_timeout(&host_dest, 0).context("umount volume")?;
+ // Umount event will be propagated to ro directory
+
+ // Remove the directory of mointpoint
+ if let Ok(md) = fs::metadata(&host_dest) {
+ if md.is_file() {
+ fs::remove_file(&host_dest).context("remove the volume mount point as a file")?;
+ }
+ if md.is_dir() {
+ fs::remove_dir(&host_dest).context("remove the volume mount point as a dir")?;
+ }
+ }
+ Ok(())
+ }
+
+ async fn umount_rootfs(&self, config: &ShareFsRootfsConfig) -> Result<()> {
+ let host_dest = do_get_host_path(&config.target, &self.id, &config.cid, false, false);
+ umount_timeout(&host_dest, 0).context("umount rootfs")?;
+
+ // Remove the directory of mointpoint
+ if let Ok(md) = fs::metadata(&host_dest) {
+ if md.is_dir() {
+ fs::remove_dir(&host_dest).context("remove the rootfs mount point as a dir")?;
+ }
+ }
+
+ Ok(())
}
}
diff --git a/src/runtime-rs/crates/resource/src/volume/block_volume.rs b/src/runtime-rs/crates/resource/src/volume/block_volume.rs
index f015c9278..da8ef03f9 100644
--- a/src/runtime-rs/crates/resource/src/volume/block_volume.rs
+++ b/src/runtime-rs/crates/resource/src/volume/block_volume.rs
@@ -5,9 +5,11 @@
//
use anyhow::Result;
+use async_trait::async_trait;
use super::Volume;
+#[derive(Debug)]
pub(crate) struct BlockVolume {}
/// BlockVolume: block device volume
@@ -17,6 +19,7 @@ impl BlockVolume {
}
}
+#[async_trait]
impl Volume for BlockVolume {
fn get_volume_mount(&self) -> anyhow::Result<Vec<oci::Mount>> {
todo!()
@@ -26,8 +29,10 @@ impl Volume for BlockVolume {
todo!()
}
- fn cleanup(&self) -> Result<()> {
- todo!()
+ async fn cleanup(&self) -> Result<()> {
+ // TODO: Clean up BlockVolume
+ warn!(sl!(), "Cleaning up BlockVolume is still unimplemented.");
+ Ok(())
}
}
diff --git a/src/runtime-rs/crates/resource/src/volume/default_volume.rs b/src/runtime-rs/crates/resource/src/volume/default_volume.rs
index 3b7752a4e..8855a8e03 100644
--- a/src/runtime-rs/crates/resource/src/volume/default_volume.rs
+++ b/src/runtime-rs/crates/resource/src/volume/default_volume.rs
@@ -5,9 +5,11 @@
//
use anyhow::Result;
+use async_trait::async_trait;
use super::Volume;
+#[derive(Debug)]
pub(crate) struct DefaultVolume {
mount: oci::Mount,
}
@@ -21,6 +23,7 @@ impl DefaultVolume {
}
}
+#[async_trait]
impl Volume for DefaultVolume {
fn get_volume_mount(&self) -> anyhow::Result<Vec<oci::Mount>> {
Ok(vec![self.mount.clone()])
@@ -30,7 +33,9 @@ impl Volume for DefaultVolume {
Ok(vec![])
}
- fn cleanup(&self) -> Result<()> {
- todo!()
+ async fn cleanup(&self) -> Result<()> {
+ // TODO: Clean up DefaultVolume
+ warn!(sl!(), "Cleaning up DefaultVolume is still unimplemented.");
+ Ok(())
}
}
diff --git a/src/runtime-rs/crates/resource/src/volume/hugepage.rs b/src/runtime-rs/crates/resource/src/volume/hugepage.rs
new file mode 100644
index 000000000..a827b2657
--- /dev/null
+++ b/src/runtime-rs/crates/resource/src/volume/hugepage.rs
@@ -0,0 +1,223 @@
+// Copyright (c) 2019-2022 Alibaba Cloud
+// Copyright (c) 2019-2022 Ant Group
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+
+use std::{
+ collections::HashMap,
+ fs::File,
+ io::{BufRead, BufReader},
+};
+
+use crate::share_fs::EPHEMERAL_PATH;
+use agent::Storage;
+use anyhow::{anyhow, Context, Ok, Result};
+use async_trait::async_trait;
+use byte_unit::Byte;
+use hypervisor::HUGETLBFS;
+use kata_sys_util::{fs::get_base_name, mount::PROC_MOUNTS_FILE};
+use kata_types::mount::KATA_EPHEMERAL_VOLUME_TYPE;
+
+use super::{Volume, BIND};
+
+type PageSize = Byte;
+type Limit = u64;
+
+const NODEV: &str = "nodev";
+
+// container hugepage
+pub(crate) struct Hugepage {
+ // storage info
+ storage: Option<Storage>,
+ // mount info
+ mount: oci::Mount,
+}
+
+// handle hugepage
+impl Hugepage {
+ pub(crate) fn new(
+ mount: &oci::Mount,
+ hugepage_limits_map: HashMap<PageSize, Limit>,
+ fs_options: Vec<String>,
+ ) -> Result<Self> {
+ // Create mount option string
+ let page_size = get_page_size(fs_options).context("failed to get page size")?;
+ let option = hugepage_limits_map
+ .get(&page_size)
+ .map(|limit| format!("pagesize={},size={}", page_size.get_bytes(), limit))
+ .context("failed to get hugepage option")?;
+ let base_name = get_base_name(mount.source.clone())?
+ .into_string()
+ .map_err(|e| anyhow!("failed to convert to string{:?}", e))?;
+ let mut mount = mount.clone();
+ // Set the mount source path to a path that resides inside the VM
+ mount.source = format!("{}{}{}", EPHEMERAL_PATH, "/", base_name);
+ // Set the mount type to "bind"
+ mount.r#type = BIND.to_string();
+
+ // Create a storage struct so that kata agent is able to create
+ // hugetlbfs backed volume inside the VM
+ let storage = Storage {
+ driver: KATA_EPHEMERAL_VOLUME_TYPE.to_string(),
+ source: NODEV.to_string(),
+ fs_type: HUGETLBFS.to_string(),
+ mount_point: mount.source.clone(),
+ options: vec![option],
+ ..Default::default()
+ };
+ Ok(Self {
+ storage: Some(storage),
+ mount,
+ })
+ }
+}
+
+#[async_trait]
+impl Volume for Hugepage {
+ fn get_volume_mount(&self) -> Result<Vec<oci::Mount>> {
+ Ok(vec![self.mount.clone()])
+ }
+
+ fn get_storage(&self) -> Result<Vec<agent::Storage>> {
+ let s = if let Some(s) = self.storage.as_ref() {
+ vec![s.clone()]
+ } else {
+ vec![]
+ };
+ Ok(s)
+ }
+
+ async fn cleanup(&self) -> Result<()> {
+ Ok(())
+ }
+}
+
+pub(crate) fn get_huge_page_option(m: &oci::Mount) -> Result<Option<Vec<String>>> {
+ if m.source.is_empty() {
+ return Err(anyhow!("empty mount source"));
+ }
+ let file = File::open(PROC_MOUNTS_FILE).context("failed open file")?;
+ let reader = BufReader::new(file);
+ for line in reader.lines().flatten() {
+ let items: Vec<&str> = line.split(' ').collect();
+ if m.source == items[1] && items[2] == HUGETLBFS {
+ let fs_options: Vec<&str> = items[3].split(',').collect();
+ return Ok(Some(
+ fs_options
+ .iter()
+ .map(|&s| s.to_string())
+ .collect::<Vec<String>>(),
+ ));
+ }
+ }
+ Ok(None)
+}
+
+// TODO add hugepage limit to sandbox memory once memory hotplug is enabled
+// https://github.com/kata-containers/kata-containers/issues/5880
+pub(crate) fn get_huge_page_limits_map(spec: &oci::Spec) -> Result<HashMap<PageSize, Limit>> {
+ let mut hugepage_limits_map: HashMap<PageSize, Limit> = HashMap::new();
+ if let Some(l) = &spec.linux {
+ if let Some(r) = &l.resources {
+ let hugepage_limits = r.hugepage_limits.clone();
+ for hugepage_limit in hugepage_limits {
+ // the pagesize send from oci spec is MB or GB, change it to Mi and Gi
+ let page_size = hugepage_limit.page_size.replace('B', "i");
+ let page_size = Byte::from_str(page_size)
+ .context("failed to create Byte object from String")?;
+ hugepage_limits_map.insert(page_size, hugepage_limit.limit);
+ }
+ return Ok(hugepage_limits_map);
+ }
+ return Ok(hugepage_limits_map);
+ }
+ Ok(hugepage_limits_map)
+}
+
+fn get_page_size(fs_options: Vec<String>) -> Result<Byte> {
+ for fs_option in fs_options {
+ if fs_option.starts_with("pagesize=") {
+ let page_size = fs_option
+ .strip_prefix("pagesize=")
+ // the parameters passed are in unit M or G, append i to be Mi and Gi
+ .map(|s| format!("{}i", s))
+ .context("failed to strip prefix pagesize")?;
+ return Byte::from_str(page_size)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment