mirror of
https://github.com/kata-containers/kata-containers.git
synced 2026-03-16 17:52:20 +00:00
Compare commits
4 Commits
3.21.0
...
sprt/test-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29e74892f4 | ||
|
|
5c5e2c68bc | ||
|
|
fd4f7638e5 | ||
|
|
a5641e27db |
3
.github/dependabot.yml
vendored
3
.github/dependabot.yml
vendored
@@ -66,9 +66,6 @@ updates:
|
||||
rustix:
|
||||
patterns:
|
||||
- rustix
|
||||
slab:
|
||||
patterns:
|
||||
- slab
|
||||
time:
|
||||
patterns:
|
||||
- time
|
||||
|
||||
2
.github/workflows/actionlint.yaml
vendored
2
.github/workflows/actionlint.yaml
vendored
@@ -2,7 +2,7 @@ name: Lint GHA workflows
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
|
||||
3
.github/workflows/basic-ci-amd64.yaml
vendored
3
.github/workflows/basic-ci-amd64.yaml
vendored
@@ -281,7 +281,10 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
vmm:
|
||||
- clh
|
||||
- qemu
|
||||
- dragonball
|
||||
- cloud-hypervisor
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
KATA_HYPERVISOR: ${{ matrix.vmm }}
|
||||
|
||||
23
.github/workflows/run-k8s-tests-on-amd64.yaml
vendored
23
.github/workflows/run-k8s-tests-on-amd64.yaml
vendored
@@ -30,7 +30,11 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
vmm:
|
||||
- clh #cloud-hypervisor
|
||||
- dragonball
|
||||
- fc #firecracker
|
||||
- qemu
|
||||
- cloud-hypervisor
|
||||
container_runtime:
|
||||
- containerd
|
||||
snapshotter:
|
||||
@@ -68,25 +72,6 @@ jobs:
|
||||
env:
|
||||
TARGET_BRANCH: ${{ inputs.target-branch }}
|
||||
|
||||
- name: Remove unnecessary directories to free up space
|
||||
run: |
|
||||
sudo rm -rf /usr/local/.ghcup
|
||||
sudo rm -rf /opt/hostedtoolcache/CodeQL
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf /usr/local/share/boost
|
||||
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
|
||||
sudo rm -rf /usr/lib/jvm
|
||||
sudo rm -rf /usr/share/swift
|
||||
sudo rm -rf /usr/local/share/powershell
|
||||
sudo rm -rf /usr/local/julia*
|
||||
sudo rm -rf /opt/az
|
||||
sudo rm -rf /usr/local/share/chromium
|
||||
sudo rm -rf /opt/microsoft
|
||||
sudo rm -rf /opt/google
|
||||
sudo rm -rf /usr/lib/firefox
|
||||
|
||||
- name: Configure CRI-O
|
||||
if: matrix.container_runtime == 'crio'
|
||||
run: bash tests/integration/kubernetes/gha-run.sh setup-crio
|
||||
|
||||
19
.github/workflows/run-kata-deploy-tests.yaml
vendored
19
.github/workflows/run-kata-deploy-tests.yaml
vendored
@@ -58,25 +58,6 @@ jobs:
|
||||
env:
|
||||
TARGET_BRANCH: ${{ inputs.target-branch }}
|
||||
|
||||
- name: Remove unnecessary directories to free up space
|
||||
run: |
|
||||
sudo rm -rf /usr/local/.ghcup
|
||||
sudo rm -rf /opt/hostedtoolcache/CodeQL
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf /usr/local/share/boost
|
||||
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
|
||||
sudo rm -rf /usr/lib/jvm
|
||||
sudo rm -rf /usr/share/swift
|
||||
sudo rm -rf /usr/local/share/powershell
|
||||
sudo rm -rf /usr/local/julia*
|
||||
sudo rm -rf /opt/az
|
||||
sudo rm -rf /usr/local/share/chromium
|
||||
sudo rm -rf /opt/microsoft
|
||||
sudo rm -rf /opt/google
|
||||
sudo rm -rf /usr/lib/firefox
|
||||
|
||||
- name: Deploy ${{ matrix.k8s }}
|
||||
run: bash tests/functional/kata-deploy/gha-run.sh deploy-k8s
|
||||
|
||||
|
||||
1
.github/workflows/zizmor.yaml
vendored
1
.github/workflows/zizmor.yaml
vendored
@@ -2,6 +2,7 @@ name: GHA security analysis
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
|
||||
permissions: {}
|
||||
|
||||
@@ -116,44 +116,33 @@ az network vnet subnet update \
|
||||
for NODE_NAME in $(kubectl get nodes -o jsonpath='{.items[*].metadata.name}'); do [[ "${NODE_NAME}" =~ 'worker' ]] && kubectl label node "${NODE_NAME}" node.kubernetes.io/worker=; done
|
||||
|
||||
# CAA artifacts
|
||||
if [[ -z "${CAA_TAG}" ]]; then
|
||||
if [[ -n "${CAA_IMAGE}" ]]; then
|
||||
echo "CAA_IMAGE (${CAA_IMAGE}) is set but CAA_TAG isn't, which is not supported. Please specify both or none"
|
||||
exit 1
|
||||
fi
|
||||
TAGS="$(curl https://quay.io/api/v1/repository/confidential-containers/cloud-api-adaptor/tag/?onlyActiveTags=true)"
|
||||
DIGEST=$(echo "${TAGS}" | jq -r '.tags[] | select(.name | contains("latest-amd64")) | .manifest_digest')
|
||||
CAA_TAG="$(echo "${TAGS}" | jq -r '.tags[] | select(.manifest_digest | contains("'"${DIGEST}"'")) | .name' | grep -v "latest")"
|
||||
fi
|
||||
if [[ -z "${CAA_IMAGE}" ]]; then
|
||||
CAA_IMAGE="quay.io/confidential-containers/cloud-api-adaptor"
|
||||
fi
|
||||
CAA_IMAGE="quay.io/confidential-containers/cloud-api-adaptor"
|
||||
TAGS="$(curl https://quay.io/api/v1/repository/confidential-containers/cloud-api-adaptor/tag/?onlyActiveTags=true)"
|
||||
DIGEST=$(echo "${TAGS}" | jq -r '.tags[] | select(.name | contains("latest-amd64")) | .manifest_digest')
|
||||
CAA_TAG="$(echo "${TAGS}" | jq -r '.tags[] | select(.manifest_digest | contains("'"${DIGEST}"'")) | .name' | grep -v "latest")"
|
||||
|
||||
# Get latest PP image
|
||||
if [[ -z "${PP_IMAGE_ID}" ]]; then
|
||||
SUCCESS_TIME=$(curl -s \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
"https://api.github.com/repos/confidential-containers/cloud-api-adaptor/actions/workflows/azure-nightly-build.yml/runs?status=success" \
|
||||
| jq -r '.workflow_runs[0].updated_at')
|
||||
PP_IMAGE_ID="/CommunityGalleries/cocopodvm-d0e4f35f-5530-4b9c-8596-112487cdea85/Images/podvm_image0/Versions/$(date -u -jf "%Y-%m-%dT%H:%M:%SZ" "${SUCCESS_TIME}" "+%Y.%m.%d" 2>/dev/null || date -d "${SUCCESS_TIME}" +%Y.%m.%d)"
|
||||
fi
|
||||
SUCCESS_TIME=$(curl -s \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
"https://api.github.com/repos/confidential-containers/cloud-api-adaptor/actions/workflows/azure-nightly-build.yml/runs?status=success" \
|
||||
| jq -r '.workflow_runs[0].updated_at')
|
||||
PP_IMAGE_ID="/CommunityGalleries/cocopodvm-d0e4f35f-5530-4b9c-8596-112487cdea85/Images/podvm_image0/Versions/$(date -u -jf "%Y-%m-%dT%H:%M:%SZ" "${SUCCESS_TIME}" "+%Y.%m.%d" 2>/dev/null || date -d "${SUCCESS_TIME}" +%Y.%m.%d)"
|
||||
|
||||
echo "AZURE_REGION=\"${AZURE_REGION}\""
|
||||
echo "PP_REGION=\"${PP_REGION}\""
|
||||
echo "AZURE_RESOURCE_GROUP=\"${AZURE_RESOURCE_GROUP}\""
|
||||
echo "PP_RESOURCE_GROUP=\"${PP_RESOURCE_GROUP}\""
|
||||
echo "PP_SUBNET_ID=\"${PP_SUBNET_ID}\""
|
||||
echo "CAA_IMAGE=\"${CAA_IMAGE}\""
|
||||
echo "CAA_TAG=\"${CAA_TAG}\""
|
||||
echo "PP_IMAGE_ID=\"${PP_IMAGE_ID}\""
|
||||
echo "AZURE_REGION: \"${AZURE_REGION}\""
|
||||
echo "PP_REGION: \"${PP_REGION}\""
|
||||
echo "AZURE_RESOURCE_GROUP: \"${AZURE_RESOURCE_GROUP}\""
|
||||
echo "PP_RESOURCE_GROUP: \"${PP_RESOURCE_GROUP}\""
|
||||
echo "PP_SUBNET_ID: \"${PP_SUBNET_ID}\""
|
||||
echo "CAA_TAG: \"${CAA_TAG}\""
|
||||
echo "PP_IMAGE_ID: \"${PP_IMAGE_ID}\""
|
||||
|
||||
# Clone and configure caa
|
||||
git clone --revision "${CAA_GIT_SHA:-main}" --depth 1 --no-checkout https://github.com/confidential-containers/cloud-api-adaptor.git
|
||||
git clone --depth 1 --no-checkout https://github.com/confidential-containers/cloud-api-adaptor.git
|
||||
pushd cloud-api-adaptor
|
||||
git sparse-checkout init --cone
|
||||
git sparse-checkout set src/cloud-api-adaptor/install/
|
||||
git checkout
|
||||
echo "CAA_GIT_SHA=\"$(git rev-parse HEAD)\""
|
||||
echo "CAA_GIT_SHA: \"$(git rev-parse HEAD)\""
|
||||
pushd src/cloud-api-adaptor
|
||||
cat <<EOF > install/overlays/azure/workload-identity.yaml
|
||||
apiVersion: apps/v1
|
||||
@@ -219,12 +208,12 @@ echo "AZURE_CLIENT_SECRET=${AZURE_CLIENT_SECRET}" >> install/overlays/azure/serv
|
||||
echo "AZURE_TENANT_ID=${AZURE_TENANT_ID}" >> install/overlays/azure/service-principal.env
|
||||
|
||||
# Deploy Operator
|
||||
git clone --revision "${OPERATOR_SHA:-main}" --depth 1 --no-checkout https://github.com/confidential-containers/operator
|
||||
git clone --depth 1 --no-checkout https://github.com/confidential-containers/operator
|
||||
pushd operator
|
||||
git sparse-checkout init --cone
|
||||
git sparse-checkout set "config/"
|
||||
git checkout
|
||||
echo "OPERATOR_SHA=\"$(git rev-parse HEAD)\""
|
||||
echo "OPERATOR_SHA: \"$(git rev-parse HEAD)\""
|
||||
oc apply -k "config/release"
|
||||
oc apply -k "config/samples/ccruntime/peer-pods"
|
||||
popd
|
||||
@@ -238,7 +227,7 @@ popd
|
||||
SECONDS=0
|
||||
( while [[ "${SECONDS}" -lt 360 ]]; do
|
||||
kubectl get runtimeclass | grep -q kata-remote && exit 0
|
||||
done; exit 1 ) || { echo "kata-remote runtimeclass not initialized in 60s"; kubectl -n confidential-containers-system get all; echo; echo "kubectl -n confidential-containers-system describe all"; kubectl -n confidential-containers-system describe all; echo; echo CAA; kubectl -n confidential-containers-system logs daemonset.apps/cloud-api-adaptor-daemonset; echo pre-install; kubectl -n confidential-containers-system logs daemonset.apps/cc-operator-pre-install-daemon; echo install; kubectl -n confidential-containers-system logs daemonset.apps/cc-operator-daemon-install; exit 1; }
|
||||
done; exit 1 ) || { echo "kata-remote runtimeclass not initialized in 60s"; kubectl -n confidential-containers-system get all; echo; echo CAA; kubectl -n confidential-containers-system logs daemonset.apps/cloud-api-adaptor-daemonset; echo pre-install; kubectl -n confidential-containers-system logs daemonset.apps/cc-operator-pre-install-daemon; echo install; kubectl -n confidential-containers-system logs daemonset.apps/cc-operator-daemon-install; exit 1; }
|
||||
|
||||
|
||||
################
|
||||
|
||||
@@ -32,24 +32,11 @@ Kubernetes users can encode in `base64` format their Policy documents, and add t
|
||||
|
||||
### Encode a Policy file
|
||||
|
||||
For example, the [`allow-all-except-exec-process.rego`](../../src/kata-opa/allow-all-except-exec-process.rego) sample policy file is different from the [default Policy](../../src/kata-opa/allow-all.rego) because it rejects any `ExecProcess` requests. To encode this policy file, you need to:
|
||||
- Embed the policy inside an init data struct
|
||||
- Compress
|
||||
- Base64 encode
|
||||
For example:
|
||||
For example, the [`allow-all-except-exec-process.rego`](../../src/kata-opa/allow-all-except-exec-process.rego) sample policy file is different from the [default Policy](../../src/kata-opa/allow-all.rego) because it rejects any `ExecProcess` requests. You can encode this policy file:
|
||||
|
||||
```bash
|
||||
$ STRING="$(< allow-all-except-exec-process.rego)"
|
||||
$ cat <<EOF | gzip -c | base64 -w0
|
||||
version = "0.1.0"
|
||||
algorithm = "sha256"
|
||||
|
||||
[data]
|
||||
"policy.rego" = '''
|
||||
$STRING
|
||||
'''
|
||||
EOF
|
||||
H4sIAAAAAAAAA42UTW/TQBCG7/4Vq/QQOCQKQXCo1ENIAkRqiGWnpBJCaGKP7RXrXTM7DnV/PRMiVUh07R582J3H8/XO7AnJa2fVjRrNpm+ms1EEpnSkuarPd76C+bv3oyj6lgPD92jUOKOzbkpYupEA4/E4ulJL13Sky4rVq+y1ms/mb9VWZ+S8K1iM1DgClijRlcBpvLqf3OoMrcfJJkfLutBI12rRQFbhZD6dCRfJ4SeUqOSz/OMSNopyLKA1rBZ5vkjiLyhBj458gr9a9KyubxRTi/9i6W9oQualcR5TzrUNElLZR20waCcExqWzDNoi9WMp2PzoHkLQSi7JdQPUJ+QtMuksWLQQu912fZK+BZHz7QolaRN0c6s9bywjFZBhL5W4lsPEFuvPjhvTlh+6mNwx2MudNdLDZXwnf4SYGFo/3O64NWZTy+SEgAQhT1lECQZKsHan4UgXLGUw+FWTzHjh0woIt661HGxJgh4xT0RoV6/w1IO19XAOKfJFTxmxva6DRQsX/12jIKBLC0Y0Er2DuUutxMM5nak9QaZt2cOwf4En1ww42nN3OK+w14/B4u+a/CWLesHWTYU1Eph+GS/w0470Y/1LcgDNA40/yKOMzw/tE7N+wOx/NwUYj9H5qf4DsX93tO4FAAA=
|
||||
$ base64 -w 0 allow-all-except-exec-process.rego
|
||||
cGFja2FnZSBhZ2VudF9wb2xpY3kKCmRlZmF1bHQgQWRkQVJQTmVpZ2hib3JzUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgQWRkU3dhcFJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IENsb3NlU3RkaW5SZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBDb3B5RmlsZVJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IENyZWF0ZUNvbnRhaW5lclJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IENyZWF0ZVNhbmRib3hSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBEZXN0cm95U2FuZGJveFJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IEdldE1ldHJpY3NSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBHZXRPT01FdmVudFJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IEd1ZXN0RGV0YWlsc1JlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IExpc3RJbnRlcmZhY2VzUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgTGlzdFJvdXRlc1JlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IE1lbUhvdHBsdWdCeVByb2JlUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgT25saW5lQ1BVTWVtUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgUGF1c2VDb250YWluZXJSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBQdWxsSW1hZ2VSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBSZWFkU3RyZWFtUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgUmVtb3ZlQ29udGFpbmVyUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgUmVtb3ZlU3RhbGVWaXJ0aW9mc1NoYXJlTW91bnRzUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgUmVzZWVkUmFuZG9tRGV2UmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgUmVzdW1lQ29udGFpbmVyUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgU2V0R3Vlc3REYXRlVGltZVJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IFNldFBvbGljeVJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IFNpZ25hbFByb2Nlc3NSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBTdGFydENvbnRhaW5lclJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IFN0YXJ0VHJhY2luZ1JlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IFN0YXRzQ29udGFpbmVyUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgU3RvcFRyYWNpbmdSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBUdHlXaW5SZXNpemVSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBVcGRhdGVDb250YWluZXJSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBVcGRhdGVFcGhlbWVyYWxNb3VudHNSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBVcGRhdGVJbnRlcmZhY2VSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBVcGRhdGVSb3V0ZXNSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBXYWl0UHJvY2Vzc1JlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IFdyaXRlU3RyZWFtUmVxdWVzdCA6PSB0cnVlCgpkZWZhdWx0IEV4ZWNQcm9jZXNzUmVxdWVzdCA6PSBmYWxzZQo=
|
||||
```
|
||||
|
||||
### Attach the Policy to a pod
|
||||
@@ -62,7 +49,7 @@ kind: Pod
|
||||
metadata:
|
||||
name: policy-exec-rejected
|
||||
annotations:
|
||||
io.katacontainers.config.hypervisor.cc_init_data: H4sIAAAAAAAAA42UTW/TQBCG7/4Vq/QQOCQKQXCo1ENIAkRqiGWnpBJCaGKP7RXrXTM7DnV/PRMiVUh07R582J3H8/XO7AnJa2fVjRrNpm+ms1EEpnSkuarPd76C+bv3oyj6lgPD92jUOKOzbkpYupEA4/E4ulJL13Sky4rVq+y1ms/mb9VWZ+S8K1iM1DgClijRlcBpvLqf3OoMrcfJJkfLutBI12rRQFbhZD6dCRfJ4SeUqOSz/OMSNopyLKA1rBZ5vkjiLyhBj458gr9a9KyubxRTi/9i6W9oQualcR5TzrUNElLZR20waCcExqWzDNoi9WMp2PzoHkLQSi7JdQPUJ+QtMuksWLQQu912fZK+BZHz7QolaRN0c6s9bywjFZBhL5W4lsPEFuvPjhvTlh+6mNwx2MudNdLDZXwnf4SYGFo/3O64NWZTy+SEgAQhT1lECQZKsHan4UgXLGUw+FWTzHjh0woIt661HGxJgh4xT0RoV6/w1IO19XAOKfJFTxmxva6DRQsX/12jIKBLC0Y0Er2DuUutxMM5nak9QaZt2cOwf4En1ww42nN3OK+w14/B4u+a/CWLesHWTYU1Eph+GS/w0470Y/1LcgDNA40/yKOMzw/tE7N+wOx/NwUYj9H5qf4DsX93tO4FAAA=
|
||||
io.katacontainers.config.agent.policy: cGFja2FnZSBhZ2VudF9wb2xpY3kKCmRlZmF1bHQgQWRkQVJQTmVpZ2hib3JzUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgQWRkU3dhcFJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IENsb3NlU3RkaW5SZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBDb3B5RmlsZVJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IENyZWF0ZUNvbnRhaW5lclJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IENyZWF0ZVNhbmRib3hSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBEZXN0cm95U2FuZGJveFJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IEdldE1ldHJpY3NSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBHZXRPT01FdmVudFJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IEd1ZXN0RGV0YWlsc1JlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IExpc3RJbnRlcmZhY2VzUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgTGlzdFJvdXRlc1JlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IE1lbUhvdHBsdWdCeVByb2JlUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgT25saW5lQ1BVTWVtUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgUGF1c2VDb250YWluZXJSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBQdWxsSW1hZ2VSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBSZWFkU3RyZWFtUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgUmVtb3ZlQ29udGFpbmVyUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgUmVtb3ZlU3RhbGVWaXJ0aW9mc1NoYXJlTW91bnRzUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgUmVzZWVkUmFuZG9tRGV2UmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgUmVzdW1lQ29udGFpbmVyUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgU2V0R3Vlc3REYXRlVGltZVJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IFNldFBvbGljeVJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IFNpZ25hbFByb2Nlc3NSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBTdGFydENvbnRhaW5lclJlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IFN0YXJ0VHJhY2luZ1JlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IFN0YXRzQ29udGFpbmVyUmVxdWVzdCA6PSB0cnVlCmRlZmF1bHQgU3RvcFRyYWNpbmdSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBUdHlXaW5SZXNpemVSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBVcGRhdGVDb250YWluZXJSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBVcGRhdGVFcGhlbWVyYWxNb3VudHNSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBVcGRhdGVJbnRlcmZhY2VSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBVcGRhdGVSb3V0ZXNSZXF1ZXN0IDo9IHRydWUKZGVmYXVsdCBXYWl0UHJvY2Vzc1JlcXVlc3QgOj0gdHJ1ZQpkZWZhdWx0IFdyaXRlU3RyZWFtUmVxdWVzdCA6PSB0cnVlCgpkZWZhdWx0IEV4ZWNQcm9jZXNzUmVxdWVzdCA6PSBmYWxzZQo=
|
||||
spec:
|
||||
runtimeClassName: kata
|
||||
containers:
|
||||
@@ -79,7 +66,7 @@ Create the pod:
|
||||
$ kubectl apply -f pod1.yaml
|
||||
```
|
||||
|
||||
While creating the Pod sandbox, the Kata Shim will notice the `io.katacontainers.config.hypervisor.cc_init_data` annotation and will create the init data device on the host and mount it on the guest as a block device. The agent then reads the init data struct from this device and sets the policy if present.
|
||||
While creating the Pod sandbox, the Kata Shim will notice the `io.katacontainers.config.agent.policy` annotation and will send the Policy document to the Kata Agent - by sending a `SetPolicy` request. Note that this request will fail if the default Policy, included in the Guest image, doesn't allow this `SetPolicy` request. If the `SetPolicy` request is rejected by the Guest, the Kata Shim will fail to start the Pod sandbox.
|
||||
|
||||
# How is the Policy being enforced?
|
||||
|
||||
|
||||
7
src/agent/Cargo.lock
generated
7
src/agent/Cargo.lock
generated
@@ -4038,9 +4038,12 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.11"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
|
||||
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slash-formatter"
|
||||
|
||||
@@ -202,7 +202,7 @@ macro_rules! config_override {
|
||||
}
|
||||
};
|
||||
|
||||
($builder:ident, $config:ident, $field:ident, $func:ident) => {
|
||||
($builder:ident, $config:ident, $field:ident, $func: ident) => {
|
||||
if let Some(v) = $builder.$field {
|
||||
$config.$field = $func(&v)?;
|
||||
}
|
||||
@@ -661,8 +661,8 @@ impl AgentConfig {
|
||||
self.server_addr = addr;
|
||||
}
|
||||
|
||||
if let Ok(level) = env::var(LOG_LEVEL_ENV_VAR) {
|
||||
if let Ok(level) = logrus_to_slog_level(&level) {
|
||||
if let Ok(addr) = env::var(LOG_LEVEL_ENV_VAR) {
|
||||
if let Ok(level) = logrus_to_slog_level(&addr) {
|
||||
self.log_level = level;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ use nix::unistd::{self, dup, sync, Pid};
|
||||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs::{self, File};
|
||||
use std::io::ErrorKind;
|
||||
use std::os::unix::fs::{self as unixfs, FileTypeExt};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::path::Path;
|
||||
@@ -466,17 +465,8 @@ fn attestation_binaries_available(logger: &Logger, procs: &GuestComponentsProcs)
|
||||
_ => vec![],
|
||||
};
|
||||
for binary in binaries.iter() {
|
||||
let exists = Path::new(binary)
|
||||
.try_exists()
|
||||
.unwrap_or_else(|error| match error.kind() {
|
||||
ErrorKind::NotFound => {
|
||||
warn!(logger, "{} not found", binary);
|
||||
false
|
||||
}
|
||||
_ => panic!("Path existence check failed for '{}': {}", binary, error),
|
||||
});
|
||||
|
||||
if !exists {
|
||||
if !Path::new(binary).exists() {
|
||||
warn!(logger, "{} not found", binary);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
7
src/dragonball/Cargo.lock
generated
7
src/dragonball/Cargo.lock
generated
@@ -1922,9 +1922,12 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.11"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
|
||||
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slog"
|
||||
|
||||
@@ -102,7 +102,7 @@ use crate::resources::Resource;
|
||||
use crate::{DeviceIo, IoAddress, IoSize, PioAddress};
|
||||
|
||||
/// Error types for `IoManager` related operations.
|
||||
#[derive(Error, Debug, PartialEq)]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
/// The inserting device overlaps with a current device.
|
||||
#[error("device address conflicts with existing devices")]
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
|
||||
use std::any::Any;
|
||||
use std::io::Error;
|
||||
use std::sync::atomic::{AtomicU16, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
@@ -123,77 +121,6 @@ mod msi {
|
||||
}
|
||||
}
|
||||
|
||||
/// Vector value used to disable MSI for a queue.
|
||||
pub const VIRTQ_MSI_NO_VECTOR: u16 = 0xffff;
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Copy)]
|
||||
pub enum VirtioInterruptType {
|
||||
Config,
|
||||
Queue(u16),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct VirtioNotifierMsix {
|
||||
pub(crate) config_vector: Arc<AtomicU16>,
|
||||
pub(crate) queues_vectors: Arc<Mutex<Vec<u16>>>,
|
||||
pub(crate) interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>>,
|
||||
pub(crate) interrupt_type: VirtioInterruptType,
|
||||
}
|
||||
|
||||
impl VirtioNotifierMsix {
|
||||
pub fn new(
|
||||
config_vector: Arc<AtomicU16>,
|
||||
queues_vectors: Arc<Mutex<Vec<u16>>>,
|
||||
interrupt_source_group: Arc<Box<dyn InterruptSourceGroup>>,
|
||||
interrupt_type: VirtioInterruptType,
|
||||
) -> Self {
|
||||
VirtioNotifierMsix {
|
||||
config_vector,
|
||||
queues_vectors,
|
||||
interrupt_source_group,
|
||||
interrupt_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InterruptNotifier for VirtioNotifierMsix {
|
||||
fn notify(&self) -> std::result::Result<(), std::io::Error> {
|
||||
let vector = match self.interrupt_type {
|
||||
VirtioInterruptType::Config => self.config_vector.load(Ordering::Acquire),
|
||||
VirtioInterruptType::Queue(queue_index) => {
|
||||
self.queues_vectors.lock().unwrap()[queue_index as usize]
|
||||
}
|
||||
};
|
||||
if vector == VIRTQ_MSI_NO_VECTOR {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.interrupt_source_group
|
||||
.trigger(vector as InterruptIndex)
|
||||
}
|
||||
fn notifier(&self) -> Option<&EventFd> {
|
||||
let vector = match self.interrupt_type {
|
||||
VirtioInterruptType::Config => self.config_vector.load(Ordering::Acquire),
|
||||
VirtioInterruptType::Queue(queue_index) => {
|
||||
self.queues_vectors.lock().unwrap()[queue_index as usize]
|
||||
}
|
||||
};
|
||||
if vector == VIRTQ_MSI_NO_VECTOR {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.interrupt_source_group
|
||||
.notifier(vector as InterruptIndex)
|
||||
}
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn clone_boxed(&self) -> Box<dyn InterruptNotifier> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// Struct to discard interrupts.
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
pub struct NoopNotifier {}
|
||||
|
||||
@@ -16,8 +16,6 @@ thiserror = "1"
|
||||
dbs-allocator = { workspace = true }
|
||||
dbs-boot = { workspace = true }
|
||||
dbs-device = { workspace = true }
|
||||
dbs-address-space = { workspace = true }
|
||||
dbs-virtio-devices = { workspace = true }
|
||||
dbs-interrupt = { workspace = true, features = [
|
||||
"kvm-irq",
|
||||
"kvm-legacy-irq",
|
||||
@@ -25,18 +23,12 @@ dbs-interrupt = { workspace = true, features = [
|
||||
] }
|
||||
downcast-rs = "1.2.0"
|
||||
byteorder = "1.4.3"
|
||||
serde = "1.0.27"
|
||||
|
||||
vm-memory = {workspace = true}
|
||||
kvm-ioctls = {workspace = true}
|
||||
kvm-bindings = {workspace = true}
|
||||
vfio-ioctls = {workspace = true}
|
||||
vfio-bindings = {workspace = true}
|
||||
libc = "0.2.39"
|
||||
vmm-sys-util = {workspace = true}
|
||||
virtio-queue = {workspace = true}
|
||||
dbs-utils = {workspace = true}
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
dbs-arch = { workspace = true }
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
//! - PCI configuration: a common framework to emulator PCI configuration space header.
|
||||
//! - PCI MSI/MSIx: structs to emulate PCI MSI/MSIx capabilities.
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::Arc;
|
||||
|
||||
use dbs_device::device_manager::IoManagerContext;
|
||||
use dbs_interrupt::KvmIrqManager;
|
||||
@@ -58,17 +58,8 @@ pub use msix::{MsixCap, MsixState, MSIX_TABLE_ENTRY_SIZE};
|
||||
mod vfio;
|
||||
pub use vfio::{VfioPciDevice, VfioPciError, VENDOR_NVIDIA};
|
||||
|
||||
mod virtio_pci;
|
||||
pub use virtio_pci::{VirtioPciDevice, VirtioPciDeviceError, CAPABILITY_BAR_SIZE};
|
||||
|
||||
mod pci_address;
|
||||
use dbs_virtio_devices::VirtioDevice;
|
||||
pub use pci_address::PciAddress;
|
||||
|
||||
mod pci_common_config;
|
||||
|
||||
/// Error codes related to PCI root/bus/device operations.
|
||||
#[derive(Debug, thiserror::Error, PartialEq)]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
/// Failed to activate the PCI root/bus/device.
|
||||
#[error("failed to activate PCI device, {0:?}")]
|
||||
@@ -119,9 +110,6 @@ pub enum Error {
|
||||
/// PCI ROM BAR address is invalid.
|
||||
#[error("address {0} size {1} too big")]
|
||||
RomBarAddressInvalid(u64, u64),
|
||||
/// Invalid parameter
|
||||
#[error("invalid pci device address")]
|
||||
InvalidParameter,
|
||||
}
|
||||
|
||||
/// Specialized `Result` for PCI related operations.
|
||||
@@ -142,8 +130,3 @@ pub fn fill_config_data(data: &mut [u8]) {
|
||||
*pos = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/// we only support one pci bus
|
||||
pub const PCI_BUS_DEFAULT: u8 = 0;
|
||||
|
||||
type ArcMutexBoxDynVirtioDevice<AS, Q, R> = Arc<Mutex<Box<dyn VirtioDevice<AS, Q, R>>>>;
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
// Copyright (C) 2024 Alibaba Cloud. All rights reserved.
|
||||
//
|
||||
// Copyright (C) 2025 Ant Group. All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
|
||||
use crate::{Error, Result};
|
||||
|
||||
const PCI_MAX_DEV_ID: u8 = 0x1f;
|
||||
const PCI_MAX_FUNC_ID: u8 = 0x7;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct PciAddress {
|
||||
/// Bus number, in the range [0, 0xff].
|
||||
bus: u8,
|
||||
/// Device id, in the range [0x0, 0x1f].
|
||||
dev: u8,
|
||||
/// Function id, in the range [0x0, 0x7].
|
||||
func: u8,
|
||||
}
|
||||
|
||||
impl PartialOrd for PciAddress {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for PciAddress {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
// Compare in the order of bus -> dev -> func.
|
||||
self.bus
|
||||
.cmp(&other.bus)
|
||||
.then_with(|| self.dev.cmp(&other.dev))
|
||||
.then_with(|| self.func.cmp(&other.func))
|
||||
}
|
||||
}
|
||||
|
||||
impl PciAddress {
|
||||
/// Create a new PCI address from bus and device/function id.
|
||||
///
|
||||
/// * `bus`: PCI bus number, in the range \[0x0, 0xff\].
|
||||
/// * `dev`: PCI device id, in the range \[0x0, 0x1f\].
|
||||
/// * `func`: PCI function id, in the range \[0x0, 0x7\].
|
||||
pub fn new(bus: u8, dev: u8, func: u8) -> Result<Self> {
|
||||
if dev > PCI_MAX_DEV_ID || func > PCI_MAX_FUNC_ID {
|
||||
return Err(Error::InvalidParameter);
|
||||
}
|
||||
|
||||
Ok(PciAddress { bus, dev, func })
|
||||
}
|
||||
|
||||
/// Get PCI device id on the PCI bus, which is in [0x0, 0x1f]
|
||||
pub fn dev_id(&self) -> u8 {
|
||||
self.dev
|
||||
}
|
||||
|
||||
/// Get PCI device function id, which is in [0x0, 0x7].
|
||||
pub fn func_id(&self) -> u8 {
|
||||
self.func
|
||||
}
|
||||
|
||||
/// Get PCI device bus number, which is in [0x0, 0xff].
|
||||
pub fn bus_id(&self) -> u8 {
|
||||
self.bus
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for PciAddress {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"PciAddress: {:02x}:{:02x}.{:02x}",
|
||||
self.bus, self.dev, self.func
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_pci_address() {
|
||||
// test invlaid device id
|
||||
assert_eq!(PciAddress::new(0, 32, 0), Err(Error::InvalidParameter));
|
||||
|
||||
// test invalid function id
|
||||
assert_eq!(PciAddress::new(0, 0, 8), Err(Error::InvalidParameter));
|
||||
|
||||
// test pci address
|
||||
let (bus, dev, func) = (3, 5, 4);
|
||||
let address = PciAddress::new(bus, dev, func).unwrap();
|
||||
assert_eq!(address.bus_id(), bus);
|
||||
assert_eq!(address.dev_id(), dev);
|
||||
assert_eq!(address.func_id(), func);
|
||||
}
|
||||
}
|
||||
@@ -1,507 +0,0 @@
|
||||
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
//
|
||||
// Copyright © 2019 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
//
|
||||
// Copyright (C) 2024 Alibaba Cloud. All rights reserved.
|
||||
//
|
||||
// Copyright (C) 2025 Ant Group. All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
|
||||
|
||||
use std::sync::atomic::{AtomicU16, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use log::{error, trace, warn};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use virtio_queue::QueueT;
|
||||
use vm_memory::{GuestAddressSpace, GuestMemoryRegion};
|
||||
|
||||
use crate::ArcMutexBoxDynVirtioDevice;
|
||||
use dbs_virtio_devices::VirtioQueueConfig;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct VirtioPciCommonConfigState {
|
||||
pub driver_status: u8,
|
||||
pub config_generation: u8,
|
||||
pub device_feature_select: u32,
|
||||
pub driver_feature_select: u32,
|
||||
pub queue_select: u16,
|
||||
pub msix_config: u16,
|
||||
pub msix_queues: Vec<u16>,
|
||||
}
|
||||
|
||||
/* The standard layout for the ring is a continuous chunk of memory which looks
|
||||
* like this. We assume num is a power of 2.
|
||||
*
|
||||
* struct vring
|
||||
* {
|
||||
* // The actual descriptors (16 bytes each)
|
||||
* struct vring_desc desc[num];
|
||||
*
|
||||
* // A ring of available descriptor heads with free-running index.
|
||||
* __virtio16 avail_flags;
|
||||
* __virtio16 avail_idx;
|
||||
* __virtio16 available[num];
|
||||
* __virtio16 used_event_idx;
|
||||
*
|
||||
* // Padding to the next align boundary.
|
||||
* char pad[];
|
||||
*
|
||||
* // A ring of used descriptor heads with free-running index.
|
||||
* __virtio16 used_flags;
|
||||
* __virtio16 used_idx;
|
||||
* struct vring_used_elem used[num];
|
||||
* __virtio16 avail_event_idx;
|
||||
* };
|
||||
* struct vring_desc {
|
||||
* __virtio64 addr;
|
||||
* __virtio32 len;
|
||||
* __virtio16 flags;
|
||||
* __virtio16 next;
|
||||
* };
|
||||
*
|
||||
* struct vring_avail {
|
||||
* __virtio16 flags;
|
||||
* __virtio16 idx;
|
||||
* __virtio16 ring[];
|
||||
* };
|
||||
*
|
||||
* // u32 is used here for ids for padding reasons.
|
||||
* struct vring_used_elem {
|
||||
* // Index of start of used descriptor chain.
|
||||
* __virtio32 id;
|
||||
* // Total length of the descriptor chain which was used (written to)
|
||||
* __virtio32 len;
|
||||
* };
|
||||
*
|
||||
* Kernel header used for this reference: include/uapi/linux/virtio_ring.h
|
||||
* Virtio Spec: https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html
|
||||
*
|
||||
*/
|
||||
|
||||
/// Contains the data for reading and writing the common configuration structure of a virtio PCI
|
||||
/// device.
|
||||
///
|
||||
/// * Registers:
|
||||
///
|
||||
/// ** About the whole device.
|
||||
/// le32 device_feature_select; // 0x00 // read-write
|
||||
/// le32 device_feature; // 0x04 // read-only for driver
|
||||
/// le32 driver_feature_select; // 0x08 // read-write
|
||||
/// le32 driver_feature; // 0x0C // read-write
|
||||
/// le16 msix_config; // 0x10 // read-write
|
||||
/// le16 num_queues; // 0x12 // read-only for driver
|
||||
/// u8 device_status; // 0x14 // read-write (driver_status)
|
||||
/// u8 config_generation; // 0x15 // read-only for driver
|
||||
///
|
||||
/// ** About a specific virtqueue.
|
||||
/// le16 queue_select; // 0x16 // read-write
|
||||
/// le16 queue_size; // 0x18 // read-write, power of 2, or 0.
|
||||
/// le16 queue_msix_vector; // 0x1A // read-write
|
||||
/// le16 queue_enable; // 0x1C // read-write (Ready)
|
||||
/// le16 queue_notify_off; // 0x1E // read-only for driver
|
||||
/// le64 queue_desc; // 0x20 // read-write
|
||||
/// le64 queue_avail; // 0x28 // read-write
|
||||
/// le64 queue_used; // 0x30 // read-write
|
||||
pub struct VirtioPciCommonConfig {
|
||||
pub driver_status: u8,
|
||||
pub config_generation: u8,
|
||||
pub device_feature_select: u32,
|
||||
pub driver_feature_select: u32,
|
||||
pub queue_select: u16,
|
||||
pub msix_config: Arc<AtomicU16>,
|
||||
pub msix_queues: Arc<Mutex<Vec<u16>>>,
|
||||
}
|
||||
|
||||
impl VirtioPciCommonConfig {
|
||||
pub fn new(state: VirtioPciCommonConfigState) -> Self {
|
||||
VirtioPciCommonConfig {
|
||||
driver_status: state.driver_status,
|
||||
config_generation: state.config_generation,
|
||||
device_feature_select: state.device_feature_select,
|
||||
driver_feature_select: state.driver_feature_select,
|
||||
queue_select: state.queue_select,
|
||||
msix_config: Arc::new(AtomicU16::new(state.msix_config)),
|
||||
msix_queues: Arc::new(Mutex::new(state.msix_queues)),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(fupan): use for live upgrade later
|
||||
#[allow(dead_code)]
|
||||
fn state(&self) -> VirtioPciCommonConfigState {
|
||||
VirtioPciCommonConfigState {
|
||||
driver_status: self.driver_status,
|
||||
config_generation: self.config_generation,
|
||||
device_feature_select: self.device_feature_select,
|
||||
driver_feature_select: self.driver_feature_select,
|
||||
queue_select: self.queue_select,
|
||||
msix_config: self.msix_config.load(Ordering::Acquire),
|
||||
msix_queues: self.msix_queues.lock().unwrap().clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_common_config_byte(&self, offset: u64) -> u8 {
|
||||
trace!("read_common_config_byte: offset 0x{:x}", offset);
|
||||
// The driver is only allowed to do aligned, properly sized access.
|
||||
match offset {
|
||||
0x14 => self.driver_status,
|
||||
0x15 => self.config_generation,
|
||||
_ => {
|
||||
warn!("invalid virtio config byte read: 0x{:x}", offset);
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_common_config_byte(&mut self, offset: u64, value: u8) {
|
||||
trace!(
|
||||
"write_common_config_byte: offset 0x{:x} value 0x{:x}",
|
||||
offset,
|
||||
value
|
||||
);
|
||||
match offset {
|
||||
0x14 => self.driver_status = value,
|
||||
_ => {
|
||||
warn!("invalid virtio config byte write: 0x{:x}", offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_common_config_word<Q: QueueT + 'static>(
|
||||
&self,
|
||||
offset: u64,
|
||||
queues: &[VirtioQueueConfig<Q>],
|
||||
) -> u16 {
|
||||
trace!("read_common_config_word: offset 0x{:x}", offset);
|
||||
match offset {
|
||||
0x10 => self.msix_config.load(Ordering::Acquire),
|
||||
0x12 => queues.len() as u16, // num_queues
|
||||
0x16 => self.queue_select,
|
||||
0x18 => self.with_queue(queues, |q| q.max_size()).unwrap_or(0),
|
||||
0x1a => self.msix_queues.lock().unwrap()[self.queue_select as usize],
|
||||
0x1c => u16::from(self.with_queue(queues, |q| q.ready()).unwrap_or(false)),
|
||||
0x1e => self.queue_select, // notify_off
|
||||
_ => {
|
||||
warn!("invalid virtio register word read: 0x{:x}", offset);
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_common_config_word<Q: QueueT + 'static>(
|
||||
&mut self,
|
||||
offset: u64,
|
||||
value: u16,
|
||||
queues: &mut [VirtioQueueConfig<Q>],
|
||||
) {
|
||||
trace!(
|
||||
"write_common_config_word: offset 0x{:x} value 0x{:x}",
|
||||
offset,
|
||||
value
|
||||
);
|
||||
match offset {
|
||||
0x10 => self.msix_config.store(value, Ordering::Release),
|
||||
0x16 => self.queue_select = value,
|
||||
0x18 => self.with_queue_mut(queues, |q| q.set_size(value)),
|
||||
0x1a => self.msix_queues.lock().unwrap()[self.queue_select as usize] = value,
|
||||
0x1c => self.with_queue_mut(queues, |q| {
|
||||
let ready = value == 1;
|
||||
q.set_ready(ready);
|
||||
}),
|
||||
_ => {
|
||||
warn!("invalid virtio register word write: 0x{:x}", offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_common_config_dword<
|
||||
AS: GuestAddressSpace + 'static,
|
||||
Q: QueueT + 'static,
|
||||
R: 'static + GuestMemoryRegion,
|
||||
>(
|
||||
&self,
|
||||
offset: u64,
|
||||
device: ArcMutexBoxDynVirtioDevice<AS, Q, R>,
|
||||
) -> u32 {
|
||||
trace!("read_common_config_dword: offset 0x{:x}", offset);
|
||||
match offset {
|
||||
0x00 => self.device_feature_select,
|
||||
0x04 => {
|
||||
// Only 64 bits of features (2 pages) are defined for now, so limit
|
||||
// device_feature_select to avoid shifting by 64 or more bits.
|
||||
let locked_device = device.lock().unwrap();
|
||||
if self.device_feature_select < 2 {
|
||||
locked_device.get_avail_features(self.device_feature_select)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
0x08 => self.driver_feature_select,
|
||||
_ => {
|
||||
warn!("invalid virtio register dword read: 0x{:x}", offset);
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_common_config_dword<
|
||||
AS: GuestAddressSpace + 'static,
|
||||
Q: QueueT + 'static,
|
||||
R: 'static + GuestMemoryRegion,
|
||||
>(
|
||||
&mut self,
|
||||
offset: u64,
|
||||
value: u32,
|
||||
queues: &mut [VirtioQueueConfig<Q>],
|
||||
device: ArcMutexBoxDynVirtioDevice<AS, Q, R>,
|
||||
) {
|
||||
trace!(
|
||||
"write_common_config_dword: offset 0x{:x} value 0x{:x}",
|
||||
offset,
|
||||
value
|
||||
);
|
||||
|
||||
match offset {
|
||||
0x00 => self.device_feature_select = value,
|
||||
0x08 => self.driver_feature_select = value,
|
||||
0x0c => {
|
||||
if self.driver_feature_select < 2 {
|
||||
let mut locked_device = device.lock().unwrap();
|
||||
locked_device.set_acked_features(self.driver_feature_select, value);
|
||||
} else {
|
||||
warn!(
|
||||
"invalid ack_features (page {}, value 0x{:x})",
|
||||
self.driver_feature_select, value
|
||||
);
|
||||
}
|
||||
}
|
||||
0x20 => self.with_queue_mut(queues, |q| q.set_desc_table_address(Some(value), None)),
|
||||
0x24 => self.with_queue_mut(queues, |q| q.set_desc_table_address(None, Some(value))),
|
||||
0x28 => self.with_queue_mut(queues, |q| q.set_avail_ring_address(Some(value), None)),
|
||||
0x2c => self.with_queue_mut(queues, |q| q.set_avail_ring_address(None, Some(value))),
|
||||
0x30 => self.with_queue_mut(queues, |q| q.set_used_ring_address(Some(value), None)),
|
||||
0x34 => self.with_queue_mut(queues, |q| q.set_used_ring_address(None, Some(value))),
|
||||
_ => {
|
||||
warn!("invalid virtio register dword write: 0x{:x}", offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_common_config_qword(&self, _offset: u64) -> u64 {
|
||||
trace!("read_common_config_qword: offset 0x{:x}", _offset);
|
||||
0 // Assume the guest has no reason to read write-only registers.
|
||||
}
|
||||
|
||||
fn write_common_config_qword<Q: QueueT + 'static>(
|
||||
&mut self,
|
||||
offset: u64,
|
||||
value: u64,
|
||||
queues: &mut [VirtioQueueConfig<Q>],
|
||||
) {
|
||||
trace!(
|
||||
"write_common_config_qword: offset 0x{:x}, value 0x{:x}",
|
||||
offset,
|
||||
value
|
||||
);
|
||||
|
||||
let low = Some((value & 0xffff_ffff) as u32);
|
||||
let high = Some((value >> 32) as u32);
|
||||
|
||||
match offset {
|
||||
0x20 => self.with_queue_mut(queues, |q| q.set_desc_table_address(low, high)),
|
||||
0x28 => self.with_queue_mut(queues, |q| q.set_avail_ring_address(low, high)),
|
||||
0x30 => self.with_queue_mut(queues, |q| q.set_used_ring_address(low, high)),
|
||||
_ => {
|
||||
warn!("invalid virtio register qword write: 0x{:x}", offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn with_queue<U, F, Q>(&self, queues: &[VirtioQueueConfig<Q>], f: F) -> Option<U>
|
||||
where
|
||||
F: FnOnce(&Q) -> U,
|
||||
Q: QueueT + 'static,
|
||||
{
|
||||
queues.get(self.queue_select as usize).map(|q| f(&q.queue))
|
||||
}
|
||||
|
||||
fn with_queue_mut<F: FnOnce(&mut Q), Q: QueueT + 'static>(
|
||||
&self,
|
||||
queues: &mut [VirtioQueueConfig<Q>],
|
||||
f: F,
|
||||
) {
|
||||
if let Some(queue) = queues.get_mut(self.queue_select as usize) {
|
||||
f(&mut queue.queue);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read<
|
||||
AS: GuestAddressSpace + 'static,
|
||||
Q: QueueT + 'static,
|
||||
R: 'static + GuestMemoryRegion,
|
||||
>(
|
||||
&self,
|
||||
offset: u64,
|
||||
data: &mut [u8],
|
||||
queues: &[VirtioQueueConfig<Q>],
|
||||
device: ArcMutexBoxDynVirtioDevice<AS, Q, R>,
|
||||
) {
|
||||
assert!(data.len() <= 8);
|
||||
|
||||
match data.len() {
|
||||
1 => {
|
||||
let v = self.read_common_config_byte(offset);
|
||||
data[0] = v;
|
||||
}
|
||||
2 => {
|
||||
let v = self.read_common_config_word(offset, queues);
|
||||
LittleEndian::write_u16(data, v);
|
||||
}
|
||||
4 => {
|
||||
let v = self.read_common_config_dword(offset, device);
|
||||
LittleEndian::write_u32(data, v);
|
||||
}
|
||||
8 => {
|
||||
let v = self.read_common_config_qword(offset);
|
||||
LittleEndian::write_u64(data, v);
|
||||
}
|
||||
_ => error!("invalid data length for virtio read: len {}", data.len()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write<
|
||||
AS: GuestAddressSpace + 'static,
|
||||
Q: QueueT + 'static,
|
||||
R: 'static + GuestMemoryRegion,
|
||||
>(
|
||||
&mut self,
|
||||
offset: u64,
|
||||
data: &[u8],
|
||||
queues: &mut [VirtioQueueConfig<Q>],
|
||||
device: ArcMutexBoxDynVirtioDevice<AS, Q, R>,
|
||||
) {
|
||||
assert!(data.len() <= 8);
|
||||
|
||||
match data.len() {
|
||||
1 => self.write_common_config_byte(offset, data[0]),
|
||||
2 => self.write_common_config_word(offset, LittleEndian::read_u16(data), queues),
|
||||
4 => {
|
||||
self.write_common_config_dword(offset, LittleEndian::read_u32(data), queues, device)
|
||||
}
|
||||
8 => self.write_common_config_qword(offset, LittleEndian::read_u64(data), queues),
|
||||
_ => error!("invalid data length for virtio write: len {}", data.len()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::virtio_pci::tests::{DummyDevice, DUMMY_FEATURES};
|
||||
use super::*;
|
||||
use dbs_virtio_devices::VirtioDevice;
|
||||
use virtio_queue::QueueSync;
|
||||
use vm_memory::{GuestMemoryMmap, GuestRegionMmap};
|
||||
|
||||
#[test]
|
||||
fn write_base_regs() {
|
||||
let regs_state = VirtioPciCommonConfigState {
|
||||
driver_status: 0xaa,
|
||||
config_generation: 0x55,
|
||||
device_feature_select: 0x0,
|
||||
driver_feature_select: 0x0,
|
||||
queue_select: 0xff,
|
||||
msix_config: 0,
|
||||
msix_queues: vec![0; 3],
|
||||
};
|
||||
let mut regs = VirtioPciCommonConfig::new(regs_state);
|
||||
|
||||
let dev: Arc<
|
||||
Mutex<Box<dyn VirtioDevice<Arc<GuestMemoryMmap>, QueueSync, GuestRegionMmap>>>,
|
||||
> = Arc::new(Mutex::new(Box::new(DummyDevice::new())));
|
||||
let mut queues = Vec::new();
|
||||
queues.push(VirtioQueueConfig::create(2, 0).unwrap());
|
||||
queues.push(VirtioQueueConfig::create(2, 1).unwrap());
|
||||
|
||||
// Can set all bits of driver_status.
|
||||
regs.write(0x14, &[0x55], &mut queues, Arc::clone(&dev));
|
||||
let mut read_back = vec![0x00];
|
||||
regs.read(0x14, &mut read_back, &queues, Arc::clone(&dev));
|
||||
assert_eq!(read_back[0], 0x55);
|
||||
|
||||
// The config generation register is read only.
|
||||
regs.write(0x15, &[0xaa], &mut queues, Arc::clone(&dev));
|
||||
let mut read_back = vec![0x00];
|
||||
regs.read(0x15, &mut read_back, &queues, Arc::clone(&dev));
|
||||
assert_eq!(read_back[0], 0x55);
|
||||
|
||||
// Device features is read-only and passed through from the device.
|
||||
regs.write(0x04, &[0, 0, 0, 0], &mut queues, Arc::clone(&dev));
|
||||
let mut read_back = vec![0, 0, 0, 0];
|
||||
regs.read(0x04, &mut read_back, &queues, Arc::clone(&dev));
|
||||
assert_eq!(LittleEndian::read_u32(&read_back), DUMMY_FEATURES as u32);
|
||||
|
||||
// Read device features with device_feature_select as 0
|
||||
regs.write(0x00, &[0, 0, 0, 0], &mut queues, Arc::clone(&dev));
|
||||
let mut read_back = vec![0, 0, 0, 0];
|
||||
regs.read(0x04, &mut read_back, &queues, Arc::clone(&dev));
|
||||
assert_eq!(LittleEndian::read_u32(&read_back), DUMMY_FEATURES as u32);
|
||||
|
||||
// Read device features with device_feature_select as 1
|
||||
regs.write(0x00, &[1, 0, 0, 0], &mut queues, Arc::clone(&dev));
|
||||
let mut read_back = vec![0, 0, 0, 0];
|
||||
regs.read(0x04, &mut read_back, &queues, Arc::clone(&dev));
|
||||
assert_eq!(
|
||||
LittleEndian::read_u32(&read_back),
|
||||
(DUMMY_FEATURES >> 32) as u32
|
||||
);
|
||||
|
||||
// Feature select registers are read/write.
|
||||
regs.write(0x00, &[1, 2, 3, 4], &mut queues, Arc::clone(&dev));
|
||||
let mut read_back = vec![0, 0, 0, 0];
|
||||
regs.read(0x00, &mut read_back, &queues, Arc::clone(&dev));
|
||||
assert_eq!(LittleEndian::read_u32(&read_back), 0x0403_0201);
|
||||
regs.write(0x08, &[1, 2, 3, 4], &mut queues, Arc::clone(&dev));
|
||||
let mut read_back = vec![0, 0, 0, 0];
|
||||
regs.read(0x08, &mut read_back, &queues, Arc::clone(&dev));
|
||||
assert_eq!(LittleEndian::read_u32(&read_back), 0x0403_0201);
|
||||
|
||||
// 'queue_select' can be read and written.
|
||||
regs.write(0x16, &[0xaa, 0x55], &mut queues, Arc::clone(&dev));
|
||||
let mut read_back = vec![0x00, 0x00];
|
||||
regs.read(0x16, &mut read_back, &queues, Arc::clone(&dev));
|
||||
assert_eq!(read_back[0], 0xaa);
|
||||
assert_eq!(read_back[1], 0x55);
|
||||
|
||||
// write msix_queues by queue_select 2
|
||||
regs.write(0x16, &[0x02, 0x00], &mut queues, Arc::clone(&dev));
|
||||
regs.write(0x1a, &[0xbb, 0xcc], &mut queues, Arc::clone(&dev));
|
||||
let mut read_back = vec![0x00, 0x00];
|
||||
regs.read(0x1a, &mut read_back, &queues, Arc::clone(&dev));
|
||||
assert_eq!(read_back[0], 0xbb);
|
||||
assert_eq!(read_back[1], 0xcc);
|
||||
|
||||
// 'msix_config' can be read and written.
|
||||
regs.write(0x10, &[0xdd, 0xee], &mut queues, Arc::clone(&dev));
|
||||
let mut read_back = vec![0x00, 0x00];
|
||||
regs.read(0x10, &mut read_back, &queues, Arc::clone(&dev));
|
||||
assert_eq!(read_back[0], 0xdd);
|
||||
assert_eq!(read_back[1], 0xee);
|
||||
|
||||
// 'queue_size' can be read and set.
|
||||
let mut read_back = vec![0x00, 0x00];
|
||||
// queue_select is 2 and queues[2] is None, so queue_size is 0
|
||||
regs.read(0x18, &mut read_back, &queues, Arc::clone(&dev));
|
||||
assert_eq!(read_back[0], 0x00);
|
||||
assert_eq!(read_back[1], 0x00);
|
||||
// queue_select is 1, so queue_size is 2
|
||||
regs.write(0x16, &[0x01, 0x00], &mut queues, Arc::clone(&dev));
|
||||
regs.read(0x18, &mut read_back, &queues, Arc::clone(&dev));
|
||||
assert_eq!(read_back[0], 0x02);
|
||||
assert_eq!(read_back[1], 0x00);
|
||||
}
|
||||
}
|
||||
@@ -888,7 +888,7 @@ pub struct VfioPciDeviceState<C: PciSystemContext> {
|
||||
vfio_path: String,
|
||||
interrupt: Interrupt,
|
||||
vfio_dev: Arc<VfioDevice>,
|
||||
context: Arc<Mutex<C>>,
|
||||
context: Weak<C>,
|
||||
configuration: PciConfiguration,
|
||||
device: Option<Weak<dyn DeviceIo>>,
|
||||
regions: Vec<Region>,
|
||||
@@ -904,7 +904,7 @@ impl<C: PciSystemContext> VfioPciDeviceState<C> {
|
||||
vfio_path: String,
|
||||
vfio_dev: Arc<VfioDevice>,
|
||||
bus: Weak<PciBus>,
|
||||
context: Arc<Mutex<C>>,
|
||||
context: Weak<C>,
|
||||
vendor_device_id: u32,
|
||||
clique_id: Option<u8>,
|
||||
vfio_container: Arc<VfioContainer>,
|
||||
@@ -1277,7 +1277,11 @@ impl<C: PciSystemContext> VfioPciDeviceState<C> {
|
||||
}
|
||||
|
||||
fn register_regions(&mut self, vm: &Arc<VmFd>) -> Result<()> {
|
||||
let ctx = self.context.lock().unwrap().get_device_manager_context();
|
||||
let ctx = self
|
||||
.context
|
||||
.upgrade()
|
||||
.ok_or(VfioPciError::BusIsDropped)?
|
||||
.get_device_manager_context();
|
||||
let mut tx = ctx.begin_tx();
|
||||
|
||||
for region in self.regions.iter_mut() {
|
||||
@@ -1332,7 +1336,22 @@ impl<C: PciSystemContext> VfioPciDeviceState<C> {
|
||||
}
|
||||
|
||||
fn unregister_regions(&mut self, vm: &Arc<VmFd>) -> Result<()> {
|
||||
let ctx = self.context.lock().unwrap().get_device_manager_context();
|
||||
// This routine handle VfioPciDevice dropped but not unmap memory
|
||||
if self.context.upgrade().is_none() {
|
||||
for region in self.regions.iter_mut() {
|
||||
if region.mappable() {
|
||||
region.unmap(vm, &self.vfio_container)?;
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let ctx = self
|
||||
.context
|
||||
.upgrade()
|
||||
.ok_or(VfioPciError::BusIsDropped)?
|
||||
.get_device_manager_context();
|
||||
let mut tx = ctx.begin_tx();
|
||||
|
||||
for region in self.regions.iter_mut() {
|
||||
@@ -1361,8 +1380,11 @@ impl<C: PciSystemContext> VfioPciDeviceState<C> {
|
||||
} else {
|
||||
// Safe to unwrap because activate() has set self.device to a valid value.
|
||||
let device = self.device.as_ref().unwrap().clone();
|
||||
let ctx: <C as PciSystemContext>::D =
|
||||
self.context.lock().unwrap().get_device_manager_context();
|
||||
let ctx: <C as PciSystemContext>::D = self
|
||||
.context
|
||||
.upgrade()
|
||||
.ok_or(VfioPciError::BusIsDropped)?
|
||||
.get_device_manager_context();
|
||||
let mut tx = ctx.begin_tx();
|
||||
|
||||
if let Err(e) = region.retrap(
|
||||
@@ -1539,7 +1561,7 @@ impl<C: PciSystemContext> VfioPciDevice<C> {
|
||||
path: String,
|
||||
bus: Weak<PciBus>,
|
||||
device: VfioDevice,
|
||||
context: Arc<Mutex<C>>,
|
||||
context: Weak<C>,
|
||||
vm_fd: Arc<VmFd>,
|
||||
vendor_device_id: u32,
|
||||
clique_id: Option<u8>,
|
||||
@@ -1627,7 +1649,11 @@ impl<C: PciSystemContext> VfioPciDevice<C> {
|
||||
state.interrupt.add_msi_irq_resource(base, size);
|
||||
}
|
||||
|
||||
let irq_manager = state.context.lock().unwrap().get_interrupt_manager();
|
||||
let irq_manager = state
|
||||
.context
|
||||
.upgrade()
|
||||
.ok_or(VfioPciError::BusIsDropped)?
|
||||
.get_interrupt_manager();
|
||||
state.interrupt.initialize(irq_manager)?;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
self.set_device_id(&mut state);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -145,8 +145,6 @@ pub enum ActivateError {
|
||||
#[cfg(feature = "vhost")]
|
||||
#[error("Vhost activate error")]
|
||||
VhostActivate(vhost_rs::Error),
|
||||
#[error("VirtioPci error")]
|
||||
VirtioPci,
|
||||
}
|
||||
|
||||
impl std::convert::From<Error> for ActivateError {
|
||||
|
||||
@@ -371,7 +371,6 @@ where
|
||||
}
|
||||
|
||||
let _ = self.intr_mgr.reset();
|
||||
self.unregister_ioevent_doorbell();
|
||||
self.unregister_ioevent();
|
||||
self.features_select = 0;
|
||||
self.acked_features_select = 0;
|
||||
|
||||
@@ -205,10 +205,6 @@ pub enum VmmAction {
|
||||
/// input. This action can only be called before the microVM has booted.
|
||||
InsertBlockDevice(BlockDeviceConfigInfo),
|
||||
|
||||
#[cfg(any(feature = "virtio-blk", feature = "vhost-user-blk"))]
|
||||
/// Prepare to remove a block device that already exists
|
||||
PrepareRemoveBlockDevice(String),
|
||||
|
||||
#[cfg(any(feature = "virtio-blk", feature = "vhost-user-blk"))]
|
||||
/// Remove a new block device for according to given drive_id
|
||||
RemoveBlockDevice(String),
|
||||
@@ -360,10 +356,6 @@ impl VmmService {
|
||||
self.add_block_device(vmm, event_mgr, block_device_config)
|
||||
}
|
||||
#[cfg(any(feature = "virtio-blk", feature = "vhost-user-blk"))]
|
||||
VmmAction::PrepareRemoveBlockDevice(blkdev_id) => {
|
||||
self.prepare_remove_block_device(vmm, &blkdev_id)
|
||||
}
|
||||
#[cfg(any(feature = "virtio-blk", feature = "vhost-user-blk"))]
|
||||
VmmAction::UpdateBlockDevice(blk_update) => {
|
||||
self.update_blk_rate_limiters(vmm, blk_update)
|
||||
}
|
||||
@@ -672,17 +664,10 @@ impl VmmService {
|
||||
VmmActionError::Block(BlockDeviceError::UpdateNotAllowedPostBoot)
|
||||
})?;
|
||||
|
||||
let (sender, receiver) = mpsc::channel();
|
||||
let vmm_data = if ctx.is_hotplug() {
|
||||
VmmData::SyncHotplug((sender.clone(), receiver))
|
||||
} else {
|
||||
VmmData::Empty
|
||||
};
|
||||
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, config, sender.clone())
|
||||
.map(|_| vmm_data)
|
||||
.insert_device(ctx, config)
|
||||
.map(|_| VmmData::Empty)
|
||||
.map_err(VmmActionError::Block)
|
||||
}
|
||||
|
||||
@@ -703,38 +688,6 @@ impl VmmService {
|
||||
.map_err(VmmActionError::Block)
|
||||
}
|
||||
|
||||
// using upcall to unplug the block device in the guest
|
||||
#[cfg(any(feature = "virtio-blk", feature = "vhost-user-blk"))]
|
||||
fn prepare_remove_block_device(
|
||||
&mut self,
|
||||
vmm: &mut Vmm,
|
||||
blockdev_id: &str,
|
||||
) -> VmmRequestResult {
|
||||
let vm = vmm.get_vm_mut().ok_or(VmmActionError::HostDeviceConfig(
|
||||
VfioDeviceError::InvalidVMID,
|
||||
))?;
|
||||
|
||||
info!("prepare_remove_block_device: {:?}", blockdev_id);
|
||||
let ctx = vm.create_device_op_context(None).map_err(|e| {
|
||||
info!("create device op context error: {:?}", e);
|
||||
if let StartMicroVmError::MicroVMAlreadyRunning = e {
|
||||
VmmActionError::HostDeviceConfig(VfioDeviceError::UpdateNotAllowedPostBoot)
|
||||
} else if let StartMicroVmError::UpcallServerNotReady = e {
|
||||
VmmActionError::UpcallServerNotReady
|
||||
} else {
|
||||
VmmActionError::StartMicroVm(e)
|
||||
}
|
||||
})?;
|
||||
|
||||
let (sender, receiver) = mpsc::channel();
|
||||
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.prepare_remove_device(&ctx, blockdev_id, sender.clone())
|
||||
.map(|_| VmmData::SyncHotplug((sender, receiver)))
|
||||
.map_err(VmmActionError::Block)
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "virtio-blk", feature = "vhost-user-blk"))]
|
||||
// Remove the device
|
||||
#[instrument(skip(self, event_mgr))]
|
||||
@@ -1573,7 +1526,6 @@ mod tests {
|
||||
queue_size: 256,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
}),
|
||||
InstanceState::Uninitialized,
|
||||
&|result| {
|
||||
|
||||
@@ -7,28 +7,19 @@
|
||||
// found in the THIRD-PARTY file.
|
||||
|
||||
//! Device manager for virtio-blk and vhost-user-blk devices.
|
||||
use std::collections::{vec_deque, VecDeque};
|
||||
use std::convert::TryInto;
|
||||
use std::fs::OpenOptions;
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::sync::Arc;
|
||||
use std::{
|
||||
collections::{vec_deque, VecDeque},
|
||||
sync::mpsc,
|
||||
};
|
||||
|
||||
use dbs_device::DeviceIo;
|
||||
use dbs_pci::VirtioPciDevice;
|
||||
use dbs_upcall::{DevMgrResponse, UpcallClientResponse};
|
||||
use dbs_virtio_devices as virtio;
|
||||
use dbs_virtio_devices::block::{aio::Aio, io_uring::IoUring, Block, LocalFile, Ufile};
|
||||
#[cfg(feature = "vhost-user-blk")]
|
||||
use dbs_virtio_devices::vhost::vhost_user::block::VhostUserBlock;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use virtio_queue::QueueSync;
|
||||
use vm_memory::GuestRegionMmap;
|
||||
|
||||
use crate::address_space_manager::GuestAddressSpaceImpl;
|
||||
use crate::config_manager::{ConfigItem, DeviceConfigInfo, RateLimiterConfigInfo};
|
||||
@@ -199,8 +190,6 @@ pub struct BlockDeviceConfigInfo {
|
||||
pub use_shared_irq: Option<bool>,
|
||||
/// Use generic irq
|
||||
pub use_generic_irq: Option<bool>,
|
||||
/// Use pci bus
|
||||
pub use_pci_bus: Option<bool>,
|
||||
}
|
||||
|
||||
impl std::default::Default for BlockDeviceConfigInfo {
|
||||
@@ -219,7 +208,6 @@ impl std::default::Default for BlockDeviceConfigInfo {
|
||||
rate_limiter: None,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -361,7 +349,6 @@ impl BlockDeviceMgr {
|
||||
&mut self,
|
||||
mut ctx: DeviceOpContext,
|
||||
config: BlockDeviceConfigInfo,
|
||||
sender: mpsc::Sender<Option<i32>>,
|
||||
) -> std::result::Result<(), BlockDeviceError> {
|
||||
if !cfg!(feature = "hotplug") && ctx.is_hotplug {
|
||||
return Err(BlockDeviceError::UpdateNotAllowedPostBoot);
|
||||
@@ -393,68 +380,31 @@ impl BlockDeviceMgr {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut slot = 0;
|
||||
|
||||
let use_generic_irq = config.use_generic_irq.unwrap_or(USE_GENERIC_IRQ);
|
||||
|
||||
match config.device_type {
|
||||
BlockDeviceType::RawBlock => {
|
||||
let device = Self::create_blk_device(&config, &mut ctx)
|
||||
.map_err(BlockDeviceError::Virtio)?;
|
||||
|
||||
let dev = if let Some(true) = config.use_pci_bus {
|
||||
let pci_dev = DeviceManager::create_virtio_pci_device(
|
||||
device,
|
||||
&mut ctx,
|
||||
use_generic_irq,
|
||||
)
|
||||
.map_err(BlockDeviceError::DeviceManager)?;
|
||||
|
||||
let (_, devfn) = DeviceManager::get_pci_device_info(&pci_dev)?;
|
||||
slot = devfn >> 3;
|
||||
|
||||
pci_dev
|
||||
} else {
|
||||
DeviceManager::create_mmio_virtio_device(
|
||||
device,
|
||||
&mut ctx,
|
||||
config.use_shared_irq.unwrap_or(self.use_shared_irq),
|
||||
use_generic_irq,
|
||||
)
|
||||
.map_err(BlockDeviceError::DeviceManager)?
|
||||
};
|
||||
|
||||
let callback: Option<Box<dyn Fn(UpcallClientResponse) + Send>> =
|
||||
Some(Box::new(move |_| {
|
||||
// send the pci device slot to caller.
|
||||
let _ = sender.send(Some(slot as i32));
|
||||
}));
|
||||
|
||||
self.update_device_by_index(index, dev.clone())?;
|
||||
let dev = DeviceManager::create_mmio_virtio_device(
|
||||
device,
|
||||
&mut ctx,
|
||||
config.use_shared_irq.unwrap_or(self.use_shared_irq),
|
||||
config.use_generic_irq.unwrap_or(USE_GENERIC_IRQ),
|
||||
)
|
||||
.map_err(BlockDeviceError::DeviceManager)?;
|
||||
self.update_device_by_index(index, Arc::clone(&dev))?;
|
||||
// live-upgrade need save/restore device from info.device.
|
||||
self.info_list[index].set_device(dev.clone());
|
||||
|
||||
let mut cleanup = |e, ctx: DeviceOpContext| -> BlockDeviceError {
|
||||
ctx.insert_hotplug_mmio_device(&dev, None).map_err(|e| {
|
||||
let logger = ctx.logger().new(slog::o!());
|
||||
self.remove_device(ctx, &config.drive_id).unwrap();
|
||||
error!(
|
||||
logger,
|
||||
"failed to hot-add pci virtio block device {}, {:?}",
|
||||
"failed to hot-add virtio block device {}, {:?}",
|
||||
&config.drive_id,
|
||||
e
|
||||
);
|
||||
BlockDeviceError::DeviceManager(e)
|
||||
};
|
||||
|
||||
if let Some(true) = config.use_pci_bus {
|
||||
let _ = ctx
|
||||
.insert_hotplug_pci_device(&dev, callback)
|
||||
.map_err(|e| cleanup(e, ctx))?;
|
||||
Ok(())
|
||||
} else {
|
||||
ctx.insert_hotplug_mmio_device(&dev, callback)
|
||||
.map_err(|e| cleanup(e, ctx))
|
||||
}
|
||||
})
|
||||
}
|
||||
#[cfg(feature = "vhost-user-blk")]
|
||||
BlockDeviceType::Spool | BlockDeviceType::Spdk => {
|
||||
@@ -467,13 +417,8 @@ impl BlockDeviceMgr {
|
||||
config.use_generic_irq.unwrap_or(USE_GENERIC_IRQ),
|
||||
)
|
||||
.map_err(BlockDeviceError::DeviceManager)?;
|
||||
let callback: Option<Box<dyn Fn(UpcallClientResponse) + Send>> =
|
||||
Some(Box::new(move |_| {
|
||||
let _ = sender.send(None);
|
||||
}));
|
||||
|
||||
self.update_device_by_index(index, Arc::clone(&dev))?;
|
||||
ctx.insert_hotplug_mmio_device(&dev, callback).map_err(|e| {
|
||||
ctx.insert_hotplug_mmio_device(&dev, None).map_err(|e| {
|
||||
let logger = ctx.logger().new(slog::o!());
|
||||
self.remove_device(ctx, &config.drive_id).unwrap();
|
||||
error!(
|
||||
@@ -505,25 +450,15 @@ impl BlockDeviceMgr {
|
||||
info.config.drive_id,
|
||||
info.config.path_on_host.to_str().unwrap_or("<unknown>")
|
||||
);
|
||||
|
||||
let use_shared_irq = info.config.use_shared_irq.unwrap_or(self.use_shared_irq);
|
||||
let use_generic_irq = info.config.use_generic_irq.unwrap_or(USE_GENERIC_IRQ);
|
||||
let device = Self::create_blk_device(&info.config, ctx)
|
||||
.map_err(BlockDeviceError::Virtio)?;
|
||||
|
||||
let device = if let Some(true) = info.config.use_pci_bus {
|
||||
DeviceManager::create_virtio_pci_device(device, ctx, use_generic_irq)
|
||||
.map_err(BlockDeviceError::RegisterBlockDevice)?
|
||||
} else {
|
||||
DeviceManager::create_mmio_virtio_device(
|
||||
device,
|
||||
ctx,
|
||||
use_shared_irq,
|
||||
use_generic_irq,
|
||||
)
|
||||
.map_err(BlockDeviceError::RegisterBlockDevice)?
|
||||
};
|
||||
|
||||
let device = DeviceManager::create_mmio_virtio_device(
|
||||
device,
|
||||
ctx,
|
||||
info.config.use_shared_irq.unwrap_or(self.use_shared_irq),
|
||||
info.config.use_generic_irq.unwrap_or(USE_GENERIC_IRQ),
|
||||
)
|
||||
.map_err(BlockDeviceError::RegisterBlockDevice)?;
|
||||
info.device = Some(device);
|
||||
}
|
||||
#[cfg(feature = "vhost-user-blk")]
|
||||
@@ -561,7 +496,7 @@ impl BlockDeviceMgr {
|
||||
while let Some(mut info) = self.info_list.pop_back() {
|
||||
info!(ctx.logger(), "remove drive {}", info.config.drive_id);
|
||||
if let Some(device) = info.device.take() {
|
||||
DeviceManager::destroy_virtio_device(device, ctx)?;
|
||||
DeviceManager::destroy_mmio_virtio_device(device, ctx)?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,62 +510,6 @@ impl BlockDeviceMgr {
|
||||
}
|
||||
}
|
||||
|
||||
/// prepare to remove device
|
||||
pub fn prepare_remove_device(
|
||||
&self,
|
||||
ctx: &DeviceOpContext,
|
||||
blockdev_id: &str,
|
||||
result_sender: Sender<Option<i32>>,
|
||||
) -> Result<(), BlockDeviceError> {
|
||||
if !cfg!(feature = "hotplug") {
|
||||
return Err(BlockDeviceError::UpdateNotAllowedPostBoot);
|
||||
}
|
||||
|
||||
info!(ctx.logger(), "prepare remove block device");
|
||||
|
||||
let callback: Option<Box<dyn Fn(UpcallClientResponse) + Send>> =
|
||||
Some(Box::new(move |result| match result {
|
||||
UpcallClientResponse::DevMgr(response) => {
|
||||
if let DevMgrResponse::Other(resp) = response {
|
||||
if let Err(e) = result_sender.send(Some(resp.result)) {
|
||||
log::error!("send upcall result failed, due to {:?}!", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
UpcallClientResponse::UpcallReset => {
|
||||
if let Err(e) = result_sender.send(None) {
|
||||
log::error!("send upcall result failed, due to {:?}!", e);
|
||||
}
|
||||
}
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => {
|
||||
log::debug!("this arm should only be triggered under test");
|
||||
}
|
||||
}));
|
||||
|
||||
let device_index = self
|
||||
.get_index_of_drive_id(blockdev_id)
|
||||
.ok_or(BlockDeviceError::InvalidDeviceId(blockdev_id.to_string()))?;
|
||||
|
||||
let info = &self.info_list[device_index];
|
||||
if let Some(device) = info.device.as_ref() {
|
||||
if let Some(_mmio_dev) = device.as_any().downcast_ref::<DbsMmioV2Device>() {
|
||||
if callback.is_some() {
|
||||
ctx.remove_hotplug_mmio_device(device, callback)?;
|
||||
}
|
||||
} else if let Some(_pci_dev) = device.as_any().downcast_ref::<VirtioPciDevice<
|
||||
GuestAddressSpaceImpl,
|
||||
QueueSync,
|
||||
GuestRegionMmap,
|
||||
>>() {
|
||||
if callback.is_some() {
|
||||
ctx.remove_hotplug_pci_device(device, callback)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// remove a block device, it basically is the inverse operation of `insert_device``
|
||||
pub fn remove_device(
|
||||
&mut self,
|
||||
@@ -645,7 +524,7 @@ impl BlockDeviceMgr {
|
||||
Some(mut info) => {
|
||||
info!(ctx.logger(), "remove drive {}", info.config.drive_id);
|
||||
if let Some(device) = info.device.take() {
|
||||
DeviceManager::destroy_virtio_device(device, &mut ctx)
|
||||
DeviceManager::destroy_mmio_virtio_device(device, &mut ctx)
|
||||
.map_err(BlockDeviceError::DeviceManager)?;
|
||||
}
|
||||
}
|
||||
@@ -904,7 +783,7 @@ impl BlockDeviceMgr {
|
||||
pub fn update_device_by_index(
|
||||
&mut self,
|
||||
index: usize,
|
||||
device: Arc<dyn DeviceIo>,
|
||||
device: Arc<DbsMmioV2Device>,
|
||||
) -> Result<(), BlockDeviceError> {
|
||||
if let Some(info) = self.info_list.get_mut(index) {
|
||||
info.device = Some(device);
|
||||
@@ -939,21 +818,6 @@ impl BlockDeviceMgr {
|
||||
.map(|_p| ())
|
||||
.map_err(|_e| BlockDeviceError::BlockEpollHanderSendFail);
|
||||
}
|
||||
} else if let Some(pci_dev) = device.as_any().downcast_ref::<VirtioPciDevice<
|
||||
GuestAddressSpaceImpl,
|
||||
QueueSync,
|
||||
GuestRegionMmap,
|
||||
>>() {
|
||||
let inner_dev = pci_dev.device();
|
||||
if let Some(blk_dev) = inner_dev
|
||||
.as_any()
|
||||
.downcast_ref::<virtio::block::Block<GuestAddressSpaceImpl>>()
|
||||
{
|
||||
return blk_dev
|
||||
.set_patch_rate_limiters(new_cfg.bytes(), new_cfg.ops())
|
||||
.map(|_p| ())
|
||||
.map_err(|_e| BlockDeviceError::BlockEpollHanderSendFail);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -984,7 +848,6 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::device_manager::tests::create_address_space;
|
||||
use crate::test_utils::tests::create_vm_for_test;
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
#[test]
|
||||
fn test_block_device_type() {
|
||||
@@ -1024,16 +887,14 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
|
||||
let mut vm = crate::vm::tests::create_vm_instance();
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
let (sender, _receiver) = channel();
|
||||
assert!(vm
|
||||
.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, dummy_block_device.clone(), sender)
|
||||
.insert_device(ctx, dummy_block_device.clone(),)
|
||||
.is_ok());
|
||||
|
||||
assert_eq!(vm.device_manager().block_manager.info_list.len(), 1);
|
||||
@@ -1100,12 +961,10 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
let (sender, _receiver) = channel();
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(device_op_ctx, dummy_block_device, sender)
|
||||
.insert_device(device_op_ctx, dummy_block_device)
|
||||
.unwrap();
|
||||
|
||||
let cfg = BlockDeviceConfigUpdateInfo {
|
||||
@@ -1178,16 +1037,14 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
|
||||
let mut vm = crate::vm::tests::create_vm_instance();
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
let (sender, _receiver) = channel();
|
||||
assert!(vm
|
||||
.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, dummy_block_device.clone(), sender)
|
||||
.insert_device(ctx, dummy_block_device.clone(),)
|
||||
.is_ok());
|
||||
|
||||
assert_eq!(vm.device_manager().block_manager.info_list.len(), 1);
|
||||
@@ -1220,7 +1077,6 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
|
||||
let dummy_file_2 = TempFile::new().unwrap();
|
||||
@@ -1239,21 +1095,19 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
|
||||
let mut vm = crate::vm::tests::create_vm_instance();
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
let (sender, _receiver) = channel();
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, root_block_device_1, sender.clone())
|
||||
.insert_device(ctx, root_block_device_1)
|
||||
.unwrap();
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
assert!(vm
|
||||
.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, root_block_device_2, sender)
|
||||
.insert_device(ctx, root_block_device_2)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
@@ -1277,7 +1131,6 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
|
||||
let dummy_file_2 = TempFile::new().unwrap();
|
||||
@@ -1296,7 +1149,6 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
|
||||
let dummy_file_3 = TempFile::new().unwrap();
|
||||
@@ -1315,7 +1167,6 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
|
||||
let mut vm = crate::vm::tests::create_vm_instance();
|
||||
@@ -1335,24 +1186,23 @@ mod tests {
|
||||
assert!(vm.device_manager().block_manager.has_root_block_device(),);
|
||||
assert!(!vm.device_manager().block_manager.has_part_uuid_root());
|
||||
assert_eq!(vm.device_manager().block_manager.info_list.len(), 3);
|
||||
let (sender, _receiver) = channel();
|
||||
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, root_block_device, sender.clone())
|
||||
.insert_device(ctx, root_block_device)
|
||||
.unwrap();
|
||||
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, dummy_block_device_2, sender.clone())
|
||||
.insert_device(ctx, dummy_block_device_2)
|
||||
.unwrap();
|
||||
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, dummy_block_device_3, sender.clone())
|
||||
.insert_device(ctx, dummy_block_device_3)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@@ -1376,7 +1226,6 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
|
||||
let dummy_file_2 = TempFile::new().unwrap();
|
||||
@@ -1395,7 +1244,6 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
|
||||
let dummy_file_3 = TempFile::new().unwrap();
|
||||
@@ -1414,26 +1262,24 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
|
||||
let mut vm = crate::vm::tests::create_vm_instance();
|
||||
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
let (sender, _receiver) = channel();
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, dummy_block_device_2.clone(), sender.clone())
|
||||
.insert_device(ctx, dummy_block_device_2.clone())
|
||||
.unwrap();
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, dummy_block_device_3.clone(), sender.clone())
|
||||
.insert_device(ctx, dummy_block_device_3.clone())
|
||||
.unwrap();
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, root_block_device.clone(), sender.clone())
|
||||
.insert_device(ctx, root_block_device.clone())
|
||||
.unwrap();
|
||||
|
||||
assert!(vm.device_manager().block_manager.has_root_block_device(),);
|
||||
@@ -1476,7 +1322,6 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
|
||||
let dummy_file_2 = TempFile::new().unwrap();
|
||||
@@ -1495,22 +1340,20 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
|
||||
let mut vm = crate::vm::tests::create_vm_instance();
|
||||
let (sender, _receiver) = channel();
|
||||
|
||||
// Add 2 block devices.
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, root_block_device, sender.clone())
|
||||
.insert_device(ctx, root_block_device)
|
||||
.unwrap();
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, dummy_block_device_2.clone(), sender.clone())
|
||||
.insert_device(ctx, dummy_block_device_2.clone())
|
||||
.unwrap();
|
||||
|
||||
// Get index zero.
|
||||
@@ -1541,7 +1384,7 @@ mod tests {
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, dummy_block_device_2.clone(), sender.clone())
|
||||
.insert_device(ctx, dummy_block_device_2.clone())
|
||||
.unwrap();
|
||||
|
||||
let index = vm
|
||||
@@ -1564,7 +1407,7 @@ mod tests {
|
||||
assert!(vm
|
||||
.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, dummy_block_device_2.clone(), sender.clone())
|
||||
.insert_device(ctx, dummy_block_device_2.clone(),)
|
||||
.is_err());
|
||||
|
||||
// Update with 2 root block devices.
|
||||
@@ -1574,7 +1417,7 @@ mod tests {
|
||||
assert!(vm
|
||||
.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, dummy_block_device_2, sender.clone())
|
||||
.insert_device(ctx, dummy_block_device_2,)
|
||||
.is_err(),);
|
||||
|
||||
// Switch roots and add a PARTUUID for the new one.
|
||||
@@ -1592,7 +1435,6 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
let root_block_device_new = BlockDeviceConfigInfo {
|
||||
path_on_host: dummy_path_2,
|
||||
@@ -1608,17 +1450,16 @@ mod tests {
|
||||
queue_size: 128,
|
||||
use_shared_irq: None,
|
||||
use_generic_irq: None,
|
||||
use_pci_bus: Some(true),
|
||||
};
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, root_block_device_old, sender.clone())
|
||||
.insert_device(ctx, root_block_device_old)
|
||||
.unwrap();
|
||||
let ctx = DeviceOpContext::create_boot_ctx(&vm, None);
|
||||
vm.device_manager_mut()
|
||||
.block_manager
|
||||
.insert_device(ctx, root_block_device_new, sender.clone())
|
||||
.insert_device(ctx, root_block_device_new)
|
||||
.unwrap();
|
||||
assert!(vm.device_manager().block_manager.has_part_uuid_root);
|
||||
}
|
||||
|
||||
@@ -310,7 +310,7 @@ impl MemDeviceMgr {
|
||||
pub fn remove_devices(&self, ctx: &mut DeviceOpContext) -> Result<(), DeviceMgrError> {
|
||||
for info in self.info_list.iter() {
|
||||
if let Some(device) = &info.device {
|
||||
DeviceManager::destroy_mmio_device(device.clone(), ctx)?;
|
||||
DeviceManager::destroy_mmio_virtio_device(device.clone(), ctx)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,19 +13,17 @@ use arc_swap::ArcSwap;
|
||||
use dbs_address_space::AddressSpace;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use dbs_arch::{DeviceType, MMIODeviceInfo};
|
||||
use dbs_boot::layout::MMIO_LOW_END;
|
||||
use dbs_device::device_manager::{Error as IoManagerError, IoManager, IoManagerContext};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use dbs_device::resources::DeviceResources;
|
||||
use dbs_device::resources::Resource;
|
||||
use dbs_device::DeviceIo;
|
||||
use dbs_interrupt::KvmIrqManager;
|
||||
use dbs_legacy_devices::ConsoleHandler;
|
||||
#[cfg(feature = "dbs-virtio-devices")]
|
||||
use dbs_pci::CAPABILITY_BAR_SIZE;
|
||||
#[cfg(all(feature = "host-device", target_arch = "aarch64"))]
|
||||
use dbs_pci::PciBusResources;
|
||||
use dbs_utils::epoll_manager::EpollManager;
|
||||
use kvm_ioctls::VmFd;
|
||||
use log::error;
|
||||
use virtio_queue::QueueSync;
|
||||
|
||||
#[cfg(feature = "dbs-virtio-devices")]
|
||||
use dbs_device::resources::ResourceConstraint;
|
||||
@@ -42,7 +40,6 @@ use dbs_virtio_devices::{
|
||||
|
||||
#[cfg(feature = "host-device")]
|
||||
use dbs_pci::VfioPciDevice;
|
||||
use dbs_pci::VirtioPciDevice;
|
||||
#[cfg(all(feature = "hotplug", feature = "dbs-upcall"))]
|
||||
use dbs_upcall::{
|
||||
DevMgrRequest, DevMgrService, MmioDevRequest, PciDevRequest, UpcallClient, UpcallClientError,
|
||||
@@ -60,8 +57,6 @@ use crate::resource_manager::ResourceManager;
|
||||
use crate::vm::{KernelConfigInfo, Vm, VmConfigInfo};
|
||||
use crate::IoManagerCached;
|
||||
|
||||
use vm_memory::GuestRegionMmap;
|
||||
|
||||
/// Virtual machine console device manager.
|
||||
pub mod console_manager;
|
||||
/// Console Manager for virtual machines console device.
|
||||
@@ -136,9 +131,6 @@ macro_rules! info(
|
||||
};
|
||||
);
|
||||
|
||||
// The flag of whether to use the shared irq.
|
||||
const USE_SHARED_IRQ: bool = true;
|
||||
|
||||
/// Errors related to device manager operations.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum DeviceMgrError {
|
||||
@@ -181,28 +173,13 @@ pub enum DeviceMgrError {
|
||||
HotplugDevice(#[source] UpcallClientError),
|
||||
|
||||
/// Failed to free device resource.
|
||||
#[error("failed to allocate/free device resources: {0}")]
|
||||
#[error("failed to free device resources: {0}")]
|
||||
ResourceError(#[source] crate::resource_manager::ResourceError),
|
||||
|
||||
#[cfg(feature = "host-device")]
|
||||
/// Error from Vfio Pci
|
||||
#[error("failed to do vfio pci operation: {0:?}")]
|
||||
VfioPci(#[source] dbs_pci::VfioPciError),
|
||||
/// Error from Virtio Pci
|
||||
#[error("failed to do virtio pci operation")]
|
||||
VirtioPci,
|
||||
/// PCI system manager error
|
||||
#[error("Pci system manager error")]
|
||||
PciSystemManager,
|
||||
/// Dragonball pci system error
|
||||
#[error("pci error: {0:?}")]
|
||||
PciError(#[source] dbs_pci::Error),
|
||||
/// Virtio Pci system error
|
||||
#[error("virtio pci error: {0:?}")]
|
||||
VirtioPciError(#[source] dbs_pci::VirtioPciDeviceError),
|
||||
/// Unsupported pci device type
|
||||
#[error("unsupported pci device type")]
|
||||
InvalidPciDeviceType,
|
||||
}
|
||||
|
||||
/// Specialized version of `std::result::Result` for device manager operations.
|
||||
@@ -313,10 +290,9 @@ pub struct DeviceOpContext {
|
||||
#[cfg(all(feature = "hotplug", feature = "dbs-upcall"))]
|
||||
upcall_client: Option<Arc<UpcallClient<DevMgrService>>>,
|
||||
#[cfg(feature = "dbs-virtio-devices")]
|
||||
virtio_devices: Vec<Arc<dyn DeviceIo>>,
|
||||
virtio_devices: Vec<Arc<DbsMmioV2Device>>,
|
||||
#[cfg(feature = "host-device")]
|
||||
vfio_manager: Option<Arc<Mutex<VfioDeviceMgr>>>,
|
||||
pci_system_manager: Arc<Mutex<PciSystemManager>>,
|
||||
vm_config: Option<VmConfigInfo>,
|
||||
shared_info: Arc<RwLock<InstanceInfo>>,
|
||||
}
|
||||
@@ -367,7 +343,6 @@ impl DeviceOpContext {
|
||||
shared_info,
|
||||
#[cfg(feature = "host-device")]
|
||||
vfio_manager: None,
|
||||
pci_system_manager: device_mgr.pci_system_manager.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,11 +444,6 @@ impl DeviceOpContext {
|
||||
}
|
||||
Ok(dev_info)
|
||||
}
|
||||
|
||||
/// check the hotplug context
|
||||
pub fn is_hotplug(&self) -> bool {
|
||||
self.is_hotplug
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "hotplug", not(feature = "dbs-upcall")))]
|
||||
@@ -543,7 +513,7 @@ impl DeviceOpContext {
|
||||
|
||||
pub(crate) fn insert_hotplug_mmio_device(
|
||||
&self,
|
||||
dev: &Arc<dyn DeviceIo>,
|
||||
dev: &Arc<DbsMmioV2Device>,
|
||||
callback: Option<Box<dyn Fn(UpcallClientResponse) + Send>>,
|
||||
) -> Result<()> {
|
||||
if !self.is_hotplug {
|
||||
@@ -562,7 +532,7 @@ impl DeviceOpContext {
|
||||
|
||||
pub(crate) fn remove_hotplug_mmio_device(
|
||||
&self,
|
||||
dev: &Arc<dyn DeviceIo>,
|
||||
dev: &Arc<DbsMmioV2Device>,
|
||||
callback: Option<Box<dyn Fn(UpcallClientResponse) + Send>>,
|
||||
) -> Result<()> {
|
||||
if !self.is_hotplug {
|
||||
@@ -660,7 +630,6 @@ pub struct DeviceManager {
|
||||
vhost_user_net_manager: VhostUserNetDeviceMgr,
|
||||
#[cfg(feature = "host-device")]
|
||||
pub(crate) vfio_manager: Arc<Mutex<VfioDeviceMgr>>,
|
||||
pub(crate) pci_system_manager: Arc<Mutex<PciSystemManager>>,
|
||||
}
|
||||
|
||||
impl DeviceManager {
|
||||
@@ -671,25 +640,11 @@ impl DeviceManager {
|
||||
epoll_manager: EpollManager,
|
||||
logger: &slog::Logger,
|
||||
shared_info: Arc<RwLock<InstanceInfo>>,
|
||||
) -> Result<Self> {
|
||||
let irq_manager = Arc::new(KvmIrqManager::new(vm_fd.clone()));
|
||||
let io_manager = Arc::new(ArcSwap::new(Arc::new(IoManager::new())));
|
||||
let io_lock = Arc::new(Mutex::new(()));
|
||||
let io_context = DeviceManagerContext::new(io_manager.clone(), io_lock.clone());
|
||||
let mut mgr = PciSystemManager::new(irq_manager.clone(), io_context, res_manager.clone())?;
|
||||
|
||||
let requirements = mgr.resource_requirements();
|
||||
let resources = res_manager
|
||||
.allocate_device_resources(&requirements, USE_SHARED_IRQ)
|
||||
.map_err(DeviceMgrError::ResourceError)?;
|
||||
mgr.activate(resources)?;
|
||||
|
||||
let pci_system_manager = Arc::new(Mutex::new(mgr));
|
||||
|
||||
Ok(DeviceManager {
|
||||
io_manager,
|
||||
io_lock,
|
||||
irq_manager,
|
||||
) -> Self {
|
||||
DeviceManager {
|
||||
io_manager: Arc::new(ArcSwap::new(Arc::new(IoManager::new()))),
|
||||
io_lock: Arc::new(Mutex::new(())),
|
||||
irq_manager: Arc::new(KvmIrqManager::new(vm_fd.clone())),
|
||||
res_manager,
|
||||
vm_fd: vm_fd.clone(),
|
||||
logger: logger.new(slog::o!()),
|
||||
@@ -716,13 +671,8 @@ impl DeviceManager {
|
||||
#[cfg(feature = "vhost-user-net")]
|
||||
vhost_user_net_manager: VhostUserNetDeviceMgr::default(),
|
||||
#[cfg(feature = "host-device")]
|
||||
vfio_manager: Arc::new(Mutex::new(VfioDeviceMgr::new(
|
||||
vm_fd,
|
||||
pci_system_manager.clone(),
|
||||
logger,
|
||||
))),
|
||||
pci_system_manager,
|
||||
})
|
||||
vfio_manager: Arc::new(Mutex::new(VfioDeviceMgr::new(vm_fd, logger))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the underlying IoManager to dispatch IO read/write requests.
|
||||
@@ -1074,7 +1024,7 @@ impl DeviceManager {
|
||||
}
|
||||
|
||||
#[cfg(feature = "dbs-virtio-devices")]
|
||||
fn get_virtio_mmio_device_info(device: &Arc<dyn DeviceIo>) -> Result<(u64, u64, u32)> {
|
||||
fn get_virtio_mmio_device_info(device: &Arc<DbsMmioV2Device>) -> Result<(u64, u64, u32)> {
|
||||
let resources = device.get_assigned_resources();
|
||||
let irq = resources
|
||||
.get_legacy_irq()
|
||||
@@ -1088,11 +1038,26 @@ impl DeviceManager {
|
||||
|
||||
Err(DeviceMgrError::GetDeviceResource)
|
||||
}
|
||||
|
||||
/// Get pci bus resources for creating fdt.
|
||||
#[cfg(feature = "host-device")]
|
||||
pub fn get_pci_bus_resources(&self) -> Option<PciBusResources> {
|
||||
let mut vfio_dev_mgr = self.vfio_manager.lock().unwrap();
|
||||
let vfio_pci_mgr = vfio_dev_mgr.get_pci_manager();
|
||||
vfio_pci_mgr.as_ref()?;
|
||||
let pci_manager = vfio_pci_mgr.unwrap();
|
||||
let ecam_space = pci_manager.get_ecam_space();
|
||||
let bar_space = pci_manager.get_bar_space();
|
||||
Some(PciBusResources {
|
||||
ecam_space,
|
||||
bar_space,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "dbs-virtio-devices")]
|
||||
impl DeviceManager {
|
||||
fn get_virtio_device_info(device: &Arc<dyn DeviceIo>) -> Result<(u64, u64, u32)> {
|
||||
fn get_virtio_device_info(device: &Arc<DbsMmioV2Device>) -> Result<(u64, u64, u32)> {
|
||||
let resources = device.get_assigned_resources();
|
||||
let irq = resources
|
||||
.get_legacy_irq()
|
||||
@@ -1114,7 +1079,7 @@ impl DeviceManager {
|
||||
ctx: &mut DeviceOpContext,
|
||||
use_shared_irq: bool,
|
||||
use_generic_irq: bool,
|
||||
) -> std::result::Result<Arc<dyn DeviceIo>, DeviceMgrError> {
|
||||
) -> std::result::Result<Arc<DbsMmioV2Device>, DeviceMgrError> {
|
||||
let features = DRAGONBALL_FEATURE_INTR_USED | DRAGONBALL_FEATURE_PER_QUEUE_NOTIFY;
|
||||
DeviceManager::create_mmio_virtio_device_with_features(
|
||||
device,
|
||||
@@ -1132,7 +1097,7 @@ impl DeviceManager {
|
||||
ctx: &mut DeviceOpContext,
|
||||
use_shared_irq: bool,
|
||||
use_generic_irq: bool,
|
||||
) -> std::result::Result<Arc<dyn DeviceIo>, DeviceMgrError> {
|
||||
) -> std::result::Result<Arc<DbsMmioV2Device>, DeviceMgrError> {
|
||||
let features = DRAGONBALL_FEATURE_PER_QUEUE_NOTIFY;
|
||||
DeviceManager::create_mmio_virtio_device_with_features(
|
||||
device,
|
||||
@@ -1151,7 +1116,7 @@ impl DeviceManager {
|
||||
features: Option<u32>,
|
||||
use_shared_irq: bool,
|
||||
use_generic_irq: bool,
|
||||
) -> std::result::Result<Arc<dyn DeviceIo>, DeviceMgrError> {
|
||||
) -> std::result::Result<Arc<DbsMmioV2Device>, DeviceMgrError> {
|
||||
// Every emulated Virtio MMIO device needs a 4K configuration space,
|
||||
// and another 4K space for per queue notification.
|
||||
const MMIO_ADDRESS_DEFAULT: ResourceConstraint = ResourceConstraint::MmioAddress {
|
||||
@@ -1182,18 +1147,12 @@ impl DeviceManager {
|
||||
Self::register_mmio_virtio_device(Arc::new(virtio_dev), ctx)
|
||||
}
|
||||
|
||||
fn destroy_mmio_device(
|
||||
/// Teardown the Virtio MMIO transport layer device associated with the virtio backend device.
|
||||
pub fn destroy_mmio_virtio_device(
|
||||
device: Arc<dyn DeviceIo>,
|
||||
ctx: &mut DeviceOpContext,
|
||||
) -> std::result::Result<(), DeviceMgrError> {
|
||||
// unregister IoManager
|
||||
Self::deregister_virtio_device(&device, ctx)?;
|
||||
|
||||
// unregister Resource manager
|
||||
let resources = device.get_assigned_resources();
|
||||
ctx.res_manager
|
||||
.free_device_resources(&resources)
|
||||
.map_err(DeviceMgrError::ResourceError)?;
|
||||
Self::destroy_mmio_device(device.clone(), ctx)?;
|
||||
|
||||
let mmio_dev = device
|
||||
.as_any()
|
||||
@@ -1205,11 +1164,27 @@ impl DeviceManager {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Create an Virtio MMIO transport layer device for the virtio backend device.
|
||||
pub fn register_mmio_virtio_device(
|
||||
fn destroy_mmio_device(
|
||||
device: Arc<dyn DeviceIo>,
|
||||
ctx: &mut DeviceOpContext,
|
||||
) -> std::result::Result<Arc<dyn DeviceIo>, DeviceMgrError> {
|
||||
) -> std::result::Result<(), DeviceMgrError> {
|
||||
// unregister IoManager
|
||||
Self::deregister_mmio_virtio_device(&device, ctx)?;
|
||||
|
||||
// unregister Resource manager
|
||||
let resources = device.get_assigned_resources();
|
||||
ctx.res_manager
|
||||
.free_device_resources(&resources)
|
||||
.map_err(DeviceMgrError::ResourceError)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Create an Virtio MMIO transport layer device for the virtio backend device.
|
||||
pub fn register_mmio_virtio_device(
|
||||
device: Arc<DbsMmioV2Device>,
|
||||
ctx: &mut DeviceOpContext,
|
||||
) -> std::result::Result<Arc<DbsMmioV2Device>, DeviceMgrError> {
|
||||
let (mmio_base, mmio_size, irq) = Self::get_virtio_device_info(&device)?;
|
||||
info!(
|
||||
ctx.logger(),
|
||||
@@ -1251,210 +1226,8 @@ impl DeviceManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an Virtio PCI transport layer device for the virtio backend device.
|
||||
pub fn create_virtio_pci_device(
|
||||
mut device: DbsVirtioDevice,
|
||||
ctx: &mut DeviceOpContext,
|
||||
use_generic_irq: bool,
|
||||
) -> std::result::Result<Arc<dyn DeviceIo>, DeviceMgrError> {
|
||||
let pci_system_manager = ctx.pci_system_manager.lock().unwrap();
|
||||
|
||||
// We always use 64bit bars, we don't support 32bit bar now
|
||||
// We aligned to the size of the bar itself, refers to cloud-hypervisor
|
||||
// https://github.com/cloud-hypervisor/cloud-hypervisor/commit/bfc65bff2a5bdb9aca7dcd3284a0ced0e5cc7db8
|
||||
//
|
||||
// Allocate virtio-pci config bar below MMIO_LOW_END.
|
||||
// Each bridge PCI bridge only has two bridge windows:
|
||||
// - One is non-prefetchable and located below `MMIO_LOW_END`.
|
||||
// - The other is prefetchable and located above `MMIO_LOW_END`.
|
||||
// In reference to `clh`, the config BAR is set as non-prefetchable.
|
||||
// Therefore, it must be allocated below `MMIO_LOW_END`.
|
||||
const DEFAULE_VIRTIO_PCI_CONFIG_BAR: ResourceConstraint = ResourceConstraint::MmioAddress {
|
||||
range: Some((0, MMIO_LOW_END)),
|
||||
align: CAPABILITY_BAR_SIZE,
|
||||
size: CAPABILITY_BAR_SIZE,
|
||||
};
|
||||
|
||||
// Virtio pci device always use msi-x, extend irq resources to other_requests
|
||||
let mut other_requests = vec![];
|
||||
VirtioPciDevice::get_interrupt_requirements(device.as_ref(), &mut other_requests);
|
||||
|
||||
// allocate device resources by pci_bus, MmioAddress + KvmSlot?
|
||||
let mut device_requests = vec![];
|
||||
device.get_resource_requirements(&mut device_requests, use_generic_irq);
|
||||
|
||||
// Extend KvmSlot resources to other_requests
|
||||
for req in device_requests.iter() {
|
||||
if !matches!(
|
||||
req,
|
||||
ResourceConstraint::PioAddress { .. } | ResourceConstraint::MmioAddress { .. }
|
||||
) {
|
||||
other_requests.push(*req);
|
||||
}
|
||||
}
|
||||
|
||||
// allocate PciMsixIrq and KvmSlot by res_manager
|
||||
let other_resources = ctx
|
||||
.res_manager
|
||||
.allocate_device_resources(&other_requests, false)
|
||||
.map_err(DeviceMgrError::ResourceError)?;
|
||||
|
||||
let pci_bus = pci_system_manager.pci_root_bus();
|
||||
let dev_id = pci_system_manager
|
||||
.new_device_id(None)
|
||||
.ok_or(DeviceMgrError::VirtioPci)?;
|
||||
|
||||
// Allocate config bar resources by pci_bus
|
||||
let default_config_req = vec![DEFAULE_VIRTIO_PCI_CONFIG_BAR];
|
||||
let default_config_res = pci_bus
|
||||
.allocate_resources(&default_config_req)
|
||||
.map_err(DeviceMgrError::PciError)?;
|
||||
assert!(default_config_res.get_all_resources().len() == 1);
|
||||
|
||||
// Allocate MmioAddress and PioAddress resource by pci bus, other resourece type will skip
|
||||
let mut device_resource = pci_bus
|
||||
.allocate_resources(&device_requests)
|
||||
.map_err(DeviceMgrError::PciError)?;
|
||||
|
||||
// Extend PciMsixIrq and KvmSlot resources to device_resource
|
||||
other_resources.get_all_resources().iter().for_each(|res| {
|
||||
device_resource.append(res.clone());
|
||||
});
|
||||
|
||||
// Do map for virtio share memory region by set_resource, this will use KvmSlot + MmioAddress resources, which should be allocated before
|
||||
let _virito_shared_mem_list = device
|
||||
.as_mut()
|
||||
.set_resource(ctx.vm_fd.clone(), device_resource.clone())
|
||||
.map_err(DeviceMgrError::Virtio)?;
|
||||
|
||||
// Extend config bar resources to device_resource
|
||||
// Now device_resource contains all resources
|
||||
default_config_res
|
||||
.get_all_resources()
|
||||
.iter()
|
||||
.for_each(|res| {
|
||||
device_resource.append(res.clone());
|
||||
});
|
||||
|
||||
drop(pci_system_manager);
|
||||
|
||||
// new a virtio pci device
|
||||
let mut virtio_dev = VirtioPciDevice::new(
|
||||
ctx.vm_fd.clone(),
|
||||
ctx.get_vm_as()?,
|
||||
ctx.get_address_space()?,
|
||||
ctx.irq_manager.clone(),
|
||||
device_resource,
|
||||
dev_id,
|
||||
device,
|
||||
true,
|
||||
Arc::downgrade(&pci_bus),
|
||||
default_config_res.get_all_resources()[0].clone(),
|
||||
)
|
||||
.map_err(DeviceMgrError::VirtioPciError)?;
|
||||
|
||||
virtio_dev
|
||||
.alloc_bars()
|
||||
.map_err(DeviceMgrError::VirtioPciError)?;
|
||||
|
||||
let arc_dev = Arc::new(virtio_dev);
|
||||
|
||||
pci_bus
|
||||
.register_device(arc_dev.clone())
|
||||
.map_err(DeviceMgrError::PciError)?;
|
||||
|
||||
Self::register_virtio_pci_device(arc_dev, ctx)
|
||||
}
|
||||
|
||||
/// Create an Virtio PCI transport layer device for the virtio backend device.
|
||||
pub fn register_virtio_pci_device(
|
||||
device: Arc<dyn DeviceIo>,
|
||||
ctx: &DeviceOpContext,
|
||||
) -> std::result::Result<Arc<dyn DeviceIo>, DeviceMgrError> {
|
||||
let resources = device.get_trapped_io_resources();
|
||||
let mut tx = ctx.io_context.begin_tx();
|
||||
if let Err(e) = ctx
|
||||
.io_context
|
||||
.register_device_io(&mut tx, device.clone(), &resources)
|
||||
{
|
||||
ctx.io_context.cancel_tx(tx);
|
||||
Err(DeviceMgrError::IoManager(e))
|
||||
} else {
|
||||
ctx.io_context.commit_tx(tx);
|
||||
Ok(device)
|
||||
}
|
||||
}
|
||||
|
||||
/// Deregister Virtio device from IoManager
|
||||
pub fn deregister_virtio_device(
|
||||
device: &Arc<dyn DeviceIo>,
|
||||
ctx: &mut DeviceOpContext,
|
||||
) -> std::result::Result<(), DeviceMgrError> {
|
||||
let resources = device.get_trapped_io_resources();
|
||||
info!(
|
||||
ctx.logger(),
|
||||
"unregister pci virtio device: {:?}", resources
|
||||
);
|
||||
let mut tx = ctx.io_context.begin_tx();
|
||||
if let Err(e) = ctx.io_context.unregister_device_io(&mut tx, &resources) {
|
||||
ctx.io_context.cancel_tx(tx);
|
||||
Err(DeviceMgrError::IoManager(e))
|
||||
} else {
|
||||
ctx.io_context.commit_tx(tx);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Destroy/Deregister resources for a Virtio PCI
|
||||
fn destroy_pci_device(
|
||||
device: Arc<dyn DeviceIo>,
|
||||
ctx: &mut DeviceOpContext,
|
||||
dev_id: u8,
|
||||
) -> std::result::Result<(), DeviceMgrError> {
|
||||
// unregister IoManager
|
||||
Self::deregister_virtio_device(&device, ctx)?;
|
||||
// unregister Resource manager
|
||||
let resources = device.get_assigned_resources();
|
||||
let mut system_resources = DeviceResources::new();
|
||||
resources.iter().for_each(|res| {
|
||||
if !matches!(
|
||||
res,
|
||||
Resource::PioAddressRange { .. } | Resource::MmioAddressRange { .. }
|
||||
) {
|
||||
system_resources.append(res.clone());
|
||||
}
|
||||
});
|
||||
info!(
|
||||
ctx.logger(),
|
||||
"unregister resource {:?} from system resource manager for pci device",
|
||||
system_resources
|
||||
);
|
||||
ctx.res_manager
|
||||
.free_device_resources(&system_resources)
|
||||
.map_err(DeviceMgrError::ResourceError)?;
|
||||
let pci_system_manager = ctx.pci_system_manager.lock().unwrap();
|
||||
let pci_bus = pci_system_manager.pci_root_bus();
|
||||
info!(
|
||||
ctx.logger(),
|
||||
"unregister resource {:?} from pci bus resource manager for pci device", resources
|
||||
);
|
||||
pci_bus.free_resources(resources);
|
||||
let _ = pci_system_manager.free_device_id(dev_id as u32);
|
||||
|
||||
let pci_dev = device
|
||||
.as_any()
|
||||
.downcast_ref::<VirtioPciDevice<GuestAddressSpaceImpl, QueueSync, GuestRegionMmap>>()
|
||||
.ok_or(DeviceMgrError::InvalidOperation)?;
|
||||
|
||||
pci_dev.remove();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "host-device")]
|
||||
fn get_pci_device_info(device: &Arc<dyn DeviceIo>) -> Result<(u8, u8)> {
|
||||
use virtio_queue::QueueSync;
|
||||
|
||||
if let Some(pci_dev) = device
|
||||
.as_any()
|
||||
.downcast_ref::<VfioPciDevice<PciSystemManager>>()
|
||||
@@ -1471,41 +1244,10 @@ impl DeviceManager {
|
||||
// together those 8 bits combined as devfn value
|
||||
let devfn = (((slot) & 0x1f) << 3) | ((func) & 0x07);
|
||||
|
||||
return Ok((busno, devfn));
|
||||
} else if let Some(pci_dev) = device.as_any().downcast_ref::<VirtioPciDevice<
|
||||
GuestAddressSpaceImpl,
|
||||
QueueSync,
|
||||
GuestRegionMmap,
|
||||
>>() {
|
||||
// reference from kernel: include/uapi/linux/pci.h
|
||||
let busno = pci_dev.bus_id().map_err(DeviceMgrError::VirtioPciError)?;
|
||||
let slot = pci_dev.device_id();
|
||||
let func = 0;
|
||||
let devfn = (((slot) & 0x1f) << 3) | ((func) & 0x07);
|
||||
|
||||
return Ok((busno, devfn));
|
||||
}
|
||||
|
||||
Err(DeviceMgrError::InvalidPciDeviceType)
|
||||
}
|
||||
|
||||
/// Teardown the Virtio PCI or MMIO transport layer device associated with the virtio backend device.
|
||||
pub fn destroy_virtio_device(
|
||||
device: Arc<dyn DeviceIo>,
|
||||
ctx: &mut DeviceOpContext,
|
||||
) -> std::result::Result<(), DeviceMgrError> {
|
||||
if let Some(mmio_dev) = device.as_any().downcast_ref::<DbsMmioV2Device>() {
|
||||
Self::destroy_mmio_device(device.clone(), ctx)?;
|
||||
mmio_dev.remove();
|
||||
} else if let Some(pci_dev) = device.as_any().downcast_ref::<VirtioPciDevice<
|
||||
GuestAddressSpaceImpl,
|
||||
QueueSync,
|
||||
GuestRegionMmap,
|
||||
>>() {
|
||||
Self::destroy_pci_device(device.clone(), ctx, pci_dev.device_id())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Err(DeviceMgrError::GetDeviceResource)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1570,29 +1312,12 @@ mod tests {
|
||||
String::from("1"),
|
||||
)));
|
||||
|
||||
let irq_manager = Arc::new(KvmIrqManager::new(vm_fd.clone()));
|
||||
let io_manager = Arc::new(ArcSwap::new(Arc::new(IoManager::new())));
|
||||
let io_lock = Arc::new(Mutex::new(()));
|
||||
let io_context = DeviceManagerContext::new(io_manager.clone(), io_lock.clone());
|
||||
let mut mgr =
|
||||
PciSystemManager::new(irq_manager.clone(), io_context, res_manager.clone())
|
||||
.unwrap();
|
||||
|
||||
let requirements = mgr.resource_requirements();
|
||||
let resources = res_manager
|
||||
.allocate_device_resources(&requirements, USE_SHARED_IRQ)
|
||||
.map_err(DeviceMgrError::ResourceError)
|
||||
.unwrap();
|
||||
mgr.activate(resources).unwrap();
|
||||
|
||||
let pci_system_manager = Arc::new(Mutex::new(mgr));
|
||||
|
||||
DeviceManager {
|
||||
vm_fd: Arc::clone(&vm_fd),
|
||||
con_manager: ConsoleManager::new(epoll_manager, &logger),
|
||||
io_manager,
|
||||
io_lock,
|
||||
irq_manager,
|
||||
io_manager: Arc::new(ArcSwap::new(Arc::new(IoManager::new()))),
|
||||
io_lock: Arc::new(Mutex::new(())),
|
||||
irq_manager: Arc::new(KvmIrqManager::new(vm_fd.clone())),
|
||||
res_manager,
|
||||
|
||||
legacy_manager: None,
|
||||
@@ -1615,12 +1340,7 @@ mod tests {
|
||||
#[cfg(feature = "vhost-user-net")]
|
||||
vhost_user_net_manager: VhostUserNetDeviceMgr::default(),
|
||||
#[cfg(feature = "host-device")]
|
||||
vfio_manager: Arc::new(Mutex::new(VfioDeviceMgr::new(
|
||||
vm_fd,
|
||||
pci_system_manager.clone(),
|
||||
&logger,
|
||||
))),
|
||||
pci_system_manager,
|
||||
vfio_manager: Arc::new(Mutex::new(VfioDeviceMgr::new(vm_fd, &logger))),
|
||||
|
||||
logger,
|
||||
shared_info,
|
||||
|
||||
@@ -17,11 +17,12 @@ use std::ops::Deref;
|
||||
use std::os::fd::RawFd;
|
||||
use std::path::Path;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::sync::{Arc, Mutex, Weak};
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
use dbs_device::resources::Resource::LegacyIrq;
|
||||
use dbs_device::resources::{DeviceResources, Resource, ResourceConstraint};
|
||||
use dbs_device::DeviceIo;
|
||||
use dbs_interrupt::KvmIrqManager;
|
||||
use dbs_pci::{VfioPciDevice, VENDOR_NVIDIA};
|
||||
use dbs_upcall::{DevMgrResponse, UpcallClientResponse};
|
||||
use kvm_ioctls::{DeviceFd, VmFd};
|
||||
@@ -36,8 +37,8 @@ use vm_memory::{
|
||||
use super::StartMicroVmError;
|
||||
use crate::address_space_manager::{GuestAddressSpaceImpl, GuestMemoryImpl};
|
||||
use crate::config_manager::{ConfigItem, DeviceConfigInfo, DeviceConfigInfos};
|
||||
use crate::device_manager::{DeviceMgrError, DeviceOpContext};
|
||||
use crate::resource_manager::ResourceError;
|
||||
use crate::device_manager::{DeviceManagerContext, DeviceMgrError, DeviceOpContext};
|
||||
use crate::resource_manager::{ResourceError, ResourceManager};
|
||||
|
||||
// The flag of whether to use the shared irq.
|
||||
const USE_SHARED_IRQ: bool = true;
|
||||
@@ -229,7 +230,7 @@ pub struct VfioDeviceMgr {
|
||||
info_list: DeviceConfigInfos<HostDeviceConfig>,
|
||||
locked_vm_size: u64,
|
||||
vfio_container: Option<Arc<VfioContainer>>,
|
||||
pci_system_manager: Arc<Mutex<PciSystemManager>>,
|
||||
pci_vfio_manager: Option<Arc<PciSystemManager>>,
|
||||
pci_legacy_irqs: Option<HashMap<u8, u8>>,
|
||||
nvidia_shared_irq: Option<u32>,
|
||||
logger: slog::Logger,
|
||||
@@ -237,17 +238,13 @@ pub struct VfioDeviceMgr {
|
||||
|
||||
impl VfioDeviceMgr {
|
||||
/// Create a new VFIO device manager.
|
||||
pub fn new(
|
||||
vm_fd: Arc<VmFd>,
|
||||
pci_system_manager: Arc<Mutex<PciSystemManager>>,
|
||||
logger: &slog::Logger,
|
||||
) -> Self {
|
||||
pub fn new(vm_fd: Arc<VmFd>, logger: &slog::Logger) -> Self {
|
||||
VfioDeviceMgr {
|
||||
vm_fd,
|
||||
info_list: DeviceConfigInfos::new(),
|
||||
locked_vm_size: 0,
|
||||
vfio_container: None,
|
||||
pci_system_manager,
|
||||
pci_vfio_manager: None,
|
||||
pci_legacy_irqs: Some(HashMap::new()),
|
||||
nvidia_shared_irq: None,
|
||||
logger: logger.new(slog::o!()),
|
||||
@@ -291,6 +288,17 @@ impl VfioDeviceMgr {
|
||||
&mut self,
|
||||
ctx: &mut DeviceOpContext,
|
||||
) -> std::result::Result<(), StartMicroVmError> {
|
||||
// create and attach pci root bus
|
||||
#[cfg(all(feature = "hotplug", feature = "host-device"))]
|
||||
if ctx.pci_hotplug_enabled {
|
||||
let _ = self
|
||||
.create_pci_manager(
|
||||
ctx.irq_manager.clone(),
|
||||
ctx.io_context.clone(),
|
||||
ctx.res_manager.clone(),
|
||||
)
|
||||
.map_err(StartMicroVmError::CreateVfioDevice)?;
|
||||
}
|
||||
for (idx, info) in self.info_list.clone().iter().enumerate() {
|
||||
self.create_device(&info.config, ctx, idx)
|
||||
.map_err(StartMicroVmError::CreateVfioDevice)?;
|
||||
@@ -566,9 +574,12 @@ impl VfioDeviceMgr {
|
||||
"subsystem" => "vfio_dev_mgr",
|
||||
"host_bdf" => &cfg.bus_slot_func,
|
||||
);
|
||||
|
||||
let pci_manager = self.get_pci_manager();
|
||||
let pci_manager = pci_manager.lock().unwrap();
|
||||
// safe to get pci_manager
|
||||
let pci_manager = self.create_pci_manager(
|
||||
ctx.irq_manager.clone(),
|
||||
ctx.io_context.clone(),
|
||||
ctx.res_manager.clone(),
|
||||
)?;
|
||||
let pci_bus = pci_manager.pci_root_bus();
|
||||
let id = pci_manager
|
||||
.new_device_id(cfg.guest_dev_id)
|
||||
@@ -596,7 +607,7 @@ impl VfioDeviceMgr {
|
||||
sysfs_path,
|
||||
Arc::downgrade(&pci_bus),
|
||||
vfio_dev,
|
||||
self.get_pci_manager(),
|
||||
Arc::downgrade(self.get_pci_manager().unwrap()),
|
||||
ctx.vm_fd.clone(),
|
||||
cfg.vendor_device_id,
|
||||
cfg.clique_id,
|
||||
@@ -654,8 +665,8 @@ impl VfioDeviceMgr {
|
||||
|
||||
// safe to unwrap because pci vfio manager is already created
|
||||
let _ = self
|
||||
.pci_system_manager
|
||||
.lock()
|
||||
.pci_vfio_manager
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.free_device_id(device_id)
|
||||
.ok_or(VfioDeviceError::InvalidDeviceID(device_id))?;
|
||||
@@ -687,9 +698,27 @@ impl VfioDeviceMgr {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn create_pci_manager(
|
||||
&mut self,
|
||||
irq_manager: Arc<KvmIrqManager>,
|
||||
io_context: DeviceManagerContext,
|
||||
res_manager: Arc<ResourceManager>,
|
||||
) -> Result<&mut Arc<PciSystemManager>> {
|
||||
if self.pci_vfio_manager.is_none() {
|
||||
let mut mgr = PciSystemManager::new(irq_manager, io_context, res_manager.clone())?;
|
||||
let requirements = mgr.resource_requirements();
|
||||
let resources = res_manager
|
||||
.allocate_device_resources(&requirements, USE_SHARED_IRQ)
|
||||
.or(Err(VfioDeviceError::NoResource))?;
|
||||
mgr.activate(resources)?;
|
||||
self.pci_vfio_manager = Some(Arc::new(mgr));
|
||||
}
|
||||
Ok(self.pci_vfio_manager.as_mut().unwrap())
|
||||
}
|
||||
|
||||
/// Get the PCI manager to support PCI device passthrough
|
||||
pub fn get_pci_manager(&mut self) -> Arc<Mutex<PciSystemManager>> {
|
||||
self.pci_system_manager.clone()
|
||||
pub fn get_pci_manager(&mut self) -> Option<&mut Arc<PciSystemManager>> {
|
||||
self.pci_vfio_manager.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,13 +12,14 @@ use dbs_interrupt::KvmIrqManager;
|
||||
use dbs_pci::ECAM_SPACE_LENGTH;
|
||||
use dbs_pci::{create_pci_root_bus, PciBus, PciDevice, PciRootDevice, PciSystemContext};
|
||||
|
||||
use super::DeviceMgrError;
|
||||
use super::{Result, VfioDeviceError};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::device_manager::vfio_dev_mgr::USE_SHARED_IRQ;
|
||||
use crate::device_manager::DeviceManagerContext;
|
||||
use crate::resource_manager::ResourceManager;
|
||||
use dbs_pci::PCI_BUS_DEFAULT;
|
||||
|
||||
/// we only support one pci bus
|
||||
pub const PCI_BUS_DEFAULT: u8 = 0;
|
||||
/// The default mmio size for pci root bus.
|
||||
const PCI_MMIO_DEFAULT_SIZE: u64 = 2048u64 << 30;
|
||||
|
||||
@@ -37,13 +38,13 @@ impl PciSystemManager {
|
||||
irq_manager: Arc<KvmIrqManager>,
|
||||
io_context: DeviceManagerContext,
|
||||
res_manager: Arc<ResourceManager>,
|
||||
) -> std::result::Result<Self, DeviceMgrError> {
|
||||
) -> std::result::Result<Self, VfioDeviceError> {
|
||||
let resources = PciSystemManager::allocate_root_device_resources(res_manager)?;
|
||||
let pci_root = Arc::new(
|
||||
PciRootDevice::create(PCI_BUS_DEFAULT, resources).map_err(DeviceMgrError::PciError)?,
|
||||
PciRootDevice::create(PCI_BUS_DEFAULT, resources).map_err(VfioDeviceError::PciError)?,
|
||||
);
|
||||
let pci_root_bus =
|
||||
create_pci_root_bus(PCI_BUS_DEFAULT).map_err(DeviceMgrError::PciError)?;
|
||||
create_pci_root_bus(PCI_BUS_DEFAULT).map_err(VfioDeviceError::PciError)?;
|
||||
|
||||
Ok(PciSystemManager {
|
||||
irq_manager,
|
||||
@@ -57,7 +58,7 @@ impl PciSystemManager {
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
fn allocate_root_device_resources(
|
||||
_res_manager: Arc<ResourceManager>,
|
||||
) -> std::result::Result<DeviceResources, DeviceMgrError> {
|
||||
) -> Result<DeviceResources> {
|
||||
let mut resources = DeviceResources::new();
|
||||
resources.append(Resource::PioAddressRange {
|
||||
// PCI CONFIG_ADDRESS port address 0xcf8 and uses 32 bits
|
||||
@@ -75,7 +76,7 @@ impl PciSystemManager {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn allocate_root_device_resources(
|
||||
res_manager: Arc<ResourceManager>,
|
||||
) -> std::result::Result<DeviceResources, DeviceMgrError> {
|
||||
) -> Result<DeviceResources> {
|
||||
let requests = vec![ResourceConstraint::MmioAddress {
|
||||
range: Some((0x0, 0xffff_ffff)),
|
||||
align: 4096,
|
||||
@@ -83,26 +84,23 @@ impl PciSystemManager {
|
||||
}];
|
||||
let resources = res_manager
|
||||
.allocate_device_resources(&requests, USE_SHARED_IRQ)
|
||||
.map_err(DeviceMgrError::ResourceError)?;
|
||||
.map_err(VfioDeviceError::AllocateDeviceResource)?;
|
||||
Ok(resources)
|
||||
}
|
||||
|
||||
/// Activate the PCI subsystem.
|
||||
pub fn activate(
|
||||
&mut self,
|
||||
resources: DeviceResources,
|
||||
) -> std::result::Result<(), DeviceMgrError> {
|
||||
pub fn activate(&mut self, resources: DeviceResources) -> Result<()> {
|
||||
let bus_id = self.pci_root_bus.bus_id();
|
||||
|
||||
self.pci_root
|
||||
.add_bus(self.pci_root_bus.clone(), bus_id)
|
||||
.map_err(DeviceMgrError::PciError)?;
|
||||
.map_err(VfioDeviceError::PciError)?;
|
||||
PciRootDevice::activate(self.pci_root.clone(), &mut self.io_context)
|
||||
.map_err(DeviceMgrError::PciError)?;
|
||||
.map_err(VfioDeviceError::PciError)?;
|
||||
|
||||
self.pci_root_bus
|
||||
.assign_resources(resources)
|
||||
.map_err(DeviceMgrError::PciError)?;
|
||||
.map_err(VfioDeviceError::PciError)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ impl VhostNetDeviceMgr {
|
||||
info.config.iface_id
|
||||
);
|
||||
if let Some(device) = info.device.take() {
|
||||
DeviceManager::destroy_mmio_device(device, ctx)?;
|
||||
DeviceManager::destroy_mmio_virtio_device(device, ctx)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -382,7 +382,7 @@ impl VirtioNetDeviceMgr {
|
||||
info.config.iface_id
|
||||
);
|
||||
if let Some(device) = info.device.take() {
|
||||
DeviceManager::destroy_mmio_device(device, ctx)?;
|
||||
DeviceManager::destroy_mmio_virtio_device(device, ctx)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -294,7 +294,7 @@ impl VsockDeviceMgr {
|
||||
info.config.id
|
||||
);
|
||||
if let Some(device) = info.device.take() {
|
||||
DeviceManager::destroy_mmio_device(device, ctx)?;
|
||||
DeviceManager::destroy_mmio_virtio_device(device, ctx)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -77,10 +77,6 @@ pub enum Error {
|
||||
/// Cannot open the VM file descriptor.
|
||||
#[error(transparent)]
|
||||
Vm(vm::VmError),
|
||||
|
||||
/// Fail to create device manager system
|
||||
#[error("failed to create device manager system: {0}")]
|
||||
DeviceMgrError(#[source] device_manager::DeviceMgrError),
|
||||
}
|
||||
|
||||
/// Errors associated with starting the instance.
|
||||
|
||||
@@ -35,7 +35,7 @@ use crate::address_space_manager::{
|
||||
use crate::api::v1::{InstanceInfo, InstanceState};
|
||||
use crate::device_manager::console_manager::DmesgWriter;
|
||||
use crate::device_manager::{DeviceManager, DeviceMgrError, DeviceOpContext};
|
||||
use crate::error::{Error, LoadInitrdError, Result, StartMicroVmError, StopMicrovmError};
|
||||
use crate::error::{LoadInitrdError, Result, StartMicroVmError, StopMicrovmError};
|
||||
use crate::event_manager::EventManager;
|
||||
use crate::kvm_context::KvmContext;
|
||||
use crate::resource_manager::ResourceManager;
|
||||
@@ -228,8 +228,7 @@ impl Vm {
|
||||
epoll_manager.clone(),
|
||||
&logger,
|
||||
api_shared_info.clone(),
|
||||
)
|
||||
.map_err(Error::DeviceMgrError)?;
|
||||
);
|
||||
|
||||
Ok(Vm {
|
||||
epoll_manager,
|
||||
|
||||
@@ -375,11 +375,7 @@ mod tests {
|
||||
fn build_oci_hook(self) -> oci::Hook {
|
||||
let mut hook = oci::Hook::default();
|
||||
hook.set_path(PathBuf::from(self.path));
|
||||
if self.args.is_empty() {
|
||||
hook.set_args(None);
|
||||
} else {
|
||||
hook.set_args(Some(self.args));
|
||||
}
|
||||
hook.set_args(Some(self.args));
|
||||
hook.set_env(Some(self.env));
|
||||
hook.set_timeout(self.timeout);
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
use kata_types::mount;
|
||||
use oci_spec::runtime::{Mount, Spec};
|
||||
use std::path::Path;
|
||||
|
||||
use crate::mount::get_linux_mount_info;
|
||||
|
||||
@@ -33,8 +34,9 @@ pub fn is_ephemeral_volume(mount: &Mount) -> bool {
|
||||
mount.destination(),
|
||||
|
||||
),
|
||||
(Some("bind"), Some(source), _dest) if get_linux_mount_info(source).is_ok_and(|info| info.fs_type == "tmpfs") &&
|
||||
is_empty_dir(source))
|
||||
(Some("bind"), Some(source), dest) if get_linux_mount_info(source).is_ok_and(|info| info.fs_type == "tmpfs") &&
|
||||
(is_empty_dir(source) || dest.as_path() == Path::new("/dev/shm"))
|
||||
)
|
||||
}
|
||||
|
||||
/// Check whether the given path is a kubernetes empty-dir volume of medium "default".
|
||||
|
||||
@@ -216,11 +216,6 @@ mod tests {
|
||||
// Test snp
|
||||
let dir = tempdir().unwrap();
|
||||
let snp_file_path = dir.path().join("sev_snp");
|
||||
if !snp_file_path.exists() {
|
||||
println!("INFO: skipping {} which needs sev_snp", module_path!());
|
||||
return;
|
||||
}
|
||||
|
||||
let path = snp_file_path.clone();
|
||||
let mut snp_file = fs::File::create(snp_file_path).unwrap();
|
||||
writeln!(snp_file, "Y").unwrap();
|
||||
@@ -240,11 +235,6 @@ mod tests {
|
||||
// Test sev
|
||||
let dir = tempdir().unwrap();
|
||||
let sev_file_path = dir.path().join("sev");
|
||||
if !sev_file_path.exists() {
|
||||
println!("INFO: skipping {} which needs sev", module_path!());
|
||||
return;
|
||||
}
|
||||
|
||||
let sev_path = sev_file_path.clone();
|
||||
let mut sev_file = fs::File::create(sev_file_path).unwrap();
|
||||
writeln!(sev_file, "Y").unwrap();
|
||||
@@ -267,11 +257,6 @@ mod tests {
|
||||
let invalid_dir = invalid_dir.to_str().unwrap();
|
||||
|
||||
let tdx_file_path = dir.path().join("tdx");
|
||||
if !tdx_file_path.exists() {
|
||||
println!("INFO: skipping {} which needs tdx", module_path!());
|
||||
return;
|
||||
}
|
||||
|
||||
let tdx_path = tdx_file_path;
|
||||
|
||||
std::fs::create_dir_all(tdx_path.clone()).unwrap();
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use std::io::Result;
|
||||
|
||||
use crate::config::{ConfigOps, TomlConfig};
|
||||
@@ -118,8 +117,7 @@ pub struct Agent {
|
||||
/// have sufficient time to complete.
|
||||
#[serde(
|
||||
default = "default_request_timeout",
|
||||
rename = "create_container_timeout",
|
||||
deserialize_with = "deserialize_secs_to_millis"
|
||||
rename = "create_container_timeout"
|
||||
)]
|
||||
pub request_timeout_ms: u32,
|
||||
|
||||
@@ -150,15 +148,6 @@ pub struct Agent {
|
||||
pub mem_agent: MemAgent,
|
||||
}
|
||||
|
||||
fn deserialize_secs_to_millis<'de, D>(deserializer: D) -> std::result::Result<u32, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let secs = u32::deserialize(deserializer)?;
|
||||
|
||||
Ok(secs.saturating_mul(1000))
|
||||
}
|
||||
|
||||
impl std::default::Default for Agent {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
||||
@@ -48,9 +48,6 @@ pub use self::ch::{CloudHypervisorConfig, HYPERVISOR_NAME_CH};
|
||||
mod remote;
|
||||
pub use self::remote::{RemoteConfig, HYPERVISOR_NAME_REMOTE};
|
||||
|
||||
mod rate_limiter;
|
||||
pub use self::rate_limiter::RateLimiterConfig;
|
||||
|
||||
/// Virtual PCI block device driver.
|
||||
pub const VIRTIO_BLK_PCI: &str = "virtio-blk-pci";
|
||||
|
||||
@@ -176,19 +173,6 @@ pub struct BlockDeviceInfo {
|
||||
/// The default if not set is empty (all annotations rejected.)
|
||||
#[serde(default)]
|
||||
pub valid_vhost_user_store_paths: Vec<String>,
|
||||
|
||||
/// controls disk I/O bandwidth (size in bits/sec)
|
||||
#[serde(default)]
|
||||
pub disk_rate_limiter_bw_max_rate: u64,
|
||||
/// increases the initial max rate
|
||||
#[serde(default)]
|
||||
pub disk_rate_limiter_bw_one_time_burst: Option<u64>,
|
||||
/// controls disk I/O bandwidth (size in ops/sec)
|
||||
#[serde(default)]
|
||||
pub disk_rate_limiter_ops_max_rate: u64,
|
||||
/// increases the initial max rate
|
||||
#[serde(default)]
|
||||
pub disk_rate_limiter_ops_one_time_burst: Option<u64>,
|
||||
}
|
||||
|
||||
impl BlockDeviceInfo {
|
||||
@@ -958,10 +942,6 @@ pub struct SecurityInfo {
|
||||
/// Another note: enabling this feature may reduce performance, you may enable
|
||||
/// /proc/sys/net/core/bpf_jit_enable to reduce the impact. see https://man7.org/linux/man-pages/man8/bpfc.8.html
|
||||
pub seccomp_sandbox: Option<String>,
|
||||
|
||||
/// selinux_label defines SELinux label for the guest
|
||||
#[serde(default)]
|
||||
pub selinux_label: Option<String>,
|
||||
}
|
||||
|
||||
fn default_qgs_port() -> u32 {
|
||||
@@ -1301,10 +1281,6 @@ pub struct Hypervisor {
|
||||
/// Disables applying SELinux on the container process within the guest.
|
||||
#[serde(default = "yes")]
|
||||
pub disable_guest_selinux: bool,
|
||||
|
||||
/// Disable applying SELinux on the VMM process.
|
||||
#[serde(default)]
|
||||
pub disable_selinux: bool,
|
||||
}
|
||||
|
||||
fn yes() -> bool {
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
// Copyright (c) 2022-2023 Intel Corporation
|
||||
//
|
||||
// Copyright (c) 2024-2025 Ant Group
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// The DEFAULT_RATE_LIMITER_REFILL_TIME is used for calculating the rate at
|
||||
// which a TokenBucket is replinished, in cases where a RateLimiter is
|
||||
// applied to either network or disk I/O.
|
||||
pub(crate) const DEFAULT_RATE_LIMITER_REFILL_TIME: u64 = 1000;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub struct TokenBucketConfig {
|
||||
pub size: u64,
|
||||
pub one_time_burst: Option<u64>,
|
||||
pub refill_time: u64,
|
||||
}
|
||||
|
||||
/// Rate limiter configuration for rust vmm hypervisor
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct RateLimiterConfig {
|
||||
/// Bandwidth rate limiter options
|
||||
pub bandwidth: Option<TokenBucketConfig>,
|
||||
/// Operations rate limiter options
|
||||
pub ops: Option<TokenBucketConfig>,
|
||||
}
|
||||
|
||||
impl RateLimiterConfig {
|
||||
/// Helper function: Creates a `TokenBucketConfig` based on the provided rate and burst.
|
||||
/// Returns `None` if the `rate` is 0.
|
||||
fn create_token_bucket_config(
|
||||
rate: u64,
|
||||
one_time_burst: Option<u64>,
|
||||
) -> Option<TokenBucketConfig> {
|
||||
if rate > 0 {
|
||||
Some(TokenBucketConfig {
|
||||
size: rate,
|
||||
one_time_burst,
|
||||
refill_time: DEFAULT_RATE_LIMITER_REFILL_TIME,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `RateLimiterConfig` instance.
|
||||
///
|
||||
/// If both `band_rate` and `ops_rate` are 0 (indicating no rate limiting configured),
|
||||
/// it returns `None`. Otherwise, it returns `Some(RateLimiterConfig)` containing
|
||||
/// the configured options.
|
||||
pub fn new(
|
||||
band_rate: u64,
|
||||
ops_rate: u64,
|
||||
band_onetime_burst: Option<u64>,
|
||||
ops_onetime_burst: Option<u64>,
|
||||
) -> Option<RateLimiterConfig> {
|
||||
// Use the helper function to create `TokenBucketConfig` for bandwidth and ops
|
||||
let bandwidth = Self::create_token_bucket_config(band_rate, band_onetime_burst);
|
||||
let ops = Self::create_token_bucket_config(ops_rate, ops_onetime_burst);
|
||||
|
||||
// Use pattern matching to concisely handle the final `Option<RateLimiterConfig>` return.
|
||||
// If both bandwidth and ops are `None`, the entire config is `None`.
|
||||
// Otherwise, return `Some` with the actual configured options.
|
||||
match (bandwidth, ops) {
|
||||
(None, None) => None,
|
||||
(b, o) => Some(RateLimiterConfig {
|
||||
bandwidth: b,
|
||||
ops: o,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unit tests
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_new_all_set() {
|
||||
let config = RateLimiterConfig::new(100, 50, Some(10), Some(5)).unwrap();
|
||||
assert_eq!(
|
||||
config.bandwidth,
|
||||
Some(TokenBucketConfig {
|
||||
size: 100,
|
||||
one_time_burst: Some(10),
|
||||
refill_time: DEFAULT_RATE_LIMITER_REFILL_TIME
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
config.ops,
|
||||
Some(TokenBucketConfig {
|
||||
size: 50,
|
||||
one_time_burst: Some(5),
|
||||
refill_time: DEFAULT_RATE_LIMITER_REFILL_TIME
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_bandwidth_only() {
|
||||
let config = RateLimiterConfig::new(100, 0, Some(10), None).unwrap();
|
||||
assert_eq!(
|
||||
config.bandwidth,
|
||||
Some(TokenBucketConfig {
|
||||
size: 100,
|
||||
one_time_burst: Some(10),
|
||||
refill_time: DEFAULT_RATE_LIMITER_REFILL_TIME
|
||||
})
|
||||
);
|
||||
assert_eq!(config.ops, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_ops_only() {
|
||||
let config = RateLimiterConfig::new(0, 50, None, Some(5)).unwrap();
|
||||
assert_eq!(config.bandwidth, None);
|
||||
assert_eq!(
|
||||
config.ops,
|
||||
Some(TokenBucketConfig {
|
||||
size: 50,
|
||||
one_time_burst: Some(5),
|
||||
refill_time: DEFAULT_RATE_LIMITER_REFILL_TIME
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_no_burst() {
|
||||
let config = RateLimiterConfig::new(100, 50, None, None).unwrap();
|
||||
assert_eq!(
|
||||
config.bandwidth,
|
||||
Some(TokenBucketConfig {
|
||||
size: 100,
|
||||
one_time_burst: None,
|
||||
refill_time: DEFAULT_RATE_LIMITER_REFILL_TIME
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
config.ops,
|
||||
Some(TokenBucketConfig {
|
||||
size: 50,
|
||||
one_time_burst: None,
|
||||
refill_time: DEFAULT_RATE_LIMITER_REFILL_TIME
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_none_set() {
|
||||
let config = RateLimiterConfig::new(0, 0, None, None);
|
||||
assert_eq!(config, None);
|
||||
}
|
||||
}
|
||||
@@ -4,17 +4,16 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::str::FromStr;
|
||||
|
||||
/// a container running within a pod
|
||||
pub const POD_CONTAINER: &str = "pod_container";
|
||||
// a container running within a pod
|
||||
pub(crate) const POD_CONTAINER: &str = "pod_container";
|
||||
// cri containerd/crio/docker: a container running within a pod
|
||||
pub(crate) const CONTAINER: &str = "container";
|
||||
|
||||
/// a pod sandbox container
|
||||
pub const POD_SANDBOX: &str = "pod_sandbox";
|
||||
// a pod sandbox container
|
||||
pub(crate) const POD_SANDBOX: &str = "pod_sandbox";
|
||||
// cri containerd/crio: a pod sandbox container
|
||||
pub(crate) const SANDBOX: &str = "sandbox";
|
||||
// docker: a sandbox sandbox container
|
||||
@@ -137,58 +136,6 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates OCI annotations by removing specified keys and adding new ones.
|
||||
///
|
||||
/// This function creates a new `HashMap` containing the updated annotations, ensuring
|
||||
/// that the original map remains unchanged. It is optimized for performance by
|
||||
/// pre-allocating the necessary capacity and handling removals and additions
|
||||
/// efficiently.
|
||||
///
|
||||
/// **Note:** If a key from `keys_to_add` already exists in the new map (either from
|
||||
/// the original annotations or from another entry in `keys_to_add`), the
|
||||
/// corresponding add operation will be **ignored**. The existing value will not be
|
||||
/// overwritten.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `annotations` - A reference to the original `HashMap` of annotations.
|
||||
/// * `keys_to_remove` - A slice of string slices (`&[&str]`) representing the keys to be removed.
|
||||
/// * `keys_to_add` - A slice of tuples (`&[(String, String)]`) representing the new key-value pairs to add.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A new `HashMap` containing the merged and updated set of annotations.
|
||||
///
|
||||
pub fn update_ocispec_annotations(
|
||||
annotations: &HashMap<String, String>,
|
||||
keys_to_remove: &[&str],
|
||||
keys_to_add: &[(String, String)],
|
||||
) -> HashMap<String, String> {
|
||||
// 1. Validate input parameters
|
||||
if keys_to_remove.is_empty() && keys_to_add.is_empty() {
|
||||
return annotations.clone();
|
||||
}
|
||||
|
||||
// Pre-allocate capacity: Original size + number of additions
|
||||
let mut updated = HashMap::with_capacity(annotations.len() + keys_to_add.len());
|
||||
|
||||
// 2. Copy retained key-value pairs (use `contains` directly)
|
||||
for (k, v) in annotations {
|
||||
if !keys_to_remove.iter().any(|&rm| rm == k) {
|
||||
updated.insert(k.clone(), v.clone());
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Add new key-value pairs
|
||||
for (key, value) in keys_to_add {
|
||||
if !updated.contains_key(key) {
|
||||
updated.insert(key.clone(), value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
updated
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -264,64 +211,4 @@ mod tests {
|
||||
assert!(Stopped.check_transition(Running).is_ok());
|
||||
assert!(Stopped.check_transition(Stopped).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_annotations_combined_operations() {
|
||||
// Initial annotations
|
||||
let mut annotations = HashMap::new();
|
||||
annotations.insert("key1".to_string(), "val1".to_string());
|
||||
annotations.insert("key2".to_string(), "val2".to_string());
|
||||
|
||||
// Keys to remove and add
|
||||
let keys_to_remove = ["key2"];
|
||||
let keys_to_add = vec![
|
||||
("key3".to_string(), "val3".to_string()),
|
||||
("key1".to_string(), "new_val1".to_string()), // Attempt to overwrite
|
||||
];
|
||||
|
||||
// Call the function with keys_to_remove and keys_to_add
|
||||
let updated = update_ocispec_annotations(&annotations, &keys_to_remove, &keys_to_add);
|
||||
|
||||
// Assert the result
|
||||
assert_eq!(updated.len(), 2);
|
||||
assert_eq!(updated.get("key1"), Some(&"val1".to_string())); // Not overwritten
|
||||
assert!(!updated.contains_key("key2")); // Removed
|
||||
assert_eq!(updated.get("key3"), Some(&"val3".to_string())); // Added
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_annotations_whith_empty_inputs() {
|
||||
// Initial annotations
|
||||
let annotations = HashMap::new();
|
||||
|
||||
// empty inputs
|
||||
let updated = update_ocispec_annotations(&annotations, &[], &[]);
|
||||
|
||||
// Assert the result
|
||||
assert_eq!(annotations, updated);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_annotations_not_in_annotations_map() {
|
||||
// Initial annotations
|
||||
let mut annotations = HashMap::new();
|
||||
annotations.insert("key1".to_string(), "val1".to_string());
|
||||
annotations.insert("key2".to_string(), "val2".to_string());
|
||||
|
||||
// Keys to remove and add
|
||||
let keys_to_remove = ["key4"];
|
||||
let keys_to_add = vec![
|
||||
("key3".to_string(), "val3".to_string()),
|
||||
("key1".to_string(), "new_val1".to_string()), // Attempt to overwrite
|
||||
];
|
||||
|
||||
// a `keys_to_remove` that isn't currently in the annotations map is passed in with "key4"
|
||||
let updated = update_ocispec_annotations(&annotations, &keys_to_remove, &keys_to_add);
|
||||
|
||||
// Assert the result
|
||||
assert_eq!(updated.len(), 3);
|
||||
assert_eq!(updated.get("key1"), Some(&"val1".to_string())); // Not overwritten
|
||||
assert_eq!(updated.get("key2"), Some(&"val2".to_string())); // keep it
|
||||
assert_eq!(updated.get("key3"), Some(&"val3".to_string())); // Added
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,14 +207,15 @@ pub fn calculate_initdata_digest(
|
||||
Ok(b64encoded_digest)
|
||||
}
|
||||
|
||||
/// Encodes initdata as an annotation
|
||||
pub fn encode_initdata(init_data: &InitData) -> String {
|
||||
let toml_str = toml::to_string(&init_data).unwrap();
|
||||
create_encoded_input(&toml_str)
|
||||
}
|
||||
/// The argument `initdata_annotation` is a Standard base64 encoded string containing a TOML formatted content.
|
||||
/// This function decodes the base64 string, parses the TOML content into an InitData structure.
|
||||
pub fn add_hypervisor_initdata_overrides(initdata_annotation: &str) -> Result<String> {
|
||||
// If the initdata is empty, return an empty string
|
||||
if initdata_annotation.is_empty() {
|
||||
info!(sl!(), "initdata_annotation is empty");
|
||||
return Ok("".to_string());
|
||||
}
|
||||
|
||||
/// Decodes initdata annotation
|
||||
pub fn decode_initdata(initdata_annotation: &str) -> Result<InitData> {
|
||||
// Base64 decode the annotation value
|
||||
let b64_decoded =
|
||||
base64::decode_config(initdata_annotation, base64::STANDARD).context("base64 decode")?;
|
||||
@@ -226,32 +227,11 @@ pub fn decode_initdata(initdata_annotation: &str) -> Result<InitData> {
|
||||
.read_to_string(&mut initdata_str)
|
||||
.context("gz decoder failed")?;
|
||||
|
||||
// Return parsed initdata
|
||||
let initdata = parse_initdata(&initdata_str).context("parse initdata overrides")?;
|
||||
// Parse the initdata
|
||||
let initdata: InitData = parse_initdata(&initdata_str).context("parse initdata overrides")?;
|
||||
|
||||
Ok(initdata)
|
||||
}
|
||||
|
||||
/// The argument `initdata_annotation` is a Standard base64 encoded string containing a TOML formatted content.
|
||||
/// This function decodes the base64 string, parses the TOML content into an InitData structure.
|
||||
pub fn add_hypervisor_initdata_overrides(initdata_annotation: &str) -> Result<String> {
|
||||
// If the initdata is empty, return an empty string
|
||||
if initdata_annotation.is_empty() {
|
||||
info!(sl!(), "initdata_annotation is empty");
|
||||
return Ok("".to_string());
|
||||
}
|
||||
|
||||
decode_initdata(initdata_annotation)?.to_string()
|
||||
}
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
/// create gzipped and base64 encoded string
|
||||
fn create_encoded_input(content: &str) -> String {
|
||||
let mut encoder = flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::default());
|
||||
encoder.write_all(content.as_bytes()).unwrap();
|
||||
let compressed = encoder.finish().unwrap();
|
||||
base64::encode_config(&compressed, base64::STANDARD)
|
||||
// initdata within a TOML string
|
||||
initdata.to_string()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -261,6 +241,14 @@ mod tests {
|
||||
use flate2::Compression;
|
||||
use std::io::Write;
|
||||
|
||||
// create gzipped and base64 encoded string
|
||||
fn create_encoded_input(content: &str) -> String {
|
||||
let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
|
||||
encoder.write_all(content.as_bytes()).unwrap();
|
||||
let compressed = encoder.finish().unwrap();
|
||||
base64::encode_config(&compressed, base64::STANDARD)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_annotation() {
|
||||
// Test with empty string input
|
||||
|
||||
@@ -68,12 +68,6 @@ pub const KATA_VIRTUAL_VOLUME_LAYER_NYDUS_FS: &str = "layer_nydus_fs";
|
||||
pub const KATA_VIRTUAL_VOLUME_IMAGE_GUEST_PULL: &str = "image_guest_pull";
|
||||
/// In CoCo scenario, we support force_guest_pull to enforce container image guest pull without remote snapshotter.
|
||||
pub const KATA_IMAGE_FORCE_GUEST_PULL: &str = "force_guest_pull";
|
||||
/// kata default guest sandbox dir.
|
||||
pub const DEFAULT_KATA_GUEST_SANDBOX_DIR: &str = "/run/kata-containers/sandbox";
|
||||
/// default shm directory name.
|
||||
pub const SHM_DIR: &str = "shm";
|
||||
/// shm device path.
|
||||
pub const SHM_DEVICE: &str = "/dev/shm";
|
||||
|
||||
/// Manager to manage registered storage device handlers.
|
||||
pub type StorageHandlerManager<H> = HandlerManager<H>;
|
||||
|
||||
@@ -138,8 +138,10 @@ mod tests {
|
||||
#[test]
|
||||
fn test_get_uds_with_sid_ok() {
|
||||
let run_path = tempdir().unwrap();
|
||||
let dir = run_path.path().join("aata98654dangboxpath1");
|
||||
fs::create_dir_all(dir.as_path()).unwrap();
|
||||
let dir1 = run_path.path().join("kata98654sandboxpath1");
|
||||
let dir2 = run_path.path().join("aata98654dangboxpath1");
|
||||
fs::create_dir_all(dir1.as_path()).unwrap();
|
||||
fs::create_dir_all(dir2.as_path()).unwrap();
|
||||
|
||||
let result = get_uds_with_sid("kata", &run_path.path().display().to_string());
|
||||
assert!(result.is_ok());
|
||||
@@ -149,7 +151,7 @@ mod tests {
|
||||
"unix://{}",
|
||||
run_path
|
||||
.path()
|
||||
.join("kata")
|
||||
.join("kata98654sandboxpath1")
|
||||
.join(SHIM_MGMT_SOCK_NAME)
|
||||
.display()
|
||||
)
|
||||
@@ -158,20 +160,21 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_get_uds_with_sid_with_zero() {
|
||||
let run_path = tempdir().unwrap();
|
||||
let result = get_uds_with_sid("acdsdfe", &run_path.path().display().to_string());
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(
|
||||
result.unwrap(),
|
||||
format!(
|
||||
"unix://{}",
|
||||
run_path
|
||||
.path()
|
||||
.join("acdsdfe")
|
||||
.join(SHIM_MGMT_SOCK_NAME)
|
||||
.display()
|
||||
let result = get_uds_with_sid("acdsdfe", KATA_PATH);
|
||||
assert!(result.is_err());
|
||||
if let Err(err) = result {
|
||||
let left = format!("{:?}", err.to_string());
|
||||
let left_unquoted = &left[1..left.len() - 1];
|
||||
let left_unescaped = left_unquoted.replace("\\\"", "\"");
|
||||
|
||||
assert_eq!(
|
||||
left_unescaped,
|
||||
format!(
|
||||
"sandbox with the provided prefix {:?} is not found",
|
||||
"acdsdfe"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
5
src/runtime-rs/Cargo.lock
generated
5
src/runtime-rs/Cargo.lock
generated
@@ -3871,7 +3871,6 @@ dependencies = [
|
||||
"cgroups-rs 0.4.0",
|
||||
"flate2",
|
||||
"futures 0.3.28",
|
||||
"hex",
|
||||
"hypervisor",
|
||||
"inotify",
|
||||
"kata-sys-util",
|
||||
@@ -4474,9 +4473,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.11"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
|
||||
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
|
||||
|
||||
[[package]]
|
||||
name = "slog"
|
||||
|
||||
@@ -227,7 +227,7 @@ ifneq (,$(DBCMD))
|
||||
# dragonball-specific options (all should be suffixed by "_DB")
|
||||
VMROOTFSDRIVER_DB := virtio-blk-pci
|
||||
DEFMAXVCPUS_DB := 0
|
||||
DEFBLOCKSTORAGEDRIVER_DB := virtio-blk-pci
|
||||
DEFBLOCKSTORAGEDRIVER_DB := virtio-blk-mmio
|
||||
DEFNETWORKMODEL_DB := tcfilter
|
||||
KERNELPARAMS_DB = console=ttyS1 agent.log_vport=1025
|
||||
KERNELTYPE_DB = uncompressed
|
||||
|
||||
@@ -178,36 +178,6 @@ block_device_driver = "virtio-blk-pci"
|
||||
# Default false
|
||||
#block_device_cache_direct = true
|
||||
|
||||
# Bandwidth rate limiter options
|
||||
#
|
||||
# disk_rate_limiter_bw_max_rate controls disk I/O bandwidth (size in bits/sec
|
||||
# for SB/VM).
|
||||
# The same value is used for inbound and outbound bandwidth.
|
||||
# Default 0-sized value means unlimited rate.
|
||||
#disk_rate_limiter_bw_max_rate = 0
|
||||
#
|
||||
# disk_rate_limiter_bw_one_time_burst increases the initial max rate and this
|
||||
# initial extra credit does *NOT* affect the overall limit and can be used for
|
||||
# an *initial* burst of data.
|
||||
# This is *optional* and only takes effect if disk_rate_limiter_bw_max_rate is
|
||||
# set to a non zero value.
|
||||
#disk_rate_limiter_bw_one_time_burst = 0
|
||||
#
|
||||
# Operation rate limiter options
|
||||
#
|
||||
# disk_rate_limiter_ops_max_rate controls disk I/O bandwidth (size in ops/sec
|
||||
# for SB/VM).
|
||||
# The same value is used for inbound and outbound bandwidth.
|
||||
# Default 0-sized value means unlimited rate.
|
||||
#disk_rate_limiter_ops_max_rate = 0
|
||||
#
|
||||
# disk_rate_limiter_ops_one_time_burst increases the initial max rate and this
|
||||
# initial extra credit does *NOT* affect the overall limit and can be used for
|
||||
# an *initial* burst of data.
|
||||
# This is *optional* and only takes effect if disk_rate_limiter_bw_max_rate is
|
||||
# set to a non zero value.
|
||||
#disk_rate_limiter_ops_one_time_burst = 0
|
||||
|
||||
# Enable pre allocation of VM RAM, default false
|
||||
# Enabling this will result in lower container density
|
||||
# as all of the memory will be allocated and locked
|
||||
@@ -417,7 +387,7 @@ container_pipe_size=@PIPESIZE@
|
||||
#
|
||||
# Effective Timeout Determination:
|
||||
# The effective timeout for a CreateContainerRequest is determined by taking the minimum of the following two values:
|
||||
# - create_container_timeout: The timeout value configured for creating containers (default: 30 seconds).
|
||||
# - create_container_timeout: The timeout value configured for creating containers (default: 30,000 milliseconds).
|
||||
# - runtime-request-timeout: The timeout value specified in the Kubelet configuration described as the link below:
|
||||
# (https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/#:~:text=runtime%2Drequest%2Dtimeout)
|
||||
# Defaults to @DEFCREATECONTAINERTIMEOUT@ second(s)
|
||||
|
||||
@@ -122,7 +122,7 @@ default_maxmemory = @DEFMAXMEMSZ@
|
||||
# is backed by a block device or a file. This driver facilitates attaching the
|
||||
# storage directly to the guest VM.
|
||||
#
|
||||
# DB supports virtio-blk-mmio and virtio-blk-pci, virtio-blk-pci is prefered
|
||||
# DB only supports virtio-blk-mmio.
|
||||
block_device_driver = "@DEFBLOCKSTORAGEDRIVER_DB@"
|
||||
|
||||
# This option changes the default hypervisor and kernel parameters
|
||||
@@ -294,7 +294,7 @@ container_pipe_size=@PIPESIZE@
|
||||
#
|
||||
# Effective Timeout Determination:
|
||||
# The effective timeout for a CreateContainerRequest is determined by taking the minimum of the following two values:
|
||||
# - create_container_timeout: The timeout value configured for creating containers (default: 30 seconds).
|
||||
# - create_container_timeout: The timeout value configured for creating containers (default: 30,000 milliseconds).
|
||||
# - runtime-request-timeout: The timeout value specified in the Kubelet configuration described as the link below:
|
||||
# (https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/#:~:text=runtime%2Drequest%2Dtimeout)
|
||||
# Defaults to @DEFCREATECONTAINERTIMEOUT@ second(s)
|
||||
|
||||
@@ -707,7 +707,7 @@ kernel_modules=[]
|
||||
#
|
||||
# Effective Timeout Determination:
|
||||
# The effective timeout for a CreateContainerRequest is determined by taking the minimum of the following two values:
|
||||
# - create_container_timeout: The timeout value configured for creating containers (default: 30 seconds).
|
||||
# - create_container_timeout: The timeout value configured for creating containers (default: 30,000 milliseconds).
|
||||
# - runtime-request-timeout: The timeout value specified in the Kubelet configuration described as the link below:
|
||||
# (https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/#:~:text=runtime%2Drequest%2Dtimeout)
|
||||
# Defaults to @DEFCREATECONTAINERTIMEOUT@ second(s)
|
||||
|
||||
@@ -559,7 +559,7 @@ reconnect_timeout_ms = 5000
|
||||
#
|
||||
# Effective Timeout Determination:
|
||||
# The effective timeout for a CreateContainerRequest is determined by taking the minimum of the following two values:
|
||||
# - create_container_timeout: The timeout value configured for creating containers (default: 30 seconds).
|
||||
# - create_container_timeout: The timeout value configured for creating containers (default: 30,000 milliseconds).
|
||||
# - runtime-request-timeout: The timeout value specified in the Kubelet configuration described as the link below:
|
||||
# (https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/#:~:text=runtime%2Drequest%2Dtimeout)
|
||||
# Defaults to @DEFCREATECONTAINERTIMEOUT@ second(s)
|
||||
|
||||
@@ -178,7 +178,7 @@ disable_guest_selinux = true
|
||||
#
|
||||
# Effective Timeout Determination:
|
||||
# The effective timeout for a CreateContainerRequest is determined by taking the minimum of the following two values:
|
||||
# - create_container_timeout: The timeout value configured for creating containers (default: 30 seconds).
|
||||
# - create_container_timeout: The timeout value configured for creating containers (default: 30,000 milliseconds).
|
||||
# - runtime-request-timeout: The timeout value specified in the Kubelet configuration described as the link below:
|
||||
# (https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/#:~:text=runtime%2Drequest%2Dtimeout)
|
||||
# Defaults to @DEFCREATECONTAINERTIMEOUT@ second(s)
|
||||
|
||||
@@ -128,36 +128,6 @@ block_device_driver = "@DEFBLOCKSTORAGEDRIVER_FC@"
|
||||
# Default false
|
||||
#block_device_cache_noflush = true
|
||||
|
||||
# Bandwidth rate limiter options
|
||||
#
|
||||
# disk_rate_limiter_bw_max_rate controls disk I/O bandwidth (size in bits/sec
|
||||
# for SB/VM).
|
||||
# The same value is used for inbound and outbound bandwidth.
|
||||
# Default 0-sized value means unlimited rate.
|
||||
#disk_rate_limiter_bw_max_rate = 0
|
||||
#
|
||||
# disk_rate_limiter_bw_one_time_burst increases the initial max rate and this
|
||||
# initial extra credit does *NOT* affect the overall limit and can be used for
|
||||
# an *initial* burst of data.
|
||||
# This is *optional* and only takes effect if disk_rate_limiter_bw_max_rate is
|
||||
# set to a non zero value.
|
||||
#disk_rate_limiter_bw_one_time_burst = 0
|
||||
#
|
||||
# Operation rate limiter options
|
||||
#
|
||||
# disk_rate_limiter_ops_max_rate controls disk I/O bandwidth (size in ops/sec
|
||||
# for SB/VM).
|
||||
# The same value is used for inbound and outbound bandwidth.
|
||||
# Default 0-sized value means unlimited rate.
|
||||
#disk_rate_limiter_ops_max_rate = 0
|
||||
#
|
||||
# disk_rate_limiter_ops_one_time_burst increases the initial max rate and this
|
||||
# initial extra credit does *NOT* affect the overall limit and can be used for
|
||||
# an *initial* burst of data.
|
||||
# This is *optional* and only takes effect if disk_rate_limiter_bw_max_rate is
|
||||
# set to a non zero value.
|
||||
#disk_rate_limiter_ops_one_time_burst = 0
|
||||
|
||||
# Enable pre allocation of VM RAM, default false
|
||||
# Enabling this will result in lower container density
|
||||
# as all of the memory will be allocated and locked
|
||||
@@ -323,7 +293,7 @@ dial_timeout = 45
|
||||
#
|
||||
# Effective Timeout Determination:
|
||||
# The effective timeout for a CreateContainerRequest is determined by taking the minimum of the following two values:
|
||||
# - create_container_timeout: The timeout value configured for creating containers (default: 30 seconds).
|
||||
# - create_container_timeout: The timeout value configured for creating containers (default: 30,000 milliseconds).
|
||||
# - runtime-request-timeout: The timeout value specified in the Kubelet configuration described as the link below:
|
||||
# (https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/#:~:text=runtime%2Drequest%2Dtimeout)
|
||||
# Defaults to @DEFCREATECONTAINERTIMEOUT@ second(s)
|
||||
|
||||
@@ -9,10 +9,11 @@ use std::path::PathBuf;
|
||||
pub mod ch_api;
|
||||
pub mod convert;
|
||||
pub mod net_util;
|
||||
mod virtio_devices;
|
||||
|
||||
use crate::virtio_devices::RateLimiterConfig;
|
||||
use kata_sys_util::protection::GuestProtection;
|
||||
use kata_types::config::hypervisor::Hypervisor as HypervisorConfig;
|
||||
use kata_types::config::hypervisor::RateLimiterConfig;
|
||||
pub use net_util::MacAddr;
|
||||
|
||||
pub const MAX_NUM_PCI_SEGMENTS: u16 = 16;
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) 2022-2023 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||
pub struct TokenBucketConfig {
|
||||
pub size: u64,
|
||||
pub one_time_burst: Option<u64>,
|
||||
pub refill_time: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct RateLimiterConfig {
|
||||
pub bandwidth: Option<TokenBucketConfig>,
|
||||
pub ops: Option<TokenBucketConfig>,
|
||||
}
|
||||
@@ -25,7 +25,6 @@ use ch_config::ch_api::{
|
||||
use ch_config::convert::{DEFAULT_DISK_QUEUES, DEFAULT_DISK_QUEUE_SIZE, DEFAULT_NUM_PCI_SEGMENTS};
|
||||
use ch_config::DiskConfig;
|
||||
use ch_config::{net_util::MacAddr, DeviceConfig, FsConfig, NetConfig, VsockConfig};
|
||||
use kata_types::config::hypervisor::RateLimiterConfig;
|
||||
use safe_path::scoped_join;
|
||||
use std::convert::TryFrom;
|
||||
use std::path::PathBuf;
|
||||
@@ -323,18 +322,6 @@ impl CloudHypervisorInner {
|
||||
.is_direct
|
||||
.unwrap_or(self.config.blockdev_info.block_device_cache_direct);
|
||||
|
||||
let block_rate_limit = RateLimiterConfig::new(
|
||||
self.config.blockdev_info.disk_rate_limiter_bw_max_rate,
|
||||
self.config.blockdev_info.disk_rate_limiter_ops_max_rate,
|
||||
self.config
|
||||
.blockdev_info
|
||||
.disk_rate_limiter_bw_one_time_burst,
|
||||
self.config
|
||||
.blockdev_info
|
||||
.disk_rate_limiter_ops_one_time_burst,
|
||||
);
|
||||
disk_config.rate_limiter_config = block_rate_limit;
|
||||
|
||||
let response = cloud_hypervisor_vm_blockdev_add(
|
||||
socket.try_clone().context("failed to clone socket")?,
|
||||
disk_config,
|
||||
|
||||
@@ -7,7 +7,6 @@ use super::inner::CloudHypervisorInner;
|
||||
use crate::ch::utils::get_api_socket_path;
|
||||
use crate::ch::utils::get_vsock_path;
|
||||
use crate::kernel_param::KernelParams;
|
||||
use crate::selinux;
|
||||
use crate::utils::{bytes_to_megs, get_jailer_root, get_sandbox_path, megs_to_bytes};
|
||||
use crate::MemoryConfig;
|
||||
use crate::VM_ROOTFS_DRIVER_BLK;
|
||||
@@ -370,25 +369,12 @@ impl CloudHypervisorInner {
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let selinux_label = self.config.security_info.selinux_label.clone();
|
||||
let _pre = cmd.pre_exec(move || {
|
||||
if let Some(netns_path) = &netns {
|
||||
let netns_fd = std::fs::File::open(netns_path);
|
||||
let _ = setns(netns_fd?.as_raw_fd(), CloneFlags::CLONE_NEWNET)
|
||||
.context("set netns failed");
|
||||
}
|
||||
if let Some(label) = selinux_label.as_ref() {
|
||||
if let Err(e) = selinux::set_exec_label(label) {
|
||||
error!(sl!(), "Failed to set SELinux label in child process: {}", e);
|
||||
// Don't return error here to avoid breaking the process startup
|
||||
// Log the error and continue
|
||||
} else {
|
||||
info!(
|
||||
sl!(),
|
||||
"Successfully set SELinux label in child process: {}", &label
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
@@ -545,12 +531,7 @@ impl CloudHypervisorInner {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn prepare_vm(
|
||||
&mut self,
|
||||
id: &str,
|
||||
netns: Option<String>,
|
||||
selinux_label: Option<String>,
|
||||
) -> Result<()> {
|
||||
pub(crate) async fn prepare_vm(&mut self, id: &str, netns: Option<String>) -> Result<()> {
|
||||
self.id = id.to_string();
|
||||
self.state = VmmState::NotReady;
|
||||
|
||||
@@ -560,13 +541,6 @@ impl CloudHypervisorInner {
|
||||
|
||||
self.netns = netns;
|
||||
|
||||
if !self.hypervisor_config().disable_selinux {
|
||||
if let Some(label) = selinux_label.as_ref() {
|
||||
self.config.security_info.selinux_label = Some(label.to_string());
|
||||
selinux::set_exec_label(label).context("failed to set SELinux process label")?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -65,10 +65,9 @@ impl Hypervisor for CloudHypervisor {
|
||||
id: &str,
|
||||
netns: Option<String>,
|
||||
_annotations: &HashMap<String, String>,
|
||||
selinux_label: Option<String>,
|
||||
) -> Result<()> {
|
||||
let mut inner = self.inner.write().await;
|
||||
inner.prepare_vm(id, netns, selinux_label).await
|
||||
inner.prepare_vm(id, netns).await
|
||||
}
|
||||
|
||||
async fn start_vm(&self, timeout: i32) -> Result<()> {
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use kata_sys_util::rand::RandomBytes;
|
||||
use kata_types::config::hypervisor::{BlockDeviceInfo, TopologyConfigInfo, VIRTIO_SCSI};
|
||||
use kata_types::config::hypervisor::{TopologyConfigInfo, VIRTIO_SCSI};
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
|
||||
use crate::{
|
||||
@@ -117,8 +117,12 @@ impl DeviceManager {
|
||||
self.pcie_topology.clone()
|
||||
}
|
||||
|
||||
async fn get_block_device_info(&self) -> BlockDeviceInfo {
|
||||
self.hypervisor.hypervisor_config().await.blockdev_info
|
||||
async fn get_block_driver(&self) -> String {
|
||||
self.hypervisor
|
||||
.hypervisor_config()
|
||||
.await
|
||||
.blockdev_info
|
||||
.block_device_driver
|
||||
}
|
||||
|
||||
async fn try_add_device(&mut self, device_id: &str) -> Result<()> {
|
||||
@@ -619,15 +623,15 @@ pub async fn do_update_device(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_block_device_info(d: &RwLock<DeviceManager>) -> BlockDeviceInfo {
|
||||
d.read().await.get_block_device_info().await
|
||||
pub async fn get_block_driver(d: &RwLock<DeviceManager>) -> String {
|
||||
d.read().await.get_block_driver().await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::DeviceManager;
|
||||
use crate::{
|
||||
device::{device_manager::get_block_device_info, DeviceConfig, DeviceType},
|
||||
device::{device_manager::get_block_driver, DeviceConfig, DeviceType},
|
||||
qemu::Qemu,
|
||||
BlockConfig, KATA_BLK_DEV_TYPE,
|
||||
};
|
||||
@@ -666,7 +670,7 @@ mod tests {
|
||||
assert!(dm.is_ok());
|
||||
|
||||
let d = dm.unwrap();
|
||||
let block_driver = get_block_device_info(&d).await.block_device_driver;
|
||||
let block_driver = get_block_driver(&d).await;
|
||||
let dev_info = DeviceConfig::BlockCfg(BlockConfig {
|
||||
path_on_host: "/dev/dddzzz".to_string(),
|
||||
driver_option: block_driver,
|
||||
|
||||
@@ -24,9 +24,9 @@ pub use vfio::{
|
||||
pub use vhost_user::{VhostUserConfig, VhostUserDevice, VhostUserType};
|
||||
pub use vhost_user_net::VhostUserNetDevice;
|
||||
pub use virtio_blk::{
|
||||
BlockConfig, BlockDevice, BlockDeviceAio, KATA_BLK_DEV_TYPE, KATA_CCW_DEV_TYPE,
|
||||
KATA_MMIO_BLK_DEV_TYPE, KATA_NVDIMM_DEV_TYPE, KATA_SCSI_DEV_TYPE, VIRTIO_BLOCK_CCW,
|
||||
VIRTIO_BLOCK_MMIO, VIRTIO_BLOCK_PCI, VIRTIO_PMEM,
|
||||
BlockConfig, BlockDevice, KATA_BLK_DEV_TYPE, KATA_CCW_DEV_TYPE, KATA_MMIO_BLK_DEV_TYPE,
|
||||
KATA_NVDIMM_DEV_TYPE, KATA_SCSI_DEV_TYPE, VIRTIO_BLOCK_CCW, VIRTIO_BLOCK_MMIO,
|
||||
VIRTIO_BLOCK_PCI, VIRTIO_PMEM,
|
||||
};
|
||||
pub use virtio_fs::{
|
||||
ShareFsConfig, ShareFsDevice, ShareFsMountConfig, ShareFsMountOperation, ShareFsMountType,
|
||||
|
||||
@@ -18,7 +18,6 @@ use dragonball::{
|
||||
vm::VmConfigInfo,
|
||||
};
|
||||
|
||||
use crate::DEFAULT_HOTPLUG_TIMEOUT;
|
||||
use kata_sys_util::mount;
|
||||
use kata_types::{
|
||||
capabilities::{Capabilities, CapabilityBits},
|
||||
@@ -38,6 +37,8 @@ const DRAGONBALL_INITRD: &str = "initrd";
|
||||
const DRAGONBALL_ROOT_FS: &str = "rootfs";
|
||||
const BALLOON_DEVICE_ID: &str = "balloon0";
|
||||
const MEM_DEVICE_ID: &str = "memmr0";
|
||||
/// default hotplug timeout
|
||||
const DEFAULT_HOTPLUG_TIMEOUT: u64 = 250;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DragonballInner {
|
||||
|
||||
@@ -6,15 +6,13 @@
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
|
||||
use super::{build_dragonball_network_config, DragonballInner};
|
||||
use crate::device::pci_path::PciPath;
|
||||
use crate::VhostUserConfig;
|
||||
use crate::{device::pci_path::PciPath, KATA_BLK_DEV_TYPE};
|
||||
use crate::{
|
||||
device::DeviceType, HybridVsockConfig, NetworkConfig, ShareFsConfig, ShareFsMountConfig,
|
||||
ShareFsMountOperation, ShareFsMountType, VfioDevice, VmmState, DEFAULT_HOTPLUG_TIMEOUT,
|
||||
JAILER_ROOT,
|
||||
ShareFsMountOperation, ShareFsMountType, VfioDevice, VmmState, JAILER_ROOT,
|
||||
};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use dbs_utils::net::MacAddr;
|
||||
@@ -35,6 +33,10 @@ const DEFAULT_VIRTIO_FS_QUEUE_SIZE: i32 = 1024;
|
||||
const VIRTIO_FS: &str = "virtio-fs";
|
||||
const INLINE_VIRTIO_FS: &str = "inline-virtio-fs";
|
||||
|
||||
pub(crate) fn drive_index_to_id(index: u64) -> String {
|
||||
format!("drive_{}", index)
|
||||
}
|
||||
|
||||
impl DragonballInner {
|
||||
pub(crate) async fn add_device(&mut self, device: DeviceType) -> Result<DeviceType> {
|
||||
if self.state == VmmState::NotReady {
|
||||
@@ -60,30 +62,15 @@ impl DragonballInner {
|
||||
|
||||
Ok(DeviceType::Vfio(hostdev))
|
||||
}
|
||||
DeviceType::Block(mut block) => {
|
||||
let use_pci_bus = if block.config.driver_option == KATA_BLK_DEV_TYPE {
|
||||
Some(true)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let guest_device_id = self
|
||||
.add_block_device(
|
||||
block.config.path_on_host.as_str(),
|
||||
block.device_id.as_str(),
|
||||
block.config.is_readonly,
|
||||
block.config.no_drop,
|
||||
block.config.is_direct,
|
||||
use_pci_bus,
|
||||
)
|
||||
.context("add block device")?;
|
||||
|
||||
if let Some(slot) = guest_device_id {
|
||||
if slot > 0 {
|
||||
block.config.pci_path = Some(PciPath::try_from(slot as u32)?);
|
||||
}
|
||||
}
|
||||
|
||||
DeviceType::Block(block) => {
|
||||
self.add_block_device(
|
||||
block.config.path_on_host.as_str(),
|
||||
block.device_id.as_str(),
|
||||
block.config.is_readonly,
|
||||
block.config.no_drop,
|
||||
block.config.is_direct,
|
||||
)
|
||||
.context("add block device")?;
|
||||
Ok(DeviceType::Block(block))
|
||||
}
|
||||
DeviceType::VhostUserBlk(block) => {
|
||||
@@ -93,7 +80,6 @@ impl DragonballInner {
|
||||
block.is_readonly,
|
||||
block.no_drop,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.context("add vhost user based block device")?;
|
||||
Ok(DeviceType::VhostUserBlk(block))
|
||||
@@ -129,9 +115,11 @@ impl DragonballInner {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
DeviceType::Block(block) => self
|
||||
.remove_block_drive(block.device_id.as_str())
|
||||
.context("remove block drive"),
|
||||
DeviceType::Block(block) => {
|
||||
let drive_id = drive_index_to_id(block.config.index);
|
||||
self.remove_block_drive(drive_id.as_str())
|
||||
.context("remove block drive")
|
||||
}
|
||||
DeviceType::Vfio(hostdev) => {
|
||||
let primary_device = hostdev.devices.first().unwrap().clone();
|
||||
let hostdev_id = primary_device.hostdev_id;
|
||||
@@ -220,8 +208,7 @@ impl DragonballInner {
|
||||
read_only: bool,
|
||||
no_drop: bool,
|
||||
is_direct: Option<bool>,
|
||||
use_pci_bus: Option<bool>,
|
||||
) -> Result<Option<i32>> {
|
||||
) -> Result<()> {
|
||||
let jailed_drive = self.get_resource(path, id).context("get resource")?;
|
||||
self.cached_block_devices.insert(id.to_string());
|
||||
|
||||
@@ -232,17 +219,16 @@ impl DragonballInner {
|
||||
is_direct: is_direct.unwrap_or(self.config.blockdev_info.block_device_cache_direct),
|
||||
no_drop,
|
||||
is_read_only: read_only,
|
||||
use_pci_bus,
|
||||
..Default::default()
|
||||
};
|
||||
self.vmm_instance
|
||||
.insert_block_device(blk_cfg, Duration::from_millis(DEFAULT_HOTPLUG_TIMEOUT))
|
||||
.insert_block_device(blk_cfg)
|
||||
.context("insert block device")
|
||||
}
|
||||
|
||||
fn remove_block_drive(&mut self, id: &str) -> Result<()> {
|
||||
self.vmm_instance
|
||||
.remove_block_device(id, Duration::from_millis(DEFAULT_HOTPLUG_TIMEOUT))
|
||||
.remove_block_device(id)
|
||||
.context("remove block device")?;
|
||||
|
||||
if self.cached_block_devices.contains(id) && self.jailed {
|
||||
|
||||
@@ -19,12 +19,7 @@ use crate::{
|
||||
};
|
||||
|
||||
impl DragonballInner {
|
||||
pub(crate) async fn prepare_vm(
|
||||
&mut self,
|
||||
id: &str,
|
||||
netns: Option<String>,
|
||||
selinux_label: Option<String>,
|
||||
) -> Result<()> {
|
||||
pub(crate) async fn prepare_vm(&mut self, id: &str, netns: Option<String>) -> Result<()> {
|
||||
self.id = id.to_string();
|
||||
self.state = VmmState::NotReady;
|
||||
|
||||
@@ -32,16 +27,6 @@ impl DragonballInner {
|
||||
self.jailer_root = get_jailer_root(id);
|
||||
self.netns = netns;
|
||||
|
||||
// Dragonball is a built-in VMM that runs as a thread inside the
|
||||
// runtime. Because it is not a standalone process, Dragonball cannot
|
||||
// independently set per-VM SELinux exec labels; any provided
|
||||
// selinux_label will be ignored.
|
||||
if selinux_label.is_some() {
|
||||
warn!(sl!(),
|
||||
"SELinux label is provided for Dragonball VM, but Dragonball does not support SELinux; the label will be ignored",
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -75,10 +75,9 @@ impl Hypervisor for Dragonball {
|
||||
id: &str,
|
||||
netns: Option<String>,
|
||||
_annotations: &HashMap<String, String>,
|
||||
selinux_label: Option<String>,
|
||||
) -> Result<()> {
|
||||
let mut inner = self.inner.write().await;
|
||||
inner.prepare_vm(id, netns, selinux_label).await
|
||||
inner.prepare_vm(id, netns).await
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
|
||||
@@ -237,37 +237,16 @@ impl VmmInstance {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn insert_block_device(
|
||||
&self,
|
||||
device_cfg: BlockDeviceConfigInfo,
|
||||
timeout: Duration,
|
||||
) -> Result<Option<i32>> {
|
||||
let vmmdata = self
|
||||
.handle_request_with_retry(Request::Sync(VmmAction::InsertBlockDevice(
|
||||
device_cfg.clone(),
|
||||
)))
|
||||
.with_context(|| format!("Failed to insert block device {:?}", device_cfg))?;
|
||||
|
||||
if let VmmData::SyncHotplug((_, receiver)) = vmmdata {
|
||||
let guest_dev_id = receiver.recv_timeout(timeout)?;
|
||||
return Ok(guest_dev_id);
|
||||
}
|
||||
Ok(None)
|
||||
pub fn insert_block_device(&self, device_cfg: BlockDeviceConfigInfo) -> Result<()> {
|
||||
self.handle_request_with_retry(Request::Sync(VmmAction::InsertBlockDevice(
|
||||
device_cfg.clone(),
|
||||
)))
|
||||
.with_context(|| format!("Failed to insert block device {:?}", device_cfg))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove_block_device(&self, id: &str, timeout: Duration) -> Result<()> {
|
||||
pub fn remove_block_device(&self, id: &str) -> Result<()> {
|
||||
info!(sl!(), "remove block device {}", id);
|
||||
|
||||
let vmmdata = self
|
||||
.handle_request(Request::Sync(VmmAction::PrepareRemoveBlockDevice(
|
||||
id.to_string(),
|
||||
)))
|
||||
.with_context(|| format!("Failed to prepare remove block device {:?}", id))?;
|
||||
|
||||
if let VmmData::SyncHotplug((_, receiver)) = vmmdata {
|
||||
let _ = receiver.recv_timeout(timeout)?;
|
||||
}
|
||||
|
||||
self.handle_request(Request::Sync(VmmAction::RemoveBlockDevice(id.to_string())))
|
||||
.with_context(|| format!("Failed to remove block device {:?}", id))?;
|
||||
Ok(())
|
||||
|
||||
@@ -16,7 +16,6 @@ use dbs_utils::net::MacAddr;
|
||||
use hyper::{Body, Method, Request, Response};
|
||||
use hyperlocal::Uri;
|
||||
use kata_sys_util::mount;
|
||||
use kata_types::config::hypervisor::RateLimiterConfig;
|
||||
use nix::mount::MsFlags;
|
||||
use serde_json::json;
|
||||
use tokio::{fs, fs::File};
|
||||
@@ -178,25 +177,9 @@ impl FcInner {
|
||||
let new_drive_path = self
|
||||
.get_resource(drive_path, new_drive_id)
|
||||
.context("get resource CONTAINER ROOTFS")?;
|
||||
|
||||
let block_rate_limit = RateLimiterConfig::new(
|
||||
self.config.blockdev_info.disk_rate_limiter_bw_max_rate,
|
||||
self.config.blockdev_info.disk_rate_limiter_ops_max_rate,
|
||||
self.config
|
||||
.blockdev_info
|
||||
.disk_rate_limiter_bw_one_time_burst,
|
||||
self.config
|
||||
.blockdev_info
|
||||
.disk_rate_limiter_ops_one_time_burst,
|
||||
);
|
||||
|
||||
let rate_limiter = serde_json::to_string(&block_rate_limit)
|
||||
.with_context(|| format!("serde {:?} to json", block_rate_limit))?;
|
||||
|
||||
let body: String = json!({
|
||||
"drive_id": format!("drive{drive_id}"),
|
||||
"path_on_host": new_drive_path,
|
||||
"rate_limiter": rate_limiter,
|
||||
"path_on_host": new_drive_path
|
||||
})
|
||||
.to_string();
|
||||
self.request_with_retry(
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
//SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::firecracker::{inner_hypervisor::FC_API_SOCKET_NAME, sl};
|
||||
use crate::HypervisorState;
|
||||
use crate::MemoryConfig;
|
||||
use crate::HYPERVISOR_FIRECRACKER;
|
||||
use crate::{device::DeviceType, VmmState};
|
||||
use crate::{selinux, HypervisorState};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use hyper::Client;
|
||||
@@ -110,7 +110,6 @@ impl FcInner {
|
||||
|
||||
// Make sure we're in the correct Network Namespace
|
||||
unsafe {
|
||||
let selinux_label = self.config.security_info.selinux_label.clone();
|
||||
let _pre = cmd.pre_exec(move || {
|
||||
if let Some(netns_path) = &netns {
|
||||
debug!(sl(), "set netns for vmm master {:?}", &netns_path);
|
||||
@@ -118,18 +117,6 @@ impl FcInner {
|
||||
let _ = setns(netns_fd?.as_raw_fd(), CloneFlags::CLONE_NEWNET)
|
||||
.context("set netns failed");
|
||||
}
|
||||
if let Some(label) = selinux_label.as_ref() {
|
||||
if let Err(e) = selinux::set_exec_label(label) {
|
||||
error!(sl!(), "Failed to set SELinux label in child process: {}", e);
|
||||
// Don't return error here to avoid breaking the process startup
|
||||
// Log the error and continue
|
||||
} else {
|
||||
info!(
|
||||
sl!(),
|
||||
"Successfully set SELinux label in child process: {}", &label
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::firecracker::{sl, FcInner};
|
||||
use crate::{selinux, VcpuThreadIds, VmmState, HYPERVISOR_FIRECRACKER};
|
||||
use crate::{VcpuThreadIds, VmmState, HYPERVISOR_FIRECRACKER};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use kata_types::capabilities::Capabilities;
|
||||
use kata_types::config::KATA_PATH;
|
||||
@@ -19,12 +19,7 @@ pub const ROOT: &str = "root";
|
||||
const HYBRID_VSOCK_SCHEME: &str = "hvsock";
|
||||
|
||||
impl FcInner {
|
||||
pub(crate) async fn prepare_vm(
|
||||
&mut self,
|
||||
id: &str,
|
||||
_netns: Option<String>,
|
||||
selinux_label: Option<String>,
|
||||
) -> Result<()> {
|
||||
pub(crate) async fn prepare_vm(&mut self, id: &str, _netns: Option<String>) -> Result<()> {
|
||||
debug!(sl(), "Preparing Firecracker");
|
||||
|
||||
self.id = id.to_string();
|
||||
@@ -60,14 +55,6 @@ impl FcInner {
|
||||
.context(format!("failed to create directory {:?}", self.vm_path));
|
||||
|
||||
self.netns = _netns.clone();
|
||||
|
||||
if !self.hypervisor_config().disable_selinux {
|
||||
if let Some(label) = selinux_label.as_ref() {
|
||||
self.config.security_info.selinux_label = Some(label.to_string());
|
||||
selinux::set_exec_label(label).context("failed to set SELinux process label")?;
|
||||
}
|
||||
}
|
||||
|
||||
self.prepare_vmm(self.netns.clone()).await?;
|
||||
self.state = VmmState::VmmServerReady;
|
||||
self.prepare_vmm_resources().await?;
|
||||
|
||||
@@ -64,10 +64,9 @@ impl Hypervisor for Firecracker {
|
||||
id: &str,
|
||||
netns: Option<String>,
|
||||
_annotations: &HashMap<String, String>,
|
||||
selinux_label: Option<String>,
|
||||
) -> Result<()> {
|
||||
let mut inner = self.inner.write().await;
|
||||
inner.prepare_vm(id, netns, selinux_label).await
|
||||
inner.prepare_vm(id, netns).await
|
||||
}
|
||||
|
||||
async fn start_vm(&self, timeout: i32) -> Result<()> {
|
||||
|
||||
@@ -19,7 +19,6 @@ pub mod firecracker;
|
||||
mod kernel_param;
|
||||
pub mod qemu;
|
||||
pub mod remote;
|
||||
pub mod selinux;
|
||||
pub use kernel_param::Param;
|
||||
pub mod utils;
|
||||
use std::collections::HashMap;
|
||||
@@ -70,10 +69,6 @@ pub const HYPERVISOR_REMOTE: &str = "remote";
|
||||
pub const DEFAULT_HYBRID_VSOCK_NAME: &str = "kata.hvsock";
|
||||
pub const JAILER_ROOT: &str = "root";
|
||||
|
||||
/// default hotplug timeout
|
||||
#[allow(dead_code)]
|
||||
const DEFAULT_HOTPLUG_TIMEOUT: u64 = 250;
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub(crate) enum VmmState {
|
||||
NotReady,
|
||||
@@ -103,7 +98,6 @@ pub trait Hypervisor: std::fmt::Debug + Send + Sync {
|
||||
id: &str,
|
||||
netns: Option<String>,
|
||||
annotations: &HashMap<String, String>,
|
||||
selinux_label: Option<String>,
|
||||
) -> Result<()>;
|
||||
async fn start_vm(&self, timeout: i32) -> Result<()>;
|
||||
async fn stop_vm(&self) -> Result<()>;
|
||||
|
||||
@@ -7,8 +7,8 @@ use super::cmdline_generator::{get_network_device, QemuCmdLine, QMP_SOCKET_FILE}
|
||||
use super::qmp::Qmp;
|
||||
use crate::device::topology::PCIePort;
|
||||
use crate::{
|
||||
device::driver::ProtectionDeviceConfig, hypervisor_persist::HypervisorState, selinux,
|
||||
HypervisorConfig, MemoryConfig, VcpuThreadIds, VsockDevice, HYPERVISOR_QEMU,
|
||||
device::driver::ProtectionDeviceConfig, hypervisor_persist::HypervisorState, HypervisorConfig,
|
||||
MemoryConfig, VcpuThreadIds, VsockDevice, HYPERVISOR_QEMU,
|
||||
};
|
||||
|
||||
use crate::utils::{bytes_to_megs, enter_netns, megs_to_bytes};
|
||||
@@ -65,23 +65,11 @@ impl QemuInner {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn prepare_vm(
|
||||
&mut self,
|
||||
id: &str,
|
||||
netns: Option<String>,
|
||||
selinux_label: Option<String>,
|
||||
) -> Result<()> {
|
||||
pub(crate) async fn prepare_vm(&mut self, id: &str, netns: Option<String>) -> Result<()> {
|
||||
info!(sl!(), "Preparing QEMU VM");
|
||||
self.id = id.to_string();
|
||||
self.netns = netns;
|
||||
|
||||
if !self.hypervisor_config().disable_selinux {
|
||||
if let Some(label) = selinux_label.as_ref() {
|
||||
self.config.security_info.selinux_label = Some(label.to_string());
|
||||
selinux::set_exec_label(label).context("failed to set SELinux process label")?;
|
||||
}
|
||||
}
|
||||
|
||||
let vm_path = [KATA_PATH, self.id.as_str()].join("/");
|
||||
std::fs::create_dir_all(vm_path)?;
|
||||
|
||||
@@ -208,23 +196,11 @@ impl QemuInner {
|
||||
|
||||
info!(sl!(), "qemu cmd: {:?}", command);
|
||||
|
||||
// we need move the qemu process into Network Namespace and set SELinux label.
|
||||
// we need move the qemu process into Network Namespace.
|
||||
unsafe {
|
||||
let selinux_label = self.config.security_info.selinux_label.clone();
|
||||
let _pre_exec = command.pre_exec(move || {
|
||||
let _ = enter_netns(&netns);
|
||||
if let Some(label) = selinux_label.as_ref() {
|
||||
if let Err(e) = selinux::set_exec_label(label) {
|
||||
error!(sl!(), "Failed to set SELinux label in child process: {}", e);
|
||||
// Don't return error here to avoid breaking the process startup
|
||||
// Log the error and continue
|
||||
} else {
|
||||
info!(
|
||||
sl!(),
|
||||
"Successfully set SELinux label in child process: {}", &label
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
|
||||
@@ -58,10 +58,9 @@ impl Hypervisor for Qemu {
|
||||
id: &str,
|
||||
netns: Option<String>,
|
||||
_annotations: &HashMap<String, String>,
|
||||
selinux_label: Option<String>,
|
||||
) -> Result<()> {
|
||||
let mut inner = self.inner.write().await;
|
||||
inner.prepare_vm(id, netns, selinux_label).await
|
||||
inner.prepare_vm(id, netns).await
|
||||
}
|
||||
|
||||
async fn start_vm(&self, timeout: i32) -> Result<()> {
|
||||
|
||||
@@ -634,7 +634,6 @@ impl Qmp {
|
||||
// add SCSI frontend device
|
||||
blkdev_add_args.insert("scsi-id".to_string(), scsi_id.into());
|
||||
blkdev_add_args.insert("lun".to_string(), lun.into());
|
||||
blkdev_add_args.insert("share-rw".to_string(), true.into());
|
||||
|
||||
self.qmp
|
||||
.execute(&qmp::device_add {
|
||||
@@ -655,7 +654,6 @@ impl Qmp {
|
||||
} else {
|
||||
let (bus, slot) = self.find_free_slot()?;
|
||||
blkdev_add_args.insert("addr".to_owned(), format!("{:02}", slot).into());
|
||||
blkdev_add_args.insert("share-rw".to_string(), true.into());
|
||||
|
||||
self.qmp
|
||||
.execute(&qmp::device_add {
|
||||
|
||||
@@ -146,16 +146,8 @@ impl RemoteInner {
|
||||
id: &str,
|
||||
netns: Option<String>,
|
||||
annotations: &HashMap<String, String>,
|
||||
selinux_label: Option<String>,
|
||||
) -> Result<()> {
|
||||
info!(sl!(), "Preparing REMOTE VM");
|
||||
// Remote does not support SELinux; any provided selinux_label will be ignored.
|
||||
if selinux_label.is_some() {
|
||||
warn!(sl!(),
|
||||
"SELinux label is provided for Remote VM, but Remote does not support SELinux; the label will be ignored",
|
||||
);
|
||||
}
|
||||
|
||||
self.id = id.to_string();
|
||||
|
||||
if let Some(netns_path) = &netns {
|
||||
|
||||
@@ -48,12 +48,9 @@ impl Hypervisor for Remote {
|
||||
id: &str,
|
||||
netns: Option<String>,
|
||||
annotations: &HashMap<String, String>,
|
||||
selinux_label: Option<String>,
|
||||
) -> Result<()> {
|
||||
let mut inner = self.inner.write().await;
|
||||
inner
|
||||
.prepare_vm(id, netns, annotations, selinux_label)
|
||||
.await
|
||||
inner.prepare_vm(id, netns, annotations).await
|
||||
}
|
||||
|
||||
async fn start_vm(&self, timeout: i32) -> Result<()> {
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
// Copyright 2025 Kata Contributors
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::fs::{self, OpenOptions};
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use nix::unistd::gettid;
|
||||
|
||||
/// Check if SELinux is enabled on the system
|
||||
pub fn is_selinux_enabled() -> bool {
|
||||
fs::read_to_string("/proc/mounts")
|
||||
.map(|buf| buf.contains("selinuxfs"))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn set_exec_label(label: &str) -> Result<()> {
|
||||
let mut attr_path = Path::new("/proc/thread-self/attr/exec").to_path_buf();
|
||||
if !attr_path.exists() {
|
||||
// Fall back to the old convention
|
||||
attr_path = Path::new("/proc/self/task")
|
||||
.join(gettid().to_string())
|
||||
.join("attr/exec")
|
||||
}
|
||||
|
||||
let mut file = OpenOptions::new()
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.open(attr_path)
|
||||
.context("open attr path")?;
|
||||
|
||||
file.write_all(label.as_bytes())
|
||||
.with_context(|| "failed to apply SELinux label")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const TEST_LABEL: &str = "system_u:system_r:unconfined_t:s0";
|
||||
|
||||
#[test]
|
||||
fn test_set_exec_label() {
|
||||
let ret = set_exec_label(TEST_LABEL);
|
||||
if is_selinux_enabled() {
|
||||
assert!(ret.is_ok(), "Expecting Ok, Got {:?}", ret);
|
||||
// Check that the label was set correctly
|
||||
let mut attr_path = std::path::Path::new("/proc/thread-self/attr/exec").to_path_buf();
|
||||
if !attr_path.exists() {
|
||||
attr_path = std::path::Path::new("/proc/self/task")
|
||||
.join(nix::unistd::gettid().to_string())
|
||||
.join("attr/exec");
|
||||
}
|
||||
let label = std::fs::read_to_string(attr_path).unwrap();
|
||||
assert_eq!(label.trim_end_matches('\0'), TEST_LABEL);
|
||||
} else {
|
||||
assert!(ret.is_err(), "Expecting error, Got {:?}", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,6 @@ inotify = "0.11.0"
|
||||
walkdir = "2.5.0"
|
||||
flate2 = { version = "1.0", features = ["zlib"] }
|
||||
tempfile = "3.19.1"
|
||||
hex = "0.4"
|
||||
|
||||
## Dependencies from `rust-netlink`
|
||||
netlink-packet-route = "0.22"
|
||||
|
||||
@@ -7,7 +7,7 @@ use agent::Agent;
|
||||
use anyhow::{anyhow, Context, Error, Result};
|
||||
use hypervisor::{
|
||||
device::{
|
||||
device_manager::{do_handle_device, get_block_device_info, DeviceManager},
|
||||
device_manager::{do_handle_device, get_block_driver, DeviceManager},
|
||||
DeviceConfig, DeviceType,
|
||||
},
|
||||
BlockConfig,
|
||||
@@ -156,9 +156,7 @@ impl SwapTask {
|
||||
let swap_path = swap_path.to_string_lossy().to_string();
|
||||
|
||||
// Add swap file to sandbox
|
||||
let block_driver = get_block_device_info(&self.device_manager)
|
||||
.await
|
||||
.block_device_driver;
|
||||
let block_driver = get_block_driver(&self.device_manager).await;
|
||||
let dev_info = DeviceConfig::BlockCfg(BlockConfig {
|
||||
path_on_host: swap_path.clone(),
|
||||
driver_option: block_driver,
|
||||
|
||||
@@ -90,9 +90,9 @@ impl ResourceManager {
|
||||
inner.setup_after_start_vm().await
|
||||
}
|
||||
|
||||
pub async fn get_storage_for_sandbox(&self, shm_size: u64) -> Result<Vec<Storage>> {
|
||||
pub async fn get_storage_for_sandbox(&self) -> Result<Vec<Storage>> {
|
||||
let inner = self.inner.read().await;
|
||||
inner.get_storage_for_sandbox(shm_size).await
|
||||
inner.get_storage_for_sandbox().await
|
||||
}
|
||||
|
||||
pub async fn handler_rootfs(
|
||||
|
||||
@@ -11,15 +11,13 @@ use anyhow::{anyhow, Context, Ok, Result};
|
||||
use async_trait::async_trait;
|
||||
use hypervisor::{
|
||||
device::{
|
||||
device_manager::{do_handle_device, get_block_device_info, DeviceManager},
|
||||
device_manager::{do_handle_device, get_block_driver, DeviceManager},
|
||||
util::{get_host_path, DEVICE_TYPE_CHAR},
|
||||
DeviceConfig, DeviceType,
|
||||
},
|
||||
BlockConfig, BlockDeviceAio, Hypervisor, VfioConfig,
|
||||
};
|
||||
use kata_types::mount::{
|
||||
Mount, DEFAULT_KATA_GUEST_SANDBOX_DIR, KATA_EPHEMERAL_VOLUME_TYPE, SHM_DIR,
|
||||
BlockConfig, Hypervisor, VfioConfig,
|
||||
};
|
||||
use kata_types::mount::Mount;
|
||||
use kata_types::{
|
||||
config::{hypervisor::TopologyConfigInfo, TomlConfig},
|
||||
mount::{adjust_rootfs_mounts, KATA_IMAGE_FORCE_GUEST_PULL},
|
||||
@@ -328,33 +326,12 @@ impl ResourceManagerInner {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_storage_for_sandbox(&self, shm_size: u64) -> Result<Vec<Storage>> {
|
||||
pub async fn get_storage_for_sandbox(&self) -> Result<Vec<Storage>> {
|
||||
let mut storages = vec![];
|
||||
if let Some(d) = self.share_fs.as_ref() {
|
||||
let mut s = d.get_storages().await.context("get storage")?;
|
||||
storages.append(&mut s);
|
||||
}
|
||||
|
||||
let shm_size_option = format!("size={}", shm_size);
|
||||
let mount_point = format!("{}/{}", DEFAULT_KATA_GUEST_SANDBOX_DIR, SHM_DIR);
|
||||
|
||||
let shm_storage = Storage {
|
||||
driver: KATA_EPHEMERAL_VOLUME_TYPE.to_string(),
|
||||
mount_point,
|
||||
source: "shm".to_string(),
|
||||
fs_type: "tmpfs".to_string(),
|
||||
options: vec![
|
||||
"noexec".to_string(),
|
||||
"nosuid".to_string(),
|
||||
"nodev".to_string(),
|
||||
"mode=1777".to_string(),
|
||||
shm_size_option,
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
storages.push(shm_storage);
|
||||
|
||||
Ok(storages)
|
||||
}
|
||||
|
||||
@@ -415,17 +392,11 @@ impl ResourceManagerInner {
|
||||
for d in linux_devices.iter() {
|
||||
match d.typ() {
|
||||
LinuxDeviceType::B => {
|
||||
let block_driver = get_block_device_info(&self.device_manager)
|
||||
.await
|
||||
.block_device_driver;
|
||||
let aio = get_block_device_info(&self.device_manager)
|
||||
.await
|
||||
.block_device_aio;
|
||||
let block_driver = get_block_driver(&self.device_manager).await;
|
||||
let dev_info = DeviceConfig::BlockCfg(BlockConfig {
|
||||
major: d.major(),
|
||||
minor: d.minor(),
|
||||
driver_option: block_driver,
|
||||
blkdev_aio: BlockDeviceAio::new(&aio),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use hypervisor::{
|
||||
device::{
|
||||
device_manager::{do_handle_device, get_block_device_info, DeviceManager},
|
||||
device_manager::{do_handle_device, get_block_driver, DeviceManager},
|
||||
DeviceConfig, DeviceType,
|
||||
},
|
||||
BlockConfig, BlockDeviceAio,
|
||||
BlockConfig,
|
||||
};
|
||||
use kata_types::config::hypervisor::{
|
||||
VIRTIO_BLK_CCW, VIRTIO_BLK_MMIO, VIRTIO_BLK_PCI, VIRTIO_PMEM, VIRTIO_SCSI,
|
||||
@@ -50,14 +50,13 @@ impl BlockRootfs {
|
||||
fs::create_dir_all(&host_path)
|
||||
.map_err(|e| anyhow!("failed to create rootfs dir {}: {:?}", host_path, e))?;
|
||||
|
||||
let blkdev_info = get_block_device_info(d).await;
|
||||
let block_driver = blkdev_info.block_device_driver.clone();
|
||||
let block_driver = get_block_driver(d).await;
|
||||
|
||||
let block_device_config = &mut BlockConfig {
|
||||
major: stat::major(dev_id) as i64,
|
||||
minor: stat::minor(dev_id) as i64,
|
||||
driver_option: block_driver.clone(),
|
||||
path_on_host: rootfs.source.clone(),
|
||||
blkdev_aio: BlockDeviceAio::new(&blkdev_info.block_device_aio),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ use kata_types::{
|
||||
/// Image guest-pull related consts
|
||||
const KUBERNETES_CRI_IMAGE_NAME: &str = "io.kubernetes.cri.image-name";
|
||||
const KUBERNETES_CRIO_IMAGE_NAME: &str = "io.kubernetes.cri-o.ImageName";
|
||||
const KATA_VIRTUAL_VOLUME_TYPE_OVERLAY_FS: &str = "overlay";
|
||||
const KATA_VIRTUAL_VOLUME_TYPE_OVERLAY_FS: &str = "overlayfs";
|
||||
const KATA_GUEST_ROOT_SHARED_FS: &str = "/run/kata-containers/";
|
||||
|
||||
const CRI_CONTAINER_TYPE_KEY_LIST: &[&str] = &[
|
||||
|
||||
@@ -40,6 +40,8 @@ const KATA_HOST_SHARED_DIR: &str = "/run/kata-containers/shared/sandboxes/";
|
||||
/// share fs (for example virtio-fs) mount path in the guest
|
||||
pub const KATA_GUEST_SHARE_DIR: &str = "/run/kata-containers/shared/containers/";
|
||||
|
||||
pub(crate) const DEFAULT_KATA_GUEST_SANDBOX_DIR: &str = "/run/kata-containers/sandbox/";
|
||||
|
||||
pub const PASSTHROUGH_FS_DIR: &str = "passthrough";
|
||||
const RAFS_DIR: &str = "rafs";
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use hypervisor::{
|
||||
device::{
|
||||
device_manager::{do_handle_device, get_block_device_info, DeviceManager},
|
||||
device_manager::{do_handle_device, get_block_driver, DeviceManager},
|
||||
DeviceConfig,
|
||||
},
|
||||
BlockConfig, BlockDeviceAio,
|
||||
BlockConfig,
|
||||
};
|
||||
use kata_sys_util::mount::get_mount_path;
|
||||
use nix::sys::{stat, stat::SFlag};
|
||||
@@ -39,14 +39,12 @@ impl BlockVolume {
|
||||
Some(path) => path,
|
||||
None => return Err(anyhow!("mount source path is empty")),
|
||||
};
|
||||
|
||||
let blkdev_info = get_block_device_info(d).await;
|
||||
let block_driver = get_block_driver(d).await;
|
||||
let fstat = stat::stat(mnt_src).context(format!("stat {}", mnt_src.display()))?;
|
||||
let block_device_config = BlockConfig {
|
||||
major: stat::major(fstat.st_rdev) as i64,
|
||||
minor: stat::minor(fstat.st_rdev) as i64,
|
||||
driver_option: blkdev_info.block_device_driver,
|
||||
blkdev_aio: BlockDeviceAio::new(&blkdev_info.block_device_aio),
|
||||
driver_option: block_driver,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use hypervisor::{
|
||||
device::{
|
||||
device_manager::{do_handle_device, get_block_device_info, DeviceManager},
|
||||
device_manager::{do_handle_device, get_block_driver, DeviceManager},
|
||||
DeviceConfig,
|
||||
},
|
||||
BlockConfig, BlockDeviceAio,
|
||||
BlockConfig,
|
||||
};
|
||||
use kata_types::mount::DirectVolumeMountInfo;
|
||||
use nix::sys::{stat, stat::SFlag};
|
||||
@@ -36,7 +36,7 @@ impl RawblockVolume {
|
||||
read_only: bool,
|
||||
sid: &str,
|
||||
) -> Result<Self> {
|
||||
let blkdev_info = get_block_device_info(d).await;
|
||||
let block_driver = get_block_driver(d).await;
|
||||
|
||||
// check volume type
|
||||
if mount_info.volume_type != KATA_DIRECT_VOLUME_TYPE {
|
||||
@@ -60,8 +60,7 @@ impl RawblockVolume {
|
||||
|
||||
let block_config = BlockConfig {
|
||||
path_on_host: mount_info.device.clone(),
|
||||
driver_option: blkdev_info.block_device_driver,
|
||||
blkdev_aio: BlockDeviceAio::new(&blkdev_info.block_device_aio),
|
||||
driver_option: block_driver,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use hypervisor::{
|
||||
device::{
|
||||
device_manager::{do_handle_device, get_block_device_info, DeviceManager},
|
||||
device_manager::{do_handle_device, get_block_driver, DeviceManager},
|
||||
DeviceConfig, DeviceType,
|
||||
},
|
||||
VhostUserConfig, VhostUserType,
|
||||
@@ -74,7 +74,7 @@ impl SPDKVolume {
|
||||
}
|
||||
}
|
||||
|
||||
let block_driver = get_block_device_info(d).await.block_device_driver;
|
||||
let block_driver = get_block_driver(d).await;
|
||||
|
||||
let vhu_blk_config = &mut VhostUserConfig {
|
||||
socket_path: device,
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use super::Volume;
|
||||
use crate::share_fs::DEFAULT_KATA_GUEST_SANDBOX_DIR;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use hypervisor::device::device_manager::DeviceManager;
|
||||
use kata_sys_util::mount::{get_mount_path, get_mount_type};
|
||||
use kata_types::mount::DEFAULT_KATA_GUEST_SANDBOX_DIR;
|
||||
use kata_types::mount::KATA_EPHEMERAL_VOLUME_TYPE;
|
||||
use nix::sys::stat::stat;
|
||||
use oci_spec::runtime as oci;
|
||||
|
||||
@@ -9,11 +9,10 @@ mod default_volume;
|
||||
mod ephemeral_volume;
|
||||
pub mod hugepage;
|
||||
mod share_fs_volume;
|
||||
mod shm_volume;
|
||||
pub mod utils;
|
||||
|
||||
pub mod direct_volume;
|
||||
use crate::volume::{direct_volume::is_direct_volume, share_fs_volume::VolumeManager};
|
||||
use crate::volume::direct_volume::is_direct_volume;
|
||||
pub mod direct_volumes;
|
||||
|
||||
use std::{sync::Arc, vec::Vec};
|
||||
@@ -46,19 +45,11 @@ pub struct VolumeResourceInner {
|
||||
#[derive(Default)]
|
||||
pub struct VolumeResource {
|
||||
inner: Arc<RwLock<VolumeResourceInner>>,
|
||||
// The core purpose of introducing `volume_manager` to `VolumeResource` is to centralize the management of shared file system volumes.
|
||||
// By creating a single VolumeManager instance within VolumeResource, all shared file volumes are managed by one central entity.
|
||||
// This single volume_manager can accurately track the references of all ShareFsVolume instances to the shared volumes,
|
||||
// ensuring correct reference counting, proper volume lifecycle management, and preventing issues like volumes being overwritten.
|
||||
volume_manager: Arc<VolumeManager>,
|
||||
}
|
||||
|
||||
impl VolumeResource {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: Arc::new(RwLock::new(VolumeResourceInner::default())),
|
||||
volume_manager: Arc::new(VolumeManager::new()),
|
||||
}
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub async fn handler_volumes(
|
||||
@@ -76,15 +67,10 @@ impl VolumeResource {
|
||||
// handle mounts
|
||||
for m in oci_mounts {
|
||||
let read_only = get_mount_options(m.options()).iter().any(|opt| opt == "ro");
|
||||
let volume: Arc<dyn Volume> = if shm_volume::is_shm_volume(m) {
|
||||
Arc::new(
|
||||
shm_volume::ShmVolume::new(m)
|
||||
.with_context(|| format!("new shm volume {:?}", m))?,
|
||||
)
|
||||
} else if ephemeral_volume::is_ephemeral_volume(m) {
|
||||
let volume: Arc<dyn Volume> = if ephemeral_volume::is_ephemeral_volume(m) {
|
||||
Arc::new(
|
||||
ephemeral_volume::EphemeralVolume::new(m)
|
||||
.with_context(|| format!("new ephemeral volume {:?}", m))?,
|
||||
.with_context(|| format!("new shm volume {:?}", m))?,
|
||||
)
|
||||
} else if is_block_volume(m) {
|
||||
// handle block volume
|
||||
@@ -115,16 +101,9 @@ impl VolumeResource {
|
||||
)
|
||||
} else if share_fs_volume::is_share_fs_volume(m) {
|
||||
Arc::new(
|
||||
share_fs_volume::ShareFsVolume::new(
|
||||
share_fs,
|
||||
m,
|
||||
cid,
|
||||
read_only,
|
||||
agent.clone(),
|
||||
self.volume_manager.clone(),
|
||||
)
|
||||
.await
|
||||
.with_context(|| format!("new share fs volume {:?}", m))?,
|
||||
share_fs_volume::ShareFsVolume::new(share_fs, m, cid, read_only, agent.clone())
|
||||
.await
|
||||
.with_context(|| format!("new share fs volume {:?}", m))?,
|
||||
)
|
||||
} else if is_skip_volume(m) {
|
||||
info!(sl!(), "skip volume {:?}", m);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//
|
||||
|
||||
use std::{
|
||||
collections::{HashMap, HashSet, VecDeque},
|
||||
collections::{HashSet, VecDeque},
|
||||
fs::File,
|
||||
io::Read,
|
||||
os::unix::fs::MetadataExt,
|
||||
@@ -22,7 +22,6 @@ use hypervisor::device::device_manager::DeviceManager;
|
||||
use inotify::{EventMask, Inotify, WatchMask};
|
||||
use kata_sys_util::mount::{get_mount_options, get_mount_path, get_mount_type};
|
||||
use nix::sys::stat::SFlag;
|
||||
use rand::{thread_rng, RngCore};
|
||||
use tokio::{
|
||||
io::AsyncReadExt,
|
||||
sync::{Mutex, RwLock},
|
||||
@@ -44,11 +43,6 @@ const SYS_MOUNT_PREFIX: [&str; 2] = ["/proc", "/sys"];
|
||||
const MONITOR_INTERVAL: Duration = Duration::from_millis(100);
|
||||
const DEBOUNCE_TIME: Duration = Duration::from_millis(500);
|
||||
|
||||
// Corresponds to os.FileMode(0750) | os.ModeDir in Go
|
||||
// So, it's (permission bits 0o750) ORed with (file type bit S_IFDIR).
|
||||
// We use u32 here because `file_mode` in CopyFileRequest is u32
|
||||
const DIR_MODE_PERMS: u32 = SFlag::S_IFDIR.bits() | 0o750;
|
||||
|
||||
// copy file to container's rootfs if filesystem sharing is not supported, otherwise
|
||||
// bind mount it in the shared directory.
|
||||
// Ignore /dev, directories and all other device files. We handle
|
||||
@@ -59,13 +53,7 @@ pub(crate) struct ShareFsVolume {
|
||||
share_fs: Option<Arc<dyn ShareFs>>,
|
||||
mounts: Vec<oci::Mount>,
|
||||
storages: Vec<agent::Storage>,
|
||||
|
||||
// Add volume manager reference
|
||||
volume_manager: Option<Arc<VolumeManager>>,
|
||||
// Record the source path for cleanup
|
||||
source_path: Option<String>,
|
||||
// Record the container ID
|
||||
container_id: String,
|
||||
monitor_task: Option<JoinHandle<()>>,
|
||||
}
|
||||
|
||||
/// Directory Monitor Config
|
||||
@@ -171,28 +159,10 @@ impl FsWatcher {
|
||||
let inotify = self.inotify.clone();
|
||||
let monitor_config = self.config.clone();
|
||||
|
||||
// Perform a full sync before starting monitoring to ensure that files which exist before monitoring starts are also synced.
|
||||
let agent_sync = agent.clone();
|
||||
let src_sync = src.clone();
|
||||
let dst_sync = dst.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut buffer = [0u8; 4096];
|
||||
let mut last_event_time = None;
|
||||
|
||||
// Initial sync: ensure existing contents in the directory are synchronized
|
||||
{
|
||||
info!(
|
||||
sl!(),
|
||||
"Initial sync from {:?} to {:?}", &src_sync, &dst_sync
|
||||
);
|
||||
if let Err(e) =
|
||||
copy_dir_recursively(&src_sync, &dst_sync.to_string_lossy(), &agent_sync).await
|
||||
{
|
||||
error!(sl!(), "Initial sync failed: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
// use cloned inotify instance
|
||||
match inotify.lock().await.read_events(&mut buffer) {
|
||||
@@ -203,8 +173,7 @@ impl FsWatcher {
|
||||
| EventMask::MODIFY
|
||||
| EventMask::DELETE
|
||||
| EventMask::MOVED_FROM
|
||||
| EventMask::MOVED_TO
|
||||
| EventMask::CLOSE_WRITE,
|
||||
| EventMask::MOVED_TO,
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
@@ -256,7 +225,7 @@ impl FsWatcher {
|
||||
if Instant::now().duration_since(t) > DEBOUNCE_TIME && *need_sync.lock().await {
|
||||
info!(sl!(), "debounce handle copyfile {:?} -> {:?}", &src, &dst);
|
||||
if let Err(e) =
|
||||
copy_dir_recursively(&src, &dst.to_string_lossy(), &agent).await
|
||||
copy_dir_recursively(&src, &dst.display().to_string(), &agent).await
|
||||
{
|
||||
error!(
|
||||
sl!(),
|
||||
@@ -278,141 +247,6 @@ impl FsWatcher {
|
||||
}
|
||||
}
|
||||
|
||||
//==========volume manager==============
|
||||
/// Sandbox-level volume state manager
|
||||
/// Tracks which paths have been copied to the guest on the runtime side
|
||||
#[derive(Clone, Default)]
|
||||
pub struct VolumeManager {
|
||||
// Mapping of source path -> volume state
|
||||
volume_states: Arc<RwLock<HashMap<String, VolumeState>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct VolumeState {
|
||||
// Source path (on the host)
|
||||
source_path: String,
|
||||
// Guest path
|
||||
guest_path: String,
|
||||
// Reference count (how many containers are using it)
|
||||
ref_count: usize,
|
||||
// List of container IDs using this volume
|
||||
containers: HashSet<String>,
|
||||
// Monitor task handle (if any)
|
||||
monitor_task: Option<Arc<JoinHandle<()>>>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl VolumeManager {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
volume_states: Arc::new(RwLock::new(HashMap::new())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets or creates the volume's guest path
|
||||
pub async fn get_or_create_volume(
|
||||
&self,
|
||||
canonical_source: &str,
|
||||
container_id: &str,
|
||||
mount_destination: &Path,
|
||||
) -> Result<String> {
|
||||
let mut states = self.volume_states.write().await;
|
||||
|
||||
if let Some(state) = states.get_mut(canonical_source) {
|
||||
// Existing volume and update reference
|
||||
state.ref_count += 1;
|
||||
state.containers.insert(container_id.to_string());
|
||||
|
||||
info!(
|
||||
sl!(),
|
||||
"Existing volume: source={:?}, guest={:?}, ref_count={}",
|
||||
canonical_source,
|
||||
state.guest_path,
|
||||
state.ref_count,
|
||||
);
|
||||
|
||||
// Return guest path
|
||||
return Ok(state.guest_path.clone());
|
||||
}
|
||||
|
||||
// Create a new volume state
|
||||
let guest_path =
|
||||
generate_guest_path(container_id, mount_destination).context("generate path failed")?;
|
||||
|
||||
let mut containers = HashSet::new();
|
||||
containers.insert(container_id.to_string());
|
||||
|
||||
let state = VolumeState {
|
||||
source_path: canonical_source.to_string(),
|
||||
guest_path: guest_path.clone(),
|
||||
ref_count: 1,
|
||||
containers,
|
||||
monitor_task: None,
|
||||
};
|
||||
|
||||
states.insert(state.source_path.clone(), state.clone());
|
||||
|
||||
info!(
|
||||
sl!(),
|
||||
"Created new volume state: source={:?}, guest={:?}",
|
||||
state.source_path,
|
||||
state.guest_path,
|
||||
);
|
||||
|
||||
// Return guest path
|
||||
Ok(guest_path)
|
||||
}
|
||||
|
||||
/// Register monitor task into the volume manager
|
||||
pub async fn register_monitor(
|
||||
&self,
|
||||
canonical_source: &str,
|
||||
monitor_task: Option<JoinHandle<()>>,
|
||||
) -> Result<()> {
|
||||
let mut states = self.volume_states.write().await;
|
||||
|
||||
if let Some(state) = states.get_mut(canonical_source) {
|
||||
if let Some(handle) = monitor_task {
|
||||
state.monitor_task = Some(Arc::new(handle));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Releases a volume reference
|
||||
pub async fn release_volume(&self, source_path: &str, container_id: &str) -> Result<bool> {
|
||||
let mut states = self.volume_states.write().await;
|
||||
|
||||
let canonical_source = std::fs::canonicalize(source_path)
|
||||
.map(|p| p.to_string_lossy().to_string())
|
||||
.unwrap_or_else(|_| source_path.to_string());
|
||||
|
||||
if let Some(state) = states.get_mut(&canonical_source) {
|
||||
state.containers.remove(container_id);
|
||||
state.ref_count = state.ref_count.saturating_sub(1);
|
||||
|
||||
if state.ref_count == 0 {
|
||||
// Abort the monitor task
|
||||
if let Some(handle) = &state.monitor_task {
|
||||
handle.abort();
|
||||
}
|
||||
|
||||
info!(
|
||||
sl!(),
|
||||
"Volume has no more references, source={:?}, guest={:?}",
|
||||
canonical_source,
|
||||
state.guest_path
|
||||
);
|
||||
|
||||
return Ok(true); // Can be cleaned up
|
||||
}
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
impl ShareFsVolume {
|
||||
pub(crate) async fn new(
|
||||
share_fs: &Option<Arc<dyn ShareFs>>,
|
||||
@@ -420,7 +254,6 @@ impl ShareFsVolume {
|
||||
cid: &str,
|
||||
readonly: bool,
|
||||
agent: Arc<dyn Agent>,
|
||||
volume_manager: Arc<VolumeManager>,
|
||||
) -> Result<Self> {
|
||||
// The file_name is in the format of "sandbox-{uuid}-{file_name}"
|
||||
let source_path = get_mount_path(m.source());
|
||||
@@ -435,11 +268,8 @@ impl ShareFsVolume {
|
||||
share_fs: share_fs.as_ref().map(Arc::clone),
|
||||
mounts: vec![],
|
||||
storages: vec![],
|
||||
volume_manager: Some(volume_manager.clone()),
|
||||
source_path: Some(source_path.clone()),
|
||||
container_id: cid.to_string(),
|
||||
monitor_task: None,
|
||||
};
|
||||
|
||||
match share_fs {
|
||||
None => {
|
||||
let src = match std::fs::canonicalize(&source_path) {
|
||||
@@ -452,57 +282,128 @@ impl ShareFsVolume {
|
||||
Ok(src) => src,
|
||||
};
|
||||
|
||||
// append oci::Mount structure to volume mounts
|
||||
let mut oci_mount = oci::Mount::default();
|
||||
oci_mount.set_destination(m.destination().clone());
|
||||
oci_mount.set_typ(Some("bind".to_string()));
|
||||
oci_mount.set_options(m.options().clone());
|
||||
|
||||
// If the mount source is a file, we can copy it to the sandbox
|
||||
if src.is_file() {
|
||||
// Generate guest path
|
||||
let guest_path = generate_guest_path(cid, m.destination())
|
||||
.context("generate path failed")?;
|
||||
// Copy a single file
|
||||
Self::copy_file_to_guest(&src, &guest_path, &agent)
|
||||
.await
|
||||
.context("copy file to guest")?;
|
||||
// This is where we set the value for the guest path
|
||||
let dest = [KATA_GUEST_SHARE_DIR, file_name.clone().as_str()].join("/");
|
||||
|
||||
oci_mount.set_source(Some(PathBuf::from(&guest_path)));
|
||||
debug!(
|
||||
sl!(),
|
||||
"copy local file {:?} to guest {:?}",
|
||||
&source_path,
|
||||
dest.clone()
|
||||
);
|
||||
|
||||
// Read file metadata
|
||||
let file_metadata = std::fs::metadata(src.clone())
|
||||
.with_context(|| format!("Failed to read metadata from file: {:?}", src))?;
|
||||
|
||||
// Open file
|
||||
let mut file = File::open(&src)
|
||||
.with_context(|| format!("Failed to open file: {:?}", src))?;
|
||||
|
||||
// Open read file contents to buffer
|
||||
let mut buffer = Vec::new();
|
||||
file.read_to_end(&mut buffer)
|
||||
.with_context(|| format!("Failed to read file: {:?}", src))?;
|
||||
|
||||
// Create gRPC request
|
||||
let r = agent::CopyFileRequest {
|
||||
path: dest.clone(),
|
||||
file_size: file_metadata.len() as i64,
|
||||
uid: file_metadata.uid() as i32,
|
||||
gid: file_metadata.gid() as i32,
|
||||
file_mode: file_metadata.mode(),
|
||||
data: buffer,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
debug!(sl!(), "copy_file: {:?} to sandbox {:?}", &src, dest.clone());
|
||||
|
||||
// Issue gRPC request to agent
|
||||
agent.copy_file(r).await.with_context(|| {
|
||||
format!(
|
||||
"copy file request failed: src: {:?}, dest: {:?}",
|
||||
file_name, dest
|
||||
)
|
||||
})?;
|
||||
|
||||
// append oci::Mount structure to volume mounts
|
||||
let mut oci_mount = oci::Mount::default();
|
||||
oci_mount.set_destination(m.destination().clone());
|
||||
oci_mount.set_typ(Some("bind".to_string()));
|
||||
oci_mount.set_source(Some(PathBuf::from(&dest)));
|
||||
oci_mount.set_options(m.options().clone());
|
||||
volume.mounts.push(oci_mount);
|
||||
} else if src.is_dir() {
|
||||
// We allow directory copying wildly
|
||||
// source path: "/var/lib/kubelet/pods/6dad7281-57ff-49e4-b844-c588ceabec16/volumes/kubernetes.io~projected/kube-api-access-8s2nl"
|
||||
info!(sl!(), "copying directory {:?} to guest", &src);
|
||||
// source_path: "/var/lib/kubelet/pods/6dad7281-57ff-49e4-b844-c588ceabec16/volumes/kubernetes.io~projected/kube-api-access-8s2nl"
|
||||
info!(sl!(), "copying directory {:?} to guest", &source_path);
|
||||
|
||||
// Get or create the guest path
|
||||
let guest_path = volume_manager
|
||||
.get_or_create_volume(&src.to_string_lossy(), cid, m.destination())
|
||||
// create target path in guest
|
||||
let dest_dir = [KATA_GUEST_SHARE_DIR, file_name.clone().as_str()].join("/");
|
||||
|
||||
// create directory
|
||||
let dir_metadata = std::fs::metadata(src.clone())
|
||||
.context(format!("read metadata from directory: {:?}", src))?;
|
||||
|
||||
// ttRPC request for creating directory
|
||||
let dir_request = agent::CopyFileRequest {
|
||||
path: dest_dir.clone(),
|
||||
file_size: 0, // useless for dir
|
||||
uid: dir_metadata.uid() as i32,
|
||||
gid: dir_metadata.gid() as i32,
|
||||
dir_mode: dir_metadata.mode(),
|
||||
file_mode: SFlag::S_IFDIR.bits(),
|
||||
data: vec![], // no files
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// dest_dir: "/run/kata-containers/sandbox/passthrough/sandbox-b2790ec0-kube-api-access-8s2nl"
|
||||
info!(
|
||||
sl!(),
|
||||
"creating directory: {:?} in sandbox with file_mode: {:?}",
|
||||
dest_dir,
|
||||
dir_request.file_mode
|
||||
);
|
||||
|
||||
// send request for creating directory
|
||||
agent
|
||||
.copy_file(dir_request)
|
||||
.await
|
||||
.context("get or create volume")?;
|
||||
.context(format!("create directory in sandbox: {:?}", dest_dir))?;
|
||||
|
||||
// Create directory
|
||||
Self::copy_directory_to_guest(&src, &guest_path, &agent)
|
||||
// recursively copy files from this directory
|
||||
// similar to `scp -r $source_dir $target_dir`
|
||||
copy_dir_recursively(src.clone(), &dest_dir, &agent)
|
||||
.await
|
||||
.context("copy directory to guest")?;
|
||||
.context(format!("failed to copy directory contents: {:?}", src))?;
|
||||
|
||||
oci_mount.set_source(Some(PathBuf::from(&guest_path)));
|
||||
volume.mounts.push(oci_mount);
|
||||
|
||||
// Start monitoring (only for watchable volumes)
|
||||
let mut monitor_task = None;
|
||||
if is_watchable_volume(&src) {
|
||||
let watcher = FsWatcher::new(&src).await?;
|
||||
let handle = watcher
|
||||
.start_monitor(agent.clone(), src.clone(), PathBuf::from(&guest_path))
|
||||
.await;
|
||||
monitor_task = Some(handle);
|
||||
// handle special mount options
|
||||
let mut options = m.options().clone().unwrap_or_default();
|
||||
if !options.iter().any(|x| x == "rbind") {
|
||||
options.push("rbind".into());
|
||||
}
|
||||
if !options.iter().any(|x| x == "rprivate") {
|
||||
options.push("rprivate".into());
|
||||
}
|
||||
|
||||
// Register monitor into Volume Manager
|
||||
volume_manager
|
||||
.register_monitor(&src.to_string_lossy(), monitor_task)
|
||||
.await?;
|
||||
// add OCI Mount
|
||||
let mut oci_mount = oci::Mount::default();
|
||||
oci_mount.set_destination(m.destination().clone());
|
||||
oci_mount.set_typ(Some("bind".to_string()));
|
||||
oci_mount.set_source(Some(PathBuf::from(&dest_dir)));
|
||||
oci_mount.set_options(Some(options));
|
||||
volume.mounts.push(oci_mount);
|
||||
|
||||
// start monitoring
|
||||
if is_watchable_volume(&src) {
|
||||
let watcher = FsWatcher::new(Path::new(&source_path)).await?;
|
||||
let monitor_task = watcher
|
||||
.start_monitor(agent.clone(), src.clone(), dest_dir.into())
|
||||
.await;
|
||||
volume.monitor_task = Some(monitor_task);
|
||||
}
|
||||
} else {
|
||||
// If not, we can ignore it. Let's issue a warning so that the user knows.
|
||||
warn!(
|
||||
@@ -590,90 +491,6 @@ impl ShareFsVolume {
|
||||
}
|
||||
Ok(volume)
|
||||
}
|
||||
|
||||
async fn copy_file_to_guest(
|
||||
src: &Path,
|
||||
guest_path: &str,
|
||||
agent: &Arc<dyn Agent>,
|
||||
) -> Result<()> {
|
||||
// Read file metadata
|
||||
let file_metadata = std::fs::metadata(src)
|
||||
.with_context(|| format!("Failed to read metadata from file: {:?}", src))?;
|
||||
|
||||
// Open file
|
||||
let mut file =
|
||||
File::open(src).with_context(|| format!("Failed to open file: {:?}", src))?;
|
||||
|
||||
// Open read file contents to buffer
|
||||
let mut buffer = Vec::new();
|
||||
file.read_to_end(&mut buffer)
|
||||
.with_context(|| format!("Failed to read file: {:?}", src))?;
|
||||
|
||||
// Create gRPC request
|
||||
let r = agent::CopyFileRequest {
|
||||
path: guest_path.to_owned(),
|
||||
file_size: file_metadata.len() as i64,
|
||||
uid: file_metadata.uid() as i32,
|
||||
gid: file_metadata.gid() as i32,
|
||||
file_mode: file_metadata.mode(),
|
||||
data: buffer,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
debug!(sl!(), "copy_file: {:?} to sandbox {:?}", &src, guest_path);
|
||||
|
||||
// Issue gRPC request to agent
|
||||
agent.copy_file(r).await.with_context(|| {
|
||||
format!(
|
||||
"copy file request failed: src: {:?}, dest: {:?}",
|
||||
src, guest_path
|
||||
)
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn copy_directory_to_guest(
|
||||
src: &Path,
|
||||
guest_path: &str,
|
||||
agent: &Arc<dyn Agent>,
|
||||
) -> Result<()> {
|
||||
// create directory
|
||||
let dir_metadata =
|
||||
std::fs::metadata(src).context(format!("read metadata from directory: {:?}", src))?;
|
||||
|
||||
// ttRPC request for creating directory
|
||||
let dir_request = agent::CopyFileRequest {
|
||||
path: guest_path.to_owned(),
|
||||
file_size: 0, // useless for dir
|
||||
uid: dir_metadata.uid() as i32,
|
||||
gid: dir_metadata.gid() as i32,
|
||||
dir_mode: DIR_MODE_PERMS,
|
||||
file_mode: dir_metadata.mode(),
|
||||
data: vec![], // no files
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
info!(
|
||||
sl!(),
|
||||
"creating directory: {:?} in sandbox with file_mode: {:?}",
|
||||
guest_path,
|
||||
dir_request.file_mode
|
||||
);
|
||||
|
||||
// send request for creating directory
|
||||
agent
|
||||
.copy_file(dir_request)
|
||||
.await
|
||||
.context(format!("create directory in sandbox: {:?}", guest_path))?;
|
||||
|
||||
// recursively copy files from this directory
|
||||
// similar to `scp -r $source_dir $target_dir`
|
||||
copy_dir_recursively(src, guest_path, agent)
|
||||
.await
|
||||
.context(format!("failed to copy directory contents: {:?}", src))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@@ -689,26 +506,7 @@ impl Volume for ShareFsVolume {
|
||||
async fn cleanup(&self, _device_manager: &RwLock<DeviceManager>) -> Result<()> {
|
||||
let share_fs = match self.share_fs.as_ref() {
|
||||
Some(fs) => fs,
|
||||
None => {
|
||||
return {
|
||||
// Release volume reference
|
||||
if let (Some(manager), Some(source)) = (&self.volume_manager, &self.source_path)
|
||||
{
|
||||
let should_cleanup =
|
||||
manager.release_volume(source, &self.container_id).await?;
|
||||
|
||||
if should_cleanup {
|
||||
info!(
|
||||
sl!(),
|
||||
"Volume {:?} has no more references, can be cleaned up", source
|
||||
);
|
||||
// NOTE: We cannot delete files from the guest because there is no corresponding API
|
||||
// Files will be cleaned up automatically when the sandbox is destroyed
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
}
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let mounted_info_set = share_fs.mounted_info_set();
|
||||
@@ -974,24 +772,6 @@ pub(crate) fn is_watchable_volume(source_path: &PathBuf) -> bool {
|
||||
|| is_configmap(source_path)
|
||||
}
|
||||
|
||||
/// Generates a guest path related to mount dest
|
||||
fn generate_guest_path(cid: &str, mount_destination: &Path) -> Result<String> {
|
||||
let mut data = vec![0u8; 8];
|
||||
let mut rng = thread_rng(); // Get a thread-local RNG
|
||||
rng.fill_bytes(&mut data);
|
||||
|
||||
let hex_str = hex::encode(data);
|
||||
let dest_base = mount_destination
|
||||
.file_name()
|
||||
.and_then(|n| n.to_str())
|
||||
.ok_or_else(|| anyhow!("get mount destination failed"))?;
|
||||
|
||||
Ok(format!(
|
||||
"{}{}-{}-{}",
|
||||
KATA_GUEST_SHARE_DIR, cid, hex_str, dest_base
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
// Copyright (c) 2019-2022 Alibaba Cloud
|
||||
// Copyright (c) 2019-2022 Ant Group
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::Volume;
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use hypervisor::device::device_manager::DeviceManager;
|
||||
use kata_sys_util::mount::{get_mount_path, get_mount_type};
|
||||
use kata_types::mount::{
|
||||
DEFAULT_KATA_GUEST_SANDBOX_DIR, KATA_EPHEMERAL_VOLUME_TYPE, SHM_DEVICE, SHM_DIR,
|
||||
};
|
||||
use oci_spec::runtime as oci;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct ShmVolume {
|
||||
mount: oci::Mount,
|
||||
}
|
||||
|
||||
impl ShmVolume {
|
||||
pub(crate) fn new(m: &oci::Mount) -> Result<Self> {
|
||||
let mut mount = oci::Mount::default();
|
||||
mount.set_destination(m.destination().clone());
|
||||
mount.set_typ(Some("bind".to_string()));
|
||||
mount.set_source(Some(
|
||||
PathBuf::from(DEFAULT_KATA_GUEST_SANDBOX_DIR).join(SHM_DIR),
|
||||
));
|
||||
mount.set_options(Some(vec!["rbind".to_string()]));
|
||||
|
||||
Ok(Self { mount })
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Volume for ShmVolume {
|
||||
fn get_volume_mount(&self) -> anyhow::Result<Vec<oci::Mount>> {
|
||||
Ok(vec![self.mount.clone()])
|
||||
}
|
||||
|
||||
fn get_storage(&self) -> Result<Vec<agent::Storage>> {
|
||||
Ok(vec![])
|
||||
}
|
||||
|
||||
async fn cleanup(&self, _device_manager: &RwLock<DeviceManager>) -> Result<()> {
|
||||
// No cleanup is required for ShmVolume because it is a mount in guest which
|
||||
// does not require explicit unmounting or deletion in host side.
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_device_id(&self) -> Result<Option<String>> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_shm_volume(m: &oci::Mount) -> bool {
|
||||
get_mount_path(&Some(m.destination().clone())).as_str() == SHM_DEVICE
|
||||
&& get_mount_type(m).as_str() != KATA_EPHEMERAL_VOLUME_TYPE
|
||||
}
|
||||
@@ -23,10 +23,6 @@ use kata_types::mount::Mount;
|
||||
use oci_spec::runtime as oci;
|
||||
use strum::Display;
|
||||
|
||||
// DEFAULT_SHM_SIZE is the default shm size to be used in case host
|
||||
// IPC is used.
|
||||
pub const DEFAULT_SHM_SIZE: u64 = 65536 * 1024;
|
||||
|
||||
/// TaskRequest: TaskRequest from shim
|
||||
/// TaskRequest and TaskResponse messages need to be paired
|
||||
#[derive(Debug, Clone, Display)]
|
||||
@@ -180,7 +176,6 @@ pub struct SandboxConfig {
|
||||
pub annotations: HashMap<String, String, RandomState>,
|
||||
pub hooks: Option<oci::Hooks>,
|
||||
pub state: runtime_spec::State,
|
||||
pub shm_size: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
||||
@@ -8,7 +8,6 @@ use super::{
|
||||
ContainerConfig, ContainerID, ContainerProcess, ExecProcessRequest, KillRequest,
|
||||
ResizePTYRequest, SandboxConfig, SandboxID, SandboxNetworkEnv, SandboxRequest,
|
||||
SandboxStatusRequest, ShutdownRequest, StopSandboxRequest, TaskRequest, UpdateRequest,
|
||||
DEFAULT_SHM_SIZE,
|
||||
};
|
||||
|
||||
use kata_types::mount::Mount;
|
||||
@@ -85,7 +84,6 @@ impl TryFrom<sandbox_api::CreateSandboxRequest> for SandboxRequest {
|
||||
bundle: from.bundle_path,
|
||||
annotations: config.annotations,
|
||||
},
|
||||
shm_size: DEFAULT_SHM_SIZE,
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use common::{
|
||||
message::Message,
|
||||
types::{
|
||||
ContainerProcess, PlatformInfo, SandboxConfig, SandboxRequest, SandboxResponse,
|
||||
SandboxStatusInfo, StartSandboxInfo, TaskRequest, TaskResponse, DEFAULT_SHM_SIZE,
|
||||
SandboxStatusInfo, StartSandboxInfo, TaskRequest, TaskResponse,
|
||||
},
|
||||
RuntimeHandler, RuntimeInstance, Sandbox, SandboxNetworkEnv,
|
||||
};
|
||||
@@ -17,15 +17,12 @@ use common::{
|
||||
use hypervisor::Param;
|
||||
use kata_sys_util::{mount::get_mount_path, spec::load_oci_spec};
|
||||
use kata_types::{
|
||||
annotations::Annotation,
|
||||
config::{default::DEFAULT_GUEST_DNS_FILE, TomlConfig},
|
||||
mount::SHM_DEVICE,
|
||||
annotations::Annotation, config::default::DEFAULT_GUEST_DNS_FILE, config::TomlConfig,
|
||||
};
|
||||
#[cfg(feature = "linux")]
|
||||
use linux_container::LinuxContainer;
|
||||
use logging::FILTER_RULE;
|
||||
use netns_rs::NetNs;
|
||||
use nix::sys::statfs;
|
||||
use oci_spec::runtime as oci;
|
||||
use persist::sandbox_persist::Persist;
|
||||
use resource::{
|
||||
@@ -307,7 +304,7 @@ impl RuntimeHandlerManager {
|
||||
#[instrument]
|
||||
async fn task_init_runtime_instance(
|
||||
&self,
|
||||
spec: &mut oci::Spec,
|
||||
spec: &oci::Spec,
|
||||
state: &spec::State,
|
||||
options: &Option<Vec<u8>>,
|
||||
) -> Result<()> {
|
||||
@@ -353,20 +350,11 @@ impl RuntimeHandlerManager {
|
||||
}
|
||||
}
|
||||
|
||||
// A nerdctl network namespace to let nerdctl know which namespace to use when calling the
|
||||
// selected CNI plugin.
|
||||
spec.annotations_mut().as_mut().unwrap().insert(
|
||||
"nerdctl/network-namespace".to_string(),
|
||||
netns.clone().unwrap(),
|
||||
);
|
||||
|
||||
let network_env = SandboxNetworkEnv {
|
||||
netns,
|
||||
network_created,
|
||||
};
|
||||
|
||||
let shm_size = get_shm_size(spec)?;
|
||||
|
||||
let sandbox_config = SandboxConfig {
|
||||
sandbox_id: inner.id.clone(),
|
||||
dns,
|
||||
@@ -375,7 +363,6 @@ impl RuntimeHandlerManager {
|
||||
annotations: spec.annotations().clone().unwrap_or_default(),
|
||||
hooks: spec.hooks().clone(),
|
||||
state: state.clone(),
|
||||
shm_size,
|
||||
};
|
||||
|
||||
inner.try_init(sandbox_config, Some(spec), options).await
|
||||
@@ -418,7 +405,7 @@ impl RuntimeHandlerManager {
|
||||
container_config.bundle,
|
||||
spec::OCI_SPEC_CONFIG_FILE_NAME
|
||||
);
|
||||
let mut spec = oci::Spec::load(&bundler_path).context("load spec")?;
|
||||
let spec = oci::Spec::load(&bundler_path).context("load spec")?;
|
||||
let state = spec::State {
|
||||
version: spec.version().clone(),
|
||||
id: container_config.container_id.to_string(),
|
||||
@@ -428,7 +415,7 @@ impl RuntimeHandlerManager {
|
||||
annotations: spec.annotations().clone().unwrap_or_default(),
|
||||
};
|
||||
|
||||
self.task_init_runtime_instance(&mut spec, &state, &container_config.options)
|
||||
self.task_init_runtime_instance(&spec, &state, &container_config.options)
|
||||
.await
|
||||
.context("try init runtime instance")?;
|
||||
let instance = self
|
||||
@@ -727,26 +714,3 @@ fn update_component_log_level(config: &TomlConfig) {
|
||||
updated_inner
|
||||
});
|
||||
}
|
||||
|
||||
fn get_shm_size(spec: &oci::Spec) -> Result<u64> {
|
||||
let mut shm_size = DEFAULT_SHM_SIZE;
|
||||
|
||||
if let Some(mounts) = spec.mounts() {
|
||||
for m in mounts {
|
||||
if m.destination().as_path() != Path::new(SHM_DEVICE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if m.typ().eq(&Some("bind".to_string()))
|
||||
&& !m.source().eq(&Some(PathBuf::from(SHM_DEVICE)))
|
||||
{
|
||||
if let Some(src) = m.source() {
|
||||
let statfs = statfs::statfs(src)?;
|
||||
shm_size = statfs.blocks() * statfs.block_size() as u64;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(shm_size)
|
||||
}
|
||||
|
||||
@@ -17,11 +17,7 @@ use common::{
|
||||
},
|
||||
};
|
||||
use kata_sys_util::k8s::update_ephemeral_storage_type;
|
||||
use kata_types::{
|
||||
annotations::{BUNDLE_PATH_KEY, CONTAINER_TYPE_KEY},
|
||||
container::{update_ocispec_annotations, POD_CONTAINER, POD_SANDBOX},
|
||||
k8s::{self, container_type},
|
||||
};
|
||||
use kata_types::k8s;
|
||||
use oci_spec::runtime::{self as oci, LinuxDeviceCgroup};
|
||||
|
||||
use oci::{LinuxResources, Process as OCIProcess};
|
||||
@@ -115,17 +111,6 @@ impl Container {
|
||||
None => true,
|
||||
};
|
||||
let annotations = spec.annotations().clone().unwrap_or_default();
|
||||
let container_typ = container_type(&spec);
|
||||
let pod_type_anno = if container_typ.is_pod_container() {
|
||||
(CONTAINER_TYPE_KEY.to_string(), POD_CONTAINER.to_string())
|
||||
} else {
|
||||
(CONTAINER_TYPE_KEY.to_string(), POD_SANDBOX.to_string())
|
||||
};
|
||||
|
||||
let bund_path_anno = (BUNDLE_PATH_KEY.to_string(), config.bundle.clone());
|
||||
let updated_annotations =
|
||||
update_ocispec_annotations(&annotations, &[], &[pod_type_anno, bund_path_anno]);
|
||||
spec.set_annotations(Some(updated_annotations.clone()));
|
||||
|
||||
amend_spec(
|
||||
&mut spec,
|
||||
|
||||
@@ -12,18 +12,16 @@ use agent::{
|
||||
};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use common::message::{Action, Message};
|
||||
use common::types::utils::option_system_time_into;
|
||||
use common::types::ContainerProcess;
|
||||
use common::{
|
||||
message::{Action, Message},
|
||||
types::DEFAULT_SHM_SIZE,
|
||||
};
|
||||
use common::{
|
||||
types::{SandboxConfig, SandboxExitInfo, SandboxStatus},
|
||||
ContainerManager, Sandbox, SandboxNetworkEnv,
|
||||
};
|
||||
|
||||
use containerd_shim_protos::events::task::{TaskExit, TaskOOM};
|
||||
use hypervisor::PortDeviceConfig;
|
||||
use hypervisor::VsockConfig;
|
||||
use hypervisor::HYPERVISOR_FIRECRACKER;
|
||||
use hypervisor::HYPERVISOR_REMOTE;
|
||||
@@ -32,11 +30,9 @@ use hypervisor::{dragonball::Dragonball, HYPERVISOR_DRAGONBALL};
|
||||
use hypervisor::{qemu::Qemu, HYPERVISOR_QEMU};
|
||||
use hypervisor::{utils::get_hvsock_path, HybridVsockConfig, DEFAULT_GUEST_VSOCK_CID};
|
||||
use hypervisor::{BlockConfig, Hypervisor};
|
||||
use hypervisor::{BlockDeviceAio, PortDeviceConfig};
|
||||
use hypervisor::{ProtectionDeviceConfig, SevSnpConfig, TdxConfig};
|
||||
use kata_sys_util::hooks::HookStates;
|
||||
use kata_sys_util::protection::{available_guest_protection, GuestProtection};
|
||||
use kata_sys_util::spec::load_oci_spec;
|
||||
use kata_types::capabilities::CapabilityBits;
|
||||
use kata_types::config::hypervisor::Hypervisor as HypervisorConfig;
|
||||
use kata_types::config::hypervisor::HYPERVISOR_NAME_CH;
|
||||
@@ -96,7 +92,6 @@ pub struct VirtSandbox {
|
||||
hypervisor: Arc<dyn Hypervisor>,
|
||||
monitor: Arc<HealthCheck>,
|
||||
sandbox_config: Option<SandboxConfig>,
|
||||
shm_size: u64,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for VirtSandbox {
|
||||
@@ -127,7 +122,6 @@ impl VirtSandbox {
|
||||
hypervisor,
|
||||
resource_manager,
|
||||
monitor: Arc::new(HealthCheck::new(true, keep_abnormal)),
|
||||
shm_size: sandbox_config.shm_size,
|
||||
sandbox_config: Some(sandbox_config),
|
||||
})
|
||||
}
|
||||
@@ -481,7 +475,6 @@ impl VirtSandbox {
|
||||
path_on_host: image_path.display().to_string(),
|
||||
is_readonly: true,
|
||||
driver_option: block_driver.clone(),
|
||||
blkdev_aio: BlockDeviceAio::Native,
|
||||
..Default::default()
|
||||
};
|
||||
let initdata_config = InitDataConfig(block_config, initdata_digest);
|
||||
@@ -518,18 +511,12 @@ impl Sandbox for VirtSandbox {
|
||||
warn!(sl!(), "sandbox is started");
|
||||
return Ok(());
|
||||
}
|
||||
let selinux_label = load_oci_spec().ok().and_then(|spec| {
|
||||
spec.process()
|
||||
.as_ref()
|
||||
.and_then(|process| process.selinux_label().clone())
|
||||
});
|
||||
|
||||
self.hypervisor
|
||||
.prepare_vm(
|
||||
id,
|
||||
sandbox_config.network_env.netns.clone(),
|
||||
&sandbox_config.annotations,
|
||||
selinux_label,
|
||||
)
|
||||
.await
|
||||
.context("prepare vm")?;
|
||||
@@ -620,7 +607,7 @@ impl Sandbox for VirtSandbox {
|
||||
dns: sandbox_config.dns.clone(),
|
||||
storages: self
|
||||
.resource_manager
|
||||
.get_storage_for_sandbox(self.shm_size)
|
||||
.get_storage_for_sandbox()
|
||||
.await
|
||||
.context("get storages for sandbox")?,
|
||||
sandbox_pidns: false,
|
||||
@@ -936,7 +923,6 @@ impl Persist for VirtSandbox {
|
||||
resource_manager,
|
||||
monitor: Arc::new(HealthCheck::new(true, keep_abnormal)),
|
||||
sandbox_config: None,
|
||||
shm_size: DEFAULT_SHM_SIZE,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ var destroyFactoryCommand = cli.Command{
|
||||
}
|
||||
|
||||
if runtimeConfig.FactoryConfig.VMCacheNumber > 0 {
|
||||
conn, err := grpc.NewClient(fmt.Sprintf("unix://%s", runtimeConfig.FactoryConfig.VMCacheEndpoint), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
conn, err := grpc.Dial(fmt.Sprintf("unix://%s", runtimeConfig.FactoryConfig.VMCacheEndpoint), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to connect %q", runtimeConfig.FactoryConfig.VMCacheEndpoint)
|
||||
}
|
||||
@@ -287,7 +287,7 @@ var statusFactoryCommand = cli.Command{
|
||||
}
|
||||
|
||||
if runtimeConfig.FactoryConfig.VMCacheNumber > 0 {
|
||||
conn, err := grpc.NewClient(fmt.Sprintf("unix://%s", runtimeConfig.FactoryConfig.VMCacheEndpoint), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
conn, err := grpc.Dial(fmt.Sprintf("unix://%s", runtimeConfig.FactoryConfig.VMCacheEndpoint), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
fmt.Fprintln(defaultOutputFile, errors.Wrapf(err, "failed to connect %q", runtimeConfig.FactoryConfig.VMCacheEndpoint))
|
||||
} else {
|
||||
|
||||
@@ -52,7 +52,7 @@ sev_snp_guest = true
|
||||
# List of valid annotation names for the hypervisor
|
||||
# Each member of the list is a regular expression, which is the base name
|
||||
# of the annotation, e.g. "path" for io.katacontainers.config.hypervisor.path"
|
||||
enable_annotations = @DEFENABLEANNOTATIONS_COCO@
|
||||
enable_annotations = @DEFENABLEANNOTATIONS@
|
||||
|
||||
# List of valid annotations values for the hypervisor
|
||||
# Each member of the list is a path pattern as described by glob(3).
|
||||
|
||||
@@ -8,137 +8,136 @@ go 1.24.6
|
||||
|
||||
require (
|
||||
code.cloudfoundry.org/bytefmt v0.0.0-20211005130812-5bb3c17173e5
|
||||
github.com/BurntSushi/toml v1.5.0
|
||||
github.com/BurntSushi/toml v1.3.2
|
||||
github.com/blang/semver v3.5.1+incompatible
|
||||
github.com/blang/semver/v4 v4.0.0
|
||||
github.com/container-orchestrated-devices/container-device-interface v0.6.0
|
||||
github.com/containerd/cgroups v1.1.0
|
||||
github.com/containerd/console v1.0.4
|
||||
github.com/containerd/containerd v1.7.27
|
||||
github.com/containerd/containerd/api v1.9.0
|
||||
github.com/containerd/containerd/api v1.8.0
|
||||
github.com/containerd/cri-containerd v1.19.0
|
||||
github.com/containerd/fifo v1.1.0
|
||||
github.com/containerd/ttrpc v1.2.7
|
||||
github.com/containerd/typeurl/v2 v2.2.3
|
||||
github.com/containernetworking/plugins v1.7.1
|
||||
github.com/containerd/typeurl/v2 v2.1.1
|
||||
github.com/containernetworking/plugins v1.4.1
|
||||
github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09
|
||||
github.com/cri-o/cri-o v1.34.0
|
||||
github.com/cri-o/cri-o v1.30.10
|
||||
github.com/docker/go-units v0.5.0
|
||||
github.com/fsnotify/fsnotify v1.9.0
|
||||
github.com/go-ini/ini v1.67.0
|
||||
github.com/go-openapi/errors v0.22.1
|
||||
github.com/go-openapi/runtime v0.28.0
|
||||
github.com/go-openapi/strfmt v0.23.0
|
||||
github.com/go-openapi/swag v0.23.1
|
||||
github.com/go-openapi/validate v0.24.0
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/go-ini/ini v1.28.2
|
||||
github.com/go-openapi/errors v0.20.4
|
||||
github.com/go-openapi/runtime v0.26.0
|
||||
github.com/go-openapi/strfmt v0.21.8
|
||||
github.com/go-openapi/swag v0.22.4
|
||||
github.com/go-openapi/validate v0.22.3
|
||||
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/intel-go/cpuid v0.0.0-20210602155658-5747e5cec0d9
|
||||
github.com/mdlayher/vsock v1.2.1
|
||||
github.com/moby/sys/userns v0.1.0
|
||||
github.com/opencontainers/runc v1.2.6
|
||||
github.com/opencontainers/runtime-spec v1.2.1
|
||||
github.com/opencontainers/selinux v1.12.0
|
||||
github.com/opencontainers/runc v1.2.0
|
||||
github.com/opencontainers/runtime-spec v1.2.0
|
||||
github.com/opencontainers/selinux v1.11.0
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.22.0
|
||||
github.com/prometheus/client_model v0.6.1
|
||||
github.com/prometheus/common v0.62.0
|
||||
github.com/prometheus/procfs v0.15.1
|
||||
github.com/safchain/ethtool v0.5.10
|
||||
github.com/prometheus/client_golang v1.18.0
|
||||
github.com/prometheus/client_model v0.5.0
|
||||
github.com/prometheus/common v0.45.0
|
||||
github.com/prometheus/procfs v0.12.0
|
||||
github.com/safchain/ethtool v0.3.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/urfave/cli v1.22.15
|
||||
github.com/vishvananda/netlink v1.3.1-0.20250303224720-0e7078ed04c8
|
||||
github.com/vishvananda/netns v0.0.5
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/urfave/cli v1.22.14
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2
|
||||
github.com/vishvananda/netns v0.0.4
|
||||
gitlab.com/nvidia/cloud-native/go-nvlib v0.0.0-20220601114329-47893b162965
|
||||
go.opentelemetry.io/otel v1.35.0
|
||||
go.opentelemetry.io/otel v1.23.1
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.0.0
|
||||
go.opentelemetry.io/otel/sdk v1.35.0
|
||||
go.opentelemetry.io/otel/trace v1.35.0
|
||||
golang.org/x/oauth2 v0.29.0
|
||||
golang.org/x/sys v0.33.0
|
||||
google.golang.org/grpc v1.72.0
|
||||
google.golang.org/protobuf v1.36.6
|
||||
k8s.io/apimachinery v0.33.0
|
||||
k8s.io/cri-api v0.33.0
|
||||
go.opentelemetry.io/otel/sdk v1.23.1
|
||||
go.opentelemetry.io/otel/trace v1.23.1
|
||||
golang.org/x/oauth2 v0.27.0
|
||||
golang.org/x/sys v0.31.0
|
||||
google.golang.org/grpc v1.62.0
|
||||
google.golang.org/protobuf v1.35.2
|
||||
k8s.io/apimachinery v0.30.0
|
||||
k8s.io/cri-api v0.30.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
|
||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/Microsoft/hcsshim v0.12.9 // indirect
|
||||
github.com/Microsoft/hcsshim v0.12.0 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cilium/ebpf v0.16.0 // indirect
|
||||
github.com/containerd/cgroups/v3 v3.0.5 // indirect
|
||||
github.com/containerd/cgroups/v3 v3.0.2 // indirect
|
||||
github.com/containerd/continuity v0.4.4 // indirect
|
||||
github.com/containerd/errdefs v1.0.0 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
github.com/containerd/errdefs v0.3.0 // indirect
|
||||
github.com/containerd/go-runc v1.1.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/platforms v0.2.1 // indirect
|
||||
github.com/containernetworking/cni v1.3.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
|
||||
github.com/containernetworking/cni v1.1.2 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.3.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.3 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/analysis v0.23.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/loads v0.22.0 // indirect
|
||||
github.com/go-openapi/spec v0.21.0 // indirect
|
||||
github.com/go-openapi/analysis v0.21.4 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/loads v0.21.2 // indirect
|
||||
github.com/go-openapi/spec v0.20.11 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/intel/goresctrl v0.8.0 // indirect
|
||||
github.com/intel/goresctrl v0.6.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/mdlayher/socket v0.5.1 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
|
||||
github.com/mdlayher/socket v0.4.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.2 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.1 // indirect
|
||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||
github.com/moby/sys/signal v0.7.0 // indirect
|
||||
github.com/moby/sys/symlink v0.2.0 // indirect
|
||||
github.com/moby/sys/user v0.4.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/moby/sys/user v0.3.0 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20250303011046-260e151b8552 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20230914150019-408c51e934dc // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/smartystreets/goconvey v1.8.1 // indirect
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
||||
go.mongodb.org/mongo-driver v1.12.1 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/sync v0.14.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.23.1 // indirect
|
||||
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/net v0.38.0 // indirect
|
||||
golang.org/x/sync v0.12.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
tags.cncf.io/container-device-interface v1.0.1 // indirect
|
||||
tags.cncf.io/container-device-interface/specs-go v1.0.0 // indirect
|
||||
tags.cncf.io/container-device-interface v0.8.1 // indirect
|
||||
tags.cncf.io/container-device-interface/specs-go v0.8.0 // indirect
|
||||
)
|
||||
|
||||
// WARNING: Do NOT use `replace` directives as those break dependabot:
|
||||
|
||||
@@ -6,13 +6,13 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h
|
||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 h1:59MxjQVfjXsBpLy+dbd2/ELV5ofnUkUZBvWSC85sheA=
|
||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg=
|
||||
github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y=
|
||||
github.com/Microsoft/hcsshim v0.12.0 h1:rbICA+XZFwrBef2Odk++0LjFvClNCJGRK+fsrP254Ts=
|
||||
github.com/Microsoft/hcsshim v0.12.0/go.mod h1:RZV12pcHCXQ42XnlQ3pz6FZfmrC1C+R4gaOHhRNML1g=
|
||||
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
@@ -22,8 +22,11 @@ github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok=
|
||||
github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
@@ -32,22 +35,20 @@ github.com/container-orchestrated-devices/container-device-interface v0.6.0 h1:a
|
||||
github.com/container-orchestrated-devices/container-device-interface v0.6.0/go.mod h1:OQlgtJtDrOxSQ1BWODC8OZK1tzi9W69wek+Jy17ndzo=
|
||||
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
||||
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
|
||||
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
|
||||
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
|
||||
github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0=
|
||||
github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE=
|
||||
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
|
||||
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
||||
github.com/containerd/containerd v1.7.27 h1:yFyEyojddO3MIGVER2xJLWoCIn+Up4GaHFquP7hsFII=
|
||||
github.com/containerd/containerd v1.7.27/go.mod h1:xZmPnl75Vc+BLGt4MIfu6bp+fy03gdHAn9bz+FreFR0=
|
||||
github.com/containerd/containerd/api v1.9.0 h1:HZ/licowTRazus+wt9fM6r/9BQO7S0vD5lMcWspGIg0=
|
||||
github.com/containerd/containerd/api v1.9.0/go.mod h1:GhghKFmTR3hNtyznBoQ0EMWr9ju5AqHjcZPsSpTKutI=
|
||||
github.com/containerd/containerd/api v1.8.0 h1:hVTNJKR8fMc/2Tiw60ZRijntNMd1U+JVMyTRdsD2bS0=
|
||||
github.com/containerd/containerd/api v1.8.0/go.mod h1:dFv4lt6S20wTu/hMcP4350RL87qPWLVa/OHOwmmdnYc=
|
||||
github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII=
|
||||
github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
|
||||
github.com/containerd/cri-containerd v1.19.0 h1:PcTvvl+SHaekCMQZFQkYjn1RKlYrK6khYbuhOeF68k0=
|
||||
github.com/containerd/cri-containerd v1.19.0/go.mod h1:wxbGdReWGCalzGOEpifoHeYCK4xAgnj4o/4bVB+9voU=
|
||||
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||
github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4=
|
||||
github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
|
||||
github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o=
|
||||
github.com/containerd/go-runc v1.1.0 h1:OX4f+/i2y5sUT7LhmcJH7GYrjjhHa1QI4e8yO0gGleA=
|
||||
@@ -58,21 +59,22 @@ github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpS
|
||||
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
|
||||
github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ=
|
||||
github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
|
||||
github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
|
||||
github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
|
||||
github.com/containernetworking/cni v1.3.0 h1:v6EpN8RznAZj9765HhXQrtXgX+ECGebEYEmnuFjskwo=
|
||||
github.com/containernetworking/cni v1.3.0/go.mod h1:Bs8glZjjFfGPHMw6hQu82RUgEPNGEaBb9KS5KtNMnJ4=
|
||||
github.com/containernetworking/plugins v1.7.1 h1:CNAR0jviDj6FS5Vg85NTgKWLDzZPfi/lj+VJfhMDTIs=
|
||||
github.com/containernetworking/plugins v1.7.1/go.mod h1:xuMdjuio+a1oVQsHKjr/mgzuZ24leAsqUYRnzGoXHy0=
|
||||
github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4=
|
||||
github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
|
||||
github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl31EQbXALQ=
|
||||
github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw=
|
||||
github.com/containernetworking/plugins v1.4.1 h1:+sJRRv8PKhLkXIl6tH1D7RMi+CbbHutDGU+ErLBORWA=
|
||||
github.com/containernetworking/plugins v1.4.1/go.mod h1:n6FFGKcaY4o2o5msgu/UImtoC+fpQXM3076VHfHbj60=
|
||||
github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09 h1:OoRAFlvDGCUqDLampLQjk0yeeSGdF9zzst/3G9IkBbc=
|
||||
github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09/go.mod h1:m2r/smMKsKwgMSAoFKHaa68ImdCSNuKE1MxvQ64xuCQ=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/cri-o/cri-o v1.34.0 h1:ux2URwAyENy5e5hD9Z95tshdfy98eqatZk0fxx3rhuk=
|
||||
github.com/cri-o/cri-o v1.34.0/go.mod h1:kP40HG+1EW5CDNHjqQBFhb6dehT5dCBKcmtO5RZAm6k=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cri-o/cri-o v1.30.10 h1:B7pKkOTBouVVQZJ3pNvqMG8hNjyvKLyGzJ/WMckDSh0=
|
||||
github.com/cri-o/cri-o v1.30.10/go.mod h1:IXuAIT/ik07PF9tj+BSY3TmnyexX8G+mlE/chjWb8QA=
|
||||
github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8=
|
||||
github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
@@ -87,47 +89,55 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/go-ini/ini v1.28.2 h1:drmmYv7psRpoGZkPtPKKTB+ZFSnvmwCMfNj5o1nLh2Y=
|
||||
github.com/go-ini/ini v1.28.2/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
|
||||
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
|
||||
github.com/go-openapi/errors v0.22.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU=
|
||||
github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0=
|
||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
|
||||
github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
|
||||
github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=
|
||||
github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc=
|
||||
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
|
||||
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
|
||||
github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
|
||||
github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
|
||||
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
|
||||
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
|
||||
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
|
||||
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
|
||||
github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc=
|
||||
github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo=
|
||||
github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
|
||||
github.com/go-openapi/errors v0.20.4 h1:unTcVm6PispJsMECE3zWgvG4xTiKda1LIR5rCRWLG6M=
|
||||
github.com/go-openapi/errors v0.20.4/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||
github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
|
||||
github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
|
||||
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
|
||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro=
|
||||
github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw=
|
||||
github.com/go-openapi/runtime v0.26.0 h1:HYOFtG00FM1UvqrcxbEJg/SwvDRvYLQKGhw2zaQjTcc=
|
||||
github.com/go-openapi/runtime v0.26.0/go.mod h1:QgRGeZwrUcSHdeh4Ka9Glvo0ug1LC5WyE+EV88plZrQ=
|
||||
github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
|
||||
github.com/go-openapi/spec v0.20.11 h1:J/TzFDLTt4Rcl/l1PmyErvkqlJDncGvPTMnCI39I4gY=
|
||||
github.com/go-openapi/spec v0.20.11/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
|
||||
github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg=
|
||||
github.com/go-openapi/strfmt v0.21.8 h1:VYBUoKYRLAlgKDrIxR/I0lKrztDQ0tuTDrbhLVP8Erg=
|
||||
github.com/go-openapi/strfmt v0.21.8/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/validate v0.22.3 h1:KxG9mu5HBRYbecRb37KRCihvGGtND2aXziBAv0NNfyI=
|
||||
github.com/go-openapi/validate v0.22.3/go.mod h1:kVxh31KbfsxU8ZyoHaDbLBWU5CnMdqBUEtadQ2G4d5M=
|
||||
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
|
||||
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 h1:sQspH8M4niEijh3PFscJRLDnkL547IeP7kpPe3uUhEg=
|
||||
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466/go.mod h1:ZiQxhyQ+bbbfxUKVvjfO498oPYvtYhZzycal3G/NHmU=
|
||||
@@ -135,8 +145,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -152,72 +162,95 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20231127191134-f3a68a39ae15 h1:t2sLhFuGXwoomaKLTuoxFfFqqlG1Gp2DpsupXq3UvZ0=
|
||||
github.com/google/pprof v0.0.0-20231127191134-f3a68a39ae15/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
|
||||
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/intel-go/cpuid v0.0.0-20210602155658-5747e5cec0d9 h1:x9HFDMDCsaxTvC4X3o0ZN6mw99dT/wYnTItGwhBRmg0=
|
||||
github.com/intel-go/cpuid v0.0.0-20210602155658-5747e5cec0d9/go.mod h1:RmeVYf9XrPRbRc3XIx0gLYA8qOFvNoPOfaEZduRlEp4=
|
||||
github.com/intel/goresctrl v0.8.0 h1:N3shVbS3kA1Hk2AmcbHv8805Hjbv+zqsCIZCGktxx50=
|
||||
github.com/intel/goresctrl v0.8.0/go.mod h1:T3ZZnuHSNouwELB5wvOoUJaB7l/4Rm23rJy/wuWJlr0=
|
||||
github.com/intel/goresctrl v0.6.0 h1:lOqo9o+uXtqPwSB4vpd1greUcWlkBSTPdnbTFgRILf4=
|
||||
github.com/intel/goresctrl v0.6.0/go.mod h1:Qg+rhwvfW78p22OJi649sCH71bJIBX7zT0b+IGe69eE=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/jsimonetti/rtnetlink/v2 v2.0.1 h1:xda7qaHDSVOsADNouv7ukSuicKZO7GgVUCXxpaIEIlM=
|
||||
github.com/jsimonetti/rtnetlink/v2 v2.0.1/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
|
||||
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
|
||||
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
|
||||
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
||||
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
|
||||
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
|
||||
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
|
||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
||||
github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ=
|
||||
github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE=
|
||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
|
||||
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
|
||||
github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
|
||||
github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||
github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI=
|
||||
github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg=
|
||||
github.com/moby/sys/symlink v0.2.0 h1:tk1rOM+Ljp0nFmfOIBtlV3rTDlWOwFRhjEeAhZB0nZc=
|
||||
github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs=
|
||||
github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
|
||||
github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
||||
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
|
||||
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
||||
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
@@ -227,25 +260,27 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
|
||||
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
|
||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo/v2 v2.17.0 h1:kdnunFXpBjbzN56hcJHrXZ8M+LOkenKA7NnBzTNigTI=
|
||||
github.com/onsi/ginkgo/v2 v2.17.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
|
||||
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo=
|
||||
github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||
github.com/opencontainers/runc v1.2.6 h1:P7Hqg40bsMvQGCS4S7DJYhUZOISMLJOB2iGX5COWiPk=
|
||||
github.com/opencontainers/runc v1.2.6/go.mod h1:dOQeFo29xZKBNeRBI0B19mJtfHv68YgCTh1X+YphA+4=
|
||||
github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
|
||||
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20250303011046-260e151b8552 h1:CkXngT0nixZqQUPDVfwVs3GiuhfTqCMk0V+OoHpxIvA=
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20250303011046-260e151b8552/go.mod h1:T487Kf80NeF2i0OyVXHiylg217e0buz8pQsa0T791RA=
|
||||
github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
|
||||
github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||
github.com/opencontainers/runc v1.2.0 h1:qke7ZVCmJcKrJVY2iHJVC+0kql9uYdkusOPsQOOeBw4=
|
||||
github.com/opencontainers/runc v1.2.0/go.mod h1:/PXzF0h531HTMsYQnmxXkBD7YaGShm/2zcRB79dksUc=
|
||||
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
|
||||
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20230914150019-408c51e934dc h1:d2hUh5O6MRBvStV55MQ8we08t42zSTqBbscoQccWmMc=
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20230914150019-408c51e934dc/go.mod h1:8tx1helyqhUC65McMm3x7HmOex8lO2/v9zPuxmKHurs=
|
||||
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
|
||||
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
||||
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
|
||||
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||
@@ -255,25 +290,29 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
|
||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
||||
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
|
||||
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/safchain/ethtool v0.5.10 h1:Im294gZtuf4pSGJRAOGKaASNi3wMeFaGaWuSaomedpc=
|
||||
github.com/safchain/ethtool v0.5.10/go.mod h1:w9jh2Lx7YBR4UwzLkzCmWl85UY0W2uZdd7/DckVE5+c=
|
||||
github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0=
|
||||
github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY=
|
||||
github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec=
|
||||
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
|
||||
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
@@ -281,75 +320,79 @@ github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/urfave/cli v1.22.15 h1:nuqt+pdC/KqswQKhETJjo7pvn/k4xMUxgW6liI7XpnM=
|
||||
github.com/urfave/cli v1.22.15/go.mod h1:wSan1hmo5zeyLGBjRJbzRTNk8gwoYa2B9n4q9dmRIc0=
|
||||
github.com/vishvananda/netlink v1.3.1-0.20250303224720-0e7078ed04c8 h1:Y4egeTrP7sccowz2GWTJVtHlwkZippgBTpUmMteFUWQ=
|
||||
github.com/vishvananda/netlink v1.3.1-0.20250303224720-0e7078ed04c8/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk=
|
||||
github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA=
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs=
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
|
||||
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
gitlab.com/nvidia/cloud-native/go-nvlib v0.0.0-20220601114329-47893b162965 h1:EXE1ZsUqiUWGV5Dw2oTYpXx24ffxj0//yhTB0Ppv+4s=
|
||||
gitlab.com/nvidia/cloud-native/go-nvlib v0.0.0-20220601114329-47893b162965/go.mod h1:TBB3sR7/jg4RCThC/cgT4fB8mAbbMO307TycfgeR59w=
|
||||
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
|
||||
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
|
||||
go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8=
|
||||
go.mongodb.org/mongo-driver v1.12.1 h1:nLkghSU8fQNaK7oUmDhQFsnrtcoNy7Z6LVFKsEecqgE=
|
||||
go.mongodb.org/mongo-driver v1.12.1/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q=
|
||||
go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
|
||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||
go.opentelemetry.io/otel v1.23.1 h1:Za4UzOqJYS+MUczKI320AtqZHZb7EqxO00jAHE0jmQY=
|
||||
go.opentelemetry.io/otel v1.23.1/go.mod h1:Td0134eafDLcTS4y+zQ26GE8u3dEuRBiBCTUIRHaikA=
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.0.0 h1:cLhx8llHw02h5JTqGqaRbYn+QVKHmrzD9vEbKnSPk5U=
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.0.0/go.mod h1:q10N1AolE1JjqKrFJK2tYw0iZpmX+HBaXBtuCzRnBGQ=
|
||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||
go.opentelemetry.io/otel/metric v1.23.1 h1:PQJmqJ9u2QaJLBOELl1cxIdPcpbwzbkjfEyelTl2rlo=
|
||||
go.opentelemetry.io/otel/metric v1.23.1/go.mod h1:mpG2QPlAfnK8yNhNJAxDZruU9Y1/HubbC+KyH8FaCWI=
|
||||
go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
|
||||
go.opentelemetry.io/otel/sdk v1.23.1 h1:O7JmZw0h76if63LQdsBMKQDWNb5oEcOThG9IrxscV+E=
|
||||
go.opentelemetry.io/otel/sdk v1.23.1/go.mod h1:LzdEVR5am1uKOOwfBWFef2DCi1nu3SA8XQxx2IerWFk=
|
||||
go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.opentelemetry.io/otel/trace v1.23.1 h1:4LrmmEd8AU2rFvU1zegmvqW7+kWarxtNOPyeL6HmYY8=
|
||||
go.opentelemetry.io/otel/trace v1.23.1/go.mod h1:4IpnpJFwr1mo/6HL8XIPJaE9y0+u1KcVmuW7dwFSVrI=
|
||||
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
|
||||
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
|
||||
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4=
|
||||
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -361,19 +404,24 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
|
||||
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
|
||||
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -381,27 +429,35 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
@@ -411,8 +467,9 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
|
||||
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -422,17 +479,17 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE=
|
||||
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
|
||||
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||
google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
|
||||
google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -444,9 +501,12 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
|
||||
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
@@ -457,21 +517,22 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
|
||||
k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||
k8s.io/cri-api v0.33.0 h1:YyGNgWmuSREqFPlP3XCstlHLilYdW898KwtKoaTYwBs=
|
||||
k8s.io/cri-api v0.33.0/go.mod h1:OLQvT45OpIA+tv91ZrpuFIGY+Y2Ho23poS7n115Aocs=
|
||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA=
|
||||
k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
|
||||
k8s.io/cri-api v0.30.0 h1:hZqh3vH5JZdqeAyhD9nPXSbT6GDgrtPJkPiIzhWKVhk=
|
||||
k8s.io/cri-api v0.30.0/go.mod h1://4/umPJSW1ISNSNng4OwjpkvswJOQwU8rnkvO8P+xg=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
tags.cncf.io/container-device-interface v1.0.1 h1:KqQDr4vIlxwfYh0Ed/uJGVgX+CHAkahrgabg6Q8GYxc=
|
||||
tags.cncf.io/container-device-interface v1.0.1/go.mod h1:JojJIOeW3hNbcnOH2q0NrWNha/JuHoDZcmYxAZwb2i0=
|
||||
tags.cncf.io/container-device-interface/specs-go v1.0.0 h1:8gLw29hH1ZQP9K1YtAzpvkHCjjyIxHZYzBAvlQ+0vD8=
|
||||
tags.cncf.io/container-device-interface/specs-go v1.0.0/go.mod h1:u86hoFWqnh3hWz3esofRFKbI261bUlvUfLKGrDhJkgQ=
|
||||
tags.cncf.io/container-device-interface v0.8.1 h1:c0jN4Mt6781jD67NdPajmZlD1qrqQyov/Xfoab37lj0=
|
||||
tags.cncf.io/container-device-interface v0.8.1/go.mod h1:Apb7N4VdILW0EVdEMRYXIDVRZfNJZ+kmEUss2kRRQ6Y=
|
||||
tags.cncf.io/container-device-interface/specs-go v0.8.0 h1:QYGFzGxvYK/ZLMrjhvY0RjpUavIn4KcmRmVP/JjdBTA=
|
||||
tags.cncf.io/container-device-interface/specs-go v0.8.0/go.mod h1:BhJIkjjPh4qpys+qm4DAYtUyryaTDg9zris+AczXyws=
|
||||
|
||||
@@ -81,7 +81,7 @@ func (s *service) serveMetrics(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// encode the metrics
|
||||
encoder := expfmt.NewEncoder(w, expfmt.NewFormat(expfmt.TypeTextPlain))
|
||||
encoder := expfmt.NewEncoder(w, expfmt.FmtText)
|
||||
for _, mf := range mfs {
|
||||
encoder.Encode(mf)
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func (s *service) serveMetrics(w http.ResponseWriter, r *http.Request) {
|
||||
func decodeAgentMetrics(body string) []*dto.MetricFamily {
|
||||
// decode agent metrics
|
||||
reader := strings.NewReader(body)
|
||||
decoder := expfmt.NewDecoder(reader, expfmt.NewFormat(expfmt.TypeTextPlain))
|
||||
decoder := expfmt.NewDecoder(reader, expfmt.FmtText)
|
||||
list := make([]*dto.MetricFamily, 0)
|
||||
|
||||
for {
|
||||
|
||||
@@ -44,7 +44,9 @@ func getConnection(endPoint string) (*grpc.ClientConn, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn, err = grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithContextDialer(dialer))
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
|
||||
defer cancel()
|
||||
conn, err = grpc.DialContext(ctx, addr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock(), grpc.WithContextDialer(dialer))
|
||||
if err != nil {
|
||||
errMsg := errors.Wrapf(err, "connect endpoint '%s', make sure you are running as root and the endpoint has been started", endPoint)
|
||||
return nil, errMsg
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user