mirror of
https://github.com/kata-containers/kata-containers.git
synced 2026-03-14 16:52:18 +00:00
Compare commits
415 Commits
2.2.0-alph
...
2.3.0-alph
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fee6f49d38 | ||
|
|
18c95b9ab1 | ||
|
|
c0daa4ebff | ||
|
|
67d1f4fd14 | ||
|
|
87152fffcb | ||
|
|
2250360b56 | ||
|
|
a9de761d71 | ||
|
|
8ae3edbc18 | ||
|
|
0c7789fad6 | ||
|
|
72e3538e36 | ||
|
|
8dadca9cd1 | ||
|
|
b564dd47b6 | ||
|
|
a89cc0bb5c | ||
|
|
8771d8c375 | ||
|
|
a99fcc3af1 | ||
|
|
39ffd8ee84 | ||
|
|
ff37f5c798 | ||
|
|
fb583780f6 | ||
|
|
8f0f949abf | ||
|
|
932ee41b3f | ||
|
|
bff38e4f4d | ||
|
|
d967d3cb37 | ||
|
|
87de26bda3 | ||
|
|
8058e97212 | ||
|
|
a6a2e525de | ||
|
|
d490704133 | ||
|
|
a0dd840ef6 | ||
|
|
0be91280f2 | ||
|
|
f62ea5dade | ||
|
|
9de1129bf7 | ||
|
|
65a1e13195 | ||
|
|
a4214738b9 | ||
|
|
a989238348 | ||
|
|
b8717f35d7 | ||
|
|
938981be1d | ||
|
|
2304f935b4 | ||
|
|
c5fea9ff70 | ||
|
|
f3539d2fb7 | ||
|
|
e26a140448 | ||
|
|
2a614577fb | ||
|
|
486baba7fd | ||
|
|
46eb07e14f | ||
|
|
80fba4d637 | ||
|
|
8594f80c0a | ||
|
|
87bbae1bd7 | ||
|
|
cfd539dc6c | ||
|
|
31c8454700 | ||
|
|
0675bab49c | ||
|
|
aaf37d72b2 | ||
|
|
348795e282 | ||
|
|
fbd4ab6cdc | ||
|
|
af93263985 | ||
|
|
02717b8c4b | ||
|
|
1c643dea24 | ||
|
|
7a5ffd4a0f | ||
|
|
2cb7b51355 | ||
|
|
76f4588f25 | ||
|
|
e155fb2b19 | ||
|
|
b980c62f43 | ||
|
|
99e9a6ad0a | ||
|
|
c23ffef4eb | ||
|
|
9586d48254 | ||
|
|
bff73de4d3 | ||
|
|
6a6dee7cc8 | ||
|
|
8915dc56d5 | ||
|
|
46942dd449 | ||
|
|
9edbc00dbc | ||
|
|
71f304ce17 | ||
|
|
f1a505dbfe | ||
|
|
961aaff004 | ||
|
|
2aa686a0f5 | ||
|
|
7effbdebcb | ||
|
|
1ab55e5afd | ||
|
|
e287708435 | ||
|
|
7445071330 | ||
|
|
f152284f1b | ||
|
|
99ab91df3d | ||
|
|
4fe23b190f | ||
|
|
e1e6827a2c | ||
|
|
a28cc7ffd6 | ||
|
|
b7d4888659 | ||
|
|
f981fc6456 | ||
|
|
e07a9fea79 | ||
|
|
f87cee9d11 | ||
|
|
6871aeaa60 | ||
|
|
15e0a3c8f0 | ||
|
|
d01aebebae | ||
|
|
b4b843178c | ||
|
|
77160e591a | ||
|
|
2f5a77d144 | ||
|
|
b9e03a1cf1 | ||
|
|
f47cad3d95 | ||
|
|
9fa1febfd9 | ||
|
|
233b53c048 | ||
|
|
2d8386ea52 | ||
|
|
8714a35063 | ||
|
|
68a6f011b5 | ||
|
|
97dcc5f78a | ||
|
|
0b03d97d0b | ||
|
|
c2f03e8993 | ||
|
|
c867d1e069 | ||
|
|
1d25d7d43f | ||
|
|
eac05ad6d6 | ||
|
|
64dd35ba4f | ||
|
|
03325f0612 | ||
|
|
48bb104660 | ||
|
|
b8133a188c | ||
|
|
d473967120 | ||
|
|
831c2feead | ||
|
|
2e28b71473 | ||
|
|
d5f85698e1 | ||
|
|
3165095669 | ||
|
|
b24ee4b11e | ||
|
|
27b9a68189 | ||
|
|
a72b08117f | ||
|
|
0a2e2c6038 | ||
|
|
eda55195fb | ||
|
|
d007bb8550 | ||
|
|
e6408fe670 | ||
|
|
fdc42ca7ff | ||
|
|
186a02593a | ||
|
|
49083bfa31 | ||
|
|
ee90affc18 | ||
|
|
767a41ce56 | ||
|
|
760ec4e58a | ||
|
|
b94252a5fa | ||
|
|
0c913040b6 | ||
|
|
d9359440e2 | ||
|
|
3fe6695b0a | ||
|
|
7df56301be | ||
|
|
57b696a5ec | ||
|
|
4f0726bc49 | ||
|
|
f186c5e284 | ||
|
|
7c610a6ff1 | ||
|
|
1d70523a59 | ||
|
|
80afba15ee | ||
|
|
5a0d3c4fac | ||
|
|
2d142bc92d | ||
|
|
7ed6423dd8 | ||
|
|
9514dda52e | ||
|
|
6ffe37b949 | ||
|
|
8508e52fdc | ||
|
|
5b514177b0 | ||
|
|
6b2ad64aea | ||
|
|
b53e84054e | ||
|
|
5957bc7d9c | ||
|
|
81e6bf6f2c | ||
|
|
d46ae3248e | ||
|
|
b789a935cf | ||
|
|
85987c6d79 | ||
|
|
b9d2eea39b | ||
|
|
4895747f35 | ||
|
|
fc90bb5314 | ||
|
|
bbb06c4975 | ||
|
|
2f9859ab2f | ||
|
|
3533a5b61d | ||
|
|
0c5ded4bd7 | ||
|
|
fe7e6a2dc1 | ||
|
|
e27733db94 | ||
|
|
fff76d5e90 | ||
|
|
2ec310934a | ||
|
|
5283f73b0c | ||
|
|
cc0bb9aebc | ||
|
|
8e9ffe6f3a | ||
|
|
838e169b9c | ||
|
|
8b15eafa6a | ||
|
|
77604de80b | ||
|
|
9806e88963 | ||
|
|
d2c7b5e782 | ||
|
|
4fbae549e4 | ||
|
|
1fbfd99d37 | ||
|
|
07f7ad9d63 | ||
|
|
9c0b8a7f5b | ||
|
|
695a7ad758 | ||
|
|
3727caf7d8 | ||
|
|
116c29c897 | ||
|
|
c0f801c0c4 | ||
|
|
b5293c5214 | ||
|
|
3160f0102d | ||
|
|
2859600a6f | ||
|
|
24cbb97f68 | ||
|
|
d75c01bd67 | ||
|
|
8befb1f39f | ||
|
|
7125f5d8cf | ||
|
|
0f8c0dbc52 | ||
|
|
070590fb53 | ||
|
|
b817340f94 | ||
|
|
d08923d55a | ||
|
|
d53d3b4f6a | ||
|
|
b4c45df885 | ||
|
|
aec530904b | ||
|
|
1e4f7faa77 | ||
|
|
bb9495c0b7 | ||
|
|
80ab91ac2f | ||
|
|
54bdd01811 | ||
|
|
dd58de368d | ||
|
|
47d95dc1c6 | ||
|
|
8ca7a7c547 | ||
|
|
31de8eb75b | ||
|
|
2b80091e14 | ||
|
|
0dc59df68f | ||
|
|
54bcd3c946 | ||
|
|
c10425233b | ||
|
|
fd2607cc43 | ||
|
|
5512da1739 | ||
|
|
add480ed59 | ||
|
|
75c5edd66a | ||
|
|
67906b4876 | ||
|
|
f7c6f17060 | ||
|
|
1838c3a33b | ||
|
|
259f0e26d1 | ||
|
|
a8649acfd0 | ||
|
|
6b00806bb8 | ||
|
|
3882619471 | ||
|
|
c5fdc0dbb6 | ||
|
|
f2ef25c67f | ||
|
|
1b71d31121 | ||
|
|
6310f0543a | ||
|
|
cb6b7667cd | ||
|
|
a733f537e5 | ||
|
|
2c835b60ed | ||
|
|
243d4b8689 | ||
|
|
e1b91986d7 | ||
|
|
4f066db8da | ||
|
|
11d84cca46 | ||
|
|
4f23b8cd47 | ||
|
|
5737b36a35 | ||
|
|
1da8fa1655 | ||
|
|
1bb0705765 | ||
|
|
b94ebc30b4 | ||
|
|
462e445d2f | ||
|
|
f8d71eb96b | ||
|
|
a8a623fb75 | ||
|
|
35cbc93dee | ||
|
|
ff87da721b | ||
|
|
fcc93b0074 | ||
|
|
8e0daf6780 | ||
|
|
b12b21f337 | ||
|
|
558f1be62d | ||
|
|
5371b9214f | ||
|
|
27b299b2a7 | ||
|
|
0508469994 | ||
|
|
acf6932863 | ||
|
|
594ff3a5bd | ||
|
|
fdf9731992 | ||
|
|
17262cfe93 | ||
|
|
dcd2986724 | ||
|
|
afd9785051 | ||
|
|
c8aab29b38 | ||
|
|
3a9ecbcca5 | ||
|
|
2f573bceaf | ||
|
|
34828df9a1 | ||
|
|
73d3798cb1 | ||
|
|
e386069158 | ||
|
|
f4fbf723e1 | ||
|
|
a20074d45c | ||
|
|
ac8f972e4b | ||
|
|
f9643d83fb | ||
|
|
5e69b498ed | ||
|
|
a104f13230 | ||
|
|
579b3f34c2 | ||
|
|
930ca55d02 | ||
|
|
79977a25ec | ||
|
|
39546a1070 | ||
|
|
38dcdc3d91 | ||
|
|
d0bc148fe0 | ||
|
|
7960689ef7 | ||
|
|
350acb2d6e | ||
|
|
858f39ef75 | ||
|
|
e0a19f6a16 | ||
|
|
8d6dd2ad61 | ||
|
|
a48dc93fd4 | ||
|
|
3799679109 | ||
|
|
67dfb0b922 | ||
|
|
bfa8fe3183 | ||
|
|
8c4dd3b421 | ||
|
|
e27080b706 | ||
|
|
6999dccaa8 | ||
|
|
feeb1ef8b1 | ||
|
|
61b1a6732b | ||
|
|
7db8a85a1f | ||
|
|
007a656173 | ||
|
|
9b8cc4581d | ||
|
|
e887b39e95 | ||
|
|
6c39c353e6 | ||
|
|
9081bee2fd | ||
|
|
b10e3e22b5 | ||
|
|
c8f32936d3 | ||
|
|
88e7075929 | ||
|
|
8c921e69ec | ||
|
|
1ab72518b3 | ||
|
|
8f76626fd6 | ||
|
|
75356967c6 | ||
|
|
da3de3c2eb | ||
|
|
305fb0547d | ||
|
|
89cf168c92 | ||
|
|
f793b28dfd | ||
|
|
9577e54e2a | ||
|
|
e8ec18a9d8 | ||
|
|
7a481c3f4f | ||
|
|
2cc9006c26 | ||
|
|
28b2c629e3 | ||
|
|
cfd690b638 | ||
|
|
8758ce26b7 | ||
|
|
a33d6bae63 | ||
|
|
432296ae7a | ||
|
|
cf4a63f1e5 | ||
|
|
4c809a53d2 | ||
|
|
d08603bebb | ||
|
|
7d3cf04f29 | ||
|
|
3f1aa8ff91 | ||
|
|
26985bbfff | ||
|
|
2c9430123e | ||
|
|
015b3baf06 | ||
|
|
2de9c5b41d | ||
|
|
e6b1766f6b | ||
|
|
55c5c871d2 | ||
|
|
bd5951247c | ||
|
|
65d2fb5d11 | ||
|
|
cfb8139f36 | ||
|
|
ae46e7bf97 | ||
|
|
3fe0af6a9b | ||
|
|
15d37d5823 | ||
|
|
66dd8719e3 | ||
|
|
d0ad388721 | ||
|
|
d671f78952 | ||
|
|
f607641a6e | ||
|
|
79e632bc23 | ||
|
|
32c9ae1388 | ||
|
|
550029c473 | ||
|
|
7d05739f01 | ||
|
|
aa264f915f | ||
|
|
34bdddbeb5 | ||
|
|
d78e396a33 | ||
|
|
7d37fbfdfb | ||
|
|
a8bb8269fe | ||
|
|
69bf7e7519 | ||
|
|
3e8a07c415 | ||
|
|
f6294226e8 | ||
|
|
064dfb164b | ||
|
|
3f0f1ceba0 | ||
|
|
6a93e5d593 | ||
|
|
57c0cee0a5 | ||
|
|
ac0bd57748 | ||
|
|
9ab6e07330 | ||
|
|
3b356be87c | ||
|
|
bb4a256a30 | ||
|
|
772c117d4e | ||
|
|
f35ba94d30 | ||
|
|
8310a3d70a | ||
|
|
5a22e0e3b1 | ||
|
|
ecd13ec43d | ||
|
|
a822cdf64d | ||
|
|
f5d9d89b73 | ||
|
|
c47a597568 | ||
|
|
a1d6c3c551 | ||
|
|
d7ce78cf6a | ||
|
|
6a1a051c65 | ||
|
|
fe0085ca55 | ||
|
|
08984b6e31 | ||
|
|
951bb6a78f | ||
|
|
b3623a2c40 | ||
|
|
2a1b6d376a | ||
|
|
2322f935c1 | ||
|
|
11f9a914b9 | ||
|
|
1316fa5300 | ||
|
|
c0cc6d5978 | ||
|
|
b9e611e363 | ||
|
|
ac6b9c53d2 | ||
|
|
789a59549e | ||
|
|
757ddf7b83 | ||
|
|
8bb9192e83 | ||
|
|
caf5760c45 | ||
|
|
bd20701f35 | ||
|
|
a9aa36cebc | ||
|
|
ecdd137c6f | ||
|
|
000049b69e | ||
|
|
1faaf5f35d | ||
|
|
90029032b4 | ||
|
|
9e6f1f7794 | ||
|
|
3f39df0d18 | ||
|
|
1bad9999fd | ||
|
|
23d31d5a7c | ||
|
|
2022c64f94 | ||
|
|
85bb5cffe1 | ||
|
|
361bee91f7 | ||
|
|
6be8bf5c66 | ||
|
|
7834f4127f | ||
|
|
bd27f7bab5 | ||
|
|
fb318532b9 | ||
|
|
6abe7caecb | ||
|
|
ad06eb90db | ||
|
|
ea9bb8e9ad | ||
|
|
685d631c4c | ||
|
|
1ab64e30aa | ||
|
|
c881899903 | ||
|
|
799cb27234 | ||
|
|
45fd58d11c | ||
|
|
2f322b8be0 | ||
|
|
383041959d | ||
|
|
2fb176ddee | ||
|
|
601e2b65c5 | ||
|
|
9d585935b5 | ||
|
|
5a71786986 | ||
|
|
be31694554 | ||
|
|
723c0ac4d5 | ||
|
|
240aae96dd | ||
|
|
66e4c77a54 | ||
|
|
8825bb298f | ||
|
|
cabddcc735 | ||
|
|
e544779c61 | ||
|
|
85c40001da | ||
|
|
b26d5b1d08 | ||
|
|
81c6e4ca9f | ||
|
|
a918c46fb6 |
18
.github/workflows/gather-artifacts.sh
vendored
18
.github/workflows/gather-artifacts.sh
vendored
@@ -1,18 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) 2019 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
||||
pushd kata-artifacts >>/dev/null
|
||||
for c in ./*.tar.gz
|
||||
do
|
||||
echo "untarring tarball $c"
|
||||
tar -xvf $c
|
||||
done
|
||||
|
||||
tar cvfJ ../kata-static.tar.xz ./opt
|
||||
popd >>/dev/null
|
||||
36
.github/workflows/generate-artifact-tarball.sh
vendored
36
.github/workflows/generate-artifact-tarball.sh
vendored
@@ -1,36 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) 2019 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
||||
|
||||
main() {
|
||||
artifact_stage=${1:-}
|
||||
artifact=$(echo ${artifact_stage} | sed -n -e 's/^install_//p' | sed -r 's/_/-/g')
|
||||
if [ -z "${artifact}" ]; then
|
||||
"Scripts needs artifact name to build"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tag=$(echo $GITHUB_REF | cut -d/ -f3-)
|
||||
export GOPATH=$HOME/go
|
||||
|
||||
go get github.com/kata-containers/packaging || true
|
||||
pushd $GOPATH/src/github.com/kata-containers/packaging/release >>/dev/null
|
||||
git checkout $tag
|
||||
pushd ../obs-packaging
|
||||
./gen_versions_txt.sh $tag
|
||||
popd
|
||||
|
||||
source ./kata-deploy-binaries.sh
|
||||
${artifact_stage} $tag
|
||||
popd
|
||||
|
||||
mv $HOME/go/src/github.com/kata-containers/packaging/release/kata-static-${artifact}.tar.gz .
|
||||
}
|
||||
|
||||
main $@
|
||||
@@ -1,34 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright (c) 2019 Intel Corporation
|
||||
# Copyright (c) 2020 Ant Group
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
|
||||
|
||||
main() {
|
||||
artifact_stage=${1:-}
|
||||
artifact=$(echo ${artifact_stage} | sed -n -e 's/^install_//p' | sed -r 's/_/-/g')
|
||||
if [ -z "${artifact}" ]; then
|
||||
"Scripts needs artifact name to build"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tag=$(echo $GITHUB_REF | cut -d/ -f3-)
|
||||
pushd $GITHUB_WORKSPACE/tools/packaging
|
||||
git checkout $tag
|
||||
./scripts/gen_versions_txt.sh $tag
|
||||
popd
|
||||
|
||||
pushd $GITHUB_WORKSPACE/tools/packaging/release
|
||||
source ./kata-deploy-binaries.sh
|
||||
${artifact_stage} $tag
|
||||
popd
|
||||
|
||||
mv $GITHUB_WORKSPACE/tools/packaging/release/kata-static-${artifact}.tar.gz .
|
||||
}
|
||||
|
||||
main $@
|
||||
58
.github/workflows/kata-deploy-push.yaml
vendored
Normal file
58
.github/workflows/kata-deploy-push.yaml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
name: kata-deploy-build
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
build-asset:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
asset:
|
||||
- kernel
|
||||
- shim-v2
|
||||
- qemu
|
||||
- cloud-hypervisor
|
||||
- firecracker
|
||||
- rootfs-image
|
||||
- rootfs-initrd
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install docker
|
||||
run: |
|
||||
curl -fsSL https://test.docker.com -o test-docker.sh
|
||||
sh test-docker.sh
|
||||
|
||||
- name: Build ${{ matrix.asset }}
|
||||
run: |
|
||||
./tools/packaging/kata-deploy/local-build/kata-deploy-binaries-in-docker.sh --build="${KATA_ASSET}"
|
||||
build_dir=$(readlink -f build)
|
||||
# store-artifact does not work with symlink
|
||||
sudo cp -r --preserve=all "${build_dir}" "kata-build"
|
||||
env:
|
||||
KATA_ASSET: ${{ matrix.asset }}
|
||||
|
||||
- name: store-artifact ${{ matrix.asset }}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: kata-artifacts
|
||||
path: kata-build/kata-static-${{ matrix.asset }}.tar.xz
|
||||
if-no-files-found: error
|
||||
|
||||
create-kata-tarball:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-asset
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: get-artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: kata-artifacts
|
||||
path: kata-artifacts
|
||||
- name: merge-artifacts
|
||||
run: |
|
||||
./tools/packaging/kata-deploy/local-build/kata-deploy-merge-builds.sh kata-artifacts
|
||||
- name: store-artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: kata-static-tarball
|
||||
path: kata-static.tar.xz
|
||||
4
.github/workflows/kata-deploy-test.yaml
vendored
4
.github/workflows/kata-deploy-test.yaml
vendored
@@ -46,9 +46,11 @@ jobs:
|
||||
VERSION="2.0.0"
|
||||
ARTIFACT_URL="https://github.com/kata-containers/kata-containers/releases/download/${VERSION}/kata-static-${VERSION}-x86_64.tar.xz"
|
||||
wget "${ARTIFACT_URL}" -O tools/packaging/kata-deploy/kata-static.tar.xz
|
||||
docker build --build-arg KATA_ARTIFACTS=kata-static.tar.xz -t katadocker/kata-deploy-ci:${PR_SHA} ./tools/packaging/kata-deploy
|
||||
docker build --build-arg KATA_ARTIFACTS=kata-static.tar.xz -t katadocker/kata-deploy-ci:${PR_SHA} -t quay.io/kata-containers/kata-deploy-ci:${PR_SHA} ./tools/packaging/kata-deploy
|
||||
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
|
||||
docker push katadocker/kata-deploy-ci:$PR_SHA
|
||||
docker login -u ${{ secrets.QUAY_DEPLOYER_USERNAME }} -p ${{ secrets.QUAY_DEPLOYER_PASSWORD }} quay.io
|
||||
docker push quay.io/kata-containers/kata-deploy-ci:$PR_SHA
|
||||
echo "##[set-output name=pr-sha;]${PR_SHA}"
|
||||
|
||||
- name: test-kata-deploy-ci-in-aks
|
||||
|
||||
4
.github/workflows/main.yaml
vendored
4
.github/workflows/main.yaml
vendored
@@ -247,9 +247,11 @@ jobs:
|
||||
pkg_sha=$(git rev-parse HEAD)
|
||||
popd
|
||||
mv release-candidate/kata-static.tar.xz ./packaging/kata-deploy/kata-static.tar.xz
|
||||
docker build --build-arg KATA_ARTIFACTS=kata-static.tar.xz -t katadocker/kata-deploy-ci:$pkg_sha ./packaging/kata-deploy
|
||||
docker build --build-arg KATA_ARTIFACTS=kata-static.tar.xz -t katadocker/kata-deploy-ci:$pkg_sha -t quay.io/kata-containers/kata-deploy-ci:$pkg_sha ./packaging/kata-deploy
|
||||
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
|
||||
docker push katadocker/kata-deploy-ci:$pkg_sha
|
||||
docker login -u ${{ secrets.QUAY_DEPLOYER_USERNAME }} -p ${{ secrets.QUAY_DEPLOYER_PASSWORD }} quay.io
|
||||
docker push quay.io/kata-containers/kata-deploy-ci:$pkg_sha
|
||||
echo "::set-output name=PKG_SHA::${pkg_sha}"
|
||||
- name: test-kata-deploy-ci-in-aks
|
||||
uses: ./packaging/kata-deploy/action
|
||||
|
||||
246
.github/workflows/release.yaml
vendored
246
.github/workflows/release.yaml
vendored
@@ -5,213 +5,45 @@ on:
|
||||
- '2.*'
|
||||
|
||||
jobs:
|
||||
get-artifact-list:
|
||||
build-asset:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
asset:
|
||||
- cloud-hypervisor
|
||||
- firecracker
|
||||
- kernel
|
||||
- qemu
|
||||
- rootfs-image
|
||||
- rootfs-initrd
|
||||
- shim-v2
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: get the list
|
||||
- name: Install docker
|
||||
run: |
|
||||
pushd $GITHUB_WORKSPACE
|
||||
tag=$(echo $GITHUB_REF | cut -d/ -f3-)
|
||||
git checkout $tag
|
||||
popd
|
||||
$GITHUB_WORKSPACE/tools/packaging/artifact-list.sh > artifact-list.txt
|
||||
- name: save-artifact-list
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: artifact-list
|
||||
path: artifact-list.txt
|
||||
curl -fsSL https://test.docker.com -o test-docker.sh
|
||||
sh test-docker.sh
|
||||
|
||||
build-kernel:
|
||||
runs-on: ubuntu-16.04
|
||||
needs: get-artifact-list
|
||||
env:
|
||||
buildstr: "install_kernel"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: get-artifact-list
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: artifact-list
|
||||
- run: |
|
||||
sudo apt-get update && sudo apt install -y flex bison libelf-dev bc iptables
|
||||
- name: build-kernel
|
||||
- name: Build ${{ matrix.asset }}
|
||||
run: |
|
||||
if grep -q $buildstr artifact-list.txt; then
|
||||
$GITHUB_WORKSPACE/.github/workflows/generate-local-artifact-tarball.sh $buildstr
|
||||
echo "artifact-built=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "artifact-built=false" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: store-artifacts
|
||||
if: ${{ env.artifact-built }} == 'true'
|
||||
./tools/packaging/kata-deploy/local-build/kata-deploy-binaries-in-docker.sh --build="${KATA_ASSET}"
|
||||
build_dir=$(readlink -f build)
|
||||
# store-artifact does not work with symlink
|
||||
sudo cp -r "${build_dir}" "kata-build"
|
||||
env:
|
||||
KATA_ASSET: ${{ matrix.asset }}
|
||||
TAR_OUTPUT: ${{ matrix.asset }}.tar.gz
|
||||
|
||||
- name: store-artifact ${{ matrix.asset }}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: kata-artifacts
|
||||
path: kata-static-kernel.tar.gz
|
||||
path: kata-build/kata-static-${{ matrix.asset }}.tar.xz
|
||||
if-no-files-found: error
|
||||
|
||||
build-experimental-kernel:
|
||||
runs-on: ubuntu-16.04
|
||||
needs: get-artifact-list
|
||||
env:
|
||||
buildstr: "install_experimental_kernel"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: get-artifact-list
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: artifact-list
|
||||
- run: |
|
||||
sudo apt-get update && sudo apt install -y flex bison libelf-dev bc iptables
|
||||
- name: build-experimental-kernel
|
||||
run: |
|
||||
if grep -q $buildstr artifact-list.txt; then
|
||||
$GITHUB_WORKSPACE/.github/workflows/generate-local-artifact-tarball.sh $buildstr
|
||||
echo "artifact-built=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "artifact-built=false" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: store-artifacts
|
||||
if: ${{ env.artifact-built }} == 'true'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: kata-artifacts
|
||||
path: kata-static-experimental-kernel.tar.gz
|
||||
|
||||
build-qemu:
|
||||
runs-on: ubuntu-16.04
|
||||
needs: get-artifact-list
|
||||
env:
|
||||
buildstr: "install_qemu"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: get-artifact-list
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: artifact-list
|
||||
- name: build-qemu
|
||||
run: |
|
||||
if grep -q $buildstr artifact-list.txt; then
|
||||
$GITHUB_WORKSPACE/.github/workflows/generate-local-artifact-tarball.sh $buildstr
|
||||
echo "artifact-built=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "artifact-built=false" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: store-artifacts
|
||||
if: ${{ env.artifact-built }} == 'true'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: kata-artifacts
|
||||
path: kata-static-qemu.tar.gz
|
||||
|
||||
build-image:
|
||||
runs-on: ubuntu-16.04
|
||||
needs: get-artifact-list
|
||||
env:
|
||||
buildstr: "install_image"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: get-artifact-list
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: artifact-list
|
||||
- name: build-image
|
||||
run: |
|
||||
if grep -q $buildstr artifact-list.txt; then
|
||||
$GITHUB_WORKSPACE/.github/workflows/generate-local-artifact-tarball.sh $buildstr
|
||||
echo "artifact-built=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "artifact-built=false" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: store-artifacts
|
||||
if: ${{ env.artifact-built }} == 'true'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: kata-artifacts
|
||||
path: kata-static-image.tar.gz
|
||||
|
||||
build-firecracker:
|
||||
runs-on: ubuntu-16.04
|
||||
needs: get-artifact-list
|
||||
env:
|
||||
buildstr: "install_firecracker"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: get-artifact-list
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: artifact-list
|
||||
- name: build-firecracker
|
||||
run: |
|
||||
if grep -q $buildstr artifact-list.txt; then
|
||||
$GITHUB_WORKSPACE/.github/workflows/generate-local-artifact-tarball.sh $buildstr
|
||||
echo "artifact-built=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "artifact-built=false" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: store-artifacts
|
||||
if: ${{ env.artifact-built }} == 'true'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: kata-artifacts
|
||||
path: kata-static-firecracker.tar.gz
|
||||
|
||||
|
||||
build-clh:
|
||||
runs-on: ubuntu-16.04
|
||||
needs: get-artifact-list
|
||||
env:
|
||||
buildstr: "install_clh"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: get-artifact-list
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: artifact-list
|
||||
- name: build-clh
|
||||
run: |
|
||||
if grep -q $buildstr artifact-list.txt; then
|
||||
$GITHUB_WORKSPACE/.github/workflows/generate-local-artifact-tarball.sh $buildstr
|
||||
echo "artifact-built=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "artifact-built=false" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: store-artifacts
|
||||
if: ${{ env.artifact-built }} == 'true'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: kata-artifacts
|
||||
path: kata-static-clh.tar.gz
|
||||
|
||||
build-kata-components:
|
||||
runs-on: ubuntu-16.04
|
||||
needs: get-artifact-list
|
||||
env:
|
||||
buildstr: "install_kata_components"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: get-artifact-list
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: artifact-list
|
||||
- name: build-kata-components
|
||||
run: |
|
||||
if grep -q $buildstr artifact-list.txt; then
|
||||
$GITHUB_WORKSPACE/.github/workflows/generate-local-artifact-tarball.sh $buildstr
|
||||
echo "artifact-built=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "artifact-built=false" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: store-artifacts
|
||||
if: ${{ env.artifact-built }} == 'true'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: kata-artifacts
|
||||
path: kata-static-kata-components.tar.gz
|
||||
|
||||
gather-artifacts:
|
||||
runs-on: ubuntu-16.04
|
||||
needs: [build-experimental-kernel, build-kernel, build-qemu, build-image, build-firecracker, build-kata-components, build-clh]
|
||||
create-kata-tarball:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-asset
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: get-artifacts
|
||||
@@ -219,24 +51,24 @@ jobs:
|
||||
with:
|
||||
name: kata-artifacts
|
||||
path: kata-artifacts
|
||||
- name: colate-artifacts
|
||||
- name: merge-artifacts
|
||||
run: |
|
||||
$GITHUB_WORKSPACE/.github/workflows/gather-artifacts.sh
|
||||
./tools/packaging/kata-deploy/local-build/kata-deploy-merge-builds.sh kata-artifacts
|
||||
- name: store-artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: release-candidate
|
||||
name: kata-static-tarball
|
||||
path: kata-static.tar.xz
|
||||
|
||||
kata-deploy:
|
||||
needs: gather-artifacts
|
||||
needs: create-kata-tarball
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: get-artifacts
|
||||
- name: get-kata-tarball
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: release-candidate
|
||||
name: kata-static-tarball
|
||||
- name: build-and-push-kata-deploy-ci
|
||||
id: build-and-push-kata-deploy-ci
|
||||
run: |
|
||||
@@ -246,9 +78,11 @@ jobs:
|
||||
pkg_sha=$(git rev-parse HEAD)
|
||||
popd
|
||||
mv kata-static.tar.xz $GITHUB_WORKSPACE/tools/packaging/kata-deploy/kata-static.tar.xz
|
||||
docker build --build-arg KATA_ARTIFACTS=kata-static.tar.xz -t katadocker/kata-deploy-ci:$pkg_sha $GITHUB_WORKSPACE/tools/packaging/kata-deploy
|
||||
docker build --build-arg KATA_ARTIFACTS=kata-static.tar.xz -t katadocker/kata-deploy-ci:$pkg_sha -t quay.io/kata-containers/kata-deploy-ci:$pkg_sha $GITHUB_WORKSPACE/tools/packaging/kata-deploy
|
||||
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
|
||||
docker push katadocker/kata-deploy-ci:$pkg_sha
|
||||
docker login -u ${{ secrets.QUAY_DEPLOYER_USERNAME }} -p ${{ secrets.QUAY_DEPLOYER_PASSWORD }} quay.io
|
||||
docker push quay.io/kata-containers/kata-deploy-ci:$pkg_sha
|
||||
mkdir -p packaging/kata-deploy
|
||||
ln -s $GITHUB_WORKSPACE/tools/packaging/kata-deploy/action packaging/kata-deploy/action
|
||||
echo "::set-output name=PKG_SHA::${pkg_sha}"
|
||||
@@ -267,7 +101,9 @@ jobs:
|
||||
# tag the container image we created and push to DockerHub
|
||||
tag=$(echo $GITHUB_REF | cut -d/ -f3-)
|
||||
docker tag katadocker/kata-deploy-ci:${{steps.build-and-push-kata-deploy-ci.outputs.PKG_SHA}} katadocker/kata-deploy:${tag}
|
||||
docker tag quay.io/kata-containers/kata-deploy-ci:${{steps.build-and-push-kata-deploy-ci.outputs.PKG_SHA}} quay.io/kata-containers/kata-deploy:${tag}
|
||||
docker push katadocker/kata-deploy:${tag}
|
||||
docker push quay.io/kata-containers/kata-deploy:${tag}
|
||||
|
||||
upload-static-tarball:
|
||||
needs: kata-deploy
|
||||
@@ -277,7 +113,7 @@ jobs:
|
||||
- name: download-artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: release-candidate
|
||||
name: kata-static-tarball
|
||||
- name: install hub
|
||||
run: |
|
||||
HUB_VER=$(curl -s "https://api.github.com/repos/github/hub/releases/latest" | jq -r .tag_name | sed 's/^v//')
|
||||
|
||||
2
.github/workflows/snap-release.yaml
vendored
2
.github/workflows/snap-release.yaml
vendored
@@ -9,6 +9,8 @@ jobs:
|
||||
steps:
|
||||
- name: Check out Git repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Snapcraft
|
||||
uses: samuelmeuli/action-snapcraft@v1
|
||||
|
||||
2
.github/workflows/snap.yaml
vendored
2
.github/workflows/snap.yaml
vendored
@@ -6,6 +6,8 @@ jobs:
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Snapcraft
|
||||
uses: samuelmeuli/action-snapcraft@v1
|
||||
|
||||
34
.github/workflows/static-checks.yaml
vendored
34
.github/workflows/static-checks.yaml
vendored
@@ -1,10 +1,19 @@
|
||||
on: ["pull_request"]
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- reopened
|
||||
- synchronize
|
||||
- labeled
|
||||
- unlabeled
|
||||
|
||||
name: Static checks
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.13.x, 1.14.x, 1.15.x]
|
||||
go-version: [1.15.x, 1.16.x]
|
||||
os: [ubuntu-20.04]
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
@@ -13,54 +22,65 @@ jobs:
|
||||
TRAVIS_PULL_REQUEST_BRANCH: ${{ github.head_ref }}
|
||||
TRAVIS_PULL_REQUEST_SHA : ${{ github.event.pull_request.head.sha }}
|
||||
RUST_BACKTRACE: "1"
|
||||
target_branch: ${TRAVIS_BRANCH}
|
||||
target_branch: ${{ github.base_ref }}
|
||||
steps:
|
||||
- name: Install Go
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
env:
|
||||
GOPATH: ${{ runner.workspace }}/kata-containers
|
||||
- name: Setup GOPATH
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
|
||||
run: |
|
||||
echo "TRAVIS_BRANCH: ${TRAVIS_BRANCH}"
|
||||
echo "TRAVIS_PULL_REQUEST_BRANCH: ${TRAVIS_PULL_REQUEST_BRANCH}"
|
||||
echo "TRAVIS_PULL_REQUEST_SHA: ${TRAVIS_PULL_REQUEST_SHA}"
|
||||
echo "TRAVIS: ${TRAVIS}"
|
||||
- name: Set env
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
|
||||
run: |
|
||||
echo "GOPATH=${{ github.workspace }}" >> $GITHUB_ENV
|
||||
echo "${{ github.workspace }}/bin" >> $GITHUB_PATH
|
||||
- name: Checkout code
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: ./src/github.com/${{ github.repository }}
|
||||
- name: Setup travis references
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
|
||||
run: |
|
||||
echo "TRAVIS_BRANCH=${TRAVIS_BRANCH:-$(echo $GITHUB_REF | awk 'BEGIN { FS = \"/\" } ; { print $3 }')}"
|
||||
target_branch=${TRAVIS_BRANCH}
|
||||
- name: Setup
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
|
||||
run: |
|
||||
cd ${GOPATH}/src/github.com/${{ github.repository }} && ./ci/setup.sh
|
||||
env:
|
||||
GOPATH: ${{ runner.workspace }}/kata-containers
|
||||
- name: Building rust
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
|
||||
run: |
|
||||
cd ${GOPATH}/src/github.com/${{ github.repository }} && ./ci/install_rust.sh
|
||||
PATH=$PATH:"$HOME/.cargo/bin"
|
||||
rustup target add x86_64-unknown-linux-musl
|
||||
rustup component add rustfmt clippy
|
||||
# Must build before static checks as we depend on some generated code in runtime and agent
|
||||
- name: Build
|
||||
# Check whether the vendored code is up-to-date & working as the first thing
|
||||
- name: Check vendored code
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
|
||||
run: |
|
||||
cd ${GOPATH}/src/github.com/${{ github.repository }} && make
|
||||
cd ${GOPATH}/src/github.com/${{ github.repository }} && make vendor
|
||||
- name: Static Checks
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
|
||||
run: |
|
||||
cd ${GOPATH}/src/github.com/${{ github.repository }} && ./ci/static-checks.sh
|
||||
cd ${GOPATH}/src/github.com/${{ github.repository }} && make static-checks
|
||||
- name: Run Compiler Checks
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
|
||||
run: |
|
||||
cd ${GOPATH}/src/github.com/${{ github.repository }} && make check
|
||||
- name: Run Unit Tests
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'force-skip-ci') }}
|
||||
run: |
|
||||
cd ${GOPATH}/src/github.com/${{ github.repository }} && make test
|
||||
|
||||
94
Glossary.md
Normal file
94
Glossary.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Glossary
|
||||
|
||||
[A](#a), [B](#b), [C](#c), [D](#d), [E](#e), [F](#f), [G](#g), [H](#h), [I](#i), [J](#j), [K](#k), [L](#l), [M](#m), [N](#n), [O](#o), [P](#p), [Q](#q), [R](#r), [S](#s), [T](#t), [U](#u), [V](#v), [W](#w), [X](#x), [Y](#y), [Z](#z)
|
||||
|
||||
## A
|
||||
|
||||
### Auto Scaling
|
||||
a method used in cloud computing, whereby the amount of computational resources in a server farm, typically measured in terms of the number of active servers, which vary automatically based on the load on the farm.
|
||||
|
||||
## B
|
||||
|
||||
## C
|
||||
|
||||
### Container Security Solutions
|
||||
The process of implementing security tools and policies that will give you the assurance that everything in your container is running as intended, and only as intended.
|
||||
|
||||
### Container Software
|
||||
A standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another.
|
||||
|
||||
### Container Runtime Interface
|
||||
A plugin interface which enables Kubelet to use a wide variety of container runtimes, without the need to recompile.
|
||||
|
||||
### Container Virtualization
|
||||
A container is a virtual runtime environment that runs on top of a single operating system (OS) kernel and emulates an operating system rather than the underlying hardware.
|
||||
|
||||
## D
|
||||
|
||||
## E
|
||||
|
||||
## F
|
||||
|
||||
## G
|
||||
|
||||
## H
|
||||
|
||||
## I
|
||||
|
||||
### Infrastructure Architecture
|
||||
A structured and modern approach for supporting an organization and facilitating innovation within an enterprise.
|
||||
|
||||
## J
|
||||
|
||||
## K
|
||||
|
||||
### Kata Containers
|
||||
Kata containers is an open source project delivering increased container security and Workload isolation through an implementation of lightweight virtual machines.
|
||||
|
||||
## L
|
||||
|
||||
## M
|
||||
|
||||
## N
|
||||
|
||||
## O
|
||||
|
||||
## P
|
||||
|
||||
### Pod Containers
|
||||
A Group of one or more containers , with shared storage/network, and a specification for how to run the containers.
|
||||
|
||||
### Private Cloud
|
||||
A computing model that offers a proprietary environment dedicated to a single business entity.
|
||||
|
||||
### Public Cloud
|
||||
Computing services offered by third-party providers over the public Internet, making them available to anyone who wants to use or purchase them.
|
||||
|
||||
## Q
|
||||
|
||||
## R
|
||||
|
||||
## S
|
||||
|
||||
### Serverless Containers
|
||||
An architecture in which code is executed on-demand. Serverless workloads are typically in the cloud, but on-premises serverless platforms exist, too.
|
||||
|
||||
## T
|
||||
|
||||
## U
|
||||
|
||||
## V
|
||||
|
||||
### Virtual Machine Monitor
|
||||
Computer software, firmware or hardware that creates and runs virtual machines.
|
||||
|
||||
### Virtual Machine Software
|
||||
A software program or operating system that not only exhibits the behavior of a separate computer, but is also capable of performing tasks such as running applications and programs like a separate computer.
|
||||
|
||||
## W
|
||||
|
||||
## X
|
||||
|
||||
## Y
|
||||
|
||||
## Z
|
||||
14
Makefile
14
Makefile
@@ -15,7 +15,7 @@ TOOLS =
|
||||
|
||||
TOOLS += agent-ctl
|
||||
|
||||
STANDARD_TARGETS = build check clean install test
|
||||
STANDARD_TARGETS = build check clean install test vendor
|
||||
|
||||
include utils.mk
|
||||
|
||||
@@ -29,4 +29,14 @@ $(eval $(call create_all_rules,$(COMPONENTS),$(TOOLS),$(STANDARD_TARGETS)))
|
||||
generate-protocols:
|
||||
make -C src/agent generate-protocols
|
||||
|
||||
.PHONY: all default
|
||||
# Some static checks rely on generated source files of components.
|
||||
static-checks: build
|
||||
bash ci/static-checks.sh
|
||||
|
||||
binary-tarball:
|
||||
make -f ./tools/packaging/kata-deploy/local-build/Makefile
|
||||
|
||||
install-binary-tarball:
|
||||
make -f ./tools/packaging/kata-deploy/local-build/Makefile install
|
||||
|
||||
.PHONY: all default static-checks binary-tarball install-binary-tarball
|
||||
|
||||
89
README.md
89
README.md
@@ -2,22 +2,6 @@
|
||||
|
||||
# Kata Containers
|
||||
|
||||
* [Kata Containers](#kata-containers)
|
||||
* [Introduction](#introduction)
|
||||
* [Getting started](#getting-started)
|
||||
* [Documentation](#documentation)
|
||||
* [Community](#community)
|
||||
* [Getting help](#getting-help)
|
||||
* [Raising issues](#raising-issues)
|
||||
* [Kata Containers 1.x versions](#kata-containers-1x-versions)
|
||||
* [Developers](#developers)
|
||||
* [Components](#components)
|
||||
* [Kata Containers 1.x components](#kata-containers-1x-components)
|
||||
* [Common repositories](#common-repositories)
|
||||
* [Packaging and releases](#packaging-and-releases)
|
||||
|
||||
---
|
||||
|
||||
Welcome to Kata Containers!
|
||||
|
||||
This repository is the home of the Kata Containers code for the 2.0 and newer
|
||||
@@ -26,11 +10,6 @@ releases.
|
||||
If you want to learn about Kata Containers, visit the main
|
||||
[Kata Containers website](https://katacontainers.io).
|
||||
|
||||
For further details on the older (first generation) Kata Containers 1.x
|
||||
versions, see the
|
||||
[Kata Containers 1.x components](#kata-containers-1x-components)
|
||||
section.
|
||||
|
||||
## Introduction
|
||||
|
||||
Kata Containers is an open source project and community working to build a
|
||||
@@ -67,69 +46,34 @@ Please raise an issue
|
||||
> **Note:**
|
||||
> If you are reporting a security issue, please follow the [vulnerability reporting process](https://github.com/kata-containers/community#vulnerability-handling)
|
||||
|
||||
#### Kata Containers 1.x versions
|
||||
|
||||
For older Kata Containers 1.x releases, please raise an issue in the
|
||||
[Kata Containers 1.x component repository](#kata-containers-1x-components)
|
||||
that seems most appropriate.
|
||||
|
||||
If in doubt, raise an issue
|
||||
[in the Kata Containers 1.x runtime repository](https://github.com/kata-containers/runtime/issues).
|
||||
|
||||
## Developers
|
||||
|
||||
### Components
|
||||
|
||||
### Main components
|
||||
|
||||
The table below lists the core parts of the project:
|
||||
|
||||
| Component | Type | Description |
|
||||
|-|-|-|
|
||||
| [agent-ctl](tools/agent-ctl) | utility | Tool that provides low-level access for testing the agent. |
|
||||
| [runtime](src/runtime) | core | Main component run by a container manager and providing a containerd shimv2 runtime implementation. |
|
||||
| [agent](src/agent) | core | Management process running inside the virtual machine / POD that sets up the container environment. |
|
||||
| [documentation](docs) | documentation | Documentation common to all components (such as design and install documentation). |
|
||||
| [osbuilder](tools/osbuilder) | infrastructure | Tool to create "mini O/S" rootfs and initrd images for the hypervisor. |
|
||||
| [packaging](tools/packaging) | infrastructure | Scripts and metadata for producing packaged binaries<br/>(components, hypervisors, kernel and rootfs). |
|
||||
| [runtime](src/runtime) | core | Main component run by a container manager and providing a containerd shimv2 runtime implementation. |
|
||||
| [trace-forwarder](src/trace-forwarder) | utility | Agent tracing helper. |
|
||||
| [tests](https://github.com/kata-containers/tests) | tests | Excludes unit tests which live with the main code. |
|
||||
|
||||
#### Kata Containers 1.x components
|
||||
### Additional components
|
||||
|
||||
For the first generation of Kata Containers (1.x versions), each component was
|
||||
kept in a separate repository.
|
||||
|
||||
For information on the Kata Containers 1.x releases, see the
|
||||
[Kata Containers 1.x releases page](https://github.com/kata-containers/runtime/releases).
|
||||
|
||||
For further information on particular Kata Containers 1.x components, see the
|
||||
individual component repositories:
|
||||
The table below lists the remaining parts of the project:
|
||||
|
||||
| Component | Type | Description |
|
||||
|-|-|-|
|
||||
| [agent](https://github.com/kata-containers/agent) | core | See [components](#components). |
|
||||
| [documentation](https://github.com/kata-containers/documentation) | documentation | |
|
||||
| [KSM throttler](https://github.com/kata-containers/ksm-throttler) | optional core | Daemon that monitors containers and deduplicates memory to maximize container density on the host. |
|
||||
| [osbuilder](https://github.com/kata-containers/osbuilder) | infrastructure | See [components](#components). |
|
||||
| [packaging](https://github.com/kata-containers/packaging) | infrastructure | See [components](#components). |
|
||||
| [proxy](https://github.com/kata-containers/proxy) | core | Multiplexes communications between the shims, agent and runtime. |
|
||||
| [runtime](https://github.com/kata-containers/runtime) | core | See [components](#components). |
|
||||
| [shim](https://github.com/kata-containers/shim) | core | Handles standard I/O and signals on behalf of the container process. |
|
||||
|
||||
> **Note:**
|
||||
>
|
||||
> - There are more components for the original Kata Containers 1.x implementation.
|
||||
> - The current implementation simplifies the design significantly:
|
||||
> compare the [current](docs/design/architecture.md) and
|
||||
> [previous generation](https://github.com/kata-containers/documentation/blob/master/design/architecture.md)
|
||||
> designs.
|
||||
|
||||
### Common repositories
|
||||
|
||||
The following repositories are used by both the current and first generation Kata Containers implementations:
|
||||
|
||||
| Component | Description | Current | First generation | Notes |
|
||||
|-|-|-|-|-|
|
||||
| CI | Continuous Integration configuration files and scripts. | [Kata 2.x](https://github.com/kata-containers/ci/tree/main) | [Kata 1.x](https://github.com/kata-containers/ci/tree/master) | |
|
||||
| kernel | The Linux kernel used by the hypervisor to boot the guest image. | [Kata 2.x][kernel] | [Kata 1.x][kernel] | Patches are stored in the packaging component. |
|
||||
| tests | Test code. | [Kata 2.x](https://github.com/kata-containers/tests/tree/main) | [Kata 1.x](https://github.com/kata-containers/tests/tree/master) | Excludes unit tests which live with the main code. |
|
||||
| www.katacontainers.io | Contains the source for the [main web site](https://www.katacontainers.io). | [Kata 2.x][github-katacontainers.io] | [Kata 1.x][github-katacontainers.io] | | |
|
||||
| [packaging](tools/packaging) | infrastructure | Scripts and metadata for producing packaged binaries<br/>(components, hypervisors, kernel and rootfs). |
|
||||
| [kernel](https://www.kernel.org) | kernel | Linux kernel used by the hypervisor to boot the guest image. Patches are stored [here](tools/packaging/kernel). |
|
||||
| [osbuilder](tools/osbuilder) | infrastructure | Tool to create "mini O/S" rootfs and initrd images and kernel for the hypervisor. |
|
||||
| [`agent-ctl`](tools/agent-ctl) | utility | Tool that provides low-level access for testing the agent. |
|
||||
| [`trace-forwarder`](src/trace-forwarder) | utility | Agent tracing helper. |
|
||||
| [`ci`](https://github.com/kata-containers/ci) | CI | Continuous Integration configuration files and scripts. |
|
||||
| [`katacontainers.io`](https://github.com/kata-containers/www.katacontainers.io) | Source for the [`katacontainers.io`](https://www.katacontainers.io) site. |
|
||||
|
||||
### Packaging and releases
|
||||
|
||||
@@ -138,6 +82,9 @@ Kata Containers is now
|
||||
However, packaging scripts and metadata are still used to generate snap and GitHub releases. See
|
||||
the [components](#components) section for further details.
|
||||
|
||||
## Glossary of Terms
|
||||
|
||||
See the [glossary of terms](Glossary.md) related to Kata Containers.
|
||||
---
|
||||
|
||||
[kernel]: https://www.kernel.org
|
||||
|
||||
@@ -15,12 +15,18 @@ die() {
|
||||
# Install the yq yaml query package from the mikefarah github repo
|
||||
# Install via binary download, as we may not have golang installed at this point
|
||||
function install_yq() {
|
||||
GOPATH=${GOPATH:-${HOME}/go}
|
||||
local yq_path="${GOPATH}/bin/yq"
|
||||
local yq_pkg="github.com/mikefarah/yq"
|
||||
local yq_version=3.4.1
|
||||
INSTALL_IN_GOPATH=${INSTALL_IN_GOPATH:-true}
|
||||
|
||||
[ -x "${GOPATH}/bin/yq" ] && [ "`${GOPATH}/bin/yq --version`"X == "yq version ${yq_version}"X ] && return
|
||||
if [ "${INSTALL_IN_GOPATH}" == "true" ];then
|
||||
GOPATH=${GOPATH:-${HOME}/go}
|
||||
mkdir -p "${GOPATH}/bin"
|
||||
local yq_path="${GOPATH}/bin/yq"
|
||||
else
|
||||
yq_path="/usr/local/bin/yq"
|
||||
fi
|
||||
[ -x "${yq_path}" ] && [ "`${yq_path} --version`"X == "yq version ${yq_version}"X ] && return
|
||||
|
||||
read -r -a sysInfo <<< "$(uname -sm)"
|
||||
|
||||
@@ -51,7 +57,6 @@ function install_yq() {
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir -p "${GOPATH}/bin"
|
||||
|
||||
# Check curl
|
||||
if ! command -v "curl" >/dev/null; then
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -o nounset
|
||||
|
||||
export tests_repo="${tests_repo:-github.com/kata-containers/tests}"
|
||||
export tests_repo_dir="$GOPATH/src/$tests_repo"
|
||||
export branch="${branch:-main}"
|
||||
export branch="${target_branch:-main}"
|
||||
|
||||
# Clones the tests repository and checkout to the branch pointed out by
|
||||
# the global $branch variable.
|
||||
@@ -15,7 +17,7 @@ export branch="${branch:-main}"
|
||||
clone_tests_repo()
|
||||
{
|
||||
if [ -d "$tests_repo_dir" ]; then
|
||||
[ -n "$CI" ] && return
|
||||
[ -n "${CI:-}" ] && return
|
||||
pushd "${tests_repo_dir}"
|
||||
git checkout "${branch}"
|
||||
git pull
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
#
|
||||
# This is the build root image for Kata Containers on OpenShift CI.
|
||||
#
|
||||
FROM centos:8
|
||||
FROM registry.centos.org/centos:8
|
||||
|
||||
RUN yum -y update && yum -y install git sudo wget
|
||||
|
||||
@@ -13,4 +13,6 @@ clone_tests_repo
|
||||
|
||||
pushd ${tests_repo_dir}
|
||||
.ci/run.sh
|
||||
# temporary fix, see https://github.com/kata-containers/tests/issues/3878
|
||||
[ "$(uname -m)" != "s390x" ] && tracing/test-agent-shutdown.sh
|
||||
popd
|
||||
|
||||
@@ -1,56 +1,3 @@
|
||||
- [Warning](#warning)
|
||||
- [Assumptions](#assumptions)
|
||||
- [Initial setup](#initial-setup)
|
||||
- [Requirements to build individual components](#requirements-to-build-individual-components)
|
||||
- [Build and install the Kata Containers runtime](#build-and-install-the-kata-containers-runtime)
|
||||
- [Check hardware requirements](#check-hardware-requirements)
|
||||
- [Configure to use initrd or rootfs image](#configure-to-use-initrd-or-rootfs-image)
|
||||
- [Enable full debug](#enable-full-debug)
|
||||
- [debug logs and shimv2](#debug-logs-and-shimv2)
|
||||
- [Enabling full `containerd` debug](#enabling-full-containerd-debug)
|
||||
- [Enabling just `containerd shim` debug](#enabling-just-containerd-shim-debug)
|
||||
- [Enabling `CRI-O` and `shimv2` debug](#enabling-cri-o-and-shimv2-debug)
|
||||
- [journald rate limiting](#journald-rate-limiting)
|
||||
- [`systemd-journald` suppressing messages](#systemd-journald-suppressing-messages)
|
||||
- [Disabling `systemd-journald` rate limiting](#disabling-systemd-journald-rate-limiting)
|
||||
- [Create and install rootfs and initrd image](#create-and-install-rootfs-and-initrd-image)
|
||||
- [Build a custom Kata agent - OPTIONAL](#build-a-custom-kata-agent---optional)
|
||||
- [Get the osbuilder](#get-the-osbuilder)
|
||||
- [Create a rootfs image](#create-a-rootfs-image)
|
||||
- [Create a local rootfs](#create-a-local-rootfs)
|
||||
- [Add a custom agent to the image - OPTIONAL](#add-a-custom-agent-to-the-image---optional)
|
||||
- [Build a rootfs image](#build-a-rootfs-image)
|
||||
- [Install the rootfs image](#install-the-rootfs-image)
|
||||
- [Create an initrd image - OPTIONAL](#create-an-initrd-image---optional)
|
||||
- [Create a local rootfs for initrd image](#create-a-local-rootfs-for-initrd-image)
|
||||
- [Build an initrd image](#build-an-initrd-image)
|
||||
- [Install the initrd image](#install-the-initrd-image)
|
||||
- [Install guest kernel images](#install-guest-kernel-images)
|
||||
- [Install a hypervisor](#install-a-hypervisor)
|
||||
- [Build a custom QEMU](#build-a-custom-qemu)
|
||||
- [Build a custom QEMU for aarch64/arm64 - REQUIRED](#build-a-custom-qemu-for-aarch64arm64---required)
|
||||
- [Run Kata Containers with Containerd](#run-kata-containers-with-containerd)
|
||||
- [Run Kata Containers with Kubernetes](#run-kata-containers-with-kubernetes)
|
||||
- [Troubleshoot Kata Containers](#troubleshoot-kata-containers)
|
||||
- [Appendices](#appendices)
|
||||
- [Checking Docker default runtime](#checking-docker-default-runtime)
|
||||
- [Set up a debug console](#set-up-a-debug-console)
|
||||
- [Simple debug console setup](#simple-debug-console-setup)
|
||||
- [Enable agent debug console](#enable-agent-debug-console)
|
||||
- [Start `kata-monitor` - ONLY NEEDED FOR 2.0.x](#start-kata-monitor---only-needed-for-20x)
|
||||
- [Connect to debug console](#connect-to-debug-console)
|
||||
- [Traditional debug console setup](#traditional-debug-console-setup)
|
||||
- [Create a custom image containing a shell](#create-a-custom-image-containing-a-shell)
|
||||
- [Build the debug image](#build-the-debug-image)
|
||||
- [Configure runtime for custom debug image](#configure-runtime-for-custom-debug-image)
|
||||
- [Create a container](#create-a-container)
|
||||
- [Connect to the virtual machine using the debug console](#connect-to-the-virtual-machine-using-the-debug-console)
|
||||
- [Enabling debug console for QEMU](#enabling-debug-console-for-qemu)
|
||||
- [Enabling debug console for cloud-hypervisor / firecracker](#enabling-debug-console-for-cloud-hypervisor--firecracker)
|
||||
- [Connecting to the debug console](#connecting-to-the-debug-console)
|
||||
- [Obtain details of the image](#obtain-details-of-the-image)
|
||||
- [Capturing kernel boot logs](#capturing-kernel-boot-logs)
|
||||
|
||||
# Warning
|
||||
|
||||
This document is written **specifically for developers**: it is not intended for end users.
|
||||
@@ -354,12 +301,13 @@ You MUST choose one of `alpine`, `centos`, `clearlinux`, `euleros`, and `fedora`
|
||||
>
|
||||
> - Check the [compatibility matrix](../tools/osbuilder/README.md#platform-distro-compatibility-matrix) before creating rootfs.
|
||||
|
||||
Optionally, add your custom agent binary to the rootfs with the following, `LIBC` default is `musl`, if `ARCH` is `ppc64le`, should set the `LIBC=gnu` and `ARCH=powerpc64le`:
|
||||
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=$(shell uname -m)
|
||||
$ [ ${ARCH} == "ppc64le" ] && export LIBC=gnu || export LIBC=musl
|
||||
$ 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
|
||||
$ sudo install -o root -g root -m 0550 -T ../../../src/agent/target/${ARCH}-unknown-linux-${LIBC}/release/kata-agent ${ROOTFS_DIR}/sbin/init
|
||||
```
|
||||
|
||||
### Build an initrd image
|
||||
@@ -469,7 +417,7 @@ script and paste its output directly into a
|
||||
> [runtime](../src/runtime) repository.
|
||||
|
||||
To perform analysis on Kata logs, use the
|
||||
[`kata-log-parser`](https://github.com/kata-containers/tests/tree/master/cmd/log-parser)
|
||||
[`kata-log-parser`](https://github.com/kata-containers/tests/tree/main/cmd/log-parser)
|
||||
tool, which can convert the logs into formats (e.g. JSON, TOML, XML, and YAML).
|
||||
|
||||
See [Set up a debug console](#set-up-a-debug-console).
|
||||
@@ -656,7 +604,7 @@ VMM solution.
|
||||
|
||||
In case of cloud-hypervisor, connect to the `vsock` as shown:
|
||||
```
|
||||
$ sudo su -c 'cd /var/run/vc/vm/{sandbox_id}/root/ && socat stdin unix-connect:clh.sock'
|
||||
$ sudo su -c 'cd /var/run/vc/vm/${sandbox_id}/root/ && socat stdin unix-connect:clh.sock'
|
||||
CONNECT 1026
|
||||
```
|
||||
|
||||
@@ -664,7 +612,7 @@ CONNECT 1026
|
||||
|
||||
For firecracker, connect to the `hvsock` as shown:
|
||||
```
|
||||
$ sudo su -c 'cd /var/run/vc/firecracker/{sandbox_id}/root/ && socat stdin unix-connect:kata.hvsock'
|
||||
$ sudo su -c 'cd /var/run/vc/firecracker/${sandbox_id}/root/ && socat stdin unix-connect:kata.hvsock'
|
||||
CONNECT 1026
|
||||
```
|
||||
|
||||
@@ -673,7 +621,7 @@ CONNECT 1026
|
||||
|
||||
For QEMU, connect to the `vsock` as shown:
|
||||
```
|
||||
$ sudo su -c 'cd /var/run/vc/vm/{sandbox_id} && socat "stdin,raw,echo=0,escape=0x11" "unix-connect:console.sock"
|
||||
$ sudo su -c 'cd /var/run/vc/vm/${sandbox_id} && socat "stdin,raw,echo=0,escape=0x11" "unix-connect:console.sock"'
|
||||
```
|
||||
|
||||
To disconnect from the virtual machine, type `CONTROL+q` (hold down the
|
||||
|
||||
@@ -1,16 +1,3 @@
|
||||
* [Introduction](#introduction)
|
||||
* [General requirements](#general-requirements)
|
||||
* [Linking advice](#linking-advice)
|
||||
* [Notes](#notes)
|
||||
* [Warnings and other admonitions](#warnings-and-other-admonitions)
|
||||
* [Files and command names](#files-and-command-names)
|
||||
* [Code blocks](#code-blocks)
|
||||
* [Images](#images)
|
||||
* [Spelling](#spelling)
|
||||
* [Names](#names)
|
||||
* [Version numbers](#version-numbers)
|
||||
* [The apostrophe](#the-apostrophe)
|
||||
|
||||
# Introduction
|
||||
|
||||
This document outlines the requirements for all documentation in the [Kata
|
||||
@@ -23,10 +10,6 @@ All documents must:
|
||||
- Be written in simple English.
|
||||
- Be written in [GitHub Flavored Markdown](https://github.github.com/gfm) format.
|
||||
- Have a `.md` file extension.
|
||||
- Include a TOC (table of contents) at the top of the document with links to
|
||||
all heading sections. We recommend using the
|
||||
[`kata-check-markdown`](https://github.com/kata-containers/tests/tree/master/cmd/check-markdown)
|
||||
tool to generate the TOC.
|
||||
- Be linked to from another document in the same repository.
|
||||
|
||||
Although GitHub allows navigation of the entire repository, it should be
|
||||
@@ -43,6 +26,10 @@ All documents must:
|
||||
which can then execute the commands specified to ensure the instructions are
|
||||
correct. This avoids documents becoming out of date over time.
|
||||
|
||||
> **Note:**
|
||||
>
|
||||
> Do not add a table of contents (TOC) since GitHub will auto-generate one.
|
||||
|
||||
# Linking advice
|
||||
|
||||
Linking between documents is strongly encouraged to help users and developers
|
||||
@@ -118,7 +105,7 @@ This section lists requirements for displaying commands and command output.
|
||||
The requirements must be adhered to since documentation containing code blocks
|
||||
is validated by the CI system, which executes the command blocks with the help
|
||||
of the
|
||||
[doc-to-script](https://github.com/kata-containers/tests/tree/master/.ci/kata-doc-to-script.sh)
|
||||
[doc-to-script](https://github.com/kata-containers/tests/tree/main/.ci/kata-doc-to-script.sh)
|
||||
utility.
|
||||
|
||||
- If a document includes commands the user should run, they **MUST** be shown
|
||||
@@ -202,7 +189,7 @@ and compare them with standard tools (e.g. `diff(1)`).
|
||||
|
||||
Since this project uses a number of terms not found in conventional
|
||||
dictionaries, we have a
|
||||
[spell checking tool](https://github.com/kata-containers/tests/tree/master/cmd/check-spelling)
|
||||
[spell checking tool](https://github.com/kata-containers/tests/tree/main/cmd/check-spelling)
|
||||
that checks both dictionary words and the additional terms we use.
|
||||
|
||||
Run the spell checking tool on your document before raising a PR to ensure it
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
# Licensing strategy
|
||||
|
||||
* [Project License](#project-license)
|
||||
* [License file](#license-file)
|
||||
* [License for individual files](#license-for-individual-files)
|
||||
|
||||
## Project License
|
||||
|
||||
The license for the [Kata Containers](https://github.com/kata-containers)
|
||||
|
||||
@@ -1,35 +1,3 @@
|
||||
* [Overview](#overview)
|
||||
* [Definition of a limitation](#definition-of-a-limitation)
|
||||
* [Scope](#scope)
|
||||
* [Contributing](#contributing)
|
||||
* [Pending items](#pending-items)
|
||||
* [Runtime commands](#runtime-commands)
|
||||
* [checkpoint and restore](#checkpoint-and-restore)
|
||||
* [events command](#events-command)
|
||||
* [update command](#update-command)
|
||||
* [Networking](#networking)
|
||||
* [Docker swarm and compose support](#docker-swarm-and-compose-support)
|
||||
* [Resource management](#resource-management)
|
||||
* [docker run and shared memory](#docker-run-and-shared-memory)
|
||||
* [docker run and sysctl](#docker-run-and-sysctl)
|
||||
* [Docker daemon features](#docker-daemon-features)
|
||||
* [SELinux support](#selinux-support)
|
||||
* [Architectural limitations](#architectural-limitations)
|
||||
* [Networking limitations](#networking-limitations)
|
||||
* [Support for joining an existing VM network](#support-for-joining-an-existing-vm-network)
|
||||
* [docker --net=host](#docker---nethost)
|
||||
* [docker run --link](#docker-run---link)
|
||||
* [Storage limitations](#storage-limitations)
|
||||
* [Kubernetes `volumeMounts.subPaths`](#kubernetes-volumemountssubpaths)
|
||||
* [Host resource sharing](#host-resource-sharing)
|
||||
* [docker run --privileged](#docker-run---privileged)
|
||||
* [Miscellaneous](#miscellaneous)
|
||||
* [Docker --security-opt option partially supported](#docker---security-opt-option-partially-supported)
|
||||
* [Appendices](#appendices)
|
||||
* [The constraints challenge](#the-constraints-challenge)
|
||||
|
||||
***
|
||||
|
||||
# Overview
|
||||
|
||||
A [Kata Container](https://github.com/kata-containers) utilizes a Virtual Machine (VM) to enhance security and
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
# Documentation
|
||||
|
||||
* [Getting Started](#getting-started)
|
||||
* [More User Guides](#more-user-guides)
|
||||
* [Kata Use-Cases](#kata-use-cases)
|
||||
* [Developer Guide](#developer-guide)
|
||||
* [Design and Implementations](#design-and-implementations)
|
||||
* [How to Contribute](#how-to-contribute)
|
||||
* [Code Licensing](#code-licensing)
|
||||
* [The Release Process](#the-release-process)
|
||||
* [Help Improving the Documents](#help-improving-the-documents)
|
||||
* [Website Changes](#website-changes)
|
||||
|
||||
The [Kata Containers](https://github.com/kata-containers)
|
||||
documentation repository hosts overall system documentation, with information
|
||||
common to multiple components.
|
||||
|
||||
@@ -1,20 +1,6 @@
|
||||
|
||||
# How to do a Kata Containers Release
|
||||
This document lists the tasks required to create a Kata Release.
|
||||
|
||||
<!-- TOC START min:1 max:3 link:true asterisk:false update:true -->
|
||||
- [How to do a Kata Containers Release](#how-to-do-a-kata-containers-release)
|
||||
- [Requirements](#requirements)
|
||||
- [Release Process](#release-process)
|
||||
- [Bump all Kata repositories](#bump-all-kata-repositories)
|
||||
- [Merge all bump version Pull requests](#merge-all-bump-version-pull-requests)
|
||||
- [Tag all Kata repositories](#tag-all-kata-repositories)
|
||||
- [Check Git-hub Actions](#check-git-hub-actions)
|
||||
- [Create release notes](#create-release-notes)
|
||||
- [Announce the release](#announce-the-release)
|
||||
<!-- TOC END -->
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
- [hub](https://github.com/github/hub)
|
||||
|
||||
@@ -1,16 +1,3 @@
|
||||
* [Introduction](#introduction)
|
||||
* [Maintenance warning](#maintenance-warning)
|
||||
* [Determine current version](#determine-current-version)
|
||||
* [Determine latest version](#determine-latest-version)
|
||||
* [Configuration changes](#configuration-changes)
|
||||
* [Upgrade Kata Containers](#upgrade-kata-containers)
|
||||
* [Upgrade native distribution packaged version](#upgrade-native-distribution-packaged-version)
|
||||
* [Static installation](#static-installation)
|
||||
* [Determine if you are using a static installation](#determine-if-you-are-using-a-static-installation)
|
||||
* [Remove a static installation](#remove-a-static-installation)
|
||||
* [Upgrade a static installation](#upgrade-a-static-installation)
|
||||
* [Custom assets](#custom-assets)
|
||||
|
||||
# Introduction
|
||||
|
||||
This document outlines the options for upgrading from a
|
||||
|
||||
@@ -8,4 +8,9 @@ Kata Containers design documents:
|
||||
- [VSocks](VSocks.md)
|
||||
- [VCPU handling](vcpu-handling.md)
|
||||
- [Host cgroups](host-cgroups.md)
|
||||
- [`Inotify` support](inotify.md)
|
||||
- [Metrics(Kata 2.0)](kata-2-0-metrics.md)
|
||||
|
||||
---
|
||||
|
||||
- [Design proposals](proposals)
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
# Kata Containers and VSOCKs
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [VSOCK communication diagram](#vsock-communication-diagram)
|
||||
- [System requirements](#system-requirements)
|
||||
- [Advantages of using VSOCKs](#advantages-of-using-vsocks)
|
||||
- [High density](#high-density)
|
||||
- [Reliability](#reliability)
|
||||
|
||||
## Introduction
|
||||
|
||||
There are two different ways processes in the virtual machine can communicate
|
||||
|
||||
BIN
docs/design/arch-images/inotify-workaround.png
Normal file
BIN
docs/design/arch-images/inotify-workaround.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 101 KiB |
@@ -1,26 +1,5 @@
|
||||
# Kata Containers Architecture
|
||||
|
||||
|
||||
- [Kata Containers Architecture](#kata-containers-architecture)
|
||||
- [Overview](#overview)
|
||||
- [Virtualization](#virtualization)
|
||||
- [Guest assets](#guest-assets)
|
||||
- [Guest kernel](#guest-kernel)
|
||||
- [Guest image](#guest-image)
|
||||
- [Root filesystem image](#root-filesystem-image)
|
||||
- [Initrd image](#initrd-image)
|
||||
- [Agent](#agent)
|
||||
- [Runtime](#runtime)
|
||||
- [Configuration](#configuration)
|
||||
- [Networking](#networking)
|
||||
- [Network Hotplug](#network-hotplug)
|
||||
- [Storage](#storage)
|
||||
- [Kubernetes support](#kubernetes-support)
|
||||
- [OCI annotations](#oci-annotations)
|
||||
- [Mixing VM based and namespace based runtimes](#mixing-vm-based-and-namespace-based-runtimes)
|
||||
- [Appendices](#appendices)
|
||||
- [DAX](#dax)
|
||||
|
||||
## Overview
|
||||
|
||||
This is an architectural overview of Kata Containers, based on the 2.0 release.
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# Kata Containers E2E Flow
|
||||
|
||||
|
||||

|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
- [Host cgroup management](#host-cgroup-management)
|
||||
- [Introduction](#introduction)
|
||||
- [`SandboxCgroupOnly` enabled](#sandboxcgrouponly-enabled)
|
||||
- [What does Kata do in this configuration?](#what-does-kata-do-in-this-configuration)
|
||||
- [Why create a Kata-cgroup under the parent cgroup?](#why-create-a-kata-cgroup-under-the-parent-cgroup)
|
||||
- [Improvements](#improvements)
|
||||
- [`SandboxCgroupOnly` disabled (default, legacy)](#sandboxcgrouponly-disabled-default-legacy)
|
||||
- [What does this method do?](#what-does-this-method-do)
|
||||
- [Impact](#impact)
|
||||
- [Supported cgroups](#supported-cgroups)
|
||||
- [Cgroups V1](#cgroups-v1)
|
||||
- [Cgroups V2](#cgroups-v2)
|
||||
- [Distro Support](#distro-support)
|
||||
- [Summary](#summary)
|
||||
|
||||
# Host cgroup management
|
||||
|
||||
## Introduction
|
||||
|
||||
30
docs/design/inotify.md
Normal file
30
docs/design/inotify.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Kata Containers support for `inotify`
|
||||
|
||||
## Background on `inotify` usage
|
||||
|
||||
A common pattern in Kubernetes is to watch for changes to files/directories passed in as `ConfigMaps`
|
||||
or `Secrets`. Sidecar's normally use `inotify` to watch for changes and then signal the primary container to reload
|
||||
the updated configuration. Kata Containers typically will pass these host files into the guest using `virtiofs`, which
|
||||
does not support `inotify` today. While we work to enable this use case in `virtiofs`, we introduced a workaround in Kata Containers.
|
||||
This document describes how Kata Containers implements this workaround.
|
||||
|
||||
### Detecting a `watchable` mount
|
||||
|
||||
Kubernetes creates `secrets` and `ConfigMap` mounts at very specific locations on the host filesystem. For container mounts,
|
||||
the `Kata Containers` runtime will check the source of the mount to identify these special cases. For these use cases, only a single file
|
||||
or very few would typically need to be watched. To avoid excessive overheads in making a mount watchable,
|
||||
we enforce a limit of eight files per mount. If a `secret` or `ConfigMap` mount contains more than 8 files, it will not be
|
||||
considered watchable. We similarly enforce a limit of 1 MB per mount to be considered watchable. Non-watchable mounts will
|
||||
continue to propagate changes from the mount on the host to the container workload, but these updates will not trigger an
|
||||
`inotify` event.
|
||||
|
||||
If at any point a mount grows beyond the eight file or 1MB limit, it will no longer be `watchable.`
|
||||
|
||||
### Presenting a `watchable` mount to the workload
|
||||
|
||||
For mounts that are considered `watchable`, inside the guest, the `kata-agent` will poll the mount presented from
|
||||
the host through `virtiofs` and copy any changed files to a `tmpfs` mount that is presented to the container. In this way,
|
||||
for `watchable` mounts, Kata will do the polling on behalf of the workload and existing workloads needn't change their usage
|
||||
of `inotify`.
|
||||
|
||||

|
||||
@@ -1,20 +1,5 @@
|
||||
# Kata 2.0 Metrics Design
|
||||
|
||||
* [Limitations of Kata 1.x and the target of Kata 2.0](#limitations-of-kata-1x-and-the-target-of-kata-20)
|
||||
* [Metrics architecture](#metrics-architecture)
|
||||
* [Kata monitor](#kata-monitor)
|
||||
* [Kata runtime](#kata-runtime)
|
||||
* [Kata agent](#kata-agent)
|
||||
* [Performance and overhead](#performance-and-overhead)
|
||||
* [Metrics list](#metrics-list)
|
||||
* [Metric types](#metric-types)
|
||||
* [Kata agent metrics](#kata-agent-metrics)
|
||||
* [Firecracker metrics](#firecracker-metrics)
|
||||
* [Kata guest OS metrics](#kata-guest-os-metrics)
|
||||
* [Hypervisor metrics](#hypervisor-metrics)
|
||||
* [Kata monitor metrics](#kata-monitor-metrics)
|
||||
* [Kata containerd shim v2 metrics](#kata-containerd-shim-v2-metrics)
|
||||
|
||||
Kata implement CRI's API and support [`ContainerStats`](https://github.com/kubernetes/kubernetes/blob/release-1.18/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.proto#L101) and [`ListContainerStats`](https://github.com/kubernetes/kubernetes/blob/release-1.18/staging/src/k8s.io/cri-api/pkg/apis/runtime/v1alpha2/api.proto#L103) interfaces to expose containers metrics. User can use these interface to get basic metrics about container.
|
||||
|
||||
But unlike `runc`, Kata is a VM-based runtime and has a different architecture.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# Kata API Design
|
||||
|
||||
To fulfill the [Kata design requirements](kata-design-requirements.md), and based on the discussion on [Virtcontainers API extensions](https://docs.google.com/presentation/d/1dbGrD1h9cpuqAPooiEgtiwWDGCYhVPdatq7owsKHDEQ), the Kata runtime library features the following APIs:
|
||||
- Sandbox based top API
|
||||
- Storage and network hotplug API
|
||||
|
||||
5
docs/design/proposals/README.md
Normal file
5
docs/design/proposals/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Design proposals
|
||||
|
||||
Kata Containers design proposal documents:
|
||||
|
||||
- [Kata Containers tracing](tracing-proposals.md)
|
||||
213
docs/design/proposals/tracing-proposals.md
Normal file
213
docs/design/proposals/tracing-proposals.md
Normal file
@@ -0,0 +1,213 @@
|
||||
# Kata Tracing proposals
|
||||
|
||||
## Overview
|
||||
|
||||
This document summarises a set of proposals triggered by the
|
||||
[tracing documentation PR][tracing-doc-pr].
|
||||
|
||||
## Required context
|
||||
|
||||
This section explains some terminology required to understand the proposals.
|
||||
Further details can be found in the
|
||||
[tracing documentation PR][tracing-doc-pr].
|
||||
|
||||
### Agent trace mode terminology
|
||||
|
||||
| Trace mode | Description | Use-case |
|
||||
|-|-|-|
|
||||
| Static | Trace agent from startup to shutdown | Entire lifespan |
|
||||
| Dynamic | Toggle tracing on/off as desired | On-demand "snapshot" |
|
||||
|
||||
### Agent trace type terminology
|
||||
|
||||
| Trace type | Description | Use-case |
|
||||
|-|-|-|
|
||||
| isolated | traces all relate to single component | Observing lifespan |
|
||||
| collated | traces "grouped" (runtime+agent) | Understanding component interaction |
|
||||
|
||||
### Container lifespan
|
||||
|
||||
| Lifespan | trace mode | trace type |
|
||||
|-|-|-|
|
||||
| short-lived | static | collated if possible, else isolated? |
|
||||
| long-running | dynamic | collated? (to see interactions) |
|
||||
|
||||
## Original plan for agent
|
||||
|
||||
- Implement all trace types and trace modes for agent.
|
||||
|
||||
- Why?
|
||||
- Maximum flexibility.
|
||||
|
||||
> **Counterargument:**
|
||||
>
|
||||
> Due to the intrusive nature of adding tracing, we have
|
||||
> learnt that landing small incremental changes is simpler and quicker!
|
||||
|
||||
- Compatibility with [Kata 1.x tracing][kata-1x-tracing].
|
||||
|
||||
> **Counterargument:**
|
||||
>
|
||||
> Agent tracing in Kata 1.x was extremely awkward to setup (to the extent
|
||||
> that it's unclear how many users actually used it!)
|
||||
>
|
||||
> This point, coupled with the new architecture for Kata 2.x, suggests
|
||||
> that we may not need to supply the same set of tracing features (in fact
|
||||
> they may not make sense)).
|
||||
|
||||
## Agent tracing proposals
|
||||
|
||||
### Agent tracing proposal 1: Don't implement dynamic trace mode
|
||||
|
||||
- All tracing will be static.
|
||||
|
||||
- Why?
|
||||
- Because dynamic tracing will always be "partial"
|
||||
|
||||
> In fact, not only would it be only a "snapshot" of activity, it may not
|
||||
> even be possible to create a complete "trace transaction". If this is
|
||||
> true, the trace output would be partial and would appear "unstructured".
|
||||
|
||||
### Agent tracing proposal 2: Simplify handling of trace type
|
||||
|
||||
- Agent tracing will be "isolated" by default.
|
||||
- Agent tracing will be "collated" if runtime tracing is also enabled.
|
||||
|
||||
- Why?
|
||||
- Offers a graceful fallback for agent tracing if runtime tracing disabled.
|
||||
- Simpler code!
|
||||
|
||||
## Questions to ask yourself (part 1)
|
||||
|
||||
- Are your containers long-running or short-lived?
|
||||
|
||||
- Would you ever need to turn on tracing "briefly"?
|
||||
- If "yes", is a "partial trace" useful or useless?
|
||||
|
||||
> Likely to be considered useless as it is a partial snapshot.
|
||||
> Alternative tracing methods may be more appropriate to dynamic
|
||||
> OpenTelemetry tracing.
|
||||
|
||||
## Questions to ask yourself (part 2)
|
||||
|
||||
- Are you happy to stop a container to enable tracing?
|
||||
If "no", dynamic tracing may be required.
|
||||
|
||||
- Would you ever want to trace the agent and the runtime "in isolation" at the
|
||||
same time?
|
||||
- If "yes", we need to fully implement `trace_mode=isolated`
|
||||
|
||||
> This seems unlikely though.
|
||||
|
||||
## Trace collection
|
||||
|
||||
The second set of proposals affect the way traces are collected.
|
||||
|
||||
### Motivation
|
||||
|
||||
Currently:
|
||||
|
||||
- The runtime sends trace spans to Jaeger directly.
|
||||
- The agent will send trace spans to the [`trace-forwarder`][trace-forwarder] component.
|
||||
- The trace forwarder will send trace spans to Jaeger.
|
||||
|
||||
Kata agent tracing overview:
|
||||
|
||||
```
|
||||
+-------------------------------------------+
|
||||
| Host |
|
||||
| |
|
||||
| +-----------+ |
|
||||
| | Trace | |
|
||||
| | Collector | |
|
||||
| +-----+-----+ |
|
||||
| ^ +--------------+ |
|
||||
| | spans | Kata VM | |
|
||||
| +-----+-----+ | | |
|
||||
| | Kata | spans | +-----+ | |
|
||||
| | Trace |<-----------------|Kata | | |
|
||||
| | Forwarder | VSOCK | |Agent| | |
|
||||
| +-----------+ Channel | +-----+ | |
|
||||
| +--------------+ |
|
||||
+-------------------------------------------+
|
||||
```
|
||||
|
||||
Currently:
|
||||
|
||||
- If agent tracing is enabled but the trace forwarder is not running,
|
||||
the agent will error.
|
||||
|
||||
- If the trace forwarder is started but Jaeger is not running,
|
||||
the trace forwarder will error.
|
||||
|
||||
### Goals
|
||||
|
||||
- The runtime and agent should:
|
||||
- Use the same trace collection implementation.
|
||||
- Use the most the common configuration items.
|
||||
|
||||
- Kata should should support more trace collection software or `SaaS`
|
||||
(for example `Zipkin`, `datadog`).
|
||||
|
||||
- Trace collection should not block normal runtime/agent operations
|
||||
(for example if `vsock-exporter`/Jaeger is not running, Kata Containers should work normally).
|
||||
|
||||
### Trace collection proposals
|
||||
|
||||
#### Trace collection proposal 1: Send all spans to the trace forwarder as a span proxy
|
||||
|
||||
Kata runtime/agent all send spans to trace forwarder, and the trace forwarder,
|
||||
acting as a tracing proxy, sends all spans to a tracing back-end, such as Jaeger or `datadog`.
|
||||
|
||||
**Pros:**
|
||||
|
||||
- Runtime/agent will be simple.
|
||||
- Could update trace collection target while Kata Containers are running.
|
||||
|
||||
**Cons:**
|
||||
|
||||
- Requires the trace forwarder component to be running (that is a pressure to operation).
|
||||
|
||||
#### Trace collection proposal 2: Send spans to collector directly from runtime/agent
|
||||
|
||||
Send spans to collector directly from runtime/agent, this proposal need
|
||||
network accessible to the collector.
|
||||
|
||||
**Pros:**
|
||||
|
||||
- No additional trace forwarder component needed.
|
||||
|
||||
**Cons:**
|
||||
|
||||
- Need more code/configuration to support all trace collectors.
|
||||
|
||||
## Future work
|
||||
|
||||
- We could add dynamic and fully isolated tracing at a later stage,
|
||||
if required.
|
||||
|
||||
## Further details
|
||||
|
||||
- See the new [GitHub project](https://github.com/orgs/kata-containers/projects/28).
|
||||
- [kata-containers-tracing-status](https://gist.github.com/jodh-intel/0ee54d41d2a803ba761e166136b42277) gist.
|
||||
- [tracing documentation PR][tracing-doc-pr].
|
||||
|
||||
## Summary
|
||||
|
||||
### Time line
|
||||
|
||||
- 2021-07-01: A summary of the discussion was
|
||||
[posted to the mail list](http://lists.katacontainers.io/pipermail/kata-dev/2021-July/001996.html).
|
||||
- 2021-06-22: These proposals were
|
||||
[discussed in the Kata Architecture Committee meeting](https://etherpad.opendev.org/p/Kata_Containers_2021_Architecture_Committee_Mtgs).
|
||||
- 2021-06-18: These proposals where
|
||||
[announced on the mailing list](http://lists.katacontainers.io/pipermail/kata-dev/2021-June/001980.html).
|
||||
|
||||
### Outcome
|
||||
|
||||
- Nobody opposed the agent proposals, so they are being implemented.
|
||||
- The trace collection proposals are still being considered.
|
||||
|
||||
[kata-1x-tracing]: https://github.com/kata-containers/agent/blob/master/TRACING.md
|
||||
[trace-forwarder]: /src/trace-forwarder
|
||||
[tracing-doc-pr]: https://github.com/kata-containers/kata-containers/pull/1937
|
||||
@@ -1,11 +1,3 @@
|
||||
- [Virtual machine vCPU sizing in Kata Containers](#virtual-machine-vcpu-sizing-in-kata-containers)
|
||||
* [Default number of virtual CPUs](#default-number-of-virtual-cpus)
|
||||
* [Virtual CPUs and Kubernetes pods](#virtual-cpus-and-kubernetes-pods)
|
||||
* [Container lifecycle](#container-lifecycle)
|
||||
* [Container without CPU constraint](#container-without-cpu-constraint)
|
||||
* [Container with CPU constraint](#container-with-cpu-constraint)
|
||||
* [Do not waste resources](#do-not-waste-resources)
|
||||
|
||||
# Virtual machine vCPU sizing in Kata Containers
|
||||
|
||||
## Default number of virtual CPUs
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
# Virtualization in Kata Containers
|
||||
|
||||
- [Virtualization in Kata Containers](#virtualization-in-kata-containers)
|
||||
- [Mapping container concepts to virtual machine technologies](#mapping-container-concepts-to-virtual-machine-technologies)
|
||||
- [Kata Containers Hypervisor and VMM support](#kata-containers-hypervisor-and-vmm-support)
|
||||
- [QEMU/KVM](#qemukvm)
|
||||
- [Machine accelerators](#machine-accelerators)
|
||||
- [Hotplug devices](#hotplug-devices)
|
||||
- [Firecracker/KVM](#firecrackerkvm)
|
||||
- [Cloud Hypervisor/KVM](#cloud-hypervisorkvm)
|
||||
- [Summary](#summary)
|
||||
|
||||
|
||||
Kata Containers, a second layer of isolation is created on top of those provided by traditional namespace-containers. The
|
||||
hardware virtualization interface is the basis of this additional layer. Kata will launch a lightweight virtual machine,
|
||||
and use the guest’s Linux kernel to create a container workload, or workloads in the case of multi-container pods. In Kubernetes
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
# Howto Guides
|
||||
|
||||
* [Howto Guides](#howto-guides)
|
||||
* [Kubernetes Integration](#kubernetes-integration)
|
||||
* [Hypervisors Integration](#hypervisors-integration)
|
||||
* [Advanced Topics](#advanced-topics)
|
||||
|
||||
## Kubernetes Integration
|
||||
|
||||
- [Run Kata containers with `crictl`](run-kata-with-crictl.md)
|
||||
- [Run Kata Containers with Kubernetes](run-kata-with-k8s.md)
|
||||
- [How to use Kata Containers and Containerd](containerd-kata.md)
|
||||
@@ -21,13 +17,13 @@
|
||||
- `firecracker`
|
||||
- `ACRN`
|
||||
|
||||
While `qemu` and `cloud-hypervisor` work out of the box with installation of Kata,
|
||||
some additional configuration is needed in case of `firecracker` and `ACRN`.
|
||||
While `qemu` , `cloud-hypervisor` and `firecracker` work out of the box with installation of Kata,
|
||||
some additional configuration is needed in case of `ACRN`.
|
||||
Refer to the following guides for additional configuration steps:
|
||||
- [Kata Containers with Firecracker](https://github.com/kata-containers/documentation/wiki/Initial-release-of-Kata-Containers-with-Firecracker-support)
|
||||
- [Kata Containers with ACRN Hypervisor](how-to-use-kata-containers-with-acrn.md)
|
||||
|
||||
## Advanced Topics
|
||||
|
||||
- [How to use Kata Containers with virtio-fs](how-to-use-virtio-fs-with-kata.md)
|
||||
- [Setting Sysctls with Kata](how-to-use-sysctls-with-kata.md)
|
||||
- [What Is VMCache and How To Enable It](what-is-vm-cache-and-how-do-I-use-it.md)
|
||||
|
||||
@@ -1,23 +1,5 @@
|
||||
# How to use Kata Containers and Containerd
|
||||
|
||||
- [Concepts](#concepts)
|
||||
- [Kubernetes `RuntimeClass`](#kubernetes-runtimeclass)
|
||||
- [Containerd Runtime V2 API: Shim V2 API](#containerd-runtime-v2-api-shim-v2-api)
|
||||
- [Install](#install)
|
||||
- [Install Kata Containers](#install-kata-containers)
|
||||
- [Install containerd with CRI plugin](#install-containerd-with-cri-plugin)
|
||||
- [Install CNI plugins](#install-cni-plugins)
|
||||
- [Install `cri-tools`](#install-cri-tools)
|
||||
- [Configuration](#configuration)
|
||||
- [Configure containerd to use Kata Containers](#configure-containerd-to-use-kata-containers)
|
||||
- [Kata Containers as a `RuntimeClass`](#kata-containers-as-a-runtimeclass)
|
||||
- [Kata Containers as the runtime for untrusted workload](#kata-containers-as-the-runtime-for-untrusted-workload)
|
||||
- [Kata Containers as the default runtime](#kata-containers-as-the-default-runtime)
|
||||
- [Configuration for `cri-tools`](#configuration-for-cri-tools)
|
||||
- [Run](#run)
|
||||
- [Launch containers with `ctr` command line](#launch-containers-with-ctr-command-line)
|
||||
- [Launch Pods with `crictl` command line](#launch-pods-with-crictl-command-line)
|
||||
|
||||
This document covers the installation and configuration of [containerd](https://containerd.io/)
|
||||
and [Kata Containers](https://katacontainers.io). The containerd provides not only the `ctr`
|
||||
command line tool, but also the [CRI](https://kubernetes.io/blog/2016/12/container-runtime-interface-cri-in-kubernetes/)
|
||||
|
||||
@@ -26,7 +26,7 @@ spec:
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: kata-monitor
|
||||
image: docker.io/katadocker/kata-monitor:2.0.0
|
||||
image: quay.io/kata-containers/kata-monitor:2.0.0
|
||||
args:
|
||||
- -log-level=debug
|
||||
ports:
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
# How to use memory hotplug feature in Kata Containers on arm64
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Install UEFI ROM](#install-uefi-rom)
|
||||
- [Run for test](#run-for-test)
|
||||
|
||||
## Introduction
|
||||
|
||||
Memory hotplug is a key feature for containers to allocate memory dynamically in deployment.
|
||||
|
||||
@@ -1,20 +1,5 @@
|
||||
# Importing Kata Containers logs with Fluentd
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [Overview](#overview)
|
||||
* [Test stack](#test-stack)
|
||||
* [Importing the logs](#importing-the-logs)
|
||||
* [Direct import `logfmt` from `systemd`](#direct-import-logfmt-from-systemd)
|
||||
* [Configuring `minikube`](#configuring-minikube)
|
||||
* [Pull from `systemd`](#pull-from-systemd)
|
||||
* [Systemd Summary](#systemd-summary)
|
||||
* [Directly importing JSON](#directly-importing-json)
|
||||
* [JSON in files](#json-in-files)
|
||||
* [Prefixing all keys](#prefixing-all-keys)
|
||||
* [Kata `shimv2`](#kata-shimv2)
|
||||
* [Caveats](#caveats)
|
||||
* [Summary](#summary)
|
||||
|
||||
# Introduction
|
||||
|
||||
This document describes how to import Kata Containers logs into [Fluentd](https://www.fluentd.org/),
|
||||
@@ -143,7 +128,7 @@ YAML can be found
|
||||
tag kata-containers
|
||||
path /run/log/journal
|
||||
pos_file /run/log/journal/kata-journald.pos
|
||||
filters [{"SYSLOG_IDENTIFIER": "kata-runtime"}, {"SYSLOG_IDENTIFIER": "kata-proxy"}, {"SYSLOG_IDENTIFIER": "kata-shim"}]
|
||||
filters [{"SYSLOG_IDENTIFIER": "kata-runtime"}, {"SYSLOG_IDENTIFIER": "kata-shim"}]
|
||||
read_from_head true
|
||||
</source>
|
||||
```
|
||||
@@ -161,7 +146,7 @@ generate some Kata specific log entries:
|
||||
|
||||
```bash
|
||||
$ minikube addons open efk
|
||||
$ cd $GOPATH/src/github.com/kata-containers/packaging/kata-deploy
|
||||
$ cd $GOPATH/src/github.com/kata-containers/kata-containers/tools/packaging/kata-deploy
|
||||
$ kubectl apply -f examples/nginx-deployment-qemu.yaml
|
||||
```
|
||||
|
||||
@@ -178,7 +163,7 @@ sub-filter on, for instance, the `SYSLOG_IDENTIFIER` to differentiate the Kata c
|
||||
on the `PRIORITY` to filter out critical issues etc.
|
||||
|
||||
Kata generates a significant amount of Kata specific information, which can be seen as
|
||||
[`logfmt`](https://github.com/kata-containers/tests/tree/master/cmd/log-parser#logfile-requirements).
|
||||
[`logfmt`](https://github.com/kata-containers/tests/tree/main/cmd/log-parser#logfile-requirements).
|
||||
data contained in the `MESSAGE` field. Imported as-is, there is no easy way to filter on that data
|
||||
in Kibana:
|
||||
|
||||
@@ -272,9 +257,8 @@ go directly to a full Kata specific JSON format logfile test.
|
||||
|
||||
Kata runtime has the ability to generate JSON logs directly, rather than its default `logfmt` format. Passing
|
||||
the `--log-format=json` argument to the Kata runtime enables this. The easiest way to pass in this extra
|
||||
parameter from a [Kata deploy](https://github.com/kata-containers/packaging/tree/master/kata-deploy) installation
|
||||
is to edit the `/opt/kata/bin/kata-qemu` shell script (generated by the
|
||||
[Kata packaging release scripts](https://github.com/kata-containers/packaging/blob/master/release/kata-deploy-binaries.sh)).
|
||||
parameter from a [Kata deploy](https://github.com/kata-containers/kata-containers/tree/main/tools/packaging/kata-deploy) installation
|
||||
is to edit the `/opt/kata/bin/kata-qemu` shell script.
|
||||
|
||||
At the same time, we will add the `--log=/var/log/kata-runtime.log` argument to store the Kata logs in their
|
||||
own file (rather than into the system journal).
|
||||
|
||||
@@ -2,14 +2,6 @@
|
||||
|
||||
This document describes how to run `kata-monitor` in a Kubernetes cluster using Prometheus's service discovery to scrape metrics from `kata-agent`.
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Pre-requisites](#pre-requisites)
|
||||
- [Configure Prometheus](#configure-prometheus)
|
||||
- [Configure `kata-monitor`](#configure-kata-monitor)
|
||||
- [Setup Grafana](#setup-grafana)
|
||||
* [Create `datasource`](#create-datasource)
|
||||
* [Import dashboard](#import-dashboard)
|
||||
|
||||
> **Warning**: This how-to is only for evaluation purpose, you **SHOULD NOT** running it in production using this configurations.
|
||||
|
||||
## Introduction
|
||||
|
||||
@@ -79,7 +79,7 @@ There are several kinds of Kata configurations and they are listed below.
|
||||
| `io.katacontainers.config.hypervisor.kernel` | string | the kernel used to boot the container VM |
|
||||
| `io.katacontainers.config.hypervisor.machine_accelerators` | string | machine specific accelerators for the hypervisor |
|
||||
| `io.katacontainers.config.hypervisor.machine_type` | string | the type of machine being emulated by the hypervisor |
|
||||
| `io.katacontainers.config.hypervisor.memory_offset` | uint32| the memory space used for `nvdimm` device by the hypervisor |
|
||||
| `io.katacontainers.config.hypervisor.memory_offset` | uint64| the memory space used for `nvdimm` device by the hypervisor |
|
||||
| `io.katacontainers.config.hypervisor.memory_slots` | uint32| the memory slots assigned to the VM by the hypervisor |
|
||||
| `io.katacontainers.config.hypervisor.msize_9p` | uint32 | the `msize` for 9p shares |
|
||||
| `io.katacontainers.config.hypervisor.path` | string | the hypervisor that will run the container VM |
|
||||
|
||||
@@ -1,22 +1,9 @@
|
||||
# How to use Kata Containers and CRI (containerd plugin) with Kubernetes
|
||||
|
||||
* [Requirements](#requirements)
|
||||
* [Install and configure containerd](#install-and-configure-containerd)
|
||||
* [Install and configure Kubernetes](#install-and-configure-kubernetes)
|
||||
* [Install Kubernetes](#install-kubernetes)
|
||||
* [Configure Kubelet to use containerd](#configure-kubelet-to-use-containerd)
|
||||
* [Configure HTTP proxy - OPTIONAL](#configure-http-proxy---optional)
|
||||
* [Start Kubernetes](#start-kubernetes)
|
||||
* [Configure Pod Network](#configure-pod-network)
|
||||
* [Allow pods to run in the master node](#allow-pods-to-run-in-the-master-node)
|
||||
* [Create runtime class for Kata Containers](#create-runtime-class-for-kata-containers)
|
||||
* [Run pod in Kata Containers](#run-pod-in-kata-containers)
|
||||
* [Delete created pod](#delete-created-pod)
|
||||
|
||||
This document describes how to set up a single-machine Kubernetes (k8s) cluster.
|
||||
|
||||
The Kubernetes cluster will use the
|
||||
[CRI containerd plugin](https://github.com/containerd/cri) and
|
||||
[CRI containerd plugin](https://github.com/containerd/containerd/tree/main/pkg/cri) and
|
||||
[Kata Containers](https://katacontainers.io) to launch untrusted workloads.
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
|
||||
This document provides an overview on how to run Kata containers with ACRN hypervisor and device model.
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Pre-requisites](#pre-requisites)
|
||||
- [Configure Docker](#configure-docker)
|
||||
- [Configure Kata Containers with ACRN](#configure-kata-containers-with-acrn)
|
||||
|
||||
## Introduction
|
||||
|
||||
ACRN is a flexible, lightweight Type-1 reference hypervisor built with real-time and safety-criticality in mind. ACRN uses an open source platform making it optimized to streamline embedded development.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Setting Sysctls with Kata
|
||||
|
||||
## Sysctls
|
||||
|
||||
In Linux, the sysctl interface allows an administrator to modify kernel
|
||||
parameters at runtime. Parameters are available via the `/proc/sys/` virtual
|
||||
process file system.
|
||||
@@ -16,11 +17,10 @@ To get a complete list of kernel parameters, run:
|
||||
$ sudo sysctl -a
|
||||
```
|
||||
|
||||
Both Docker and Kubernetes provide mechanisms for setting namespaced sysctls.
|
||||
Namespaced sysctls can be set per pod in the case of Kubernetes or per container
|
||||
in case of Docker.
|
||||
Kubernetes provide mechanisms for setting namespaced sysctls.
|
||||
Namespaced sysctls can be set per pod in the case of Kubernetes.
|
||||
The following sysctls are known to be namespaced and can be set with
|
||||
Docker and Kubernetes:
|
||||
Kubernetes:
|
||||
|
||||
- `kernel.shm*`
|
||||
- `kernel.msg*`
|
||||
@@ -30,31 +30,10 @@ Docker and Kubernetes:
|
||||
|
||||
### Namespaced Sysctls:
|
||||
|
||||
Kata Containers supports setting namespaced sysctls with Docker and Kubernetes.
|
||||
Kata Containers supports setting namespaced sysctls with Kubernetes.
|
||||
All namespaced sysctls can be set in the same way as regular Linux based
|
||||
containers, the difference being, in the case of Kata they are set inside the guest.
|
||||
|
||||
#### Setting Namespaced Sysctls with Docker:
|
||||
|
||||
```
|
||||
$ sudo docker run --runtime=kata-runtime -it alpine cat /proc/sys/fs/mqueue/queues_max
|
||||
256
|
||||
$ sudo docker run --runtime=kata-runtime --sysctl fs.mqueue.queues_max=512 -it alpine cat /proc/sys/fs/mqueue/queues_max
|
||||
512
|
||||
```
|
||||
|
||||
... and:
|
||||
|
||||
```
|
||||
$ sudo docker run --runtime=kata-runtime -it alpine cat /proc/sys/kernel/shmmax
|
||||
18446744073692774399
|
||||
$ sudo docker run --runtime=kata-runtime --sysctl kernel.shmmax=1024 -it alpine cat /proc/sys/kernel/shmmax
|
||||
1024
|
||||
```
|
||||
|
||||
For additional documentation on setting sysctls with Docker please refer to [Docker-sysctl-doc](https://docs.docker.com/engine/reference/commandline/run/#configure-namespaced-kernel-parameters-sysctls-at-runtime).
|
||||
|
||||
|
||||
#### Setting Namespaced Sysctls with Kubernetes:
|
||||
|
||||
Kubernetes considers certain sysctls as safe and others as unsafe. For detailed
|
||||
@@ -100,7 +79,7 @@ spec:
|
||||
|
||||
### Non-Namespaced Sysctls:
|
||||
|
||||
Docker and Kubernetes disallow sysctls without a namespace.
|
||||
Kubernetes disallow sysctls without a namespace.
|
||||
The recommendation is to set them directly on the host or use a privileged
|
||||
container in the case of Kubernetes.
|
||||
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
# Kata Containers with virtio-fs
|
||||
|
||||
- [Kata Containers with virtio-fs](#kata-containers-with-virtio-fs)
|
||||
- [Introduction](#introduction)
|
||||
|
||||
## Introduction
|
||||
|
||||
Container deployments utilize explicit or implicit file sharing between host filesystem and containers. From a trust perspective, avoiding a shared file-system between the trusted host and untrusted container is recommended. This is not always feasible. In Kata Containers, block-based volumes are preferred as they allow usage of either device pass through or `virtio-blk` for access within the virtual machine.
|
||||
|
||||
As of the 2.0 release of Kata Containers, [virtio-fs](https://virtio-fs.gitlab.io/) is the default filesystem sharing mechanism.
|
||||
|
||||
virtio-fs support works out of the box for `cloud-hypervisor` and `qemu`, when Kata Containers is deployed using `kata-deploy`. Learn more about `kata-deploy` and how to use `kata-deploy` in Kubernetes [here](https://github.com/kata-containers/packaging/tree/master/kata-deploy#kubernetes-quick-start).
|
||||
virtio-fs support works out of the box for `cloud-hypervisor` and `qemu`, when Kata Containers is deployed using `kata-deploy`. Learn more about `kata-deploy` and how to use `kata-deploy` in Kubernetes [here](https://github.com/kata-containers/kata-containers/tree/main/tools/packaging/kata-deploy#kubernetes-quick-start).
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
# Kata Containers with `virtio-mem`
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Requisites](#requisites)
|
||||
- [Run a Kata Container utilizing `virtio-mem`](#run-a-kata-container-utilizing-virtio-mem)
|
||||
|
||||
## Introduction
|
||||
|
||||
The basic idea of `virtio-mem` is to provide a flexible, cross-architecture memory hot plug and hot unplug solution that avoids many limitations imposed by existing technologies, architectures, and interfaces.
|
||||
@@ -41,7 +37,7 @@ $ echo 1 | sudo tee /proc/sys/vm/overcommit_memory
|
||||
Use following command to start a Kata Container.
|
||||
```
|
||||
$ pod_yaml=pod.yaml
|
||||
$ container_yaml=${REPORT_DIR}/container.yaml
|
||||
$ container_yaml=container.yaml
|
||||
$ image="quay.io/prometheus/busybox:latest"
|
||||
$ cat << EOF > "${pod_yaml}"
|
||||
metadata:
|
||||
|
||||
@@ -3,11 +3,6 @@
|
||||
Kata Containers supports creation of containers that are "privileged" (i.e. have additional capabilities and access
|
||||
that is not normally granted).
|
||||
|
||||
* [Warnings](#warnings)
|
||||
* [Host Devices](#host-devices)
|
||||
* [Containerd and CRI](#containerd-and-cri)
|
||||
* [CRI-O](#cri-o)
|
||||
|
||||
## Warnings
|
||||
|
||||
**Warning:** Whilst this functionality is supported, it can decrease the security of Kata Containers if not configured
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
# Working with `crictl`
|
||||
|
||||
* [What's `cri-tools`](#whats-cri-tools)
|
||||
* [Use `crictl` run Pods in Kata containers](#use-crictl-run-pods-in-kata-containers)
|
||||
* [Run `busybox` Pod](#run-busybox-pod)
|
||||
* [Run pod sandbox with config file](#run-pod-sandbox-with-config-file)
|
||||
* [Create container in the pod sandbox with config file](#create-container-in-the-pod-sandbox-with-config-file)
|
||||
* [Start container](#start-container)
|
||||
* [Run `redis` Pod](#run-redis-pod)
|
||||
* [Create `redis-server` Pod](#create-redis-server-pod)
|
||||
* [Create `redis-client` Pod](#create-redis-client-pod)
|
||||
* [Check `redis` server is working](#check-redis-server-is-working)
|
||||
|
||||
## What's `cri-tools`
|
||||
|
||||
[`cri-tools`](https://github.com/kubernetes-sigs/cri-tools) provides debugging and validation tools for Kubelet Container Runtime Interface (CRI).
|
||||
|
||||
@@ -1,18 +1,5 @@
|
||||
# Run Kata Containers with Kubernetes
|
||||
|
||||
* [Run Kata Containers with Kubernetes](#run-kata-containers-with-kubernetes)
|
||||
* [Prerequisites](#prerequisites)
|
||||
* [Install a CRI implementation](#install-a-cri-implementation)
|
||||
* [CRI-O](#cri-o)
|
||||
* [Kubernetes Runtime Class (CRI-O v1.12 )](#kubernetes-runtime-class-cri-o-v112)
|
||||
* [Untrusted annotation (until CRI-O v1.12)](#untrusted-annotation-until-cri-o-v112)
|
||||
* [Network namespace management](#network-namespace-management)
|
||||
* [containerd with CRI plugin](#containerd-with-cri-plugin)
|
||||
* [Install Kubernetes](#install-kubernetes)
|
||||
* [Configure for CRI-O](#configure-for-cri-o)
|
||||
* [Configure for containerd](#configure-for-containerd)
|
||||
* [Run a Kubernetes pod with Kata Containers](#run-a-kubernetes-pod-with-kata-containers)
|
||||
|
||||
## Prerequisites
|
||||
This guide requires Kata Containers available on your system, install-able by following [this guide](../install/README.md).
|
||||
|
||||
|
||||
@@ -1,21 +1,5 @@
|
||||
# Kata Containers and service mesh for Kubernetes
|
||||
|
||||
* [Assumptions](#assumptions)
|
||||
* [How they work](#how-they-work)
|
||||
* [Prerequisites](#prerequisites)
|
||||
* [Kata and Kubernetes](#kata-and-kubernetes)
|
||||
* [Restrictions](#restrictions)
|
||||
* [Install and deploy your service mesh](#install-and-deploy-your-service-mesh)
|
||||
* [Service Mesh Istio](#service-mesh-istio)
|
||||
* [Service Mesh Linkerd](#service-mesh-linkerd)
|
||||
* [Inject your services with sidecars](#inject-your-services-with-sidecars)
|
||||
* [Sidecar Istio](#sidecar-istio)
|
||||
* [Sidecar Linkerd](#sidecar-linkerd)
|
||||
* [Run your services with Kata](#run-your-services-with-kata)
|
||||
* [Lower privileges](#lower-privileges)
|
||||
* [Add annotations](#add-annotations)
|
||||
* [Deploy](#deploy)
|
||||
|
||||
A service mesh is a way to monitor and control the traffic between
|
||||
micro-services running in your Kubernetes cluster. It is a powerful
|
||||
tool that you might want to use in combination with the security
|
||||
@@ -76,15 +60,16 @@ is not able to perform a proper setup of the rules.
|
||||
|
||||
### Service Mesh Istio
|
||||
|
||||
As a reference, you can follow Istio [instructions](https://istio.io/docs/setup/kubernetes/quick-start/#download-and-prepare-for-the-installation).
|
||||
|
||||
The following is a summary of what you need to install Istio on your system:
|
||||
|
||||
```
|
||||
$ curl -L https://git.io/getLatestIstio | sh -
|
||||
$ cd istio-*
|
||||
$ export PATH=$PWD/bin:$PATH
|
||||
```
|
||||
|
||||
See the [Istio documentation](https://istio.io/docs) for further details.
|
||||
|
||||
Now deploy Istio in the control plane of your cluster with the following:
|
||||
```
|
||||
$ kubectl apply -f install/kubernetes/istio-demo.yaml
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
# What Is VMCache and How To Enable It
|
||||
|
||||
* [What is VMCache](#what-is-vmcache)
|
||||
* [How is this different to VM templating](#how-is-this-different-to-vm-templating)
|
||||
* [How to enable VMCache](#how-to-enable-vmcache)
|
||||
* [Limitations](#limitations)
|
||||
|
||||
### What is VMCache
|
||||
|
||||
VMCache is a new function that creates VMs as caches before using it.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# What Is VM Templating and How To Enable It
|
||||
|
||||
### What is VM templating
|
||||
|
||||
VM templating is a Kata Containers feature that enables new VM
|
||||
creation using a cloning technique. When enabled, new VMs are created
|
||||
by cloning from a pre-created template VM, and they will share the
|
||||
@@ -8,11 +9,13 @@ same initramfs, kernel and agent memory in readonly mode. It is very
|
||||
much like a process fork done by the kernel but here we *fork* VMs.
|
||||
|
||||
### How is this different from VMCache
|
||||
|
||||
Both [VMCache](../how-to/what-is-vm-cache-and-how-do-I-use-it.md) and VM templating help speed up new container creation.
|
||||
When VMCache enabled, new VMs are created by the VMCache server. So it is not vulnerable to share memory CVE because each VM doesn't share the memory.
|
||||
VM templating saves a lot of memory if there are many Kata Containers running on the same host.
|
||||
|
||||
### What are the Pros
|
||||
|
||||
VM templating helps speed up new container creation and saves a lot
|
||||
of memory if there are many Kata Containers running on the same host.
|
||||
If you are running a density workload, or care a lot about container
|
||||
@@ -29,6 +32,7 @@ showed that VM templating speeds up Kata Containers creation by as much as
|
||||
38.68%. See [full results here](https://gist.github.com/bergwolf/06974a3c5981494a40e2c408681c085d).
|
||||
|
||||
### What are the Cons
|
||||
|
||||
One drawback of VM templating is that it cannot avoid cross-VM side-channel
|
||||
attack such as [CVE-2015-2877](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-2877)
|
||||
that originally targeted at the Linux KSM feature.
|
||||
@@ -39,10 +43,11 @@ and can be classified as potentially misunderstood behaviors rather than vulnera
|
||||
**Warning**: If you care about such attack vector, do not use VM templating or KSM.
|
||||
|
||||
### How to enable VM templating
|
||||
|
||||
VM templating can be enabled by changing your Kata Containers config file (`/usr/share/defaults/kata-containers/configuration.toml`,
|
||||
overridden by `/etc/kata-containers/configuration.toml` if provided) such that:
|
||||
|
||||
- `qemu-lite` is specified in `hypervisor.qemu`->`path` section
|
||||
- `qemu` version `v4.1.0` or above is specified in `hypervisor.qemu`->`path` section
|
||||
- `enable_template = true`
|
||||
- `initrd =` is set
|
||||
- `image =` option is commented out or removed
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
# Hypervisors
|
||||
|
||||
* [Hypervisors](#hypervisors)
|
||||
* [Introduction](#introduction)
|
||||
* [Types](#types)
|
||||
* [Determine currently configured hypervisor](#determine-currently-configured-hypervisor)
|
||||
* [Choose a Hypervisor](#choose-a-hypervisor)
|
||||
|
||||
## Introduction
|
||||
|
||||
Kata Containers supports multiple hypervisors. This document provides a very
|
||||
|
||||
@@ -1,39 +1,19 @@
|
||||
# Kata Containers installation user guides
|
||||
# Kata Containers installation guides
|
||||
|
||||
* [Kata Containers installation user guides](#kata-containers-installation-user-guides)
|
||||
* [Prerequisites](#prerequisites)
|
||||
* [Legacy installation](#legacy-installation)
|
||||
* [Packaged installation methods](#packaged-installation-methods)
|
||||
* [Official packages](#official-packages)
|
||||
* [Snap Installation](#snap-installation)
|
||||
* [Automatic Installation](#automatic-installation)
|
||||
* [Manual Installation](#manual-installation)
|
||||
* [Build from source installation](#build-from-source-installation)
|
||||
* [Installing on a Cloud Service Platform](#installing-on-a-cloud-service-platform)
|
||||
* [Further information](#further-information)
|
||||
|
||||
The following is an overview of the different installation methods available. All of these methods equally result
|
||||
in a system configured to run Kata Containers.
|
||||
The following is an overview of the different installation methods available.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Kata Containers requires nested virtualization or bare metal.
|
||||
See the
|
||||
[hardware requirements](/src/runtime/README.md#hardware-requirements)
|
||||
to see if your system is capable of running Kata Containers.
|
||||
|
||||
## Legacy installation
|
||||
|
||||
If you wish to install a legacy 1.x version of Kata Containers, see
|
||||
[the Kata Containers 1.x installation documentation](https://github.com/kata-containers/documentation/tree/master/install/).
|
||||
Kata Containers requires nested virtualization or bare metal. Check
|
||||
[hardware requirements](/src/runtime/README.md#hardware-requirements) to see if your system is capable of running Kata
|
||||
Containers.
|
||||
|
||||
## Packaged installation methods
|
||||
|
||||
> **Notes:**
|
||||
>
|
||||
> - Packaged installation methods uses your distribution's native package format (such as RPM or DEB).
|
||||
> - You are strongly encouraged to choose an installation method that provides
|
||||
> automatic updates, to ensure you benefit from security updates and bug fixes.
|
||||
Packaged installation methods uses your distribution's native package format (such as RPM or DEB).
|
||||
|
||||
*Note:* We encourage installation methods that provides automatic updates, it ensures security updates and bug fixes are
|
||||
easily applied.
|
||||
|
||||
| Installation method | Description | Automatic updates | Use case |
|
||||
|------------------------------------------------------|---------------------------------------------------------------------|-------------------|----------------------------------------------------------|
|
||||
@@ -52,16 +32,9 @@ Kata packages are provided by official distribution repositories for:
|
||||
| [CentOS](centos-installation-guide.md) | 8 |
|
||||
| [Fedora](fedora-installation-guide.md) | 34 |
|
||||
|
||||
> **Note::**
|
||||
>
|
||||
> All users are encouraged to uses the official distribution versions of Kata
|
||||
> Containers unless they understand the implications of alternative methods.
|
||||
|
||||
### Snap Installation
|
||||
|
||||
> **Note:** The snap installation is available for all distributions which support `snapd`.
|
||||
|
||||
[](https://snapcraft.io/kata-containers)
|
||||
The snap installation is available for all distributions which support `snapd`.
|
||||
|
||||
[Use snap](snap-installation-guide.md) to install Kata Containers from https://snapcraft.io.
|
||||
|
||||
@@ -75,11 +48,9 @@ Follow the [containerd installation guide](container-manager/containerd/containe
|
||||
|
||||
## Build from source installation
|
||||
|
||||
> **Notes:**
|
||||
>
|
||||
> - Power users who decide to build from sources should be aware of the
|
||||
> implications of using an unpackaged system which will not be automatically
|
||||
> updated as new [releases](../Stable-Branch-Strategy.md) are made available.
|
||||
*Note:* Power users who decide to build from sources should be aware of the
|
||||
implications of using an unpackaged system which will not be automatically
|
||||
updated as new [releases](../Stable-Branch-Strategy.md) are made available.
|
||||
|
||||
[Building from sources](../Developer-Guide.md#initial-setup) allows power users
|
||||
who are comfortable building software from source to use the latest component
|
||||
@@ -95,6 +66,6 @@ versions. This is not recommended for normal users.
|
||||
|
||||
## Further information
|
||||
|
||||
* The [upgrading document](../Upgrading.md).
|
||||
* The [developer guide](../Developer-Guide.md).
|
||||
* The [runtime documentation](../../src/runtime/README.md).
|
||||
* [upgrading document](../Upgrading.md)
|
||||
* [developer guide](../Developer-Guide.md)
|
||||
* [runtime documentation](../../src/runtime/README.md)
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
# Install Kata Containers on Amazon Web Services
|
||||
|
||||
* [Install and Configure AWS CLI](#install-and-configure-aws-cli)
|
||||
* [Create or Import an EC2 SSH key pair](#create-or-import-an-ec2-ssh-key-pair)
|
||||
* [Launch i3.metal instance](#launch-i3metal-instance)
|
||||
* [Install Kata](#install-kata)
|
||||
|
||||
Kata Containers on Amazon Web Services (AWS) makes use of [i3.metal](https://aws.amazon.com/ec2/instance-types/i3/) instances. Most of the installation procedure is identical to that for Kata on your preferred distribution, except that you have to run it on bare metal instances since AWS doesn't support nested virtualization yet. This guide walks you through creating an i3.metal instance.
|
||||
|
||||
## Install and Configure AWS CLI
|
||||
|
||||
@@ -98,12 +98,12 @@
|
||||
|
||||
```toml
|
||||
[plugins]
|
||||
[plugins.cri]
|
||||
[plugins.cri.containerd]
|
||||
default_runtime_name = "kata"
|
||||
|
||||
[plugins.cri.containerd.runtimes.kata]
|
||||
runtime_type = "io.containerd.kata.v2"
|
||||
[plugins."io.containerd.grpc.v1.cri"]
|
||||
[plugins."io.containerd.grpc.v1.cri".containerd]
|
||||
default_runtime_name = "kata"
|
||||
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
|
||||
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata]
|
||||
runtime_type = "io.containerd.kata.v2"
|
||||
```
|
||||
|
||||
> **Note:**
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
# Install Kata Containers on Google Compute Engine
|
||||
|
||||
* [Create an Image with Nested Virtualization Enabled](#create-an-image-with-nested-virtualization-enabled)
|
||||
* [Create the Image](#create-the-image)
|
||||
* [Verify VMX is Available](#verify-vmx-is-available)
|
||||
* [Install Kata](#install-kata)
|
||||
* [Create a Kata-enabled Image](#create-a-kata-enabled-image)
|
||||
|
||||
Kata Containers on Google Compute Engine (GCE) makes use of [nested virtualization](https://cloud.google.com/compute/docs/instances/enable-nested-virtualization-vm-instances). Most of the installation procedure is identical to that for Kata on your preferred distribution, but enabling nested virtualization currently requires extra steps on GCE. This guide walks you through creating an image and instance with nested virtualization enabled. Note that `kata-runtime check` checks for nested virtualization, but does not fail if support is not found.
|
||||
|
||||
As a pre-requisite this guide assumes an installed and configured instance of the [Google Cloud SDK](https://cloud.google.com/sdk/downloads). For a zero-configuration option, all of the commands below were been tested under [Google Cloud Shell](https://cloud.google.com/shell/) (as of Jun 2018). Verify your `gcloud` installation and configuration:
|
||||
|
||||
@@ -1,24 +1,12 @@
|
||||
# Installing Kata Containers in Minikube
|
||||
|
||||
* [Installing Kata Containers in Minikube](#installing-kata-containers-in-minikube)
|
||||
* [Introduction](#introduction)
|
||||
* [Prerequisites](#prerequisites)
|
||||
* [Setting up Minikube](#setting-up-minikube)
|
||||
* [Checking for nested virtualization](#checking-for-nested-virtualization)
|
||||
* [Check Minikube is running](#check-minikube-is-running)
|
||||
* [Installing Kata Containers](#installing-kata-containers)
|
||||
* [Enabling Kata Containers](#enabling-kata-containers)
|
||||
* [Register the runtime](#register-the-runtime)
|
||||
* [Testing Kata Containers](#testing-kata-containers)
|
||||
* [Wrapping up](#wrapping-up)
|
||||
|
||||
## Introduction
|
||||
|
||||
[Minikube](https://kubernetes.io/docs/setup/minikube/) is an easy way to try out a Kubernetes (k8s)
|
||||
cluster locally. It creates a single node Kubernetes stack in a local VM.
|
||||
|
||||
[Kata Containers](https://github.com/kata-containers) can be installed into a Minikube cluster using
|
||||
[`kata-deploy`](https://github.com/kata-containers/packaging/tree/master/kata-deploy).
|
||||
[`kata-deploy`](https://github.com/kata-containers/kata-containers/tree/main/tools/packaging/kata-deploy).
|
||||
|
||||
This document details the pre-requisites, installation steps, and how to check
|
||||
the installation has been successful.
|
||||
@@ -135,7 +123,7 @@ $ kubectl apply -f kata-deploy/base/kata-deploy.yaml
|
||||
This installs the Kata Containers components into `/opt/kata` inside the Minikube node. It can take
|
||||
a few minutes for the operation to complete. You can check the installation has worked by checking
|
||||
the status of the `kata-deploy` pod, which will be executing
|
||||
[this script](https://github.com/kata-containers/packaging/blob/master/kata-deploy/scripts/kata-deploy.sh),
|
||||
[this script](https://github.com/kata-containers/kata-containers/tree/main/tools/packaging/kata-deploy/scripts/kata-deploy.sh),
|
||||
and will be executing a `sleep infinity` once it has successfully completed its work.
|
||||
You can accomplish this by running the following:
|
||||
|
||||
@@ -166,8 +154,8 @@ $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/node-api/master/
|
||||
Now register the `kata qemu` runtime with that class. This should result in no errors:
|
||||
|
||||
```sh
|
||||
$ cd kata-containers/tools/packaging/kata-deploy/k8s-1.14
|
||||
$ kubectl apply -f kata-qemu-runtimeClass.yaml
|
||||
$ cd kata-containers/tools/packaging/kata-deploy/runtimeclasses
|
||||
$ kubectl apply -f kata-runtimeClasses.yaml
|
||||
```
|
||||
|
||||
The Kata Containers installation process should be complete and enabled in the Minikube cluster.
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
# Kata Containers snap package
|
||||
|
||||
* [Install Kata Containers](#install-kata-containers)
|
||||
* [Configure Kata Containers](#configure-kata-containers)
|
||||
* [Integration with shim v2 Container Engines](#integration-with-shim-v2-container-engines)
|
||||
* [Remove Kata Containers snap package](#remove-kata-containers-snap-package)
|
||||
|
||||
|
||||
## Install Kata Containers
|
||||
|
||||
Kata Containers can be installed in any Linux distribution that supports
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
# Using Intel GPU device with Kata Containers
|
||||
|
||||
- [Using Intel GPU device with Kata Containers](#using-intel-gpu-device-with-kata-containers)
|
||||
- [Hardware Requirements](#hardware-requirements)
|
||||
- [Host Kernel Requirements](#host-kernel-requirements)
|
||||
- [Install and configure Kata Containers](#install-and-configure-kata-containers)
|
||||
- [Build Kata Containers kernel with GPU support](#build-kata-containers-kernel-with-gpu-support)
|
||||
- [GVT-d with Kata Containers](#gvt-d-with-kata-containers)
|
||||
- [GVT-g with Kata Containers](#gvt-g-with-kata-containers)
|
||||
|
||||
An Intel Graphics device can be passed to a Kata Containers container using GPU
|
||||
passthrough (Intel GVT-d) as well as GPU mediated passthrough (Intel GVT-g).
|
||||
|
||||
@@ -65,8 +57,8 @@ configuration in the Kata `configuration.toml` file as shown below.
|
||||
$ sudo sed -i -e 's/^# *\(hotplug_vfio_on_root_bus\).*=.*$/\1 = true/g' /usr/share/defaults/kata-containers/configuration.toml
|
||||
```
|
||||
|
||||
Make sure you are using the `pc` machine type by verifying `machine_type = "pc"` is
|
||||
set in the `configuration.toml`.
|
||||
Make sure you are using the `q35` machine type by verifying `machine_type = "q35"` is
|
||||
set in the `configuration.toml`. Make sure `pcie_root_port` is set to a positive value.
|
||||
|
||||
## Build Kata Containers kernel with GPU support
|
||||
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
# Using Nvidia GPU device with Kata Containers
|
||||
|
||||
- [Using Nvidia GPU device with Kata Containers](#using-nvidia-gpu-device-with-kata-containers)
|
||||
- [Hardware Requirements](#hardware-requirements)
|
||||
- [Host BIOS Requirements](#host-bios-requirements)
|
||||
- [Host Kernel Requirements](#host-kernel-requirements)
|
||||
- [Install and configure Kata Containers](#install-and-configure-kata-containers)
|
||||
- [Build Kata Containers kernel with GPU support](#build-kata-containers-kernel-with-gpu-support)
|
||||
- [Nvidia GPU pass-through mode with Kata Containers](#nvidia-gpu-pass-through-mode-with-kata-containers)
|
||||
- [Nvidia vGPU mode with Kata Containers](#nvidia-vgpu-mode-with-kata-containers)
|
||||
- [Install Nvidia Driver in Kata Containers](#install-nvidia-driver-in-kata-containers)
|
||||
- [References](#references)
|
||||
|
||||
|
||||
An Nvidia GPU device can be passed to a Kata Containers container using GPU passthrough
|
||||
(Nvidia GPU pass-through mode) as well as GPU mediated passthrough (Nvidia vGPU mode).
|
||||
|
||||
@@ -75,13 +63,6 @@ To use non-large BARs devices (for example, Nvidia Tesla T4), you need Kata vers
|
||||
Follow the [Kata Containers setup instructions](../install/README.md)
|
||||
to install the latest version of Kata.
|
||||
|
||||
The following configuration in the Kata `configuration.toml` file as shown below can work:
|
||||
```
|
||||
machine_type = "pc"
|
||||
|
||||
hotplug_vfio_on_root_bus = true
|
||||
```
|
||||
|
||||
To use large BARs devices (for example, Nvidia Tesla P100), you need Kata version 1.11.0 or above.
|
||||
|
||||
The following configuration in the Kata `configuration.toml` file as shown below can work:
|
||||
@@ -310,4 +291,4 @@ Tue Mar 3 00:03:49 2020
|
||||
|
||||
- [Configuring a VM for GPU Pass-Through by Using the QEMU Command Line](https://docs.nvidia.com/grid/latest/grid-vgpu-user-guide/index.html#using-gpu-pass-through-red-hat-el-qemu-cli)
|
||||
- https://gitlab.com/nvidia/container-images/driver/-/tree/master
|
||||
- https://github.com/NVIDIA/nvidia-docker/wiki/Driver-containers-(Beta)
|
||||
- https://github.com/NVIDIA/nvidia-docker/wiki/Driver-containers
|
||||
|
||||
@@ -1,33 +1,5 @@
|
||||
# Table of Contents
|
||||
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [Introduction](#introduction)
|
||||
- [Helpful Links before starting](#helpful-links-before-starting)
|
||||
- [Steps to enable Intel® QAT in Kata Containers](#steps-to-enable-intel-qat-in-kata-containers)
|
||||
- [Script variables](#script-variables)
|
||||
- [Set environment variables (Every Reboot)](#set-environment-variables-every-reboot)
|
||||
- [Prepare the Ubuntu Host](#prepare-the-ubuntu-host)
|
||||
- [Identify which PCI Bus the Intel® QAT card is on](#identify-which-pci-bus-the-intel-qat-card-is-on)
|
||||
- [Install necessary packages for Ubuntu](#install-necessary-packages-for-ubuntu)
|
||||
- [Download Intel® QAT drivers](#download-intel-qat-drivers)
|
||||
- [Copy Intel® QAT configuration files and enable virtual functions](#copy-intel-qat-configuration-files-and-enable-virtual-functions)
|
||||
- [Expose and Bind Intel® QAT virtual functions to VFIO-PCI (Every reboot)](#expose-and-bind-intel-qat-virtual-functions-to-vfio-pci-every-reboot)
|
||||
- [Check Intel® QAT virtual functions are enabled](#check-intel-qat-virtual-functions-are-enabled)
|
||||
- [Prepare Kata Containers](#prepare-kata-containers)
|
||||
- [Download Kata kernel Source](#download-kata-kernel-source)
|
||||
- [Build Kata kernel](#build-kata-kernel)
|
||||
- [Copy Kata kernel](#copy-kata-kernel)
|
||||
- [Prepare Kata root filesystem](#prepare-kata-root-filesystem)
|
||||
- [Compile Intel® QAT drivers for Kata Containers kernel and add to Kata Containers rootfs](#compile-intel-qat-drivers-for-kata-containers-kernel-and-add-to-kata-containers-rootfs)
|
||||
- [Copy Kata rootfs](#copy-kata-rootfs)
|
||||
- [Verify Intel® QAT works in a container](#verify-intel-qat-works-in-a-container)
|
||||
- [Build OpenSSL Intel® QAT engine container](#build-openssl-intel-qat-engine-container)
|
||||
- [Test Intel® QAT with the ctr tool](#test-intel-qat-with-the-ctr-tool)
|
||||
- [Test Intel® QAT in Kubernetes](#test-intel-qat-in-kubernetes)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [Optional Scripts](#optional-scripts)
|
||||
- [Verify Intel® QAT card counters are incremented](#verify-intel-qat-card-counters-are-incremented)
|
||||
|
||||
# Introduction
|
||||
|
||||
Intel® QuickAssist Technology (QAT) provides hardware acceleration
|
||||
@@ -74,7 +46,7 @@ Make sure to check [`01.org`](https://01.org/intel-quickassist-technology) for
|
||||
the latest driver.
|
||||
|
||||
```bash
|
||||
$ export QAT_DRIVER_VER=qat1.7.l.4.12.0-00011.tar.gz
|
||||
$ export QAT_DRIVER_VER=qat1.7.l.4.14.0-00031.tar.gz
|
||||
$ export QAT_DRIVER_URL=https://downloadmirror.intel.com/30178/eng/${QAT_DRIVER_VER}
|
||||
$ export QAT_CONF_LOCATION=~/QAT_conf
|
||||
$ export QAT_DOCKERFILE=https://raw.githubusercontent.com/intel/intel-device-plugins-for-kubernetes/master/demo/openssl-qat-engine/Dockerfile
|
||||
@@ -402,7 +374,7 @@ different hypervisor, different install method for Kata, or a different
|
||||
Intel® QAT chipset then the command will need to be modified.
|
||||
|
||||
> **Note: The following was tested with
|
||||
[containerd v1.3.9](https://github.com/containerd/containerd/releases/tag/v1.3.9).**
|
||||
[containerd v1.4.6](https://github.com/containerd/containerd/releases/tag/v1.4.6).**
|
||||
|
||||
```bash
|
||||
$ config_file="/opt/kata/share/defaults/kata-containers/configuration-qemu.toml"
|
||||
@@ -604,4 +576,4 @@ $ for i in 0434 0435 37c8 1f18 1f19; do lspci -d 8086:$i; done
|
||||
$ sudo watch cat /sys/kernel/debug/qat_c6xx_0000\:b1\:00.0/fw_counters
|
||||
$ sudo watch cat /sys/kernel/debug/qat_c6xx_0000\:b3\:00.0/fw_counters
|
||||
$ sudo watch cat /sys/kernel/debug/qat_c6xx_0000\:b5\:00.0/fw_counters
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
# Kata Containers with SGX
|
||||
|
||||
- [Check if SGX is enabled](#check-if-sgx-is-enabled)
|
||||
- [Install Host kernel with SGX support](#install-host-kernel-with-sgx-support)
|
||||
- [Install Guest kernel with SGX support](#install-guest-kernel-with-sgx-support)
|
||||
- [Run Kata Containers with SGX enabled](#run-kata-containers-with-sgx-enabled)
|
||||
|
||||
Intel® Software Guard Extensions (SGX) is a set of instructions that increases the security
|
||||
of applications code and data, giving them more protections from disclosure or modification.
|
||||
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
# Setup to run SPDK vhost-user devices with Kata Containers and Docker*
|
||||
|
||||
- [SPDK vhost-user target overview](#spdk-vhost-user-target-overview)
|
||||
- [Install and setup SPDK vhost-user target](#install-and-setup-spdk-vhost-user-target)
|
||||
- [Get source code and build SPDK](#get-source-code-and-build-spdk)
|
||||
- [Run SPDK vhost-user target](#run-spdk-vhost-user-target)
|
||||
- [Host setup for vhost-user devices](#host-setup-for-vhost-user-devices)
|
||||
- [Launch a Kata container with SPDK vhost-user block device](#launch-a-kata-container-with-spdk-vhost-user-block-device)
|
||||
|
||||
> **NOTE:** This guide only applies to QEMU, since the vhost-user storage
|
||||
> **Note:** This guide only applies to QEMU, since the vhost-user storage
|
||||
> device is only available for QEMU now. The enablement work on other
|
||||
> hypervisors is still ongoing.
|
||||
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
# Setup to use SR-IOV with Kata Containers and Docker*
|
||||
|
||||
- [Install the SR-IOV Docker\* plugin](#install-the-sr-iov-docker-plugin)
|
||||
- [Host setup for SR-IOV](#host-setup-for-sr-iov)
|
||||
- [Checking your NIC for SR-IOV](#checking-your-nic-for-sr-iov)
|
||||
- [IOMMU Groups and PCIe Access Control Services](#iommu-groups-and-pcie-access-control-services)
|
||||
- [Update the host kernel](#update-the-host-kernel)
|
||||
- [Set up the SR-IOV Device](#set-up-the-sr-iov-device)
|
||||
- [Example: Launch a Kata Containers container using SR-IOV](#example-launch-a-kata-containers-container-using-sr-iov)
|
||||
|
||||
Single Root I/O Virtualization (SR-IOV) enables splitting a physical device into
|
||||
virtual functions (VFs). Virtual functions enable direct passthrough to virtual
|
||||
machines or containers. For Kata Containers, we enabled a Container Network
|
||||
|
||||
@@ -12,7 +12,7 @@ For more information about VPP visit their [wiki](https://wiki.fd.io/view/VPP).
|
||||
|
||||
## Install and configure Kata Containers
|
||||
|
||||
Follow the [Kata Containers setup instructions](https://github.com/kata-containers/documentation/wiki/Developer-Guide).
|
||||
Follow the [Kata Containers setup instructions](../Developer-Guide.md).
|
||||
|
||||
In order to make use of VHOST-USER based interfaces, the container needs to be backed
|
||||
by huge pages. `HugePages` support is required for the large memory pool allocation used for
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# OpenStack Zun DevStack working with Kata Containers
|
||||
|
||||
## Introduction
|
||||
|
||||
This guide describes how to get Kata Containers to work with OpenStack Zun
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
# Kata Containers snap image
|
||||
|
||||
* [Initial setup](#initial-setup)
|
||||
* [Install snap](#install-snap)
|
||||
* [Build and install snap image](#build-and-install-snap-image)
|
||||
* [Configure Kata Containers](#configure-kata-containers)
|
||||
* [Integration with docker and Kubernetes](#integration-with-docker-and-kubernetes)
|
||||
* [Remove snap](#remove-snap)
|
||||
* [Limitations](#limitations)
|
||||
|
||||
This directory contains the resources needed to build the Kata Containers
|
||||
[snap][1] image.
|
||||
|
||||
|
||||
@@ -80,6 +80,8 @@ parts:
|
||||
- uidmap
|
||||
- gnupg2
|
||||
override-build: |
|
||||
[ "$(uname -m)" = "ppc64le" ] || [ "$(uname -m)" = "s390x" ] && sudo apt-get --no-install-recommends install -y protobuf-compiler
|
||||
|
||||
yq=${SNAPCRAFT_STAGE}/yq
|
||||
|
||||
# set GOPATH
|
||||
@@ -88,6 +90,7 @@ parts:
|
||||
|
||||
export GOROOT=${SNAPCRAFT_STAGE}
|
||||
export PATH="${GOROOT}/bin:${PATH}"
|
||||
export GO111MODULE="auto"
|
||||
|
||||
http_proxy=${http_proxy:-""}
|
||||
https_proxy=${https_proxy:-""}
|
||||
@@ -112,14 +115,17 @@ parts:
|
||||
cd ${kata_dir}/tools/osbuilder
|
||||
|
||||
# build image
|
||||
export AGENT_VERSION=$(cat ${kata_dir}/VERSION)
|
||||
export AGENT_INIT=yes
|
||||
export USE_DOCKER=1
|
||||
export DEBUG=1
|
||||
case "$(uname -m)" in
|
||||
aarch64|ppc64le|s390x)
|
||||
aarch64)
|
||||
sudo -E PATH=$PATH make initrd DISTRO=alpine
|
||||
;;
|
||||
ppc64le|s390x)
|
||||
# Cannot use alpine on ppc64le/s390x because it would require a musl agent
|
||||
sudo -E PATH=$PATH make initrd DISTRO=ubuntu
|
||||
;;
|
||||
x86_64)
|
||||
# In some build systems it's impossible to build a rootfs image, try with the initrd image
|
||||
sudo -E PATH=$PATH make image DISTRO=clearlinux || sudo -E PATH=$PATH make initrd DISTRO=alpine
|
||||
@@ -141,6 +147,7 @@ parts:
|
||||
export GOPATH=${SNAPCRAFT_STAGE}/gopath
|
||||
export GOROOT=${SNAPCRAFT_STAGE}
|
||||
export PATH="${GOROOT}/bin:${PATH}"
|
||||
export GO111MODULE="auto"
|
||||
kata_dir=${GOPATH}/src/github.com/${SNAPCRAFT_PROJECT_NAME}/${SNAPCRAFT_PROJECT_NAME}
|
||||
|
||||
cd ${kata_dir}/src/runtime
|
||||
@@ -162,12 +169,9 @@ parts:
|
||||
SKIP_GO_VERSION_CHECK=1 \
|
||||
QEMUCMD=qemu-system-$arch
|
||||
|
||||
if [ -e ${SNAPCRAFT_PART_INSTALL}/../../image/install/usr/share/kata-containers/kata-containers.img ]; then
|
||||
# Use rootfs image by default
|
||||
sed -i -e '/^initrd =/d' ${SNAPCRAFT_PART_INSTALL}/usr/share/defaults/${SNAPCRAFT_PROJECT_NAME}/configuration.toml
|
||||
else
|
||||
# Use initrd by default
|
||||
sed -i -e '/^image =/d' ${SNAPCRAFT_PART_INSTALL}/usr/share/defaults/${SNAPCRAFT_PROJECT_NAME}/configuration.toml
|
||||
if [ ! -f ${SNAPCRAFT_PART_INSTALL}/../../image/install/usr/share/kata-containers/kata-containers.img ]; then
|
||||
sed -i -e "s|^image =.*|initrd = \"/snap/${SNAPCRAFT_PROJECT_NAME}/current/usr/share/kata-containers/kata-containers-initrd.img\"|" \
|
||||
${SNAPCRAFT_PART_INSTALL}/usr/share/defaults/${SNAPCRAFT_PROJECT_NAME}/configuration.toml
|
||||
fi
|
||||
|
||||
kernel:
|
||||
@@ -180,19 +184,29 @@ parts:
|
||||
- bison
|
||||
- flex
|
||||
override-build: |
|
||||
yq=${SNAPCRAFT_STAGE}/yq
|
||||
export GOPATH=${SNAPCRAFT_STAGE}/gopath
|
||||
kata_dir=${GOPATH}/src/github.com/${SNAPCRAFT_PROJECT_NAME}/${SNAPCRAFT_PROJECT_NAME}
|
||||
versions_file="${kata_dir}/versions.yaml"
|
||||
kernel_version="$(${yq} r $versions_file assets.kernel.version)"
|
||||
#Remove extra 'v'
|
||||
kernel_version=${kernel_version#v}
|
||||
|
||||
[ "$(uname -m)" = "s390x" ] && sudo apt-get --no-install-recommends install -y libssl-dev
|
||||
|
||||
export GOPATH=${SNAPCRAFT_STAGE}/gopath
|
||||
export GO111MODULE="auto"
|
||||
kata_dir=${GOPATH}/src/github.com/${SNAPCRAFT_PROJECT_NAME}/${SNAPCRAFT_PROJECT_NAME}
|
||||
|
||||
cd ${kata_dir}/tools/packaging/kernel
|
||||
|
||||
# Setup and build kernel
|
||||
./build-kernel.sh -d setup
|
||||
./build-kernel.sh -v ${kernel_version} -d setup
|
||||
kernel_dir_prefix="kata-linux-"
|
||||
cd ${kernel_dir_prefix}*
|
||||
version=$(basename ${PWD} | sed 's|'"${kernel_dir_prefix}"'||' | cut -d- -f1)
|
||||
make -j $(($(nproc)-1)) EXTRAVERSION=".container"
|
||||
|
||||
kernel_suffix=${version}.container
|
||||
kernel_suffix=${kernel_version}.container
|
||||
kata_kernel_dir=${SNAPCRAFT_PART_INSTALL}/usr/share/kata-containers
|
||||
mkdir -p ${kata_kernel_dir}
|
||||
|
||||
@@ -202,8 +216,10 @@ parts:
|
||||
ln -sf ${vmlinuz_name} ${kata_kernel_dir}/vmlinuz.container
|
||||
|
||||
# Install raw kernel
|
||||
vmlinux_path=vmlinux
|
||||
[ "$(uname -m)" = "s390x" ] && vmlinux_path=arch/s390/boot/compressed/vmlinux
|
||||
vmlinux_name=vmlinux-${kernel_suffix}
|
||||
cp vmlinux ${kata_kernel_dir}/${vmlinux_name}
|
||||
cp ${vmlinux_path} ${kata_kernel_dir}/${vmlinux_name}
|
||||
ln -sf ${vmlinux_name} ${kata_kernel_dir}/vmlinux.container
|
||||
|
||||
qemu:
|
||||
@@ -227,21 +243,24 @@ parts:
|
||||
- libblkid-dev
|
||||
- libffi-dev
|
||||
- libmount-dev
|
||||
- libseccomp-dev
|
||||
- libselinux1-dev
|
||||
- ninja-build
|
||||
override-build: |
|
||||
yq=${SNAPCRAFT_STAGE}/yq
|
||||
export GOPATH=${SNAPCRAFT_STAGE}/gopath
|
||||
export GO111MODULE="auto"
|
||||
kata_dir=${GOPATH}/src/github.com/${SNAPCRAFT_PROJECT_NAME}/${SNAPCRAFT_PROJECT_NAME}
|
||||
|
||||
versions_file="${kata_dir}/versions.yaml"
|
||||
# arch-specific definition
|
||||
case "$(uname -m)" in
|
||||
"aarch64")
|
||||
branch="$(${yq} r ${versions_file} assets.hypervisor.qemu.architecture.aarch64.branch)"
|
||||
branch="$(${yq} r ${versions_file} assets.hypervisor.qemu.architecture.aarch64.version)"
|
||||
url="$(${yq} r ${versions_file} assets.hypervisor.qemu.url)"
|
||||
commit="$(${yq} r ${versions_file} assets.hypervisor.qemu.architecture.aarch64.commit)"
|
||||
patches_dir="${kata_dir}/tools/packaging/obs-packaging/qemu-aarch64/patches/"
|
||||
patches_dir="${kata_dir}/tools/packaging/qemu/patches/$(echo ${branch} | sed -e 's/.[[:digit:]]*$//' -e 's/^v//').x"
|
||||
patches_version_dir="${kata_dir}/tools/packaging/qemu/patches/tag_patches/${branch}"
|
||||
;;
|
||||
|
||||
*)
|
||||
@@ -255,6 +274,7 @@ parts:
|
||||
|
||||
# download source
|
||||
qemu_dir=${SNAPCRAFT_STAGE}/qemu
|
||||
rm -rf "${qemu_dir}"
|
||||
git clone --branch ${branch} --single-branch ${url} "${qemu_dir}"
|
||||
cd ${qemu_dir}
|
||||
[ -z "${commit}" ] || git checkout ${commit}
|
||||
@@ -263,11 +283,12 @@ parts:
|
||||
[ -n "$(ls -A capstone)" ] || git clone https://github.com/qemu/capstone capstone
|
||||
|
||||
# Apply branch patches
|
||||
[ -d "${patches_version_dir}" ] || mkdir "${patches_version_dir}"
|
||||
${kata_dir}/tools/packaging/scripts/apply_patches.sh "${patches_dir}"
|
||||
${kata_dir}/tools/packaging/scripts/apply_patches.sh "${patches_version_dir}"
|
||||
|
||||
# Only x86_64 supports libpmem
|
||||
[ "$(uname -m)" = "x86_64" ] && sudo apt-get --no-install-recommends install -y apt-utils ca-certificates libpmem-dev libseccomp-dev
|
||||
[ "$(uname -m)" = "x86_64" ] && sudo apt-get --no-install-recommends install -y apt-utils ca-certificates libpmem-dev
|
||||
|
||||
configure_hypervisor=${kata_dir}/tools/packaging/scripts/configure-hypervisor.sh
|
||||
chmod +x ${configure_hypervisor}
|
||||
@@ -278,7 +299,15 @@ parts:
|
||||
| xargs ./configure
|
||||
|
||||
# Copy QEMU configurations (Kconfigs)
|
||||
cp -a ${kata_dir}/tools/packaging/qemu/default-configs/* default-configs/devices/
|
||||
case "$(branch)" in
|
||||
"v5.1.0")
|
||||
cp -a ${kata_dir}/tools/packaging/qemu/default-configs/* default-configs
|
||||
;;
|
||||
|
||||
*)
|
||||
cp -a ${kata_dir}/tools/packaging/qemu/default-configs/* default-configs/devices/
|
||||
;;
|
||||
esac
|
||||
|
||||
# build and install
|
||||
make -j $(($(nproc)-1))
|
||||
|
||||
1
src/agent/.gitignore
vendored
1
src/agent/.gitignore
vendored
@@ -1 +1,2 @@
|
||||
tarpaulin-report.html
|
||||
vendor/
|
||||
|
||||
108
src/agent/Cargo.lock
generated
108
src/agent/Cargo.lock
generated
@@ -1,5 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.15.1"
|
||||
@@ -51,6 +53,17 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4d7d63395147b81a9e570bcc6243aaf71c017bd666d4909cfef0085bdda8d73"
|
||||
|
||||
[[package]]
|
||||
name = "async-recursion"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.50"
|
||||
@@ -507,6 +520,7 @@ name = "kata-agent"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
"async-trait",
|
||||
"capctl",
|
||||
"cgroups-rs",
|
||||
@@ -516,8 +530,8 @@ dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"logging",
|
||||
"netlink-packet-utils 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"netlink-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"netlink-packet-utils",
|
||||
"netlink-sys",
|
||||
"nix 0.21.0",
|
||||
"oci",
|
||||
"opentelemetry",
|
||||
@@ -535,6 +549,7 @@ dependencies = [
|
||||
"slog-scope",
|
||||
"slog-stdlog",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-vsock",
|
||||
"tracing",
|
||||
@@ -641,9 +656,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.7.11"
|
||||
version = "0.7.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956"
|
||||
checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
@@ -670,43 +685,34 @@ checksum = "2eb04b9f127583ed176e163fb9ec6f3e793b87e21deedd5734a69386a18a0151"
|
||||
[[package]]
|
||||
name = "netlink-packet-core"
|
||||
version = "0.2.4"
|
||||
source = "git+https://github.com/little-dude/netlink?rev=a9367bc4700496ddebc088110c28f40962923326#a9367bc4700496ddebc088110c28f40962923326"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac48279d5062bdf175bdbcb6b58ff1d6b0ecd54b951f7a0ff4bc0550fe903ccb"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byteorder",
|
||||
"libc",
|
||||
"netlink-packet-utils 0.4.0 (git+https://github.com/little-dude/netlink?rev=a9367bc4700496ddebc088110c28f40962923326)",
|
||||
"netlink-packet-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "netlink-packet-route"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/little-dude/netlink?rev=a9367bc4700496ddebc088110c28f40962923326#a9367bc4700496ddebc088110c28f40962923326"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c92a86a6528fe6d0a811c48d28213ca896a2b8bf2f6cadf2ab5bb12d32ec0f1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"libc",
|
||||
"netlink-packet-core",
|
||||
"netlink-packet-utils 0.4.0 (git+https://github.com/little-dude/netlink?rev=a9367bc4700496ddebc088110c28f40962923326)",
|
||||
"netlink-packet-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "netlink-packet-utils"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c2afb159d0e3ac700e85f0df25b8438b99d43ed0c0b685242fcdf1b5673e54d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byteorder",
|
||||
"paste",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "netlink-packet-utils"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/little-dude/netlink?rev=a9367bc4700496ddebc088110c28f40962923326#a9367bc4700496ddebc088110c28f40962923326"
|
||||
checksum = "5fcfb6f758b66e964b2339596d94078218d96aad5b32003e8e2a1d23c27a6784"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byteorder",
|
||||
@@ -716,34 +722,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "netlink-proto"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/little-dude/netlink?rev=a9367bc4700496ddebc088110c28f40962923326#a9367bc4700496ddebc088110c28f40962923326"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddd06e90449ae973fe3888c1ff85949604ef5189b4ac9a2ae39518da1e00762d"
|
||||
dependencies = [
|
||||
"bytes 1.0.1",
|
||||
"futures",
|
||||
"log",
|
||||
"netlink-packet-core",
|
||||
"netlink-sys 0.6.0 (git+https://github.com/little-dude/netlink?rev=a9367bc4700496ddebc088110c28f40962923326)",
|
||||
"netlink-sys",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "netlink-sys"
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d61c5374735aa0cd07cb7fd820b656062b187b5588d79517f72956b57c6de9ef"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"libc",
|
||||
"log",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "netlink-sys"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/little-dude/netlink?rev=a9367bc4700496ddebc088110c28f40962923326#a9367bc4700496ddebc088110c28f40962923326"
|
||||
checksum = "f48ea34ea0678719815c3753155067212f853ad2d8ef4a49167bae7f7c254188"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"libc",
|
||||
@@ -877,6 +873,8 @@ dependencies = [
|
||||
"rand",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1250,8 +1248,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rtnetlink"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/little-dude/netlink?rev=a9367bc4700496ddebc088110c28f40962923326#a9367bc4700496ddebc088110c28f40962923326"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "279f7e9a312496b3e726e776cbd1f3102bd5ffe66503c3f44d642f7327995919"
|
||||
dependencies = [
|
||||
"byteordered",
|
||||
"futures",
|
||||
@@ -1513,18 +1512,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.24"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
|
||||
checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.24"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
|
||||
checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
@@ -1552,9 +1551,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.6.0"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd3076b5c8cc18138b8f8814895c11eb4de37114a5d127bafdc5e55798ceef37"
|
||||
checksum = "98c8b05dc14c75ea83d63dd391100353789f5f24b8b3866542a5e85c8be8e985"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes 1.0.1",
|
||||
@@ -1563,6 +1562,7 @@ dependencies = [
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"tokio-macros",
|
||||
@@ -1580,6 +1580,17 @@ dependencies = [
|
||||
"syn 1.0.72",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-stream"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8864d706fdb3cc0843a49647ac892720dac98a6eeb818b77190592cf4994066"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.6.7"
|
||||
@@ -1783,12 +1794,13 @@ dependencies = [
|
||||
"bincode",
|
||||
"byteorder",
|
||||
"libc",
|
||||
"nix 0.20.0",
|
||||
"nix 0.21.0",
|
||||
"opentelemetry",
|
||||
"serde",
|
||||
"slog",
|
||||
"thiserror",
|
||||
"vsock",
|
||||
"tokio",
|
||||
"tokio-vsock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -18,18 +18,21 @@ capctl = "0.2.0"
|
||||
serde_json = "1.0.39"
|
||||
scan_fmt = "0.2.3"
|
||||
scopeguard = "1.0.0"
|
||||
thiserror = "1.0.26"
|
||||
regex = "1"
|
||||
|
||||
# Async helpers
|
||||
async-trait = "0.1.42"
|
||||
tokio = { version = "1.2.0", features = ["rt", "rt-multi-thread", "sync", "macros", "io-util", "time", "signal", "io-std", "process", "fs"] }
|
||||
async-recursion = "0.3.2"
|
||||
futures = "0.3.12"
|
||||
netlink-sys = { version = "0.6.0", features = ["tokio_socket",]}
|
||||
|
||||
# Async runtime
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio-vsock = "0.3.1"
|
||||
# Because the author has no time to maintain the crate, we switch the dependency to github,
|
||||
# Once the new version released on crates.io, we switch it back.
|
||||
# https://github.com/little-dude/netlink/issues/161
|
||||
rtnetlink = { git = "https://github.com/little-dude/netlink", rev = "a9367bc4700496ddebc088110c28f40962923326" }
|
||||
netlink-packet-utils = "0.4.0"
|
||||
|
||||
netlink-sys = { version = "0.7.0", features = ["tokio_socket",]}
|
||||
rtnetlink = "0.8.0"
|
||||
netlink-packet-utils = "0.4.1"
|
||||
ipnetwork = "0.17.0"
|
||||
|
||||
# slog:
|
||||
@@ -52,7 +55,7 @@ cgroups = { package = "cgroups-rs", version = "0.2.5" }
|
||||
tracing = "0.1.26"
|
||||
tracing-subscriber = "0.2.18"
|
||||
tracing-opentelemetry = "0.13.0"
|
||||
opentelemetry = "0.14.0"
|
||||
opentelemetry = { version = "0.14.0", features = ["rt-tokio-current-thread"]}
|
||||
vsock-exporter = { path = "vsock-exporter" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -27,40 +27,7 @@ COMMIT_MSG = $(if $(COMMIT),$(COMMIT),unknown)
|
||||
# Exported to allow cargo to see it
|
||||
export VERSION_COMMIT := $(if $(COMMIT),$(VERSION)-$(COMMIT),$(VERSION))
|
||||
|
||||
##VAR BUILD_TYPE=release|debug type of rust build
|
||||
BUILD_TYPE = release
|
||||
|
||||
##VAR ARCH=arch target to build (format: uname -m)
|
||||
ARCH = $(shell uname -m)
|
||||
##VAR LIBC=musl|gnu
|
||||
LIBC ?= musl
|
||||
ifneq ($(LIBC),musl)
|
||||
ifeq ($(LIBC),gnu)
|
||||
override LIBC = gnu
|
||||
else
|
||||
$(error "ERROR: A non supported LIBC value was passed. Supported values are musl and gnu")
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH), ppc64le)
|
||||
override ARCH = powerpc64le
|
||||
override LIBC = gnu
|
||||
$(warning "WARNING: powerpc64le-unknown-linux-musl target is unavailable")
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH), s390x)
|
||||
override LIBC = gnu
|
||||
$(warning "WARNING: s390x-unknown-linux-musl target is unavailable")
|
||||
endif
|
||||
|
||||
|
||||
EXTRA_RUSTFLAGS :=
|
||||
ifeq ($(ARCH), aarch64)
|
||||
override EXTRA_RUSTFLAGS = -C link-arg=-lgcc
|
||||
$(warning "WARNING: aarch64-musl needs extra symbols from libgcc")
|
||||
endif
|
||||
|
||||
TRIPLE = $(ARCH)-unknown-linux-$(LIBC)
|
||||
include ../../utils.mk
|
||||
|
||||
TARGET_PATH = target/$(TRIPLE)/$(BUILD_TYPE)/$(TARGET)
|
||||
|
||||
@@ -154,6 +121,10 @@ clean:
|
||||
@rm -f $(GENERATED_FILES)
|
||||
@rm -f tarpaulin-report.html
|
||||
|
||||
vendor:
|
||||
@cargo vendor
|
||||
|
||||
|
||||
#TARGET test: run cargo tests
|
||||
test:
|
||||
@cargo test --all --target $(TRIPLE)
|
||||
@@ -223,7 +194,8 @@ codecov-html: check_tarpaulin
|
||||
help \
|
||||
show-header \
|
||||
show-summary \
|
||||
optimize
|
||||
optimize \
|
||||
vendor
|
||||
|
||||
##TARGET generate-protocols: generate/update grpc agent protocols
|
||||
generate-protocols:
|
||||
|
||||
@@ -66,6 +66,7 @@ service AgentService {
|
||||
rpc SetGuestDateTime(SetGuestDateTimeRequest) returns (google.protobuf.Empty);
|
||||
rpc CopyFile(CopyFileRequest) returns (google.protobuf.Empty);
|
||||
rpc GetOOMEvent(GetOOMEventRequest) returns (OOMEvent);
|
||||
rpc AddSwap(AddSwapRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
message CreateContainerRequest {
|
||||
@@ -503,6 +504,10 @@ message OOMEvent {
|
||||
string container_id = 1;
|
||||
}
|
||||
|
||||
message AddSwapRequest {
|
||||
repeated uint32 PCIPath = 1;
|
||||
}
|
||||
|
||||
message GetMetricsRequest {}
|
||||
|
||||
message Metrics {
|
||||
|
||||
@@ -232,19 +232,19 @@ fn set_devices_resources(
|
||||
let mut devices = vec![];
|
||||
|
||||
for d in device_resources.iter() {
|
||||
if let Some(dev) = linux_device_group_to_cgroup_device(&d) {
|
||||
if let Some(dev) = linux_device_group_to_cgroup_device(d) {
|
||||
devices.push(dev);
|
||||
}
|
||||
}
|
||||
|
||||
for d in DEFAULT_DEVICES.iter() {
|
||||
if let Some(dev) = linux_device_to_cgroup_device(&d) {
|
||||
if let Some(dev) = linux_device_to_cgroup_device(d) {
|
||||
devices.push(dev);
|
||||
}
|
||||
}
|
||||
|
||||
for d in DEFAULT_ALLOWED_DEVICES.iter() {
|
||||
if let Some(dev) = linux_device_group_to_cgroup_device(&d) {
|
||||
if let Some(dev) = linux_device_group_to_cgroup_device(d) {
|
||||
devices.push(dev);
|
||||
}
|
||||
}
|
||||
@@ -828,7 +828,7 @@ fn get_blkio_stats_v2(cg: &cgroups::Cgroup) -> SingularPtrField<BlkioStats> {
|
||||
|
||||
fn get_blkio_stats(cg: &cgroups::Cgroup) -> SingularPtrField<BlkioStats> {
|
||||
if cg.v2() {
|
||||
return get_blkio_stats_v2(&cg);
|
||||
return get_blkio_stats_v2(cg);
|
||||
}
|
||||
|
||||
let blkio_controller: &BlkIoController = get_controller_or_return_singular_none!(cg);
|
||||
@@ -923,12 +923,12 @@ pub fn get_mounts() -> Result<HashMap<String, String>> {
|
||||
let paths = get_paths()?;
|
||||
|
||||
for l in fs::read_to_string(MOUNTS)?.lines() {
|
||||
let p: Vec<&str> = l.split(" - ").collect();
|
||||
let p: Vec<&str> = l.splitn(2, " - ").collect();
|
||||
let pre: Vec<&str> = p[0].split(' ').collect();
|
||||
let post: Vec<&str> = p[1].split(' ').collect();
|
||||
|
||||
if post.len() != 3 {
|
||||
warn!(sl!(), "mountinfo corrupted!");
|
||||
warn!(sl!(), "can't parse {} line {:?}", MOUNTS, l);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1022,7 +1022,7 @@ impl Manager {
|
||||
.unwrap()
|
||||
.trim_start_matches(root_path.to_str().unwrap());
|
||||
info!(sl!(), "updating cpuset for parent path {:?}", &r_path);
|
||||
let cg = new_cgroup(cgroups::hierarchies::auto(), &r_path);
|
||||
let cg = new_cgroup(cgroups::hierarchies::auto(), r_path);
|
||||
let cpuset_controller: &CpuSetController = cg.controller_of().unwrap();
|
||||
cpuset_controller.set_cpus(guest_cpuset)?;
|
||||
}
|
||||
|
||||
@@ -139,19 +139,6 @@ async fn notify_on_oom(cid: &str, dir: String) -> Result<Receiver<String>> {
|
||||
register_memory_event(cid, dir, "memory.oom_control", "").await
|
||||
}
|
||||
|
||||
// level is one of "low", "medium", or "critical"
|
||||
async fn notify_memory_pressure(cid: &str, dir: String, level: &str) -> Result<Receiver<String>> {
|
||||
if dir.is_empty() {
|
||||
return Err(anyhow!("memory controller missing"));
|
||||
}
|
||||
|
||||
if level != "low" && level != "medium" && level != "critical" {
|
||||
return Err(anyhow!("invalid pressure level {}", level));
|
||||
}
|
||||
|
||||
register_memory_event(cid, dir, "memory.pressure_level", level).await
|
||||
}
|
||||
|
||||
async fn register_memory_event(
|
||||
cid: &str,
|
||||
cg_dir: String,
|
||||
|
||||
@@ -62,10 +62,7 @@ use tokio::sync::Mutex;
|
||||
|
||||
use crate::utils;
|
||||
|
||||
const STATE_FILENAME: &str = "state.json";
|
||||
const EXEC_FIFO_FILENAME: &str = "exec.fifo";
|
||||
const VER_MARKER: &str = "1.2.5";
|
||||
const PID_NS_PATH: &str = "/proc/self/ns/pid";
|
||||
|
||||
const INIT: &str = "INIT";
|
||||
const NO_PIVOT: &str = "NO_PIVOT";
|
||||
@@ -94,10 +91,6 @@ impl ContainerStatus {
|
||||
self.cur_status
|
||||
}
|
||||
|
||||
fn pre_status(&self) -> ContainerState {
|
||||
self.pre_status
|
||||
}
|
||||
|
||||
fn transition(&mut self, to: ContainerState) {
|
||||
self.pre_status = self.status();
|
||||
self.cur_status = to;
|
||||
@@ -397,7 +390,7 @@ fn do_init_child(cwfd: RawFd) -> Result<()> {
|
||||
let linux = spec.linux.as_ref().unwrap();
|
||||
|
||||
// get namespace vector to join/new
|
||||
let nses = get_namespaces(&linux);
|
||||
let nses = get_namespaces(linux);
|
||||
|
||||
let mut userns = false;
|
||||
let mut to_new = CloneFlags::empty();
|
||||
@@ -568,7 +561,7 @@ fn do_init_child(cwfd: RawFd) -> Result<()> {
|
||||
}
|
||||
|
||||
if to_new.contains(CloneFlags::CLONE_NEWNS) {
|
||||
mount::finish_rootfs(cfd_log, &spec)?;
|
||||
mount::finish_rootfs(cfd_log, &spec, &oci_process)?;
|
||||
}
|
||||
|
||||
if !oci_process.cwd.is_empty() {
|
||||
@@ -946,7 +939,7 @@ impl BaseContainer for LinuxContainer {
|
||||
|
||||
join_namespaces(
|
||||
&logger,
|
||||
&spec,
|
||||
spec,
|
||||
&p,
|
||||
self.cgroup_manager.as_ref().unwrap(),
|
||||
&st,
|
||||
@@ -1038,7 +1031,7 @@ impl BaseContainer for LinuxContainer {
|
||||
let fifo = format!("{}/{}", &self.root, EXEC_FIFO_FILENAME);
|
||||
let fd = fcntl::open(fifo.as_str(), OFlag::O_WRONLY, Mode::from_bits_truncate(0))?;
|
||||
let data: &[u8] = &[0];
|
||||
unistd::write(fd, &data)?;
|
||||
unistd::write(fd, data)?;
|
||||
info!(self.logger, "container started");
|
||||
self.init_process_start_time = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
@@ -1401,18 +1394,8 @@ impl LinuxContainer {
|
||||
logger: logger.new(o!("module" => "rustjail", "subsystem" => "container", "cid" => id)),
|
||||
})
|
||||
}
|
||||
|
||||
fn load<T: Into<String>>(_id: T, _base: T) -> Result<Self> {
|
||||
Err(anyhow!("not supported"))
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the differing rlimit types for different targets
|
||||
#[cfg(target_env = "musl")]
|
||||
type RlimitsType = libc::c_int;
|
||||
#[cfg(target_env = "gnu")]
|
||||
type RlimitsType = libc::__rlimit_resource_t;
|
||||
|
||||
fn setgroups(grps: &[libc::gid_t]) -> Result<()> {
|
||||
let ret = unsafe { libc::setgroups(grps.len(), grps.as_ptr() as *const libc::gid_t) };
|
||||
Errno::result(ret).map(drop)?;
|
||||
@@ -1554,6 +1537,7 @@ mod tests {
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use tempfile::tempdir;
|
||||
use tokio::process::Command;
|
||||
|
||||
macro_rules! sl {
|
||||
() => {
|
||||
@@ -1561,12 +1545,27 @@ mod tests {
|
||||
};
|
||||
}
|
||||
|
||||
async fn which(cmd: &str) -> String {
|
||||
let output: std::process::Output = Command::new("which")
|
||||
.arg(cmd)
|
||||
.output()
|
||||
.await
|
||||
.expect("which command failed to run");
|
||||
|
||||
match String::from_utf8(output.stdout) {
|
||||
Ok(v) => v.trim_end_matches('\n').to_string(),
|
||||
Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_execute_hook() {
|
||||
let xargs = which("xargs").await;
|
||||
|
||||
execute_hook(
|
||||
&slog_scope::logger(),
|
||||
&Hook {
|
||||
path: "/usr/bin/xargs".to_string(),
|
||||
path: xargs,
|
||||
args: vec![],
|
||||
env: vec![],
|
||||
timeout: None,
|
||||
@@ -1586,10 +1585,12 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_execute_hook_with_timeout() {
|
||||
let sleep = which("sleep").await;
|
||||
|
||||
let res = execute_hook(
|
||||
&slog_scope::logger(),
|
||||
&Hook {
|
||||
path: "/usr/bin/sleep".to_string(),
|
||||
path: sleep,
|
||||
args: vec!["2".to_string()],
|
||||
env: vec![],
|
||||
timeout: Some(1),
|
||||
@@ -1626,7 +1627,7 @@ mod tests {
|
||||
let pre_status = status.status();
|
||||
status.transition(*s);
|
||||
|
||||
assert_eq!(pre_status, status.pre_status());
|
||||
assert_eq!(pre_status, status.pre_status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,15 +3,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
// #![allow(unused_attributes)]
|
||||
// #![allow(unused_imports)]
|
||||
// #![allow(unused_variables)]
|
||||
// #![allow(unused_mut)]
|
||||
#![allow(dead_code)]
|
||||
// #![allow(deprecated)]
|
||||
// #![allow(unused_must_use)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
// #![allow(unused_comparisons)]
|
||||
#[macro_use]
|
||||
#[cfg(test)]
|
||||
extern crate serial_test;
|
||||
@@ -464,10 +456,6 @@ fn linux_grpc_to_oci(l: &grpc::Linux) -> oci::Linux {
|
||||
}
|
||||
}
|
||||
|
||||
fn linux_oci_to_grpc(_l: &oci::Linux) -> grpc::Linux {
|
||||
grpc::Linux::default()
|
||||
}
|
||||
|
||||
pub fn grpc_to_oci(grpc: &grpc::Spec) -> oci::Spec {
|
||||
// process
|
||||
let process = if grpc.Process.is_some() {
|
||||
@@ -523,7 +511,6 @@ pub fn grpc_to_oci(grpc: &grpc::Spec) -> oci::Spec {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[allow(unused_macros)]
|
||||
#[macro_export]
|
||||
macro_rules! skip_if_not_root {
|
||||
() => {
|
||||
|
||||
@@ -13,7 +13,7 @@ use nix::mount::{MntFlags, MsFlags};
|
||||
use nix::sys::stat::{self, Mode, SFlag};
|
||||
use nix::unistd::{self, Gid, Uid};
|
||||
use nix::NixPath;
|
||||
use oci::{LinuxDevice, Mount, Spec};
|
||||
use oci::{LinuxDevice, Mount, Process, Spec};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs::{self, OpenOptions};
|
||||
use std::mem::MaybeUninit;
|
||||
@@ -62,49 +62,56 @@ const PROC_SUPER_MAGIC: libc::c_uint = 0x00009fa0;
|
||||
lazy_static! {
|
||||
static ref PROPAGATION: HashMap<&'static str, MsFlags> = {
|
||||
let mut m = HashMap::new();
|
||||
m.insert("shared", MsFlags::MS_SHARED);
|
||||
m.insert("rshared", MsFlags::MS_SHARED | MsFlags::MS_REC);
|
||||
m.insert("private", MsFlags::MS_PRIVATE);
|
||||
m.insert("rprivate", MsFlags::MS_PRIVATE | MsFlags::MS_REC);
|
||||
m.insert("slave", MsFlags::MS_SLAVE);
|
||||
m.insert("rshared", MsFlags::MS_SHARED | MsFlags::MS_REC);
|
||||
m.insert("rslave", MsFlags::MS_SLAVE | MsFlags::MS_REC);
|
||||
m.insert("unbindable", MsFlags::MS_UNBINDABLE);
|
||||
m.insert("runbindable", MsFlags::MS_UNBINDABLE | MsFlags::MS_REC);
|
||||
m.insert("shared", MsFlags::MS_SHARED);
|
||||
m.insert("slave", MsFlags::MS_SLAVE);
|
||||
m.insert("unbindable", MsFlags::MS_UNBINDABLE);
|
||||
m
|
||||
};
|
||||
static ref OPTIONS: HashMap<&'static str, (bool, MsFlags)> = {
|
||||
let mut m = HashMap::new();
|
||||
m.insert("defaults", (false, MsFlags::empty()));
|
||||
m.insert("ro", (false, MsFlags::MS_RDONLY));
|
||||
m.insert("rw", (true, MsFlags::MS_RDONLY));
|
||||
m.insert("suid", (true, MsFlags::MS_NOSUID));
|
||||
m.insert("nosuid", (false, MsFlags::MS_NOSUID));
|
||||
m.insert("dev", (true, MsFlags::MS_NODEV));
|
||||
m.insert("nodev", (false, MsFlags::MS_NODEV));
|
||||
m.insert("exec", (true, MsFlags::MS_NOEXEC));
|
||||
m.insert("noexec", (false, MsFlags::MS_NOEXEC));
|
||||
m.insert("sync", (false, MsFlags::MS_SYNCHRONOUS));
|
||||
m.insert("acl", (false, MsFlags::MS_POSIXACL));
|
||||
m.insert("async", (true, MsFlags::MS_SYNCHRONOUS));
|
||||
m.insert("dirsync", (false, MsFlags::MS_DIRSYNC));
|
||||
m.insert("remount", (false, MsFlags::MS_REMOUNT));
|
||||
m.insert("mand", (false, MsFlags::MS_MANDLOCK));
|
||||
m.insert("nomand", (true, MsFlags::MS_MANDLOCK));
|
||||
m.insert("atime", (true, MsFlags::MS_NOATIME));
|
||||
m.insert("noatime", (false, MsFlags::MS_NOATIME));
|
||||
m.insert("diratime", (true, MsFlags::MS_NODIRATIME));
|
||||
m.insert("nodiratime", (false, MsFlags::MS_NODIRATIME));
|
||||
m.insert("bind", (false, MsFlags::MS_BIND));
|
||||
m.insert("defaults", (false, MsFlags::empty()));
|
||||
m.insert("dev", (true, MsFlags::MS_NODEV));
|
||||
m.insert("diratime", (true, MsFlags::MS_NODIRATIME));
|
||||
m.insert("dirsync", (false, MsFlags::MS_DIRSYNC));
|
||||
m.insert("exec", (true, MsFlags::MS_NOEXEC));
|
||||
m.insert("iversion", (false, MsFlags::MS_I_VERSION));
|
||||
m.insert("lazytime", (false, MsFlags::MS_LAZYTIME));
|
||||
m.insert("loud", (true, MsFlags::MS_SILENT));
|
||||
m.insert("mand", (false, MsFlags::MS_MANDLOCK));
|
||||
m.insert("noacl", (true, MsFlags::MS_POSIXACL));
|
||||
m.insert("noatime", (false, MsFlags::MS_NOATIME));
|
||||
m.insert("nodev", (false, MsFlags::MS_NODEV));
|
||||
m.insert("nodiratime", (false, MsFlags::MS_NODIRATIME));
|
||||
m.insert("noexec", (false, MsFlags::MS_NOEXEC));
|
||||
m.insert("noiversion", (true, MsFlags::MS_I_VERSION));
|
||||
m.insert("nolazytime", (true, MsFlags::MS_LAZYTIME));
|
||||
m.insert("nomand", (true, MsFlags::MS_MANDLOCK));
|
||||
m.insert("norelatime", (true, MsFlags::MS_RELATIME));
|
||||
m.insert("nostrictatime", (true, MsFlags::MS_STRICTATIME));
|
||||
m.insert("nosuid", (false, MsFlags::MS_NOSUID));
|
||||
m.insert("rbind", (false, MsFlags::MS_BIND | MsFlags::MS_REC));
|
||||
m.insert("relatime", (false, MsFlags::MS_RELATIME));
|
||||
m.insert("norelatime", (true, MsFlags::MS_RELATIME));
|
||||
m.insert("remount", (false, MsFlags::MS_REMOUNT));
|
||||
m.insert("ro", (false, MsFlags::MS_RDONLY));
|
||||
m.insert("rw", (true, MsFlags::MS_RDONLY));
|
||||
m.insert("silent", (false, MsFlags::MS_SILENT));
|
||||
m.insert("strictatime", (false, MsFlags::MS_STRICTATIME));
|
||||
m.insert("nostrictatime", (true, MsFlags::MS_STRICTATIME));
|
||||
m.insert("suid", (true, MsFlags::MS_NOSUID));
|
||||
m.insert("sync", (false, MsFlags::MS_SYNCHRONOUS));
|
||||
m
|
||||
};
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[allow(unused_variables)]
|
||||
pub fn mount<
|
||||
P1: ?Sized + NixPath,
|
||||
P2: ?Sized + NixPath,
|
||||
@@ -124,7 +131,6 @@ pub fn mount<
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[allow(unused_variables)]
|
||||
pub fn umount2<P: ?Sized + NixPath>(
|
||||
target: &P,
|
||||
flags: MntFlags,
|
||||
@@ -183,7 +189,7 @@ pub fn init_rootfs(
|
||||
|
||||
let mut bind_mount_dev = false;
|
||||
for m in &spec.mounts {
|
||||
let (mut flags, pgflags, data) = parse_mount(&m);
|
||||
let (mut flags, pgflags, data) = parse_mount(m);
|
||||
if !m.destination.starts_with('/') || m.destination.contains("..") {
|
||||
return Err(anyhow!(
|
||||
"the mount destination {} is invalid",
|
||||
@@ -192,7 +198,7 @@ pub fn init_rootfs(
|
||||
}
|
||||
|
||||
if m.r#type == "cgroup" {
|
||||
mount_cgroups(cfd_log, &m, rootfs, flags, &data, cpath, mounts)?;
|
||||
mount_cgroups(cfd_log, m, rootfs, flags, &data, cpath, mounts)?;
|
||||
} else {
|
||||
if m.destination == "/dev" {
|
||||
if m.r#type == "bind" {
|
||||
@@ -220,7 +226,7 @@ pub fn init_rootfs(
|
||||
}
|
||||
}
|
||||
|
||||
mount_from(cfd_log, &m, &rootfs, flags, &data, "")?;
|
||||
mount_from(cfd_log, m, rootfs, flags, &data, "")?;
|
||||
// bind mount won't change mount options, we need remount to make mount options
|
||||
// effective.
|
||||
// first check that we have non-default options required before attempting a
|
||||
@@ -350,7 +356,7 @@ fn mount_cgroups(
|
||||
mounts: &HashMap<String, String>,
|
||||
) -> Result<()> {
|
||||
if cgroups::hierarchies::is_cgroup2_unified_mode() {
|
||||
return mount_cgroups_v2(cfd_log, &m, rootfs, flags);
|
||||
return mount_cgroups_v2(cfd_log, m, rootfs, flags);
|
||||
}
|
||||
// mount tmpfs
|
||||
let ctm = Mount {
|
||||
@@ -444,7 +450,6 @@ fn mount_cgroups(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
|
||||
new_root: &P1,
|
||||
put_old: &P2,
|
||||
@@ -577,7 +582,6 @@ fn parse_mount_table() -> Result<Vec<Info>> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[allow(unused_variables)]
|
||||
fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<(), nix::Error> {
|
||||
#[cfg(not(test))]
|
||||
return unistd::chroot(path);
|
||||
@@ -898,10 +902,21 @@ fn bind_dev(dev: &LinuxDevice) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn finish_rootfs(cfd_log: RawFd, spec: &Spec) -> Result<()> {
|
||||
pub fn finish_rootfs(cfd_log: RawFd, spec: &Spec, process: &Process) -> Result<()> {
|
||||
let olddir = unistd::getcwd()?;
|
||||
log_child!(cfd_log, "old cwd: {}", olddir.to_str().unwrap());
|
||||
unistd::chdir("/")?;
|
||||
|
||||
if !process.cwd.is_empty() {
|
||||
// Although the process.cwd string can be unclean/malicious (../../dev, etc),
|
||||
// we are running on our own mount namespace and we just chrooted into the
|
||||
// container's root. It's safe to create CWD from there.
|
||||
log_child!(cfd_log, "Creating CWD {}", process.cwd.as_str());
|
||||
// Unconditionally try to create CWD, create_dir_all will not fail if
|
||||
// it already exists.
|
||||
fs::create_dir_all(process.cwd.as_str())?;
|
||||
}
|
||||
|
||||
if spec.linux.is_some() {
|
||||
let linux = spec.linux.as_ref().unwrap();
|
||||
|
||||
@@ -1207,7 +1222,7 @@ mod tests {
|
||||
options: vec!["ro".to_string(), "shared".to_string()],
|
||||
}];
|
||||
|
||||
let ret = finish_rootfs(stdout_fd, &spec);
|
||||
let ret = finish_rootfs(stdout_fd, &spec, &oci::Process::default());
|
||||
assert!(ret.is_ok(), "Should pass. Got: {:?}", ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ pub fn validate(conf: &Config) -> Result<()> {
|
||||
security(oci).context("security")?;
|
||||
usernamespace(oci).context("usernamespace")?;
|
||||
cgroupnamespace(oci).context("cgroupnamespace")?;
|
||||
sysctl(&oci).context("sysctl")?;
|
||||
sysctl(oci).context("sysctl")?;
|
||||
|
||||
if conf.rootless_euid {
|
||||
rootless_euid(oci).context("rootless euid")?;
|
||||
|
||||
140
src/agent/src/ccw.rs
Normal file
140
src/agent/src/ccw.rs
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright (c) IBM Corp. 2021
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::anyhow;
|
||||
|
||||
// CCW bus ID follow the format <xx>.<d>.<xxxx> [1, p. 11], where
|
||||
// - <xx> is the channel subsystem ID, which is always 0 from the guest side, but different from
|
||||
// the host side, e.g. 0xfe for virtio-*-ccw [1, p. 435],
|
||||
// - <d> is the subchannel set ID, which ranges from 0-3 [2], and
|
||||
// - <xxxx> is the device number (0000-ffff; leading zeroes can be omitted,
|
||||
// e.g. 3 instead of 0003).
|
||||
// [1] https://www.ibm.com/docs/en/linuxonibm/pdf/lku4dd04.pdf
|
||||
// [2] https://qemu.readthedocs.io/en/latest/system/s390x/css.html
|
||||
|
||||
// Maximum subchannel set ID
|
||||
const SUBCHANNEL_SET_MAX: u8 = 3;
|
||||
|
||||
// CCW device. From the guest side, the first field is always 0 and can therefore be omitted.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Device {
|
||||
subchannel_set_id: u8,
|
||||
device_number: u16,
|
||||
}
|
||||
|
||||
impl Device {
|
||||
pub fn new(subchannel_set_id: u8, device_number: u16) -> anyhow::Result<Self> {
|
||||
if subchannel_set_id > SUBCHANNEL_SET_MAX {
|
||||
return Err(anyhow!(
|
||||
"Subchannel set ID {:?} should be in range [0..{}]",
|
||||
subchannel_set_id,
|
||||
SUBCHANNEL_SET_MAX
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Device {
|
||||
subchannel_set_id,
|
||||
device_number,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Device {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(s: &str) -> anyhow::Result<Self> {
|
||||
let split: Vec<&str> = s.split('.').collect();
|
||||
if split.len() != 3 {
|
||||
return Err(anyhow!(
|
||||
"Wrong bus format. It needs to be in the form 0.<d>.<xxxx>, got {:?}",
|
||||
s
|
||||
));
|
||||
}
|
||||
|
||||
if split[0] != "0" {
|
||||
return Err(anyhow!(
|
||||
"Wrong bus format. First digit needs to be 0, but is {:?}",
|
||||
split[0]
|
||||
));
|
||||
}
|
||||
|
||||
let subchannel_set_id = match split[1].parse::<u8>() {
|
||||
Ok(id) => id,
|
||||
Err(_) => {
|
||||
return Err(anyhow!(
|
||||
"Wrong bus format. Second digit needs to be 0-3, but is {:?}",
|
||||
split[1]
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
let device_number = match u16::from_str_radix(split[2], 16) {
|
||||
Ok(id) => id,
|
||||
Err(_) => {
|
||||
return Err(anyhow!(
|
||||
"Wrong bus format. Third digit needs to be 0-ffff, but is {:?}",
|
||||
split[2]
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
Device::new(subchannel_set_id, device_number)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Device {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
write!(f, "0.{}.{:04x}", self.subchannel_set_id, self.device_number)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::ccw::Device;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn test_new_device() {
|
||||
// Valid devices
|
||||
let device = Device::new(0, 0).unwrap();
|
||||
assert_eq!(format!("{}", device), "0.0.0000");
|
||||
|
||||
let device = Device::new(3, 0xffff).unwrap();
|
||||
assert_eq!(format!("{}", device), "0.3.ffff");
|
||||
|
||||
// Invalid device
|
||||
let device = Device::new(4, 0);
|
||||
assert!(device.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_device_from_str() {
|
||||
// Valid devices
|
||||
let device = Device::from_str("0.0.0").unwrap();
|
||||
assert_eq!(format!("{}", device), "0.0.0000");
|
||||
|
||||
let device = Device::from_str("0.0.0000").unwrap();
|
||||
assert_eq!(format!("{}", device), "0.0.0000");
|
||||
|
||||
let device = Device::from_str("0.3.ffff").unwrap();
|
||||
assert_eq!(format!("{}", device), "0.3.ffff");
|
||||
|
||||
// Invalid devices
|
||||
let device = Device::from_str("0.0");
|
||||
assert!(device.is_err());
|
||||
|
||||
let device = Device::from_str("1.0.0");
|
||||
assert!(device.is_err());
|
||||
|
||||
let device = Device::from_str("0.not_a_subchannel_set_id.0");
|
||||
assert!(device.is_err());
|
||||
|
||||
let device = Device::from_str("0.0.not_a_device_number");
|
||||
assert!(device.is_err());
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,8 +14,13 @@ use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
#[cfg(target_arch = "s390x")]
|
||||
use crate::ccw;
|
||||
use crate::linux_abi::*;
|
||||
use crate::mount::{DRIVER_BLK_TYPE, DRIVER_MMIO_BLK_TYPE, DRIVER_NVDIMM_TYPE, DRIVER_SCSI_TYPE};
|
||||
use crate::mount::{
|
||||
DRIVER_BLK_CCW_TYPE, DRIVER_BLK_TYPE, DRIVER_MMIO_BLK_TYPE, DRIVER_NVDIMM_TYPE,
|
||||
DRIVER_SCSI_TYPE,
|
||||
};
|
||||
use crate::pci;
|
||||
use crate::sandbox::Sandbox;
|
||||
use crate::uevent::{wait_for_uevent, Uevent, UeventMatcher};
|
||||
@@ -57,7 +62,7 @@ pub fn online_device(path: &str) -> Result<()> {
|
||||
// the sysfs path for the PCI host bridge, based on the PCI path
|
||||
// provided.
|
||||
#[instrument]
|
||||
fn pcipath_to_sysfs(root_bus_sysfs: &str, pcipath: &pci::Path) -> Result<String> {
|
||||
pub fn pcipath_to_sysfs(root_bus_sysfs: &str, pcipath: &pci::Path) -> Result<String> {
|
||||
let mut bus = "0000:00".to_string();
|
||||
let mut relpath = String::new();
|
||||
|
||||
@@ -163,6 +168,47 @@ pub async fn get_virtio_blk_pci_device_name(
|
||||
Ok(format!("{}/{}", SYSTEM_DEV_PATH, &uev.devname))
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "s390x")]
|
||||
#[derive(Debug)]
|
||||
struct VirtioBlkCCWMatcher {
|
||||
rex: Regex,
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "s390x")]
|
||||
impl VirtioBlkCCWMatcher {
|
||||
fn new(root_bus_path: &str, device: &ccw::Device) -> Self {
|
||||
let re = format!(
|
||||
r"^{}/0\.[0-3]\.[0-9a-f]{{1,4}}/{}/virtio[0-9]+/block/",
|
||||
root_bus_path, device
|
||||
);
|
||||
VirtioBlkCCWMatcher {
|
||||
rex: Regex::new(&re).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "s390x")]
|
||||
impl UeventMatcher for VirtioBlkCCWMatcher {
|
||||
fn is_match(&self, uev: &Uevent) -> bool {
|
||||
uev.action == "add" && self.rex.is_match(&uev.devpath) && !uev.devname.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "s390x")]
|
||||
#[instrument]
|
||||
pub async fn get_virtio_blk_ccw_device_name(
|
||||
sandbox: &Arc<Mutex<Sandbox>>,
|
||||
device: &ccw::Device,
|
||||
) -> Result<String> {
|
||||
let matcher = VirtioBlkCCWMatcher::new(&create_ccw_root_bus_path(), device);
|
||||
let uev = wait_for_uevent(sandbox, matcher).await?;
|
||||
let devname = uev.devname;
|
||||
return match Path::new(SYSTEM_DEV_PATH).join(&devname).to_str() {
|
||||
Some(path) => Ok(String::from(path)),
|
||||
None => Err(anyhow!("CCW device name {} is not valid UTF-8", &devname)),
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PmemBlockMatcher {
|
||||
suffix: String,
|
||||
@@ -352,6 +398,32 @@ async fn virtio_blk_device_handler(
|
||||
update_spec_device_list(&dev, spec, devidx)
|
||||
}
|
||||
|
||||
// device.id should be a CCW path string
|
||||
#[cfg(target_arch = "s390x")]
|
||||
#[instrument]
|
||||
async fn virtio_blk_ccw_device_handler(
|
||||
device: &Device,
|
||||
spec: &mut Spec,
|
||||
sandbox: &Arc<Mutex<Sandbox>>,
|
||||
devidx: &DevIndex,
|
||||
) -> Result<()> {
|
||||
let mut dev = device.clone();
|
||||
let ccw_device = ccw::Device::from_str(&device.id)?;
|
||||
dev.vm_path = get_virtio_blk_ccw_device_name(sandbox, &ccw_device).await?;
|
||||
update_spec_device_list(&dev, spec, devidx)
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "s390x"))]
|
||||
#[instrument]
|
||||
async fn virtio_blk_ccw_device_handler(
|
||||
_: &Device,
|
||||
_: &mut Spec,
|
||||
_: &Arc<Mutex<Sandbox>>,
|
||||
_: &DevIndex,
|
||||
) -> Result<()> {
|
||||
Err(anyhow!("CCW is only supported on s390x"))
|
||||
}
|
||||
|
||||
// device.Id should be the SCSI address of the disk in the format "scsiID:lunID"
|
||||
#[instrument]
|
||||
async fn virtio_scsi_device_handler(
|
||||
@@ -444,6 +516,7 @@ async fn add_device(
|
||||
|
||||
match device.field_type.as_str() {
|
||||
DRIVER_BLK_TYPE => virtio_blk_device_handler(device, spec, sandbox, devidx).await,
|
||||
DRIVER_BLK_CCW_TYPE => virtio_blk_ccw_device_handler(device, spec, sandbox, devidx).await,
|
||||
DRIVER_MMIO_BLK_TYPE => virtiommio_blk_device_handler(device, spec, sandbox, devidx).await,
|
||||
DRIVER_NVDIMM_TYPE => virtio_nvdimm_device_handler(device, spec, sandbox, devidx).await,
|
||||
DRIVER_SCSI_TYPE => virtio_scsi_device_handler(device, spec, sandbox, devidx).await,
|
||||
@@ -893,12 +966,12 @@ mod tests {
|
||||
uev_a.subsystem = "block".to_string();
|
||||
uev_a.devname = devname.to_string();
|
||||
uev_a.devpath = format!("{}{}/virtio4/block/{}", root_bus, relpath_a, devname);
|
||||
let matcher_a = VirtioBlkPciMatcher::new(&relpath_a);
|
||||
let matcher_a = VirtioBlkPciMatcher::new(relpath_a);
|
||||
|
||||
let mut uev_b = uev_a.clone();
|
||||
let relpath_b = "/0000:00:0a.0/0000:00:0b.0";
|
||||
uev_b.devpath = format!("{}{}/virtio0/block/{}", root_bus, relpath_b, devname);
|
||||
let matcher_b = VirtioBlkPciMatcher::new(&relpath_b);
|
||||
let matcher_b = VirtioBlkPciMatcher::new(relpath_b);
|
||||
|
||||
assert!(matcher_a.is_match(&uev_a));
|
||||
assert!(matcher_b.is_match(&uev_b));
|
||||
@@ -906,6 +979,66 @@ mod tests {
|
||||
assert!(!matcher_a.is_match(&uev_b));
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "s390x")]
|
||||
#[tokio::test]
|
||||
async fn test_virtio_blk_ccw_matcher() {
|
||||
let root_bus = create_ccw_root_bus_path();
|
||||
let subsystem = "block";
|
||||
let devname = "vda";
|
||||
let relpath = "0.0.0002";
|
||||
|
||||
let mut uev = crate::uevent::Uevent::default();
|
||||
uev.action = crate::linux_abi::U_EVENT_ACTION_ADD.to_string();
|
||||
uev.subsystem = subsystem.to_string();
|
||||
uev.devname = devname.to_string();
|
||||
uev.devpath = format!(
|
||||
"{}/0.0.0001/{}/virtio1/{}/{}",
|
||||
root_bus, relpath, subsystem, devname
|
||||
);
|
||||
|
||||
// Valid path
|
||||
let device = ccw::Device::from_str(relpath).unwrap();
|
||||
let matcher = VirtioBlkCCWMatcher::new(&root_bus, &device);
|
||||
assert!(matcher.is_match(&uev));
|
||||
|
||||
// Invalid paths
|
||||
uev.devpath = format!(
|
||||
"{}/0.0.0001/0.0.0003/virtio1/{}/{}",
|
||||
root_bus, subsystem, devname
|
||||
);
|
||||
assert!(!matcher.is_match(&uev));
|
||||
|
||||
uev.devpath = format!("0.0.0001/{}/virtio1/{}/{}", relpath, subsystem, devname);
|
||||
assert!(!matcher.is_match(&uev));
|
||||
|
||||
uev.devpath = format!(
|
||||
"{}/0.0.0001/{}/virtio/{}/{}",
|
||||
root_bus, relpath, subsystem, devname
|
||||
);
|
||||
assert!(!matcher.is_match(&uev));
|
||||
|
||||
uev.devpath = format!("{}/0.0.0001/{}/virtio1", root_bus, relpath);
|
||||
assert!(!matcher.is_match(&uev));
|
||||
|
||||
uev.devpath = format!(
|
||||
"{}/1.0.0001/{}/virtio1/{}/{}",
|
||||
root_bus, relpath, subsystem, devname
|
||||
);
|
||||
assert!(!matcher.is_match(&uev));
|
||||
|
||||
uev.devpath = format!(
|
||||
"{}/0.4.0001/{}/virtio1/{}/{}",
|
||||
root_bus, relpath, subsystem, devname
|
||||
);
|
||||
assert!(!matcher.is_match(&uev));
|
||||
|
||||
uev.devpath = format!(
|
||||
"{}/0.0.10000/{}/virtio1/{}/{}",
|
||||
root_bus, relpath, subsystem, devname
|
||||
);
|
||||
assert!(!matcher.is_match(&uev));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_scsi_block_matcher() {
|
||||
let root_bus = create_pci_root_bus_path();
|
||||
@@ -920,7 +1053,7 @@ mod tests {
|
||||
"{}/0000:00:00.0/virtio0/host0/target0:0:0/0:0:{}/block/sda",
|
||||
root_bus, addr_a
|
||||
);
|
||||
let matcher_a = ScsiBlockMatcher::new(&addr_a);
|
||||
let matcher_a = ScsiBlockMatcher::new(addr_a);
|
||||
|
||||
let mut uev_b = uev_a.clone();
|
||||
let addr_b = "2:0";
|
||||
@@ -928,7 +1061,7 @@ mod tests {
|
||||
"{}/0000:00:00.0/virtio0/host0/target0:0:2/0:0:{}/block/sdb",
|
||||
root_bus, addr_b
|
||||
);
|
||||
let matcher_b = ScsiBlockMatcher::new(&addr_b);
|
||||
let matcher_b = ScsiBlockMatcher::new(addr_b);
|
||||
|
||||
assert!(matcher_a.is_match(&uev_a));
|
||||
assert!(matcher_b.is_match(&uev_b));
|
||||
|
||||
@@ -65,6 +65,10 @@ pub fn create_pci_root_bus_path() -> String {
|
||||
ret
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "s390x")]
|
||||
pub fn create_ccw_root_bus_path() -> String {
|
||||
String::from("/devices/css0")
|
||||
}
|
||||
// From https://www.kernel.org/doc/Documentation/acpi/namespace.txt
|
||||
// The Linux kernel's core ACPI subsystem creates struct acpi_device
|
||||
// objects for ACPI namespace objects representing devices, power resources
|
||||
|
||||
@@ -34,6 +34,8 @@ use std::process::exit;
|
||||
use std::sync::Arc;
|
||||
use tracing::{instrument, span};
|
||||
|
||||
#[cfg(target_arch = "s390x")]
|
||||
mod ccw;
|
||||
mod config;
|
||||
mod console;
|
||||
mod device;
|
||||
@@ -52,6 +54,7 @@ mod test_utils;
|
||||
mod uevent;
|
||||
mod util;
|
||||
mod version;
|
||||
mod watcher;
|
||||
|
||||
use mount::{cgroups_mount, general_mount};
|
||||
use sandbox::Sandbox;
|
||||
@@ -299,7 +302,7 @@ async fn start_sandbox(
|
||||
}
|
||||
|
||||
// Initialize unique sandbox structure.
|
||||
let s = Sandbox::new(&logger).context("Failed to create sandbox")?;
|
||||
let s = Sandbox::new(logger).context("Failed to create sandbox")?;
|
||||
if init_mode {
|
||||
s.rtnl.handle_localhost().await?;
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ fn update_guest_metrics() {
|
||||
Ok(kernel_stats) => {
|
||||
set_gauge_vec_cpu_time(&GUEST_CPU_TIME, "total", &kernel_stats.total);
|
||||
for (i, cpu_time) in kernel_stats.cpu_time.iter().enumerate() {
|
||||
set_gauge_vec_cpu_time(&GUEST_CPU_TIME, format!("{}", i).as_str(), &cpu_time);
|
||||
set_gauge_vec_cpu_time(&GUEST_CPU_TIME, format!("{}", i).as_str(), cpu_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,13 +6,16 @@
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::CString;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::iter;
|
||||
use std::os::unix::fs::{MetadataExt, PermissionsExt};
|
||||
|
||||
use std::path::Path;
|
||||
use std::ptr::null;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use libc::{c_void, mount};
|
||||
@@ -20,8 +23,6 @@ use nix::mount::{self, MsFlags};
|
||||
use nix::unistd::Gid;
|
||||
|
||||
use regex::Regex;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader};
|
||||
|
||||
use crate::device::{
|
||||
get_scsi_device_name, get_virtio_blk_pci_device_name, online_device, wait_for_pmem_device,
|
||||
@@ -30,6 +31,8 @@ use crate::linux_abi::*;
|
||||
use crate::pci;
|
||||
use crate::protocols::agent::Storage;
|
||||
use crate::Sandbox;
|
||||
#[cfg(target_arch = "s390x")]
|
||||
use crate::{ccw, device::get_virtio_blk_ccw_device_name};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use slog::Logger;
|
||||
use tracing::instrument;
|
||||
@@ -37,11 +40,13 @@ use tracing::instrument;
|
||||
pub const DRIVER_9P_TYPE: &str = "9p";
|
||||
pub const DRIVER_VIRTIOFS_TYPE: &str = "virtio-fs";
|
||||
pub const DRIVER_BLK_TYPE: &str = "blk";
|
||||
pub const DRIVER_BLK_CCW_TYPE: &str = "blk-ccw";
|
||||
pub const DRIVER_MMIO_BLK_TYPE: &str = "mmioblk";
|
||||
pub const DRIVER_SCSI_TYPE: &str = "scsi";
|
||||
pub const DRIVER_NVDIMM_TYPE: &str = "nvdimm";
|
||||
pub const DRIVER_EPHEMERAL_TYPE: &str = "ephemeral";
|
||||
pub const DRIVER_LOCAL_TYPE: &str = "local";
|
||||
pub const DRIVER_WATCHABLE_BIND_TYPE: &str = "watchable-bind";
|
||||
|
||||
pub const TYPE_ROOTFS: &str = "rootfs";
|
||||
|
||||
@@ -132,7 +137,7 @@ lazy_static! {
|
||||
];
|
||||
}
|
||||
|
||||
pub const STORAGE_HANDLER_LIST: [&str; 8] = [
|
||||
pub const STORAGE_HANDLER_LIST: &[&str] = &[
|
||||
DRIVER_BLK_TYPE,
|
||||
DRIVER_9P_TYPE,
|
||||
DRIVER_VIRTIOFS_TYPE,
|
||||
@@ -141,6 +146,7 @@ pub const STORAGE_HANDLER_LIST: [&str; 8] = [
|
||||
DRIVER_LOCAL_TYPE,
|
||||
DRIVER_SCSI_TYPE,
|
||||
DRIVER_NVDIMM_TYPE,
|
||||
DRIVER_WATCHABLE_BIND_TYPE,
|
||||
];
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -276,7 +282,7 @@ async fn ephemeral_storage_handler(
|
||||
fs::set_permissions(&storage.mount_point, permission)?;
|
||||
}
|
||||
} else {
|
||||
common_storage_handler(logger, &storage)?;
|
||||
common_storage_handler(logger, storage)?;
|
||||
}
|
||||
|
||||
Ok("".to_string())
|
||||
@@ -386,6 +392,31 @@ async fn virtio_blk_storage_handler(
|
||||
common_storage_handler(logger, &storage)
|
||||
}
|
||||
|
||||
// virtio_blk_ccw_storage_handler handles storage for the blk-ccw driver (s390x)
|
||||
#[cfg(target_arch = "s390x")]
|
||||
#[instrument]
|
||||
async fn virtio_blk_ccw_storage_handler(
|
||||
logger: &Logger,
|
||||
storage: &Storage,
|
||||
sandbox: Arc<Mutex<Sandbox>>,
|
||||
) -> Result<String> {
|
||||
let mut storage = storage.clone();
|
||||
let ccw_device = ccw::Device::from_str(&storage.source)?;
|
||||
let dev_path = get_virtio_blk_ccw_device_name(&sandbox, &ccw_device).await?;
|
||||
storage.source = dev_path;
|
||||
common_storage_handler(logger, &storage)
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "s390x"))]
|
||||
#[instrument]
|
||||
async fn virtio_blk_ccw_storage_handler(
|
||||
_: &Logger,
|
||||
_: &Storage,
|
||||
_: Arc<Mutex<Sandbox>>,
|
||||
) -> Result<String> {
|
||||
Err(anyhow!("CCW is only supported on s390x"))
|
||||
}
|
||||
|
||||
// virtio_scsi_storage_handler handles the storage for scsi driver.
|
||||
#[instrument]
|
||||
async fn virtio_scsi_storage_handler(
|
||||
@@ -425,6 +456,20 @@ async fn nvdimm_storage_handler(
|
||||
common_storage_handler(logger, &storage)
|
||||
}
|
||||
|
||||
async fn bind_watcher_storage_handler(
|
||||
logger: &Logger,
|
||||
storage: &Storage,
|
||||
sandbox: Arc<Mutex<Sandbox>>,
|
||||
) -> Result<()> {
|
||||
let mut locked = sandbox.lock().await;
|
||||
let container_id = locked.id.clone();
|
||||
|
||||
locked
|
||||
.bind_watcher
|
||||
.add_container(container_id, iter::once(storage.clone()), logger)
|
||||
.await
|
||||
}
|
||||
|
||||
// mount_storage performs the mount described by the storage structure.
|
||||
#[instrument]
|
||||
fn mount_storage(logger: &Logger, storage: &Storage) -> Result<()> {
|
||||
@@ -478,7 +523,7 @@ fn mount_storage(logger: &Logger, storage: &Storage) -> Result<()> {
|
||||
|
||||
/// Looks for `mount_point` entry in the /proc/mounts.
|
||||
#[instrument]
|
||||
fn is_mounted(mount_point: &str) -> Result<bool> {
|
||||
pub fn is_mounted(mount_point: &str) -> Result<bool> {
|
||||
let mount_point = mount_point.trim_end_matches('/');
|
||||
let found = fs::metadata(mount_point).is_ok()
|
||||
// Looks through /proc/mounts and check if the mount exists
|
||||
@@ -504,8 +549,12 @@ fn parse_mount_flags_and_options(options_vec: Vec<&str>) -> (MsFlags, String) {
|
||||
if !opt.is_empty() {
|
||||
match FLAGS.get(opt) {
|
||||
Some(x) => {
|
||||
let (_, f) = *x;
|
||||
flags |= f;
|
||||
let (clear, f) = *x;
|
||||
if clear {
|
||||
flags &= !f;
|
||||
} else {
|
||||
flags |= f;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if !options.is_empty() {
|
||||
@@ -540,6 +589,9 @@ pub async fn add_storages(
|
||||
|
||||
let res = match handler_name.as_str() {
|
||||
DRIVER_BLK_TYPE => virtio_blk_storage_handler(&logger, &storage, sandbox.clone()).await,
|
||||
DRIVER_BLK_CCW_TYPE => {
|
||||
virtio_blk_ccw_storage_handler(&logger, &storage, sandbox.clone()).await
|
||||
}
|
||||
DRIVER_9P_TYPE => virtio9p_storage_handler(&logger, &storage, sandbox.clone()).await,
|
||||
DRIVER_VIRTIOFS_TYPE => {
|
||||
virtiofs_storage_handler(&logger, &storage, sandbox.clone()).await
|
||||
@@ -555,6 +607,11 @@ pub async fn add_storages(
|
||||
virtio_scsi_storage_handler(&logger, &storage, sandbox.clone()).await
|
||||
}
|
||||
DRIVER_NVDIMM_TYPE => nvdimm_storage_handler(&logger, &storage, sandbox.clone()).await,
|
||||
DRIVER_WATCHABLE_BIND_TYPE => {
|
||||
bind_watcher_storage_handler(&logger, &storage, sandbox.clone()).await?;
|
||||
// Don't register watch mounts, they're handled separately by the watcher.
|
||||
Ok(String::new())
|
||||
}
|
||||
_ => {
|
||||
return Err(anyhow!(
|
||||
"Failed to find the storage handler {}",
|
||||
@@ -769,19 +826,21 @@ pub fn remove_mounts(mounts: &[String]) -> Result<()> {
|
||||
#[instrument]
|
||||
fn ensure_destination_exists(destination: &str, fs_type: &str) -> Result<()> {
|
||||
let d = Path::new(destination);
|
||||
if !d.exists() {
|
||||
let dir = d
|
||||
.parent()
|
||||
.ok_or_else(|| anyhow!("mount destination {} doesn't exist", destination))?;
|
||||
if !dir.exists() {
|
||||
fs::create_dir_all(dir).context(format!("create dir all failed on {:?}", dir))?;
|
||||
}
|
||||
if d.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
let dir = d
|
||||
.parent()
|
||||
.ok_or_else(|| anyhow!("mount destination {} doesn't exist", destination))?;
|
||||
|
||||
if !dir.exists() {
|
||||
fs::create_dir_all(dir).context(format!("create dir all {:?}", dir))?;
|
||||
}
|
||||
|
||||
if fs_type != "bind" || d.is_dir() {
|
||||
fs::create_dir_all(d).context(format!("create dir all failed on {:?}", d))?;
|
||||
fs::create_dir_all(d).context(format!("create dir all {:?}", d))?;
|
||||
} else {
|
||||
fs::OpenOptions::new().create(true).open(d)?;
|
||||
fs::File::create(d).context(format!("create file {:?}", d))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -807,6 +866,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{skip_if_not_root, skip_loop_if_not_root, skip_loop_if_root};
|
||||
use libc::umount;
|
||||
use std::fs::metadata;
|
||||
use std::fs::File;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Write;
|
||||
@@ -1044,8 +1104,8 @@ mod tests {
|
||||
|
||||
// Create an actual mount
|
||||
let bare_mount = BareMount::new(
|
||||
&mnt_src_filename,
|
||||
&mnt_dest_filename,
|
||||
mnt_src_filename,
|
||||
mnt_dest_filename,
|
||||
"bind",
|
||||
MsFlags::MS_BIND,
|
||||
"",
|
||||
@@ -1214,7 +1274,7 @@ mod tests {
|
||||
let logger = slog::Logger::root(drain, o!());
|
||||
let result = get_cgroup_mounts(&logger, "", true);
|
||||
|
||||
assert_eq!(true, result.is_ok());
|
||||
assert!(result.is_ok());
|
||||
let result = result.unwrap();
|
||||
assert_eq!(1, result.len());
|
||||
assert_eq!(result[0].fstype, "cgroup2");
|
||||
@@ -1382,4 +1442,39 @@ mod tests {
|
||||
assert!(mounts[1].eq(&cg_devices_mount), "{}", msg);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ensure_destination_exists() {
|
||||
let dir = tempdir().expect("failed to create tmpdir");
|
||||
|
||||
let mut testfile = dir.into_path();
|
||||
testfile.push("testfile");
|
||||
|
||||
let result = ensure_destination_exists(testfile.to_str().unwrap(), "bind");
|
||||
|
||||
assert!(result.is_ok());
|
||||
assert!(testfile.exists());
|
||||
|
||||
let result = ensure_destination_exists(testfile.to_str().unwrap(), "bind");
|
||||
assert!(result.is_ok());
|
||||
|
||||
let meta = metadata(testfile).unwrap();
|
||||
|
||||
assert!(meta.is_file());
|
||||
|
||||
let dir = tempdir().expect("failed to create tmpdir");
|
||||
let mut testdir = dir.into_path();
|
||||
testdir.push("testdir");
|
||||
|
||||
let result = ensure_destination_exists(testdir.to_str().unwrap(), "ext4");
|
||||
assert!(result.is_ok());
|
||||
assert!(testdir.exists());
|
||||
|
||||
let result = ensure_destination_exists(testdir.to_str().unwrap(), "ext4");
|
||||
assert!(result.is_ok());
|
||||
|
||||
//let meta = metadata(testdir.to_str().unwrap()).unwrap();
|
||||
let meta = metadata(testdir).unwrap();
|
||||
assert!(meta.is_dir());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ impl Namespace {
|
||||
|
||||
let new_thread = tokio::spawn(async move {
|
||||
if let Err(err) = || -> Result<()> {
|
||||
let origin_ns_path = get_current_thread_ns_path(&ns_type.get());
|
||||
let origin_ns_path = get_current_thread_ns_path(ns_type.get());
|
||||
|
||||
File::open(Path::new(&origin_ns_path))?;
|
||||
|
||||
@@ -121,8 +121,12 @@ impl Namespace {
|
||||
let mut flags = MsFlags::empty();
|
||||
|
||||
if let Some(x) = FLAGS.get("rbind") {
|
||||
let (_, f) = *x;
|
||||
flags |= f;
|
||||
let (clear, f) = *x;
|
||||
if clear {
|
||||
flags &= !f;
|
||||
} else {
|
||||
flags |= f;
|
||||
}
|
||||
};
|
||||
|
||||
let bare_mount = BareMount::new(source, destination, "none", flags, "", &logger);
|
||||
|
||||
@@ -82,8 +82,8 @@ impl Handle {
|
||||
|
||||
// Add new ip addresses from request
|
||||
for ip_address in &iface.IPAddresses {
|
||||
let ip = IpAddr::from_str(&ip_address.get_address())?;
|
||||
let mask = u8::from_str_radix(ip_address.get_mask(), 10)?;
|
||||
let ip = IpAddr::from_str(ip_address.get_address())?;
|
||||
let mask = ip_address.get_mask().parse::<u8>()?;
|
||||
|
||||
self.add_addresses(link.index(), std::iter::once(IpNetwork::new(ip, mask)?))
|
||||
.await?;
|
||||
@@ -512,7 +512,7 @@ impl Handle {
|
||||
.and_then(|addr| if addr.is_empty() { None } else { Some(addr) }) // Make sure it's not empty
|
||||
.ok_or(nix::Error::Sys(nix::errno::Errno::EINVAL))?;
|
||||
|
||||
let ip = IpAddr::from_str(&ip_address)
|
||||
let ip = IpAddr::from_str(ip_address)
|
||||
.map_err(|e| anyhow!("Failed to parse IP {}: {:?}", ip_address, e))?;
|
||||
|
||||
// Import rtnetlink objects that make sense only for this function
|
||||
|
||||
@@ -127,16 +127,11 @@ mod tests {
|
||||
// call do_setup_guest_dns
|
||||
let result = do_setup_guest_dns(logger, dns.clone(), src_filename, dst_filename);
|
||||
|
||||
assert_eq!(
|
||||
true,
|
||||
result.is_ok(),
|
||||
"result should be ok, but {:?}",
|
||||
result
|
||||
);
|
||||
assert!(result.is_ok(), "result should be ok, but {:?}", result);
|
||||
|
||||
// get content of /etc/resolv.conf
|
||||
let content = fs::read_to_string(dst_filename);
|
||||
assert_eq!(true, content.is_ok());
|
||||
assert!(content.is_ok());
|
||||
let content = content.unwrap();
|
||||
|
||||
let expected_dns: Vec<&str> = content.split('\n').collect();
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use crate::pci;
|
||||
use async_trait::async_trait;
|
||||
use rustjail::{pipestream::PipeStream, process::StreamType};
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt, ReadHalf};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use ttrpc::{
|
||||
@@ -20,8 +23,9 @@ use anyhow::{anyhow, Context, Result};
|
||||
use oci::{LinuxNamespace, Root, Spec};
|
||||
use protobuf::{RepeatedField, SingularPtrField};
|
||||
use protocols::agent::{
|
||||
AgentDetails, CopyFileRequest, GuestDetailsResponse, Interfaces, Metrics, OOMEvent,
|
||||
ReadStreamResponse, Routes, StatsContainerResponse, WaitProcessResponse, WriteStreamResponse,
|
||||
AddSwapRequest, AgentDetails, CopyFileRequest, GuestDetailsResponse, Interfaces, Metrics,
|
||||
OOMEvent, ReadStreamResponse, Routes, StatsContainerResponse, WaitProcessResponse,
|
||||
WriteStreamResponse,
|
||||
};
|
||||
use protocols::empty::Empty;
|
||||
use protocols::health::{
|
||||
@@ -40,7 +44,7 @@ use nix::sys::stat;
|
||||
use nix::unistd::{self, Pid};
|
||||
use rustjail::process::ProcessOperations;
|
||||
|
||||
use crate::device::{add_devices, rescan_pci_bus, update_device_cgroup};
|
||||
use crate::device::{add_devices, pcipath_to_sysfs, rescan_pci_bus, update_device_cgroup};
|
||||
use crate::linux_abi::*;
|
||||
use crate::metrics::get_metrics;
|
||||
use crate::mount::{add_storages, remove_mounts, BareMount, STORAGE_HANDLER_LIST};
|
||||
@@ -51,7 +55,15 @@ use crate::sandbox::Sandbox;
|
||||
use crate::version::{AGENT_VERSION, API_VERSION};
|
||||
use crate::AGENT_CONFIG;
|
||||
|
||||
use libc::{self, c_ushort, pid_t, winsize, TIOCSWINSZ};
|
||||
use crate::trace_rpc_call;
|
||||
use crate::tracer::extract_carrier_from_ttrpc;
|
||||
use opentelemetry::global;
|
||||
use tracing::span;
|
||||
use tracing_opentelemetry::OpenTelemetrySpanExt;
|
||||
|
||||
use tracing::instrument;
|
||||
|
||||
use libc::{self, c_char, c_ushort, pid_t, winsize, TIOCSWINSZ};
|
||||
use std::convert::TryFrom;
|
||||
use std::fs;
|
||||
use std::os::unix::prelude::PermissionsExt;
|
||||
@@ -74,7 +86,7 @@ macro_rules! sl {
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AgentService {
|
||||
sandbox: Arc<Mutex<Sandbox>>,
|
||||
}
|
||||
@@ -97,6 +109,7 @@ fn verify_cid(id: &str) -> Result<()> {
|
||||
}
|
||||
|
||||
impl AgentService {
|
||||
#[instrument]
|
||||
async fn do_create_container(
|
||||
&self,
|
||||
req: protocols::agent::CreateContainerRequest,
|
||||
@@ -177,7 +190,7 @@ impl AgentService {
|
||||
let p = if oci.process.is_some() {
|
||||
Process::new(
|
||||
&sl!(),
|
||||
&oci.process.as_ref().unwrap(),
|
||||
oci.process.as_ref().unwrap(),
|
||||
cid.as_str(),
|
||||
true,
|
||||
pipe_size,
|
||||
@@ -196,6 +209,7 @@ impl AgentService {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
async fn do_start_container(&self, req: protocols::agent::StartContainerRequest) -> Result<()> {
|
||||
let cid = req.container_id;
|
||||
|
||||
@@ -221,6 +235,7 @@ impl AgentService {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
async fn do_remove_container(
|
||||
&self,
|
||||
req: protocols::agent::RemoveContainerRequest,
|
||||
@@ -232,7 +247,7 @@ impl AgentService {
|
||||
// Find the sandbox storage used by this container
|
||||
let mounts = sandbox.container_mounts.get(&cid);
|
||||
if let Some(mounts) = mounts {
|
||||
remove_mounts(&mounts)?;
|
||||
remove_mounts(mounts)?;
|
||||
|
||||
for m in mounts.iter() {
|
||||
if sandbox.storages.get(m).is_some() {
|
||||
@@ -253,11 +268,14 @@ impl AgentService {
|
||||
if req.timeout == 0 {
|
||||
let s = Arc::clone(&self.sandbox);
|
||||
let mut sandbox = s.lock().await;
|
||||
let ctr = sandbox
|
||||
.get_container(&cid)
|
||||
.ok_or_else(|| anyhow!("Invalid container id"))?;
|
||||
|
||||
ctr.destroy().await?;
|
||||
sandbox.bind_watcher.remove_container(&cid).await;
|
||||
|
||||
sandbox
|
||||
.get_container(&cid)
|
||||
.ok_or_else(|| anyhow!("Invalid container id"))?
|
||||
.destroy()
|
||||
.await?;
|
||||
|
||||
remove_container_resources(&mut sandbox)?;
|
||||
|
||||
@@ -273,6 +291,7 @@ impl AgentService {
|
||||
let mut sandbox = s.lock().await;
|
||||
if let Some(ctr) = sandbox.get_container(&cid2) {
|
||||
ctr.destroy().await.unwrap();
|
||||
sandbox.bind_watcher.remove_container(&cid2).await;
|
||||
tx.send(1).unwrap();
|
||||
};
|
||||
});
|
||||
@@ -298,6 +317,7 @@ impl AgentService {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
async fn do_exec_process(&self, req: protocols::agent::ExecProcessRequest) -> Result<()> {
|
||||
let cid = req.container_id.clone();
|
||||
let exec_id = req.exec_id.clone();
|
||||
@@ -326,6 +346,7 @@ impl AgentService {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
async fn do_signal_process(&self, req: protocols::agent::SignalProcessRequest) -> Result<()> {
|
||||
let cid = req.container_id.clone();
|
||||
let eid = req.exec_id.clone();
|
||||
@@ -360,6 +381,7 @@ impl AgentService {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
async fn do_wait_process(
|
||||
&self,
|
||||
req: protocols::agent::WaitProcessRequest,
|
||||
@@ -509,9 +531,10 @@ impl AgentService {
|
||||
impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
async fn create_container(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::CreateContainerRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "create_container", req);
|
||||
match self.do_create_container(req).await {
|
||||
Err(e) => Err(ttrpc_error(ttrpc::Code::INTERNAL, e.to_string())),
|
||||
Ok(_) => Ok(Empty::new()),
|
||||
@@ -520,9 +543,10 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn start_container(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::StartContainerRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "start_container", req);
|
||||
match self.do_start_container(req).await {
|
||||
Err(e) => Err(ttrpc_error(ttrpc::Code::INTERNAL, e.to_string())),
|
||||
Ok(_) => Ok(Empty::new()),
|
||||
@@ -531,9 +555,10 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn remove_container(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::RemoveContainerRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "remove_container", req);
|
||||
match self.do_remove_container(req).await {
|
||||
Err(e) => Err(ttrpc_error(ttrpc::Code::INTERNAL, e.to_string())),
|
||||
Ok(_) => Ok(Empty::new()),
|
||||
@@ -542,9 +567,10 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn exec_process(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::ExecProcessRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "exec_process", req);
|
||||
match self.do_exec_process(req).await {
|
||||
Err(e) => Err(ttrpc_error(ttrpc::Code::INTERNAL, e.to_string())),
|
||||
Ok(_) => Ok(Empty::new()),
|
||||
@@ -553,9 +579,10 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn signal_process(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::SignalProcessRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "signal_process", req);
|
||||
match self.do_signal_process(req).await {
|
||||
Err(e) => Err(ttrpc_error(ttrpc::Code::INTERNAL, e.to_string())),
|
||||
Ok(_) => Ok(Empty::new()),
|
||||
@@ -564,9 +591,10 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn wait_process(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::WaitProcessRequest,
|
||||
) -> ttrpc::Result<WaitProcessResponse> {
|
||||
trace_rpc_call!(ctx, "wait_process", req);
|
||||
self.do_wait_process(req)
|
||||
.await
|
||||
.map_err(|e| ttrpc_error(ttrpc::Code::INTERNAL, e.to_string()))
|
||||
@@ -574,9 +602,10 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn update_container(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::UpdateContainerRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "update_container", req);
|
||||
let cid = req.container_id.clone();
|
||||
let res = req.resources;
|
||||
|
||||
@@ -608,9 +637,10 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn stats_container(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::StatsContainerRequest,
|
||||
) -> ttrpc::Result<StatsContainerResponse> {
|
||||
trace_rpc_call!(ctx, "stats_container", req);
|
||||
let cid = req.container_id;
|
||||
let s = Arc::clone(&self.sandbox);
|
||||
let mut sandbox = s.lock().await;
|
||||
@@ -628,14 +658,15 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn pause_container(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::PauseContainerRequest,
|
||||
) -> ttrpc::Result<protocols::empty::Empty> {
|
||||
trace_rpc_call!(ctx, "pause_container", req);
|
||||
let cid = req.get_container_id();
|
||||
let s = Arc::clone(&self.sandbox);
|
||||
let mut sandbox = s.lock().await;
|
||||
|
||||
let ctr = sandbox.get_container(&cid).ok_or_else(|| {
|
||||
let ctr = sandbox.get_container(cid).ok_or_else(|| {
|
||||
ttrpc_error(
|
||||
ttrpc::Code::INVALID_ARGUMENT,
|
||||
"invalid container id".to_string(),
|
||||
@@ -650,14 +681,15 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn resume_container(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::ResumeContainerRequest,
|
||||
) -> ttrpc::Result<protocols::empty::Empty> {
|
||||
trace_rpc_call!(ctx, "resume_container", req);
|
||||
let cid = req.get_container_id();
|
||||
let s = Arc::clone(&self.sandbox);
|
||||
let mut sandbox = s.lock().await;
|
||||
|
||||
let ctr = sandbox.get_container(&cid).ok_or_else(|| {
|
||||
let ctr = sandbox.get_container(cid).ok_or_else(|| {
|
||||
ttrpc_error(
|
||||
ttrpc::Code::INVALID_ARGUMENT,
|
||||
"invalid container id".to_string(),
|
||||
@@ -702,9 +734,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn close_stdin(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::CloseStdinRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "close_stdin", req);
|
||||
|
||||
let cid = req.container_id.clone();
|
||||
let eid = req.exec_id;
|
||||
let s = Arc::clone(&self.sandbox);
|
||||
@@ -736,9 +770,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn tty_win_resize(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::TtyWinResizeRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "tty_win_resize", req);
|
||||
|
||||
let cid = req.container_id.clone();
|
||||
let eid = req.exec_id.clone();
|
||||
let s = Arc::clone(&self.sandbox);
|
||||
@@ -774,9 +810,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn update_interface(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::UpdateInterfaceRequest,
|
||||
) -> ttrpc::Result<Interface> {
|
||||
trace_rpc_call!(ctx, "update_interface", req);
|
||||
|
||||
let interface = req.interface.into_option().ok_or_else(|| {
|
||||
ttrpc_error(
|
||||
ttrpc::Code::INVALID_ARGUMENT,
|
||||
@@ -799,9 +837,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn update_routes(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::UpdateRoutesRequest,
|
||||
) -> ttrpc::Result<Routes> {
|
||||
trace_rpc_call!(ctx, "update_routes", req);
|
||||
|
||||
let new_routes = req
|
||||
.routes
|
||||
.into_option()
|
||||
@@ -837,9 +877,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn list_interfaces(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
_req: protocols::agent::ListInterfacesRequest,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::ListInterfacesRequest,
|
||||
) -> ttrpc::Result<Interfaces> {
|
||||
trace_rpc_call!(ctx, "list_interfaces", req);
|
||||
|
||||
let list = self
|
||||
.sandbox
|
||||
.lock()
|
||||
@@ -862,9 +904,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn list_routes(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
_req: protocols::agent::ListRoutesRequest,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::ListRoutesRequest,
|
||||
) -> ttrpc::Result<Routes> {
|
||||
trace_rpc_call!(ctx, "list_routes", req);
|
||||
|
||||
let list = self
|
||||
.sandbox
|
||||
.lock()
|
||||
@@ -899,9 +943,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn create_sandbox(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::CreateSandboxRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "create_sandbox", req);
|
||||
|
||||
{
|
||||
let sandbox = self.sandbox.clone();
|
||||
let mut s = sandbox.lock().await;
|
||||
@@ -962,9 +1008,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn destroy_sandbox(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
_req: protocols::agent::DestroySandboxRequest,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::DestroySandboxRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "destroy_sandbox", req);
|
||||
|
||||
let s = Arc::clone(&self.sandbox);
|
||||
let mut sandbox = s.lock().await;
|
||||
// destroy all containers, clean up, notify agent to exit
|
||||
@@ -981,9 +1029,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn add_arp_neighbors(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::AddARPNeighborsRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "add_arp_neighbors", req);
|
||||
|
||||
let neighs = req
|
||||
.neighbors
|
||||
.into_option()
|
||||
@@ -1013,11 +1063,12 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn online_cpu_mem(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::OnlineCPUMemRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
let s = Arc::clone(&self.sandbox);
|
||||
let sandbox = s.lock().await;
|
||||
trace_rpc_call!(ctx, "online_cpu_mem", req);
|
||||
|
||||
sandbox
|
||||
.online_cpu_memory(&req)
|
||||
@@ -1028,9 +1079,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn reseed_random_dev(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::ReseedRandomDevRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "reseed_random_dev", req);
|
||||
|
||||
random::reseed_rng(req.data.as_slice())
|
||||
.map_err(|e| ttrpc_error(ttrpc::Code::INTERNAL, e.to_string()))?;
|
||||
|
||||
@@ -1039,9 +1092,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn get_guest_details(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::GuestDetailsRequest,
|
||||
) -> ttrpc::Result<GuestDetailsResponse> {
|
||||
trace_rpc_call!(ctx, "get_guest_details", req);
|
||||
|
||||
info!(sl!(), "get guest details!");
|
||||
let mut resp = GuestDetailsResponse::new();
|
||||
// to get memory block size
|
||||
@@ -1065,9 +1120,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn mem_hotplug_by_probe(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::MemHotplugByProbeRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "mem_hotplug_by_probe", req);
|
||||
|
||||
do_mem_hotplug_by_probe(&req.memHotplugProbeAddr)
|
||||
.map_err(|e| ttrpc_error(ttrpc::Code::INTERNAL, e.to_string()))?;
|
||||
|
||||
@@ -1076,9 +1133,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn set_guest_date_time(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::SetGuestDateTimeRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "set_guest_date_time", req);
|
||||
|
||||
do_set_guest_date_time(req.Sec, req.Usec)
|
||||
.map_err(|e| ttrpc_error(ttrpc::Code::INTERNAL, e.to_string()))?;
|
||||
|
||||
@@ -1087,9 +1146,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn copy_file(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::CopyFileRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "copy_file", req);
|
||||
|
||||
do_copy_file(&req).map_err(|e| ttrpc_error(ttrpc::Code::INTERNAL, e.to_string()))?;
|
||||
|
||||
Ok(Empty::new())
|
||||
@@ -1097,9 +1158,11 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
async fn get_metrics(
|
||||
&self,
|
||||
_ctx: &TtrpcContext,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::GetMetricsRequest,
|
||||
) -> ttrpc::Result<Metrics> {
|
||||
trace_rpc_call!(ctx, "get_metrics", req);
|
||||
|
||||
match get_metrics(&req) {
|
||||
Err(e) => Err(ttrpc_error(ttrpc::Code::INTERNAL, e.to_string())),
|
||||
Ok(s) => {
|
||||
@@ -1133,6 +1196,18 @@ impl protocols::agent_ttrpc::AgentService for AgentService {
|
||||
|
||||
Err(ttrpc_error(ttrpc::Code::INTERNAL, ""))
|
||||
}
|
||||
|
||||
async fn add_swap(
|
||||
&self,
|
||||
ctx: &TtrpcContext,
|
||||
req: protocols::agent::AddSwapRequest,
|
||||
) -> ttrpc::Result<Empty> {
|
||||
trace_rpc_call!(ctx, "add_swap", req);
|
||||
|
||||
do_add_swap(&req).map_err(|e| ttrpc_error(ttrpc::Code::INTERNAL, e.to_string()))?;
|
||||
|
||||
Ok(Empty::new())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -1482,6 +1557,56 @@ fn do_copy_file(req: &CopyFileRequest) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn path_name_lookup<P: std::clone::Clone + AsRef<Path> + std::fmt::Debug>(
|
||||
path: P,
|
||||
lookup: &str,
|
||||
) -> Result<(PathBuf, String)> {
|
||||
for entry in fs::read_dir(path.clone())? {
|
||||
let entry = entry?;
|
||||
if let Some(name) = entry.path().file_name() {
|
||||
if let Some(name) = name.to_str() {
|
||||
if Some(0) == name.find(lookup) {
|
||||
return Ok((entry.path(), name.to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(anyhow!("cannot get {} dir in {:?}", lookup, path))
|
||||
}
|
||||
|
||||
fn do_add_swap(req: &AddSwapRequest) -> Result<()> {
|
||||
// re-scan PCI bus
|
||||
// looking for hidden devices
|
||||
rescan_pci_bus().context("Could not rescan PCI bus")?;
|
||||
|
||||
let mut slots = Vec::new();
|
||||
for slot in &req.PCIPath {
|
||||
slots.push(pci::Slot::new(*slot as u8)?);
|
||||
}
|
||||
let pcipath = pci::Path::new(slots)?;
|
||||
let root_bus_sysfs = format!("{}{}", SYSFS_DIR, create_pci_root_bus_path());
|
||||
let sysfs_rel_path = format!(
|
||||
"{}{}",
|
||||
root_bus_sysfs,
|
||||
pcipath_to_sysfs(&root_bus_sysfs, &pcipath)?
|
||||
);
|
||||
let (mut virtio_path, _) = path_name_lookup(sysfs_rel_path, "virtio")?;
|
||||
virtio_path.push("block");
|
||||
let (_, dev_name) = path_name_lookup(virtio_path, "vd")?;
|
||||
let dev_name = format!("/dev/{}", dev_name);
|
||||
|
||||
let c_str = CString::new(dev_name)?;
|
||||
let ret = unsafe { libc::swapon(c_str.as_ptr() as *const c_char, 0) };
|
||||
if ret != 0 {
|
||||
return Err(anyhow!(
|
||||
"libc::swapon get error {}",
|
||||
io::Error::last_os_error()
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Setup container bundle under CONTAINER_BASE, which is cleaned up
|
||||
// before removing a container.
|
||||
// - bundle path is /<CONTAINER_BASE>/<cid>/
|
||||
|
||||
@@ -9,6 +9,7 @@ use crate::namespace::Namespace;
|
||||
use crate::netlink::Handle;
|
||||
use crate::network::Network;
|
||||
use crate::uevent::{Uevent, UeventMatcher};
|
||||
use crate::watcher::BindWatcher;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use libc::pid_t;
|
||||
use oci::{Hook, Hooks};
|
||||
@@ -54,6 +55,7 @@ pub struct Sandbox {
|
||||
pub hooks: Option<Hooks>,
|
||||
pub event_rx: Arc<Mutex<Receiver<String>>>,
|
||||
pub event_tx: Option<Sender<String>>,
|
||||
pub bind_watcher: BindWatcher,
|
||||
}
|
||||
|
||||
impl Sandbox {
|
||||
@@ -85,6 +87,7 @@ impl Sandbox {
|
||||
hooks: None,
|
||||
event_rx,
|
||||
event_tx: Some(tx),
|
||||
bind_watcher: BindWatcher::new(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -181,7 +184,6 @@ impl Sandbox {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
pub fn add_container(&mut self, c: LinuxContainer) {
|
||||
self.containers.insert(c.id.clone(), c);
|
||||
}
|
||||
@@ -210,12 +212,10 @@ impl Sandbox {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
pub fn get_container(&mut self, id: &str) -> Option<&mut LinuxContainer> {
|
||||
self.containers.get_mut(id)
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
pub fn find_process(&mut self, pid: pid_t) -> Option<&mut Process> {
|
||||
for (_, c) in self.containers.iter_mut() {
|
||||
if c.processes.get(&pid).is_some() {
|
||||
@@ -272,7 +272,7 @@ impl Sandbox {
|
||||
ctr.cgroup_manager
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.update_cpuset_path(guest_cpuset.as_str(), &container_cpust)?;
|
||||
.update_cpuset_path(guest_cpuset.as_str(), container_cpust)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -461,7 +461,7 @@ mod tests {
|
||||
use tempfile::Builder;
|
||||
|
||||
fn bind_mount(src: &str, dst: &str, logger: &Logger) -> Result<(), Error> {
|
||||
let baremount = BareMount::new(src, dst, "bind", MsFlags::MS_BIND, "", &logger);
|
||||
let baremount = BareMount::new(src, dst, "bind", MsFlags::MS_BIND, "", logger);
|
||||
baremount.mount()
|
||||
}
|
||||
|
||||
@@ -474,7 +474,7 @@ mod tests {
|
||||
let tmpdir_path = tmpdir.path().to_str().unwrap();
|
||||
|
||||
// Add a new sandbox storage
|
||||
let new_storage = s.set_sandbox_storage(&tmpdir_path);
|
||||
let new_storage = s.set_sandbox_storage(tmpdir_path);
|
||||
|
||||
// Check the reference counter
|
||||
let ref_count = s.storages[tmpdir_path];
|
||||
@@ -483,11 +483,11 @@ mod tests {
|
||||
"Invalid refcount, got {} expected 1.",
|
||||
ref_count
|
||||
);
|
||||
assert_eq!(new_storage, true);
|
||||
assert!(new_storage);
|
||||
|
||||
// Use the existing sandbox storage
|
||||
let new_storage = s.set_sandbox_storage(&tmpdir_path);
|
||||
assert_eq!(new_storage, false, "Should be false as already exists.");
|
||||
let new_storage = s.set_sandbox_storage(tmpdir_path);
|
||||
assert!(!new_storage, "Should be false as already exists.");
|
||||
|
||||
// Since we are using existing storage, the reference counter
|
||||
// should be 2 by now.
|
||||
@@ -527,7 +527,7 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
assert!(
|
||||
s.remove_sandbox_storage(&srcdir_path).is_err(),
|
||||
s.remove_sandbox_storage(srcdir_path).is_err(),
|
||||
"Expect Err as the directory i not a mountpoint"
|
||||
);
|
||||
|
||||
@@ -556,7 +556,6 @@ mod tests {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[allow(unused_assignments)]
|
||||
async fn unset_and_remove_sandbox_storage() {
|
||||
skip_if_not_root!();
|
||||
|
||||
@@ -587,10 +586,10 @@ mod tests {
|
||||
|
||||
assert!(bind_mount(srcdir_path, destdir_path, &logger).is_ok());
|
||||
|
||||
assert_eq!(s.set_sandbox_storage(&destdir_path), true);
|
||||
assert!(s.unset_and_remove_sandbox_storage(&destdir_path).is_ok());
|
||||
assert!(s.set_sandbox_storage(destdir_path));
|
||||
assert!(s.unset_and_remove_sandbox_storage(destdir_path).is_ok());
|
||||
|
||||
let mut other_dir_str = String::new();
|
||||
let other_dir_str;
|
||||
{
|
||||
// Create another folder in a separate scope to ensure that is
|
||||
// deleted
|
||||
@@ -601,7 +600,7 @@ mod tests {
|
||||
let other_dir_path = other_dir.path().to_str().unwrap();
|
||||
other_dir_str = other_dir_path.to_string();
|
||||
|
||||
assert_eq!(s.set_sandbox_storage(&other_dir_path), true);
|
||||
assert!(s.set_sandbox_storage(other_dir_path));
|
||||
}
|
||||
|
||||
assert!(s.unset_and_remove_sandbox_storage(&other_dir_str).is_err());
|
||||
@@ -615,17 +614,15 @@ mod tests {
|
||||
let storage_path = "/tmp/testEphe";
|
||||
|
||||
// Add a new sandbox storage
|
||||
assert_eq!(s.set_sandbox_storage(&storage_path), true);
|
||||
assert!(s.set_sandbox_storage(storage_path));
|
||||
// Use the existing sandbox storage
|
||||
assert_eq!(
|
||||
s.set_sandbox_storage(&storage_path),
|
||||
false,
|
||||
assert!(
|
||||
!s.set_sandbox_storage(storage_path),
|
||||
"Expects false as the storage is not new."
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
s.unset_sandbox_storage(&storage_path).unwrap(),
|
||||
false,
|
||||
assert!(
|
||||
!s.unset_sandbox_storage(storage_path).unwrap(),
|
||||
"Expects false as there is still a storage."
|
||||
);
|
||||
|
||||
@@ -637,9 +634,8 @@ mod tests {
|
||||
ref_count
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
s.unset_sandbox_storage(&storage_path).unwrap(),
|
||||
true,
|
||||
assert!(
|
||||
s.unset_sandbox_storage(storage_path).unwrap(),
|
||||
"Expects true as there is still a storage."
|
||||
);
|
||||
|
||||
@@ -655,7 +651,7 @@ mod tests {
|
||||
// If no container is using the sandbox storage, the reference
|
||||
// counter for it should not exist.
|
||||
assert!(
|
||||
s.unset_sandbox_storage(&storage_path).is_err(),
|
||||
s.unset_sandbox_storage(storage_path).is_err(),
|
||||
"Expects false as the reference counter should no exist."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#[cfg(test)]
|
||||
mod test_utils {
|
||||
#[macro_export]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! skip_if_root {
|
||||
() => {
|
||||
if nix::unistd::Uid::effective().is_root() {
|
||||
@@ -18,7 +17,6 @@ mod test_utils {
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! skip_if_not_root {
|
||||
() => {
|
||||
if !nix::unistd::Uid::effective().is_root() {
|
||||
@@ -29,7 +27,6 @@ mod test_utils {
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! skip_loop_if_root {
|
||||
($msg:expr) => {
|
||||
if nix::unistd::Uid::effective().is_root() {
|
||||
@@ -44,7 +41,6 @@ mod test_utils {
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! skip_loop_if_not_root {
|
||||
($msg:expr) => {
|
||||
if !nix::unistd::Uid::effective().is_root() {
|
||||
|
||||
@@ -5,14 +5,17 @@
|
||||
|
||||
use crate::config::AgentConfig;
|
||||
use anyhow::Result;
|
||||
use opentelemetry::sdk::propagation::TraceContextPropagator;
|
||||
use opentelemetry::{global, sdk::trace::Config, trace::TracerProvider};
|
||||
use slog::{info, o, Logger};
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
use tracing_opentelemetry::OpenTelemetryLayer;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::Registry;
|
||||
use ttrpc::r#async::TtrpcContext;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum TraceType {
|
||||
@@ -63,7 +66,7 @@ pub fn setup_tracing(name: &'static str, logger: &Logger, _agent_cfg: &AgentConf
|
||||
let config = Config::default();
|
||||
|
||||
let builder = opentelemetry::sdk::trace::TracerProvider::builder()
|
||||
.with_simple_exporter(exporter)
|
||||
.with_batch_exporter(exporter, opentelemetry::runtime::TokioCurrentThread)
|
||||
.with_config(config);
|
||||
|
||||
let provider = builder.build();
|
||||
@@ -81,6 +84,8 @@ pub fn setup_tracing(name: &'static str, logger: &Logger, _agent_cfg: &AgentConf
|
||||
|
||||
tracing::subscriber::set_global_default(subscriber)?;
|
||||
|
||||
global::set_text_map_propagator(TraceContextPropagator::new());
|
||||
|
||||
info!(logger, "tracing setup");
|
||||
|
||||
Ok(())
|
||||
@@ -89,3 +94,29 @@ pub fn setup_tracing(name: &'static str, logger: &Logger, _agent_cfg: &AgentConf
|
||||
pub fn end_tracing() {
|
||||
global::shutdown_tracer_provider();
|
||||
}
|
||||
|
||||
pub fn extract_carrier_from_ttrpc(ttrpc_context: &TtrpcContext) -> HashMap<String, String> {
|
||||
let mut carrier = HashMap::new();
|
||||
for (k, v) in &ttrpc_context.metadata {
|
||||
carrier.insert(k.clone(), v.join(","));
|
||||
}
|
||||
|
||||
carrier
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! trace_rpc_call {
|
||||
($ctx: ident, $name:literal, $req: ident) => {
|
||||
// extract context from request context
|
||||
let parent_context = global::get_text_map_propagator(|propagator| {
|
||||
propagator.extract(&extract_carrier_from_ttrpc($ctx))
|
||||
});
|
||||
|
||||
// generate tracing span
|
||||
let rpc_span = span!(tracing::Level::INFO, $name, "mod"="rpc.rs", req=?$req);
|
||||
|
||||
// assign parent span from external context
|
||||
rpc_span.set_parent(parent_context);
|
||||
let _enter = rpc_span.enter();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -87,14 +87,14 @@ impl Uevent {
|
||||
sb.uevent_map.insert(self.devpath.clone(), self.clone());
|
||||
|
||||
// Notify watchers that are interested in the udev event.
|
||||
for watch in &mut sb.uevent_watchers {
|
||||
sb.uevent_watchers.iter_mut().for_each(move |watch| {
|
||||
if let Some((matcher, _)) = watch {
|
||||
if matcher.is_match(&self) {
|
||||
if matcher.is_match(self) {
|
||||
let (_, sender) = watch.take().unwrap();
|
||||
let _ = sender.send(self.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
@@ -114,7 +114,7 @@ pub async fn wait_for_uevent(
|
||||
let mut sb = sandbox.lock().await;
|
||||
for uev in sb.uevent_map.values() {
|
||||
if matcher.is_match(uev) {
|
||||
info!(sl!(), "Device {:?} found in pci device map", uev);
|
||||
info!(sl!(), "Device {:?} found in device map", uev);
|
||||
return Ok(uev.clone());
|
||||
}
|
||||
}
|
||||
@@ -221,15 +221,17 @@ pub(crate) fn spawn_test_watcher(sandbox: Arc<Mutex<Sandbox>>, uev: Uevent) {
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
let mut sb = sandbox.lock().await;
|
||||
for w in &mut sb.uevent_watchers {
|
||||
if let Some((matcher, _)) = w {
|
||||
let uev = uev.clone();
|
||||
sb.uevent_watchers.iter_mut().for_each(move |watch| {
|
||||
if let Some((matcher, _)) = watch {
|
||||
if matcher.is_match(&uev) {
|
||||
let (_, sender) = w.take().unwrap();
|
||||
let _ = sender.send(uev);
|
||||
let (_, sender) = watch.take().unwrap();
|
||||
let _ = sender.send(uev.clone());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
drop(sb); // unlock
|
||||
}
|
||||
});
|
||||
|
||||
998
src/agent/src/watcher.rs
Normal file
998
src/agent/src/watcher.rs
Normal file
@@ -0,0 +1,998 @@
|
||||
// Copyright (c) 2021 Apple Inc.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#![allow(clippy::unknown_clippy_lints)]
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use std::time::SystemTime;
|
||||
|
||||
use anyhow::{ensure, Context, Result};
|
||||
use async_recursion::async_recursion;
|
||||
use nix::mount::{umount, MsFlags};
|
||||
use slog::{debug, error, info, warn, Logger};
|
||||
use thiserror::Error;
|
||||
use tokio::fs;
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::task;
|
||||
use tokio::time::{self, Duration};
|
||||
|
||||
use crate::mount::BareMount;
|
||||
use crate::protocols::agent as protos;
|
||||
|
||||
/// The maximum number of file system entries agent will watch for each mount.
|
||||
const MAX_ENTRIES_PER_STORAGE: usize = 16;
|
||||
|
||||
/// The maximum size of a watchable mount in bytes.
|
||||
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
|
||||
const WATCH_MOUNT_POINT_PATH: &str = "/run/kata-containers/shared/containers/watchable/";
|
||||
|
||||
/// Represents a single watched storage entry which may have multiple files to watch.
|
||||
#[derive(Default, Debug, Clone)]
|
||||
struct Storage {
|
||||
/// A mount point without inotify capabilities.
|
||||
source_mount_point: PathBuf,
|
||||
|
||||
/// The target mount point, where the watched files will be copied/mirrored
|
||||
/// when being changed, added or removed. This will be subdirectory of a tmpfs
|
||||
target_mount_point: PathBuf,
|
||||
|
||||
/// Flag to indicate that the Storage should be watched. Storage will be watched until
|
||||
/// the source becomes too large, either in number of files (>16) or total size (>1MB).
|
||||
watch: bool,
|
||||
|
||||
/// The list of files to watch from the source mount point and updated in the target one.
|
||||
watched_files: HashMap<PathBuf, SystemTime>,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum WatcherError {
|
||||
#[error(
|
||||
"Too many file system entries within to watch within: {mnt} ({count} must be < {})",
|
||||
MAX_ENTRIES_PER_STORAGE
|
||||
)]
|
||||
MountTooManyFiles { count: usize, mnt: String },
|
||||
|
||||
#[error(
|
||||
"Mount too large to watch: {mnt} ({size} must be < {})",
|
||||
MAX_SIZE_PER_WATCHABLE_MOUNT
|
||||
)]
|
||||
MountTooLarge { size: u64, mnt: String },
|
||||
}
|
||||
|
||||
impl Drop for Storage {
|
||||
fn drop(&mut self) {
|
||||
if !&self.watch {
|
||||
// If we weren't watching this storage entry, it means that a bind mount
|
||||
// was created.
|
||||
let _ = umount(&self.target_mount_point);
|
||||
}
|
||||
let _ = std::fs::remove_dir_all(&self.target_mount_point);
|
||||
}
|
||||
}
|
||||
|
||||
impl Storage {
|
||||
async fn new(storage: protos::Storage) -> Result<Storage> {
|
||||
let entry = Storage {
|
||||
source_mount_point: PathBuf::from(&storage.source),
|
||||
target_mount_point: PathBuf::from(&storage.mount_point),
|
||||
watch: true,
|
||||
watched_files: HashMap::new(),
|
||||
};
|
||||
Ok(entry)
|
||||
}
|
||||
|
||||
async fn update_target(&self, logger: &Logger, source_path: impl AsRef<Path>) -> Result<()> {
|
||||
let source_file_path = source_path.as_ref();
|
||||
|
||||
let dest_file_path = if self.source_mount_point.is_file() {
|
||||
// Simple file to file copy
|
||||
// Assume target mount is a file path
|
||||
self.target_mount_point.clone()
|
||||
} else {
|
||||
let dest_file_path = self.make_target_path(&source_file_path)?;
|
||||
|
||||
if let Some(path) = dest_file_path.parent() {
|
||||
debug!(logger, "Creating destination directory: {}", path.display());
|
||||
fs::create_dir_all(path)
|
||||
.await
|
||||
.with_context(|| format!("Unable to mkdir all for {}", path.display()))?;
|
||||
}
|
||||
|
||||
dest_file_path
|
||||
};
|
||||
|
||||
debug!(
|
||||
logger,
|
||||
"Copy from {} to {}",
|
||||
source_file_path.display(),
|
||||
dest_file_path.display()
|
||||
);
|
||||
fs::copy(&source_file_path, &dest_file_path)
|
||||
.await
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"Copy from {} to {} failed",
|
||||
source_file_path.display(),
|
||||
dest_file_path.display()
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn scan(&mut self, logger: &Logger) -> Result<usize> {
|
||||
debug!(logger, "Scanning for changes");
|
||||
|
||||
let mut remove_list = Vec::new();
|
||||
let mut updated_files: Vec<PathBuf> = Vec::new();
|
||||
|
||||
// Remove deleted files for tracking list
|
||||
self.watched_files.retain(|st, _| {
|
||||
if st.exists() {
|
||||
true
|
||||
} else {
|
||||
remove_list.push(st.to_path_buf());
|
||||
false
|
||||
}
|
||||
});
|
||||
|
||||
// Delete from target
|
||||
for path in remove_list {
|
||||
// File has been deleted, remove it from target mount
|
||||
let target = self.make_target_path(path)?;
|
||||
debug!(logger, "Removing file from mount: {}", target.display());
|
||||
let _ = fs::remove_file(target).await;
|
||||
}
|
||||
|
||||
// Scan new & changed files
|
||||
self.scan_path(
|
||||
logger,
|
||||
self.source_mount_point.clone().as_path(),
|
||||
&mut updated_files,
|
||||
)
|
||||
.await
|
||||
.with_context(|| "Scan path failed")?;
|
||||
|
||||
// Update identified files:
|
||||
for path in &updated_files {
|
||||
if let Err(e) = self.update_target(logger, path.as_path()).await {
|
||||
error!(logger, "failure in update_target: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(updated_files.len())
|
||||
}
|
||||
|
||||
#[async_recursion]
|
||||
async fn scan_path(
|
||||
&mut self,
|
||||
logger: &Logger,
|
||||
path: &Path,
|
||||
update_list: &mut Vec<PathBuf>,
|
||||
) -> Result<u64> {
|
||||
let mut size: u64 = 0;
|
||||
debug!(logger, "Scanning path: {}", path.display());
|
||||
|
||||
if path.is_file() {
|
||||
let metadata = path
|
||||
.metadata()
|
||||
.with_context(|| format!("Failed to query metadata for: {}", path.display()))?;
|
||||
|
||||
let modified = metadata
|
||||
.modified()
|
||||
.with_context(|| format!("Failed to get modified date for: {}", path.display()))?;
|
||||
|
||||
size += metadata.len();
|
||||
|
||||
ensure!(
|
||||
self.watched_files.len() <= MAX_ENTRIES_PER_STORAGE,
|
||||
WatcherError::MountTooManyFiles {
|
||||
count: self.watched_files.len(),
|
||||
mnt: self.source_mount_point.display().to_string()
|
||||
}
|
||||
);
|
||||
|
||||
// Insert will return old entry if any
|
||||
if let Some(old_st) = self.watched_files.insert(path.to_path_buf(), modified) {
|
||||
if modified > old_st {
|
||||
update_list.push(PathBuf::from(&path))
|
||||
}
|
||||
} else {
|
||||
// Storage just added, copy to target
|
||||
debug!(logger, "New entry: {}", path.display());
|
||||
update_list.push(PathBuf::from(&path))
|
||||
}
|
||||
} else {
|
||||
// Scan dir recursively
|
||||
let mut entries = fs::read_dir(path)
|
||||
.await
|
||||
.with_context(|| format!("Failed to read dir: {}", path.display()))?;
|
||||
|
||||
while let Some(entry) = entries.next_entry().await? {
|
||||
let path = entry.path();
|
||||
let res_size = self
|
||||
.scan_path(logger, path.as_path(), update_list)
|
||||
.await
|
||||
.with_context(|| format!("Unable to scan inner path: {}", path.display()))?;
|
||||
size += res_size;
|
||||
}
|
||||
}
|
||||
|
||||
ensure!(
|
||||
size <= MAX_SIZE_PER_WATCHABLE_MOUNT,
|
||||
WatcherError::MountTooLarge {
|
||||
size,
|
||||
mnt: self.source_mount_point.display().to_string()
|
||||
}
|
||||
);
|
||||
|
||||
Ok(size)
|
||||
}
|
||||
|
||||
fn make_target_path(&self, source_file_path: impl AsRef<Path>) -> Result<PathBuf> {
|
||||
let relative_path = source_file_path
|
||||
.as_ref()
|
||||
.strip_prefix(&self.source_mount_point)
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"Failed to strip prefix: {} - {}",
|
||||
source_file_path.as_ref().display().to_string(),
|
||||
&self.source_mount_point.display()
|
||||
)
|
||||
})?;
|
||||
|
||||
let dest_file_path = Path::new(&self.target_mount_point).join(relative_path);
|
||||
Ok(dest_file_path)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
struct SandboxStorages(Vec<Storage>);
|
||||
|
||||
impl SandboxStorages {
|
||||
async fn add(
|
||||
&mut self,
|
||||
list: impl IntoIterator<Item = protos::Storage>,
|
||||
|
||||
logger: &Logger,
|
||||
) -> Result<()> {
|
||||
for storage in list.into_iter() {
|
||||
let entry = Storage::new(storage)
|
||||
.await
|
||||
.with_context(|| "Failed to add storage")?;
|
||||
self.0.push(entry);
|
||||
}
|
||||
|
||||
// Perform initial copy
|
||||
self.check(logger)
|
||||
.await
|
||||
.with_context(|| "Failed to perform initial check")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn check(&mut self, logger: &Logger) -> Result<()> {
|
||||
for entry in self.0.iter_mut().filter(|e| e.watch) {
|
||||
if let Err(e) = entry.scan(logger).await {
|
||||
match e.downcast_ref::<WatcherError>() {
|
||||
Some(WatcherError::MountTooLarge { .. })
|
||||
| Some(WatcherError::MountTooManyFiles { .. }) => {
|
||||
//
|
||||
// If the mount we were watching is too large (bytes), or contains too many unique files,
|
||||
// we no longer want to watch. Instead, we'll attempt to create a bind mount and mark this storage
|
||||
// as non-watchable. if there's an error in creating bind mount, we'll continue watching.
|
||||
//
|
||||
// Ensure the target mount point exists:
|
||||
if !entry.target_mount_point.as_path().exists() {
|
||||
if entry.source_mount_point.as_path().is_dir() {
|
||||
fs::create_dir_all(entry.target_mount_point.as_path())
|
||||
.await
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"create dir for bindmount {:?}",
|
||||
entry.target_mount_point.as_path()
|
||||
)
|
||||
})?;
|
||||
} else {
|
||||
fs::File::create(entry.target_mount_point.as_path())
|
||||
.await
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"create file {:?}",
|
||||
entry.target_mount_point.as_path()
|
||||
)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
match BareMount::new(
|
||||
entry.source_mount_point.to_str().unwrap(),
|
||||
entry.target_mount_point.to_str().unwrap(),
|
||||
"bind",
|
||||
MsFlags::MS_BIND,
|
||||
"bind",
|
||||
logger,
|
||||
)
|
||||
.mount()
|
||||
{
|
||||
Ok(_) => {
|
||||
entry.watch = false;
|
||||
info!(logger, "watchable mount replaced with bind mount")
|
||||
}
|
||||
Err(e) => error!(logger, "unable to replace watchable: {:?}", e),
|
||||
}
|
||||
}
|
||||
_ => warn!(logger, "scan error: {:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles watchable mounts. The watcher will manage one or more mounts for one or more containers. For each
|
||||
/// mount that is added, the watcher will maintain a list of files to monitor, and periodically checks for new,
|
||||
/// removed or changed (modified date) files. When a change is identified, the watcher will either copy the new
|
||||
/// or updated file to a target mount point, or remove the removed file from the target mount point. All WatchableStorage
|
||||
/// target mount points are expected to reside within a single tmpfs, whose root is created by the BindWatcher.
|
||||
///
|
||||
/// This is a temporary workaround to handle config map updates until we get inotify on 9p/virtio-fs.
|
||||
/// More context on this:
|
||||
/// - https://github.com/kata-containers/runtime/issues/1505
|
||||
/// - https://github.com/kata-containers/kata-containers/issues/1879
|
||||
#[derive(Debug, Default)]
|
||||
pub struct BindWatcher {
|
||||
/// Container ID -> Vec of watched entries
|
||||
sandbox_storages: Arc<Mutex<HashMap<String, SandboxStorages>>>,
|
||||
watch_thread: Option<task::JoinHandle<()>>,
|
||||
}
|
||||
|
||||
impl Drop for BindWatcher {
|
||||
fn drop(&mut self) {
|
||||
self.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
impl BindWatcher {
|
||||
pub fn new() -> BindWatcher {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
pub async fn add_container(
|
||||
&mut self,
|
||||
id: String,
|
||||
mounts: impl IntoIterator<Item = protos::Storage>,
|
||||
logger: &Logger,
|
||||
) -> 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?;
|
||||
|
||||
// Spawn background thread to monitor changes
|
||||
self.watch_thread = Some(Self::spawn_watcher(
|
||||
logger.clone(),
|
||||
Arc::clone(&self.sandbox_storages),
|
||||
WATCH_INTERVAL_SECS,
|
||||
));
|
||||
}
|
||||
|
||||
self.sandbox_storages
|
||||
.lock()
|
||||
.await
|
||||
.entry(id)
|
||||
.or_insert_with(SandboxStorages::default)
|
||||
.add(mounts, logger)
|
||||
.await
|
||||
.with_context(|| "Failed to add container")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn remove_container(&self, id: &str) {
|
||||
self.sandbox_storages.lock().await.remove(id);
|
||||
}
|
||||
|
||||
fn spawn_watcher(
|
||||
logger: Logger,
|
||||
sandbox_storages: Arc<Mutex<HashMap<String, SandboxStorages>>>,
|
||||
interval_secs: u64,
|
||||
) -> tokio::task::JoinHandle<()> {
|
||||
tokio::spawn(async move {
|
||||
let mut interval = time::interval(Duration::from_secs(interval_secs));
|
||||
|
||||
loop {
|
||||
interval.tick().await;
|
||||
|
||||
debug!(&logger, "Looking for changed files");
|
||||
for (_, entries) in sandbox_storages.lock().await.iter_mut() {
|
||||
if let Err(err) = entries.check(&logger).await {
|
||||
// We don't fail background loop, but rather log error instead.
|
||||
warn!(logger, "Check failed: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn mount(&self, logger: &Logger) -> Result<()> {
|
||||
fs::create_dir_all(WATCH_MOUNT_POINT_PATH).await?;
|
||||
|
||||
BareMount::new(
|
||||
"tmpfs",
|
||||
WATCH_MOUNT_POINT_PATH,
|
||||
"tmpfs",
|
||||
MsFlags::empty(),
|
||||
"",
|
||||
logger,
|
||||
)
|
||||
.mount()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cleanup(&mut self) {
|
||||
if let Some(handle) = self.watch_thread.take() {
|
||||
// Stop our background thread
|
||||
handle.abort();
|
||||
}
|
||||
|
||||
let _ = umount(WATCH_MOUNT_POINT_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::mount::is_mounted;
|
||||
use crate::skip_if_not_root;
|
||||
use std::fs;
|
||||
use std::thread;
|
||||
|
||||
async fn create_test_storage(dir: &Path, id: &str) -> Result<(protos::Storage, PathBuf)> {
|
||||
let src_path = dir.join(format!("src{}", id));
|
||||
let src_filename = src_path.to_str().expect("failed to create src filename");
|
||||
let dest_path = dir.join(format!("dest{}", id));
|
||||
let dest_filename = dest_path.to_str().expect("failed to create dest filename");
|
||||
|
||||
std::fs::create_dir_all(src_filename).expect("failed to create path");
|
||||
|
||||
let storage = protos::Storage {
|
||||
source: src_filename.to_string(),
|
||||
mount_point: dest_filename.to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
Ok((storage, src_path))
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_watch_entries() {
|
||||
skip_if_not_root!();
|
||||
|
||||
// If there's an error with an entry, let's make sure it is removed, and that the
|
||||
// mount-destination behaves like a standard bind-mount.
|
||||
|
||||
// Create an entries vector with four storage objects: storage0,1,2,3.
|
||||
// 0th we'll have fail due to too many files before running a check
|
||||
// 1st will just have a single medium sized file, we'll keep it watchable throughout
|
||||
// 2nd will have a large file (<1MB), but we'll later make larger to make unwatchable
|
||||
// 3rd will have several files, and later we'll make unwatchable by having too many files.
|
||||
// We'll run check a couple of times to verify watchable is always watchable, and unwatchable bind mounts
|
||||
// match our expectations.
|
||||
let dir = tempfile::tempdir().expect("failed to create tempdir");
|
||||
|
||||
let (storage0, src0_path) = create_test_storage(dir.path(), "1")
|
||||
.await
|
||||
.expect("failed to create storage");
|
||||
let (storage1, src1_path) = create_test_storage(dir.path(), "2")
|
||||
.await
|
||||
.expect("failed to create storage");
|
||||
let (storage2, src2_path) = create_test_storage(dir.path(), "3")
|
||||
.await
|
||||
.expect("failed to create storage");
|
||||
let (storage3, src3_path) = create_test_storage(dir.path(), "4")
|
||||
.await
|
||||
.expect("failed to create storage");
|
||||
|
||||
// setup storage0: too many files
|
||||
for i in 1..21 {
|
||||
fs::write(src0_path.join(format!("{}.txt", i)), "original").unwrap();
|
||||
}
|
||||
|
||||
// setup storage1: two small files
|
||||
std::fs::File::create(src1_path.join("small.txt"))
|
||||
.unwrap()
|
||||
.set_len(10)
|
||||
.unwrap();
|
||||
fs::write(src1_path.join("foo.txt"), "original").unwrap();
|
||||
|
||||
// setup storage2: large file, but still watchable
|
||||
std::fs::File::create(src2_path.join("large.txt"))
|
||||
.unwrap()
|
||||
.set_len(MAX_SIZE_PER_WATCHABLE_MOUNT)
|
||||
.unwrap();
|
||||
|
||||
// setup storage3: many files, but still watchable
|
||||
for i in 1..MAX_ENTRIES_PER_STORAGE + 1 {
|
||||
fs::write(src3_path.join(format!("{}.txt", i)), "original").unwrap();
|
||||
}
|
||||
|
||||
let logger = slog::Logger::root(slog::Discard, o!());
|
||||
|
||||
let mut entries = SandboxStorages {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
entries
|
||||
.add(std::iter::once(storage0), &logger)
|
||||
.await
|
||||
.unwrap();
|
||||
entries
|
||||
.add(std::iter::once(storage1), &logger)
|
||||
.await
|
||||
.unwrap();
|
||||
entries
|
||||
.add(std::iter::once(storage2), &logger)
|
||||
.await
|
||||
.unwrap();
|
||||
entries
|
||||
.add(std::iter::once(storage3), &logger)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(entries.check(&logger).await.is_ok());
|
||||
// Check that there are four entries
|
||||
assert_eq!(entries.0.len(), 4);
|
||||
|
||||
//verify that storage 0 is no longer going to be watched, but 1,2,3 are
|
||||
assert!(!entries.0[0].watch);
|
||||
assert!(entries.0[1].watch);
|
||||
assert!(entries.0[2].watch);
|
||||
assert!(entries.0[3].watch);
|
||||
|
||||
assert_eq!(std::fs::read_dir(dir.path()).unwrap().count(), 8);
|
||||
|
||||
//verify target mount points contain expected number of entries:
|
||||
assert_eq!(
|
||||
std::fs::read_dir(entries.0[0].target_mount_point.as_path())
|
||||
.unwrap()
|
||||
.count(),
|
||||
20
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read_dir(entries.0[1].target_mount_point.as_path())
|
||||
.unwrap()
|
||||
.count(),
|
||||
2
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read_dir(entries.0[2].target_mount_point.as_path())
|
||||
.unwrap()
|
||||
.count(),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read_dir(entries.0[3].target_mount_point.as_path())
|
||||
.unwrap()
|
||||
.count(),
|
||||
MAX_ENTRIES_PER_STORAGE
|
||||
);
|
||||
|
||||
// Add two files to storage 0, verify it is updated without needing to run check:
|
||||
fs::write(src0_path.join("1.txt"), "updated").unwrap();
|
||||
fs::write(src0_path.join("foo.txt"), "new").unwrap();
|
||||
fs::write(src0_path.join("bar.txt"), "new").unwrap();
|
||||
assert_eq!(
|
||||
std::fs::read_dir(entries.0[0].target_mount_point.as_path())
|
||||
.unwrap()
|
||||
.count(),
|
||||
22
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read_to_string(&entries.0[0].target_mount_point.as_path().join("1.txt")).unwrap(),
|
||||
"updated"
|
||||
);
|
||||
|
||||
//
|
||||
// Prepare for second check: update mount sources
|
||||
//
|
||||
|
||||
// source 3 will become unwatchable
|
||||
fs::write(src3_path.join("foo.txt"), "updated").unwrap();
|
||||
|
||||
// source 2 will become unwatchable:
|
||||
std::fs::File::create(src2_path.join("small.txt"))
|
||||
.unwrap()
|
||||
.set_len(10)
|
||||
.unwrap();
|
||||
|
||||
// source 1: expect just an update
|
||||
fs::write(src1_path.join("foo.txt"), "updated").unwrap();
|
||||
|
||||
assert!(entries.check(&logger).await.is_ok());
|
||||
|
||||
// verify that only storage 1 is still watchable
|
||||
assert!(!entries.0[0].watch);
|
||||
assert!(entries.0[1].watch);
|
||||
assert!(!entries.0[2].watch);
|
||||
assert!(!entries.0[3].watch);
|
||||
|
||||
// Verify storage 1 was updated, and storage 2,3 are up to date despite no watch
|
||||
assert_eq!(
|
||||
std::fs::read_dir(entries.0[0].target_mount_point.as_path())
|
||||
.unwrap()
|
||||
.count(),
|
||||
22
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read_dir(entries.0[1].target_mount_point.as_path())
|
||||
.unwrap()
|
||||
.count(),
|
||||
2
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read_to_string(&entries.0[1].target_mount_point.as_path().join("foo.txt")).unwrap(),
|
||||
"updated"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
std::fs::read_dir(entries.0[2].target_mount_point.as_path())
|
||||
.unwrap()
|
||||
.count(),
|
||||
2
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read_dir(entries.0[3].target_mount_point.as_path())
|
||||
.unwrap()
|
||||
.count(),
|
||||
MAX_ENTRIES_PER_STORAGE + 1
|
||||
);
|
||||
|
||||
// verify that we can remove files as well, but that it isn't observed until check is run
|
||||
// for a watchable mount:
|
||||
fs::remove_file(src1_path.join("foo.txt")).unwrap();
|
||||
assert_eq!(
|
||||
std::fs::read_dir(entries.0[1].target_mount_point.as_path())
|
||||
.unwrap()
|
||||
.count(),
|
||||
2
|
||||
);
|
||||
assert!(entries.check(&logger).await.is_ok());
|
||||
assert_eq!(
|
||||
std::fs::read_dir(entries.0[1].target_mount_point.as_path())
|
||||
.unwrap()
|
||||
.count(),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn watch_directory_too_large() {
|
||||
let source_dir = tempfile::tempdir().unwrap();
|
||||
let dest_dir = tempfile::tempdir().unwrap();
|
||||
let mut entry = Storage::new(protos::Storage {
|
||||
source: source_dir.path().display().to_string(),
|
||||
mount_point: dest_dir.path().display().to_string(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let logger = slog::Logger::root(slog::Discard, o!());
|
||||
|
||||
// Create a file that is too large:
|
||||
std::fs::File::create(source_dir.path().join("big.txt"))
|
||||
.unwrap()
|
||||
.set_len(MAX_SIZE_PER_WATCHABLE_MOUNT + 1)
|
||||
.unwrap();
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
|
||||
// Expect to receive a MountTooLarge error
|
||||
match entry.scan(&logger).await {
|
||||
Ok(_) => panic!("expected error"),
|
||||
Err(e) => match e.downcast_ref::<WatcherError>() {
|
||||
Some(WatcherError::MountTooLarge { .. }) => {}
|
||||
_ => panic!("unexpected error"),
|
||||
},
|
||||
}
|
||||
fs::remove_file(source_dir.path().join("big.txt")).unwrap();
|
||||
|
||||
std::fs::File::create(source_dir.path().join("big.txt"))
|
||||
.unwrap()
|
||||
.set_len(MAX_SIZE_PER_WATCHABLE_MOUNT - 1)
|
||||
.unwrap();
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
|
||||
assert!(entry.scan(&logger).await.is_ok());
|
||||
|
||||
std::fs::File::create(source_dir.path().join("too-big.txt"))
|
||||
.unwrap()
|
||||
.set_len(2)
|
||||
.unwrap();
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
|
||||
// Expect to receive a MountTooLarge error
|
||||
match entry.scan(&logger).await {
|
||||
Ok(_) => panic!("expected error"),
|
||||
Err(e) => match e.downcast_ref::<WatcherError>() {
|
||||
Some(WatcherError::MountTooLarge { .. }) => {}
|
||||
_ => panic!("unexpected error"),
|
||||
},
|
||||
}
|
||||
|
||||
fs::remove_file(source_dir.path().join("big.txt")).unwrap();
|
||||
fs::remove_file(source_dir.path().join("too-big.txt")).unwrap();
|
||||
|
||||
// Up to 16 files should be okay:
|
||||
for i in 1..MAX_ENTRIES_PER_STORAGE + 1 {
|
||||
fs::write(source_dir.path().join(format!("{}.txt", i)), "original").unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(entry.scan(&logger).await.unwrap(), MAX_ENTRIES_PER_STORAGE);
|
||||
|
||||
// 17 files is too many:
|
||||
fs::write(source_dir.path().join("17.txt"), "updated").unwrap();
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
|
||||
// Expect to receive a MountTooManyFiles error
|
||||
match entry.scan(&logger).await {
|
||||
Ok(_) => panic!("expected error"),
|
||||
Err(e) => match e.downcast_ref::<WatcherError>() {
|
||||
Some(WatcherError::MountTooManyFiles { .. }) => {}
|
||||
_ => panic!("unexpected error"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn watch_directory() {
|
||||
// Prepare source directory:
|
||||
// ./tmp/1.txt
|
||||
// ./tmp/A/B/2.txt
|
||||
let source_dir = tempfile::tempdir().unwrap();
|
||||
fs::write(source_dir.path().join("1.txt"), "one").unwrap();
|
||||
fs::create_dir_all(source_dir.path().join("A/B")).unwrap();
|
||||
fs::write(source_dir.path().join("A/B/1.txt"), "two").unwrap();
|
||||
|
||||
let dest_dir = tempfile::tempdir().unwrap();
|
||||
|
||||
let mut entry = Storage::new(protos::Storage {
|
||||
source: source_dir.path().display().to_string(),
|
||||
mount_point: dest_dir.path().display().to_string(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let logger = slog::Logger::root(slog::Discard, o!());
|
||||
|
||||
assert_eq!(entry.scan(&logger).await.unwrap(), 2);
|
||||
|
||||
// Should copy no files since nothing is changed since last check
|
||||
assert_eq!(entry.scan(&logger).await.unwrap(), 0);
|
||||
|
||||
// Should copy 1 file
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
fs::write(source_dir.path().join("A/B/1.txt"), "updated").unwrap();
|
||||
assert_eq!(entry.scan(&logger).await.unwrap(), 1);
|
||||
assert_eq!(
|
||||
fs::read_to_string(dest_dir.path().join("A/B/1.txt")).unwrap(),
|
||||
"updated"
|
||||
);
|
||||
|
||||
// Should copy no new files after copy happened
|
||||
assert_eq!(entry.scan(&logger).await.unwrap(), 0);
|
||||
|
||||
// Update another file
|
||||
fs::write(source_dir.path().join("1.txt"), "updated").unwrap();
|
||||
assert_eq!(entry.scan(&logger).await.unwrap(), 1);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn watch_file() {
|
||||
let source_dir = tempfile::tempdir().unwrap();
|
||||
let source_file = source_dir.path().join("1.txt");
|
||||
|
||||
fs::write(&source_file, "one").unwrap();
|
||||
|
||||
let dest_dir = tempfile::tempdir().unwrap();
|
||||
let dest_file = dest_dir.path().join("1.txt");
|
||||
|
||||
let mut entry = Storage::new(protos::Storage {
|
||||
source: source_file.display().to_string(),
|
||||
mount_point: dest_file.display().to_string(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let logger = slog::Logger::root(slog::Discard, o!());
|
||||
|
||||
assert_eq!(entry.scan(&logger).await.unwrap(), 1);
|
||||
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
fs::write(&source_file, "two").unwrap();
|
||||
assert_eq!(entry.scan(&logger).await.unwrap(), 1);
|
||||
assert_eq!(fs::read_to_string(&dest_file).unwrap(), "two");
|
||||
assert_eq!(entry.scan(&logger).await.unwrap(), 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn delete_file() {
|
||||
let source_dir = tempfile::tempdir().unwrap();
|
||||
let source_file = source_dir.path().join("1.txt");
|
||||
fs::write(&source_file, "one").unwrap();
|
||||
|
||||
let dest_dir = tempfile::tempdir().unwrap();
|
||||
let target_file = dest_dir.path().join("1.txt");
|
||||
|
||||
let mut entry = Storage::new(protos::Storage {
|
||||
source: source_dir.path().display().to_string(),
|
||||
mount_point: dest_dir.path().display().to_string(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let logger = slog::Logger::root(slog::Discard, o!());
|
||||
|
||||
assert_eq!(entry.scan(&logger).await.unwrap(), 1);
|
||||
assert_eq!(entry.watched_files.len(), 1);
|
||||
|
||||
assert!(target_file.exists());
|
||||
assert!(entry.watched_files.contains_key(&source_file));
|
||||
|
||||
// Remove source file
|
||||
fs::remove_file(&source_file).unwrap();
|
||||
|
||||
assert_eq!(entry.scan(&logger).await.unwrap(), 0);
|
||||
|
||||
assert_eq!(entry.watched_files.len(), 0);
|
||||
assert!(!target_file.exists());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn make_target_path() {
|
||||
let source_dir = tempfile::tempdir().unwrap();
|
||||
let target_dir = tempfile::tempdir().unwrap();
|
||||
|
||||
let source_dir = source_dir.path();
|
||||
let target_dir = target_dir.path();
|
||||
|
||||
let entry = Storage::new(protos::Storage {
|
||||
source: source_dir.display().to_string(),
|
||||
mount_point: target_dir.display().to_string(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
entry.make_target_path(source_dir.join("1.txt")).unwrap(),
|
||||
target_dir.join("1.txt")
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
entry
|
||||
.make_target_path(source_dir.join("a/b/2.txt"))
|
||||
.unwrap(),
|
||||
target_dir.join("a/b/2.txt")
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn create_tmpfs() {
|
||||
skip_if_not_root!();
|
||||
|
||||
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());
|
||||
|
||||
watcher.cleanup();
|
||||
assert!(!is_mounted(WATCH_MOUNT_POINT_PATH).unwrap());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn spawn_thread() {
|
||||
skip_if_not_root!();
|
||||
|
||||
let source_dir = tempfile::tempdir().unwrap();
|
||||
fs::write(source_dir.path().join("1.txt"), "one").unwrap();
|
||||
|
||||
let dest_dir = tempfile::tempdir().unwrap();
|
||||
|
||||
let storage = protos::Storage {
|
||||
source: source_dir.path().display().to_string(),
|
||||
mount_point: dest_dir.path().display().to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let logger = slog::Logger::root(slog::Discard, o!());
|
||||
let mut watcher = BindWatcher::default();
|
||||
|
||||
watcher
|
||||
.add_container("test".into(), std::iter::once(storage), &logger)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
thread::sleep(Duration::from_secs(WATCH_INTERVAL_SECS));
|
||||
|
||||
let out = fs::read_to_string(dest_dir.path().join("1.txt")).unwrap();
|
||||
assert_eq!(out, "one");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn verify_container_cleanup_watching() {
|
||||
skip_if_not_root!();
|
||||
|
||||
let source_dir = tempfile::tempdir().unwrap();
|
||||
fs::write(source_dir.path().join("1.txt"), "one").unwrap();
|
||||
|
||||
let dest_dir = tempfile::tempdir().unwrap();
|
||||
|
||||
let storage = protos::Storage {
|
||||
source: source_dir.path().display().to_string(),
|
||||
mount_point: dest_dir.path().display().to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let logger = slog::Logger::root(slog::Discard, o!());
|
||||
let mut watcher = BindWatcher::default();
|
||||
|
||||
watcher
|
||||
.add_container("test".into(), std::iter::once(storage), &logger)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
thread::sleep(Duration::from_secs(WATCH_INTERVAL_SECS));
|
||||
|
||||
let out = fs::read_to_string(dest_dir.path().join("1.txt")).unwrap();
|
||||
assert!(dest_dir.path().exists());
|
||||
assert_eq!(out, "one");
|
||||
|
||||
watcher.remove_container("test").await;
|
||||
|
||||
thread::sleep(Duration::from_secs(WATCH_INTERVAL_SECS));
|
||||
assert!(!dest_dir.path().exists());
|
||||
|
||||
for i in 1..21 {
|
||||
fs::write(source_dir.path().join(format!("{}.txt", i)), "fluff").unwrap();
|
||||
}
|
||||
|
||||
// verify non-watched storage is cleaned up correctly
|
||||
let storage1 = protos::Storage {
|
||||
source: source_dir.path().display().to_string(),
|
||||
mount_point: dest_dir.path().display().to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
watcher
|
||||
.add_container("test".into(), std::iter::once(storage1), &logger)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
thread::sleep(Duration::from_secs(WATCH_INTERVAL_SECS));
|
||||
|
||||
assert!(dest_dir.path().exists());
|
||||
assert!(is_mounted(dest_dir.path().to_str().unwrap()).unwrap());
|
||||
|
||||
watcher.remove_container("test").await;
|
||||
|
||||
thread::sleep(Duration::from_secs(WATCH_INTERVAL_SECS));
|
||||
|
||||
assert!(!dest_dir.path().exists());
|
||||
assert!(!is_mounted(dest_dir.path().to_str().unwrap()).unwrap());
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user