Compare commits

..

4 Commits

Author SHA1 Message Date
Aurélien Bombo
29e74892f4 test3 2025-09-11 12:26:53 -05:00
Aurélien Bombo
5c5e2c68bc test2 2025-09-11 12:23:18 -05:00
Aurélien Bombo
fd4f7638e5 test 2025-09-11 12:15:31 -05:00
Aurélien Bombo
a5641e27db test
Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
2025-09-11 09:08:29 -05:00
1220 changed files with 49926 additions and 88121 deletions

View File

@@ -66,9 +66,6 @@ updates:
rustix:
patterns:
- rustix
slab:
patterns:
- slab
time:
patterns:
- time

View File

@@ -2,7 +2,7 @@ name: Lint GHA workflows
on:
workflow_dispatch:
pull_request:
pull_request_target:
types:
- opened
- edited

View File

@@ -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 }}

View File

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

View File

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

View File

@@ -2,6 +2,7 @@ name: GHA security analysis
on:
push:
branches: ["main"]
pull_request:
permissions: {}

View File

@@ -1 +1 @@
3.21.0
3.20.0

View File

@@ -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; }
################

View File

@@ -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
View File

@@ -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"

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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"

View File

@@ -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")]

View File

@@ -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 {}

View File

@@ -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 }

View File

@@ -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>>>>;

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

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

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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| {

View File

@@ -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);
}

View File

@@ -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)?;
}
}

View File

@@ -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,

View File

@@ -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()
}
}

View File

@@ -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(())
}

View File

@@ -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)?;
}
}

View File

@@ -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(())

View File

@@ -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(())

View File

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

View File

@@ -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,

View File

@@ -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);

View File

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

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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);
}
}

View File

@@ -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
}
}

View File

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

View File

@@ -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>;

View File

@@ -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]

View File

@@ -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"

View File

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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;

View File

@@ -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>,
}

View File

@@ -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,

View File

@@ -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(())
}

View File

@@ -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<()> {

View File

@@ -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,

View File

@@ -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,

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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(())
}

View File

@@ -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]

View File

@@ -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(())

View File

@@ -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(

View File

@@ -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(())
});
}

View File

@@ -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?;

View File

@@ -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<()> {

View File

@@ -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<()>;

View File

@@ -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(())
});
}

View File

@@ -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<()> {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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<()> {

View File

@@ -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);
}
}
}

View File

@@ -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"

View File

@@ -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,

View File

@@ -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(

View File

@@ -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()
});

View File

@@ -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()
};

View File

@@ -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] = &[

View File

@@ -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";

View File

@@ -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()
};

View File

@@ -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()
};

View File

@@ -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,

View File

@@ -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;

View File

@@ -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);

View File

@@ -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::*;

View File

@@ -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
}

View File

@@ -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)]

View File

@@ -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,
})))
}
}

View File

@@ -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)
}

View File

@@ -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,

View File

@@ -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,
})
}
}

View File

@@ -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 {

View File

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

View File

@@ -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:

View File

@@ -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=

View File

@@ -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 {

View File

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