mirror of
https://github.com/aljazceru/kata-containers.git
synced 2026-02-23 07:24:24 +01:00
Merge pull request #5328 from GeorginaKin/CCv0
CCv0: Merge main into CCv0 branch
This commit is contained in:
36
.github/workflows/kata-deploy-test.yaml
vendored
36
.github/workflows/kata-deploy-test.yaml
vendored
@@ -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/is-organization-member@1.0.1
|
||||
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}
|
||||
@@ -53,8 +59,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:
|
||||
@@ -89,8 +99,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:
|
||||
@@ -116,8 +130,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,6 +117,7 @@ The table below lists the core parts of the project:
|
||||
| Component | Type | Description |
|
||||
|-|-|-|
|
||||
| [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 |
|
||||
|
||||
@@ -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:
|
||||
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:
|
||||
|
||||
`/usr/share/defaults/kata-containers/configuration.toml` and comment out the `image` line with the following. 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,7 +80,7 @@ rootfs `image`(100MB+).
|
||||
|
||||
Enable seccomp as follows:
|
||||
|
||||
```
|
||||
```bash
|
||||
$ sudo sed -i '/^disable_guest_seccomp/ s/true/false/' /etc/kata-containers/configuration.toml
|
||||
```
|
||||
|
||||
@@ -100,9 +90,7 @@ This will pass container seccomp profiles to the kata agent.
|
||||
|
||||
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 +163,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 +188,7 @@ RateLimitBurst=0
|
||||
|
||||
Restart `systemd-journald` for the changes to take effect:
|
||||
|
||||
```sh
|
||||
```bash
|
||||
$ sudo systemctl restart systemd-journald
|
||||
```
|
||||
|
||||
@@ -214,25 +202,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 +227,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 +234,26 @@ 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.
|
||||
|
||||
```
|
||||
$ 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:**
|
||||
@@ -287,17 +269,18 @@ $ 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
|
||||
|
||||
```
|
||||
$ 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}'
|
||||
```bash
|
||||
$ pushd kata-containers/tools/osbuilder/image-builder
|
||||
$ script -fec 'sudo -E USE_DOCKER=true ./image_builder.sh "${ROOTFS_DIR}"'
|
||||
$ popd
|
||||
```
|
||||
|
||||
> **Notes:**
|
||||
@@ -313,21 +296,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 +323,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 +339,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 +382,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 +430,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-static-virtiofsd.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 +487,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 +504,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 +515,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 +577,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 +595,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 +607,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 +618,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 +631,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 +652,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 +665,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 +673,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 +682,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 +695,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
|
||||
```
|
||||
|
||||
|
||||
@@ -81,31 +81,31 @@ In our case, there will be a variety of resources, and every resource has severa
|
||||
- Stage 2 (September): support common features
|
||||
- Stage 3: support full features
|
||||
|
||||
| **Class** | **Sub-Class** | **Development Stage** |
|
||||
| -------------------------- | ------------------- | --------------------- |
|
||||
| Service | task service | Stage 1 |
|
||||
| | extend service | Stage 3 |
|
||||
| | image service | Stage 3 |
|
||||
| Runtime handler | `Virt-Container` | Stage 1 |
|
||||
| | `Wasm-Container` | Stage 3 |
|
||||
| | `Linux-Container` | Stage 3 |
|
||||
| Endpoint | VETH Endpoint | Stage 1 |
|
||||
| | Physical Endpoint | Stage 2 |
|
||||
| | Tap Endpoint | Stage 2 |
|
||||
| | `Tuntap` Endpoint | Stage 2 |
|
||||
| | `IPVlan` Endpoint | Stage 3 |
|
||||
| | `MacVlan` Endpoint | Stage 3 |
|
||||
| | MACVTAP Endpoint | Stage 3 |
|
||||
| | `VhostUserEndpoint` | Stage 3 |
|
||||
| Network Interworking Model | Tc filter | Stage 1 |
|
||||
| | `MacVtap` | Stage 3 |
|
||||
| Storage | Virtio-fs | Stage 1 |
|
||||
| | `nydus` | Stage 2 |
|
||||
| Hypervisor | `Dragonball` | Stage 1 |
|
||||
| | QEMU | Stage 2 |
|
||||
| | ACRN | Stage 3 |
|
||||
| | Cloud Hypervisor | Stage 3 |
|
||||
| | Firecracker | Stage 3 |
|
||||
| **Class** | **Sub-Class** | **Development Stage** | **Status** |
|
||||
| -------------------------- | ------------------- | --------------------- |------------|
|
||||
| Service | task service | Stage 1 | ✅ |
|
||||
| | extend service | Stage 3 | 🚫 |
|
||||
| | image service | Stage 3 | 🚫 |
|
||||
| Runtime handler | `Virt-Container` | Stage 1 | ✅ |
|
||||
| Endpoint | VETH Endpoint | Stage 1 | ✅ |
|
||||
| | Physical Endpoint | Stage 2 | ✅ |
|
||||
| | Tap Endpoint | Stage 2 | ✅ |
|
||||
| | `Tuntap` Endpoint | Stage 2 | ✅ |
|
||||
| | `IPVlan` Endpoint | Stage 2 | ✅ |
|
||||
| | `MacVlan` Endpoint | Stage 2 | ✅ |
|
||||
| | MACVTAP Endpoint | Stage 3 | 🚫 |
|
||||
| | `VhostUserEndpoint` | Stage 3 | 🚫 |
|
||||
| Network Interworking Model | Tc filter | Stage 1 | ✅ |
|
||||
| | `MacVtap` | Stage 3 | 🚧 |
|
||||
| Storage | Virtio-fs | Stage 1 | ✅ |
|
||||
| | `nydus` | Stage 2 | 🚧 |
|
||||
| | `device mapper` | Stage 2 | 🚫 |
|
||||
| `Cgroup V2` | | Stage 2 | 🚧 |
|
||||
| Hypervisor | `Dragonball` | Stage 1 | 🚧 |
|
||||
| | QEMU | Stage 2 | 🚫 |
|
||||
| | ACRN | Stage 3 | 🚫 |
|
||||
| | Cloud Hypervisor | Stage 3 | 🚫 |
|
||||
| | Firecracker | Stage 3 | 🚫 |
|
||||
|
||||
## FAQ
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
- [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)
|
||||
- [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)
|
||||
|
||||
@@ -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
|
||||
|
||||
159
docs/how-to/how-to-run-kata-containers-with-SNP-VMs.md
Normal file
159
docs/how-to/how-to-run-kata-containers-with-SNP-VMs.md
Normal file
@@ -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.
|
||||
|
||||

|
||||
|
||||
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 --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
|
||||
```
|
||||
|
||||
4
docs/how-to/images/SNP-stack.svg
Normal file
4
docs/how-to/images/SNP-stack.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 9.0 KiB |
2
src/agent/Cargo.lock
generated
2
src/agent/Cargo.lock
generated
@@ -3130,7 +3130,7 @@ dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"libseccomp",
|
||||
"nix 0.23.1",
|
||||
"nix 0.24.2",
|
||||
"oci",
|
||||
"path-absolutize",
|
||||
"protobuf",
|
||||
|
||||
@@ -12,7 +12,7 @@ serde_derive = "1.0.91"
|
||||
oci = { path = "../../libs/oci" }
|
||||
protocols = { path ="../../libs/protocols" }
|
||||
caps = "0.5.0"
|
||||
nix = "0.23.0"
|
||||
nix = "0.24.2"
|
||||
scopeguard = "1.0.0"
|
||||
capctl = "0.2.0"
|
||||
lazy_static = "1.3.0"
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use nix::errno::Errno;
|
||||
use nix::pty;
|
||||
use nix::sys::{socket, uio};
|
||||
use nix::sys::socket;
|
||||
use nix::unistd::{self, dup2};
|
||||
use std::io::IoSlice;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::path::Path;
|
||||
|
||||
@@ -23,10 +24,7 @@ pub fn setup_console_socket(csocket_path: &str) -> Result<Option<RawFd>> {
|
||||
None,
|
||||
)?;
|
||||
|
||||
match socket::connect(
|
||||
socket_fd,
|
||||
&socket::SockAddr::Unix(socket::UnixAddr::new(Path::new(csocket_path))?),
|
||||
) {
|
||||
match socket::connect(socket_fd, &socket::UnixAddr::new(Path::new(csocket_path))?) {
|
||||
Ok(()) => Ok(Some(socket_fd)),
|
||||
Err(errno) => Err(anyhow!("failed to open console fd: {}", errno)),
|
||||
}
|
||||
@@ -36,11 +34,11 @@ pub fn setup_master_console(socket_fd: RawFd) -> Result<()> {
|
||||
let pseudo = pty::openpty(None, None)?;
|
||||
|
||||
let pty_name: &[u8] = b"/dev/ptmx";
|
||||
let iov = [uio::IoVec::from_slice(pty_name)];
|
||||
let iov = [IoSlice::new(pty_name)];
|
||||
let fds = [pseudo.master];
|
||||
let cmsg = socket::ControlMessage::ScmRights(&fds);
|
||||
|
||||
socket::sendmsg(socket_fd, &iov, &[cmsg], socket::MsgFlags::empty(), None)?;
|
||||
socket::sendmsg::<()>(socket_fd, &iov, &[cmsg], socket::MsgFlags::empty(), None)?;
|
||||
|
||||
unistd::setsid()?;
|
||||
let ret = unsafe { libc::ioctl(pseudo.slave, libc::TIOCSCTTY) };
|
||||
|
||||
@@ -779,16 +779,20 @@ pub async fn add_storages(
|
||||
}
|
||||
};
|
||||
|
||||
// Todo need to rollback the mounted storage if err met.
|
||||
|
||||
if res.is_err() {
|
||||
error!(
|
||||
logger,
|
||||
"add_storages failed, storage: {:?}, error: {:?} ", storage, res
|
||||
);
|
||||
}
|
||||
|
||||
let mount_point = res?;
|
||||
let mount_point = match res {
|
||||
Err(e) => {
|
||||
error!(
|
||||
logger,
|
||||
"add_storages failed, storage: {:?}, error: {:?} ", storage, e
|
||||
);
|
||||
let mut sb = sandbox.lock().await;
|
||||
sb.unset_sandbox_storage(&storage.mount_point)
|
||||
.map_err(|e| warn!(logger, "fail to unset sandbox storage {:?}", e))
|
||||
.ok();
|
||||
return Err(e);
|
||||
}
|
||||
Ok(m) => m,
|
||||
};
|
||||
|
||||
if !mount_point.is_empty() {
|
||||
mount_list.push(mount_point);
|
||||
|
||||
@@ -462,8 +462,22 @@ impl AgentService {
|
||||
if p.init && sig == libc::SIGTERM && !is_signal_handled(&proc_status_file, sig as u32) {
|
||||
sig = libc::SIGKILL;
|
||||
}
|
||||
p.signal(sig)?;
|
||||
}
|
||||
|
||||
match p.signal(sig) {
|
||||
Err(Errno::ESRCH) => {
|
||||
info!(
|
||||
sl!(),
|
||||
"signal encounter ESRCH, continue";
|
||||
"container-id" => cid.clone(),
|
||||
"exec-id" => eid.clone(),
|
||||
"pid" => p.pid,
|
||||
"signal" => sig,
|
||||
);
|
||||
}
|
||||
Err(err) => return Err(anyhow!(err)),
|
||||
Ok(()) => (),
|
||||
}
|
||||
};
|
||||
|
||||
if eid.is_empty() {
|
||||
// eid is empty, signal all the remaining processes in the container cgroup
|
||||
|
||||
@@ -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 {
|
||||
@@ -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;
|
||||
@@ -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());
|
||||
|
||||
watcher.cleanup();
|
||||
assert!(!is_mounted(WATCH_MOUNT_POINT_PATH).unwrap());
|
||||
thread::sleep(Duration::from_millis(20));
|
||||
|
||||
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();
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ 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,9 +36,9 @@ 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.10.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"
|
||||
@@ -46,7 +46,7 @@ slog-async = "2.7.0"
|
||||
|
||||
[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"]
|
||||
@@ -55,11 +55,12 @@ virtio-net = ["dbs-virtio-devices/virtio-net", "virtio-queue"]
|
||||
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" }
|
||||
dbs-device = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-interrupt = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-legacy-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-upcall = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-utils = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-virtio-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-boot = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-arch = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-address-space = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
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
|
||||
|
||||
check: clippy format
|
||||
|
||||
@@ -33,9 +33,9 @@ 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,
|
||||
address::Address, FileOffset, GuestAddress, GuestAddressSpace, GuestMemoryMmap, GuestMemoryRegion,
|
||||
GuestRegionMmap, GuestUsize, MemoryRegionAddress, MmapRegion,
|
||||
};
|
||||
|
||||
|
||||
@@ -577,7 +577,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 {
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -147,13 +147,13 @@ 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,14 +591,19 @@ 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();
|
||||
self.con_manager
|
||||
.create_socket_console(com1, path)
|
||||
.map_err(StartMicroVmError::DeviceManager)?;
|
||||
|
||||
if let Some(legacy_manager) = self.legacy_manager.as_ref() {
|
||||
if let Some(path) = com1_sock_path {
|
||||
// Currently, the `com1_sock_path` "stdio" is only reserved for creating the stdio console
|
||||
if path != "stdio" {
|
||||
let com1 = legacy_manager.get_com1_serial();
|
||||
self.con_manager
|
||||
.create_socket_console(com1, path)
|
||||
.map_err(StartMicroVmError::DeviceManager)?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
} 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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -136,7 +136,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(),
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
2
src/libs/Cargo.lock
generated
2
src/libs/Cargo.lock
generated
@@ -413,6 +413,7 @@ dependencies = [
|
||||
"byte-unit",
|
||||
"glob",
|
||||
"lazy_static",
|
||||
"nix 0.24.2",
|
||||
"num_cpus",
|
||||
"oci",
|
||||
"regex",
|
||||
@@ -421,6 +422,7 @@ dependencies = [
|
||||
"slog",
|
||||
"slog-scope",
|
||||
"tempfile",
|
||||
"test-utils",
|
||||
"thiserror",
|
||||
"toml",
|
||||
]
|
||||
|
||||
@@ -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()?;
|
||||
|
||||
@@ -10,9 +10,9 @@ use kata_types::container::ContainerType;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
/// unknow container type
|
||||
#[error("unknow container type {0}")]
|
||||
UnknowContainerType(String),
|
||||
/// unknown container type
|
||||
#[error("unknown container type {0}")]
|
||||
UnknownContainerType(String),
|
||||
/// missing sandboxID
|
||||
#[error("missing sandboxID")]
|
||||
MissingSandboxID,
|
||||
@@ -56,7 +56,7 @@ pub fn get_contaier_type(spec: &oci::Spec) -> Result<ContainerType, Error> {
|
||||
"sandbox" => return Ok(ContainerType::PodSandbox),
|
||||
"podsandbox" => return Ok(ContainerType::PodSandbox),
|
||||
"container" => return Ok(ContainerType::PodContainer),
|
||||
_ => return Err(Error::UnknowContainerType(type_value.clone())),
|
||||
_ => return Err(Error::UnknownContainerType(type_value.clone())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ oci = { path = "../oci" }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
test-utils = { path = "../test-utils" }
|
||||
nix = "0.24.2"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -383,17 +383,17 @@ impl Annotation {
|
||||
}
|
||||
|
||||
/// Get the annotation of cpu quota for sandbox
|
||||
pub fn get_sandbox_cpu_quota(&self) -> u64 {
|
||||
pub fn get_sandbox_cpu_quota(&self) -> i64 {
|
||||
let value = self
|
||||
.get_value::<u64>(SANDBOX_CPU_QUOTA_KEY)
|
||||
.get_value::<i64>(SANDBOX_CPU_QUOTA_KEY)
|
||||
.unwrap_or(Some(0));
|
||||
value.unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Get the annotation of cpu period for sandbox
|
||||
pub fn get_sandbox_cpu_period(&self) -> i64 {
|
||||
pub fn get_sandbox_cpu_period(&self) -> u64 {
|
||||
let value = self
|
||||
.get_value::<i64>(SANDBOX_CPU_PERIOD_KEY)
|
||||
.get_value::<u64>(SANDBOX_CPU_PERIOD_KEY)
|
||||
.unwrap_or(Some(0));
|
||||
value.unwrap_or(0)
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,38 +301,42 @@ 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(",");
|
||||
|
||||
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 {
|
||||
self.default_vcpus = cpus as i32;
|
||||
} else if self.default_vcpus == 0 {
|
||||
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(())
|
||||
}
|
||||
|
||||
/// 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(())
|
||||
}
|
||||
|
||||
/// Get default number of guest vCPUs.
|
||||
pub fn get_default_vcpus(&self) -> u32 {
|
||||
let cpus = num_cpus::get() as u32;
|
||||
if self.default_vcpus < 0 || self.default_vcpus as u32 > cpus {
|
||||
cpus
|
||||
} else if self.default_vcpus == 0 {
|
||||
default::DEFAULT_GUEST_VCPUS
|
||||
} else {
|
||||
self.default_vcpus as u32
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration information for shared filesystem, such virtio-9p and virtio-fs.
|
||||
/// Configuration information for debug
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct DebugInfo {
|
||||
/// This option changes the default hypervisor and kernel parameters to enable debug output
|
||||
@@ -596,7 +612,7 @@ impl MemoryInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration information for virtual machine.
|
||||
/// Configuration information for network.
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct NetworkInfo {
|
||||
/// If vhost-net backend for virtio-net is not desired, set to true.
|
||||
@@ -638,7 +654,7 @@ impl NetworkInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration information for virtual machine.
|
||||
/// Configuration information for security.
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct SecurityInfo {
|
||||
/// Enable running QEMU VMM as a non-root user.
|
||||
@@ -818,11 +834,15 @@ impl SharedFsInfo {
|
||||
validate_path_pattern(&self.valid_virtio_fs_daemon_paths, path)
|
||||
}
|
||||
|
||||
fn adjust_virtio_fs(&mut self, _inline: bool) -> Result<()> {
|
||||
resolve_path!(
|
||||
self.virtio_fs_daemon,
|
||||
"Virtio-fs daemon path {} is invalid: {}"
|
||||
)?;
|
||||
fn adjust_virtio_fs(&mut self, inline: bool) -> Result<()> {
|
||||
// inline mode doesn't need external virtiofsd daemon
|
||||
if !inline {
|
||||
resolve_path!(
|
||||
self.virtio_fs_daemon,
|
||||
"Virtio-fs daemon path {} is invalid: {}"
|
||||
)?;
|
||||
}
|
||||
|
||||
if self.virtio_fs_cache.is_empty() {
|
||||
self.virtio_fs_cache = default::DEFAULT_VIRTIO_FS_CACHE_MODE.to_string();
|
||||
}
|
||||
@@ -836,16 +856,13 @@ impl SharedFsInfo {
|
||||
}
|
||||
|
||||
fn validate_virtio_fs(&self, inline: bool) -> Result<()> {
|
||||
if inline && !self.virtio_fs_daemon.is_empty() {
|
||||
return Err(eother!(
|
||||
"Executable path for inline-virtio-fs is not empty: {}",
|
||||
&self.virtio_fs_daemon
|
||||
));
|
||||
// inline mode doesn't need external virtiofsd daemon
|
||||
if !inline {
|
||||
validate_path!(
|
||||
self.virtio_fs_daemon,
|
||||
"Virtio-fs daemon path {} is invalid: {}"
|
||||
)?;
|
||||
}
|
||||
validate_path!(
|
||||
self.virtio_fs_daemon,
|
||||
"Virtio-fs daemon path {} is invalid: {}"
|
||||
)?;
|
||||
|
||||
let l = ["none", "auto", "always"];
|
||||
|
||||
@@ -1066,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_vcpus as i32,
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
478
src/runtime-rs/Cargo.lock
generated
478
src/runtime-rs/Cargo.lock
generated
@@ -84,12 +84,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"
|
||||
@@ -274,23 +268,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"
|
||||
@@ -478,21 +455,21 @@ dependencies = [
|
||||
"ttrpc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpuid-bool"
|
||||
version = "0.1.2"
|
||||
@@ -585,22 +562,20 @@ dependencies = [
|
||||
|
||||
[[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"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9acd47f8b1ad8a6a62450d2d83ced5452dbf9549e2b98709d945554b22a45ed7"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323#c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323"
|
||||
dependencies = [
|
||||
"arc-swap 1.5.0",
|
||||
"arc-swap",
|
||||
"libc",
|
||||
"nix 0.23.1",
|
||||
"thiserror",
|
||||
@@ -620,7 +595,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "dbs-arch"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323#c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323"
|
||||
dependencies = [
|
||||
"kvm-bindings",
|
||||
"kvm-ioctls",
|
||||
@@ -633,7 +608,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "dbs-boot"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323#c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323"
|
||||
dependencies = [
|
||||
"dbs-arch",
|
||||
"kvm-bindings",
|
||||
@@ -648,7 +623,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "dbs-device"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323#c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
@@ -656,7 +631,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "dbs-interrupt"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323#c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323"
|
||||
dependencies = [
|
||||
"dbs-device",
|
||||
"kvm-bindings",
|
||||
@@ -668,7 +643,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "dbs-legacy-devices"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323#c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323"
|
||||
dependencies = [
|
||||
"dbs-device",
|
||||
"dbs-utils",
|
||||
@@ -680,9 +655,9 @@ dependencies = [
|
||||
|
||||
[[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",
|
||||
@@ -691,7 +666,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "dbs-utils"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323#c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"event-manager",
|
||||
@@ -706,9 +681,8 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "dbs-virtio-devices"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=7a8e832b53d66994d6a16f0513d69f540583dcd0#7a8e832b53d66994d6a16f0513d69f540583dcd0"
|
||||
source = "git+https://github.com/openanolis/dragonball-sandbox.git?rev=c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323#c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323"
|
||||
dependencies = [
|
||||
"blobfs",
|
||||
"byteorder",
|
||||
"caps",
|
||||
"dbs-device",
|
||||
@@ -722,7 +696,8 @@ dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"nix 0.23.1",
|
||||
"rafs",
|
||||
"nydus-blobfs",
|
||||
"nydus-rafs",
|
||||
"rlimit",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -765,21 +740,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",
|
||||
@@ -922,20 +887,24 @@ 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",
|
||||
@@ -1124,16 +1093,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 +1138,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"
|
||||
@@ -1207,7 +1246,7 @@ 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",
|
||||
@@ -1391,9 +1430,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 +1693,47 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nydus-api"
|
||||
version = "0.1.1"
|
||||
source = "git+https://github.com/dragonflyoss/image-service.git?rev=e429be3e8623d47db0f97186f761aeda2983c6f4#e429be3e8623d47db0f97186f761aeda2983c6f4"
|
||||
dependencies = [
|
||||
"dbs-uhttp",
|
||||
"http",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"mio",
|
||||
"nydus-error",
|
||||
"nydus-utils",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"url",
|
||||
"vmm-sys-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nydus-blobfs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/dragonflyoss/image-service.git?rev=e429be3e8623d47db0f97186f761aeda2983c6f4#e429be3e8623d47db0f97186f761aeda2983c6f4"
|
||||
dependencies = [
|
||||
"fuse-backend-rs",
|
||||
"libc",
|
||||
"log",
|
||||
"nydus-error",
|
||||
"nydus-rafs",
|
||||
"nydus-storage",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"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.1"
|
||||
source = "git+https://github.com/dragonflyoss/image-service.git?rev=e429be3e8623d47db0f97186f761aeda2983c6f4#e429be3e8623d47db0f97186f761aeda2983c6f4"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"httpdate",
|
||||
@@ -1668,21 +1744,79 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nydus-utils"
|
||||
name = "nydus-rafs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/dragonflyoss/image-service.git?rev=316380792092f73c99f832c4cb44ef4319d6f76b#316380792092f73c99f832c4cb44ef4319d6f76b"
|
||||
source = "git+https://github.com/dragonflyoss/image-service.git?rev=e429be3e8623d47db0f97186f761aeda2983c6f4#e429be3e8623d47db0f97186f761aeda2983c6f4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
"bitflags",
|
||||
"blake3",
|
||||
"flate2",
|
||||
"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",
|
||||
"serde_with",
|
||||
"sha2 0.10.5",
|
||||
"spmc",
|
||||
"vm-memory",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nydus-storage"
|
||||
version = "0.5.0"
|
||||
source = "git+https://github.com/dragonflyoss/image-service.git?rev=e429be3e8623d47db0f97186f761aeda2983c6f4#e429be3e8623d47db0f97186f761aeda2983c6f4"
|
||||
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",
|
||||
"serde_with",
|
||||
"sha2 0.10.5",
|
||||
"tokio",
|
||||
"vm-memory",
|
||||
"vmm-sys-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nydus-utils"
|
||||
version = "0.3.1"
|
||||
source = "git+https://github.com/dragonflyoss/image-service.git?rev=e429be3e8623d47db0f97186f761aeda2983c6f4#e429be3e8623d47db0f97186f761aeda2983c6f4"
|
||||
dependencies = [
|
||||
"blake3",
|
||||
"flate2",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"lz4-sys",
|
||||
"nix 0.24.2",
|
||||
"nydus-error",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"sha2 0.10.5",
|
||||
"tokio",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
@@ -1792,7 +1926,6 @@ dependencies = [
|
||||
"kata-sys-util",
|
||||
"kata-types",
|
||||
"libc",
|
||||
"rustc-serialize",
|
||||
"safe-path",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -1808,6 +1941,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"
|
||||
@@ -1965,34 +2118,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"
|
||||
@@ -2183,6 +2308,7 @@ dependencies = [
|
||||
"serde",
|
||||
"slog",
|
||||
"slog-scope",
|
||||
"test-utils",
|
||||
"tokio",
|
||||
"uuid",
|
||||
]
|
||||
@@ -2217,6 +2343,9 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"common",
|
||||
"hyper",
|
||||
"hyperlocal",
|
||||
"hypervisor",
|
||||
"kata-types",
|
||||
"lazy_static",
|
||||
"linux_container",
|
||||
@@ -2236,12 +2365,6 @@ version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-serialize"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.34.8"
|
||||
@@ -2275,6 +2398,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"
|
||||
@@ -2395,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"
|
||||
@@ -2414,7 +2554,7 @@ dependencies = [
|
||||
"rand 0.8.5",
|
||||
"serial_test",
|
||||
"service",
|
||||
"sha2",
|
||||
"sha2 0.9.3",
|
||||
"slog",
|
||||
"slog-async",
|
||||
"slog-scope",
|
||||
@@ -2477,7 +2617,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",
|
||||
]
|
||||
@@ -2515,34 +2655,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"
|
||||
@@ -2618,6 +2730,13 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-utils"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nix 0.24.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tests_utils"
|
||||
version = "0.1.0"
|
||||
@@ -2739,6 +2858,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"
|
||||
@@ -2770,6 +2903,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"
|
||||
@@ -2936,9 +3101,9 @@ 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",
|
||||
@@ -2953,11 +3118,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",
|
||||
]
|
||||
@@ -2970,9 +3135,9 @@ 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",
|
||||
@@ -2994,6 +3159,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"
|
||||
@@ -3212,8 +3387,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"
|
||||
|
||||
@@ -4,11 +4,11 @@ members = [
|
||||
]
|
||||
|
||||
[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" }
|
||||
dbs-address-space = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-device = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-utils = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-interrupt = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-legacy-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-virtio-devices = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-boot = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
dbs-arch = { git = "https://github.com/openanolis/dragonball-sandbox.git", rev = "c3d7831aee7c3962b8a90f0afbfd0fb7e4d30323" }
|
||||
|
||||
@@ -44,29 +44,43 @@ else
|
||||
endif
|
||||
|
||||
ifeq ($(PREFIX),)
|
||||
PREFIX := /usr
|
||||
PREFIX := /usr
|
||||
EXEC_PREFIX := $(PREFIX)/local
|
||||
##VAR BINDIR=<path> is a directory for installing executable programs
|
||||
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
|
||||
|
||||
PREFIXDEPS := $(PREFIX)
|
||||
PREFIXDEPS := $(PREFIX)
|
||||
LIBEXECDIR := $(PREFIXDEPS)/libexec
|
||||
SHAREDIR := $(PREFIX)/share
|
||||
DEFAULTSDIR := $(SHAREDIR)/defaults
|
||||
PROJECT_DIR = $(PROJECT_TAG)
|
||||
IMAGENAME = $(PROJECT_TAG).img
|
||||
TARGET = $(PROJECT_COMPONENT)
|
||||
|
||||
SYSCONFDIR := /etc
|
||||
CONFIG_FILE = configuration.toml
|
||||
HYPERVISOR_DB = dragonball
|
||||
HYPERVISOR_ACRN = acrn
|
||||
HYPERVISOR_FC = firecracker
|
||||
HYPERVISOR_QEMU = qemu
|
||||
HYPERVISOR_CLH = cloud-hypervisor
|
||||
|
||||
|
||||
DEFAULT_HYPERVISOR ?= $(HYPERVISOR_DB)
|
||||
|
||||
HYPERVISORS := $(HYPERVISOR_DB)
|
||||
# List of hypervisors this build system can generate configuration for.
|
||||
HYPERVISORS := $(HYPERVISOR_DB) $(HYPERVISOR_ACRN) $(HYPERVISOR_FC) $(HYPERVISOR_QEMU) $(HYPERVISOR_CLH)
|
||||
|
||||
DBVALIDHYPERVISORPATHS := []
|
||||
PKGDATADIR := $(PREFIXDEPS)/share/$(PROJECT_DIR)
|
||||
KERNELDIR := $(PKGDATADIR)
|
||||
IMAGEPATH := $(PKGDATADIR)/$(IMAGENAME)
|
||||
PKGLIBEXECDIR := $(LIBEXECDIR)/$(PROJECT_DIR)
|
||||
FIRMWAREPATH :=
|
||||
FIRMWAREVOLUMEPATH :=
|
||||
|
||||
@@ -84,7 +98,7 @@ DEFMEMSZ := 2048
|
||||
# - hugepage memory
|
||||
DEFMEMSLOTS := 10
|
||||
#Default number of bridges
|
||||
DEFBRIDGES := 1
|
||||
DEFBRIDGES := 0
|
||||
DEFENABLEANNOTATIONS := []
|
||||
DEFDISABLEGUESTSECCOMP := true
|
||||
DEFDISABLEGUESTEMPTYDIR := false
|
||||
@@ -290,9 +304,7 @@ endif
|
||||
TARGET_PATH = target/$(TRIPLE)/$(BUILD_TYPE)/$(TARGET)
|
||||
|
||||
##VAR DESTDIR=<path> is a directory prepended to each installed target file
|
||||
DESTDIR :=
|
||||
##VAR BINDIR=<path> is a directory for installing executable programs
|
||||
BINDIR := /usr/local/bin
|
||||
DESTDIR ?= /
|
||||
|
||||
GENERATED_CODE = crates/shim/src/config.rs
|
||||
|
||||
@@ -330,8 +342,12 @@ define get_toolchain_version
|
||||
$(shell printf "%s: %s\\n" "toolchain" "$(or $(shell rustup show active-toolchain 2>/dev/null), (unknown))")
|
||||
endef
|
||||
|
||||
# Install a configuration file
|
||||
# params:
|
||||
# $1 : file to install
|
||||
# $2 : directory path where file will be installed
|
||||
define INSTALL_FILE
|
||||
install -D -m 644 $1 $(DESTDIR)$2/$1 || exit 1;
|
||||
install --mode 0644 -D $1 $(DESTDIR)$2/$(notdir $1);
|
||||
endef
|
||||
|
||||
# Returns the name of the kernel file to use based on the provided KERNELTYPE.
|
||||
@@ -382,20 +398,62 @@ show-header:
|
||||
@printf "%s - version %s (commit %s)\n\n" "$(TARGET)" "$(VERSION)" "$(COMMIT_MSG)"
|
||||
|
||||
show-summary: show-header
|
||||
@printf "project:\n"
|
||||
@printf "• Project:\n"
|
||||
@printf " name: $(PROJECT_NAME)\n"
|
||||
@printf " url: $(PROJECT_URL)\n"
|
||||
@printf " component: $(PROJECT_COMPONENT)\n"
|
||||
@printf "target: $(TARGET)\n"
|
||||
@printf "architecture:\n"
|
||||
@printf " host: $(ARCH)\n"
|
||||
@printf "rust:\n"
|
||||
@printf "\n"
|
||||
@printf "• Target: $(TARGET)\n"
|
||||
@printf "\n"
|
||||
@printf "• Architecture: $(ARCH)\n"
|
||||
@printf "\n"
|
||||
@printf "• Rust:\n"
|
||||
@printf " %s\n" "$(call get_command_version,cargo)"
|
||||
@printf " %s\n" "$(call get_command_version,rustc)"
|
||||
@printf " %s\n" "$(call get_command_version,rustup)"
|
||||
@printf " %s\n" "$(call get_toolchain_version)"
|
||||
@printf "\n"
|
||||
|
||||
@printf "• Hypervisors:\n"
|
||||
@printf "\tDefault: $(DEFAULT_HYPERVISOR)\n"
|
||||
@printf "\tKnown: $(sort $(HYPERVISORS))\n"
|
||||
@printf "\tAvailable for this architecture: $(sort $(KNOWN_HYPERVISORS))\n"
|
||||
@printf "\n"
|
||||
@printf "• Summary:\n"
|
||||
@printf "\n"
|
||||
@printf "\tdestination install path (DESTDIR) : %s\n" $(abspath $(DESTDIR))
|
||||
@printf "\tbinary installation path (BINDIR) : %s\n" $(abspath $(BINDIR))
|
||||
@printf "\tbinaries to install :\n"
|
||||
@printf \
|
||||
"$(foreach b,$(sort $(SHIMV2)),$(shell printf "\\t - $(shell readlink -m $(DESTDIR)/$(BINDIR)/$(b))\\\n"))"
|
||||
@printf "\tconfigs to install (CONFIGS) :\n"
|
||||
@printf \
|
||||
"$(foreach c,$(sort $(CONFIGS)),$(shell printf "\\t - $(c)\\\n"))"
|
||||
@printf "\tinstall paths (CONFIG_PATHS) :\n"
|
||||
@printf \
|
||||
"$(foreach c,$(sort $(CONFIG_PATHS)),$(shell printf "\\t - $(c)\\\n"))"
|
||||
@printf "\talternate config paths (SYSCONFIG_PATHS) : %s\n"
|
||||
@printf \
|
||||
"$(foreach c,$(sort $(SYSCONFIG_PATHS)),$(shell printf "\\t - $(c)\\\n"))"
|
||||
@printf "\tdefault install path for $(DEFAULT_HYPERVISOR) (CONFIG_PATH) : %s\n" $(abspath $(CONFIG_PATH))
|
||||
@printf "\tdefault alternate config path (SYSCONFIG) : %s\n" $(abspath $(SYSCONFIG))
|
||||
ifneq (,$(findstring $(HYPERVISOR_QEMU),$(KNOWN_HYPERVISORS)))
|
||||
@printf "\t$(HYPERVISOR_QEMU) hypervisor path (QEMUPATH) : %s\n" $(abspath $(QEMUPATH))
|
||||
endif
|
||||
ifneq (,$(findstring $(HYPERVISOR_QEMU_VIRTIOFS),$(KNOWN_HYPERVISORS)))
|
||||
@printf "\t$(HYPERVISOR_QEMU_VIRTIOFS) hypervisor path (QEMUVIRTIOFSPATH) : %s\n" $(abspath $(QEMUVIRTIOFSPATH))
|
||||
endif
|
||||
ifneq (,$(findstring $(HYPERVISOR_CLH),$(KNOWN_HYPERVISORS)))
|
||||
@printf "\t$(HYPERVISOR_CLH) hypervisor path (CLHPATH) : %s\n" $(abspath $(CLHPATH))
|
||||
endif
|
||||
ifneq (,$(findstring $(HYPERVISOR_FC),$(KNOWN_HYPERVISORS)))
|
||||
@printf "\t$(HYPERVISOR_FC) hypervisor path (FCPATH) : %s\n" $(abspath $(FCPATH))
|
||||
endif
|
||||
ifneq (,$(findstring $(HYPERVISOR_ACRN),$(KNOWN_HYPERVISORS)))
|
||||
@printf "\t$(HYPERVISOR_ACRN) hypervisor path (ACRNPATH) : %s\n" $(abspath $(ACRNPATH))
|
||||
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`
|
||||
help: Makefile show-summary
|
||||
@echo "========================== Help ============================="
|
||||
@@ -429,10 +487,10 @@ codecov-html: check_tarpaulin
|
||||
install: install-runtime install-configs
|
||||
|
||||
install-runtime: runtime
|
||||
install -D $(TARGET_PATH) $(BINDIR)
|
||||
install -D $(TARGET_PATH) $(DESTDIR)$(BINDIR)/$(notdir $(TARGET_PATH))
|
||||
|
||||
install-configs: $(CONFIGS)
|
||||
$(foreach f,$(CONFIGS),$(call INSTALL_CONFIG,$f,$(dir $(CONFIG_PATH)))) \
|
||||
$(foreach f,$(CONFIGS),$(call INSTALL_FILE,$f,$(dir $(CONFIG_PATH)))) \
|
||||
sudo ln -sf $(DEFAULT_HYPERVISOR_CONFIG) $(DESTDIR)/$(CONFIG_PATH)
|
||||
|
||||
.PHONY: \
|
||||
|
||||
126
src/runtime-rs/README.md
Normal file
126
src/runtime-rs/README.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# runtime-rs
|
||||
|
||||
## Wath's runtime-rs
|
||||
|
||||
`runtime-rs` is a new component introduced in Kata Containers 3.0, it is a Rust version of runtime(shim). It like [runtime](../runtime), but they have many difference:
|
||||
|
||||
- `runtime-rs` is written in Rust, and `runtime` is written in Go.
|
||||
- `runtime` is the default shim in Kata Containers 3.0, `runtime-rs` is still under heavy development.
|
||||
- `runtime-rs` has a completed different architecture than `runtime`, you can check at the [architecture overview](../../docs/design/architecture_3.0).
|
||||
|
||||
**Note**:
|
||||
|
||||
`runtime-rs` is still under heavy development, you should avoid using it in critical system.
|
||||
|
||||
## Architecture overview
|
||||
|
||||
Also, `runtime-rs` provides the following features:
|
||||
|
||||
- Turn key solution with builtin `Dragonball` Sandbox, all components in one process
|
||||
- Async I/O to reduce resource consumption
|
||||
- Extensible framework for multiple services, runtimes and hypervisors
|
||||
- Lifecycle management for sandbox and container associated resources
|
||||
|
||||
See the [architecture overview](../../docs/design/architecture_3.0)
|
||||
for details on the `runtime-rs` design.
|
||||
|
||||
`runtime-rs` is a runtime written in Rust, it is composed of several crates.
|
||||
|
||||
This picture shows the overview about the crates under this directory and the relation between crates.
|
||||
|
||||

|
||||
|
||||
Not all the features have been implemented yet, for details please check the [roadmap](../../docs/design/architecture_3.0/README.md#roadmap).
|
||||
|
||||
## Crates
|
||||
|
||||
The `runtime-rs` directory contains some crates in the crates directory that compose the `containerd-shim-kata-v2`.
|
||||
|
||||
| Crate | Description |
|
||||
|-|-|
|
||||
| [`shim`](crates/shim)| containerd shimv2 implementation |
|
||||
| [`service`](crates/service)| services for containers, includes task service |
|
||||
| [`runtimes`](crates/runtimes)| container runtimes |
|
||||
| [`resource`](crates/resource)| sandbox and container resources |
|
||||
| [`hypervisor`](crates/hypervisor)| hypervisor that act as a sandbox |
|
||||
| [`agent`](crates/agent)| library used to communicate with agent in the guest OS |
|
||||
| [`persist`](crates/persist)| persist container state to disk |
|
||||
|
||||
### shim
|
||||
|
||||
`shim` is the entry point of the containerd shim process, it implements containerd shim's [binary protocol](https://github.com/containerd/containerd/tree/v1.6.8/runtime/v2#commands):
|
||||
|
||||
- start: start a new shim process
|
||||
- delete: delete exist a shim process
|
||||
- run: run ttRPC service in shim
|
||||
|
||||
containerd will launch a shim process and the shim process will serve as a ttRPC server to provide shim service through `TaskService` from `service` crate.
|
||||
|
||||
### service
|
||||
|
||||
The `runtime-rs` has an extensible framework, includes extension of services, runtimes, and hypervisors.
|
||||
|
||||
Currently, only containerd compatible `TaskService` is implemented.
|
||||
|
||||
`TaskService` has implemented the [containerd shim protocol](https://docs.rs/containerd-shim-protos/0.2.0/containerd_shim_protos/),
|
||||
and interacts with runtimes through messages.
|
||||
|
||||
### runtimes
|
||||
|
||||
Runtime is a container runtime, the runtime handler handles messages from task services to manage containers.
|
||||
Runtime handler and Runtime instance is used to deal with the operation for sandbox and container.
|
||||
|
||||
Currently, only `VirtContainer` has been implemented.
|
||||
|
||||
### resource
|
||||
|
||||
In `runtime-rs`, all networks/volumes/rootfs are abstracted as resources.
|
||||
|
||||
Resources are classified into two types:
|
||||
|
||||
- sandbox resources: network, share-fs
|
||||
- container resources: rootfs, volume, cgroup
|
||||
|
||||
[Here](../../docs/design/architecture_3.0/README.md#resource-manager) is a detailed description of the resources.
|
||||
|
||||
### hypervisor
|
||||
|
||||
For `VirtContainer`, there will be more hypervisors to choose.
|
||||
|
||||
Currently, only built-in `Dragonball` has been implemented.
|
||||
|
||||
### agent
|
||||
|
||||
`agent` is used to communicate with agent in the guest OS from the shim side. The only supported agent is `KataAgent`.
|
||||
|
||||
### persist
|
||||
|
||||
Persist defines traits and functions to help different components save state to disk and load state from disk.
|
||||
|
||||
## Build and install
|
||||
|
||||
```bash
|
||||
$ make
|
||||
$ sudo make install
|
||||
```
|
||||
## Configuration
|
||||
|
||||
`runtime-rs` has the same [configuration as `runtime`](../runtime/README.md#configuration) with some [limitations](#limitations).
|
||||
|
||||
## Logging
|
||||
|
||||
See the
|
||||
[debugging section of the developer guide](../../docs/Developer-Guide.md#troubleshoot-kata-containers).
|
||||
|
||||
## Debugging
|
||||
|
||||
See the
|
||||
[debugging section of the developer guide](../../docs/Developer-Guide.md#troubleshoot-kata-containers).
|
||||
|
||||
## Limitations
|
||||
|
||||
For Kata Containers limitations, see the
|
||||
[limitations file](../../docs/Limitations.md)
|
||||
for further details.
|
||||
|
||||
`runtime-rs` is under heavy developments, and doesn't support all features as the Golang version [`runtime`](../runtime), check the [roadmap](../../docs/design/architecture_3.0/README.md#roadmap) for details.
|
||||
@@ -128,9 +128,12 @@ block_device_driver = "@DEFBLOCKSTORAGEDRIVER_DB@"
|
||||
#guest_hook_path = "/usr/share/oci/hooks"
|
||||
|
||||
# Shared file system type:
|
||||
# - virtio-fs (default)
|
||||
# - inline-virtio-fs (default)
|
||||
# - virtio-fs
|
||||
# - virtio-9p
|
||||
# - virtio-fs-nydus
|
||||
# "inline-virtio-fs" is the same as "virtio-fs", but it is running in the same process
|
||||
# of shim, does not need an external virtiofsd process.
|
||||
shared_fs = "@DBSHAREDFS@"
|
||||
|
||||
[agent.@PROJECT_TYPE@]
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -96,9 +100,9 @@ impl_agent!(
|
||||
stats_container | crate::ContainerID | crate::StatsContainerResponse | None,
|
||||
pause_container | crate::ContainerID | crate::Empty | None,
|
||||
resume_container | crate::ContainerID | crate::Empty | None,
|
||||
write_stdin | crate::WriteStreamRequest | crate::WriteStreamResponse | None,
|
||||
read_stdout | crate::ReadStreamRequest | crate::ReadStreamResponse | None,
|
||||
read_stderr | crate::ReadStreamRequest | crate::ReadStreamResponse | None,
|
||||
write_stdin | crate::WriteStreamRequest | crate::WriteStreamResponse | Some(0),
|
||||
read_stdout | crate::ReadStreamRequest | crate::ReadStreamResponse | Some(0),
|
||||
read_stderr | crate::ReadStreamRequest | crate::ReadStreamResponse | Some(0),
|
||||
close_stdin | crate::CloseStdinRequest | crate::Empty | None,
|
||||
tty_win_resize | crate::TtyWinResizeRequest | crate::Empty | None,
|
||||
update_interface | crate::UpdateInterfaceRequest | crate::Interface | None,
|
||||
|
||||
@@ -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,17 @@ 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(inner.socket_address.clone())
|
||||
}
|
||||
|
||||
pub(crate) async fn agent_config(&self) -> AgentConfig {
|
||||
let inner = self.inner.lock().await;
|
||||
let inner = self.inner.read().await;
|
||||
inner.config.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ 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.10.0"
|
||||
|
||||
kata-sys-util = { path = "../../../libs/kata-sys-util" }
|
||||
kata-types = { path = "../../../libs/kata-types" }
|
||||
|
||||
94
src/runtime-rs/crates/hypervisor/README.md
Normal file
94
src/runtime-rs/crates/hypervisor/README.md
Normal file
@@ -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
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||
@@ -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)
|
||||
|
||||
@@ -91,6 +91,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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -11,7 +11,6 @@ anyhow = "^1.0"
|
||||
kata-sys-util = { path = "../../../libs/kata-sys-util"}
|
||||
kata-types = { path = "../../../libs/kata-types" }
|
||||
libc = "0.2"
|
||||
rustc-serialize = "0.3.24"
|
||||
serde = { version = "1.0.138", features = ["derive"] }
|
||||
serde_json = "1.0.82"
|
||||
safe-path = { path = "../../../libs/safe-path"}
|
||||
|
||||
@@ -5,6 +5,9 @@ authors = ["The Kata Containers community <kata-dev@lists.katacontainers.io>"]
|
||||
edition = "2018"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[dev-dependencies]
|
||||
test-utils = { path = "../../../libs/test-utils" }
|
||||
|
||||
[dependencies]
|
||||
anyhow = "^1.0"
|
||||
async-trait = "0.1.48"
|
||||
|
||||
@@ -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())
|
||||
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());
|
||||
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());
|
||||
}
|
||||
}
|
||||
@@ -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())
|
||||
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());
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,119 +181,40 @@ fn parse_bridge(mut ibs: Vec<InfoBridge>) -> Bridge {
|
||||
}
|
||||
bridge
|
||||
}
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Default)]
|
||||
pub struct Device {
|
||||
attrs: Option<LinkAttrs>,
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
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>,
|
||||
}
|
||||
|
||||
impl_network_dev!($r_type, $r_struct);
|
||||
};
|
||||
}
|
||||
|
||||
#[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"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Default)]
|
||||
pub struct Vlan {
|
||||
attrs: Option<LinkAttrs>,
|
||||
|
||||
/// on create only
|
||||
pub peer_name: String,
|
||||
}
|
||||
|
||||
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 +224,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);
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ use std::{sync::Arc, vec::Vec};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use kata_types::mount::Mount;
|
||||
use nix::sys::stat::{self, SFlag};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::share_fs::ShareFs;
|
||||
@@ -98,24 +97,3 @@ impl RootFsResource {
|
||||
fn is_single_layer_rootfs(rootfs_mounts: &[Mount]) -> bool {
|
||||
rootfs_mounts.len() == 1
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn get_block_device(file_path: &str) -> Option<u64> {
|
||||
if file_path.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
match stat::stat(file_path) {
|
||||
Ok(fstat) => {
|
||||
if SFlag::from_bits_truncate(fstat.st_mode) == SFlag::S_IFBLK {
|
||||
return Some(fstat.st_rdev);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
error!(sl!(), "failed to stat for {} {:?}", file_path, err);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
@@ -25,7 +25,10 @@ const VIRTIO_FS: &str = "virtio-fs";
|
||||
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";
|
||||
@@ -51,10 +54,12 @@ pub struct ShareFsVolumeConfig {
|
||||
pub source: String,
|
||||
pub target: String,
|
||||
pub readonly: bool,
|
||||
pub mount_options: Vec<String>,
|
||||
}
|
||||
|
||||
pub struct ShareFsMountResult {
|
||||
pub guest_path: String,
|
||||
pub storages: Vec<agent::Storage>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
||||
@@ -13,7 +13,6 @@ use kata_sys_util::mount;
|
||||
use super::utils;
|
||||
|
||||
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";
|
||||
|
||||
@@ -16,9 +16,8 @@ use kata_types::config::hypervisor::SharedFsInfo;
|
||||
use super::{
|
||||
share_virtio_fs::{
|
||||
prepare_virtiofs, FS_TYPE_VIRTIO_FS, KATA_VIRTIO_FS_DEV_TYPE, MOUNT_GUEST_TAG,
|
||||
PASSTHROUGH_FS_DIR,
|
||||
},
|
||||
utils, ShareFs, *,
|
||||
utils, ShareFs, PASSTHROUGH_FS_DIR, *,
|
||||
};
|
||||
|
||||
lazy_static! {
|
||||
|
||||
@@ -41,13 +41,20 @@ pub(crate) fn share_to_guest(
|
||||
|
||||
Ok(do_get_guest_path(target, cid, is_volume))
|
||||
}
|
||||
|
||||
// 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(crate) 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 {
|
||||
@@ -66,11 +73,11 @@ 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 {
|
||||
pub(crate) fn do_get_guest_path(target: &str, cid: &str, is_volume: bool) -> String {
|
||||
do_get_guest_any_path(target, cid, is_volume, false)
|
||||
}
|
||||
|
||||
fn do_get_host_path(
|
||||
pub(crate) fn do_get_host_path(
|
||||
target: &str,
|
||||
sid: &str,
|
||||
cid: &str,
|
||||
|
||||
@@ -4,10 +4,21 @@
|
||||
// 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_types::k8s::is_watchable_mount;
|
||||
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";
|
||||
|
||||
use super::{
|
||||
utils, ShareFsMount, ShareFsMountResult, ShareFsRootfsConfig, ShareFsVolumeConfig,
|
||||
KATA_GUEST_SHARE_DIR, PASSTHROUGH_FS_DIR,
|
||||
};
|
||||
|
||||
pub struct VirtiofsShareMount {
|
||||
id: String,
|
||||
@@ -32,11 +43,14 @@ impl ShareFsMount for VirtiofsShareMount {
|
||||
false,
|
||||
)
|
||||
.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(
|
||||
let mut guest_path = utils::share_to_guest(
|
||||
&config.source,
|
||||
&config.target,
|
||||
&self.id,
|
||||
@@ -45,6 +59,61 @@ impl ShareFsMount for VirtiofsShareMount {
|
||||
true,
|
||||
)
|
||||
.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,
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(ShareFsMountResult {
|
||||
guest_path,
|
||||
storages: vec![],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
use std::{path::Path, sync::Arc};
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use nix::sys::stat::{stat, SFlag};
|
||||
|
||||
use super::Volume;
|
||||
use crate::share_fs::{ShareFs, ShareFsVolumeConfig};
|
||||
@@ -20,6 +19,7 @@ use crate::share_fs::{ShareFs, ShareFsVolumeConfig};
|
||||
// skip the volumes whose source had already set to guest share dir.
|
||||
pub(crate) struct ShareFsVolume {
|
||||
mounts: Vec<oci::Mount>,
|
||||
storages: Vec<agent::Storage>,
|
||||
}
|
||||
|
||||
impl ShareFsVolume {
|
||||
@@ -31,47 +31,30 @@ impl ShareFsVolume {
|
||||
let file_name = Path::new(&m.source).file_name().unwrap().to_str().unwrap();
|
||||
let file_name = generate_mount_path(cid, file_name);
|
||||
|
||||
let mut volume = Self { mounts: vec![] };
|
||||
let mut volume = Self {
|
||||
mounts: vec![],
|
||||
storages: vec![],
|
||||
};
|
||||
match share_fs {
|
||||
None => {
|
||||
let mut need_copy = false;
|
||||
match stat(Path::new(&m.source)) {
|
||||
Ok(stat) => {
|
||||
// Ignore the mount if this is not a regular file (excludes
|
||||
// directory, socket, device, ...) as it cannot be handled by
|
||||
// a simple copy. But this should not be treated as an error,
|
||||
// only as a limitation.
|
||||
// golang implement:
|
||||
// ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket |
|
||||
// ModeDevice | ModeCharDevice | ModeIrregular
|
||||
let file_type = SFlag::S_IFDIR
|
||||
| SFlag::S_IFLNK
|
||||
| SFlag::S_IFIFO
|
||||
| SFlag::S_IFSOCK
|
||||
| SFlag::S_IFCHR
|
||||
| SFlag::S_IFREG;
|
||||
if !file_type.contains(SFlag::from_bits_truncate(stat.st_mode)) {
|
||||
debug!(
|
||||
sl!(),
|
||||
"Ignoring non-regular file as FS sharing not supported. mount: {:?}",
|
||||
m
|
||||
);
|
||||
return Ok(volume);
|
||||
}
|
||||
if SFlag::from_bits_truncate(stat.st_mode) != SFlag::S_IFDIR {
|
||||
need_copy = true;
|
||||
}
|
||||
}
|
||||
let src = match std::fs::canonicalize(&m.source) {
|
||||
Err(err) => {
|
||||
return Err(anyhow!(format!(
|
||||
"failed to stat file {} {:?}",
|
||||
"failed to canonicalize file {} {:?}",
|
||||
&m.source, err
|
||||
)));
|
||||
)))
|
||||
}
|
||||
Ok(src) => src,
|
||||
};
|
||||
|
||||
if need_copy {
|
||||
if src.is_file() {
|
||||
// TODO: copy file
|
||||
debug!(sl!(), "FIXME: copy file {}", &m.source);
|
||||
} else {
|
||||
debug!(
|
||||
sl!(),
|
||||
"Ignoring non-regular file as FS sharing not supported. mount: {:?}", m
|
||||
);
|
||||
}
|
||||
}
|
||||
Some(share_fs) => {
|
||||
@@ -82,10 +65,15 @@ impl ShareFsVolume {
|
||||
source: m.source.clone(),
|
||||
target: file_name,
|
||||
readonly: false,
|
||||
mount_options: m.options.clone(),
|
||||
})
|
||||
.await
|
||||
.context("share fs volume")?;
|
||||
|
||||
// set storages for the volume
|
||||
volume.storages = mount_result.storages;
|
||||
|
||||
// set mount for the volume
|
||||
volume.mounts.push(oci::Mount {
|
||||
destination: m.destination.clone(),
|
||||
r#type: "bind".to_string(),
|
||||
@@ -104,7 +92,7 @@ impl Volume for ShareFsVolume {
|
||||
}
|
||||
|
||||
fn get_storage(&self) -> Result<Vec<agent::Storage>> {
|
||||
Ok(vec![])
|
||||
Ok(self.storages.clone())
|
||||
}
|
||||
|
||||
fn cleanup(&self) -> Result<()> {
|
||||
@@ -121,7 +109,7 @@ fn is_host_device(dest: &str) -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
if dest.starts_with("/dev") {
|
||||
if dest.starts_with("/dev/") {
|
||||
let src = match std::fs::canonicalize(dest) {
|
||||
Err(_) => return false,
|
||||
Ok(src) => src,
|
||||
@@ -138,7 +126,6 @@ fn is_host_device(dest: &str) -> bool {
|
||||
}
|
||||
|
||||
// Note, don't generate random name, attaching rafs depends on the predictable name.
|
||||
// If template_mnt is passed, just use existed name in it
|
||||
pub fn generate_mount_path(id: &str, file_name: &str) -> String {
|
||||
let mut nid = String::from(id);
|
||||
if nid.len() > 10 {
|
||||
|
||||
@@ -11,12 +11,15 @@ lazy_static = "1.4.0"
|
||||
slog = "2.5.2"
|
||||
slog-scope = "4.4.0"
|
||||
tokio = { version = "1.8.0", features = ["rt-multi-thread"] }
|
||||
hyper = { version = "0.14.20", features = ["stream", "server", "http1"] }
|
||||
hyperlocal = "0.8"
|
||||
|
||||
common = { path = "./common" }
|
||||
kata-types = { path = "../../../libs/kata-types" }
|
||||
logging = { path = "../../../libs/logging"}
|
||||
oci = { path = "../../../libs/oci" }
|
||||
persist = { path = "../persist" }
|
||||
hypervisor = { path = "../hypervisor" }
|
||||
# runtime handler
|
||||
linux_container = { path = "./linux_container", optional = true }
|
||||
virt_container = { path = "./virt_container", optional = true }
|
||||
|
||||
@@ -13,4 +13,7 @@ pub trait Sandbox: Send + Sync {
|
||||
async fn stop(&self) -> Result<()>;
|
||||
async fn cleanup(&self, container_id: &str) -> Result<()>;
|
||||
async fn shutdown(&self) -> Result<()>;
|
||||
|
||||
// agent function
|
||||
async fn agent_sock(&self) -> Result<String>;
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ pub struct ContainerConfig {
|
||||
pub bundle: String,
|
||||
pub rootfs_mounts: Vec<Mount>,
|
||||
pub terminal: bool,
|
||||
pub options: Option<Vec<u8>>,
|
||||
pub stdin: Option<String>,
|
||||
pub stdout: Option<String>,
|
||||
pub stderr: Option<String>,
|
||||
|
||||
@@ -4,19 +4,17 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::{
|
||||
convert::{From, TryFrom},
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use containerd_shim_protos::api;
|
||||
use kata_types::mount::Mount;
|
||||
|
||||
use super::{
|
||||
ContainerConfig, ContainerID, ContainerProcess, ExecProcessRequest, KillRequest, Request,
|
||||
ResizePTYRequest, ShutdownRequest, UpdateRequest,
|
||||
};
|
||||
use anyhow::{Context, Result};
|
||||
use containerd_shim_protos::api;
|
||||
use kata_types::mount::Mount;
|
||||
use std::{
|
||||
convert::{From, TryFrom},
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
fn trans_from_shim_mount(from: api::Mount) -> Mount {
|
||||
let options = from.options.to_vec();
|
||||
@@ -42,6 +40,11 @@ fn trans_from_shim_mount(from: api::Mount) -> Mount {
|
||||
impl TryFrom<api::CreateTaskRequest> for Request {
|
||||
type Error = anyhow::Error;
|
||||
fn try_from(from: api::CreateTaskRequest) -> Result<Self> {
|
||||
let options = if from.has_options() {
|
||||
Some(from.get_options().get_value().to_vec())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(Request::CreateContainer(ContainerConfig {
|
||||
container_id: from.id.clone(),
|
||||
bundle: from.bundle.clone(),
|
||||
@@ -52,6 +55,7 @@ impl TryFrom<api::CreateTaskRequest> for Request {
|
||||
.map(trans_from_shim_mount)
|
||||
.collect(),
|
||||
terminal: from.terminal,
|
||||
options,
|
||||
stdin: (!from.stdin.is_empty()).then(|| from.stdin.clone()),
|
||||
stdout: (!from.stdout.is_empty()).then(|| from.stdout.clone()),
|
||||
stderr: (!from.stderr.is_empty()).then(|| from.stderr.clone()),
|
||||
|
||||
@@ -11,4 +11,6 @@ logging::logger_with_subsystem!(sl, "runtimes");
|
||||
|
||||
pub mod manager;
|
||||
pub use manager::RuntimeHandlerManager;
|
||||
mod shim_mgmt;
|
||||
pub use shim_mgmt::{client::MgmtClient, server::sb_storage_path};
|
||||
mod static_resource;
|
||||
|
||||
@@ -4,16 +4,17 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::{str::from_utf8, sync::Arc};
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
|
||||
use crate::static_resource::StaticResourceManager;
|
||||
use crate::{shim_mgmt::server::MgmtServer, static_resource::StaticResourceManager};
|
||||
use common::{
|
||||
message::Message,
|
||||
types::{Request, Response},
|
||||
RuntimeHandler, RuntimeInstance, Sandbox,
|
||||
};
|
||||
use hypervisor::Param;
|
||||
use kata_types::{annotations::Annotation, config::TomlConfig};
|
||||
#[cfg(feature = "linux")]
|
||||
use linux_container::LinuxContainer;
|
||||
@@ -74,7 +75,7 @@ impl RuntimeHandlerManagerInner {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn try_init(&mut self, spec: &oci::Spec) -> Result<()> {
|
||||
async fn try_init(&mut self, spec: &oci::Spec, options: &Option<Vec<u8>>) -> Result<()> {
|
||||
// return if runtime instance has init
|
||||
if self.runtime_instance.is_some() {
|
||||
return Ok(());
|
||||
@@ -104,11 +105,21 @@ impl RuntimeHandlerManagerInner {
|
||||
None
|
||||
};
|
||||
|
||||
let config = load_config(spec).context("load config")?;
|
||||
let config = load_config(spec, options).context("load config")?;
|
||||
self.init_runtime_handler(netns, Arc::new(config))
|
||||
.await
|
||||
.context("init runtime handler")?;
|
||||
|
||||
// the sandbox creation can reach here only once and the sandbox is created
|
||||
// so we can safely create the shim management socket right now
|
||||
// the unwrap here is safe because the runtime handler is correctly created
|
||||
let shim_mgmt_svr = MgmtServer::new(
|
||||
&self.id,
|
||||
self.runtime_instance.as_ref().unwrap().sandbox.clone(),
|
||||
);
|
||||
tokio::task::spawn(Arc::new(shim_mgmt_svr).run());
|
||||
info!(sl!(), "shim management http server starts");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -172,9 +183,13 @@ impl RuntimeHandlerManager {
|
||||
.ok_or_else(|| anyhow!("runtime not ready"))
|
||||
}
|
||||
|
||||
async fn try_init_runtime_instance(&self, spec: &oci::Spec) -> Result<()> {
|
||||
async fn try_init_runtime_instance(
|
||||
&self,
|
||||
spec: &oci::Spec,
|
||||
options: &Option<Vec<u8>>,
|
||||
) -> Result<()> {
|
||||
let mut inner = self.inner.write().await;
|
||||
inner.try_init(spec).await
|
||||
inner.try_init(spec, options).await
|
||||
}
|
||||
|
||||
pub async fn handler_message(&self, req: Request) -> Result<Response> {
|
||||
@@ -183,7 +198,7 @@ impl RuntimeHandlerManager {
|
||||
let bundler_path = format!("{}/{}", req.bundle, oci::OCI_SPEC_CONFIG_FILE_NAME);
|
||||
let spec = oci::Spec::load(&bundler_path).context("load spec")?;
|
||||
|
||||
self.try_init_runtime_instance(&spec)
|
||||
self.try_init_runtime_instance(&spec, &req.options)
|
||||
.await
|
||||
.context("try init runtime instance")?;
|
||||
let instance = self
|
||||
@@ -196,6 +211,7 @@ impl RuntimeHandlerManager {
|
||||
.create_container(req, spec)
|
||||
.await
|
||||
.context("create container")?;
|
||||
|
||||
Ok(Response::CreateContainer(shim_pid))
|
||||
} else {
|
||||
self.handler_request(req).await.context("handler request")
|
||||
@@ -298,13 +314,21 @@ impl RuntimeHandlerManager {
|
||||
/// 2. shimv2 create task option
|
||||
/// TODO: https://github.com/kata-containers/kata-containers/issues/3961
|
||||
/// 3. environment
|
||||
fn load_config(spec: &oci::Spec) -> Result<TomlConfig> {
|
||||
fn load_config(spec: &oci::Spec, option: &Option<Vec<u8>>) -> Result<TomlConfig> {
|
||||
const KATA_CONF_FILE: &str = "KATA_CONF_FILE";
|
||||
let annotation = Annotation::new(spec.annotations.clone());
|
||||
let config_path = if let Some(path) = annotation.get_sandbox_config_path() {
|
||||
path
|
||||
} else if let Ok(path) = std::env::var(KATA_CONF_FILE) {
|
||||
path
|
||||
} else if let Some(option) = option {
|
||||
// get rid of the special characters in options to get the config path
|
||||
let path = if option.len() > 2 {
|
||||
from_utf8(&option[2..])?.to_string()
|
||||
} else {
|
||||
String::from("")
|
||||
};
|
||||
path
|
||||
} else {
|
||||
String::from("")
|
||||
};
|
||||
@@ -312,6 +336,10 @@ fn load_config(spec: &oci::Spec) -> Result<TomlConfig> {
|
||||
let (mut toml_config, _) =
|
||||
TomlConfig::load_from_file(&config_path).context("load toml config")?;
|
||||
annotation.update_config_by_annotation(&mut toml_config)?;
|
||||
update_agent_kernel_params(&mut toml_config)?;
|
||||
|
||||
// validate configuration and return the error
|
||||
toml_config.validate()?;
|
||||
|
||||
// Sandbox sizing information *may* be provided in two scenarios:
|
||||
// 1. The upper layer runtime (ie, containerd or crio) provide sandbox sizing information as an annotation
|
||||
@@ -332,3 +360,20 @@ fn load_config(spec: &oci::Spec) -> Result<TomlConfig> {
|
||||
info!(sl!(), "get config content {:?}", &toml_config);
|
||||
Ok(toml_config)
|
||||
}
|
||||
|
||||
// this update the agent-specfic kernel parameters into hypervisor's bootinfo
|
||||
// the agent inside the VM will read from file cmdline to get the params and function
|
||||
fn update_agent_kernel_params(config: &mut TomlConfig) -> Result<()> {
|
||||
let mut params = vec![];
|
||||
if let Ok(kv) = config.get_agent_kernel_params() {
|
||||
for (k, v) in kv.into_iter() {
|
||||
if let Ok(s) = Param::new(k.as_str(), v.as_str()).to_string() {
|
||||
params.push(s);
|
||||
}
|
||||
}
|
||||
if let Some(h) = config.hypervisor.get_mut(&config.runtime.hypervisor_name) {
|
||||
h.boot_info.add_kernel_params(params);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
61
src/runtime-rs/crates/runtimes/src/shim_mgmt/client.rs
Normal file
61
src/runtime-rs/crates/runtimes/src/shim_mgmt/client.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
// 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 super::server::mgmt_socket_addr;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use hyper::{Body, Client, 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: String, timeout: Option<Duration>) -> Result<Self> {
|
||||
let unix_socket_path = mgmt_socket_addr(sid);
|
||||
let s_addr = unix_socket_path
|
||||
.strip_prefix("unix:")
|
||||
.context("failed to strix 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 work = self.client.get(url);
|
||||
match self.timeout {
|
||||
Some(timeout) => match tokio::time::timeout(timeout, work).await {
|
||||
Ok(result) => result.map_err(|e| anyhow!(e)),
|
||||
Err(_) => Err(anyhow!("TIMEOUT")),
|
||||
},
|
||||
// if timeout not set, work executes directly
|
||||
None => work.await.context("failed to GET"),
|
||||
}
|
||||
}
|
||||
}
|
||||
52
src/runtime-rs/crates/runtimes/src/shim_mgmt/handlers.rs
Normal file
52
src/runtime-rs/crates/runtimes/src/shim_mgmt/handlers.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2019-2022 Alibaba Cloud
|
||||
// Copyright (c) 2019-2022 Ant Group
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
// This defines the handlers corresponding to the url when a request is sent to destined url,
|
||||
// the handler function should be invoked, and the corresponding data will be in the response
|
||||
|
||||
use common::Sandbox;
|
||||
use hyper::{Body, Method, Request, Response, Result, StatusCode};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::server::AGENT_URL;
|
||||
|
||||
// main router for response, this works as a multiplexer on
|
||||
// http arrival which invokes the corresponding handler function
|
||||
pub(crate) async fn handler_mux(
|
||||
sandbox: Arc<dyn Sandbox>,
|
||||
req: Request<Body>,
|
||||
) -> Result<Response<Body>> {
|
||||
info!(
|
||||
sl!(),
|
||||
"mgmt-svr(mux): recv req, method: {}, uri: {}",
|
||||
req.method(),
|
||||
req.uri().path()
|
||||
);
|
||||
match (req.method(), req.uri().path()) {
|
||||
(&Method::GET, AGENT_URL) => agent_url_handler(sandbox, req).await,
|
||||
_ => Ok(not_found(req).await),
|
||||
}
|
||||
}
|
||||
|
||||
// url not found
|
||||
async fn not_found(_req: Request<Body>) -> Response<Body> {
|
||||
Response::builder()
|
||||
.status(StatusCode::NOT_FOUND)
|
||||
.body(Body::from("URL NOT FOUND"))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
// returns the url for agent
|
||||
async fn agent_url_handler(
|
||||
sandbox: Arc<dyn Sandbox>,
|
||||
_req: Request<Body>,
|
||||
) -> Result<Response<Body>> {
|
||||
let agent_sock = sandbox
|
||||
.agent_sock()
|
||||
.await
|
||||
.unwrap_or_else(|_| String::from(""));
|
||||
Ok(Response::new(Body::from(agent_sock)))
|
||||
}
|
||||
9
src/runtime-rs/crates/runtimes/src/shim_mgmt/mod.rs
Normal file
9
src/runtime-rs/crates/runtimes/src/shim_mgmt/mod.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright (c) 2019-2022 Alibaba Cloud
|
||||
// Copyright (c) 2019-2022 Ant Group
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
pub mod client;
|
||||
mod handlers;
|
||||
pub mod server;
|
||||
118
src/runtime-rs/crates/runtimes/src/shim_mgmt/server.rs
Normal file
118
src/runtime-rs/crates/runtimes/src/shim_mgmt/server.rs
Normal file
@@ -0,0 +1,118 @@
|
||||
// Copyright (c) 2019-2022 Alibaba Cloud
|
||||
// Copyright (c) 2019-2022 Ant Group
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
// Shim management service, this service starts a management http server on a socket
|
||||
// and wire certain URL with a corresponding handler. When a command-line interface
|
||||
// or further shim functions want the information corresponding to this, it can just
|
||||
// send a GET request to the url, and the info will be in the response
|
||||
|
||||
#![allow(dead_code)] // some url's handler are *to be* developed
|
||||
|
||||
use std::{fs, path::Path, sync::Arc};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use common::Sandbox;
|
||||
use hyper::{server::conn::Http, service::service_fn};
|
||||
use persist::KATA_PATH;
|
||||
use tokio::net::UnixListener;
|
||||
|
||||
use super::handlers::handler_mux;
|
||||
|
||||
pub(crate) const DIRECT_VOLUMN_PATH_KEY: &str = "path";
|
||||
pub(crate) const DIRECT_VOLUMN_STATS_URL: &str = "/direct-volumn/stats";
|
||||
pub(crate) const DIRECT_VOLUMN_RESIZE_URL: &str = "/direct-volumn/resize";
|
||||
pub(crate) const AGENT_URL: &str = "/agent-url";
|
||||
pub(crate) const IP_TABLE_URL: &str = "/iptables";
|
||||
pub(crate) const IP6_TABLE_URL: &str = "/ip6tables";
|
||||
pub(crate) const METRICS_URL: &str = "/metrics";
|
||||
|
||||
const SHIM_MGMT_SOCK_NAME: &str = "shim-monitor.sock";
|
||||
|
||||
/// The shim management server instance
|
||||
pub struct MgmtServer {
|
||||
/// socket address(with prefix like hvsock://)
|
||||
pub s_addr: String,
|
||||
|
||||
/// The sandbox instance
|
||||
pub sandbox: Arc<dyn Sandbox>,
|
||||
}
|
||||
|
||||
impl MgmtServer {
|
||||
/// construct a new management server
|
||||
pub fn new(sid: &str, sandbox: Arc<dyn Sandbox>) -> Self {
|
||||
Self {
|
||||
s_addr: mgmt_socket_addr(sid.to_owned()),
|
||||
sandbox,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(when metrics is supported): write metric addresses to fs
|
||||
// TODO(when metrics is supported): register shim metrics
|
||||
// TODO(when metrics is supported): register sandbox metrics
|
||||
// running management http server in an infinite loop, able to serve concurrent requests
|
||||
pub async fn run(self: Arc<Self>) {
|
||||
let listener = listener_from_path(self.s_addr.clone()).await.unwrap();
|
||||
// start an infinite loop, which serves the incomming uds stream
|
||||
loop {
|
||||
let (stream, _) = listener.accept().await.unwrap();
|
||||
let me = self.clone();
|
||||
// spawn a light weight thread to multiplex to the handler
|
||||
tokio::task::spawn(async move {
|
||||
if let Err(err) = Http::new()
|
||||
.serve_connection(
|
||||
stream,
|
||||
service_fn(|request| handler_mux(me.sandbox.clone(), request)),
|
||||
)
|
||||
.await
|
||||
{
|
||||
warn!(sl!(), "Failed to serve connection: {:?}", err);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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: String) -> String {
|
||||
let p = Path::new(&sb_storage_path())
|
||||
.join(sid)
|
||||
.join(SHIM_MGMT_SOCK_NAME);
|
||||
format!("unix://{}", p.to_string_lossy())
|
||||
}
|
||||
|
||||
// from path, return a unix listener corresponding to that path,
|
||||
// if the path(socket file) is not created, we create that here
|
||||
async fn listener_from_path(path: String) -> Result<UnixListener> {
|
||||
// create the socket if not present
|
||||
let trim_path = path.strip_prefix("unix:").context("trim path")?;
|
||||
let file_path = Path::new("/").join(trim_path);
|
||||
let file_path = file_path.as_path();
|
||||
if let Some(parent_dir) = file_path.parent() {
|
||||
fs::create_dir_all(parent_dir).context("create parent dir")?;
|
||||
}
|
||||
// bind the socket and return the listener
|
||||
info!(sl!(), "mgmt-svr: binding to path {}", path);
|
||||
UnixListener::bind(file_path).context("bind address")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn mgmt_svr_test_sock_addr() {
|
||||
let sid = String::from("414123");
|
||||
let addr = mgmt_socket_addr(sid);
|
||||
assert_eq!(addr, "unix:///run/kata/414123/shim-monitor.sock");
|
||||
}
|
||||
}
|
||||
@@ -128,8 +128,8 @@ fn get_sizing_info(annotation: Annotation) -> Result<(u64, i64, i64)> {
|
||||
// since we are *adding* our result to the config, a value of 0 will cause no change
|
||||
// and if the annotation is not assigned (but static resource management is), we will
|
||||
// log a *warning* to fill that with zero value
|
||||
let period = annotation.get_sandbox_cpu_quota();
|
||||
let quota = annotation.get_sandbox_cpu_period();
|
||||
let period = annotation.get_sandbox_cpu_period();
|
||||
let quota = annotation.get_sandbox_cpu_quota();
|
||||
let memory = annotation.get_sandbox_mem();
|
||||
Ok((period, quota, memory))
|
||||
}
|
||||
@@ -137,31 +137,149 @@ fn get_sizing_info(annotation: Annotation) -> Result<(u64, i64, i64)> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use kata_types::annotations::cri_containerd;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct InputData {
|
||||
period: Option<u64>,
|
||||
quota: Option<i64>,
|
||||
memory: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct TestData<'a> {
|
||||
desc: &'a str,
|
||||
input: InputData,
|
||||
result: StaticResource,
|
||||
}
|
||||
|
||||
fn get_test_data() -> Vec<TestData<'static>> {
|
||||
[
|
||||
TestData {
|
||||
desc: "no resource limit",
|
||||
input: InputData {
|
||||
period: None,
|
||||
quota: None,
|
||||
memory: None,
|
||||
},
|
||||
result: StaticResource { vcpu: 0, mem_mb: 0 },
|
||||
},
|
||||
TestData {
|
||||
desc: "normal resource limit",
|
||||
// data below should result in 2200 mCPU(round up to 3 vcpus) and 512 MiB of memory
|
||||
input: InputData {
|
||||
period: Some(100_000),
|
||||
quota: Some(220_000),
|
||||
memory: Some(1024 * 1024 * 512),
|
||||
},
|
||||
result: StaticResource {
|
||||
vcpu: 3,
|
||||
mem_mb: 512,
|
||||
},
|
||||
},
|
||||
]
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_static_resource_mgmt() {
|
||||
// data below should result in 2200 mCPU(round up to 3 vcpus) and 512 MiB of memory
|
||||
let period: u64 = 100000;
|
||||
let memory: i64 = 1048576 * 512; // 512 MiB
|
||||
let quota: i64 = 220000;
|
||||
fn test_static_resource_mgmt_sandbox() {
|
||||
let tests = get_test_data();
|
||||
|
||||
let cpu = oci::LinuxCpu {
|
||||
period: Some(period),
|
||||
quota: Some(quota),
|
||||
..Default::default()
|
||||
};
|
||||
if let Ok(cpu_resource) = LinuxContainerCpuResources::try_from(&cpu) {
|
||||
if let Some(v) = cpu_resource.get_vcpus() {
|
||||
assert_eq!(v, 3);
|
||||
}
|
||||
// run tests
|
||||
for (i, d) in tests.iter().enumerate() {
|
||||
let spec = oci::Spec {
|
||||
annotations: HashMap::from([
|
||||
(
|
||||
cri_containerd::CONTAINER_TYPE_LABEL_KEY.to_string(),
|
||||
cri_containerd::SANDBOX.to_string(),
|
||||
),
|
||||
(
|
||||
cri_containerd::SANDBOX_CPU_PERIOD_KEY.to_string(),
|
||||
d.input.period.map_or(String::new(), |v| format!("{}", v)),
|
||||
), // CPU period
|
||||
(
|
||||
cri_containerd::SANDBOX_CPU_QUOTA_KEY.to_string(),
|
||||
d.input.quota.map_or(String::new(), |v| format!("{}", v)),
|
||||
), // CPU quota
|
||||
(
|
||||
cri_containerd::SANDBOX_MEM_KEY.to_string(),
|
||||
d.input.memory.map_or(String::new(), |v| format!("{}", v)),
|
||||
), // memory in bytes
|
||||
]),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let static_resource = StaticResource::try_from(&spec);
|
||||
assert!(
|
||||
static_resource.is_ok(),
|
||||
"test[{}]: {:?} should be ok",
|
||||
i,
|
||||
d.desc
|
||||
);
|
||||
|
||||
let static_resource = static_resource.unwrap();
|
||||
assert_eq!(
|
||||
static_resource.vcpu, d.result.vcpu,
|
||||
"test[{}]: {:?} vcpu should be {}",
|
||||
i, d.desc, d.result.vcpu,
|
||||
);
|
||||
assert_eq!(
|
||||
static_resource.mem_mb, d.result.mem_mb,
|
||||
"test[{}]: {:?} memory should be {}",
|
||||
i, d.desc, d.result.mem_mb,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let mem_mb = if memory < 0 {
|
||||
0
|
||||
} else {
|
||||
(memory / 1024 / 1024) as u32
|
||||
};
|
||||
#[test]
|
||||
fn test_static_resource_mgmt_container() {
|
||||
let tests = get_test_data();
|
||||
|
||||
assert_eq!(mem_mb, 512);
|
||||
// run tests
|
||||
for (i, d) in tests.iter().enumerate() {
|
||||
let spec = oci::Spec {
|
||||
annotations: HashMap::from([(
|
||||
cri_containerd::CONTAINER_TYPE_LABEL_KEY.to_string(),
|
||||
cri_containerd::CONTAINER.to_string(),
|
||||
)]),
|
||||
linux: Some(oci::Linux {
|
||||
resources: Some(oci::LinuxResources {
|
||||
cpu: Some(oci::LinuxCpu {
|
||||
period: d.input.period,
|
||||
quota: d.input.quota,
|
||||
..Default::default()
|
||||
}),
|
||||
memory: Some(oci::LinuxMemory {
|
||||
limit: d.input.memory,
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let static_resource = StaticResource::try_from(&spec);
|
||||
assert!(
|
||||
static_resource.is_ok(),
|
||||
"test[{}]: {:?} should be ok",
|
||||
i,
|
||||
d.desc
|
||||
);
|
||||
|
||||
let static_resource = static_resource.unwrap();
|
||||
assert_eq!(
|
||||
static_resource.vcpu, d.result.vcpu,
|
||||
"test[{}]: {:?} vcpu should be {}",
|
||||
i, d.desc, d.result.vcpu,
|
||||
);
|
||||
assert_eq!(
|
||||
static_resource.mem_mb, d.result.mem_mb,
|
||||
"test[{}]: {:?} memory should be {}",
|
||||
i, d.desc, d.result.mem_mb,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,13 +256,13 @@ impl ContainerInner {
|
||||
|
||||
pub async fn close_io(&mut self, process: &ContainerProcess) -> Result<()> {
|
||||
match process.process_type {
|
||||
ProcessType::Container => self.init_process.close_io().await,
|
||||
ProcessType::Container => self.init_process.close_io(self.agent.clone()).await,
|
||||
ProcessType::Exec => {
|
||||
let exec = self
|
||||
.exec_processes
|
||||
.get_mut(&process.exec_id)
|
||||
.ok_or_else(|| Error::ProcessNotFound(process.clone()))?;
|
||||
exec.process.close_io().await;
|
||||
exec.process.close_io(self.agent.clone()).await;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ impl Process {
|
||||
) -> Result<()> {
|
||||
info!(self.logger, "run io copy for {}", io_name);
|
||||
let io_name = io_name.to_string();
|
||||
let logger = self.logger.new(o!("io name" => io_name));
|
||||
let logger = self.logger.new(o!("io_name" => io_name));
|
||||
let _ = tokio::spawn(async move {
|
||||
loop {
|
||||
match tokio::io::copy(&mut reader, &mut writer).await {
|
||||
@@ -141,9 +141,11 @@ impl Process {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
warn!(logger, "io: failed to copy stream {}", e);
|
||||
warn!(logger, "run_io_copy: failed to copy stream: {}", e);
|
||||
}
|
||||
Ok(length) => {
|
||||
warn!(logger, "run_io_copy: stop to copy stream length {}", length)
|
||||
}
|
||||
Ok(length) => warn!(logger, "io: stop to copy stream length {}", length),
|
||||
};
|
||||
break;
|
||||
}
|
||||
@@ -163,8 +165,8 @@ impl Process {
|
||||
let status = self.status.clone();
|
||||
|
||||
let _ = tokio::spawn(async move {
|
||||
//wait on all of the container's io stream terminated
|
||||
info!(logger, "begin wait group io",);
|
||||
// wait on all of the container's io stream terminated
|
||||
info!(logger, "begin wait group io");
|
||||
wg.wait().await;
|
||||
info!(logger, "end wait group for io");
|
||||
|
||||
@@ -223,8 +225,16 @@ impl Process {
|
||||
*status = ProcessStatus::Stopped;
|
||||
}
|
||||
|
||||
pub async fn close_io(&mut self) {
|
||||
pub async fn close_io(&mut self, agent: Arc<dyn Agent>) {
|
||||
self.wg_stdin.wait().await;
|
||||
|
||||
let req = agent::CloseStdinRequest {
|
||||
process_id: self.process.clone().into(),
|
||||
};
|
||||
|
||||
if let Err(e) = agent.close_stdin(req).await {
|
||||
warn!(self.logger, "failed clsoe process io: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_status(&self) -> ProcessStatus {
|
||||
|
||||
@@ -262,6 +262,10 @@ impl Sandbox for VirtSandbox {
|
||||
// TODO: cleanup other snadbox resource
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn agent_sock(&self) -> Result<String> {
|
||||
self.agent.agent_sock().await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
||||
@@ -77,5 +77,6 @@ impl_service!(
|
||||
wait | api::WaitRequest | api::WaitResponse,
|
||||
stats | api::StatsRequest | api::StatsResponse,
|
||||
connect | api::ConnectRequest | api::ConnectResponse,
|
||||
shutdown | api::ShutdownRequest | api::Empty
|
||||
shutdown | api::ShutdownRequest | api::Empty,
|
||||
close_io | api::CloseIORequest | api::Empty
|
||||
);
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
// WARNING: This file is auto-generated - DO NOT EDIT!
|
||||
//
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub const PROJECT_NAME: &str = "@PROJECT_NAME@";
|
||||
pub const RUNTIME_VERSION: &str = "@RUNTIME_VERSION@";
|
||||
pub const RUNTIME_VERSION_COMMIT: &str = "@VERSION_COMMIT@";
|
||||
|
||||
1
src/runtime-rs/docs/images/crate-overview.drawio
Normal file
1
src/runtime-rs/docs/images/crate-overview.drawio
Normal file
File diff suppressed because one or more lines are too long
4
src/runtime-rs/docs/images/crate-overview.svg
Normal file
4
src/runtime-rs/docs/images/crate-overview.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 104 KiB |
150
src/runtime-rs/docs/images/hypervisor-config.svg
Normal file
150
src/runtime-rs/docs/images/hypervisor-config.svg
Normal file
@@ -0,0 +1,150 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="791px" preserveAspectRatio="none" style="width:1205px;height:791px;background:#FFFFFF;" version="1.1" viewBox="0 0 1205 791" width="1205px" zoomAndPan="magnify"><defs/><g><!--MD5=[77140a42179fe8241cde5d77dd05aadc]
|
||||
cluster config--><g id="cluster_config"><rect fill="none" height="229" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:1.0;" width="708" x="238" y="244"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="51" x="566.5" y="258.9951">config</text></g><!--MD5=[f60c27907dbfcd7ab7a2dc027340c222]
|
||||
cluster hypervisor_mod--><g id="cluster_hypervisor_mod"><rect fill="#FFACAB" height="288" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:1.0;" width="1192" x="7" y="497"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="127" x="539.5" y="511.9951">hypervisor_mod</text></g><!--MD5=[a5ad5601cea2ba57e8fff80f8f2869de]
|
||||
cluster HYPERVISOR_PLUGINS--><g id="cluster_HYPERVISOR_PLUGINS"><rect fill="none" height="213" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:1.0;" width="588" x="555" y="7"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="175" x="761.5" y="21.9951">HYPERVISOR_PLUGINS</text></g><!--MD5=[d0a9bfef0f4555b2d3f87b49ea12fa29]
|
||||
class ConfigPlugin--><g id="elem_ConfigPlugin"><rect codeLine="2" fill="#F1F1F1" height="129.4844" id="ConfigPlugin" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="162" x="768" y="303.5"/><ellipse cx="801.45" cy="319.5" fill="#B4A7E5" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M802.4031,316.2813 L804.1219,316.2813 C804.5125,316.2813 804.7,316.25 804.825,316.1719 C805.0906,316.0156 805.2313,315.7344 805.2313,315.4375 C805.2313,315.1719 805.1219,314.9063 804.8875,314.7344 C804.7156,314.625 804.575,314.5938 804.1219,314.5938 L798.9813,314.5938 C798.5438,314.5938 798.4188,314.6094 798.2625,314.7031 C798.0125,314.8594 797.8563,315.1563 797.8563,315.4375 C797.8563,315.7188 797.9969,315.9688 798.2156,316.1406 C798.3719,316.25 798.5594,316.2813 798.9813,316.2813 L800.7,316.2813 L800.7,322.7969 L798.9813,322.7969 C798.5438,322.7969 798.4188,322.8125 798.2625,322.9219 C798.0125,323.0781 797.8563,323.3594 797.8563,323.6563 C797.8563,323.9063 797.9969,324.1719 798.2156,324.3281 C798.3719,324.4531 798.575,324.5 798.9813,324.5 L804.1219,324.5 C804.8719,324.5 805.2313,324.2188 805.2313,323.6563 C805.2313,323.375 805.1219,323.125 804.8875,322.9531 C804.7156,322.8281 804.575,322.7969 804.1219,322.7969 L802.4031,322.7969 L802.4031,316.2813 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="89" x="819.55" y="324.3467">ConfigPlugin</text><line style="stroke:#181818;stroke-width:0.5;" x1="769" x2="929" y1="335.5" y2="335.5"/><line style="stroke:#181818;stroke-width:0.5;" x1="769" x2="929" y1="343.5" y2="343.5"/><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="776" y="354.1484"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="788" y="360.4951">name()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="776" y="370.4453"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="105" x="788" y="376.792">adjust_config()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="776" y="386.7422"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="67" x="788" y="393.0889">validate()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="776" y="403.0391"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="136" x="788" y="409.3857">get_min_memory()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="776" y="419.3359"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="112" x="788" y="425.6826">get_max_cpus()</text></g><!--MD5=[6a4ac9a1b88b51fd43f45a5feb60ac84]
|
||||
class ConfigOps--><g id="elem_ConfigOps"><rect codeLine="10" fill="#F1F1F1" height="80.5938" id="ConfigOps" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="131" x="601.5" y="327.5"/><ellipse cx="628.2" cy="343.5" fill="#B4A7E5" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M629.1531,340.2813 L630.8719,340.2813 C631.2625,340.2813 631.45,340.25 631.575,340.1719 C631.8406,340.0156 631.9813,339.7344 631.9813,339.4375 C631.9813,339.1719 631.8719,338.9063 631.6375,338.7344 C631.4656,338.625 631.325,338.5938 630.8719,338.5938 L625.7313,338.5938 C625.2938,338.5938 625.1688,338.6094 625.0125,338.7031 C624.7625,338.8594 624.6063,339.1563 624.6063,339.4375 C624.6063,339.7188 624.7469,339.9688 624.9656,340.1406 C625.1219,340.25 625.3094,340.2813 625.7313,340.2813 L627.45,340.2813 L627.45,346.7969 L625.7313,346.7969 C625.2938,346.7969 625.1688,346.8125 625.0125,346.9219 C624.7625,347.0781 624.6063,347.3594 624.6063,347.6563 C624.6063,347.9063 624.7469,348.1719 624.9656,348.3281 C625.1219,348.4531 625.325,348.5 625.7313,348.5 L630.8719,348.5 C631.6219,348.5 631.9813,348.2188 631.9813,347.6563 C631.9813,347.375 631.8719,347.125 631.6375,346.9531 C631.4656,346.8281 631.325,346.7969 630.8719,346.7969 L629.1531,346.7969 L629.1531,340.2813 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" font-style="italic" lengthAdjust="spacing" textLength="73" x="644.8" y="348.3467">ConfigOps</text><line style="stroke:#181818;stroke-width:0.5;" x1="602.5" x2="731.5" y1="359.5" y2="359.5"/><line style="stroke:#181818;stroke-width:0.5;" x1="602.5" x2="731.5" y1="367.5" y2="367.5"/><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="609.5" y="378.1484"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="105" x="621.5" y="384.4951">adjust_config()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="609.5" y="394.4453"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="67" x="621.5" y="400.792">validate()</text></g><!--MD5=[acd5679a085e2767e957f7e8ea3b939a]
|
||||
class TomlConfig--><g id="elem_TomlConfig"><rect codeLine="15" fill="#F1F1F1" height="178.375" id="TomlConfig" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="312" x="254" y="279"/><ellipse cx="364.25" cy="295" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M366.5938,290.6719 C365.6563,290.2344 365.0625,290.0938 364.1875,290.0938 C361.5625,290.0938 359.5625,292.1719 359.5625,294.8906 L359.5625,296.0156 C359.5625,298.5938 361.6719,300.4844 364.5625,300.4844 C365.7813,300.4844 366.9375,300.1875 367.6875,299.6406 C368.2656,299.2344 368.5938,298.7813 368.5938,298.3906 C368.5938,297.9375 368.2031,297.5469 367.7344,297.5469 C367.5156,297.5469 367.3125,297.625 367.125,297.8125 C366.6719,298.2969 366.6719,298.2969 366.4844,298.3906 C366.0625,298.6563 365.375,298.7813 364.6094,298.7813 C362.5625,298.7813 361.2656,297.6875 361.2656,295.9844 L361.2656,294.8906 C361.2656,293.1094 362.5156,291.7969 364.25,291.7969 C364.8281,291.7969 365.4375,291.9531 365.9063,292.2031 C366.3906,292.4844 366.5625,292.7031 366.6563,293.1094 C366.7188,293.5156 366.75,293.6406 366.8906,293.7656 C367.0313,293.9063 367.2656,294.0156 367.4844,294.0156 C367.75,294.0156 368.0156,293.875 368.1875,293.6563 C368.2969,293.5 368.3281,293.3125 368.3281,292.8906 L368.3281,291.4688 C368.3281,291.0313 368.3125,290.9063 368.2188,290.75 C368.0625,290.4844 367.7813,290.3438 367.4844,290.3438 C367.1875,290.3438 366.9844,290.4375 366.7656,290.75 L366.5938,290.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="83" x="384.75" y="299.8467">TomlConfig</text><line style="stroke:#181818;stroke-width:0.5;" x1="255" x2="565" y1="311" y2="311"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="233" x="260" y="327.9951">agent: HashMap<String, Agent></text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="300" x="260" y="344.292">hypervisor: HashMap<String, Hypervisor></text><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="127" x="260" y="360.5889">runtime: Runtime</text><line style="stroke:#181818;stroke-width:0.5;" x1="255" x2="565" y1="367.8906" y2="367.8906"/><ellipse cx="265" cy="381.5391" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="112" x="274" y="384.8857">load_from_file()</text><ellipse cx="265" cy="397.8359" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="144" x="274" y="401.1826">load_raw_from_file()</text><ellipse cx="265" cy="414.1328" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="40" x="274" y="417.4795">load()</text><ellipse cx="265" cy="430.4297" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="67" x="274" y="433.7764">validate()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="262" y="443.7266"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="175" x="274" y="450.0732">get_default_config_file()</text></g><!--MD5=[3df83ebb488701c1bfe1401fb1d1ff46]
|
||||
class blockdev_info--><g id="elem_blockdev_info"><rect codeLine="28" fill="#F1F1F1" height="48" id="blockdev_info" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="133" x="321.5" y="721"/><ellipse cx="336.5" cy="737" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M338.8438,732.6719 C337.9063,732.2344 337.3125,732.0938 336.4375,732.0938 C333.8125,732.0938 331.8125,734.1719 331.8125,736.8906 L331.8125,738.0156 C331.8125,740.5938 333.9219,742.4844 336.8125,742.4844 C338.0313,742.4844 339.1875,742.1875 339.9375,741.6406 C340.5156,741.2344 340.8438,740.7813 340.8438,740.3906 C340.8438,739.9375 340.4531,739.5469 339.9844,739.5469 C339.7656,739.5469 339.5625,739.625 339.375,739.8125 C338.9219,740.2969 338.9219,740.2969 338.7344,740.3906 C338.3125,740.6563 337.625,740.7813 336.8594,740.7813 C334.8125,740.7813 333.5156,739.6875 333.5156,737.9844 L333.5156,736.8906 C333.5156,735.1094 334.7656,733.7969 336.5,733.7969 C337.0781,733.7969 337.6875,733.9531 338.1563,734.2031 C338.6406,734.4844 338.8125,734.7031 338.9063,735.1094 C338.9688,735.5156 339,735.6406 339.1406,735.7656 C339.2813,735.9063 339.5156,736.0156 339.7344,736.0156 C340,736.0156 340.2656,735.875 340.4375,735.6563 C340.5469,735.5 340.5781,735.3125 340.5781,734.8906 L340.5781,733.4688 C340.5781,733.0313 340.5625,732.9063 340.4688,732.75 C340.3125,732.4844 340.0313,732.3438 339.7344,732.3438 C339.4375,732.3438 339.2344,732.4375 339.0156,732.75 L338.8438,732.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="101" x="350.5" y="741.8467">blockdev_info</text><line style="stroke:#181818;stroke-width:0.5;" x1="322.5" x2="453.5" y1="753" y2="753"/><line style="stroke:#181818;stroke-width:0.5;" x1="322.5" x2="453.5" y1="761" y2="761"/></g><!--MD5=[07a90a3bf8882e1898f25fb76e9245fd]
|
||||
class boot_info--><g id="elem_boot_info"><rect codeLine="30" fill="#F1F1F1" height="48" id="boot_info" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="102" x="490" y="721"/><ellipse cx="505" cy="737" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M507.3438,732.6719 C506.4063,732.2344 505.8125,732.0938 504.9375,732.0938 C502.3125,732.0938 500.3125,734.1719 500.3125,736.8906 L500.3125,738.0156 C500.3125,740.5938 502.4219,742.4844 505.3125,742.4844 C506.5313,742.4844 507.6875,742.1875 508.4375,741.6406 C509.0156,741.2344 509.3438,740.7813 509.3438,740.3906 C509.3438,739.9375 508.9531,739.5469 508.4844,739.5469 C508.2656,739.5469 508.0625,739.625 507.875,739.8125 C507.4219,740.2969 507.4219,740.2969 507.2344,740.3906 C506.8125,740.6563 506.125,740.7813 505.3594,740.7813 C503.3125,740.7813 502.0156,739.6875 502.0156,737.9844 L502.0156,736.8906 C502.0156,735.1094 503.2656,733.7969 505,733.7969 C505.5781,733.7969 506.1875,733.9531 506.6563,734.2031 C507.1406,734.4844 507.3125,734.7031 507.4063,735.1094 C507.4688,735.5156 507.5,735.6406 507.6406,735.7656 C507.7813,735.9063 508.0156,736.0156 508.2344,736.0156 C508.5,736.0156 508.7656,735.875 508.9375,735.6563 C509.0469,735.5 509.0781,735.3125 509.0781,734.8906 L509.0781,733.4688 C509.0781,733.0313 509.0625,732.9063 508.9688,732.75 C508.8125,732.4844 508.5313,732.3438 508.2344,732.3438 C507.9375,732.3438 507.7344,732.4375 507.5156,732.75 L507.3438,732.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="70" x="519" y="741.8467">boot_info</text><line style="stroke:#181818;stroke-width:0.5;" x1="491" x2="591" y1="753" y2="753"/><line style="stroke:#181818;stroke-width:0.5;" x1="491" x2="591" y1="761" y2="761"/></g><!--MD5=[943fcfe90cdc5d40eea176478e39e489]
|
||||
class cpu_info--><g id="elem_cpu_info"><rect codeLine="32" fill="#F1F1F1" height="48" id="cpu_info" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="93" x="1089.5" y="572.5"/><ellipse cx="1104.5" cy="588.5" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M1106.8438,584.1719 C1105.9063,583.7344 1105.3125,583.5938 1104.4375,583.5938 C1101.8125,583.5938 1099.8125,585.6719 1099.8125,588.3906 L1099.8125,589.5156 C1099.8125,592.0938 1101.9219,593.9844 1104.8125,593.9844 C1106.0313,593.9844 1107.1875,593.6875 1107.9375,593.1406 C1108.5156,592.7344 1108.8438,592.2813 1108.8438,591.8906 C1108.8438,591.4375 1108.4531,591.0469 1107.9844,591.0469 C1107.7656,591.0469 1107.5625,591.125 1107.375,591.3125 C1106.9219,591.7969 1106.9219,591.7969 1106.7344,591.8906 C1106.3125,592.1563 1105.625,592.2813 1104.8594,592.2813 C1102.8125,592.2813 1101.5156,591.1875 1101.5156,589.4844 L1101.5156,588.3906 C1101.5156,586.6094 1102.7656,585.2969 1104.5,585.2969 C1105.0781,585.2969 1105.6875,585.4531 1106.1563,585.7031 C1106.6406,585.9844 1106.8125,586.2031 1106.9063,586.6094 C1106.9688,587.0156 1107,587.1406 1107.1406,587.2656 C1107.2813,587.4063 1107.5156,587.5156 1107.7344,587.5156 C1108,587.5156 1108.2656,587.375 1108.4375,587.1563 C1108.5469,587 1108.5781,586.8125 1108.5781,586.3906 L1108.5781,584.9688 C1108.5781,584.5313 1108.5625,584.4063 1108.4688,584.25 C1108.3125,583.9844 1108.0313,583.8438 1107.7344,583.8438 C1107.4375,583.8438 1107.2344,583.9375 1107.0156,584.25 L1106.8438,584.1719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="61" x="1118.5" y="593.3467">cpu_info</text><line style="stroke:#181818;stroke-width:0.5;" x1="1090.5" x2="1181.5" y1="604.5" y2="604.5"/><line style="stroke:#181818;stroke-width:0.5;" x1="1090.5" x2="1181.5" y1="612.5" y2="612.5"/></g><!--MD5=[dafde80c53158477244574fa147b5aea]
|
||||
class debug_info--><g id="elem_debug_info"><rect codeLine="34" fill="#F1F1F1" height="48" id="debug_info" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="112" x="627" y="721"/><ellipse cx="642" cy="737" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M644.3438,732.6719 C643.4063,732.2344 642.8125,732.0938 641.9375,732.0938 C639.3125,732.0938 637.3125,734.1719 637.3125,736.8906 L637.3125,738.0156 C637.3125,740.5938 639.4219,742.4844 642.3125,742.4844 C643.5313,742.4844 644.6875,742.1875 645.4375,741.6406 C646.0156,741.2344 646.3438,740.7813 646.3438,740.3906 C646.3438,739.9375 645.9531,739.5469 645.4844,739.5469 C645.2656,739.5469 645.0625,739.625 644.875,739.8125 C644.4219,740.2969 644.4219,740.2969 644.2344,740.3906 C643.8125,740.6563 643.125,740.7813 642.3594,740.7813 C640.3125,740.7813 639.0156,739.6875 639.0156,737.9844 L639.0156,736.8906 C639.0156,735.1094 640.2656,733.7969 642,733.7969 C642.5781,733.7969 643.1875,733.9531 643.6563,734.2031 C644.1406,734.4844 644.3125,734.7031 644.4063,735.1094 C644.4688,735.5156 644.5,735.6406 644.6406,735.7656 C644.7813,735.9063 645.0156,736.0156 645.2344,736.0156 C645.5,736.0156 645.7656,735.875 645.9375,735.6563 C646.0469,735.5 646.0781,735.3125 646.0781,734.8906 L646.0781,733.4688 C646.0781,733.0313 646.0625,732.9063 645.9688,732.75 C645.8125,732.4844 645.5313,732.3438 645.2344,732.3438 C644.9375,732.3438 644.7344,732.4375 644.5156,732.75 L644.3438,732.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="80" x="656" y="741.8467">debug_info</text><line style="stroke:#181818;stroke-width:0.5;" x1="628" x2="738" y1="753" y2="753"/><line style="stroke:#181818;stroke-width:0.5;" x1="628" x2="738" y1="761" y2="761"/></g><!--MD5=[709174d258c54d86a4dc1805c7737cab]
|
||||
class device_info--><g id="elem_device_info"><rect codeLine="36" fill="#F1F1F1" height="48" id="device_info" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="114" x="345" y="572.5"/><ellipse cx="360" cy="588.5" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M362.3438,584.1719 C361.4063,583.7344 360.8125,583.5938 359.9375,583.5938 C357.3125,583.5938 355.3125,585.6719 355.3125,588.3906 L355.3125,589.5156 C355.3125,592.0938 357.4219,593.9844 360.3125,593.9844 C361.5313,593.9844 362.6875,593.6875 363.4375,593.1406 C364.0156,592.7344 364.3438,592.2813 364.3438,591.8906 C364.3438,591.4375 363.9531,591.0469 363.4844,591.0469 C363.2656,591.0469 363.0625,591.125 362.875,591.3125 C362.4219,591.7969 362.4219,591.7969 362.2344,591.8906 C361.8125,592.1563 361.125,592.2813 360.3594,592.2813 C358.3125,592.2813 357.0156,591.1875 357.0156,589.4844 L357.0156,588.3906 C357.0156,586.6094 358.2656,585.2969 360,585.2969 C360.5781,585.2969 361.1875,585.4531 361.6563,585.7031 C362.1406,585.9844 362.3125,586.2031 362.4063,586.6094 C362.4688,587.0156 362.5,587.1406 362.6406,587.2656 C362.7813,587.4063 363.0156,587.5156 363.2344,587.5156 C363.5,587.5156 363.7656,587.375 363.9375,587.1563 C364.0469,587 364.0781,586.8125 364.0781,586.3906 L364.0781,584.9688 C364.0781,584.5313 364.0625,584.4063 363.9688,584.25 C363.8125,583.9844 363.5313,583.8438 363.2344,583.8438 C362.9375,583.8438 362.7344,583.9375 362.5156,584.25 L362.3438,584.1719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="82" x="374" y="593.3467">device_info</text><line style="stroke:#181818;stroke-width:0.5;" x1="346" x2="458" y1="604.5" y2="604.5"/><line style="stroke:#181818;stroke-width:0.5;" x1="346" x2="458" y1="612.5" y2="612.5"/></g><!--MD5=[80e2cb146ae92867d04633e19bc6c7a0]
|
||||
class machine_info--><g id="elem_machine_info"><rect codeLine="38" fill="#F1F1F1" height="48" id="machine_info" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="128" x="182" y="572.5"/><ellipse cx="197" cy="588.5" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M199.3438,584.1719 C198.4063,583.7344 197.8125,583.5938 196.9375,583.5938 C194.3125,583.5938 192.3125,585.6719 192.3125,588.3906 L192.3125,589.5156 C192.3125,592.0938 194.4219,593.9844 197.3125,593.9844 C198.5313,593.9844 199.6875,593.6875 200.4375,593.1406 C201.0156,592.7344 201.3438,592.2813 201.3438,591.8906 C201.3438,591.4375 200.9531,591.0469 200.4844,591.0469 C200.2656,591.0469 200.0625,591.125 199.875,591.3125 C199.4219,591.7969 199.4219,591.7969 199.2344,591.8906 C198.8125,592.1563 198.125,592.2813 197.3594,592.2813 C195.3125,592.2813 194.0156,591.1875 194.0156,589.4844 L194.0156,588.3906 C194.0156,586.6094 195.2656,585.2969 197,585.2969 C197.5781,585.2969 198.1875,585.4531 198.6563,585.7031 C199.1406,585.9844 199.3125,586.2031 199.4063,586.6094 C199.4688,587.0156 199.5,587.1406 199.6406,587.2656 C199.7813,587.4063 200.0156,587.5156 200.2344,587.5156 C200.5,587.5156 200.7656,587.375 200.9375,587.1563 C201.0469,587 201.0781,586.8125 201.0781,586.3906 L201.0781,584.9688 C201.0781,584.5313 201.0625,584.4063 200.9688,584.25 C200.8125,583.9844 200.5313,583.8438 200.2344,583.8438 C199.9375,583.8438 199.7344,583.9375 199.5156,584.25 L199.3438,584.1719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="96" x="211" y="593.3467">machine_info</text><line style="stroke:#181818;stroke-width:0.5;" x1="183" x2="309" y1="604.5" y2="604.5"/><line style="stroke:#181818;stroke-width:0.5;" x1="183" x2="309" y1="612.5" y2="612.5"/></g><!--MD5=[51fde411b48d0cbe229a2d16b1ccec06]
|
||||
class memory_info--><g id="elem_memory_info"><rect codeLine="40" fill="#F1F1F1" height="48" id="memory_info" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="127" x="927.5" y="572.5"/><ellipse cx="942.5" cy="588.5" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M944.8438,584.1719 C943.9063,583.7344 943.3125,583.5938 942.4375,583.5938 C939.8125,583.5938 937.8125,585.6719 937.8125,588.3906 L937.8125,589.5156 C937.8125,592.0938 939.9219,593.9844 942.8125,593.9844 C944.0313,593.9844 945.1875,593.6875 945.9375,593.1406 C946.5156,592.7344 946.8438,592.2813 946.8438,591.8906 C946.8438,591.4375 946.4531,591.0469 945.9844,591.0469 C945.7656,591.0469 945.5625,591.125 945.375,591.3125 C944.9219,591.7969 944.9219,591.7969 944.7344,591.8906 C944.3125,592.1563 943.625,592.2813 942.8594,592.2813 C940.8125,592.2813 939.5156,591.1875 939.5156,589.4844 L939.5156,588.3906 C939.5156,586.6094 940.7656,585.2969 942.5,585.2969 C943.0781,585.2969 943.6875,585.4531 944.1563,585.7031 C944.6406,585.9844 944.8125,586.2031 944.9063,586.6094 C944.9688,587.0156 945,587.1406 945.1406,587.2656 C945.2813,587.4063 945.5156,587.5156 945.7344,587.5156 C946,587.5156 946.2656,587.375 946.4375,587.1563 C946.5469,587 946.5781,586.8125 946.5781,586.3906 L946.5781,584.9688 C946.5781,584.5313 946.5625,584.4063 946.4688,584.25 C946.3125,583.9844 946.0313,583.8438 945.7344,583.8438 C945.4375,583.8438 945.2344,583.9375 945.0156,584.25 L944.8438,584.1719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="95" x="956.5" y="593.3467">memory_info</text><line style="stroke:#181818;stroke-width:0.5;" x1="928.5" x2="1053.5" y1="604.5" y2="604.5"/><line style="stroke:#181818;stroke-width:0.5;" x1="928.5" x2="1053.5" y1="612.5" y2="612.5"/></g><!--MD5=[930ee312a2ff2763bb01cb09bf7e582b]
|
||||
class network_info--><g id="elem_network_info"><rect codeLine="42" fill="#F1F1F1" height="48" id="network_info" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="127" x="765.5" y="572.5"/><ellipse cx="780.5" cy="588.5" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M782.8438,584.1719 C781.9063,583.7344 781.3125,583.5938 780.4375,583.5938 C777.8125,583.5938 775.8125,585.6719 775.8125,588.3906 L775.8125,589.5156 C775.8125,592.0938 777.9219,593.9844 780.8125,593.9844 C782.0313,593.9844 783.1875,593.6875 783.9375,593.1406 C784.5156,592.7344 784.8438,592.2813 784.8438,591.8906 C784.8438,591.4375 784.4531,591.0469 783.9844,591.0469 C783.7656,591.0469 783.5625,591.125 783.375,591.3125 C782.9219,591.7969 782.9219,591.7969 782.7344,591.8906 C782.3125,592.1563 781.625,592.2813 780.8594,592.2813 C778.8125,592.2813 777.5156,591.1875 777.5156,589.4844 L777.5156,588.3906 C777.5156,586.6094 778.7656,585.2969 780.5,585.2969 C781.0781,585.2969 781.6875,585.4531 782.1563,585.7031 C782.6406,585.9844 782.8125,586.2031 782.9063,586.6094 C782.9688,587.0156 783,587.1406 783.1406,587.2656 C783.2813,587.4063 783.5156,587.5156 783.7344,587.5156 C784,587.5156 784.2656,587.375 784.4375,587.1563 C784.5469,587 784.5781,586.8125 784.5781,586.3906 L784.5781,584.9688 C784.5781,584.5313 784.5625,584.4063 784.4688,584.25 C784.3125,583.9844 784.0313,583.8438 783.7344,583.8438 C783.4375,583.8438 783.2344,583.9375 783.0156,584.25 L782.8438,584.1719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="95" x="794.5" y="593.3467">network_info</text><line style="stroke:#181818;stroke-width:0.5;" x1="766.5" x2="891.5" y1="604.5" y2="604.5"/><line style="stroke:#181818;stroke-width:0.5;" x1="766.5" x2="891.5" y1="612.5" y2="612.5"/></g><!--MD5=[8eebe0bf7397aac919c7d6fe02490cf6]
|
||||
class security_info--><g id="elem_security_info"><rect codeLine="44" fill="#F1F1F1" height="48" id="security_info" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="124" x="23" y="572.5"/><ellipse cx="38" cy="588.5" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M40.3438,584.1719 C39.4063,583.7344 38.8125,583.5938 37.9375,583.5938 C35.3125,583.5938 33.3125,585.6719 33.3125,588.3906 L33.3125,589.5156 C33.3125,592.0938 35.4219,593.9844 38.3125,593.9844 C39.5313,593.9844 40.6875,593.6875 41.4375,593.1406 C42.0156,592.7344 42.3438,592.2813 42.3438,591.8906 C42.3438,591.4375 41.9531,591.0469 41.4844,591.0469 C41.2656,591.0469 41.0625,591.125 40.875,591.3125 C40.4219,591.7969 40.4219,591.7969 40.2344,591.8906 C39.8125,592.1563 39.125,592.2813 38.3594,592.2813 C36.3125,592.2813 35.0156,591.1875 35.0156,589.4844 L35.0156,588.3906 C35.0156,586.6094 36.2656,585.2969 38,585.2969 C38.5781,585.2969 39.1875,585.4531 39.6563,585.7031 C40.1406,585.9844 40.3125,586.2031 40.4063,586.6094 C40.4688,587.0156 40.5,587.1406 40.6406,587.2656 C40.7813,587.4063 41.0156,587.5156 41.2344,587.5156 C41.5,587.5156 41.7656,587.375 41.9375,587.1563 C42.0469,587 42.0781,586.8125 42.0781,586.3906 L42.0781,584.9688 C42.0781,584.5313 42.0625,584.4063 41.9688,584.25 C41.8125,583.9844 41.5313,583.8438 41.2344,583.8438 C40.9375,583.8438 40.7344,583.9375 40.5156,584.25 L40.3438,584.1719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="92" x="52" y="593.3467">security_info</text><line style="stroke:#181818;stroke-width:0.5;" x1="24" x2="146" y1="604.5" y2="604.5"/><line style="stroke:#181818;stroke-width:0.5;" x1="24" x2="146" y1="612.5" y2="612.5"/></g><!--MD5=[3c1f2944d03bf21933b185d462c61e23]
|
||||
class shared_fs--><g id="elem_shared_fs"><rect codeLine="46" fill="#F1F1F1" height="48" id="shared_fs" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="100" x="774" y="721"/><ellipse cx="789" cy="737" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M791.3438,732.6719 C790.4063,732.2344 789.8125,732.0938 788.9375,732.0938 C786.3125,732.0938 784.3125,734.1719 784.3125,736.8906 L784.3125,738.0156 C784.3125,740.5938 786.4219,742.4844 789.3125,742.4844 C790.5313,742.4844 791.6875,742.1875 792.4375,741.6406 C793.0156,741.2344 793.3438,740.7813 793.3438,740.3906 C793.3438,739.9375 792.9531,739.5469 792.4844,739.5469 C792.2656,739.5469 792.0625,739.625 791.875,739.8125 C791.4219,740.2969 791.4219,740.2969 791.2344,740.3906 C790.8125,740.6563 790.125,740.7813 789.3594,740.7813 C787.3125,740.7813 786.0156,739.6875 786.0156,737.9844 L786.0156,736.8906 C786.0156,735.1094 787.2656,733.7969 789,733.7969 C789.5781,733.7969 790.1875,733.9531 790.6563,734.2031 C791.1406,734.4844 791.3125,734.7031 791.4063,735.1094 C791.4688,735.5156 791.5,735.6406 791.6406,735.7656 C791.7813,735.9063 792.0156,736.0156 792.2344,736.0156 C792.5,736.0156 792.7656,735.875 792.9375,735.6563 C793.0469,735.5 793.0781,735.3125 793.0781,734.8906 L793.0781,733.4688 C793.0781,733.0313 793.0625,732.9063 792.9688,732.75 C792.8125,732.4844 792.5313,732.3438 792.2344,732.3438 C791.9375,732.3438 791.7344,732.4375 791.5156,732.75 L791.3438,732.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="68" x="803" y="741.8467">shared_fs</text><line style="stroke:#181818;stroke-width:0.5;" x1="775" x2="873" y1="753" y2="753"/><line style="stroke:#181818;stroke-width:0.5;" x1="775" x2="873" y1="761" y2="761"/></g><!--MD5=[0a81fe9965a9dd8a4ead36d7be72d836]
|
||||
class Hypervisor--><g id="elem_Hypervisor"><rect codeLine="48" fill="#F1F1F1" height="129.4844" id="Hypervisor" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="236" x="494" y="532"/><ellipse cx="569.25" cy="548" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M571.5938,543.6719 C570.6563,543.2344 570.0625,543.0938 569.1875,543.0938 C566.5625,543.0938 564.5625,545.1719 564.5625,547.8906 L564.5625,549.0156 C564.5625,551.5938 566.6719,553.4844 569.5625,553.4844 C570.7813,553.4844 571.9375,553.1875 572.6875,552.6406 C573.2656,552.2344 573.5938,551.7813 573.5938,551.3906 C573.5938,550.9375 573.2031,550.5469 572.7344,550.5469 C572.5156,550.5469 572.3125,550.625 572.125,550.8125 C571.6719,551.2969 571.6719,551.2969 571.4844,551.3906 C571.0625,551.6563 570.375,551.7813 569.6094,551.7813 C567.5625,551.7813 566.2656,550.6875 566.2656,548.9844 L566.2656,547.8906 C566.2656,546.1094 567.5156,544.7969 569.25,544.7969 C569.8281,544.7969 570.4375,544.9531 570.9063,545.2031 C571.3906,545.4844 571.5625,545.7031 571.6563,546.1094 C571.7188,546.5156 571.75,546.6406 571.8906,546.7656 C572.0313,546.9063 572.2656,547.0156 572.4844,547.0156 C572.75,547.0156 573.0156,546.875 573.1875,546.6563 C573.2969,546.5 573.3281,546.3125 573.3281,545.8906 L573.3281,544.4688 C573.3281,544.0313 573.3125,543.9063 573.2188,543.75 C573.0625,543.4844 572.7813,543.3438 572.4844,543.3438 C572.1875,543.3438 571.9844,543.4375 571.7656,543.75 L571.5938,543.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="77" x="589.75" y="552.8467">Hypervisor</text><line style="stroke:#181818;stroke-width:0.5;" x1="495" x2="729" y1="564" y2="564"/><line style="stroke:#181818;stroke-width:0.5;" x1="495" x2="729" y1="572" y2="572"/><ellipse cx="505" cy="585.6484" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="191" x="514" y="588.9951">validate_hypervisor_path()</text><ellipse cx="505" cy="601.9453" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="210" x="514" y="605.292">validate_hypervisor_ctlpath()</text><ellipse cx="505" cy="618.2422" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="150" x="514" y="621.5889">validate_jailer_path()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="502" y="631.5391"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="105" x="514" y="637.8857">adjust_config()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="502" y="647.8359"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="67" x="514" y="654.1826">validate()</text></g><!--MD5=[eac946183a641505cbae743e3812c86c]
|
||||
class dragonball--><g id="elem_dragonball"><rect codeLine="70" fill="#F1F1F1" height="162.0781" id="dragonball" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="162" x="571" y="42"/><ellipse cx="610.3" cy="58" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M612.6438,53.6719 C611.7063,53.2344 611.1125,53.0938 610.2375,53.0938 C607.6125,53.0938 605.6125,55.1719 605.6125,57.8906 L605.6125,59.0156 C605.6125,61.5938 607.7219,63.4844 610.6125,63.4844 C611.8313,63.4844 612.9875,63.1875 613.7375,62.6406 C614.3156,62.2344 614.6438,61.7813 614.6438,61.3906 C614.6438,60.9375 614.2531,60.5469 613.7844,60.5469 C613.5656,60.5469 613.3625,60.625 613.175,60.8125 C612.7219,61.2969 612.7219,61.2969 612.5344,61.3906 C612.1125,61.6563 611.425,61.7813 610.6594,61.7813 C608.6125,61.7813 607.3156,60.6875 607.3156,58.9844 L607.3156,57.8906 C607.3156,56.1094 608.5656,54.7969 610.3,54.7969 C610.8781,54.7969 611.4875,54.9531 611.9563,55.2031 C612.4406,55.4844 612.6125,55.7031 612.7063,56.1094 C612.7688,56.5156 612.8,56.6406 612.9406,56.7656 C613.0813,56.9063 613.3156,57.0156 613.5344,57.0156 C613.8,57.0156 614.0656,56.875 614.2375,56.6563 C614.3469,56.5 614.3781,56.3125 614.3781,55.8906 L614.3781,54.4688 C614.3781,54.0313 614.3625,53.9063 614.2688,53.75 C614.1125,53.4844 613.8313,53.3438 613.5344,53.3438 C613.2375,53.3438 613.0344,53.4375 612.8156,53.75 L612.6438,53.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="76" x="629.7" y="62.8467">dragonball</text><line style="stroke:#181818;stroke-width:0.5;" x1="572" x2="732" y1="74" y2="74"/><line style="stroke:#181818;stroke-width:0.5;" x1="572" x2="732" y1="82" y2="82"/><ellipse cx="582" cy="95.6484" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="39" x="591" y="98.9951">new()</text><ellipse cx="582" cy="111.9453" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="67" x="591" y="115.292">register()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="579" y="125.2422"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="591" y="131.5889">name()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="579" y="141.5391"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="105" x="591" y="147.8857">adjust_config()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="579" y="157.8359"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="67" x="591" y="164.1826">validate()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="579" y="174.1328"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="136" x="591" y="180.4795">get_min_memory()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="579" y="190.4297"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="112" x="591" y="196.7764">get_max_cpus()</text></g><!--MD5=[ce848d17456a91e28fb1bacf339a3a80]
|
||||
class qemu--><g id="elem_qemu"><rect codeLine="80" fill="#F1F1F1" height="162.0781" id="qemu" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="162" x="768" y="42"/><ellipse cx="824.75" cy="58" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M827.0938,53.6719 C826.1563,53.2344 825.5625,53.0938 824.6875,53.0938 C822.0625,53.0938 820.0625,55.1719 820.0625,57.8906 L820.0625,59.0156 C820.0625,61.5938 822.1719,63.4844 825.0625,63.4844 C826.2813,63.4844 827.4375,63.1875 828.1875,62.6406 C828.7656,62.2344 829.0938,61.7813 829.0938,61.3906 C829.0938,60.9375 828.7031,60.5469 828.2344,60.5469 C828.0156,60.5469 827.8125,60.625 827.625,60.8125 C827.1719,61.2969 827.1719,61.2969 826.9844,61.3906 C826.5625,61.6563 825.875,61.7813 825.1094,61.7813 C823.0625,61.7813 821.7656,60.6875 821.7656,58.9844 L821.7656,57.8906 C821.7656,56.1094 823.0156,54.7969 824.75,54.7969 C825.3281,54.7969 825.9375,54.9531 826.4063,55.2031 C826.8906,55.4844 827.0625,55.7031 827.1563,56.1094 C827.2188,56.5156 827.25,56.6406 827.3906,56.7656 C827.5313,56.9063 827.7656,57.0156 827.9844,57.0156 C828.25,57.0156 828.5156,56.875 828.6875,56.6563 C828.7969,56.5 828.8281,56.3125 828.8281,55.8906 L828.8281,54.4688 C828.8281,54.0313 828.8125,53.9063 828.7188,53.75 C828.5625,53.4844 828.2813,53.3438 827.9844,53.3438 C827.6875,53.3438 827.4844,53.4375 827.2656,53.75 L827.0938,53.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="40" x="845.25" y="62.8467">qemu</text><line style="stroke:#181818;stroke-width:0.5;" x1="769" x2="929" y1="74" y2="74"/><line style="stroke:#181818;stroke-width:0.5;" x1="769" x2="929" y1="82" y2="82"/><ellipse cx="779" cy="95.6484" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="39" x="788" y="98.9951">new()</text><ellipse cx="779" cy="111.9453" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="67" x="788" y="115.292">register()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="776" y="125.2422"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="788" y="131.5889">name()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="776" y="141.5391"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="105" x="788" y="147.8857">adjust_config()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="776" y="157.8359"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="67" x="788" y="164.1826">validate()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="776" y="174.1328"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="136" x="788" y="180.4795">get_min_memory()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="776" y="190.4297"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="112" x="788" y="196.7764">get_max_cpus()</text></g><!--MD5=[130c22a499add137713f736e88c2785b]
|
||||
class cloudHypervisor--><g id="elem_cloudHypervisor"><rect codeLine="90" fill="#F1F1F1" height="162.0781" id="cloudHypervisor" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:0.5;" width="162" x="965" y="42"/><ellipse cx="986.75" cy="58" fill="#ADD1B2" rx="11" ry="11" style="stroke:#181818;stroke-width:1.0;"/><path d="M989.0938,53.6719 C988.1563,53.2344 987.5625,53.0938 986.6875,53.0938 C984.0625,53.0938 982.0625,55.1719 982.0625,57.8906 L982.0625,59.0156 C982.0625,61.5938 984.1719,63.4844 987.0625,63.4844 C988.2813,63.4844 989.4375,63.1875 990.1875,62.6406 C990.7656,62.2344 991.0938,61.7813 991.0938,61.3906 C991.0938,60.9375 990.7031,60.5469 990.2344,60.5469 C990.0156,60.5469 989.8125,60.625 989.625,60.8125 C989.1719,61.2969 989.1719,61.2969 988.9844,61.3906 C988.5625,61.6563 987.875,61.7813 987.1094,61.7813 C985.0625,61.7813 983.7656,60.6875 983.7656,58.9844 L983.7656,57.8906 C983.7656,56.1094 985.0156,54.7969 986.75,54.7969 C987.3281,54.7969 987.9375,54.9531 988.4063,55.2031 C988.8906,55.4844 989.0625,55.7031 989.1563,56.1094 C989.2188,56.5156 989.25,56.6406 989.3906,56.7656 C989.5313,56.9063 989.7656,57.0156 989.9844,57.0156 C990.25,57.0156 990.5156,56.875 990.6875,56.6563 C990.7969,56.5 990.8281,56.3125 990.8281,55.8906 L990.8281,54.4688 C990.8281,54.0313 990.8125,53.9063 990.7188,53.75 C990.5625,53.4844 990.2813,53.3438 989.9844,53.3438 C989.6875,53.3438 989.4844,53.4375 989.2656,53.75 L989.0938,53.6719 Z " fill="#000000"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="1002.25" y="62.8467">cloudHypervisor</text><line style="stroke:#181818;stroke-width:0.5;" x1="966" x2="1126" y1="74" y2="74"/><line style="stroke:#181818;stroke-width:0.5;" x1="966" x2="1126" y1="82" y2="82"/><ellipse cx="976" cy="95.6484" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="39" x="985" y="98.9951">new()</text><ellipse cx="976" cy="111.9453" fill="#84BE84" rx="3" ry="3" style="stroke:#038048;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="67" x="985" y="115.292">register()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="973" y="125.2422"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="50" x="985" y="131.5889">name()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="973" y="141.5391"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="105" x="985" y="147.8857">adjust_config()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="973" y="157.8359"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="67" x="985" y="164.1826">validate()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="973" y="174.1328"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="136" x="985" y="180.4795">get_min_memory()</text><rect fill="#F24D5C" height="6" style="stroke:#C82930;stroke-width:1.0;" width="6" x="973" y="190.4297"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="112" x="985" y="196.7764">get_max_cpus()</text></g><!--MD5=[e1cdd066bc29e668f65fd4821c38c756]
|
||||
reverse link Hypervisor to blockdev_info--><g id="link_Hypervisor_blockdev_info"><path codeLine="56" d="M503.604,668.393 C474.497,687.429 445.065,706.6783 423.183,720.9898 " fill="none" id="Hypervisor-backto-blockdev_info" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="514.728,661.118,507.5172,661.0549,504.6855,667.6868,511.8964,667.7499,514.728,661.118" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[7fc396386bf8d2a0f798e64fa798295f]
|
||||
reverse link Hypervisor to boot_info--><g id="link_Hypervisor_boot_info"><path codeLine="57" d="M575.274,673.28 C566.897,690.564 558.612,707.6606 552.286,720.7133 " fill="none" id="Hypervisor-backto-boot_info" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="581.065,661.331,574.8486,664.9857,575.8312,672.1295,582.0476,668.4748,581.065,661.331" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[1ebb49ba2a4db51bc8166590b22d030a]
|
||||
reverse link Hypervisor to cpu_info--><g id="link_Hypervisor_cpu_info"><path codeLine="58" d="M681.263,523.53 C705.558,504.597 734.57,488.49 765.5,485 C797.409,481.4 1022.59,481.4 1054.5,485 C1062.43,485.895 1065.55,484.304 1072,489 C1100.62,509.837 1118.74,547.721 1128.13,572.496 " fill="none" id="Hypervisor-backto-cpu_info" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="671.148,531.789,678.3254,531.0929,680.4435,524.1999,673.266,524.896,671.148,531.789" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[9a8db0d6a0950fbb171d4777f5d8184b]
|
||||
reverse link Hypervisor to debug_info--><g id="link_Hypervisor_debug_info"><path codeLine="59" d="M648.726,673.28 C657.103,690.564 665.388,707.6606 671.714,720.7133 " fill="none" id="Hypervisor-backto-debug_info" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="642.935,661.331,641.9524,668.4748,648.1688,672.1295,649.1514,664.9857,642.935,661.331" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[ecacd4cd26bc197f90cd354b7a684ca2]
|
||||
link device_info to Hypervisor--><g id="link_device_info_Hypervisor"><path codeLine="60" d="M459.012,596.5 C466.295,596.5 473.578,596.5 480.862,596.5 " fill="none" id="device_info-to-Hypervisor" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="493.972,596.5,487.972,592.5,481.972,596.5,487.972,600.5,493.972,596.5" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[09317b023a93dcac53ddee6c2cfcc7e5]
|
||||
link machine_info to Hypervisor--><g id="link_machine_info_Hypervisor"><path codeLine="61" d="M257.646,572.446 C270.936,547.63 295.033,509.711 327,489 C333.696,484.662 336.572,485.895 344.5,485 C369.674,482.16 433.326,482.16 458.5,485 C489.43,488.49 518.442,504.597 542.737,523.53 " fill="none" id="machine_info-to-Hypervisor" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="552.852,531.789,550.734,524.896,543.5565,524.1999,545.6746,531.0929,552.852,531.789" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[c222af19cb04716dd07a3d3a7abefe4c]
|
||||
reverse link Hypervisor to memory_info--><g id="link_Hypervisor_memory_info"><path codeLine="62" d="M681.263,523.53 C705.558,504.597 734.57,488.49 765.5,485 C793.544,481.836 864.456,481.836 892.5,485 C900.428,485.895 903.304,484.662 910,489 C941.967,509.711 966.064,547.63 979.354,572.446 " fill="none" id="Hypervisor-backto-memory_info" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="671.148,531.789,678.3254,531.0929,680.4435,524.1999,673.266,524.896,671.148,531.789" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[572309a275970e67c373cdcbcf940a15]
|
||||
reverse link Hypervisor to network_info--><g id="link_Hypervisor_network_info"><path codeLine="63" d="M743.412,596.5 C750.725,596.5 758.038,596.5 765.351,596.5 " fill="none" id="Hypervisor-backto-network_info" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="730.248,596.5,736.248,600.5,742.248,596.5,736.248,592.5,730.248,596.5" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[a5f52857f2cb6be0e2752620d15064af]
|
||||
link security_info to Hypervisor--><g id="link_security_info_Hypervisor"><path codeLine="64" d="M96.207,572.449 C109.042,547.634 132.44,509.717 164,489 C170.67,484.622 173.572,485.895 181.5,485 C212.084,481.549 427.916,481.549 458.5,485 C489.43,488.49 518.442,504.597 542.737,523.53 " fill="none" id="security_info-to-Hypervisor" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="552.852,531.789,550.734,524.896,543.5565,524.1999,545.6746,531.0929,552.852,531.789" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[9f5975e9d2c0934f9424b619157b5536]
|
||||
reverse link Hypervisor to shared_fs--><g id="link_Hypervisor_shared_fs"><path codeLine="65" d="M714.953,668.644 C742.382,687.599 770.083,706.7413 790.702,720.9898 " fill="none" id="Hypervisor-backto-shared_fs" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="704.061,661.118,706.7236,667.8196,713.9337,667.9393,711.2711,661.2378,704.061,661.118" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[9be08e633cf478f902ff08a85eb049d1]
|
||||
reverse link ConfigOps to Hypervisor--><g id="link_ConfigOps_Hypervisor"><path codeLine="66" d="M652.576,428.402 C644.852,460.209 635.335,499.402 627.459,531.835 " fill="none" id="ConfigOps-backto-Hypervisor" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="645.835,426.496,657.357,408.712,659.44,429.799,645.835,426.496" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[4d606d397df52c406553e50dcf54fdff]
|
||||
reverse link TomlConfig to Hypervisor--><g id="link_TomlConfig_Hypervisor"><path codeLine="67" d="M497.574,467.195 C517.064,489.05 537.234,511.666 555.11,531.71 " fill="none" id="TomlConfig-backto-Hypervisor" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="#181818" points="488.677,457.219,489.6856,464.3592,496.6645,466.1744,495.6559,459.0342,488.677,457.219" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[eef3358ce4d784fa237eb23a2926f81f]
|
||||
link dragonball to ConfigPlugin--><g id="link_dragonball_ConfigPlugin"><path codeLine="101" d="M723.359,204.161 C732.443,214.769 741.521,225.578 750,236 C763.293,252.338 777.16,270.158 790.162,287.243 " fill="none" id="dragonball-to-ConfigPlugin" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="795.842,283.149,802.315,303.326,784.673,291.59,795.842,283.149" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[9cee432c8b2397e396af6165e94c5d29]
|
||||
link qemu to ConfigPlugin--><g id="link_qemu_ConfigPlugin"><path codeLine="102" d="M849,204.241 C849,229.531 849,257.528 849,283.068 " fill="none" id="qemu-to-ConfigPlugin" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="856,283.377,849,303.377,842,283.377,856,283.377" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[41ce5f6f25c608b93e7c22ea96a599a6]
|
||||
link cloudHypervisor to ConfigPlugin--><g id="link_cloudHypervisor_ConfigPlugin"><path codeLine="103" d="M980.949,204.241 C959.222,231.041 935.031,260.88 913.357,287.615 " fill="none" id="cloudHypervisor-to-ConfigPlugin" style="stroke:#181818;stroke-width:1.0;"/><polygon fill="none" points="918.612,292.249,900.579,303.377,907.737,283.432,918.612,292.249" style="stroke:#181818;stroke-width:1.0;"/></g><!--MD5=[0aa238e862ca84d6a981d5f8c43e151d]
|
||||
@startuml
|
||||
package config <<Rectangle>>{
|
||||
interface ConfigPlugin {
|
||||
-name()
|
||||
-adjust_config()
|
||||
-validate()
|
||||
-get_min_memory()
|
||||
-get_max_cpus()
|
||||
}
|
||||
|
||||
interface ConfigOps {
|
||||
-adjust_config()
|
||||
-validate()
|
||||
}
|
||||
|
||||
class TomlConfig {
|
||||
agent: HashMap<String, Agent>
|
||||
hypervisor: HashMap<String, Hypervisor>
|
||||
runtime: Runtime
|
||||
+load_from_file()
|
||||
+load_raw_from_file()
|
||||
+load()
|
||||
+ validate()
|
||||
-get_default_config_file()
|
||||
}
|
||||
}
|
||||
|
||||
package hypervisor_mod <<Rectangle>> #FFACAB {
|
||||
class blockdev_info{
|
||||
}
|
||||
class boot_info{
|
||||
}
|
||||
class cpu_info{
|
||||
}
|
||||
class debug_info{
|
||||
}
|
||||
class device_info{
|
||||
}
|
||||
class machine_info{
|
||||
}
|
||||
class memory_info{
|
||||
}
|
||||
class network_info{
|
||||
}
|
||||
class security_info{
|
||||
}
|
||||
class shared_fs{
|
||||
}
|
||||
class Hypervisor{
|
||||
+validate_hypervisor_path()
|
||||
+validate_hypervisor_ctlpath()
|
||||
+validate_jailer_path()
|
||||
-adjust_config()
|
||||
-validate()
|
||||
}
|
||||
}
|
||||
Hypervisor *-down- blockdev_info
|
||||
Hypervisor *-down- boot_info
|
||||
Hypervisor *-right- cpu_info
|
||||
Hypervisor *-down- debug_info
|
||||
Hypervisor *-left- device_info
|
||||
Hypervisor *-left- machine_info
|
||||
Hypervisor *-right- memory_info
|
||||
Hypervisor *-right- network_info
|
||||
Hypervisor *-left- security_info
|
||||
Hypervisor *-down- shared_fs
|
||||
ConfigOps <|-down- Hypervisor
|
||||
TomlConfig *-down- Hypervisor
|
||||
|
||||
package HYPERVISOR_PLUGINS <<Rectangle>> {
|
||||
class dragonball {
|
||||
+new()
|
||||
+register()
|
||||
-name()
|
||||
-adjust_config()
|
||||
-validate()
|
||||
-get_min_memory()
|
||||
-get_max_cpus()
|
||||
}
|
||||
|
||||
class qemu {
|
||||
+new()
|
||||
+register()
|
||||
-name()
|
||||
-adjust_config()
|
||||
-validate()
|
||||
-get_min_memory()
|
||||
-get_max_cpus()
|
||||
}
|
||||
|
||||
class cloudHypervisor {
|
||||
+new()
|
||||
+register()
|
||||
-name()
|
||||
-adjust_config()
|
||||
-validate()
|
||||
-get_min_memory()
|
||||
-get_max_cpus()
|
||||
}
|
||||
}
|
||||
|
||||
ConfigPlugin <|-up- dragonball
|
||||
ConfigPlugin <|-up- qemu
|
||||
ConfigPlugin <|-up- cloudHypervisor
|
||||
@enduml
|
||||
|
||||
PlantUML version 1.2022.8beta9(Unknown compile time)
|
||||
(GPL source distribution)
|
||||
Java Runtime: Java(TM) SE Runtime Environment
|
||||
JVM: Java HotSpot(TM) 64-Bit Server VM
|
||||
Default Encoding: UTF-8
|
||||
Language: en
|
||||
Country: US
|
||||
--></g></svg>
|
||||
|
After Width: | Height: | Size: 51 KiB |
60
src/runtime-rs/docs/images/vm-start.svg
Normal file
60
src/runtime-rs/docs/images/vm-start.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 23 KiB |
@@ -404,7 +404,8 @@ ifneq (,$(ACRNCMD))
|
||||
DEFMAXVCPUS_ACRN := 1
|
||||
DEFBLOCKSTORAGEDRIVER_ACRN := virtio-blk
|
||||
DEFNETWORKMODEL_ACRN := macvtap
|
||||
KERNEL_NAME_ACRN = $(call MAKE_KERNEL_NAME,$(KERNELTYPE))
|
||||
KERNELTYPE_ACRN = compressed
|
||||
KERNEL_NAME_ACRN = $(call MAKE_KERNEL_NAME,$(KERNELTYPE_ACRN))
|
||||
KERNELPATH_ACRN = $(KERNELDIR)/$(KERNEL_NAME_ACRN)
|
||||
endif
|
||||
|
||||
@@ -479,6 +480,7 @@ USER_VARS += FCVALIDJAILERPATHS
|
||||
USER_VARS += SYSCONFIG
|
||||
USER_VARS += IMAGENAME
|
||||
USER_VARS += IMAGEPATH
|
||||
USER_VARS += INITRDNAME
|
||||
USER_VARS += INITRDPATH
|
||||
USER_VARS += MACHINETYPE
|
||||
USER_VARS += KERNELDIR
|
||||
|
||||
@@ -30,7 +30,6 @@ const (
|
||||
cpuFlagLM = "lm"
|
||||
cpuFlagSVM = "svm"
|
||||
cpuFlagSSE4_1 = "sse4_1"
|
||||
kernelModvhm = "vhm_dev"
|
||||
kernelModvhost = "vhost"
|
||||
kernelModvhostnet = "vhost_net"
|
||||
kernelModvhostvsock = "vhost_vsock"
|
||||
@@ -46,7 +45,7 @@ const (
|
||||
cpuTypeUnknown = -1
|
||||
)
|
||||
|
||||
const acrnDevice = "/dev/acrn_vhm"
|
||||
const acrnDevice = "/dev/acrn_hsm"
|
||||
|
||||
// ioctl_ACRN_CREATE_VM is the IOCTL to create VM in ACRN.
|
||||
// Current Linux mainstream kernel doesn't have support for ACRN.
|
||||
@@ -54,18 +53,31 @@ const acrnDevice = "/dev/acrn_vhm"
|
||||
// Until the support is available, directly use the value instead
|
||||
// of macros.
|
||||
//https://github.com/kata-containers/runtime/issues/1784
|
||||
const ioctl_ACRN_CREATE_VM = 0x43000010 //nolint
|
||||
const ioctl_ACRN_DESTROY_VM = 0x43000011 //nolint
|
||||
const ioctl_ACRN_CREATE_VM = 0xC030A210 //nolint
|
||||
const ioctl_ACRN_PAUSE_VM = 0xA213 //nolint
|
||||
const ioctl_ACRN_DESTROY_VM = 0xA211 //nolint
|
||||
|
||||
type acrn_create_vm struct { //nolint
|
||||
vmid uint16 //nolint
|
||||
reserved0 uint16 //nolint
|
||||
vcpu_num uint16 //nolint
|
||||
reserved1 uint16 //nolint
|
||||
uuid [16]uint8
|
||||
vm_flag uint64 //nolint
|
||||
req_buf uint64 //nolint
|
||||
reserved2 [16]uint8 //nolint
|
||||
type acrn_vm_creation struct { //nolint
|
||||
vmid uint16 //nolint
|
||||
reserved0 uint16 //nolint
|
||||
vcpu_num uint16 //nolint
|
||||
reserved1 uint16 //nolint
|
||||
name [16]uint8
|
||||
vm_flag uint64 //nolint
|
||||
ioreq_buf uint64 //nolint
|
||||
cpu_affinity uint64 //nolint
|
||||
}
|
||||
|
||||
var io_request_page [4096]byte
|
||||
|
||||
type acrn_io_request struct { // nolint
|
||||
io_type uint32 // nolint
|
||||
completion_polling uint32 // nolint
|
||||
reserved0 [14]uint32 // nolint
|
||||
data [8]uint64 // nolint
|
||||
reserved1 uint32 // nolint
|
||||
kernel_handled uint32 // nolint
|
||||
processed uint32 // nolint
|
||||
}
|
||||
|
||||
// cpuType save the CPU type
|
||||
@@ -150,10 +162,6 @@ func setCPUtype(hypervisorType vc.HypervisorType) error {
|
||||
archGenuineIntel: "Intel Architecture CPU",
|
||||
}
|
||||
archRequiredKernelModules = map[string]kernelModule{
|
||||
kernelModvhm: {
|
||||
desc: "Intel ACRN",
|
||||
required: false,
|
||||
},
|
||||
kernelModvhost: {
|
||||
desc: msgKernelVirtio,
|
||||
required: false,
|
||||
@@ -162,6 +170,10 @@ func setCPUtype(hypervisorType vc.HypervisorType) error {
|
||||
desc: msgKernelVirtioNet,
|
||||
required: false,
|
||||
},
|
||||
kernelModvhostvsock: {
|
||||
desc: msgKernelVirtioVhostVsock,
|
||||
required: false,
|
||||
},
|
||||
}
|
||||
case "mock":
|
||||
archRequiredCPUFlags = map[string]string{
|
||||
@@ -247,19 +259,10 @@ func acrnIsUsable() error {
|
||||
defer syscall.Close(f)
|
||||
kataLog.WithField("device", acrnDevice).Info("device available")
|
||||
|
||||
acrnInst := vc.Acrn{}
|
||||
uuidStr, err := acrnInst.GetNextAvailableUUID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uuid, err := acrnInst.GetACRNUUIDBytes(uuidStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Converting UUID str to bytes failed, Err:%s", err)
|
||||
}
|
||||
|
||||
var createVM acrn_create_vm
|
||||
createVM.uuid = uuid
|
||||
var createVM acrn_vm_creation
|
||||
copy(createVM.name[:], "KataACRNVM")
|
||||
ioreq_buf := (*acrn_io_request)(unsafe.Pointer(&io_request_page))
|
||||
createVM.ioreq_buf = uint64(uintptr(unsafe.Pointer(ioreq_buf)))
|
||||
|
||||
ret, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
|
||||
uintptr(f),
|
||||
@@ -269,10 +272,23 @@ func acrnIsUsable() error {
|
||||
if errno == syscall.EBUSY {
|
||||
kataLog.WithField("reason", "another hypervisor running").Error("cannot create VM")
|
||||
}
|
||||
kataLog.WithFields(logrus.Fields{
|
||||
"ret": ret,
|
||||
"errno": errno,
|
||||
"VM_name": createVM.name,
|
||||
}).Info("Create VM Error")
|
||||
return errno
|
||||
}
|
||||
|
||||
ret, _, errno = syscall.Syscall(syscall.SYS_IOCTL,
|
||||
uintptr(f),
|
||||
uintptr(ioctl_ACRN_PAUSE_VM),
|
||||
0)
|
||||
if ret != 0 || errno != 0 {
|
||||
kataLog.WithFields(logrus.Fields{
|
||||
"ret": ret,
|
||||
"errno": errno,
|
||||
}).Info("Create VM Error")
|
||||
}).Info("PAUSE VM Error")
|
||||
return errno
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
path = "@QEMUPATH@"
|
||||
kernel = "@KERNELPATH@"
|
||||
image = "@IMAGEPATH@"
|
||||
# initrd = "@INITRDPATH@"
|
||||
machine_type = "@MACHINETYPE@"
|
||||
|
||||
# Enable confidential guest support.
|
||||
@@ -58,6 +59,12 @@ machine_type = "@MACHINETYPE@"
|
||||
# SEV certificate chain path
|
||||
#sev_cert_chain="@DEFSEVCERTCHAIN@"
|
||||
|
||||
# Choose AMD SEV-SNP confidential guests
|
||||
# In case of using confidential guests on AMD hardware that supports both SEV
|
||||
# and SEV-SNP, the following enables SEV-SNP guests. SEV guests are default.
|
||||
# Default false
|
||||
# sev_snp_guest = true
|
||||
|
||||
# Enable running QEMU VMM as a non-root user.
|
||||
# By default QEMU VMM run as root. When this is set to true, QEMU VMM process runs as
|
||||
# a non-root random user. See documentation for the limitations of this mode.
|
||||
|
||||
@@ -64,7 +64,7 @@ require (
|
||||
replace (
|
||||
github.com/containerd/containerd => github.com/confidential-containers/containerd v1.6.7-0.20220619164525-4b12e77e79dc
|
||||
github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.2
|
||||
github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.3
|
||||
github.com/opencontainers/runc => github.com/opencontainers/runc v1.1.3
|
||||
github.com/uber-go/atomic => go.uber.org/atomic v1.5.1
|
||||
google.golang.org/genproto => google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8
|
||||
)
|
||||
|
||||
@@ -159,7 +159,6 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
|
||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||
@@ -183,14 +182,12 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
|
||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/checkpoint-restore/checkpointctl v0.0.0-20220321135231-33f4a66335f0/go.mod h1:67kWC1PXQLR3lM/mmNnu3Kzn7K4TSWZAGUuQP1JSngk=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.2.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||
github.com/cilium/ebpf v0.7.0 h1:1k/q3ATgxSXRdrmPfH8d7YK0GfqVsEKZAX9dQZvs56k=
|
||||
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
@@ -291,7 +288,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
|
||||
@@ -1019,8 +1015,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
|
||||
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k=
|
||||
github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||
github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w=
|
||||
github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
|
||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20201121164853-7413a7f753e1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
@@ -1029,7 +1025,6 @@ github.com/opencontainers/runtime-spec v1.0.3-0.20211214071223-8958f93039ab h1:Y
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20211214071223-8958f93039ab/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20220714195903-17b3287fafb7/go.mod h1:/tgP02fPXGHkU3/qKK1Y0Db4yqNyGm03vLq/mzHzcS4=
|
||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||
github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo=
|
||||
github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||
@@ -1127,7 +1122,7 @@ github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZ
|
||||
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||
github.com/seccomp/libseccomp-golang v0.10.0 h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY=
|
||||
github.com/seccomp/libseccomp-golang v0.10.0/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.3.1/go.mod h1:o8hhjkbNl2gOamKUA/eNW3xUrntHT9L4W89W1nfj43U=
|
||||
@@ -1620,7 +1615,6 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/pkg/rootless"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
// only register the proto type
|
||||
crioption "github.com/containerd/containerd/pkg/runtimeoptions/v1"
|
||||
@@ -136,7 +137,7 @@ func create(ctx context.Context, s *service, r *taskAPI.CreateTaskRequest) (*con
|
||||
katautils.HandleFactory(ctx, vci, s.config)
|
||||
rootless.SetRootless(s.config.HypervisorConfig.Rootless)
|
||||
if rootless.IsRootless() {
|
||||
if err := configureNonRootHypervisor(s.config); err != nil {
|
||||
if err := configureNonRootHypervisor(s.config, r.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -308,13 +309,17 @@ func doMount(mounts []*containerd_types.Mount, rootfs string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func configureNonRootHypervisor(runtimeConfig *oci.RuntimeConfig) error {
|
||||
func configureNonRootHypervisor(runtimeConfig *oci.RuntimeConfig, sandboxId string) error {
|
||||
userName, err := utils.CreateVmmUser()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
shimLog.WithFields(logrus.Fields{
|
||||
"user_name": userName,
|
||||
"sandbox_id": sandboxId,
|
||||
}).WithError(err).Warn("configure non root hypervisor failed, delete the user")
|
||||
if err2 := utils.RemoveVmmUser(userName); err2 != nil {
|
||||
shimLog.WithField("userName", userName).WithError(err).Warn("failed to remove user")
|
||||
}
|
||||
@@ -335,7 +340,14 @@ func configureNonRootHypervisor(runtimeConfig *oci.RuntimeConfig) error {
|
||||
return err
|
||||
}
|
||||
runtimeConfig.HypervisorConfig.Uid = uint32(uid)
|
||||
runtimeConfig.HypervisorConfig.User = userName
|
||||
runtimeConfig.HypervisorConfig.Gid = uint32(gid)
|
||||
shimLog.WithFields(logrus.Fields{
|
||||
"user_name": userName,
|
||||
"uid": uid,
|
||||
"gid": gid,
|
||||
"sandbox_id": sandboxId,
|
||||
}).Debug("successfully created a non root user for the hypervisor")
|
||||
|
||||
userTmpDir := path.Join("/run/user/", fmt.Sprint(uid))
|
||||
_, err = os.Stat(userTmpDir)
|
||||
|
||||
@@ -60,6 +60,12 @@ func (device *BlockDevice) Attach(ctx context.Context, devReceiver api.DeviceRec
|
||||
return err
|
||||
}
|
||||
|
||||
hypervisorType := devReceiver.GetHypervisorType()
|
||||
if hypervisorType == "acrn" {
|
||||
deviceLogger().Debug("Special casing for ACRN to increment BlockIndex")
|
||||
index = index + 1
|
||||
}
|
||||
|
||||
drive := &config.BlockDrive{
|
||||
File: device.DeviceInfo.HostPath,
|
||||
Format: "raw",
|
||||
|
||||
@@ -231,6 +231,9 @@ const (
|
||||
// SEVGuest represents an SEV guest object
|
||||
SEVGuest ObjectType = "sev-guest"
|
||||
|
||||
// SNPGuest represents an SNP guest object
|
||||
SNPGuest ObjectType = "sev-snp-guest"
|
||||
|
||||
// SecExecGuest represents an s390x Secure Execution (Protected Virtualization in QEMU) object
|
||||
SecExecGuest ObjectType = "s390-pv-guest"
|
||||
// PEFGuest represent ppc64le PEF(Protected Execution Facility) object.
|
||||
@@ -311,6 +314,8 @@ func (object Object) Valid() bool {
|
||||
case TDXGuest:
|
||||
return object.ID != "" && object.File != "" && object.DeviceID != ""
|
||||
case SEVGuest:
|
||||
fallthrough
|
||||
case SNPGuest:
|
||||
return object.ID != "" && object.File != "" && object.CBitPos != 0 && object.ReducedPhysBits != 0
|
||||
case SecExecGuest:
|
||||
return object.ID != ""
|
||||
@@ -365,6 +370,8 @@ func (object Object) QemuParams(config *Config) []string {
|
||||
deviceParams = append(deviceParams, fmt.Sprintf("config-firmware-volume=%s", object.FirmwareVolume))
|
||||
}
|
||||
case SEVGuest:
|
||||
fallthrough
|
||||
case SNPGuest:
|
||||
objectParams = append(objectParams, string(object.Type))
|
||||
objectParams = append(objectParams, fmt.Sprintf("id=%s", object.ID))
|
||||
objectParams = append(objectParams, fmt.Sprintf("cbitpos=%d", object.CBitPos))
|
||||
|
||||
@@ -86,6 +86,7 @@ const defaultVhostUserStorePath string = "/var/run/kata-containers/vhost-user/"
|
||||
const defaultRxRateLimiterMaxRate = uint64(0)
|
||||
const defaultTxRateLimiterMaxRate = uint64(0)
|
||||
const defaultConfidentialGuest = false
|
||||
const defaultSevSnpGuest = false
|
||||
const defaultGuestSwap = false
|
||||
const defaultRootlessHypervisor = false
|
||||
const defaultDisableSeccomp = false
|
||||
|
||||
@@ -159,6 +159,7 @@ type hypervisor struct {
|
||||
DisableVhostNet bool `toml:"disable_vhost_net"`
|
||||
GuestMemoryDumpPaging bool `toml:"guest_memory_dump_paging"`
|
||||
ConfidentialGuest bool `toml:"confidential_guest"`
|
||||
SevSnpGuest bool `toml:"sev_snp_guest"`
|
||||
GuestSwap bool `toml:"enable_guest_swap"`
|
||||
Rootless bool `toml:"rootless"`
|
||||
DisableSeccomp bool `toml:"disable_seccomp"`
|
||||
@@ -838,6 +839,7 @@ func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
|
||||
GuestMemoryDumpPath: h.GuestMemoryDumpPath,
|
||||
GuestMemoryDumpPaging: h.GuestMemoryDumpPaging,
|
||||
ConfidentialGuest: h.ConfidentialGuest,
|
||||
SevSnpGuest: h.SevSnpGuest,
|
||||
GuestSwap: h.GuestSwap,
|
||||
Rootless: h.Rootless,
|
||||
LegacySerial: h.LegacySerial,
|
||||
@@ -1253,6 +1255,7 @@ func GetDefaultHypervisorConfig() vc.HypervisorConfig {
|
||||
TxRateLimiterMaxRate: defaultTxRateLimiterMaxRate,
|
||||
SGXEPCSize: defaultSGXEPCSize,
|
||||
ConfidentialGuest: defaultConfidentialGuest,
|
||||
SevSnpGuest: defaultSevSnpGuest,
|
||||
GuestSwap: defaultGuestSwap,
|
||||
Rootless: defaultRootlessHypervisor,
|
||||
DisableSeccomp: defaultDisableSeccomp,
|
||||
|
||||
26
src/runtime/vendor/github.com/bits-and-blooms/bitset/.gitignore
generated
vendored
26
src/runtime/vendor/github.com/bits-and-blooms/bitset/.gitignore
generated
vendored
@@ -1,26 +0,0 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
|
||||
target
|
||||
37
src/runtime/vendor/github.com/bits-and-blooms/bitset/.travis.yml
generated
vendored
37
src/runtime/vendor/github.com/bits-and-blooms/bitset/.travis.yml
generated
vendored
@@ -1,37 +0,0 @@
|
||||
language: go
|
||||
|
||||
sudo: false
|
||||
|
||||
branches:
|
||||
except:
|
||||
- release
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- travis
|
||||
|
||||
go:
|
||||
- "1.11.x"
|
||||
- tip
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
before_install:
|
||||
- if [ -n "$GH_USER" ]; then git config --global github.user ${GH_USER}; fi;
|
||||
- if [ -n "$GH_TOKEN" ]; then git config --global github.token ${GH_TOKEN}; fi;
|
||||
- go get github.com/mattn/goveralls
|
||||
|
||||
before_script:
|
||||
- make deps
|
||||
|
||||
script:
|
||||
- make qa
|
||||
|
||||
after_failure:
|
||||
- cat ./target/test/report.xml
|
||||
|
||||
after_success:
|
||||
- if [ "$TRAVIS_GO_VERSION" = "1.11.1" ]; then $HOME/gopath/bin/goveralls -covermode=count -coverprofile=target/report/coverage.out -service=travis-ci; fi;
|
||||
27
src/runtime/vendor/github.com/bits-and-blooms/bitset/LICENSE
generated
vendored
27
src/runtime/vendor/github.com/bits-and-blooms/bitset/LICENSE
generated
vendored
@@ -1,27 +0,0 @@
|
||||
Copyright (c) 2014 Will Fitzgerald. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
93
src/runtime/vendor/github.com/bits-and-blooms/bitset/README.md
generated
vendored
93
src/runtime/vendor/github.com/bits-and-blooms/bitset/README.md
generated
vendored
@@ -1,93 +0,0 @@
|
||||
# bitset
|
||||
|
||||
*Go language library to map between non-negative integers and boolean values*
|
||||
|
||||
[](https://github.com/willf/bitset/actions?query=workflow%3ATest)
|
||||
[](https://goreportcard.com/report/github.com/willf/bitset)
|
||||
[](https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc)
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
Package bitset implements bitsets, a mapping between non-negative integers and boolean values.
|
||||
It should be more efficient than map[uint] bool.
|
||||
|
||||
It provides methods for setting, clearing, flipping, and testing individual integers.
|
||||
|
||||
But it also provides set intersection, union, difference, complement, and symmetric operations, as well as tests to check whether any, all, or no bits are set, and querying a bitset's current length and number of positive bits.
|
||||
|
||||
BitSets are expanded to the size of the largest set bit; the memory allocation is approximately Max bits, where Max is the largest set bit. BitSets are never shrunk. On creation, a hint can be given for the number of bits that will be used.
|
||||
|
||||
Many of the methods, including Set, Clear, and Flip, return a BitSet pointer, which allows for chaining.
|
||||
|
||||
### Example use:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
"github.com/bits-and-blooms/bitset"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("Hello from BitSet!\n")
|
||||
var b bitset.BitSet
|
||||
// play some Go Fish
|
||||
for i := 0; i < 100; i++ {
|
||||
card1 := uint(rand.Intn(52))
|
||||
card2 := uint(rand.Intn(52))
|
||||
b.Set(card1)
|
||||
if b.Test(card2) {
|
||||
fmt.Println("Go Fish!")
|
||||
}
|
||||
b.Clear(card1)
|
||||
}
|
||||
|
||||
// Chaining
|
||||
b.Set(10).Set(11)
|
||||
|
||||
for i, e := b.NextSet(0); e; i, e = b.NextSet(i + 1) {
|
||||
fmt.Println("The following bit is set:", i)
|
||||
}
|
||||
if b.Intersection(bitset.New(100).Set(10)).Count() == 1 {
|
||||
fmt.Println("Intersection works.")
|
||||
} else {
|
||||
fmt.Println("Intersection doesn't work???")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
As an alternative to BitSets, one should check out the 'big' package, which provides a (less set-theoretical) view of bitsets.
|
||||
|
||||
Package documentation is at: https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc
|
||||
|
||||
## Memory Usage
|
||||
|
||||
The memory usage of a bitset using N bits is at least N/8 bytes. The number of bits in a bitset is at least as large as one plus the greatest bit index you have accessed. Thus it is possible to run out of memory while using a bitset. If you have lots of bits, you might prefer compressed bitsets, like the [Roaring bitmaps](http://roaringbitmap.org) and its [Go implementation](https://github.com/RoaringBitmap/roaring).
|
||||
|
||||
## Implementation Note
|
||||
|
||||
Go 1.9 introduced a native `math/bits` library. We provide backward compatibility to Go 1.7, which might be removed.
|
||||
|
||||
It is possible that a later version will match the `math/bits` return signature for counts (which is `int`, rather than our library's `unit64`). If so, the version will be bumped.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
go get github.com/bits-and-blooms/bitset
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
If you wish to contribute to this project, please branch and issue a pull request against master ("[GitHub Flow](https://guides.github.com/introduction/flow/)")
|
||||
|
||||
## Running all tests
|
||||
|
||||
Before committing the code, please check if it passes tests, has adequate coverage, etc.
|
||||
```bash
|
||||
go test
|
||||
go test -cover
|
||||
```
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user