Compare commits

..

114 Commits

Author SHA1 Message Date
Fabiano Fidêncio
c7d0c270ee release: Bump version to 3.24.0
Bump VERSION and helm-chart versions

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-12-12 18:15:41 +01:00
Fabiano Fidêncio
50b853eb93 tests: nvidia: Always rely on the "kata" default runtime class
This is a pattern already followed by all the other tests.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-12-12 16:31:42 +01:00
Manuel Huber
ff2396aeec tests: nvidia: Declare KATA_HYPERVISOR variable
Align with other test logic - declare the KATA_HYPERVISOR in the
run bash script, then declare the RUNTIME_CLASS_NAME variable in
the bats files.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-12 16:31:42 +01:00
Manuel Huber
6e31cf2156 tests: nvidia: cc: USE is_confidential_gpu_hw
This function has recently been introduced, so we align patterns.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-12 16:31:42 +01:00
Manuel Huber
cd1f55b41c tests: nvidia: cc: Set GPU0 policy for NIM tests
Now that we have a more restrictive resource policy for KBS, let
us start adopting it across all NVIDIA test cases. This policy was
previously introduced by the NVIDIA attestation test.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-12 16:31:42 +01:00
Manuel Huber
edbac264cb tests: nvidia: cc: Remove KBS variable
The variable is now set in the CI YAML file, thus removing the
assignment.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-12 16:31:42 +01:00
Manuel Huber
9665b74653 tests: nvidia: cc: address shellcheck warnings
Address shellcheck warnings for run_kubernetes_nv_tests.sh

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-12 16:31:42 +01:00
Manuel Huber
5f9e7a03a8 tests: nvidia: do not use teardown_common
Clean up in each NVIDIA bats file according to our needs.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-12 16:31:42 +01:00
Alex Lyn
c3fd4c1621 version: Bump rtnetlink and netlink-packet-route
It aims to upgrade rtnetlink to mitigate netlink log noise.
This commit upgrades the `rtnetlink` dependency (and corresponding
libraries like `netlink-packet-route`) to address excessive and
unnecessary netlink-related logging during sandbox startup.

Problem:
The previously used `rtnetlink v0.16` (depending on `netlink-proto
v0.11.3`) generates a high volume of DEBUG/INFO level netlink messages
during sandbox initialization. This noise:
1.  Overloads the logging system, often leading to warnings like
"slog-async: logger dropped messages due to channel overflow."
2.  Interferes with effective troubleshooting by distracting developers
from legitimate Kata errors.

Solution:
We upgrade to `rtnetlink v0.19` (and `netlink-proto v0.12`), as testing
confirms that the latest versions have correctly elevated the verbosity
of these netlink internal events to the TRACE level.

This change significantly enhances the log analysis experience by
suppressing unnecessary network-related logs during startup.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-12-12 14:27:33 +01:00
Manuel Huber
1781fb8b06 tests: nvidia: cc: Use CUDA image from NVCR
Pull from nvcr.io to avoid hitting unauthenticated pull rate
limits.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-12 12:52:33 +01:00
Manuel Huber
f63f95f315 tests: nvidia: cc: generate pod security policies
With these changes, we create pod security policies when running
against NVIDIA TEE GPU handlers where AUTO_GENERATE_POLICY is set.
For the non-TEE GPU tests, the added functions bail out by design.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-12 12:52:33 +01:00
Manuel Huber
bf26ad9532 nvidia: tests: remove outer CDI annotations
With the new device plugin being used by CI runners, these
annotations are no longer necessary.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-12 12:52:33 +01:00
Manuel Huber
37b4f6ae8b tests: Adapt NVIDIA common policy settings
Following existing patterns, we adapt the common policy settings
for NVIDIA GPU CI platforms. For instance, for our CI runners, we
use containerd 2.x.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-12 12:52:33 +01:00
Manuel Huber
f4c0c8546e tests: Enable AUTO_GENERATE_POLICY for NVIDIA TEEs
Enable auto-generate policy for qemu-nvidia-gpu-* if the user
didn't specify an AUTO_GENERATE_POLICY value.

Setting this in run_kubernetes_nv_tests.sh is too late as
gha-run.sh calls into run_tests, setup.sh, and then into
create_common_genpolicy_settings() where the rules.rego and
genpolicy-settings file are being copied to the right locations.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-12 12:52:33 +01:00
Manuel Huber
b9774e44b6 genpolicy: tests: Add VFIO passthrough test cases
Add one valid test case with 2 GPUs with proper VFIO device
entries and CDI annotations.
Add seven test cases with invalid combinations of VFIO device
entries and CDI annotations.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-12 12:52:33 +01:00
Manuel Huber
d3e6936820 genpolicy: validation of vfio passthrough GPUs
Add rules for vfio passthrough GPUs. When creating the security
policy document, parse GPU resource limits and derive CDI
annotation patterns and VFIO device entries.
With various values for CDI annotations and device paths being
runtime-dependent, use regular expressions.
For now, this enables passthrough of NVIDIA GPUs, but the changes
are designed to allow for other VFIO device types.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-12 12:52:33 +01:00
Alex Lyn
82e8e9fbe0 doc: add block device's settings to the doc page
Add the block device specific annotations which is dedicated within
runtime-rs for num_queues and queue_sie to the document to help
users set the two parameters.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-12-11 21:10:22 +01:00
Alex Lyn
a8a458664d kata-types: Allow dynamic queue config via Pod annotations
This commit introduces the capability to dynamically configure
`queue_size` and `num_queues` parameters via Pod annotations.

Currently, `kata-runtime` allows for static configuration of
`queue_size` and `num_queues` for block devices through its config
file. However, a critical issue arises when a Pod is allocated fewer
CPU cores than the statically configured `num_queues` value. In such
scenarios, the Pod fails to start, leading to operational instability
and limiting flexibility in resource allocation.

To address this, this feature enables users to override the default
queue_size and num_queues parameters by specifying them in Pod
annotations.This allows for fine-grained control and dynamic adjustment
of these parameters based on the specific resource allocation of a Pod.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-12-11 21:10:22 +01:00
Steve Horsman
51459b9b15 Merge pull request #12220 from fidencio/topic/ci-arm64-temporarily-disable-arm64-non-k8s-tests
ci: arm64-non-k8s: temporarily skip the tests
2025-12-11 11:35:39 +00:00
Fabiano Fidêncio
46c7d6c9f8 ci: arm64-non-k8s: temporarily skip the tests
The runner is down for a few weeks. I may end up bringing in my personal
runner, but I'm not confident I can easily do this before the holidays,
thus I'm skipping the tests for now.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-12-11 12:14:32 +01:00
Manuel Huber
560f6f6c74 tests: nvidia: cc: Affirming attestation policy
Set the attestation policy for GPU0 to affirming. This requires
the GPU, for instance, to have production properties, such as
properly signed VBIOS firmware.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-11 10:16:58 +01:00
Alex Lyn
751b6875f9 tests: Temporarily skip the cpu-ns test for the s390x platform
As some reasons that this CI is continuously failed, we'd like to
temporarily skip it for the s390x platform. And it will be enabled
when we addressed related issues.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-12-10 22:11:56 +01:00
Alex Lyn
d495b77135 runtime-rs: Align the default annptations with runtime-go
As the default enable_annotations in runtime-rs is different with
runtime-go, we should make it align with configuration in runtime-go.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-12-10 22:11:56 +01:00
Alex Lyn
c8dd5fbacf runtime-rs: Migrate vCPU tracking to fractional float
This commit refactors the vCPU resource management within runtime's
`CpuResource` structure and related calculation logic to use
floating-point numbers (`f32`) instead of integers (`u32`).

This migration is necessary to fully support the fractional vCPU
allocation introduced in the `kata-types` library, ensuring better
precision in:
1.Allocation Tracking: `current_vcpu` now tracks the precise
fractional value (e.g., 1.5 vCPUs).
2.Resource Calculation: `calc_cpu_resources` now returns a precise
`f32` sum of container vCPU requests, including normalization logic
based on the maximum period, removing the previous integer rounding
steps in the calculation.
3.Hypervisor Interaction: The integer vCPU requirement for the
hypervisor remains, so `ceil()` is now explicitly applied only when
interacting with the hypervisor or agent APIs
(`do_update_cpu_resources`, `current_vcpu`, `online_cpu_mem`).

And key changes as below:
1. `CpuResource::current_vcpu` updated from `u32` to `f32`.
2. `calc_cpu_resources` return type changed from `u32` to `f32`.
3. CPU hotplug logic now uses `f32` for the target vCPU count and applies
4. `ceil()` before calling `hypervisor.resize_vcpu()`.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-12-10 22:11:56 +01:00
Alex Lyn
84fd33c3bc kata-types: Use fractional float for vCPU resource tracking
Refactors `LinuxContainerCpuResources` and `LinuxSandboxCpuResources`
to track calculated vCPU allocation using `f64` (fractional float)
instead of `u64` (milliseconds).

This ensures more precise resource calculation (`quota / period`) and
aggregation by avoiding rounding errors inherent in millisecond-based
integer tracking.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-12-10 22:11:56 +01:00
Alex Lyn
0f04363ea8 tests: Disable CPU elasticity tests for nontee scenarios
This commit updates the non-TEE tests to disable two specific test
cases: `k8s-number-cpus.bats` and `k8s-sandbox-vcpus-allocation.bats`.

These tests are designed to cover CPU elasticity/dynamic scaling
capabilities. In the non-TEE scenario, we are enforcing the disabling of
this capability by setting the default configuration to
`static_sandbox_resource_mgmt=true`.

Although the tests currently pass, allowing them to run is logically
inconsistent with the intended non-TEE configuration. Therefore, we are
disabling them for all non-TEE runtimes, specifically targeting:
- `qemu-coco-dev`
- `qemu-coco-dev-runtime-rs`

This change ensures that our non-TEE CI accurately reflects the static
resource management policy and prevents misleading test results.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-12-10 22:11:56 +01:00
Alex Lyn
beaf44dd2e tests: disable block volume test for s390 arch
As runtime-rs doesn't support block device hotplug in s390 arch,
with this fact, we just disable or skip the test when it is the
s390.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-12-10 22:11:56 +01:00
Alex Lyn
535ba589f4 runtime-rs: Enable elastic resource feature
To support such feature, the item in Makefile should be enabled,
and it can be set true when make build, just like this:
`DEFSTATICRESOURCEMGMT_QEMU := false`
When users don't want this feature, they can set it with true via
the configuration.toml.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-12-10 22:11:56 +01:00
Alex Lyn
28371dbec5 tests: Enable cloud-hypervisor and qemu-runtime-rs within the CI
Enable the cpu hotplug tests within the k8s-number-cpus.bats for both
cloud-hypervisor and qemu-runtime-rs.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-12-10 22:11:56 +01:00
Alex Lyn
82a72b4564 tests: Enable cpu hotplug for dragonball and clh in vcpus allocation
We have support cpu hotplug features within dragonball and clh, this
commit is to enable the test within the CI.

Fixes: #8660

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-12-10 22:11:56 +01:00
Alex Lyn
6196d3d646 tests: Enable cpu hotplug tests in k8s-cpu-ns.bats
As previous failure within the case, we choose to skip it, but now
the cpu hotplug has been corrected, and it's time to re-enable it.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-12-10 22:11:56 +01:00
Alex Lyn
96bd13e85d tests: Add support for qemu-runtime-rs
We have supportted virtio-scsi driver, and now the CI should be
enabled.

Fixes: #10373

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-12-10 22:11:56 +01:00
dependabot[bot]
2137b1fa3a build(deps): bump github.com/containernetworking/plugins in /src/runtime
Bumps [github.com/containernetworking/plugins](https://github.com/containernetworking/plugins) from 1.7.1 to 1.9.0.
- [Release notes](https://github.com/containernetworking/plugins/releases)
- [Commits](https://github.com/containernetworking/plugins/compare/v1.7.1...v1.9.0)

---
updated-dependencies:
- dependency-name: github.com/containernetworking/plugins
  dependency-version: 1.9.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-10 16:10:24 +01:00
LandonTClipp
b50a73912d runtime: Config test extension for IOMMUFDID
Adding additional cases for the IOMMUFDID method to check for
non-IOMMUFD paths are passed. The method should do the right
thing.

Signed-off-by: LandonTClipp <11232769+LandonTClipp@users.noreply.github.com>
2025-12-10 15:46:28 +01:00
LandonTClipp
d5e4cf6b4d runtime: Add test for ExecuteVFIODeviceAdd
Copilot made a good point that we should have a test for this.
Thus, this commit.

Signed-off-by: LandonTClipp <11232769+LandonTClipp@users.noreply.github.com>
2025-12-10 15:46:28 +01:00
LandonTClipp
137866f793 runtime: Allow QMP commands to be logged in debug level
Logging the QMP commands gives us a lot of flexibility to
troubleshoot issues with what is being sent to QEMU.

Signed-off-by: LandonTClipp <11232769+LandonTClipp@users.noreply.github.com>
2025-12-10 15:46:28 +01:00
LandonTClipp
a3b5764f67 runtime: Fix import cycle and add unit test for IOMMUFDID()
An import cycle was introduced because of a mutual need
for the constant that describes the prefix of IOMMUFD files.
We need to extract this out into a higher-level package.

Signed-off-by: LandonTClipp <11232769+LandonTClipp@users.noreply.github.com>
2025-12-10 15:46:28 +01:00
LandonTClipp
09438fd54f runtime: Add IOMMUFD Object Creation for QEMU QMP Commands
The QMP commands sent to QEMU did not properly set up
IOMMUFD objects in the codepath that handles VFIO device
hot-plugging. This is mainly relevant in the Kubernetes
use-case where the VFIO devices are not available when
QEMU is first launched.

Signed-off-by: LandonTClipp <11232769+LandonTClipp@users.noreply.github.com>
2025-12-10 15:46:28 +01:00
Manuel Huber
cb8fd2e3b1 runtime: gpu: Skip CDI annos for pause container
The pause container does not need CDI annotations, these are only
intended for workload containers.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-10 13:26:04 +01:00
Fabiano Fidêncio
69a0ac979c tests: Adjust install_bats()
The function assumes that the runner is a Ubuntu machine, which so far
has been true as part of our CI.

However, the new ARM runner is running on Debian, and those mirror
additions would simply break.

With this in mind, for any distro that's not ubuntu, let's just make
sure to inform the owner of the system to have bats already installed as
part of the environment provided.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-12-10 12:05:04 +01:00
Fabiano Fidêncio
406f6b1d15 Revert "tests: Add workaround to override CDI files"
This reverts commit 5a81b010f2, as we now
have all the infrastructure properly set up as part of our CI node.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-12-09 23:18:11 +01:00
Fabiano Fidêncio
3db7b88eff tests: remove containerd guest pull stability tests
Remove the existing containerd guest pull stability tests workflow
as we're going to rebuild all the VMs used for testing and introduce
new, more focused stability tests for nydus-snapshotter.

The new tests will be added soon, as part of another PR.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-12-08 16:29:11 +01:00
Fabiano Fidêncio
5b6a2d25bc podOverhead: Reduce memory overhead for GPU runtime classes
Now that we've bumped to QEMU 10.2.0-rc1, we can take advantage of a fix
that's present there, which fixes the double memory allocation for the
cases where GPUs are being cold-plugged.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-12-06 00:16:43 +01:00
Fabiano Fidêndio
71f78cc87e tests: cc: gpu: Lower the amount of memory required by the pods
We've made the pods require a ridiculous amount of memory, just for the
sake of getting them running.

Now that those are running, tests are passing, CI is required, let's
work to lower the amount of mmemory needed as everything else is working
as expected.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-12-06 00:16:43 +01:00
Dan Mihai
965ad10cf2 tests: k8s: tests_common.sh local modification
Clean-up shellcheck warnings:

SC2030 (info): Modification of cmd_out is local (to subshell caused by (..) group).
SC2031 (info): cmd_out was modified in a subshell. That change might be lost.

Signed-off-by: Dan Mihai <dmihai@microsoft.com>
2025-12-06 00:16:23 +01:00
Dan Mihai
8199171cc4 tests: k8s: tests_common.sh braces around variables
Clean-up shellcheck warnings:

SC2250 (style): Prefer putting braces around variable references even
when not strictly required.

Signed-off-by: Dan Mihai <dmihai@microsoft.com>
2025-12-06 00:16:23 +01:00
Fabiano Fidêncio
5a81b010f2 tests: Add workaround to override CDI files
Let's add a simple backup and restore logic for the CDI configuration
file nvidia.com-pgpu.yaml in the k8s-nvidia-*.bats and
k8s-confidential-attestation.bats test files.

Althought not optimal, this is a temporary workaround needed until
NVIDIA releases what's needed for the GPU Operator to properly deal with
cold plugged devices for the Confidential Containers cases, which is
work in progress right now.

After that's released, we can revert/drop this patch.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-12-05 18:58:35 +01:00
Fabiano Fidêncio
aaa67df4dd versions: Bump experimental {tdx,snp} QEMU
Let's bump experimental {tdx,snp} QEMU to the tags created Today in the
Confidential Containers repo, which match with QEMU 10.2.0-rc1.

This bump is specially beneficial for us, as we can get rid of QEMU's
double memory allocation when **cold plugging** a GPU.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-12-05 18:58:35 +01:00
Zvonko Kaiser
f8ad17499d gpu: VFIO handling container vs sandbox
If the sandbox has cold-plugged a IOMMUFD device but the
device-plugins sends us a /dev/vfio/<NUM> device we need to
check if the IOMMUFD device and the  VFIO device are the same
We have the sibling.BDF we now need to extract the BDF of the
devPath that is either /dev/vfio/<NUM> or /dev/vfio/devices/vfio<NUM>

Signed-off-by: Zvonko Kaiser <zkaiser@nvidia.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-05 16:53:31 +01:00
Zvonko Kaiser
147e9f188e Merge pull request #12080 from manuelh-dev/mahuber/cc-gpu-ci-attestation
tests: nvidia: cc: Add attestation test
2025-12-05 09:31:57 -05:00
Steve Horsman
2f1b98c232 Merge pull request #12197 from stevenhorsman/logrus-1.9.3-bump
version: Bump sirupsen/logrus
2025-12-05 14:18:50 +00:00
Manuel Huber
e5861cde20 tests: use Authorization when GH_TOKEN is set
Same as for other uses of GH_TOKEN, use it when set in order to
avoid rate limiting issues.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-05 14:08:43 +01:00
stevenhorsman
9eba559bd6 version: Bump sirupsen/logrus
Bump the github.com/sirupsen/logrus version to 1.9.3
across our components where it is back-level to bring us
up-to-date and resolve high severity CVE-2025-65637

Signed-off-by: stevenhorsman <steven@uk.ibm.com>
2025-12-05 11:12:04 +00:00
Manuel Huber
34efa83afc tests: nvidia: cc: Add attestation test
Add the attestation bats test case to the NVIDIA CI and provide a
second pod manifest for the attestation test with a GPU. This will
enable composite attestation in a subsequent step.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-05 11:48:55 +01:00
Manuel Huber
e31d592a0c versions: Bump coco-trustee
Bump to pull in a fix for composite attestation with GPUs. The new
commit ID corresponds to the fix (change for default GPU policy),
currently being the top commit of the main branch.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-05 11:48:55 +01:00
Manuel Huber
73dfa9b9d5 versions: Bump coco-guest-components
Bump to pull in a fix for NVIDIA CC GPU attestation.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-05 11:48:55 +01:00
Manuel Huber
116a72ad0d tests: cc: Fix command evaluation
This brings two fixes:
- use the test_key variable to check against the aatest value.
- properly check the run command invocation (run w/o bash does not
  seem to like the pipe which leads to ALWAYS evaluating the
  status result to 1. With this, the deny-all test would ALWAYS
  succeed regardless of whether aatest was actually returned or not.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-05 11:48:55 +01:00
Manuel Huber
23675c784b tests: cc: Reset default policy
When running these tests repeatedly locally, the default policy is not
being reset after the test completes, then subsequent runs fail.
Similar to k8s-sealed-secrets.bats, we set the default policy in an if
condition.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-05 11:48:55 +01:00
Manuel Huber
f70c3adaf1 tests: cc: Add kbs_set_gpu0_resource_policy
This allows setting a GPU0 resource policy, enabling GPU
attestation tests to not use the default resource policy.
For now, the policy requires attestation's ear status to
not be contraindicated. In a future change we will require
this to be affirming once our CI runners' vBIOS version is
properly configured.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-05 11:48:55 +01:00
Manuel Huber
c2d1e2dcc9 tests: cc: Add is_confidential_gpu_hardware
This enables attestation tests to figure out whether composite
attestation with a GPU can be executed.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-05 11:48:55 +01:00
Manuel Huber
53e94df203 tests: nvidia: cc: add SUPPORTED_TEE_HYPERVISORS
Add the NVIDIA TEE hypervisors. With this, attestation tests can be run
against the NVIDIA handlers, for instance.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-05 11:48:55 +01:00
Fabiano Fidêncio
923f97bc66 rootfs: Temporarily revert "gpu: Handle root_hash.txt correctly"
This reverts commit e4a13b9a4a, as it
caused some issues with the GPU workflows.

Reverting it is better, as it unblocks other PRs.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-12-05 11:47:37 +01:00
Steve Horsman
d27af53902 Merge pull request #12185 from stevenhorsman/runtime-rs-required-checks
ci: Add qemu-runtime-rs AKS tests to required
2025-12-05 10:43:25 +00:00
stevenhorsman
403de2161f version: Update golang to 1.24.11
Needed to fix:
```
Vulnerability #1: GO-2025-4155
    Excessive resource consumption when printing error string for host
    certificate validation in crypto/x509
  More info: https://pkg.go.dev/vuln/GO-2025-4155
  Standard library
    Found in: crypto/x509@go1.24.9
    Fixed in: crypto/x509@go1.24.11
    Vulnerable symbols found:
      #1: x509.HostnameError.Error
```

Signed-off-by: stevenhorsman <steven@uk.ibm.com>
2025-12-04 22:50:07 +01:00
Steve Horsman
425f4ffc8d Merge pull request #12124 from zvonkok/nvidia-measured-rootfs
gpu: Measured rootfs
2025-12-04 14:54:11 +00:00
Steve Horsman
f673f33e72 Merge pull request #12172 from fidencio/topic/gatekeeper-mark-nvidia-jobs-as-required
gatekeeper: Mark NVIDIA CC GPU test as required
2025-12-04 12:48:57 +00:00
stevenhorsman
112810c796 ci: Add qemu-runtime-rs AKS tests to required
Add the small and normal variants of the qemu-runtime-rs
tests to the required-tests list now that they are stable.

Signed-off-by: stevenhorsman <steven@uk.ibm.com>
2025-12-04 11:15:43 +00:00
Fabiano Fidêncio
c505afb67c gatekeeper: Mark NVIDIA CC GPU test as required
It's been stable for the past 10 nightlies, no retries.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-12-04 11:14:25 +00:00
Steve Horsman
635f7892d5 Merge pull request #12190 from BbolroC/mark-s390x-jobs-as-nonrequired
gatekeeper: Drop all s390x e2e tests temporarily
2025-12-04 11:10:46 +00:00
Steve Horsman
2a6ebc556f Merge pull request #12175 from kata-containers/mahuber/gpu-ci-genpolicy
ci: nvidia: Install kata-artifacts
2025-12-04 09:23:32 +00:00
Hyounggyu Choi
b6ef7eb9c3 gatekeeper: Drop all s390x e2e tests temporarily
This commit marks three s390x CI jobs as non-required.
Please check out the details at #12189.

Signed-off-by: Hyounggyu Choi <Hyounggyu.Choi@ibm.com>
2025-12-04 08:05:14 +01:00
Steve Horsman
10b0717cae Merge pull request #12179 from stevenhorsman/nginx-test-image-by-digest
tests: Switch nginx test image ref to digest
2025-12-03 13:39:07 +00:00
Zvonko Kaiser
e4a13b9a4a gpu: Handle root_hash.txt correctly
Updates to the shim-v2 build and the binaries.sh script.
Makeing sure that both variants "confidential" AND
"nvidia-gpu-confidential" are handled.

Signed-off-by: Zvonko Kaiser <zkaiser@nvidia.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-02 19:56:19 +01:00
Steve Horsman
d8405cb7fb Merge pull request #11983 from stevenhorsman/toolchain-guidance
doc: Document our Toolchain policy
2025-12-02 15:47:54 +00:00
stevenhorsman
b9cb667687 doc: Document our Toolchain policy
Create an initial version of our toolchain policy as agreed in
Architecture Committee meetings and the PTG

Fixes: #9841
Signed-off-by: stevenhorsman <steven@uk.ibm.com>
2025-12-02 14:28:29 +00:00
stevenhorsman
79a75b63bf tests: Switch nginx test image ref to digest
As tags are mutable and digests are not, lets pin our image
by digest to give our CI a better chance of stability

Signed-off-by: stevenhorsman <steven@uk.ibm.com>
2025-12-02 13:02:50 +00:00
stevenhorsman
5c618dc8e2 tests: Switch nginx images to use version.yaml details
- Swap out the hard-coded nginx registry and verisons for reading
the test image details for version.yaml
which can also ensure that the quay.io mirror is used
rather than the docker hub versions which can hit pull limits
- Try setting imagePullPoliycy Always to fix issues with the arm CI

Signed-off-by: stevenhorsman <steven@uk.ibm.com>
2025-12-02 10:04:09 +01:00
Manuel Huber
3427b5c00e ci: nvidia: Install kata-artifacts
In preparation for Kata agent security policy testing, installing
Kata tools to provide genpolicy.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-01 17:59:19 +00:00
Manuel Huber
4355af7972 kata-deploy: Fix binary find install_tools_helper
Using make tarball targets for tools locally, binaries may exist
for both debug and release builds. In this case, cryptic errors
are shown as we try to install multiple binaries.
This change require exactly one binary to be found and errors  out
in other cases.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-12-01 09:29:24 -08:00
Manuel Huber
5a5c43429e ci: nvidia: remove kubectl_retry calls
When tests regress, the CI wait time can increase significantly
with the current kubectly_retry attempt logic. Thus, align with
other tests and remove kubectl_retry invocations. Instead, rely on
proper timeouts.

Signed-off-by: Manuel Huber <manuelh@nvidia.com>
2025-11-28 19:00:57 +01:00
Fabiano Fidêncio
e3646adedf gatekeeper: Drop SEV-SNP from required
SEV-SNP machine is failing due to nydus not being deployed in the
machine.

We cannot easily contact the maintainers due to the US Holidays, and I
think this should become a criteria for a machine not be added as
required again (different regions coverage).

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-11-28 12:46:07 +01:00
Steve Horsman
8534afb9e8 Merge pull request #12150 from stevenhorsman/add-gatekeeper-triggers
ci: Add two extra gatekeeper triggers
2025-11-28 09:34:41 +00:00
Zvonko Kaiser
9dfa6df2cb agent: Bump CDI-rs to latest
Latest version of container-device-interface is v0.1.1

Signed-off-by: Zvonko Kaiser <zkaiser@nvidia.com>
2025-11-27 22:57:50 +01:00
Fabiano Fidêncio
776e08dbba build: Add nvidia image rootfs builds
So far we've only been building the initrd for the nvidia rootfs.
However, we're also interested on having the image beind used for a few
use-cases.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-11-27 22:46:07 +01:00
stevenhorsman
531311090c ci: Add two extra gatekeeper triggers
We hit a case that gatekeeper was failing due to thinking the WIP check
had failed, but since it ran the PR had been edited to remove that from
the title. We should listen to edits and unlabels of the PR to ensure that
gatekeeper doesn't get outdated in situations like this.

Signed-off-by: stevenhorsman <steven@uk.ibm.com>
2025-11-27 16:45:04 +00:00
Zvonko Kaiser
bfc9e446e1 kernel: Add NUMA config
Add per arch specific NUMA enablement kernel settings

Signed-off-by: Zvonko Kaiser <zkaiser@nvidia.com>
2025-11-27 12:45:27 +01:00
Steve Horsman
c5ae8c4ba0 Merge pull request #12144 from BbolroC/use-runs-on-to-choose-runners
GHA: Use `runs-on` only for choosing proper runners
2025-11-27 09:54:39 +00:00
Fabiano Fidêncio
2e1ca580a6 runtime-rs: Only QEMU supports templating
We can remove the checks and default values attribution from all other
shims.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-11-27 10:31:28 +01:00
Alex Lyn
df8315c865 Merge pull request #12130 from Apokleos/stability-rs
tests: Enable stability tests for runtime-rs
2025-11-27 14:27:58 +08:00
Fupan Li
50dce0cc89 Merge pull request #12141 from Apokleos/fix-nydus-sn
tests: Properly handle containerd config based on version
2025-11-27 11:59:59 +08:00
Fabiano Fidêncio
fa42641692 kata-deploy: Cover all flavours of QEMU shims with multiInstallSuffix
We were missing all the runtime-rs variants.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-11-26 17:44:16 +01:00
Fabiano Fidêncio
96d1e0fe97 kata-deploy: Fix multiInstallSuffix for NV shims
When using the multiInstallSuffix we must be cautelous on using the shim
name, as qemu-nvidia-gpu* doesn't actually have a matching QEMU itself,
but should rather be mapped to:
qemu-nvidia-gpu -> qemu
qemu-nvidia-gpu-snp -> qemu-snp-experimental
qemu-nvidia-gpu-tdx -> qemu-tdx-experimental

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2025-11-26 17:44:16 +01:00
Markus Rudy
d8f347d397 Merge pull request #12112 from shwetha-s-poojary/fix_list_routes
agent: fix the list_routes failure
2025-11-26 17:32:10 +01:00
Steve Horsman
3573408f6b Merge pull request #11586 from zvonkok/numa-qemu
qemu: Enable NUMA
2025-11-26 16:28:16 +00:00
Steve Horsman
aae483bf1d Merge pull request #12096 from Amulyam24/enable-ibm-runners
ci: re-enable IBM runners for ppc64le and s390x
2025-11-26 13:51:21 +00:00
Steve Horsman
5c09849fe6 Merge pull request #12143 from kata-containers/topic/add-report-tests-to-workflows
workflows: Add Report tests to all workflows
2025-11-26 13:18:21 +00:00
Steve Horsman
ed7108e61a Merge pull request #12138 from arvindskumar99/SNPrequired
CI: readding SNP as required
2025-11-26 11:33:07 +00:00
Amulyam24
43a004444a ci: re-enable IBM runners for ppc64le and s390x
This PR re-enables the IBM runners for ppc64le/s390x build jobs and s390x static checks.

Signed-off-by: Amulyam24 <amulmek1@in.ibm.com>
2025-11-26 16:20:01 +05:30
Hyounggyu Choi
6f761149a7 GHA: Use runs-on only for choosing proper runners
Fixes: #12123

`include` in #12069, introduced to choose a different runner
based on component, leads to another set of redundant jobs
where `matrix.command` is empty.
This commit gets back to the `runs-on` solution, but makes
the condition human-readable.

Signed-off-by: Hyounggyu Choi <Hyounggyu.Choi@ibm.com>
2025-11-26 11:35:30 +01:00
Alex Lyn
4e450691f4 tests: Unify nydus configuration to containerd v3 schema
Containerd configuration syntax (`config.toml`) varies across versions,
requiring per-version logic for fields like `runtime`.

However, testing confirms that containerd LTS (1.7.x) and newer
versions fully support the v3 schema for the nydus remote snapshotter.

This commit changes the previous containerd v1 settings in `config.toml`.
Instead, it introduces a unified v3-style configuration for nydus, which
can be vailid for lts and active containerds.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-11-26 17:58:16 +08:00
stevenhorsman
4c59cf1a5d workflows: Add Report tests to all workflows
In the CoCo tests jobs @wainersm create a report tests step
that summarises the jobs, so they are easier to understand and
get results for. This is very useful, so let's roll it out to all the bats
tests.

Signed-off-by: stevenhorsman <steven@uk.ibm.com>
2025-11-26 09:28:36 +00:00
shwetha-s-poojary
4510e6b49e agent: fix the list_routes failure
relax list_routes tests so not every route requires a device

Signed-off-by: shwetha-s-poojary <shwetha.s-poojary@ibm.com>
2025-11-25 20:25:46 -08:00
Xuewei Niu
04e1cf06ed Merge pull request #12137 from Apokleos/fix-netdev-mq
runtime-rs: fix QMP 'mq' parameter type in netdev_add to boolean
2025-11-26 11:49:33 +08:00
Arvind Kumar
c085011a0a CI: readding SNP as required
Reenabling the SNP CI node as a required test.

Signed-off-by: Arvind Kumar <arvinkum@amd.com>
2025-11-25 17:05:01 +00:00
Zvonko Kaiser
45cce49b72 shellcheckk: Fix [] [[]] SC2166
This file is a beast so doing one shellcheck fix after the other.

Signed-off-by: Zvonko Kaiser <zkaiser@nvidia.com>
2025-11-25 15:46:16 +01:00
Zvonko Kaiser
b2c9439314 qemu: Update tools/packaging/static-build/qemu/build-qemu.sh
This nit was introduced by 227e717 during the v3.1.0 era. The + sign from the bash substitution ${CI:+...} was copied by mistake.

Signed-off-by: Zvonko Kaiser <zkaiser@nvidia.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-25 15:46:09 +01:00
Zvonko Kaiser
2f3d42c0e4 shellcheck: build-qemu.sh is clean
Make shellcheck happy

Signed-off-by: Zvonko Kaiser <zkaiser@nvidia.com>
2025-11-25 15:46:07 +01:00
Zvonko Kaiser
f55de74ac5 shellcheck: build-base-qemu.sh is clean
Make shellcheck happy

Signed-off-by: Zvonko Kaiser <zkaiser@nvidia.com>
2025-11-25 15:45:49 +01:00
Zvonko Kaiser
040f920de1 qemu: Enable NUMA support
Enable NUMA support with QEMU.

Signed-off-by: Zvonko Kaiser <zkaiser@nvidia.com>
2025-11-25 15:45:00 +01:00
Alex Lyn
7f4d856e38 tests: Enable nydus tests for qemu-runtime-rs
We need enable nydus tests for qemu-runtime-rs, and this commit
aims to do it.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-11-25 17:45:57 +08:00
Alex Lyn
98df3e760c runtime-rs: fix QMP 'mq' parameter type in netdev_add to boolean
QEMU netdev_add QMP command requires the 'mq' (multi-queue) argument
to be of boolean type (`true` / `false`). In runtime-rs the virtio-net
device hotplug logic currently passes a string value (e.g. "on"/"off"),
which causes QEMU to reject the command:
```
    Invalid parameter type for 'mq', expected: boolean
```
This patch modifies `hotplug_network_device` to insert 'mq' as a proper
boolean value of `true . This fixes sandbox startup failures when
multi-queue is enabled.

Fixes #12136

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-11-25 17:34:36 +08:00
Alex Lyn
23393d47f6 tests: Enable stability tests for qemu-runtime-rs on nontee
Enable the stability tests for qemu-runtime-rs CoCo on non-TEE
environments

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-11-25 16:18:37 +08:00
Alex Lyn
f1d971040d tests: Enable run-nerdctl-tests for qemu-runtime-rs
Enable nerdctl tests for qemu-runtime-rs

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-11-25 16:14:50 +08:00
Alex Lyn
c7842aed16 tests: Enable stability tests for runtime-rs
As previous set without qemu-runtime-rs, we enable it in this commit.

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
2025-11-25 16:12:12 +08:00
275 changed files with 6322 additions and 2056 deletions

View File

@@ -10,11 +10,6 @@ self-hosted-runner:
- amd64-nvidia-a100
- amd64-nvidia-h100-snp
- arm64-k8s
- containerd-v1.7-overlayfs
- containerd-v2.0-overlayfs
- containerd-v2.1-overlayfs
- containerd-v2.2
- containerd-v2.2-overlayfs
- garm-ubuntu-2004
- garm-ubuntu-2004-smaller
- garm-ubuntu-2204
@@ -25,6 +20,7 @@ self-hosted-runner:
- ppc64le-k8s
- ppc64le-small
- ubuntu-24.04-ppc64le
- ubuntu-24.04-s390x
- metrics
- riscv-builder
- sev-snp

View File

@@ -12,7 +12,12 @@ name: Build checks
jobs:
check:
name: check
runs-on: ${{ matrix.runner || inputs.instance }}
runs-on: >-
${{
( contains(inputs.instance, 's390x') && matrix.component.name == 'runtime' ) && 's390x' ||
( contains(inputs.instance, 'ppc64le') && (matrix.component.name == 'runtime' || matrix.component.name == 'agent') ) && 'ppc64le' ||
inputs.instance
}}
strategy:
fail-fast: false
matrix:
@@ -70,36 +75,6 @@ jobs:
- protobuf-compiler
instance:
- ${{ inputs.instance }}
include:
- component:
name: runtime
path: src/runtime
needs:
- golang
- XDG_RUNTIME_DIR
instance: ubuntu-24.04-s390x
runner: s390x
- component:
name: runtime
path: src/runtime
needs:
- golang
- XDG_RUNTIME_DIR
instance: ubuntu-24.04-ppc64le
runner: ppc64le
- component:
name: agent
path: src/agent
needs:
- rust
- libdevmapper
- libseccomp
- protobuf-compiler
- clang
instance: ubuntu-24.04-ppc64le
runner: ppc64le
steps:
- name: Adjust a permission for repo

View File

@@ -171,6 +171,8 @@ jobs:
- rootfs-image
- rootfs-image-confidential
- rootfs-image-mariner
- rootfs-image-nvidia-gpu
- rootfs-image-nvidia-gpu-confidential
- rootfs-initrd
- rootfs-initrd-confidential
- rootfs-initrd-nvidia-gpu

View File

@@ -150,6 +150,7 @@ jobs:
matrix:
asset:
- rootfs-image
- rootfs-image-nvidia-gpu
- rootfs-initrd
- rootfs-initrd-nvidia-gpu
steps:

View File

@@ -32,7 +32,7 @@ jobs:
permissions:
contents: read
packages: write
runs-on: ppc64le-small
runs-on: ubuntu-24.04-ppc64le
strategy:
matrix:
asset:
@@ -89,7 +89,7 @@ jobs:
build-asset-rootfs:
name: build-asset-rootfs
runs-on: ppc64le-small
runs-on: ubuntu-24.04-ppc64le
needs: build-asset
permissions:
contents: read
@@ -170,7 +170,7 @@ jobs:
build-asset-shim-v2:
name: build-asset-shim-v2
runs-on: ppc64le-small
runs-on: ubuntu-24.04-ppc64le
needs: [build-asset, build-asset-rootfs, remove-rootfs-binary-artifacts]
permissions:
contents: read
@@ -230,7 +230,7 @@ jobs:
create-kata-tarball:
name: create-kata-tarball
runs-on: ppc64le-small
runs-on: ubuntu-24.04-ppc64le
needs: [build-asset, build-asset-rootfs, build-asset-shim-v2]
permissions:
contents: read

View File

@@ -32,7 +32,7 @@ permissions: {}
jobs:
build-asset:
name: build-asset
runs-on: s390x
runs-on: ubuntu-24.04-s390x
permissions:
contents: read
packages: write
@@ -257,7 +257,7 @@ jobs:
build-asset-shim-v2:
name: build-asset-shim-v2
runs-on: s390x
runs-on: ubuntu-24.04-s390x
needs: [build-asset, build-asset-rootfs, remove-rootfs-binary-artifacts]
permissions:
contents: read
@@ -319,7 +319,7 @@ jobs:
create-kata-tarball:
name: create-kata-tarball
runs-on: s390x
runs-on: ubuntu-24.04-s390x
needs:
- build-asset
- build-asset-rootfs

View File

@@ -147,7 +147,7 @@ jobs:
tag: ${{ inputs.tag }}-s390x
commit-hash: ${{ inputs.commit-hash }}
target-branch: ${{ inputs.target-branch }}
runner: s390x
runner: ubuntu-24.04-s390x
arch: s390x
secrets:
QUAY_DEPLOYER_PASSWORD: ${{ secrets.QUAY_DEPLOYER_PASSWORD }}
@@ -165,7 +165,7 @@ jobs:
tag: ${{ inputs.tag }}-ppc64le
commit-hash: ${{ inputs.commit-hash }}
target-branch: ${{ inputs.target-branch }}
runner: ppc64le-small
runner: ubuntu-24.04-ppc64le
arch: ppc64le
secrets:
QUAY_DEPLOYER_PASSWORD: ${{ secrets.QUAY_DEPLOYER_PASSWORD }}
@@ -314,6 +314,7 @@ jobs:
needs: publish-kata-deploy-payload-amd64
uses: ./.github/workflows/run-k8s-tests-on-nvidia-gpu.yaml
with:
tarball-suffix: -${{ inputs.tag }}
registry: ghcr.io
repo: ${{ github.repository_owner }}/kata-deploy-ci
tag: ${{ inputs.tag }}-amd64
@@ -473,7 +474,7 @@ jobs:
vmm: ${{ matrix.params.vmm }}
run-cri-containerd-tests-arm64:
if: ${{ inputs.skip-test != 'yes' }}
if: false
needs: build-kata-static-tarball-arm64
strategy:
fail-fast: false

View File

@@ -10,7 +10,9 @@ on:
- opened
- synchronize
- reopened
- edited
- labeled
- unlabeled
permissions: {}

View File

@@ -31,7 +31,7 @@ jobs:
permissions:
contents: read
packages: write
runs-on: ppc64le-small
runs-on: ubuntu-24.04-ppc64le
steps:
- name: Login to Kata Containers ghcr.io
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0

View File

@@ -35,7 +35,7 @@ jobs:
permissions:
contents: read
packages: write
runs-on: s390x
runs-on: ubuntu-24.04-s390x
steps:
- name: Login to Kata Containers ghcr.io
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0

View File

@@ -1,167 +0,0 @@
name: CI | Run containerd guest pull stability tests
on:
schedule:
- cron: "0 */1 * * *" #run every hour
permissions: {}
# This job relies on k8s pre-installed using kubeadm
jobs:
run-containerd-guest-pull-stability-tests:
name: run-containerd-guest-pull-stability-tests-${{ matrix.environment.test-type }}-${{ matrix.environment.containerd }}
strategy:
fail-fast: false
matrix:
environment: [
{ test-type: multi-snapshotter, containerd: v2.2 },
{ test-type: force-guest-pull, containerd: v1.7 },
{ test-type: force-guest-pull, containerd: v2.0 },
{ test-type: force-guest-pull, containerd: v2.1 },
{ test-type: force-guest-pull, containerd: v2.2 },
]
env:
# I don't want those to be inside double quotes, so I'm deliberately ignoring the double quotes here.
IMAGES_LIST: quay.io/mongodb/mongodb-community-server@sha256:8b73733842da21b6bbb6df4d7b2449229bb3135d2ec8c6880314d88205772a11 ghcr.io/edgelesssys/redis@sha256:ecb0a964c259a166a1eb62f0eb19621d42bd1cce0bc9bb0c71c828911d4ba93d
runs-on: containerd-${{ matrix.environment.test-type }}-${{ matrix.environment.containerd }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Rotate the journal
run: sudo journalctl --rotate --vacuum-time 1s
- name: Pull the kata-deploy image to be used
run: sudo ctr -n k8s.io image pull quay.io/kata-containers/kata-deploy-ci:kata-containers-latest
- name: Deploy Kata Containers
run: bash tests/integration/kubernetes/gha-run.sh deploy-kata
env:
KATA_HYPERVISOR: qemu-coco-dev
KUBERNETES: vanilla
SNAPSHOTTER: ${{ matrix.environment.test-type == 'multi-snapshotter' && 'nydus' || '' }}
USE_EXPERIMENTAL_SETUP_SNAPSHOTTER: ${{ matrix.environment.test-type == 'multi-snapshotter' }}
EXPERIMENTAL_FORCE_GUEST_PULL: ${{ matrix.environment.test-type == 'force-guest-pull' && 'qemu-coco-dev' || '' }}
# This is needed as we may hit the createContainerTimeout
- name: Adjust Kata Containers' create_container_timeout
run: |
sudo sed -i -e 's/^\(create_container_timeout\).*=.*$/\1 = 600/g' /opt/kata/share/defaults/kata-containers/configuration-qemu-coco-dev.toml
grep "create_container_timeout.*=" /opt/kata/share/defaults/kata-containers/configuration-qemu-coco-dev.toml
# This is needed in order to have enough tmpfs space inside the guest to pull the image
- name: Adjust Kata Containers' default_memory
run: |
sudo sed -i -e 's/^\(default_memory\).*=.*$/\1 = 4096/g' /opt/kata/share/defaults/kata-containers/configuration-qemu-coco-dev.toml
grep "default_memory.*=" /opt/kata/share/defaults/kata-containers/configuration-qemu-coco-dev.toml
- name: Run a few containers using overlayfs
run: |
# I don't want those to be inside double quotes, so I'm deliberately ignoring the double quotes here
# shellcheck disable=SC2086
for img in ${IMAGES_LIST}; do
echo "overlayfs | Using on image: ${img}"
pod="$(echo ${img} | tr ':.@/' '-' | awk '{print substr($0,1,56)}')"
kubectl run "${pod}" \
-it --rm \
--restart=Never \
--image="${img}" \
--image-pull-policy=Always \
--pod-running-timeout=10m \
-- uname -r
done
- name: Run a the same few containers using a different snapshotter
run: |
# I don't want those to be inside double quotes, so I'm deliberately ignoring the double quotes here
# shellcheck disable=SC2086
for img in ${IMAGES_LIST}; do
echo "nydus | Using on image: ${img}"
pod="kata-$(echo ${img} | tr ':.@/' '-' | awk '{print substr($0,1,56)}')"
kubectl run "${pod}" \
-it --rm \
--restart=Never \
--image="${img}" \
--image-pull-policy=Always \
--pod-running-timeout=10m \
--overrides='{
"spec": {
"runtimeClassName": "kata-qemu-coco-dev"
}
}' \
-- uname -r
done
- name: Uninstall Kata Containers
run: bash tests/integration/kubernetes/gha-run.sh cleanup
env:
KATA_HYPERVISOR: qemu-coco-dev
KUBERNETES: vanilla
SNAPSHOTTER: nydus
USE_EXPERIMENTAL_SETUP_SNAPSHOTTER: true
- name: Run a few containers using overlayfs
run: |
# I don't want those to be inside double quotes, so I'm deliberately ignoring the double quotes here
# shellcheck disable=SC2086
for img in ${IMAGES_LIST}; do
echo "overlayfs | Using on image: ${img}"
pod="$(echo ${img} | tr ':.@/' '-' | awk '{print substr($0,1,56)}')"
kubectl run "${pod}" \
-it --rm \
--restart=Never \
--image=${img} \
--image-pull-policy=Always \
--pod-running-timeout=10m \
-- uname -r
done
- name: Deploy Kata Containers
run: bash tests/integration/kubernetes/gha-run.sh deploy-kata
env:
KATA_HYPERVISOR: qemu-coco-dev
KUBERNETES: vanilla
SNAPSHOTTER: nydus
USE_EXPERIMENTAL_SETUP_SNAPSHOTTER: true
# This is needed as we may hit the createContainerTimeout
- name: Adjust Kata Containers' create_container_timeout
run: |
sudo sed -i -e 's/^\(create_container_timeout\).*=.*$/\1 = 600/g' /opt/kata/share/defaults/kata-containers/configuration-qemu-coco-dev.toml
grep "create_container_timeout.*=" /opt/kata/share/defaults/kata-containers/configuration-qemu-coco-dev.toml
# This is needed in order to have enough tmpfs space inside the guest to pull the image
- name: Adjust Kata Containers' default_memory
run: |
sudo sed -i -e 's/^\(default_memory\).*=.*$/\1 = 4096/g' /opt/kata/share/defaults/kata-containers/configuration-qemu-coco-dev.toml
grep "default_memory.*=" /opt/kata/share/defaults/kata-containers/configuration-qemu-coco-dev.toml
- name: Run a the same few containers using a different snapshotter
run: |
# I don't want those to be inside double quotes, so I'm deliberately ignoring the double quotes here
# shellcheck disable=SC2086
for img in ${IMAGES_LIST}; do
echo "nydus | Using on image: ${img}"
pod="kata-$(echo ${img} | tr ':.@/' '-' | awk '{print substr($0,1,56)}')"
kubectl run "${pod}" \
-it --rm \
--restart=Never \
--image="${img}" \
--image-pull-policy=Always \
--pod-running-timeout=10m \
--overrides='{
"spec": {
"runtimeClassName": "kata-qemu-coco-dev"
}
}' \
-- uname -r
done
- name: Uninstall Kata Containers
run: bash tests/integration/kubernetes/gha-run.sh cleanup || true
if: always()
env:
KATA_HYPERVISOR: qemu-coco-dev
KUBERNETES: vanilla
SNAPSHOTTER: nydus
USE_EXPERIMENTAL_SETUP_SNAPSHOTTER: true

View File

@@ -142,6 +142,10 @@ jobs:
timeout-minutes: 60
run: bash tests/integration/kubernetes/gha-run.sh run-tests
- name: Report tests
if: always()
run: bash tests/integration/kubernetes/gha-run.sh report-tests
- name: Refresh OIDC token in case access token expired
if: always()
uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0

View File

@@ -68,6 +68,10 @@ jobs:
timeout-minutes: 30
run: bash tests/integration/kubernetes/gha-run.sh run-tests
- name: Report tests
if: always()
run: bash tests/integration/kubernetes/gha-run.sh report-tests
- name: Collect artifacts ${{ matrix.vmm }}
if: always()
run: bash tests/integration/kubernetes/gha-run.sh collect-artifacts

View File

@@ -2,6 +2,9 @@ name: CI | Run NVIDIA GPU kubernetes tests on amd64
on:
workflow_call:
inputs:
tarball-suffix:
required: true
type: string
registry:
required: true
type: string
@@ -45,6 +48,7 @@ jobs:
GH_PR_NUMBER: ${{ inputs.pr-number }}
KATA_HYPERVISOR: ${{ matrix.environment.vmm }}
KUBERNETES: kubeadm
KBS: ${{ matrix.environment.name == 'nvidia-gpu-snp' && 'true' || 'false' }}
K8S_TEST_HOST_TYPE: baremetal
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
@@ -59,6 +63,15 @@ jobs:
env:
TARGET_BRANCH: ${{ inputs.target-branch }}
- name: get-kata-tarball
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: kata-static-tarball-amd64${{ inputs.tarball-suffix }}
path: kata-artifacts
- name: Install kata
run: bash tests/integration/kubernetes/gha-run.sh install-kata-tools kata-artifacts
- name: Uninstall previous `kbs-client`
if: matrix.environment.name != 'nvidia-gpu'
timeout-minutes: 10
@@ -89,6 +102,11 @@ jobs:
run: bash tests/integration/kubernetes/gha-run.sh run-nv-tests
env:
NGC_API_KEY: ${{ secrets.NGC_API_KEY }}
- name: Report tests
if: always()
run: bash tests/integration/kubernetes/gha-run.sh report-tests
- name: Collect artifacts ${{ matrix.environment.vmm }}
if: always()
run: bash tests/integration/kubernetes/gha-run.sh collect-artifacts

View File

@@ -75,3 +75,7 @@ jobs:
- name: Run tests
timeout-minutes: 30
run: bash tests/integration/kubernetes/gha-run.sh run-tests
- name: Report tests
if: always()
run: bash tests/integration/kubernetes/gha-run.sh report-tests

View File

@@ -131,6 +131,10 @@ jobs:
timeout-minutes: 60
run: bash tests/integration/kubernetes/gha-run.sh run-tests
- name: Report tests
if: always()
run: bash tests/integration/kubernetes/gha-run.sh report-tests
- name: Delete kata-deploy
if: always()
run: bash tests/integration/kubernetes/gha-run.sh cleanup-zvsi

View File

@@ -140,6 +140,10 @@ jobs:
timeout-minutes: 300
run: bash tests/stability/gha-stability-run.sh run-tests
- name: Report tests
if: always()
run: bash tests/integration/kubernetes/gha-run.sh report-tests
- name: Refresh OIDC token in case access token expired
if: always()
uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0

View File

@@ -102,6 +102,10 @@ jobs:
- name: Run tests
run: bash tests/functional/kata-deploy/gha-run.sh run-tests
- name: Report tests
if: always()
run: bash tests/integration/kubernetes/gha-run.sh report-tests
- name: Refresh OIDC token in case access token expired
if: always()
uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0

View File

@@ -85,3 +85,7 @@ jobs:
- name: Run tests
run: bash tests/functional/kata-deploy/gha-run.sh run-tests
- name: Report tests
if: always()
run: bash tests/integration/kubernetes/gha-run.sh report-tests

View File

@@ -29,7 +29,7 @@ jobs:
matrix:
instance:
- "ubuntu-24.04-arm"
- "s390x"
- "ubuntu-24.04-s390x"
- "ubuntu-24.04-ppc64le"
uses: ./.github/workflows/build-checks.yaml
with:

1
.gitignore vendored
View File

@@ -18,3 +18,4 @@ src/tools/log-parser/kata-log-parser
tools/packaging/static-build/agent/install_libseccomp.sh
.envrc
.direnv
**/.DS_Store

View File

@@ -1 +1 @@
3.23.0
3.24.0

View File

@@ -83,3 +83,7 @@ Documents that help to understand and contribute to Kata Containers.
If you have a suggestion for how we can improve the
[website](https://katacontainers.io), please raise an issue (or a PR) on
[the repository that holds the source for the website](https://github.com/OpenStackweb/kata-netlify-refresh).
### Toolchain Guidance
* [Toolchain Guidance](./Toochain-Guidance.md)

39
docs/Toochain-Guidance.md Normal file
View File

@@ -0,0 +1,39 @@
# Toolchains
As a community we want to strike a balance between having up-to-date toolchains, to receive the
latest security fixes and to be able to benefit from new features and packages, whilst not being
too bleeding edge and disrupting downstream and other consumers. As a result we have the following
guidelines (note, not hard rules) for our go and rust toolchains that we are attempting to try out:
## Go toolchain
Go is released [every six months](https://go.dev/wiki/Go-Release-Cycle) with support for the
[last two major release versions](https://go.dev/doc/devel/release#policy). We always want to
ensure that we are on a supported version so we receive security fixes. To try and make
things easier for some of our users, we aim to be using the older of the two supported major
versions, unless there is a compelling reason to adopt the newer version.
In practice this means that we bump our major version of the go toolchain every six months to
version (1.x-1) in response to a new version (1.x) coming out, which makes our current version
(1.x-2) no longer supported. We will bump the minor version whenever required to satisfy
dependency updates, or security fixes.
Our go toolchain version is recorded in [`versions.yaml`](../versions.yaml) under
`.languages.golang.version` and should match with the version in our `go.mod` files.
## Rust toolchain
Rust has a [six week](https://doc.rust-lang.org/book/appendix-05-editions.html#:~:text=The%20Rust%20language%20and%20compiler,these%20tiny%20changes%20add%20up.)
release cycle and they only support the latest stable release, so if we wanted to remain on a
supported release we would only ever build with the latest stable and bump every 6 weeks.
However feedback from our community has indicated that this is a challenge as downstream consumers
often want to get rust from their distro, or downstream fork and these struggle to keep up with
the six week release schedule. As a result the community has agreed to try out a policy of
"stable-2", where we aim to build with a rust version that is two versions behind the latest stable
version.
In practice this should mean that we bump our rust toolchain every six weeks, to version
1.x-2 when 1.x is released as stable and we should be picking up the latest point release
of that version, if there were any.
The rust-toolchain that we are using is recorded in [`rust-toolchain.toml`](../rust-toolchain.toml).

View File

@@ -97,6 +97,8 @@ There are several kinds of Kata configurations and they are listed below.
| `io.katacontainers.config.hypervisor.use_legacy_serial` | `boolean` | uses legacy serial device for guest's console (QEMU) |
| `io.katacontainers.config.hypervisor.default_gpus` | uint32 | the minimum number of GPUs required for the VM. Only used by remote hypervisor to help with instance selection |
| `io.katacontainers.config.hypervisor.default_gpu_model` | string | the GPU model required for the VM. Only used by remote hypervisor to help with instance selection |
| `io.katacontainers.config.hypervisor.block_device_num_queues` | `usize` | The number of queues to use for block devices (runtime-rs only) |
| `io.katacontainers.config.hypervisor.block_device_queue_size` | uint32 | The size of the of the queue to use for block devices (runtime-rs only) |
## Container Options
| Key | Value Type | Comments |

View File

@@ -186,7 +186,7 @@ base64 = "0.22"
sha2 = "0.10.8"
async-compression = { version = "0.4.22", features = ["tokio", "gzip"] }
container-device-interface = "0.1.0"
container-device-interface = "0.1.1"
[target.'cfg(target_arch = "s390x")'.dependencies]
pv_core = { git = "https://github.com/ibm-s390-linux/s390-tools", rev = "4942504a9a2977d49989a5e5b7c1c8e07dc0fa41", package = "s390_pv_core" }

View File

@@ -401,11 +401,10 @@ impl Handle {
}
if let RouteAttribute::Oif(index) = attribute {
route.device = self
.find_link(LinkFilter::Index(*index))
.await
.context(format!("error looking up device {index}"))?
.name();
route.device = match self.find_link(LinkFilter::Index(*index)).await {
Ok(link) => link.name(),
Err(_) => String::new(),
};
}
}
@@ -1005,10 +1004,6 @@ mod tests {
.expect("Failed to list routes");
assert_ne!(all.len(), 0);
for r in &all {
assert_ne!(r.device.len(), 0);
}
}
#[tokio::test]

View File

@@ -283,6 +283,13 @@ pub const KATA_ANNO_CFG_HYPERVISOR_DEFAULT_GPUS: &str =
pub const KATA_ANNO_CFG_HYPERVISOR_DEFAULT_GPU_MODEL: &str =
"io.katacontainers.config.hypervisor.default_gpu_model";
/// Block device specific annotation for num_queues
pub const KATA_ANNO_CFG_HYPERVISOR_BLOCK_DEV_NUM_QUEUES: &str =
"io.katacontainers.config.hypervisor.block_device_num_queues";
/// Block device specific annotation for queue_size
pub const KATA_ANNO_CFG_HYPERVISOR_BLOCK_DEV_QUEUE_SIZE: &str =
"io.katacontainers.config.hypervisor.block_device_queue_size";
// Runtime related annotations
/// Prefix for Runtime configurations.
pub const KATA_ANNO_CFG_RUNTIME_PREFIX: &str = "io.katacontainers.config.runtime.";
@@ -503,6 +510,7 @@ impl Annotation {
let u32_err = io::Error::new(io::ErrorKind::InvalidData, "parse u32 error".to_string());
let u64_err = io::Error::new(io::ErrorKind::InvalidData, "parse u64 error".to_string());
let i32_err = io::Error::new(io::ErrorKind::InvalidData, "parse i32 error".to_string());
let usize_err = io::Error::new(io::ErrorKind::InvalidData, "parse usize error".to_string());
let hv = config.hypervisor.get_mut(hypervisor_name).ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidData,
@@ -960,7 +968,26 @@ impl Annotation {
return Err(u32_err);
}
},
KATA_ANNO_CFG_HYPERVISOR_BLOCK_DEV_NUM_QUEUES => {
match self.get_value::<usize>(key) {
Ok(v) => {
hv.blockdev_info.num_queues = v.unwrap_or_default();
}
Err(_e) => {
return Err(usize_err);
}
}
}
KATA_ANNO_CFG_HYPERVISOR_BLOCK_DEV_QUEUE_SIZE => {
match self.get_value::<u32>(key) {
Ok(v) => {
hv.blockdev_info.queue_size = v.unwrap_or_default();
}
Err(_e) => {
return Err(u32_err);
}
}
}
_ => {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,

View File

@@ -85,11 +85,6 @@ impl ConfigPlugin for CloudHypervisorConfig {
if ch.memory_info.memory_slots == 0 {
ch.memory_info.memory_slots = default::DEFAULT_CH_MEMORY_SLOTS;
}
// Apply factory defaults
if ch.factory.template_path.is_empty() {
ch.factory.template_path = default::DEFAULT_TEMPLATE_PATH.to_string();
}
}
Ok(())

View File

@@ -79,11 +79,6 @@ impl ConfigPlugin for DragonballConfig {
if db.memory_info.memory_slots == 0 {
db.memory_info.memory_slots = default::DEFAULT_DRAGONBALL_MEMORY_SLOTS;
}
// Apply factory defaults
if db.factory.template_path.is_empty() {
db.factory.template_path = default::DEFAULT_TEMPLATE_PATH.to_string();
}
}
Ok(())
}

View File

@@ -69,11 +69,6 @@ impl ConfigPlugin for FirecrackerConfig {
firecracker.memory_info.default_memory =
default::DEFAULT_FIRECRACKER_MEMORY_SIZE_MB;
}
// Apply factory defaults
if firecracker.factory.template_path.is_empty() {
firecracker.factory.template_path = default::DEFAULT_TEMPLATE_PATH.to_string();
}
}
Ok(())

View File

@@ -92,7 +92,6 @@ impl ConfigPlugin for QemuConfig {
qemu.memory_info.memory_slots = default::DEFAULT_QEMU_MEMORY_SLOTS;
}
// Apply factory defaults
if qemu.factory.template_path.is_empty() {
qemu.factory.template_path = default::DEFAULT_TEMPLATE_PATH.to_string();
}

View File

@@ -25,6 +25,7 @@ pub enum Error {
}
/// Assigned CPU resources for a Linux container.
/// Stores fractional vCPU allocation for more precise resource tracking.
#[derive(Clone, Default, Debug)]
pub struct LinuxContainerCpuResources {
shares: u64,
@@ -32,7 +33,8 @@ pub struct LinuxContainerCpuResources {
quota: i64,
cpuset: CpuSet,
nodeset: NumaNodeSet,
calculated_vcpu_time_ms: Option<u64>,
/// Calculated fractional vCPU allocation, e.g., 0.25 means 1/4 of a CPU.
calculated_vcpu: Option<f64>,
}
impl LinuxContainerCpuResources {
@@ -61,10 +63,10 @@ impl LinuxContainerCpuResources {
&self.nodeset
}
/// Get number of vCPUs to fulfill the CPU resource request, `None` means unconstrained.
pub fn get_vcpus(&self) -> Option<u64> {
self.calculated_vcpu_time_ms
.map(|v| v.saturating_add(999) / 1000)
/// Get the number of vCPUs assigned to the container as a fractional value.
/// Returns `None` if unconstrained (no limit).
pub fn get_vcpus(&self) -> Option<f64> {
self.calculated_vcpu
}
}
@@ -75,15 +77,18 @@ impl TryFrom<&oci::LinuxCpu> for LinuxContainerCpuResources {
fn try_from(value: &oci::LinuxCpu) -> Result<Self, Self::Error> {
let period = value.period().unwrap_or(0);
let quota = value.quota().unwrap_or(-1);
let value_cpus = value.cpus().as_ref().map_or("", |cpus| cpus);
let value_cpus = value.cpus().as_deref().unwrap_or("");
let cpuset = CpuSet::from_str(value_cpus).map_err(Error::InvalidCpuSet)?;
let value_mems = value.mems().as_ref().map_or("", |mems| mems);
let value_mems = value.mems().as_deref().unwrap_or("");
let nodeset = NumaNodeSet::from_str(value_mems).map_err(Error::InvalidNodeSet)?;
// If quota is -1, it means the CPU resource request is unconstrained. In that case,
// we don't currently assign additional CPUs.
let milli_sec = if quota >= 0 && period != 0 {
Some((quota as u64).saturating_mul(1000) / period)
// Calculate fractional vCPUs:
// If quota >= 0 and period > 0, vCPUs = quota / period.
// Otherwise, if cpuset is non-empty, derive from cpuset length.
let vcpu_fraction = if quota >= 0 && period > 0 {
Some(quota as f64 / period as f64)
} else if !cpuset.is_empty() {
Some(cpuset.len() as f64)
} else {
None
};
@@ -94,16 +99,18 @@ impl TryFrom<&oci::LinuxCpu> for LinuxContainerCpuResources {
quota,
cpuset,
nodeset,
calculated_vcpu_time_ms: milli_sec,
calculated_vcpu: vcpu_fraction,
})
}
}
/// Assigned CPU resources for a Linux sandbox/pod.
/// Aggregated CPU resources for a Linux sandbox/pod.
/// Tracks cumulative fractional vCPU allocation across all containers in the pod.
#[derive(Default, Debug)]
pub struct LinuxSandboxCpuResources {
shares: u64,
calculated_vcpu_time_ms: u64,
/// Total fractional vCPU allocation for the sandbox.
calculated_vcpu: f64,
cpuset: CpuSet,
nodeset: NumaNodeSet,
}
@@ -122,9 +129,9 @@ impl LinuxSandboxCpuResources {
self.shares
}
/// Get assigned vCPU time in ms.
pub fn calculated_vcpu_time_ms(&self) -> u64 {
self.calculated_vcpu_time_ms
/// Return the cumulative fractional vCPU allocation for the sandbox.
pub fn calculated_vcpu(&self) -> f64 {
self.calculated_vcpu
}
/// Get the CPU set.
@@ -137,19 +144,23 @@ impl LinuxSandboxCpuResources {
&self.nodeset
}
/// Get number of vCPUs to fulfill the CPU resource request.
pub fn get_vcpus(&self) -> u64 {
if self.calculated_vcpu_time_ms == 0 && !self.cpuset.is_empty() {
self.cpuset.len() as u64
} else {
self.calculated_vcpu_time_ms.saturating_add(999) / 1000
/// Get the number of vCPUs for the sandbox as a fractional value.
/// If no quota and cpuset is defined, return cpuset length as float.
pub fn get_vcpus(&self) -> f64 {
if self.calculated_vcpu == 0.0 {
if !self.cpuset.is_empty() {
return self.cpuset.len() as f64;
}
return 0.0;
}
self.calculated_vcpu
}
/// Merge resources assigned to a container into the sandbox/pod resources.
/// Merge container CPU resources into this sandbox CPU resource object.
/// Aggregates fractional vCPU allocation and extends cpuset/nodeset.
pub fn merge(&mut self, container_resource: &LinuxContainerCpuResources) -> &mut Self {
if let Some(v) = container_resource.calculated_vcpu_time_ms.as_ref() {
self.calculated_vcpu_time_ms += v;
if let Some(v) = container_resource.calculated_vcpu {
self.calculated_vcpu += v;
}
self.cpuset.extend(&container_resource.cpuset);
self.nodeset.extend(&container_resource.nodeset);
@@ -160,16 +171,16 @@ impl LinuxSandboxCpuResources {
#[cfg(test)]
mod tests {
use super::*;
const EPSILON: f64 = 0.0001;
#[test]
fn test_linux_container_cpu_resources() {
let resources = LinuxContainerCpuResources::default();
assert_eq!(resources.shares(), 0);
assert_eq!(resources.calculated_vcpu_time_ms, None);
assert!(resources.cpuset.is_empty());
assert!(resources.nodeset.is_empty());
assert!(resources.calculated_vcpu_time_ms.is_none());
assert!(resources.get_vcpus().is_none());
let mut linux_cpu = oci::LinuxCpu::default();
linux_cpu.set_shares(Some(2048));
@@ -182,11 +193,20 @@ mod tests {
assert_eq!(resources.shares(), 2048);
assert_eq!(resources.period(), 100);
assert_eq!(resources.quota(), 1001);
assert_eq!(resources.calculated_vcpu_time_ms, Some(10010));
assert_eq!(resources.get_vcpus().unwrap(), 11);
// Expected fractional vCPUs = quota / period
let expected_vcpus = 1001.0 / 100.0;
assert!(
(resources.get_vcpus().unwrap() - expected_vcpus).abs() < EPSILON,
"got {}, expect {}",
resources.get_vcpus().unwrap(),
expected_vcpus
);
assert_eq!(resources.cpuset().len(), 3);
assert_eq!(resources.nodeset().len(), 1);
// Test cpuset-only path (no quota)
let mut linux_cpu = oci::LinuxCpu::default();
linux_cpu.set_shares(Some(2048));
linux_cpu.set_cpus(Some("1".to_string()));
@@ -196,8 +216,10 @@ mod tests {
assert_eq!(resources.shares(), 2048);
assert_eq!(resources.period(), 0);
assert_eq!(resources.quota(), -1);
assert_eq!(resources.calculated_vcpu_time_ms, None);
assert!(resources.get_vcpus().is_none());
assert!(
(resources.get_vcpus().unwrap() - 1.0).abs() < EPSILON,
"cpuset size vCPU mismatch"
);
assert_eq!(resources.cpuset().len(), 1);
assert_eq!(resources.nodeset().len(), 2);
}
@@ -207,8 +229,7 @@ mod tests {
let mut sandbox = LinuxSandboxCpuResources::new(1024);
assert_eq!(sandbox.shares(), 1024);
assert_eq!(sandbox.get_vcpus(), 0);
assert_eq!(sandbox.calculated_vcpu_time_ms(), 0);
assert_eq!(sandbox.get_vcpus(), 0.0);
assert!(sandbox.cpuset().is_empty());
assert!(sandbox.nodeset().is_empty());
@@ -222,11 +243,20 @@ mod tests {
let resources = LinuxContainerCpuResources::try_from(&linux_cpu).unwrap();
sandbox.merge(&resources);
assert_eq!(sandbox.shares(), 1024);
assert_eq!(sandbox.get_vcpus(), 11);
assert_eq!(sandbox.calculated_vcpu_time_ms(), 10010);
// vCPUs after merge = quota / period
let expected_vcpus = 1001.0 / 100.0;
assert!(
(sandbox.get_vcpus() - expected_vcpus).abs() < EPSILON,
"sandbox vCPU mismatch: got {}, expect {}",
sandbox.get_vcpus(),
expected_vcpus
);
assert_eq!(sandbox.cpuset().len(), 3);
assert_eq!(sandbox.nodeset().len(), 1);
// Merge cpuset-only container
let mut linux_cpu = oci::LinuxCpu::default();
linux_cpu.set_shares(Some(2048));
linux_cpu.set_cpus(Some("1,4".to_string()));
@@ -236,8 +266,15 @@ mod tests {
sandbox.merge(&resources);
assert_eq!(sandbox.shares(), 1024);
assert_eq!(sandbox.get_vcpus(), 11);
assert_eq!(sandbox.calculated_vcpu_time_ms(), 10010);
// Expect quota-based + cpuset len (since cpuset is treated as allocation)
let expected_after_merge = expected_vcpus + resources.get_vcpus().unwrap();
assert!(
(sandbox.get_vcpus() - expected_after_merge).abs() < EPSILON,
"sandbox vCPU mismatch after cpuset merge: got {}, expect {}",
sandbox.get_vcpus(),
expected_after_merge
);
assert_eq!(sandbox.cpuset().len(), 4);
assert_eq!(sandbox.nodeset().len(), 2);
}

View File

@@ -2590,55 +2590,37 @@ dependencies = [
[[package]]
name = "netlink-packet-core"
version = "0.7.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4"
checksum = "3463cbb78394cb0141e2c926b93fc2197e473394b761986eca3b9da2c63ae0f4"
dependencies = [
"anyhow",
"byteorder",
"netlink-packet-utils",
"paste",
]
[[package]]
name = "netlink-packet-route"
version = "0.22.0"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0e7987b28514adf555dc1f9a5c30dfc3e50750bbaffb1aec41ca7b23dcd8e4"
checksum = "9ea06a7cec15a9df94c58bddc472b1de04ca53bd32e72da7da2c5dd1c3885edc"
dependencies = [
"anyhow",
"bitflags 2.9.0",
"byteorder",
"libc",
"log",
"netlink-packet-core",
"netlink-packet-utils",
]
[[package]]
name = "netlink-packet-utils"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34"
dependencies = [
"anyhow",
"byteorder",
"paste",
"thiserror 1.0.69",
]
[[package]]
name = "netlink-proto"
version = "0.11.3"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b33524dc0968bfad349684447bfce6db937a9ac3332a1fe60c0c5a5ce63f21"
checksum = "b65d130ee111430e47eed7896ea43ca693c387f097dd97376bffafbf25812128"
dependencies = [
"bytes",
"futures 0.3.28",
"log",
"netlink-packet-core",
"netlink-sys",
"thiserror 1.0.69",
"tokio",
"thiserror 2.0.11",
]
[[package]]
@@ -3948,18 +3930,18 @@ dependencies = [
[[package]]
name = "rtnetlink"
version = "0.16.0"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cb5850b5aa2c9c0ae44f157694bbe85107a2e13d76eb3178d0e3ee96c410f57"
checksum = "1f3ee907fdcec9200d13b9cdb64dfc8179cb4ac16ead6ae0ac76333dc41981fc"
dependencies = [
"futures 0.3.28",
"futures-channel",
"futures-util",
"log",
"netlink-packet-core",
"netlink-packet-route",
"netlink-packet-utils",
"netlink-proto",
"netlink-sys",
"nix 0.29.0",
"nix 0.30.1",
"thiserror 1.0.69",
"tokio",
]

View File

@@ -150,8 +150,8 @@ DEFMEMSLOTS := 10
DEFMAXMEMSZ := 0
##VAR DEFBRIDGES=<number> Default number of bridges
DEFBRIDGES := 0
DEFENABLEANNOTATIONS := [\"kernel_params\"]
DEFENABLEANNOTATIONS_COCO := [\"kernel_params\",\"cc_init_data\"]
DEFENABLEANNOTATIONS := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"default_vcpus\", \"default_memory\"]
DEFENABLEANNOTATIONS_COCO := [\"enable_iommu\", \"virtio_fs_extra_args\", \"kernel_params\", \"default_vcpus\", \"default_memory\", \"cc_init_data\"]
DEFDISABLEGUESTSECCOMP := true
DEFDISABLEGUESTEMPTYDIR := false
##VAR DEFAULTEXPFEATURES=[features] Default experimental features enabled
@@ -328,7 +328,7 @@ ifneq (,$(QEMUCMD))
KERNELPATH_COCO = $(KERNELDIR)/$(KERNEL_NAME_COCO)
# overriding options
DEFSTATICRESOURCEMGMT_QEMU := true
DEFSTATICRESOURCEMGMT_QEMU := false
# qemu-specific options
DEFSANDBOXCGROUPONLY_QEMU := false

View File

@@ -263,20 +263,6 @@ tx_rate_limiter_max_rate = 0
# disable applying SELinux on the VMM process (default false)
disable_selinux = @DEFDISABLESELINUX@
[factory]
# VM templating support. Once enabled, new VMs are created from template
# using vm cloning. They will share the same initial kernel, initramfs and
# agent memory by mapping it readonly. It helps speeding up new container
# creation and saves a lot of memory if there are many kata containers running
# on the same host.
#
# When disabled, new VMs are created from scratch.
#
# Note: Requires "initrd=" to be set ("image=" is not supported).
#
# Default false
enable_template = false
[agent.@PROJECT_TYPE@]
# If enabled, make the agent display debug-level messages.
# (default: disabled)

View File

@@ -40,9 +40,9 @@ tempfile = "3.19.1"
hex = "0.4"
## Dependencies from `rust-netlink`
netlink-packet-route = "0.22"
netlink-packet-route = "0.26"
netlink-sys = "0.8"
rtnetlink = "0.16"
rtnetlink = "0.19"
# Local dependencies
agent = { workspace = true }

View File

@@ -10,7 +10,6 @@ use kata_types::{config::TomlConfig, cpu::LinuxContainerCpuResources};
use oci::LinuxCpu;
use oci_spec::runtime as oci;
use std::{
cmp,
collections::{HashMap, HashSet},
convert::TryFrom,
sync::Arc,
@@ -22,7 +21,7 @@ use crate::ResourceUpdateOp;
#[derive(Default, Debug, Clone)]
pub struct CpuResource {
/// Current number of vCPUs
pub(crate) current_vcpu: Arc<RwLock<u32>>,
pub(crate) current_vcpu: Arc<RwLock<f32>>,
/// Default number of vCPUs
pub(crate) default_vcpu: f32,
@@ -39,7 +38,7 @@ impl CpuResource {
.get(&hypervisor_name)
.context(format!("failed to get hypervisor {}", hypervisor_name))?;
Ok(Self {
current_vcpu: Arc::new(RwLock::new(hypervisor_config.cpu_info.default_vcpus as u32)),
current_vcpu: Arc::new(RwLock::new(hypervisor_config.cpu_info.default_vcpus)),
default_vcpu: hypervisor_config.cpu_info.default_vcpus,
container_cpu_resources: Arc::new(RwLock::new(HashMap::new())),
})
@@ -71,14 +70,14 @@ impl CpuResource {
Ok(())
}
pub(crate) async fn current_vcpu(&self) -> u32 {
pub(crate) async fn current_vcpu(&self) -> f32 {
let current_vcpu = self.current_vcpu.read().await;
*current_vcpu
}
async fn update_current_vcpu(&self, new_vcpus: u32) {
let mut current_vcpu = self.current_vcpu.write().await;
*current_vcpu = new_vcpus;
*current_vcpu = new_vcpus as f32;
}
// update container_cpu_resources field
@@ -116,10 +115,11 @@ impl CpuResource {
}
// calculates the total required vcpus by adding each container's requirements within the pod
async fn calc_cpu_resources(&self) -> Result<u32> {
async fn calc_cpu_resources(&self) -> Result<f32> {
let resources = self.container_cpu_resources.read().await;
if resources.is_empty() {
return Ok(self.default_vcpu.ceil() as u32);
// No containers, just keep the default vCPU configuration
return Ok(self.default_vcpu);
}
// If requests of individual containers are expresses with different
@@ -128,6 +128,7 @@ impl CpuResource {
// to use the largest period as the common denominator since it
// shifts precision out of the fractional part and into the
// integral part in case a rewritten quota ends up non-integral.
// Determine the largest CPU period among containers, will be used to normalize quotas
let max_period = resources
.iter()
.map(|(_, cpu_resource)| cpu_resource.period())
@@ -155,53 +156,74 @@ impl CpuResource {
let quota = cpu_resource.quota() as f64;
let period = cpu_resource.period() as f64;
if quota >= 0.0 && period != 0.0 {
if quota >= 0.0 && period > 0.0 {
// Normalize to max_period before adding quotas
total_quota += quota * (max_period / period);
}
}
// contrained only by cpuset
// constrained only by cpuset (no quota set)
if total_quota == 0.0 && !cpuset_vcpu.is_empty() {
info!(sl!(), "(from cpuset)get vcpus # {:?}", cpuset_vcpu);
return Ok(cpuset_vcpu.len() as u32);
return Ok(cpuset_vcpu.len() as f32);
}
let total_vcpu = if total_quota > 0.0 && max_period != 0.0 {
self.default_vcpu as f64 + total_quota / max_period
} else {
self.default_vcpu as f64
};
// When quota is set: calculate vCPUs as quota/period after normalization
if total_quota > 0.0 && max_period > 0.0 {
let quota_vcpu = total_quota / max_period;
info!(
sl!(),
"(from cfs_quota&cfs_period) target vcpus {} from quota {} max_period {}",
quota_vcpu,
total_quota,
max_period
);
info!(
sl!(),
"(from cfs_quota&cfs_period)get vcpus count {}", total_vcpu
);
Ok(total_vcpu.ceil() as u32)
let total_vcpu = quota_vcpu as f32 + self.default_vcpu;
return Ok(total_vcpu);
}
// Default case: no quota, no cpuset: use default_vcpu
Ok(self.default_vcpu.max(1.0))
}
// do hotplug and hot-unplug the vcpu
async fn do_update_cpu_resources(
&self,
new_vcpus: u32,
new_vcpus: f32,
op: ResourceUpdateOp,
hypervisor: &dyn Hypervisor,
) -> Result<u32> {
let old_vcpus = self.current_vcpu().await;
// when adding vcpus, ignore old_vcpus > new_vcpus
// when deleting vcpus, ignore old_vcpus < new_vcpus
// Prevent decreasing vCPUs on an Add operation or increasing on a Delete
if (op == ResourceUpdateOp::Add && old_vcpus > new_vcpus)
|| (op == ResourceUpdateOp::Del && old_vcpus < new_vcpus)
{
return Ok(old_vcpus);
return Ok(old_vcpus.ceil() as u32);
}
// do not reduce computing power
// the number of vcpus would not be lower than the default size
let new_vcpus = cmp::max(new_vcpus, self.default_vcpu.ceil() as u32);
// Enforce minimum of 1 vCPU for the VM
let min_vcpus = 1.0_f32;
let target_vcpus = if new_vcpus < min_vcpus {
min_vcpus
} else {
new_vcpus
};
// Hypervisor only supports integer vCPU counts round up at the last step
let target_vcpus_int = target_vcpus.ceil() as u32;
info!(
sl!(),
"(do_update_cpu_resources) old_vcpus {} -> new_vcpus {} (ceil to {})",
old_vcpus,
new_vcpus,
target_vcpus_int
);
let (_, new) = hypervisor
.resize_vcpu(old_vcpus, new_vcpus)
.resize_vcpu(old_vcpus.ceil() as u32, target_vcpus_int)
.await
.context("resize vcpus")?;
@@ -225,6 +247,7 @@ mod tests {
.entry("qemu".to_owned())
.and_modify(|hv_config| hv_config.cpu_info.default_vcpus = default_vcpus);
config.runtime.hypervisor_name = "qemu".to_owned();
CpuResource::new(Arc::new(config)).unwrap()
}
@@ -251,31 +274,15 @@ mod tests {
// result of 0.99999999999999989) but it still doesn't guarantee the
// correct result in general. For instance, adding 0.1 twenty times
// in 64 bits results in 2.0000000000000004.
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
(100_000, 1_000_000),
],
)
.await;
add_linux_container_cpu_resources(&mut cpu_resource, vec![(100_000, 1_000_000); 10]).await;
assert_eq!(cpu_resource.calc_cpu_resources().await.unwrap(), 1);
// 10 * 0.1 = 1.0: matches expected vCPU sum (float-safe in f64)
assert_eq!(cpu_resource.calc_cpu_resources().await.unwrap(), 1.0);
}
#[tokio::test]
async fn test_big_allocation_1() {
let default_vcpus = 10.0;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
let mut cpu_resource = get_cpu_resource_with_default_vcpus(10.0);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![
@@ -286,16 +293,20 @@ mod tests {
)
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
128 + default_vcpus as u32
const EPSILON: f32 = 0.0001;
let actual = cpu_resource.calc_cpu_resources().await.unwrap();
let expected = 138.0;
assert!(
(actual - expected).abs() < EPSILON,
"got {}, expect {}",
actual,
expected
);
}
#[tokio::test]
async fn test_big_allocation_2() {
let default_vcpus = 10.0;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
let mut cpu_resource = get_cpu_resource_with_default_vcpus(10.0);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![
@@ -306,98 +317,114 @@ mod tests {
)
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
(33 + 31 + 77 + 1) + default_vcpus as u32
const EPSILON: f32 = 0.0001;
let actual = cpu_resource.calc_cpu_resources().await.unwrap();
let expected = 151.0;
assert!(
(actual - expected).abs() < EPSILON,
"got {}, expect {}",
actual,
expected
);
}
#[tokio::test]
async fn test_big_allocation_3() {
let default_vcpus = 10.0;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
let mut cpu_resource = get_cpu_resource_with_default_vcpus(10.0);
add_linux_container_cpu_resources(&mut cpu_resource, vec![(141_000_008, 1_000_000)]).await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
142 + default_vcpus as u32
// 141 + 1(response to hypervisor ceil handling, still in calc we keep float)
const EPSILON: f32 = 0.0001;
let actual = cpu_resource.calc_cpu_resources().await.unwrap();
let expected = 151.0;
assert!(
(actual - expected).abs() < EPSILON,
"got {}, expect {}",
actual,
expected
);
}
#[tokio::test]
async fn test_big_allocation_4() {
let default_vcpus = 10.0;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![
(17_000_001, 1_000_000),
(17_000_001, 1_000_000),
(17_000_001, 1_000_000),
(17_000_001, 1_000_000),
],
)
.await;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(10.0);
add_linux_container_cpu_resources(&mut cpu_resource, vec![(17_000_001, 1_000_000); 4])
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
(4 * 17 + 1) + default_vcpus as u32
const EPSILON: f32 = 0.0001;
let actual = cpu_resource.calc_cpu_resources().await.unwrap();
let expected = 78.0;
assert!(
(actual - expected).abs() < EPSILON,
"got {}, expect {}",
actual,
expected
);
}
#[tokio::test]
async fn test_divisible_periods() {
let default_vcpus = 3.0;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
let mut cpu_resource = get_cpu_resource_with_default_vcpus(3.0);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![(1_000_000, 1_000_000), (1_000_000, 500_000)],
)
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
3 + default_vcpus as u32
);
// periods normalized: second gets * 2 quota. total=1+2=3
assert_eq!(cpu_resource.calc_cpu_resources().await.unwrap(), 6.0);
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
let mut cpu_resource = get_cpu_resource_with_default_vcpus(3.0);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![(3_000_000, 1_500_000), (1_000_000, 500_000)],
)
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
4 + default_vcpus as u32
);
// normalized: first quota=2, second quota=2. total=4
assert_eq!(cpu_resource.calc_cpu_resources().await.unwrap(), 7.0);
}
#[tokio::test]
async fn test_indivisible_periods() {
let default_vcpus = 1.0;
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
const EPSILON: f32 = 0.0001;
// Case 1
let mut cpu_resource = get_cpu_resource_with_default_vcpus(1.0);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![(1_000_000, 1_000_000), (900_000, 300_000)],
)
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
4 + default_vcpus as u32
let actual = cpu_resource.calc_cpu_resources().await.unwrap();
let expected = 5.0; // pure quota sum, no default_vcpu added
assert!(
(actual - expected).abs() < EPSILON,
"case1: got {}, expect {}",
actual,
expected
);
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
// Case 2
let mut cpu_resource = get_cpu_resource_with_default_vcpus(1.0);
add_linux_container_cpu_resources(
&mut cpu_resource,
vec![(1_000_000, 1_000_000), (900_000, 299_999)],
)
.await;
assert_eq!(
cpu_resource.calc_cpu_resources().await.unwrap(),
5 + default_vcpus as u32
let actual = cpu_resource.calc_cpu_resources().await.unwrap();
// total_quota = 1_000_000 + (900_000 * (1_000_000 / 299_999))
// total_vcpus = total_quota / 1_000_000
let expected = (1_000_000.0 + (900_000.0 * (1_000_000.0 / 299_999.0))) / 1_000_000.0 + 1.0;
assert!(
(actual - expected as f32).abs() < EPSILON,
"case2: got {}, expect {}",
actual,
expected
);
}
@@ -407,17 +434,18 @@ mod tests {
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(&mut cpu_resource, vec![(250_000, 1_000_000)]).await;
assert_eq!(cpu_resource.calc_cpu_resources().await.unwrap(), 1);
assert_eq!(cpu_resource.calc_cpu_resources().await.unwrap(), 0.75);
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(&mut cpu_resource, vec![(500_000, 1_000_000)]).await;
assert_eq!(cpu_resource.calc_cpu_resources().await.unwrap(), 1);
assert_eq!(cpu_resource.calc_cpu_resources().await.unwrap(), 1.0);
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(&mut cpu_resource, vec![(500_001, 1_000_000)]).await;
assert_eq!(cpu_resource.calc_cpu_resources().await.unwrap(), 2);
let mut cpu_resource = get_cpu_resource_with_default_vcpus(default_vcpus);
add_linux_container_cpu_resources(&mut cpu_resource, vec![(500_001, 1_000_000)]).await;
assert_eq!(cpu_resource.calc_cpu_resources().await.unwrap(), 1.000001);
// This test doesn't pass because 0.1 is periodic in binary and thus
// not exactly representable by a float of any width for fundamental

View File

@@ -17,7 +17,7 @@ use oci_spec::runtime as oci;
// sandbox/container's workload
#[derive(Clone, Copy, Debug)]
struct InitialSize {
vcpu: u32,
vcpu: f32,
mem_mb: u32,
orig_toml_default_mem: u32,
}
@@ -28,7 +28,7 @@ const MIB: i64 = 1024 * 1024;
impl TryFrom<&HashMap<String, String>> for InitialSize {
type Error = anyhow::Error;
fn try_from(an: &HashMap<String, String>) -> Result<Self> {
let mut vcpu: u32 = 0;
let mut vcpu: f32 = 0.0;
let annotation = Annotation::new(an.clone());
let (period, quota, memory) =
@@ -56,7 +56,7 @@ impl TryFrom<&HashMap<String, String>> for InitialSize {
impl TryFrom<&oci::Spec> for InitialSize {
type Error = anyhow::Error;
fn try_from(spec: &oci::Spec) -> Result<Self> {
let mut vcpu: u32 = 0;
let mut vcpu: f32 = 0.0;
let mut mem_mb: u32 = 0;
match container_type(spec) {
// podsandbox, from annotation
@@ -140,8 +140,8 @@ impl InitialSizeManager {
.get_mut(hypervisor_name)
.context("failed to get hypervisor config")?;
if self.resource.vcpu > 0 {
hv.cpu_info.default_vcpus = self.resource.vcpu as f32
if self.resource.vcpu > 0.0 {
info!(sl!(), "resource with vcpu {}", self.resource.vcpu);
}
self.resource.orig_toml_default_mem = hv.memory_info.default_memory;
if self.resource.mem_mb > 0 {
@@ -160,11 +160,11 @@ impl InitialSizeManager {
}
}
fn get_nr_vcpu(resource: &LinuxContainerCpuResources) -> u32 {
fn get_nr_vcpu(resource: &LinuxContainerCpuResources) -> f32 {
if let Some(v) = resource.get_vcpus() {
v as u32
v as f32
} else {
0
0.0
}
}
@@ -223,7 +223,7 @@ mod tests {
memory: None,
},
result: InitialSize {
vcpu: 0,
vcpu: 0.0,
mem_mb: 0,
orig_toml_default_mem: 0,
},
@@ -237,7 +237,7 @@ mod tests {
memory: Some(512 * MIB),
},
result: InitialSize {
vcpu: 3,
vcpu: 3.0,
mem_mb: 512,
orig_toml_default_mem: 0,
},
@@ -250,7 +250,7 @@ mod tests {
memory: Some(513 * MIB),
},
result: InitialSize {
vcpu: 0,
vcpu: 0.0,
mem_mb: 514,
orig_toml_default_mem: 0,
},
@@ -295,9 +295,12 @@ mod tests {
let initial_size = initial_size.unwrap();
assert_eq!(
initial_size.vcpu, d.result.vcpu,
initial_size.vcpu.ceil(),
d.result.vcpu,
"test[{}]: {:?} vcpu should be {}",
i, d.desc, d.result.vcpu,
i,
d.desc,
d.result.vcpu,
);
assert_eq!(
initial_size.mem_mb, d.result.mem_mb,
@@ -349,9 +352,12 @@ mod tests {
let initial_size = initial_size.unwrap();
assert_eq!(
initial_size.vcpu, d.result.vcpu,
initial_size.vcpu.ceil(),
d.result.vcpu,
"test[{}]: {:?} vcpu should be {}",
i, d.desc, d.result.vcpu,
i,
d.desc,
d.result.vcpu,
);
assert_eq!(
initial_size.mem_mb, d.result.mem_mb,

View File

@@ -592,7 +592,7 @@ impl ResourceManagerInner {
self.agent
.online_cpu_mem(OnlineCPUMemRequest {
wait: false,
nb_cpus: self.cpu_resource.current_vcpu().await,
nb_cpus: self.cpu_resource.current_vcpu().await.ceil() as u32,
cpu_only: false,
})
.await

View File

@@ -1,7 +1,7 @@
module github.com/kata-containers/kata-containers/src/runtime
// Keep in sync with version in versions.yaml
go 1.24.9
go 1.24.11
// WARNING: Do NOT use `replace` directives as those break dependabot:
// https://github.com/kata-containers/kata-containers/issues/11020
@@ -20,8 +20,8 @@ require (
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/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09
github.com/containernetworking/plugins v1.9.0
github.com/coreos/go-systemd/v22 v22.6.0
github.com/cri-o/cri-o v1.34.0
github.com/docker/go-units v0.5.0
github.com/fsnotify/fsnotify v1.9.0
@@ -46,11 +46,11 @@ require (
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/safchain/ethtool v0.6.2
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.11.1
github.com/urfave/cli v1.22.15
github.com/vishvananda/netlink v1.3.1-0.20250303224720-0e7078ed04c8
github.com/vishvananda/netlink v1.3.1
github.com/vishvananda/netns v0.0.5
gitlab.com/nvidia/cloud-native/go-nvlib v0.0.0-20220601114329-47893b162965
go.opentelemetry.io/otel v1.35.0
@@ -58,9 +58,9 @@ require (
go.opentelemetry.io/otel/sdk v1.35.0
go.opentelemetry.io/otel/trace v1.35.0
golang.org/x/oauth2 v0.30.0
golang.org/x/sys v0.34.0
golang.org/x/sys v0.35.0
google.golang.org/grpc v1.72.0
google.golang.org/protobuf v1.36.6
google.golang.org/protobuf v1.36.7
k8s.io/apimachinery v0.33.0
k8s.io/cri-api v0.33.0
k8s.io/kubelet v0.33.0
@@ -72,7 +72,7 @@ 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.13.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
@@ -92,7 +92,7 @@ require (
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/go-logr/logr v1.4.2 // indirect
github.com/go-logr/logr v1.4.3 // 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
@@ -132,9 +132,9 @@ require (
go.opentelemetry.io/otel/metric v1.35.0 // indirect
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
golang.org/x/mod v0.26.0 // indirect
golang.org/x/net v0.42.0 // indirect
golang.org/x/net v0.43.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/text v0.27.0 // indirect
golang.org/x/text v0.28.0 // indirect
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect

View File

@@ -11,10 +11,12 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
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/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
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.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA=
github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=
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=
@@ -64,10 +66,10 @@ github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++
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/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/containernetworking/plugins v1.9.0 h1:Mg3SXBdRGkdXyFC4lcwr6u2ZB2SDeL6LC3U+QrEANuQ=
github.com/containernetworking/plugins v1.9.0/go.mod h1:JG3BxoJifxxHBhG3hFyxyhid7JgRVBu/wtooGEvWf1c=
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
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=
@@ -100,8 +102,8 @@ github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXE
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/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/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/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=
@@ -130,7 +132,6 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8Wd
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/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=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
@@ -165,8 +166,8 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
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/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY=
github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U=
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=
@@ -229,13 +230,13 @@ 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.25.1 h1:Fwp6crTREKM+oA6Cz4MsO8RhKQzs2/gOIVOUscMAfZY=
github.com/onsi/ginkgo/v2 v2.25.1/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk=
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.38.1 h1:FaLA8GlcpXDwsb7m0h2A9ew2aTk3vnZMlzFgg5tz/pk=
github.com/onsi/gomega v1.38.1/go.mod h1:LfcV8wZLvwcYRwPiJysphKAEsmcFnLMK/9c+PjvlX8g=
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=
@@ -270,8 +271,8 @@ github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
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.6.2 h1:O3ZPFAKEUEfbtE6J/feEe2Ft7dIJ2Sy8t4SdMRiIMHY=
github.com/safchain/ethtool v0.6.2/go.mod h1:VS7cn+bP3Px3rIq55xImBiZGHVLNyBh5dqG6dDQy8+I=
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=
@@ -295,9 +296,8 @@ github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtse
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/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0=
github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=
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=
@@ -339,6 +339,8 @@ 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.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
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=
@@ -364,8 +366,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
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-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
@@ -395,15 +397,14 @@ golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBc
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.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
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.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
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=
@@ -413,8 +414,8 @@ 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.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
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=
@@ -446,8 +447,8 @@ 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.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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=

View File

@@ -15,6 +15,7 @@ import (
"github.com/container-orchestrated-devices/container-device-interface/pkg/cdi"
"github.com/go-ini/ini"
"github.com/kata-containers/kata-containers/src/runtime/pkg/device"
vcTypes "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
"github.com/opencontainers/runtime-spec/specs-go"
"golang.org/x/sys/unix"
@@ -431,6 +432,16 @@ type VFIODev struct {
HostPath string
}
// IOMMUFDID returns the IOMMUFD ID if the VFIO device is backed by IOMMUFD
// otherwise returns an empty string.
func (t VFIODev) IOMMUFDID() string {
if !strings.HasPrefix(t.DevfsDev, device.IommufdDevPath) {
return ""
}
basename := filepath.Base(t.DevfsDev)
return strings.TrimPrefix(basename, "vfio")
}
// RNGDev represents a random number generator device
type RNGDev struct {
// ID is used to identify the device in the hypervisor options.

View File

@@ -68,3 +68,24 @@ func TestGetSysDevPathImpl(t *testing.T) {
assert.Contains(path, expectedFormat)
assert.Contains(path, "block")
}
func TestIOMMUFDID(t *testing.T) {
for _, tc := range []struct {
devfsDev string
expected string
}{
{"/dev/vfio/42", ""},
{"/dev/vfio/devices/vfio99", "99"},
{"/dev/vfio/invalid", ""},
{"/dev/other/42", ""},
} {
t.Run(tc.devfsDev, func(t *testing.T) {
assert := assert.New(t)
info := VFIODev{
DevfsDev: "/dev/vfio/devices/vfio5",
}
assert.Equal("5", info.IOMMUFDID())
})
}
}

View File

@@ -0,0 +1,11 @@
// Copyright (c) 2017-2018 Intel Corporation
// Copyright (c) 2018 Huawei Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package device
const (
IommufdDevPath = "/dev/vfio/devices"
)

View File

@@ -160,7 +160,7 @@ func checkIgnorePCIClass(pciClass string, deviceBDF string, bitmask uint64) (boo
return false, nil
}
func getMajorMinorFromDevPath(devPath string) (uint32, uint32, error) {
func GetMajorMinorFromDevPath(devPath string) (uint32, uint32, error) {
fi, err := os.Stat(devPath)
if err != nil {
return 0, 0, err
@@ -181,7 +181,7 @@ func extractIndex(devicePath string) (string, error) {
return strings.TrimPrefix(base, prefix), nil
}
func getBdfFromVFIODev(major uint32, minor uint32) (string, error) {
func GetBDFFromVFIODev(major uint32, minor uint32) (string, error) {
devPath := fmt.Sprintf("/sys/dev/char/%d:%d", major, minor)
realPath, err := filepath.EvalSymlinks(devPath)
if err != nil {
@@ -203,13 +203,13 @@ func GetDeviceFromVFIODev(device config.DeviceInfo) ([]*config.VFIODev, error) {
// device major:minor entries in /sys/chart/major:minor
// $ ls -l /dev/vfio/devices/vfio0
// crw------- 1 root root 237, 0 Jan 15 16:53 /dev/vfio/devices/vfio0
major, minor, err := getMajorMinorFromDevPath(device.HostPath)
major, minor, err := GetMajorMinorFromDevPath(device.HostPath)
if err != nil {
return nil, fmt.Errorf("Failed to get major:minor from %s: %v", device.HostPath, err)
}
// $ ls -l /sys/dev/char/237:0
// /sys/dev/char/237:0 -> ../../devices/pci0000:64/0000:64:00.0/0000:65:00.0/vfio-dev/vfio0
deviceBDF, err := getBdfFromVFIODev(major, minor)
deviceBDF, err := GetBDFFromVFIODev(major, minor)
if err != nil {
return nil, err
}

View File

@@ -15,6 +15,7 @@ import (
"github.com/sirupsen/logrus"
pkgDevice "github.com/kata-containers/kata-containers/src/runtime/pkg/device"
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/api"
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/config"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
@@ -28,7 +29,6 @@ const (
iommuGroupPath = "/sys/bus/pci/devices/%s/iommu_group"
vfioDevPath = "/dev/vfio/%s"
vfioAPSysfsDir = "/sys/devices/vfio_ap"
IommufdDevPath = "/dev/vfio/devices"
)
// VFIODevice is a vfio device meant to be passed to the hypervisor
@@ -69,7 +69,7 @@ func (device *VFIODevice) Attach(ctx context.Context, devReceiver api.DeviceRece
// In the case of IOMMUFD the device.HostPath will look like
// /dev/vfio/devices/vfio0
// (1) Check if we have the new IOMMUFD or old container based VFIO
if strings.HasPrefix(device.DeviceInfo.HostPath, IommufdDevPath) {
if strings.HasPrefix(device.DeviceInfo.HostPath, pkgDevice.IommufdDevPath) {
device.VfioDevs, err = GetDeviceFromVFIODev(*device.DeviceInfo)
if err != nil {
return err

View File

@@ -27,7 +27,7 @@ import (
"strings"
"syscall"
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/drivers"
pkgDevice "github.com/kata-containers/kata-containers/src/runtime/pkg/device"
)
// Machine describes the machine type qemu will emulate.
@@ -2023,7 +2023,7 @@ func (vfioDev VFIODevice) QemuParams(config *Config) []string {
deviceParams = append(deviceParams, fmt.Sprintf("devno=%s", vfioDev.DevNo))
}
if strings.HasPrefix(vfioDev.DevfsDev, drivers.IommufdDevPath) {
if strings.HasPrefix(vfioDev.DevfsDev, pkgDevice.IommufdDevPath) {
qemuParams = append(qemuParams, "-object")
qemuParams = append(qemuParams, fmt.Sprintf("iommufd,id=iommufd%s", vfioDev.ID))
deviceParams = append(deviceParams, fmt.Sprintf("iommufd=iommufd%s", vfioDev.ID))

View File

@@ -43,6 +43,10 @@ type QMPLog interface {
// Errorf writes error output to the log. A newline will be
// added to the output if one is not provided.
Errorf(string, ...interface{})
// Debugf writes debug output to the log. A newline will be
// added to the output if one is not provided.
Debugf(string, ...interface{})
}
type qmpNullLogger struct{}
@@ -60,6 +64,9 @@ func (l qmpNullLogger) Warningf(format string, v ...interface{}) {
func (l qmpNullLogger) Errorf(format string, v ...interface{}) {
}
func (l qmpNullLogger) Debugf(format string, v ...interface{}) {
}
// QMPConfig is a configuration structure that can be used to specify a
// logger and a channel to which logs and QMP events are to be sent. If
// neither of these fields are specified, or are set to nil, no logs will be
@@ -653,6 +660,7 @@ func (q *QMP) executeCommandWithResponse(ctx context.Context, name string, args
func (q *QMP) executeCommand(ctx context.Context, name string, args map[string]interface{},
filter *qmpEventFilter) error {
q.cfg.Logger.Debugf("Executing QMP command: %s: %v", name, args)
_, err := q.executeCommandWithResponse(ctx, name, args, nil, filter)
return err
@@ -1160,7 +1168,8 @@ func (q *QMP) ExecutePCIVhostUserDevAdd(ctx context.Context, driver, devID, char
// devID is the id of the device to add. Must be valid QMP identifier.
// bdf is the PCI bus-device-function of the pci device.
// bus is optional. When hot plugging a PCIe device, the bus can be the ID of the pcie-root-port.
func (q *QMP) ExecuteVFIODeviceAdd(ctx context.Context, devID, bdf, bus, romfile string) error {
// iommufdID is the ID of the iommufd object to be created for this device. If empty, no iommufd object will be created.
func (q *QMP) ExecuteVFIODeviceAdd(ctx context.Context, devID, bdf, bus, romfile string, iommufdID string) error {
var driver string
var transport VirtioTransport
@@ -1179,6 +1188,17 @@ func (q *QMP) ExecuteVFIODeviceAdd(ctx context.Context, devID, bdf, bus, romfile
if bus != "" {
args["bus"] = bus
}
if iommufdID != "" {
iommufdIDFull := "iommufd" + iommufdID
objectAddArgs := map[string]interface{}{
"qom-type": "iommufd",
"id": iommufdIDFull,
}
if err := q.executeCommand(ctx, "object-add", objectAddArgs, nil); err != nil {
return err
}
args["iommufd"] = iommufdIDFull
}
return q.executeCommand(ctx, "device_add", args, nil)
}

View File

@@ -50,6 +50,10 @@ func (l qmpTestLogger) Errorf(format string, v ...interface{}) {
l.Infof(format, v...)
}
func (l qmpTestLogger) Debugf(format string, v ...interface{}) {
l.Infof(format, v...)
}
// nolint: govet
type qmpTestCommand struct {
name string
@@ -1136,6 +1140,51 @@ func TestQMPAPVFIOMediatedDeviceAdd(t *testing.T) {
<-disconnectedCh
}
func TestExecuteVFIODeviceAdd(t *testing.T) {
bdf := "04:00.0"
romfile := ""
for _, tc := range []struct {
name string
iommufdID string
}{
{
name: "with IOMMUFD",
iommufdID: "0",
},
{
name: "without IOMMUFD",
iommufdID: "",
},
} {
t.Run(tc.name, func(t *testing.T) {
connectedCh := make(chan *QMPVersion)
disconnectedCh := make(chan struct{})
buf := newQMPTestCommandBuffer(t)
// Note: At the time of writing, the QMPTestCommandBuffer does not
// support verifying parameters passed to object-add and device_add.
// So we just verify that the commands are sent in the correct order.
if tc.iommufdID != "" {
buf.AddCommand("object-add", nil, "return", nil)
}
buf.AddCommand("device_add", nil, "return", nil)
cfg := QMPConfig{Logger: qmpTestLogger{}}
q := startQMPLoop(buf, cfg, connectedCh, disconnectedCh)
checkVersion(t, connectedCh)
err := q.ExecuteVFIODeviceAdd(context.Background(), "devID", bdf, "rp1", romfile, tc.iommufdID)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
q.Shutdown()
<-disconnectedCh
})
}
}
// Checks that CPU are correctly added using device_add
func TestQMPCPUDeviceAdd(t *testing.T) {
drivers := []string{"host-x86_64-cpu", "host-s390x-cpu", "host-powerpc64-cpu"}

View File

@@ -0,0 +1,12 @@
Language: Cpp
BasedOnStyle: Microsoft
BreakBeforeBraces: Attach
PointerAlignment: Left
AllowShortFunctionsOnASingleLine: All
# match Go style
IndentCaseLabels: false
# don't break comments over line limit (needed for CodeQL exceptions)
ReflowComments: false
InsertNewlineAtEOF: true
KeepEmptyLines:
AtEndOfFile: true

View File

@@ -5,9 +5,6 @@ run:
- admin
- functional
- integration
skip-dirs:
# paths are relative to module root
- cri-containerd/test-images
linters:
enable:
@@ -34,13 +31,15 @@ linters-settings:
# struct order is often for Win32 compat
# also, ignore pointer bytes/GC issues for now until performance becomes an issue
- fieldalignment
check-shadowing: true
stylecheck:
# https://staticcheck.io/docs/checks
checks: ["all"]
issues:
exclude-dirs:
# paths are relative to module root
- cri-containerd/test-images
exclude-rules:
# err is very often shadowed in nested scopes
- linters:
@@ -70,22 +69,22 @@ issues:
- path: layer.go
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: hcsshim.go
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: cmd\\ncproxy\\nodenetsvc\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: cmd\\ncproxy_mock\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: internal\\hcs\\schema2\\
linters:
@@ -95,67 +94,67 @@ issues:
- path: internal\\wclayer\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: hcn\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: internal\\hcs\\schema1\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: internal\\hns\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: ext4\\internal\\compactext4\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: ext4\\internal\\format\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: internal\\guestrequest\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: internal\\guest\\prot\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: internal\\windevice\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: internal\\winapi\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: internal\\vmcompute\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: internal\\regstate\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
- path: internal\\hcserror\\
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"
# v0 APIs are deprecated, but still retained for backwards compatability
- path: cmd\\ncproxy\\
@@ -171,4 +170,4 @@ issues:
- path: internal\\vhdx\\info
linters:
- stylecheck
Text: "ST1003:"
text: "ST1003:"

View File

@@ -1,13 +1,20 @@
BASE:=base.tar.gz
DEV_BUILD:=0
include Makefile.bootfiles
GO:=go
GO_FLAGS:=-ldflags "-s -w" # strip Go binaries
CGO_ENABLED:=0
GOMODVENDOR:=
KMOD:=0
CFLAGS:=-O2 -Wall
LDFLAGS:=-static -s # strip C binaries
LDFLAGS:=-static -s #strip C binaries
LDLIBS:=
PREPROCESSORFLAGS:=
ifeq "$(KMOD)" "1"
LDFLAGS:= -s
LDLIBS:= -lkmod
PREPROCESSORFLAGS:=-DMODULES=1
endif
GO_FLAGS_EXTRA:=
ifeq "$(GOMODVENDOR)" "1"
@@ -23,108 +30,14 @@ SRCROOT=$(dir $(abspath $(firstword $(MAKEFILE_LIST))))
# additional directories to search for rule prerequisites and targets
VPATH=$(SRCROOT)
DELTA_TARGET=out/delta.tar.gz
ifeq "$(DEV_BUILD)" "1"
DELTA_TARGET=out/delta-dev.tar.gz
endif
ifeq "$(SNP_BUILD)" "1"
DELTA_TARGET=out/delta-snp.tar.gz
endif
# The link aliases for gcstools
GCS_TOOLS=\
generichook \
install-drivers
# Common path prefix.
PATH_PREFIX:=
# These have PATH_PREFIX prepended to obtain the full path in recipies e.g. $(PATH_PREFIX)/$(VMGS_TOOL)
VMGS_TOOL:=
IGVM_TOOL:=
KERNEL_PATH:=
.PHONY: all always rootfs test snp simple
.DEFAULT_GOAL := all
all: out/initrd.img out/rootfs.tar.gz
clean:
find -name '*.o' -print0 | xargs -0 -r rm
rm -rf bin deps rootfs out
test:
cd $(SRCROOT) && $(GO) test -v ./internal/guest/...
rootfs: out/rootfs.vhd
snp: out/kernelinitrd.vmgs out/rootfs.hash.vhd out/rootfs.vhd out/v2056.vmgs
simple: out/simple.vmgs snp
%.vmgs: %.bin
rm -f $@
# du -BM returns the size of the bin file in M, eg 7M. The sed command replaces the M with *1024*1024 and then bc does the math to convert to bytes
$(PATH_PREFIX)/$(VMGS_TOOL) create --filepath $@ --filesize `du -BM $< | sed "s/M.*/*1024*1024/" | bc`
$(PATH_PREFIX)/$(VMGS_TOOL) write --filepath $@ --datapath $< -i=8
# Simplest debug UVM used to test changes to the linux kernel. No dmverity protection. Boots an initramdisk rather than directly booting a vhd disk.
out/simple.bin: out/initrd.img $(PATH_PREFIX)/$(KERNEL_PATH) boot/startup_simple.sh
rm -f $@
python3 $(PATH_PREFIX)/$(IGVM_TOOL) -o $@ -kernel $(PATH_PREFIX)/$(KERNEL_PATH) -append "8250_core.nr_uarts=0 panic=-1 debug loglevel=7 rdinit=/startup_simple.sh" -rdinit out/initrd.img -vtl 0
ROOTFS_DEVICE:=/dev/sda
VERITY_DEVICE:=/dev/sdb
# Debug build for use with uvmtester. UVM with dm-verity protected vhd disk mounted directly via the kernel command line. Ignores corruption in dm-verity protected disk. (Use dmesg to see if dm-verity is ignoring data corruption.)
out/v2056.bin: out/rootfs.vhd out/rootfs.hash.vhd $(PATH_PREFIX)/$(KERNEL_PATH) out/rootfs.hash.datasectors out/rootfs.hash.datablocksize out/rootfs.hash.hashblocksize out/rootfs.hash.datablocks out/rootfs.hash.rootdigest out/rootfs.hash.salt boot/startup_v2056.sh
rm -f $@
python3 $(PATH_PREFIX)/$(IGVM_TOOL) -o $@ -kernel $(PATH_PREFIX)/$(KERNEL_PATH) -append "8250_core.nr_uarts=0 panic=-1 debug loglevel=7 root=/dev/dm-0 dm-mod.create=\"dmverity,,,ro,0 $(shell cat out/rootfs.hash.datasectors) verity 1 $(ROOTFS_DEVICE) $(VERITY_DEVICE) $(shell cat out/rootfs.hash.datablocksize) $(shell cat out/rootfs.hash.hashblocksize) $(shell cat out/rootfs.hash.datablocks) 0 sha256 $(shell cat out/rootfs.hash.rootdigest) $(shell cat out/rootfs.hash.salt) 1 ignore_corruption\" init=/startup_v2056.sh" -vtl 0
# Full UVM with dm-verity protected vhd disk mounted directly via the kernel command line.
out/kernelinitrd.bin: out/rootfs.vhd out/rootfs.hash.vhd out/rootfs.hash.datasectors out/rootfs.hash.datablocksize out/rootfs.hash.hashblocksize out/rootfs.hash.datablocks out/rootfs.hash.rootdigest out/rootfs.hash.salt $(PATH_PREFIX)/$(KERNEL_PATH) boot/startup.sh
rm -f $@
python3 $(PATH_PREFIX)/$(IGVM_TOOL) -o $@ -kernel $(PATH_PREFIX)/$(KERNEL_PATH) -append "8250_core.nr_uarts=0 panic=-1 debug loglevel=7 root=/dev/dm-0 dm-mod.create=\"dmverity,,,ro,0 $(shell cat out/rootfs.hash.datasectors) verity 1 $(ROOTFS_DEVICE) $(VERITY_DEVICE) $(shell cat out/rootfs.hash.datablocksize) $(shell cat out/rootfs.hash.hashblocksize) $(shell cat out/rootfs.hash.datablocks) 0 sha256 $(shell cat out/rootfs.hash.rootdigest) $(shell cat out/rootfs.hash.salt)\" init=/startup.sh" -vtl 0
# Rule to make a vhd from a file. This is used to create the rootfs.hash.vhd from rootfs.hash.
%.vhd: % bin/cmd/tar2ext4
./bin/cmd/tar2ext4 -only-vhd -i $< -o $@
# Rule to make a vhd from an ext4 file. This is used to create the rootfs.vhd from rootfs.ext4.
%.vhd: %.ext4 bin/cmd/tar2ext4
./bin/cmd/tar2ext4 -only-vhd -i $< -o $@
%.hash %.hash.info %.hash.datablocks %.hash.rootdigest %hash.datablocksize %.hash.datasectors %.hash.hashblocksize: %.ext4 %.hash.salt
veritysetup format --no-superblock --salt $(shell cat out/rootfs.hash.salt) $< $*.hash > $*.hash.info
# Retrieve info required by dm-verity at boot time
# Get the blocksize of rootfs
cat $*.hash.info | awk '/^Root hash:/{ print $$3 }' > $*.hash.rootdigest
cat $*.hash.info | awk '/^Salt:/{ print $$2 }' > $*.hash.salt
cat $*.hash.info | awk '/^Data block size:/{ print $$4 }' > $*.hash.datablocksize
cat $*.hash.info | awk '/^Hash block size:/{ print $$4 }' > $*.hash.hashblocksize
cat $*.hash.info | awk '/^Data blocks:/{ print $$3 }' > $*.hash.datablocks
echo $$(( $$(cat $*.hash.datablocks) * $$(cat $*.hash.datablocksize) / 512 )) > $*.hash.datasectors
out/rootfs.hash.salt:
hexdump -vn32 -e'8/4 "%08X" 1 "\n"' /dev/random > $@
out/rootfs.ext4: out/rootfs.tar.gz bin/cmd/tar2ext4
gzip -f -d ./out/rootfs.tar.gz
./bin/cmd/tar2ext4 -i ./out/rootfs.tar -o $@
out/rootfs.tar.gz: out/initrd.img
rm -rf rootfs-conv
mkdir rootfs-conv
gunzip -c out/initrd.img | (cd rootfs-conv && cpio -imd)
tar -zcf $@ -C rootfs-conv .
rm -rf rootfs-conv
out/initrd.img: $(BASE) $(DELTA_TARGET) $(SRCROOT)/hack/catcpio.sh
$(SRCROOT)/hack/catcpio.sh "$(BASE)" $(DELTA_TARGET) > out/initrd.img.uncompressed
gzip -c out/initrd.img.uncompressed > $@
rm out/initrd.img.uncompressed
# This target includes utilities which may be useful for testing purposes.
out/delta-dev.tar.gz: out/delta.tar.gz bin/internal/tools/snp-report
rm -rf rootfs-dev
@@ -168,10 +81,7 @@ out/delta.tar.gz: bin/init bin/vsockexec bin/cmd/gcs bin/cmd/gcstools bin/cmd/ho
tar -zcf $@ -C rootfs .
rm -rf rootfs
out/containerd-shim-runhcs-v1.exe:
GOOS=windows $(GO_BUILD) -o $@ $(SRCROOT)/cmd/containerd-shim-runhcs-v1
bin/cmd/gcs bin/cmd/gcstools bin/cmd/hooks/wait-paths bin/cmd/tar2ext4 bin/internal/tools/snp-report bin/cmd/dmverity-vhd:
bin/cmd/gcs bin/cmd/gcstools bin/cmd/hooks/wait-paths bin/cmd/tar2ext4 bin/internal/tools/snp-report:
@mkdir -p $(dir $@)
GOOS=linux $(GO_BUILD) -o $@ $(SRCROOT)/$(@:bin/%=%)
@@ -181,8 +91,8 @@ bin/vsockexec: vsockexec/vsockexec.o vsockexec/vsock.o
bin/init: init/init.o vsockexec/vsock.o
@mkdir -p bin
$(CC) $(LDFLAGS) -o $@ $^
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
%.o: %.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
$(CC) $(PREPROCESSORFLAGS) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<

View File

@@ -0,0 +1,197 @@
BASE:=base.tar.gz
DEV_BUILD:=0
DELTA_TARGET=out/delta.tar.gz
ifeq "$(DEV_BUILD)" "1"
DELTA_TARGET=out/delta-dev.tar.gz
endif
ifeq "$(SNP_BUILD)" "1"
DELTA_TARGET=out/delta-snp.tar.gz
endif
SRCROOT=$(dir $(abspath $(firstword $(MAKEFILE_LIST))))
PATH_PREFIX:=
# These have PATH_PREFIX prepended to obtain the full path in recipies e.g. $(PATH_PREFIX)/$(VMGS_TOOL)
VMGS_TOOL:=
IGVM_TOOL:=
KERNEL_PATH:=
TAR2EXT4_TOOL:=bin/cmd/tar2ext4
ROOTFS_DEVICE:=/dev/sda
HASH_DEVICE:=/dev/sdb
.PHONY: all always rootfs test snp simple
.DEFAULT_GOAL := all
all: out/initrd.img out/rootfs.tar.gz
clean:
find -name '*.o' -print0 | xargs -0 -r rm
rm -rf bin rootfs out
rootfs: out/rootfs.vhd
snp: out/kernel.vmgs out/rootfs-verity.vhd out/v2056.vmgs out/v2056combined.vmgs
simple: out/simple.vmgs snp
%.vmgs: %.bin
rm -f $@
# du -BM returns the size of the bin file in M, eg 7M. The sed command replaces the M with *1024*1024 and then bc does the math to convert to bytes
$(PATH_PREFIX)/$(VMGS_TOOL) create --filepath $@ --filesize `du -BM $< | sed "s/M.*/*1024*1024/" | bc`
$(PATH_PREFIX)/$(VMGS_TOOL) write --filepath $@ --datapath $< -i=8
# Simplest debug UVM used to test changes to the linux kernel. No dmverity protection. Boots an initramdisk rather than directly booting a vhd disk.
out/simple.bin: out/initrd.img $(PATH_PREFIX)/$(KERNEL_PATH) boot/startup_simple.sh
rm -f $@
python3 $(PATH_PREFIX)/$(IGVM_TOOL) \
-o $@ \
-kernel $(PATH_PREFIX)/$(KERNEL_PATH) \
-append "8250_core.nr_uarts=0 panic=-1 debug loglevel=7 rdinit=/startup_simple.sh" \
-rdinit out/initrd.img \
-vtl 0
# The boot performance is optimized by supplying rootfs as a SCSI attachment. In this case the kernel boots with
# dm-verity to ensure the integrity. Similar to layer VHDs the verity Merkle tree is appended to ext4 filesystem.
# It transpires that the /dev/sd* order is not deterministic wrt the scsi device order. Thus build a single userland
# fs + merkle tree device and boot that.
#
# From https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/dm-init.html
#
# dm-mod.create=<name>,<uuid>,<minor>,<flags>,<table>[,<table>+][;<name>,<uuid>,<minor>,<flags>,<table>[,<table>+]+]
#
# where:
# <name> ::= The device name.
# <uuid> ::= xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | ""
# <minor> ::= The device minor number | ""
# <flags> ::= "ro" | "rw"
# <table> ::= <start_sector> <num_sectors> <target_type> <target_args>
# <target_type> ::= "verity" | "linear" | ... (see list below)
#
# From https://docs.kernel.org/admin-guide/device-mapper/verity.html
# <version> <dev> <hash_dev>
# <data_block_size> <hash_block_size>
# <num_data_blocks> <hash_start_block>
# <algorithm> <digest> <salt>
# [<#opt_params> <opt_params>]
#
# typical igvm tool line once all the macros are expanded
# python3 /home/user/igvmfile.py -o out/v2056.bin -kernel /hose/user/bzImage -append "8250_core.nr_uarts=0 panic=-1 debug loglevel=9 ignore_loglevel dev.scsi.logging_level=9411 root=/dev/dm-0 dm-mod.create=\"dmverity,,,ro,0 196744 verity 1 /dev/sda /dev/sdb 4096 4096 24593 0 sha256 6d625a306aafdf73125a84388b7bfdd2c3a154bd8d698955f4adffc736bdfd66 b9065c23231f0d8901cc3a68e1d3b8d624213e76d6f9f6d3ccbcb829f9c710ba 1 ignore_corruption\" init=/startup_v2056.sh" -vtl 0
#
# so a kernel command line of:
# 8250_core.nr_uarts=0 panic=-1 debug loglevel=9 ignore_loglevel dev.scsi.logging_level=9411 root=/dev/dm-0 dm-mod.create=\"dmverity,,,ro,0 196744 verity 1 /dev/sda /dev/sdb 4096 4096 24593 0 sha256 6d625a306aafdf73125a84388b7bfdd2c3a154bd8d698955f4adffc736bdfd66 b9065c23231f0d8901cc3a68e1d3b8d624213e76d6f9f6d3ccbcb829f9c710ba 1 ignore_corruption\" init=/startup_v2056.sh
#
# and a dm-mod.create of:
# dmverity,,,ro,0 196744 verity 1 /dev/sda /dev/sdb 4096 4096 24593 0 sha256 6d625a306aafdf73125a84388b7bfdd2c3a154bd8d698955f4adffc736bdfd66 b9065c23231f0d8901cc3a68e1d3b8d624213e76d6f9f6d3ccbcb829f9c710ba 1 ignore_corruption
#
# which breaks down to:
#
# name = "dmverity"
# uuid = ""
# minor = ""
# flags = "ro"
# table = 0 196744 verity "args"
# start_sector = 0
# num_sectors = 196744
# target_type = verity
# target_args = 1 /dev/sda /dev/sdb 4096 4096 24593 0 sha256 6d625a306aafdf73125a84388b7bfdd2c3a154bd8d698955f4adffc736bdfd66 b9065c23231f0d8901cc3a68e1d3b8d624213e76d6f9f6d3ccbcb829f9c710ba 1 ignore_corruption
# args:
# version 1
# dev /dev/sda
# hash_dev /dev/sdb
# data_block_size 4096
# hash_block_size 4096
# num_data_blocks 24593
# hash_start_block 0
# algorithm sha256
# digest 6d625a306aafdf73125a84388b7bfdd2c3a154bd8d698955f4adffc736bdfd66
# salt b9065c23231f0d8901cc3a68e1d3b8d624213e76d6f9f6d3ccbcb829f9c710ba
# opt_params
# count = 1
# ignore_corruption
#
# combined typical (not bigger count of sectors for the whole device)
# dmverity,,,ro,0 199672 verity 1 /dev/sda /dev/sda 4096 4096 24959 24959 sha256 4aa6e79866ee946ddbd9cddd6554bc6449272942fcc65934326817785a3bd374 adc4956274489c936395bab046a2d476f21ef436e571ba53da2fdf3aee59bf0a
#
# A few notes:
# - num_sectors is the size of the final (aka target) verity device, i.e. the size of our rootfs excluding the Merkle
# tree.
# - We don't add verity superblock, so the <hash_start_block> will be exactly at the end of ext4 filesystem and equal
# to its size. In the case when verity superblock is present an extra block should be added to the offset value,
# i.e. 24959 becomes 24960.
# Debug build for use with uvmtester. UVM with dm-verity protected vhd disk mounted directly via the kernel command line.
# Ignores corruption in dm-verity protected disk. (Use dmesg to see if dm-verity is ignoring data corruption.)
out/v2056.bin: out/rootfs.vhd out/rootfs.hash.vhd $(PATH_PREFIX)/$(KERNEL_PATH) out/rootfs.hash.datasectors out/rootfs.hash.datablocksize out/rootfs.hash.hashblocksize out/rootfs.hash.datablocks out/rootfs.hash.rootdigest out/rootfs.hash.salt boot/startup_v2056.sh
rm -f $@
python3 $(PATH_PREFIX)/$(IGVM_TOOL) \
-o $@ \
-kernel $(PATH_PREFIX)/$(KERNEL_PATH) \
-append "8250_core.nr_uarts=0 panic=-1 debug loglevel=9 root=/dev/dm-0 dm-mod.create=\"dmverity,,,ro,0 $(shell cat out/rootfs.hash.datasectors) verity 1 $(ROOTFS_DEVICE) $(HASH_DEVICE) $(shell cat out/rootfs.hash.datablocksize) $(shell cat out/rootfs.hash.hashblocksize) $(shell cat out/rootfs.hash.datablocks) $(shell cat out/rootfs.hash.datablocks) sha256 $(shell cat out/rootfs.hash.rootdigest) $(shell cat out/rootfs.hash.salt) 1 ignore_corruption\" init=/startup_v2056.sh" \
-vtl 0
out/v2056combined.bin: out/rootfs-verity.vhd $(PATH_PREFIX)/$(KERNEL_PATH) out/rootfs.hash.datablocksize out/rootfs.hash.hashblocksize out/rootfs.hash.datablocks out/rootfs.hash.rootdigest out/rootfs.hash.salt boot/startup_v2056.sh
rm -f $@
echo root=/dev/dm-0 dm-mod.create=\"dmverity,,,ro,0 $(shell cat out/rootfs.hash.datasectors) verity 1 $(ROOTFS_DEVICE) $(ROOTFS_DEVICE) $(shell cat out/rootfs.hash.datablocksize) $(shell cat out/rootfs.hash.hashblocksize) $(shell cat out/rootfs.hash.datablocks) $(shell cat out/rootfs.hash.datablocks) sha256 $(shell cat out/rootfs.hash.rootdigest) $(shell cat out/rootfs.hash.salt) 1 ignore_corruption\"
python3 $(PATH_PREFIX)/$(IGVM_TOOL) \
-o $@ \
-kernel $(PATH_PREFIX)/$(KERNEL_PATH) \
-append "8250_core.nr_uarts=0 panic=-1 debug loglevel=9 ignore_loglevel dev.scsi.logging_level=9411 root=/dev/dm-0 dm-mod.create=\"dmverity,,,ro,0 $(shell cat out/rootfs.hash.datasectors) verity 1 $(ROOTFS_DEVICE) $(ROOTFS_DEVICE) $(shell cat out/rootfs.hash.datablocksize) $(shell cat out/rootfs.hash.hashblocksize) $(shell cat out/rootfs.hash.datablocks) $(shell cat out/rootfs.hash.datablocks) sha256 $(shell cat out/rootfs.hash.rootdigest) $(shell cat out/rootfs.hash.salt) 1 ignore_corruption\" init=/startup_v2056.sh" \
-vtl 0
# Full UVM with dm-verity protected vhd disk mounted directly via the kernel command line.
out/kernel.bin: out/rootfs-verity.vhd $(PATH_PREFIX)/$(KERNEL_PATH) out/rootfs.hash.datasectors out/rootfs.hash.datablocksize out/rootfs.hash.hashblocksize out/rootfs.hash.datablocks out/rootfs.hash.rootdigest out/rootfs.hash.salt boot/startup.sh
rm -f $@
echo root=/dev/dm-0 dm-mod.create=\"dmverity,,,ro,0 $(shell cat out/rootfs.hash.datasectors) verity 1 $(ROOTFS_DEVICE) $(ROOTFS_DEVICE) $(shell cat out/rootfs.hash.datablocksize) $(shell cat out/rootfs.hash.hashblocksize) $(shell cat out/rootfs.hash.datablocks) $(shell cat out/rootfs.hash.datablocks) sha256 $(shell cat out/rootfs.hash.rootdigest) $(shell cat out/rootfs.hash.salt)\"
python3 $(PATH_PREFIX)/$(IGVM_TOOL) \
-o $@ \
-kernel $(PATH_PREFIX)/$(KERNEL_PATH) \
-append "8250_core.nr_uarts=0 panic=-1 debug loglevel=7 root=/dev/dm-0 dm-mod.create=\"dmverity,,,ro,0 $(shell cat out/rootfs.hash.datasectors) verity 1 $(ROOTFS_DEVICE) $(ROOTFS_DEVICE) $(shell cat out/rootfs.hash.datablocksize) $(shell cat out/rootfs.hash.hashblocksize) $(shell cat out/rootfs.hash.datablocks) $(shell cat out/rootfs.hash.datablocks) sha256 $(shell cat out/rootfs.hash.rootdigest) $(shell cat out/rootfs.hash.salt)\" init=/startup.sh" \
-vtl 0
# Rule to make a vhd from a file. This is used to create the rootfs.hash.vhd from rootfs.hash.
%.vhd: % $(TAR2EXT4_TOOL)
$(TAR2EXT4_TOOL) -only-vhd -i $< -o $@
# Rule to make a vhd from an ext4 file. This is used to create the rootfs.vhd from rootfs.ext4.
%.vhd: %.ext4 $(TAR2EXT4_TOOL)
$(TAR2EXT4_TOOL) -only-vhd -i $< -o $@
%.hash %.hash.info %.hash.datablocks %.hash.rootdigest %hash.datablocksize %.hash.datasectors %.hash.hashblocksize: %.ext4 %.hash.salt
veritysetup format --no-superblock --salt $(shell cat out/rootfs.hash.salt) $< $*.hash > $*.hash.info
# Retrieve info required by dm-verity at boot time
# Get the blocksize of rootfs
cat $*.hash.info | awk '/^Root hash:/{ print $$3 }' > $*.hash.rootdigest
cat $*.hash.info | awk '/^Salt:/{ print $$2 }' > $*.hash.salt
cat $*.hash.info | awk '/^Data block size:/{ print $$4 }' > $*.hash.datablocksize
cat $*.hash.info | awk '/^Hash block size:/{ print $$4 }' > $*.hash.hashblocksize
cat $*.hash.info | awk '/^Data blocks:/{ print $$3 }' > $*.hash.datablocks
echo $$(( $$(cat $*.hash.datablocks) * $$(cat $*.hash.datablocksize) / 512 )) > $*.hash.datasectors
out/rootfs.hash.salt:
hexdump -vn32 -e'8/4 "%08X" 1 "\n"' /dev/random > $@
out/rootfs.ext4: out/rootfs.tar.gz $(TAR2EXT4_TOOL)
gzip -f -d ./out/rootfs.tar.gz
$(TAR2EXT4_TOOL) -i ./out/rootfs.tar -o $@
out/rootfs-verity.ext4: out/rootfs.ext4 out/rootfs.hash
cp out/rootfs.ext4 $@
cat out/rootfs.hash >> $@
out/rootfs.tar.gz: out/initrd.img
rm -rf rootfs-conv
mkdir rootfs-conv
gunzip -c out/initrd.img | (cd rootfs-conv && cpio -imd)
tar -zcf $@ -C rootfs-conv .
rm -rf rootfs-conv
out/initrd.img: $(BASE) $(DELTA_TARGET) $(SRCROOT)/hack/catcpio.sh
$(SRCROOT)/hack/catcpio.sh "$(BASE)" $(DELTA_TARGET) > out/initrd.img.uncompressed
gzip -c out/initrd.img.uncompressed > $@
rm out/initrd.img.uncompressed

View File

@@ -44,7 +44,7 @@ delta.tar.gz initrd.img rootfs.tar.gz
### Containerd Shim
For info on the [Runtime V2 API](https://github.com/containerd/containerd/blob/master/runtime/v2/README.md).
For info on the [Runtime V2 API](https://github.com/containerd/containerd/blob/main/core/runtime/v2/README.md).
Contrary to the typical Linux architecture of shim -> runc, the runhcs shim is used both to launch and manage the lifetime of containers.

View File

@@ -63,10 +63,10 @@ func (process *Process) SystemID() string {
}
func (process *Process) processSignalResult(ctx context.Context, err error) (bool, error) {
switch err { //nolint:errorlint
case nil:
if err == nil {
return true, nil
case ErrVmcomputeOperationInvalidState, ErrComputeSystemDoesNotExist, ErrElementNotFound:
}
if errors.Is(err, ErrVmcomputeOperationInvalidState) || errors.Is(err, ErrComputeSystemDoesNotExist) || errors.Is(err, ErrElementNotFound) {
if !process.stopped() {
// The process should be gone, but we have not received the notification.
// After a second, force unblock the process wait to work around a possible
@@ -82,9 +82,8 @@ func (process *Process) processSignalResult(ctx context.Context, err error) (boo
}()
}
return false, nil
default:
return false, err
}
return false, nil
}
// Signal signals the process with `options`.

View File

@@ -24,4 +24,6 @@ type Chipset struct {
// LinuxKernelDirect - Added in v2.2 Builds >=181117
LinuxKernelDirect *LinuxKernelDirect `json:"LinuxKernelDirect,omitempty"`
FirmwareFile *FirmwareFile `json:"FirmwareFile,omitempty"`
}

View File

@@ -9,14 +9,6 @@
package hcsschema
const (
CimMountFlagNone uint32 = 0x0
CimMountFlagChildOnly uint32 = 0x1
CimMountFlagEnableDax uint32 = 0x2
CimMountFlagCacheFiles uint32 = 0x4
CimMountFlagCacheRegions uint32 = 0x8
)
type CimMount struct {
ImagePath string `json:"ImagePath,omitempty"`
FileSystemName string `json:"FileSystemName,omitempty"`

View File

@@ -0,0 +1,8 @@
package hcsschema
type FirmwareFile struct {
// Parameters is an experimental/pre-release field. The field itself or its
// behavior can change in future iterations of the schema. Avoid taking a hard
// dependency on this field.
Parameters []byte `json:"Parameters,omitempty"`
}

View File

@@ -1,49 +0,0 @@
/*
* HCS API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.1
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type Memory2 struct {
SizeInMB uint64 `json:"SizeInMB,omitempty"`
AllowOvercommit bool `json:"AllowOvercommit,omitempty"`
EnableHotHint bool `json:"EnableHotHint,omitempty"`
EnableColdHint bool `json:"EnableColdHint,omitempty"`
EnableEpf bool `json:"EnableEpf,omitempty"`
// EnableDeferredCommit is private in the schema. If regenerated need to add back.
EnableDeferredCommit bool `json:"EnableDeferredCommit,omitempty"`
// EnableColdDiscardHint if enabled, then the memory cold discard hint feature is exposed
// to the VM, allowing it to trim non-zeroed pages from the working set (if supported by
// the guest operating system).
EnableColdDiscardHint bool `json:"EnableColdDiscardHint,omitempty"`
// LowMmioGapInMB is the low MMIO region allocated below 4GB.
//
// TODO: This is pre-release support in schema 2.3. Need to add build number
// docs when a public build with this is out.
LowMMIOGapInMB uint64 `json:"LowMmioGapInMB,omitempty"`
// HighMmioBaseInMB is the high MMIO region allocated above 4GB (base and
// size).
//
// TODO: This is pre-release support in schema 2.3. Need to add build number
// docs when a public build with this is out.
HighMMIOBaseInMB uint64 `json:"HighMmioBaseInMB,omitempty"`
// HighMmioGapInMB is the high MMIO region.
//
// TODO: This is pre-release support in schema 2.3. Need to add build number
// docs when a public build with this is out.
HighMMIOGapInMB uint64 `json:"HighMmioGapInMB,omitempty"`
}

View File

@@ -0,0 +1,21 @@
// Autogenerated code; DO NOT EDIT.
/*
* Schema Open API
*
* No description provided (generated by Swagger Codegen https://github.com/swaggerapi/swaggercodegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swaggerapi/swaggercodegen.git)
*/
package hcsschema
type MemoryBackingType string
// List of MemoryBackingType
const (
MemoryBackingType_PHYSICAL MemoryBackingType = "Physical"
MemoryBackingType_VIRTUAL MemoryBackingType = "Virtual"
MemoryBackingType_HYBRID MemoryBackingType = "Hybrid"
)

View File

@@ -0,0 +1,19 @@
// Autogenerated code; DO NOT EDIT.
/*
* Schema Open API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type Numa struct {
VirtualNodeCount uint8 `json:"VirtualNodeCount,omitempty"`
PreferredPhysicalNodes []int64 `json:"PreferredPhysicalNodes,omitempty"`
Settings []NumaSetting `json:"Settings,omitempty"`
MaxSizePerNode uint64 `json:"MaxSizePerNode,omitempty"`
}

View File

@@ -0,0 +1,17 @@
// Autogenerated code; DO NOT EDIT.
/*
* Schema Open API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type NumaNode struct {
VirtualNodeIndex uint32 `json:"VirtualNodeIndex,omitempty"`
PhysicalNodeIndex uint32 `json:"PhysicalNodeIndex,omitempty"`
}

View File

@@ -0,0 +1,19 @@
// Autogenerated code; DO NOT EDIT.
/*
* Schema Open API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type NumaNodeMemory struct {
// Total physical memory on on this physical NUMA node that is consumable by the VMs.
TotalConsumableMemoryInPages uint64 `json:"TotalConsumableMemoryInPages,omitempty"`
// Currently available physical memory on this physical NUMA node for the VMs.
AvailableMemoryInPages uint64 `json:"AvailableMemoryInPages,omitempty"`
}

View File

@@ -0,0 +1,17 @@
// Autogenerated code; DO NOT EDIT.
/*
* Schema Open API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type NumaNodeProcessor struct {
TotalAssignedProcessors uint32 `json:"TotalAssignedProcessors,omitempty"`
TotalAvailableProcessors uint32 `json:"TotalAvailableProcessors,omitempty"`
}

View File

@@ -0,0 +1,21 @@
// Autogenerated code; DO NOT EDIT.
/*
* Schema Open API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type NumaProcessors struct {
CountPerNode Range `json:"count_per_node,omitempty"`
NodePerSocket uint32 `json:"node_per_socket,omitempty"`
}
type Range struct {
Max uint32 `json:"max,omitempty"`
}

View File

@@ -0,0 +1,21 @@
// Autogenerated code; DO NOT EDIT.
/*
* Schema Open API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type NumaSetting struct {
VirtualNodeNumber uint32 `json:"VirtualNodeNumber,omitempty"`
PhysicalNodeNumber uint32 `json:"PhysicalNodeNumber,omitempty"`
VirtualSocketNumber uint32 `json:"VirtualSocketNumber,omitempty"`
CountOfProcessors uint32 `json:"CountOfProcessors,omitempty"`
CountOfMemoryBlocks uint64 `json:"CountOfMemoryBlocks,omitempty"`
MemoryBackingType MemoryBackingType `json:"MemoryBackingType,omitempty"`
}

View File

@@ -1,23 +0,0 @@
/*
* HCS API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.5
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type Processor2 struct {
Count int32 `json:"Count,omitempty"`
Limit int32 `json:"Limit,omitempty"`
Weight int32 `json:"Weight,omitempty"`
ExposeVirtualizationExtensions bool `json:"ExposeVirtualizationExtensions,omitempty"`
// An optional object that configures the CPU Group to which a Virtual Machine is going to bind to.
CpuGroup *CpuGroup `json:"CpuGroup,omitempty"`
}

View File

@@ -26,6 +26,8 @@ type Properties struct {
RuntimeId string `json:"RuntimeId,omitempty"`
SystemGUID string `json:"SystemGUID,omitempty"`
RuntimeTemplateId string `json:"RuntimeTemplateId,omitempty"`
State string `json:"State,omitempty"`

View File

@@ -23,4 +23,5 @@ const (
PTICHeartbeatStatus PropertyType = "ICHeartbeatStatus"
PTProcessorTopology PropertyType = "ProcessorTopology"
PTCPUGroup PropertyType = "CpuGroup"
PTSystemGUID PropertyType = "SystemGUID"
)

View File

@@ -1,16 +1,18 @@
// Autogenerated code; DO NOT EDIT.
/*
* HCS API
* Schema Open API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.1
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type Topology struct {
Memory *Memory2 `json:"Memory,omitempty"`
Processor *Processor2 `json:"Processor,omitempty"`
Memory *VirtualMachineMemory `json:"Memory,omitempty"`
Processor *VirtualMachineProcessor `json:"Processor,omitempty"`
Numa *Numa `json:"Numa,omitempty"`
}

View File

@@ -1,36 +1,29 @@
// Autogenerated code; DO NOT EDIT.
/*
* HCS API
* Schema Open API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.1
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
// Configuration of a virtual machine, used during its creation to set up and/or use resources.
type VirtualMachine struct {
// StopOnReset is private in the schema. If regenerated need to put back.
StopOnReset bool `json:"StopOnReset,omitempty"`
Chipset *Chipset `json:"Chipset,omitempty"`
ComputeTopology *Topology `json:"ComputeTopology,omitempty"`
Devices *Devices `json:"Devices,omitempty"`
GuestState *GuestState `json:"GuestState,omitempty"`
RestoreState *RestoreState `json:"RestoreState,omitempty"`
Version *Version `json:"Version,omitempty"`
// When set to true, the virtual machine will treat a reset as a stop, releasing resources and cleaning up state.
StopOnReset bool `json:"StopOnReset,omitempty"`
Chipset *Chipset `json:"Chipset,omitempty"`
ComputeTopology *Topology `json:"ComputeTopology,omitempty"`
Devices *Devices `json:"Devices,omitempty"`
GuestState *GuestState `json:"GuestState,omitempty"`
RestoreState *RestoreState `json:"RestoreState,omitempty"`
RegistryChanges *RegistryChanges `json:"RegistryChanges,omitempty"`
StorageQoS *StorageQoS `json:"StorageQoS,omitempty"`
StorageQoS *StorageQoS `json:"StorageQoS,omitempty"`
DebugOptions *DebugOptions `json:"DebugOptions,omitempty"`
GuestConnection *GuestConnection `json:"GuestConnection,omitempty"`
SecuritySettings *SecuritySettings `json:"SecuritySettings,omitempty"`
DebugOptions *DebugOptions `json:"DebugOptions,omitempty"`
SecuritySettings *SecuritySettings `json:"SecuritySettings,omitempty"`
}

View File

@@ -0,0 +1,33 @@
// Autogenerated code; DO NOT EDIT.
/*
* Schema Open API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type VirtualMachineMemory struct {
SizeInMB uint64 `json:"SizeInMB,omitempty"`
Backing *MemoryBackingType `json:"Backing,omitempty"`
// If enabled, then the VM's memory is backed by the Windows pagefile rather than physically backed, statically allocated memory.
AllowOvercommit bool `json:"AllowOvercommit,omitempty"`
// If enabled, then the memory hot hint feature is exposed to the VM, allowing it to prefetch pages into its working set. (if supported by the guest operating system).
EnableHotHint bool `json:"EnableHotHint,omitempty"`
// If enabled, then the memory cold hint feature is exposed to the VM, allowing it to trim zeroed pages from its working set (if supported by the guest operating system).
EnableColdHint bool `json:"EnableColdHint,omitempty"`
// If enabled, then the memory cold discard hint feature is exposed to the VM, allowing it to trim non-zeroed pages from the working set (if supported by the guest operating system).
EnableColdDiscardHint bool `json:"EnableColdDiscardHint,omitempty"`
// If enabled, then commit is not charged for each backing page until first access.
EnableDeferredCommit bool `json:"EnableDeferredCommit,omitempty"`
// Low MMIO region allocated below 4GB
LowMMIOGapInMB uint64 `json:"LowMmioGapInMB,omitempty"`
// High MMIO region allocated above 4GB (base and size)
HighMMIOBaseInMB uint64 `json:"HighMmioBaseInMB,omitempty"`
HighMMIOGapInMB uint64 `json:"HighMmioGapInMB,omitempty"`
SlitType *VirtualSlitType `json:"SlitType,omitempty"`
}

View File

@@ -0,0 +1,21 @@
// Autogenerated code; DO NOT EDIT.
/*
* Schema Open API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type VirtualMachineProcessor struct {
Count uint32 `json:"Count,omitempty"`
Limit uint64 `json:"Limit,omitempty"`
Weight uint64 `json:"Weight,omitempty"`
Reservation uint64 `json:"Reservation,omitempty"`
CpuGroup *CpuGroup `json:"CpuGroup,omitempty"`
NumaProcessorsSettings *NumaProcessors `json:"NumaProcessorsSettings,omitempty"`
}

View File

@@ -9,8 +9,9 @@
package hcsschema
// TODO: This is pre-release support in schema 2.3. Need to add build number
// TODO: PropagateNumaAffinity is pre-release/experimental field in schema 2.11. Need to add build number
// docs when a public build with this is out.
type VirtualPciDevice struct {
Functions []VirtualPciFunction `json:",omitempty"`
PropagateNumaAffinity *bool `json:"PropagateNumaAffinity,omitempty"`
}

View File

@@ -0,0 +1,23 @@
// Autogenerated code; DO NOT EDIT.
/*
* Schema Open API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
// VirtualSlitType : Indicates if a virtual SLIT should ne enabled for a VM and the type of virtual SLIT to be enabled.
type VirtualSlitType string
// List of VirtualSlitType
const (
VirtualSlitType_NONE VirtualSlitType = "None"
VirtualSlitType_FIRMWARE VirtualSlitType = "Firmware"
VirtualSlitType_MEASURED VirtualSlitType = "Measured"
VirtualSlitType_FIRMWARE_FALLBACK_MEASURED VirtualSlitType = "FirmwareFallbackMeasured"
)

View File

@@ -13,4 +13,6 @@ type WindowsCrashReporting struct {
DumpFileName string `json:"DumpFileName,omitempty"`
MaxDumpSize int64 `json:"MaxDumpSize,omitempty"`
DumpType string `json:"DumpType,omitempty"`
}

View File

@@ -238,9 +238,10 @@ func (computeSystem *System) Shutdown(ctx context.Context) error {
resultJSON, err := vmcompute.HcsShutdownComputeSystem(ctx, computeSystem.handle, "")
events := processHcsResult(ctx, resultJSON)
switch err { //nolint:errorlint
case nil, ErrVmcomputeAlreadyStopped, ErrComputeSystemDoesNotExist, ErrVmcomputeOperationPending:
default:
if err != nil &&
!errors.Is(err, ErrVmcomputeAlreadyStopped) &&
!errors.Is(err, ErrComputeSystemDoesNotExist) &&
!errors.Is(err, ErrVmcomputeOperationPending) {
return makeSystemError(computeSystem, operation, err, events)
}
return nil
@@ -259,9 +260,10 @@ func (computeSystem *System) Terminate(ctx context.Context) error {
resultJSON, err := vmcompute.HcsTerminateComputeSystem(ctx, computeSystem.handle, "")
events := processHcsResult(ctx, resultJSON)
switch err { //nolint:errorlint
case nil, ErrVmcomputeAlreadyStopped, ErrComputeSystemDoesNotExist, ErrVmcomputeOperationPending:
default:
if err != nil &&
!errors.Is(err, ErrVmcomputeAlreadyStopped) &&
!errors.Is(err, ErrComputeSystemDoesNotExist) &&
!errors.Is(err, ErrVmcomputeOperationPending) {
return makeSystemError(computeSystem, operation, err, events)
}
return nil
@@ -279,14 +281,13 @@ func (computeSystem *System) waitBackground() {
span.AddAttributes(trace.StringAttribute("cid", computeSystem.id))
err := waitForNotification(ctx, computeSystem.callbackNumber, hcsNotificationSystemExited, nil)
switch err { //nolint:errorlint
case nil:
if err == nil {
log.G(ctx).Debug("system exited")
case ErrVmcomputeUnexpectedExit:
} else if errors.Is(err, ErrVmcomputeUnexpectedExit) {
log.G(ctx).Debug("unexpected system exit")
computeSystem.exitError = makeSystemError(computeSystem, operation, err, nil)
err = nil
default:
} else {
err = makeSystemError(computeSystem, operation, err, nil)
}
computeSystem.closedWaitOnce.Do(func() {

View File

@@ -47,7 +47,7 @@ func (nnvManagementMacList *HNSNnvManagementMacList) Set() (*HNSNnvManagementMac
func GetNnvManagementMacAddressList() (*HNSNnvManagementMacList, error) {
operation := "Get"
title := "hcsshim::nnvManagementMacList::" + operation
logrus.Debugf(title)
logrus.Debug(title)
return HNSNnvManagementMacRequest("GET", "", "")
}
@@ -55,6 +55,6 @@ func GetNnvManagementMacAddressList() (*HNSNnvManagementMacList, error) {
func DeleteNnvManagementMacAddressList() (*HNSNnvManagementMacList, error) {
operation := "Delete"
title := "hcsshim::nnvManagementMacList::" + operation
logrus.Debugf(title)
logrus.Debug(title)
return HNSNnvManagementMacRequest("DELETE", "", "")
}

View File

@@ -22,9 +22,8 @@ import (
// of the job and a mutex for synchronized handle access.
type JobObject struct {
handle windows.Handle
// All accesses to this MUST be done atomically except in `Open` as the object
// is being created in the function. 1 signifies that this job is currently a silo.
silo uint32
// silo signifies that this job is currently a silo.
silo atomic.Bool
mq *queue.MessageQueue
handleLock sync.RWMutex
}
@@ -204,9 +203,7 @@ func Open(ctx context.Context, options *Options) (_ *JobObject, err error) {
handle: jobHandle,
}
if isJobSilo(jobHandle) {
job.silo = 1
}
job.silo.Store(isJobSilo(jobHandle))
// If the IOCP we'll be using to receive messages for all jobs hasn't been
// created, create it and start polling.
@@ -479,7 +476,7 @@ func (job *JobObject) ApplyFileBinding(root, target string, readOnly bool) error
return ErrAlreadyClosed
}
if !job.isSilo() {
if !job.silo.Load() {
return ErrNotSilo
}
@@ -546,7 +543,7 @@ func (job *JobObject) PromoteToSilo() error {
return ErrAlreadyClosed
}
if job.isSilo() {
if job.silo.Load() {
return nil
}
@@ -569,15 +566,10 @@ func (job *JobObject) PromoteToSilo() error {
return fmt.Errorf("failed to promote job to silo: %w", err)
}
atomic.StoreUint32(&job.silo, 1)
job.silo.Store(true)
return nil
}
// isSilo returns if the job object is a silo.
func (job *JobObject) isSilo() bool {
return atomic.LoadUint32(&job.silo) == 1
}
// QueryPrivateWorkingSet returns the private working set size for the job. This is calculated by adding up the
// private working set for every process running in the job.
func (job *JobObject) QueryPrivateWorkingSet() (uint64, error) {

View File

@@ -150,6 +150,7 @@ func (job *JobObject) SetCPUAffinity(affinityBitMask uint64) error {
return fmt.Errorf("affinity bitmask (%d) exceeds max allowable value (%d)", affinityBitMask, maxUintptr)
}
// CodeQL [SM03681] checked against max value above (there is no math.MaxUintPtr ...)
info.BasicLimitInformation.Affinity = uintptr(affinityBitMask)
return job.setExtendedInformation(info)
}

View File

@@ -4,7 +4,6 @@ import (
"context"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
type entryContextKeyType int
@@ -20,13 +19,13 @@ var (
// Instead, use `L.With*` or `L.Dup()`. Or `G(context.Background())`.
L = logrus.NewEntry(logrus.StandardLogger())
// G is an alias for GetEntry
// G is an alias for GetEntry.
G = GetEntry
// S is an alias for SetEntry
// S is an alias for SetEntry.
S = SetEntry
// U is an alias for UpdateContext
// U is an alias for UpdateContext.
U = UpdateContext
)
@@ -83,7 +82,7 @@ func UpdateContext(ctx context.Context) context.Context {
// WithContext returns a context that contains the provided log entry.
// The entry can be extracted with `GetEntry` (`G`)
//
// The entry in the context is a copy of `entry` (generated by `entry.WithContext`)
// The entry in the context is a copy of `entry` (generated by `entry.WithContext`).
func WithContext(ctx context.Context, entry *logrus.Entry) (context.Context, *logrus.Entry) {
// regardless of the order, entry.Context != GetEntry(ctx)
// here, the returned entry will reference the supplied context
@@ -93,25 +92,6 @@ func WithContext(ctx context.Context, entry *logrus.Entry) (context.Context, *lo
return ctx, entry
}
// Copy extracts the tracing Span and logging entry from the src Context, if they
// exist, and adds them to the dst Context.
//
// This is useful to share tracing and logging between contexts, but not the
// cancellation. For example, if the src Context has been cancelled but cleanup
// operations triggered by the cancellation require a non-cancelled context to
// execute.
func Copy(dst context.Context, src context.Context) context.Context {
if s := trace.FromContext(src); s != nil {
dst = trace.NewContext(dst, s)
}
if e := fromContext(src); e != nil {
dst, _ = WithContext(dst, e)
}
return dst
}
func fromContext(ctx context.Context) *logrus.Entry {
e, _ := ctx.Value(_entryContextKey).(*logrus.Entry)
return e

View File

@@ -103,9 +103,7 @@ func encode(v interface{}) (_ []byte, err error) {
if jErr := enc.Encode(v); jErr != nil {
if err != nil {
// TODO (go1.20): use multierror via fmt.Errorf("...: %w; ...: %w", ...)
//nolint:errorlint // non-wrapping format verb for fmt.Errorf
return nil, fmt.Errorf("protojson encoding: %v; json encoding: %w", err, jErr)
return nil, fmt.Errorf("protojson encoding: %w; json encoding: %w", err, jErr)
}
return nil, fmt.Errorf("json encoding: %w", jErr)
}

View File

@@ -22,23 +22,14 @@ var (
// case sensitive keywords, so "env" is not a substring on "Environment"
_scrubKeywords = [][]byte{[]byte("env"), []byte("Environment")}
_scrub int32
_scrub atomic.Bool
)
// SetScrubbing enables scrubbing
func SetScrubbing(enable bool) {
v := int32(0) // cant convert from bool to int32 directly
if enable {
v = 1
}
atomic.StoreInt32(&_scrub, v)
}
func SetScrubbing(enable bool) { _scrub.Store(enable) }
// IsScrubbingEnabled checks if scrubbing is enabled
func IsScrubbingEnabled() bool {
v := atomic.LoadInt32(&_scrub)
return v != 0
}
func IsScrubbingEnabled() bool { return _scrub.Load() }
// ScrubProcessParameters scrubs HCS Create Process requests with config parameters of
// type internal/hcs/schema2.ScrubProcessParameters (aka hcsshema.ScrubProcessParameters)

View File

@@ -104,7 +104,7 @@ func execute(ctx gcontext.Context, timeout time.Duration, f func() error) error
}()
select {
case <-ctx.Done():
if ctx.Err() == gcontext.DeadlineExceeded { //nolint:errorlint
if ctx.Err() == gcontext.DeadlineExceeded {
log.G(ctx).WithField(logfields.Timeout, trueTimeout).
Warning("Syscall did not complete within operation timeout. This may indicate a platform issue. " +
"If it appears to be making no forward progress, obtain the stacks and see if there is a syscall " +

View File

@@ -34,6 +34,7 @@ const (
UtilityVMPath = `UtilityVM`
UtilityVMFilesPath = `UtilityVM\Files`
RegFilesPath = `Files\Windows\System32\config`
BootDirRelativePath = `\EFI\Microsoft\Boot`
BcdFilePath = `UtilityVM\Files\EFI\Microsoft\Boot\BCD`
BootMgrFilePath = `UtilityVM\Files\EFI\Microsoft\Boot\bootmgfw.efi`
ContainerBaseVhd = `blank-base.vhdx`

View File

@@ -32,10 +32,16 @@ type CimFsFileMetadata struct {
EACount uint32
}
type CimFsImagePath struct {
ImageDir *uint16
ImageName *uint16
}
//sys CimMountImage(imagePath string, fsName string, flags uint32, volumeID *g) (hr error) = cimfs.CimMountImage?
//sys CimDismountImage(volumeID *g) (hr error) = cimfs.CimDismountImage?
//sys CimCreateImage(imagePath string, oldFSName *uint16, newFSName *uint16, cimFSHandle *FsHandle) (hr error) = cimfs.CimCreateImage?
//sys CimCreateImage2(imagePath string, flags uint32, oldFSName *uint16, newFSName *uint16, cimFSHandle *FsHandle) (hr error) = cimfs.CimCreateImage2?
//sys CimCloseImage(cimFSHandle FsHandle) = cimfs.CimCloseImage?
//sys CimCommitImage(cimFSHandle FsHandle) (hr error) = cimfs.CimCommitImage?
@@ -45,3 +51,8 @@ type CimFsFileMetadata struct {
//sys CimDeletePath(cimFSHandle FsHandle, path string) (hr error) = cimfs.CimDeletePath?
//sys CimCreateHardLink(cimFSHandle FsHandle, newPath string, oldPath string) (hr error) = cimfs.CimCreateHardLink?
//sys CimCreateAlternateStream(cimFSHandle FsHandle, path string, size uint64, cimStreamHandle *StreamHandle) (hr error) = cimfs.CimCreateAlternateStream?
//sys CimAddFsToMergedImage(cimFSHandle FsHandle, path string) (hr error) = cimfs.CimAddFsToMergedImage?
//sys CimAddFsToMergedImage2(cimFSHandle FsHandle, path string, flags uint32) (hr error) = cimfs.CimAddFsToMergedImage2?
//sys CimMergeMountImage(numCimPaths uint32, backingImagePaths *CimFsImagePath, flags uint32, volumeID *g) (hr error) = cimfs.CimMergeMountImage?
//sys CimTombstoneFile(cimFSHandle FsHandle, path string) (hr error) = cimfs.CimTombstoneFile?
//sys CimCreateMergeLink(cimFSHandle FsHandle, newPath string, oldPath string) (hr error) = cimfs.CimCreateMergeLink?

View File

@@ -53,6 +53,8 @@ var (
procCM_Get_Device_ID_ListA = modcfgmgr32.NewProc("CM_Get_Device_ID_ListA")
procCM_Get_Device_ID_List_SizeA = modcfgmgr32.NewProc("CM_Get_Device_ID_List_SizeA")
procCM_Locate_DevNodeW = modcfgmgr32.NewProc("CM_Locate_DevNodeW")
procCimAddFsToMergedImage = modcimfs.NewProc("CimAddFsToMergedImage")
procCimAddFsToMergedImage2 = modcimfs.NewProc("CimAddFsToMergedImage2")
procCimCloseImage = modcimfs.NewProc("CimCloseImage")
procCimCloseStream = modcimfs.NewProc("CimCloseStream")
procCimCommitImage = modcimfs.NewProc("CimCommitImage")
@@ -60,9 +62,13 @@ var (
procCimCreateFile = modcimfs.NewProc("CimCreateFile")
procCimCreateHardLink = modcimfs.NewProc("CimCreateHardLink")
procCimCreateImage = modcimfs.NewProc("CimCreateImage")
procCimCreateImage2 = modcimfs.NewProc("CimCreateImage2")
procCimCreateMergeLink = modcimfs.NewProc("CimCreateMergeLink")
procCimDeletePath = modcimfs.NewProc("CimDeletePath")
procCimDismountImage = modcimfs.NewProc("CimDismountImage")
procCimMergeMountImage = modcimfs.NewProc("CimMergeMountImage")
procCimMountImage = modcimfs.NewProc("CimMountImage")
procCimTombstoneFile = modcimfs.NewProc("CimTombstoneFile")
procCimWriteStream = modcimfs.NewProc("CimWriteStream")
procSetJobCompartmentId = modiphlpapi.NewProc("SetJobCompartmentId")
procClosePseudoConsole = modkernel32.NewProc("ClosePseudoConsole")
@@ -181,6 +187,54 @@ func _CMLocateDevNode(pdnDevInst *uint32, pDeviceID *uint16, uFlags uint32) (hr
return
}
func CimAddFsToMergedImage(cimFSHandle FsHandle, path string) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(path)
if hr != nil {
return
}
return _CimAddFsToMergedImage(cimFSHandle, _p0)
}
func _CimAddFsToMergedImage(cimFSHandle FsHandle, path *uint16) (hr error) {
hr = procCimAddFsToMergedImage.Find()
if hr != nil {
return
}
r0, _, _ := syscall.SyscallN(procCimAddFsToMergedImage.Addr(), uintptr(cimFSHandle), uintptr(unsafe.Pointer(path)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func CimAddFsToMergedImage2(cimFSHandle FsHandle, path string, flags uint32) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(path)
if hr != nil {
return
}
return _CimAddFsToMergedImage2(cimFSHandle, _p0, flags)
}
func _CimAddFsToMergedImage2(cimFSHandle FsHandle, path *uint16, flags uint32) (hr error) {
hr = procCimAddFsToMergedImage2.Find()
if hr != nil {
return
}
r0, _, _ := syscall.SyscallN(procCimAddFsToMergedImage2.Addr(), uintptr(cimFSHandle), uintptr(unsafe.Pointer(path)), uintptr(flags))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func CimCloseImage(cimFSHandle FsHandle) (err error) {
err = procCimCloseImage.Find()
if err != nil {
@@ -321,6 +375,59 @@ func _CimCreateImage(imagePath *uint16, oldFSName *uint16, newFSName *uint16, ci
return
}
func CimCreateImage2(imagePath string, flags uint32, oldFSName *uint16, newFSName *uint16, cimFSHandle *FsHandle) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(imagePath)
if hr != nil {
return
}
return _CimCreateImage2(_p0, flags, oldFSName, newFSName, cimFSHandle)
}
func _CimCreateImage2(imagePath *uint16, flags uint32, oldFSName *uint16, newFSName *uint16, cimFSHandle *FsHandle) (hr error) {
hr = procCimCreateImage2.Find()
if hr != nil {
return
}
r0, _, _ := syscall.SyscallN(procCimCreateImage2.Addr(), uintptr(unsafe.Pointer(imagePath)), uintptr(flags), uintptr(unsafe.Pointer(oldFSName)), uintptr(unsafe.Pointer(newFSName)), uintptr(unsafe.Pointer(cimFSHandle)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func CimCreateMergeLink(cimFSHandle FsHandle, newPath string, oldPath string) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(newPath)
if hr != nil {
return
}
var _p1 *uint16
_p1, hr = syscall.UTF16PtrFromString(oldPath)
if hr != nil {
return
}
return _CimCreateMergeLink(cimFSHandle, _p0, _p1)
}
func _CimCreateMergeLink(cimFSHandle FsHandle, newPath *uint16, oldPath *uint16) (hr error) {
hr = procCimCreateMergeLink.Find()
if hr != nil {
return
}
r0, _, _ := syscall.SyscallN(procCimCreateMergeLink.Addr(), uintptr(cimFSHandle), uintptr(unsafe.Pointer(newPath)), uintptr(unsafe.Pointer(oldPath)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func CimDeletePath(cimFSHandle FsHandle, path string) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(path)
@@ -360,6 +467,21 @@ func CimDismountImage(volumeID *g) (hr error) {
return
}
func CimMergeMountImage(numCimPaths uint32, backingImagePaths *CimFsImagePath, flags uint32, volumeID *g) (hr error) {
hr = procCimMergeMountImage.Find()
if hr != nil {
return
}
r0, _, _ := syscall.SyscallN(procCimMergeMountImage.Addr(), uintptr(numCimPaths), uintptr(unsafe.Pointer(backingImagePaths)), uintptr(flags), uintptr(unsafe.Pointer(volumeID)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func CimMountImage(imagePath string, fsName string, flags uint32, volumeID *g) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(imagePath)
@@ -389,6 +511,30 @@ func _CimMountImage(imagePath *uint16, fsName *uint16, flags uint32, volumeID *g
return
}
func CimTombstoneFile(cimFSHandle FsHandle, path string) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(path)
if hr != nil {
return
}
return _CimTombstoneFile(cimFSHandle, _p0)
}
func _CimTombstoneFile(cimFSHandle FsHandle, path *uint16) (hr error) {
hr = procCimTombstoneFile.Find()
if hr != nil {
return
}
r0, _, _ := syscall.SyscallN(procCimTombstoneFile.Addr(), uintptr(cimFSHandle), uintptr(unsafe.Pointer(path)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func CimWriteStream(cimStreamHandle StreamHandle, buffer uintptr, bufferSize uint32) (hr error) {
hr = procCimWriteStream.Find()
if hr != nil {

View File

@@ -3,7 +3,8 @@ package osversion
// List of stable ABI compliant ltsc releases
// Note: List must be sorted in ascending order
var compatLTSCReleases = []uint16{
V21H2Server,
LTSC2022,
LTSC2025,
}
// CheckHostAndContainerCompat checks if given host and container
@@ -20,16 +21,25 @@ func CheckHostAndContainerCompat(host, ctr OSVersion) bool {
}
// If host is < WS 2022, exact version match is required
if host.Build < V21H2Server {
if host.Build < LTSC2022 {
return host.Build == ctr.Build
}
var supportedLtscRelease uint16
// Find the latest LTSC version that is earlier than the host version.
// This is the earliest version of container that the host can run.
//
// If the host version is an LTSC, then it supports compatibility with
// everything from the previous LTSC up to itself, so we want supportedLTSCRelease
// to be the previous entry.
//
// If no match is found, then we know that the host is LTSC2022 exactly,
// since we already checked that it's not less than LTSC2022.
var supportedLTSCRelease uint16 = LTSC2022
for i := len(compatLTSCReleases) - 1; i >= 0; i-- {
if host.Build >= compatLTSCReleases[i] {
supportedLtscRelease = compatLTSCReleases[i]
if host.Build > compatLTSCReleases[i] {
supportedLTSCRelease = compatLTSCReleases[i]
break
}
}
return ctr.Build >= supportedLtscRelease && ctr.Build <= host.Build
return supportedLTSCRelease <= ctr.Build && ctr.Build <= host.Build
}

View File

@@ -81,4 +81,11 @@ const (
// V22H2Win11 corresponds to Windows 11 (2022 Update).
V22H2Win11 = 22621
// V23H2 is the 23H2 release in the Windows Server annual channel.
V23H2 = 25398
// Windows Server 2025 build 26100
V25H1Server = 26100
LTSC2025 = V25H1Server
)

View File

@@ -61,8 +61,7 @@ func ImportLayerFromTar(ctx context.Context, r io.Reader, path string, parentLay
func writeLayerFromTar(ctx context.Context, r io.Reader, w wclayer.LayerWriter, root string) (int64, error) {
t := tar.NewReader(r)
// CodeQL [SM03409] False positive, `internal/safefile` package ensures tar extractions are always
// bound to the layer root directory.
// CodeQL [SM03409] `internal\wclayer` uses `internal/safefile` to bind tar extraction to the layer's root directory
hdr, err := t.Next()
totalSize := int64(0)
buf := bufio.NewWriter(nil)
@@ -80,16 +79,14 @@ func writeLayerFromTar(ctx context.Context, r io.Reader, w wclayer.LayerWriter,
if err != nil {
return 0, err
}
// CodeQL [SM03409] False positive, `internal/safefile` package ensures tar extractions are always
// bound to the layer root directory.
// CodeQL [SM03409] `internal\wclayer` uses `internal/safefile` to bind tar extraction to the layer's root directory
hdr, err = t.Next()
} else if hdr.Typeflag == tar.TypeLink {
err = w.AddLink(filepath.FromSlash(hdr.Name), filepath.FromSlash(hdr.Linkname))
if err != nil {
return 0, err
}
// CodeQL [SM03409] False positive, `internal/safefile` package ensures tar extractions are always
// bound to the layer root directory.
// CodeQL [SM03409] `internal\wclayer` uses `internal/safefile` to bind tar extraction to the layer's root directory
hdr, err = t.Next()
} else {
var (

View File

@@ -12,7 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// Integration with the systemd D-Bus API. See http://www.freedesktop.org/wiki/Software/systemd/dbus/
// Package dbus provides integration with the systemd D-Bus API.
// See http://www.freedesktop.org/wiki/Software/systemd/dbus/
package dbus
import (

View File

@@ -24,15 +24,15 @@ import (
"github.com/godbus/dbus/v5"
)
// Who can be used to specify which process to kill in the unit via the KillUnitWithTarget API
// Who specifies which process to send a signal to via the [KillUnitWithTarget].
type Who string
const (
// All sends the signal to all processes in the unit
// All sends the signal to all processes in the unit.
All Who = "all"
// Main sends the signal to the main process of the unit
// Main sends the signal to the main process of the unit.
Main Who = "main"
// Control sends the signal to the control process of the unit
// Control sends the signal to the control process of the unit.
Control Who = "control"
)
@@ -41,7 +41,8 @@ func (c *Conn) jobComplete(signal *dbus.Signal) {
var job dbus.ObjectPath
var unit string
var result string
dbus.Store(signal.Body, &id, &job, &unit, &result)
_ = dbus.Store(signal.Body, &id, &job, &unit, &result)
c.jobListener.Lock()
out, ok := c.jobListener.jobs[job]
if ok {
@@ -51,7 +52,7 @@ func (c *Conn) jobComplete(signal *dbus.Signal) {
c.jobListener.Unlock()
}
func (c *Conn) startJob(ctx context.Context, ch chan<- string, job string, args ...interface{}) (int, error) {
func (c *Conn) startJob(ctx context.Context, ch chan<- string, job string, args ...any) (int, error) {
if ch != nil {
c.jobListener.Lock()
defer c.jobListener.Unlock()
@@ -102,6 +103,10 @@ func (c *Conn) StartUnit(name string, mode string, ch chan<- string) (int, error
// has been removed too. skipped indicates that a job was skipped because it
// didn't apply to the units current state.
//
// Important: It is the caller's responsibility to unblock the provided channel write,
// either by reading from the channel or by using a buffered channel. Until the write
// is unblocked, the Conn object cannot handle other jobs.
//
// If no error occurs, the ID of the underlying systemd job will be returned. There
// does exist the possibility for no error to be returned, but for the returned job
// ID to be 0. In this case, the actual underlying ID is not 0 and this datapoint
@@ -192,19 +197,21 @@ func (c *Conn) StartTransientUnitContext(ctx context.Context, name string, mode
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.StartTransientUnit", name, mode, properties, make([]PropertyCollection, 0))
}
// Deprecated: use KillUnitContext instead.
// Deprecated: use [KillUnitWithTarget] instead.
func (c *Conn) KillUnit(name string, signal int32) {
c.KillUnitContext(context.Background(), name, signal)
}
// KillUnitContext takes the unit name and a UNIX signal number to send.
// All of the unit's processes are killed.
//
// Deprecated: use [KillUnitWithTarget] instead, with target argument set to [All].
func (c *Conn) KillUnitContext(ctx context.Context, name string, signal int32) {
c.KillUnitWithTarget(ctx, name, All, signal)
_ = c.KillUnitWithTarget(ctx, name, All, signal)
}
// KillUnitWithTarget is like KillUnitContext, but allows you to specify which
// process in the unit to send the signal to.
// KillUnitWithTarget sends a signal to the specified unit.
// The target argument can be one of [All], [Main], or [Control].
func (c *Conn) KillUnitWithTarget(ctx context.Context, name string, target Who, signal int32) error {
return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.KillUnit", 0, name, string(target), signal).Store()
}
@@ -240,7 +247,7 @@ func (c *Conn) SystemStateContext(ctx context.Context) (*Property, error) {
}
// getProperties takes the unit path and returns all of its dbus object properties, for the given dbus interface.
func (c *Conn) getProperties(ctx context.Context, path dbus.ObjectPath, dbusInterface string) (map[string]interface{}, error) {
func (c *Conn) getProperties(ctx context.Context, path dbus.ObjectPath, dbusInterface string) (map[string]any, error) {
var err error
var props map[string]dbus.Variant
@@ -254,7 +261,7 @@ func (c *Conn) getProperties(ctx context.Context, path dbus.ObjectPath, dbusInte
return nil, err
}
out := make(map[string]interface{}, len(props))
out := make(map[string]any, len(props))
for k, v := range props {
out[k] = v.Value()
}
@@ -263,36 +270,36 @@ func (c *Conn) getProperties(ctx context.Context, path dbus.ObjectPath, dbusInte
}
// Deprecated: use GetUnitPropertiesContext instead.
func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) {
func (c *Conn) GetUnitProperties(unit string) (map[string]any, error) {
return c.GetUnitPropertiesContext(context.Background(), unit)
}
// GetUnitPropertiesContext takes the (unescaped) unit name and returns all of
// its dbus object properties.
func (c *Conn) GetUnitPropertiesContext(ctx context.Context, unit string) (map[string]interface{}, error) {
func (c *Conn) GetUnitPropertiesContext(ctx context.Context, unit string) (map[string]any, error) {
path := unitPath(unit)
return c.getProperties(ctx, path, "org.freedesktop.systemd1.Unit")
}
// Deprecated: use GetUnitPathPropertiesContext instead.
func (c *Conn) GetUnitPathProperties(path dbus.ObjectPath) (map[string]interface{}, error) {
func (c *Conn) GetUnitPathProperties(path dbus.ObjectPath) (map[string]any, error) {
return c.GetUnitPathPropertiesContext(context.Background(), path)
}
// GetUnitPathPropertiesContext takes the (escaped) unit path and returns all
// of its dbus object properties.
func (c *Conn) GetUnitPathPropertiesContext(ctx context.Context, path dbus.ObjectPath) (map[string]interface{}, error) {
func (c *Conn) GetUnitPathPropertiesContext(ctx context.Context, path dbus.ObjectPath) (map[string]any, error) {
return c.getProperties(ctx, path, "org.freedesktop.systemd1.Unit")
}
// Deprecated: use GetAllPropertiesContext instead.
func (c *Conn) GetAllProperties(unit string) (map[string]interface{}, error) {
func (c *Conn) GetAllProperties(unit string) (map[string]any, error) {
return c.GetAllPropertiesContext(context.Background(), unit)
}
// GetAllPropertiesContext takes the (unescaped) unit name and returns all of
// its dbus object properties.
func (c *Conn) GetAllPropertiesContext(ctx context.Context, unit string) (map[string]interface{}, error) {
func (c *Conn) GetAllPropertiesContext(ctx context.Context, unit string) (map[string]any, error) {
path := unitPath(unit)
return c.getProperties(ctx, path, "")
}
@@ -331,20 +338,20 @@ func (c *Conn) GetServiceProperty(service string, propertyName string) (*Propert
return c.GetServicePropertyContext(context.Background(), service, propertyName)
}
// GetServiceProperty returns property for given service name and property name.
// GetServicePropertyContext returns property for given service name and property name.
func (c *Conn) GetServicePropertyContext(ctx context.Context, service string, propertyName string) (*Property, error) {
return c.getProperty(ctx, service, "org.freedesktop.systemd1.Service", propertyName)
}
// Deprecated: use GetUnitTypePropertiesContext instead.
func (c *Conn) GetUnitTypeProperties(unit string, unitType string) (map[string]interface{}, error) {
func (c *Conn) GetUnitTypeProperties(unit string, unitType string) (map[string]any, error) {
return c.GetUnitTypePropertiesContext(context.Background(), unit, unitType)
}
// GetUnitTypePropertiesContext returns the extra properties for a unit, specific to the unit type.
// Valid values for unitType: Service, Socket, Target, Device, Mount, Automount, Snapshot, Timer, Swap, Path, Slice, Scope.
// Returns "dbus.Error: Unknown interface" error if the unitType is not the correct type of the unit.
func (c *Conn) GetUnitTypePropertiesContext(ctx context.Context, unit string, unitType string) (map[string]interface{}, error) {
func (c *Conn) GetUnitTypePropertiesContext(ctx context.Context, unit string, unitType string) (map[string]any, error) {
path := unitPath(unit)
return c.getProperties(ctx, path, "org.freedesktop.systemd1."+unitType)
}
@@ -389,22 +396,22 @@ type UnitStatus struct {
JobPath dbus.ObjectPath // The job object path
}
type storeFunc func(retvalues ...interface{}) error
type storeFunc func(retvalues ...any) error
func (c *Conn) listUnitsInternal(f storeFunc) ([]UnitStatus, error) {
result := make([][]interface{}, 0)
result := make([][]any, 0)
err := f(&result)
if err != nil {
return nil, err
}
resultInterface := make([]interface{}, len(result))
resultInterface := make([]any, len(result))
for i := range result {
resultInterface[i] = result[i]
}
status := make([]UnitStatus, len(result))
statusInterface := make([]interface{}, len(status))
statusInterface := make([]any, len(status))
for i := range status {
statusInterface[i] = &status[i]
}
@@ -499,19 +506,19 @@ type UnitFile struct {
}
func (c *Conn) listUnitFilesInternal(f storeFunc) ([]UnitFile, error) {
result := make([][]interface{}, 0)
result := make([][]any, 0)
err := f(&result)
if err != nil {
return nil, err
}
resultInterface := make([]interface{}, len(result))
resultInterface := make([]any, len(result))
for i := range result {
resultInterface[i] = result[i]
}
files := make([]UnitFile, len(result))
fileInterface := make([]interface{}, len(files))
fileInterface := make([]any, len(files))
for i := range files {
fileInterface[i] = &files[i]
}
@@ -529,7 +536,7 @@ func (c *Conn) ListUnitFiles() ([]UnitFile, error) {
return c.ListUnitFilesContext(context.Background())
}
// ListUnitFiles returns an array of all available units on disk.
// ListUnitFilesContext returns an array of all available units on disk.
func (c *Conn) ListUnitFilesContext(ctx context.Context) ([]UnitFile, error) {
return c.listUnitFilesInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitFiles", 0).Store)
}
@@ -569,19 +576,19 @@ func (c *Conn) LinkUnitFiles(files []string, runtime bool, force bool) ([]LinkUn
// or unlink), the file name of the symlink and the destination of the
// symlink.
func (c *Conn) LinkUnitFilesContext(ctx context.Context, files []string, runtime bool, force bool) ([]LinkUnitFileChange, error) {
result := make([][]interface{}, 0)
result := make([][]any, 0)
err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.LinkUnitFiles", 0, files, runtime, force).Store(&result)
if err != nil {
return nil, err
}
resultInterface := make([]interface{}, len(result))
resultInterface := make([]any, len(result))
for i := range result {
resultInterface[i] = result[i]
}
changes := make([]LinkUnitFileChange, len(result))
changesInterface := make([]interface{}, len(changes))
changesInterface := make([]any, len(changes))
for i := range changes {
changesInterface[i] = &changes[i]
}
@@ -618,19 +625,19 @@ func (c *Conn) EnableUnitFiles(files []string, runtime bool, force bool) (bool,
func (c *Conn) EnableUnitFilesContext(ctx context.Context, files []string, runtime bool, force bool) (bool, []EnableUnitFileChange, error) {
var carries_install_info bool
result := make([][]interface{}, 0)
result := make([][]any, 0)
err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.EnableUnitFiles", 0, files, runtime, force).Store(&carries_install_info, &result)
if err != nil {
return false, nil, err
}
resultInterface := make([]interface{}, len(result))
resultInterface := make([]any, len(result))
for i := range result {
resultInterface[i] = result[i]
}
changes := make([]EnableUnitFileChange, len(result))
changesInterface := make([]interface{}, len(changes))
changesInterface := make([]any, len(changes))
for i := range changes {
changesInterface[i] = &changes[i]
}
@@ -667,19 +674,19 @@ func (c *Conn) DisableUnitFiles(files []string, runtime bool) ([]DisableUnitFile
// symlink or unlink), the file name of the symlink and the destination of the
// symlink.
func (c *Conn) DisableUnitFilesContext(ctx context.Context, files []string, runtime bool) ([]DisableUnitFileChange, error) {
result := make([][]interface{}, 0)
result := make([][]any, 0)
err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.DisableUnitFiles", 0, files, runtime).Store(&result)
if err != nil {
return nil, err
}
resultInterface := make([]interface{}, len(result))
resultInterface := make([]any, len(result))
for i := range result {
resultInterface[i] = result[i]
}
changes := make([]DisableUnitFileChange, len(result))
changesInterface := make([]interface{}, len(changes))
changesInterface := make([]any, len(changes))
for i := range changes {
changesInterface[i] = &changes[i]
}
@@ -713,19 +720,19 @@ func (c *Conn) MaskUnitFiles(files []string, runtime bool, force bool) ([]MaskUn
// runtime only (true, /run/systemd/..), or persistently (false,
// /etc/systemd/..).
func (c *Conn) MaskUnitFilesContext(ctx context.Context, files []string, runtime bool, force bool) ([]MaskUnitFileChange, error) {
result := make([][]interface{}, 0)
result := make([][]any, 0)
err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.MaskUnitFiles", 0, files, runtime, force).Store(&result)
if err != nil {
return nil, err
}
resultInterface := make([]interface{}, len(result))
resultInterface := make([]any, len(result))
for i := range result {
resultInterface[i] = result[i]
}
changes := make([]MaskUnitFileChange, len(result))
changesInterface := make([]interface{}, len(changes))
changesInterface := make([]any, len(changes))
for i := range changes {
changesInterface[i] = &changes[i]
}
@@ -757,19 +764,19 @@ func (c *Conn) UnmaskUnitFiles(files []string, runtime bool) ([]UnmaskUnitFileCh
// for runtime only (true, /run/systemd/..), or persistently (false,
// /etc/systemd/..).
func (c *Conn) UnmaskUnitFilesContext(ctx context.Context, files []string, runtime bool) ([]UnmaskUnitFileChange, error) {
result := make([][]interface{}, 0)
result := make([][]any, 0)
err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.UnmaskUnitFiles", 0, files, runtime).Store(&result)
if err != nil {
return nil, err
}
resultInterface := make([]interface{}, len(result))
resultInterface := make([]any, len(result))
for i := range result {
resultInterface[i] = result[i]
}
changes := make([]UnmaskUnitFileChange, len(result))
changesInterface := make([]interface{}, len(changes))
changesInterface := make([]any, len(changes))
for i := range changes {
changesInterface[i] = &changes[i]
}
@@ -829,18 +836,18 @@ func (c *Conn) ListJobsContext(ctx context.Context) ([]JobStatus, error) {
}
func (c *Conn) listJobsInternal(ctx context.Context) ([]JobStatus, error) {
result := make([][]interface{}, 0)
result := make([][]any, 0)
if err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListJobs", 0).Store(&result); err != nil {
return nil, err
}
resultInterface := make([]interface{}, len(result))
resultInterface := make([]any, len(result))
for i := range result {
resultInterface[i] = result[i]
}
status := make([]JobStatus, len(result))
statusInterface := make([]interface{}, len(status))
statusInterface := make([]any, len(status))
for i := range status {
statusInterface[i] = &status[i]
}
@@ -852,13 +859,18 @@ func (c *Conn) listJobsInternal(ctx context.Context) ([]JobStatus, error) {
return status, nil
}
// Freeze the cgroup associated with the unit.
// Note that FreezeUnit and ThawUnit are only supported on systems running with cgroup v2.
// FreezeUnit freezes the cgroup associated with the unit.
// Note that FreezeUnit and [ThawUnit] are only supported on systems running with cgroup v2.
func (c *Conn) FreezeUnit(ctx context.Context, unit string) error {
return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.FreezeUnit", 0, unit).Store()
}
// Unfreeze the cgroup associated with the unit.
// ThawUnit unfreezes the cgroup associated with the unit.
func (c *Conn) ThawUnit(ctx context.Context, unit string) error {
return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ThawUnit", 0, unit).Store()
}
// AttachProcessesToUnit moves existing processes, identified by pids, into an existing systemd unit.
func (c *Conn) AttachProcessesToUnit(ctx context.Context, unit, subcgroup string, pids []uint32) error {
return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.AttachProcessesToUnit", 0, unit, subcgroup, pids).Store()
}

View File

@@ -70,7 +70,7 @@ func (c *Conn) dispatch() {
switch signal.Name {
case "org.freedesktop.systemd1.Manager.JobRemoved":
unitName := signal.Body[2].(string)
c.sysobj.Call("org.freedesktop.systemd1.Manager.GetUnit", 0, unitName).Store(&unitPath)
_ = c.sysobj.Call("org.freedesktop.systemd1.Manager.GetUnit", 0, unitName).Store(&unitPath)
case "org.freedesktop.systemd1.Manager.UnitNew":
unitPath = signal.Body[1].(dbus.ObjectPath)
case "org.freedesktop.DBus.Properties.PropertiesChanged":
@@ -262,7 +262,7 @@ func (c *Conn) shouldIgnore(path dbus.ObjectPath) bool {
return ok && t >= time.Now().UnixNano()
}
func (c *Conn) updateIgnore(path dbus.ObjectPath, info map[string]interface{}) {
func (c *Conn) updateIgnore(path dbus.ObjectPath, info map[string]any) {
loadState, ok := info["LoadState"].(string)
if !ok {
return

View File

@@ -40,8 +40,8 @@ func (s *SubscriptionSet) Subscribe() (<-chan map[string]*UnitStatus, <-chan err
}
// NewSubscriptionSet returns a new subscription set.
func (conn *Conn) NewSubscriptionSet() *SubscriptionSet {
return &SubscriptionSet{newSet(), conn}
func (c *Conn) NewSubscriptionSet() *SubscriptionSet {
return &SubscriptionSet{newSet(), c}
}
// mismatchUnitStatus returns true if the provided UnitStatus objects

View File

@@ -1,26 +1,28 @@
version: "2"
run:
timeout: 1m
tests: true
linters:
disable-all: true
enable:
default: none
enable: # please keep this alphabetized
- asasalint
- asciicheck
- copyloopvar
- dupl
- errcheck
- forcetypeassert
- goconst
- gocritic
- gofmt
- goimports
- gosimple
- govet
- ineffassign
- misspell
- musttag
- revive
- staticcheck
- typecheck
- unused
issues:
exclude-use-default: false
max-issues-per-linter: 0
max-same-issues: 10

View File

@@ -77,7 +77,7 @@ func newSink(fn func(prefix, args string), formatter Formatter) logr.LogSink {
write: fn,
}
// For skipping fnlogger.Info and fnlogger.Error.
l.Formatter.AddCallDepth(1)
l.AddCallDepth(1) // via Formatter
return l
}
@@ -164,17 +164,17 @@ type fnlogger struct {
}
func (l fnlogger) WithName(name string) logr.LogSink {
l.Formatter.AddName(name)
l.AddName(name) // via Formatter
return &l
}
func (l fnlogger) WithValues(kvList ...any) logr.LogSink {
l.Formatter.AddValues(kvList)
l.AddValues(kvList) // via Formatter
return &l
}
func (l fnlogger) WithCallDepth(depth int) logr.LogSink {
l.Formatter.AddCallDepth(depth)
l.AddCallDepth(depth) // via Formatter
return &l
}

View File

@@ -1,18 +1,35 @@
version: "2"
linters:
enable:
- gosimple
- gci
- gofmt
- gocritic
- misspell
- goimports
- staticcheck
- errcheck
- govet
- misspell
- gocritic
linters-settings:
gci:
sections:
- standard
- default
- prefix(github.com/safchain/ethtool)
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
paths:
- third_party$
- builtin$
- examples$
formatters:
enable:
- gci
- gofmt
- goimports
settings:
gci:
sections:
- standard
- default
- prefix(github.com/safchain/ethtool)
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$

View File

@@ -3,5 +3,6 @@ extends: default
rules:
document-start: disable
line-length: disable
truthy:
check-keys: false

View File

@@ -29,7 +29,8 @@ import (
"bytes"
"encoding/hex"
"fmt"
"strings"
"sync"
"time"
"unsafe"
"golang.org/x/sys/unix"
@@ -53,37 +54,75 @@ const (
ETH_SS_FEATURES = 4
// CMD supported
ETHTOOL_GSET = 0x00000001 /* Get settings. */
ETHTOOL_SSET = 0x00000002 /* Set settings. */
ETHTOOL_GWOL = 0x00000005 /* Get wake-on-lan options. */
ETHTOOL_SWOL = 0x00000006 /* Set wake-on-lan options. */
ETHTOOL_GDRVINFO = 0x00000003 /* Get driver info. */
ETHTOOL_GMSGLVL = 0x00000007 /* Get driver message level */
ETHTOOL_SMSGLVL = 0x00000008 /* Set driver msg level. */
ETHTOOL_GSET = 0x00000001 /* Get settings. */
ETHTOOL_SSET = 0x00000002 /* Set settings. */
ETHTOOL_GWOL = 0x00000005 /* Get wake-on-lan options. */
ETHTOOL_SWOL = 0x00000006 /* Set wake-on-lan options. */
ETHTOOL_GDRVINFO = 0x00000003 /* Get driver info. */
ETHTOOL_GMSGLVL = 0x00000007 /* Get driver message level */
ETHTOOL_SMSGLVL = 0x00000008 /* Set driver msg level. */
ETHTOOL_GLINKSETTINGS = unix.ETHTOOL_GLINKSETTINGS // 0x4c
ETHTOOL_SLINKSETTINGS = unix.ETHTOOL_SLINKSETTINGS // 0x4d
// Get link status for host, i.e. whether the interface *and* the
// physical port (if there is one) are up (ethtool_value).
ETHTOOL_GLINK = 0x0000000a
ETHTOOL_GCOALESCE = 0x0000000e /* Get coalesce config */
ETHTOOL_SCOALESCE = 0x0000000f /* Set coalesce config */
ETHTOOL_GRINGPARAM = 0x00000010 /* Get ring parameters */
ETHTOOL_SRINGPARAM = 0x00000011 /* Set ring parameters. */
ETHTOOL_GPAUSEPARAM = 0x00000012 /* Get pause parameters */
ETHTOOL_SPAUSEPARAM = 0x00000013 /* Set pause parameters. */
ETHTOOL_GSTRINGS = 0x0000001b /* Get specified string set */
ETHTOOL_GSTATS = 0x0000001d /* Get NIC-specific statistics */
ETHTOOL_GPERMADDR = 0x00000020 /* Get permanent hardware address */
ETHTOOL_GFLAGS = 0x00000025 /* Get flags bitmap(ethtool_value) */
ETHTOOL_GPFLAGS = 0x00000027 /* Get driver-private flags bitmap */
ETHTOOL_SPFLAGS = 0x00000028 /* Set driver-private flags bitmap */
ETHTOOL_GSSET_INFO = 0x00000037 /* Get string set info */
ETHTOOL_GFEATURES = 0x0000003a /* Get device offload settings */
ETHTOOL_SFEATURES = 0x0000003b /* Change device offload settings */
ETHTOOL_GCHANNELS = 0x0000003c /* Get no of channels */
ETHTOOL_SCHANNELS = 0x0000003d /* Set no of channels */
ETHTOOL_GET_TS_INFO = 0x00000041 /* Get time stamping and PHC info */
ETHTOOL_GMODULEINFO = 0x00000042 /* Get plug-in module information */
ETHTOOL_GMODULEEEPROM = 0x00000043 /* Get plug-in module eeprom */
ETHTOOL_GLINK = 0x0000000a
ETHTOOL_GCOALESCE = 0x0000000e /* Get coalesce config */
ETHTOOL_SCOALESCE = 0x0000000f /* Set coalesce config */
ETHTOOL_GRINGPARAM = 0x00000010 /* Get ring parameters */
ETHTOOL_SRINGPARAM = 0x00000011 /* Set ring parameters. */
ETHTOOL_GPAUSEPARAM = 0x00000012 /* Get pause parameters */
ETHTOOL_SPAUSEPARAM = 0x00000013 /* Set pause parameters. */
ETHTOOL_GSTRINGS = 0x0000001b /* Get specified string set */
ETHTOOL_PHYS_ID = 0x0000001c /* Identify the NIC */
ETHTOOL_GSTATS = 0x0000001d /* Get NIC-specific statistics */
ETHTOOL_GPERMADDR = 0x00000020 /* Get permanent hardware address */
ETHTOOL_GFLAGS = 0x00000025 /* Get flags bitmap(ethtool_value) */
ETHTOOL_GPFLAGS = 0x00000027 /* Get driver-private flags bitmap */
ETHTOOL_SPFLAGS = 0x00000028 /* Set driver-private flags bitmap */
ETHTOOL_GSSET_INFO = 0x00000037 /* Get string set info */
ETHTOOL_GFEATURES = 0x0000003a /* Get device offload settings */
ETHTOOL_SFEATURES = 0x0000003b /* Change device offload settings */
ETHTOOL_GCHANNELS = 0x0000003c /* Get no of channels */
ETHTOOL_SCHANNELS = 0x0000003d /* Set no of channels */
ETHTOOL_GET_TS_INFO = 0x00000041 /* Get time stamping and PHC info */
ETHTOOL_GMODULEINFO = 0x00000042 /* Get plug-in module information */
ETHTOOL_GMODULEEEPROM = 0x00000043 /* Get plug-in module eeprom */
ETHTOOL_GRXFHINDIR = 0x00000038 /* Get RX flow hash indir'n table */
ETHTOOL_SRXFHINDIR = 0x00000039 /* Set RX flow hash indir'n table */
ETH_RXFH_INDIR_NO_CHANGE = 0xFFFFFFFF
// Speed and Duplex unknowns/constants (Manually defined based on <linux/ethtool.h>)
SPEED_UNKNOWN = 0xffffffff // ((__u32)-1) SPEED_UNKNOWN
DUPLEX_HALF = 0x00 // DUPLEX_HALF
DUPLEX_FULL = 0x01 // DUPLEX_FULL
DUPLEX_UNKNOWN = 0xff // DUPLEX_UNKNOWN
// Port types (Manually defined based on <linux/ethtool.h>)
PORT_TP = 0x00 // PORT_TP
PORT_AUI = 0x01 // PORT_AUI
PORT_MII = 0x02 // PORT_MII
PORT_FIBRE = 0x03 // PORT_FIBRE
PORT_BNC = 0x04 // PORT_BNC
PORT_DA = 0x05 // PORT_DA
PORT_NONE = 0xef // PORT_NONE
PORT_OTHER = 0xff // PORT_OTHER
// Autoneg settings (Manually defined based on <linux/ethtool.h>)
AUTONEG_DISABLE = 0x00 // AUTONEG_DISABLE
AUTONEG_ENABLE = 0x01 // AUTONEG_ENABLE
// MDIX states (Manually defined based on <linux/ethtool.h>)
ETH_TP_MDI_INVALID = 0x00 // ETH_TP_MDI_INVALID
ETH_TP_MDI = 0x01 // ETH_TP_MDI
ETH_TP_MDI_X = 0x02 // ETH_TP_MDI_X
ETH_TP_MDI_AUTO = 0x03 // Control value ETH_TP_MDI_AUTO
// Link mode mask bits count (Manually defined based on ethtool.h)
ETHTOOL_LINK_MODE_MASK_NBITS = 92 // __ETHTOOL_LINK_MODE_MASK_NBITS
// Calculate max nwords based on NBITS using the manually defined constant
MAX_LINK_MODE_MASK_NWORDS = (ETHTOOL_LINK_MODE_MASK_NBITS + 31) / 32 // = 3
)
// MAX_GSTRINGS maximum number of stats entries that ethtool can
@@ -100,6 +139,27 @@ const (
MAX_SSET_INFO = 64
)
const (
DEFAULT_BLINK_DURATION = 60 * time.Second
)
var (
gstringsPool = sync.Pool{
New: func() interface{} {
// new() will allocate and zero-initialize the struct.
// The large data array within ethtoolGStrings will be zeroed.
return new(EthtoolGStrings)
},
}
statsPool = sync.Pool{
New: func() interface{} {
// new() will allocate and zero-initialize the struct.
// The large data array within ethtoolStats will be zeroed.
return new(EthtoolStats)
},
}
)
type ifreq struct {
ifr_name [IFNAMSIZ]byte
ifr_data uintptr
@@ -209,6 +269,12 @@ type Coalesce struct {
RateSampleInterval uint32
}
// IdentityConf is an identity config for an interface
type IdentityConf struct {
Cmd uint32
Duration uint32
}
// WoL options
const (
WAKE_PHY = 1 << 0
@@ -324,14 +390,14 @@ type TimestampingInformation struct {
rxReserved [3]uint32
}
type ethtoolGStrings struct {
type EthtoolGStrings struct {
cmd uint32
string_set uint32
len uint32
data [MAX_GSTRINGS * ETH_GSTRING_LEN]byte
}
type ethtoolStats struct {
type EthtoolStats struct {
cmd uint32
n_stats uint32
data [MAX_GSTRINGS]uint64
@@ -389,6 +455,22 @@ type Ethtool struct {
fd int
}
// max values for my setup dont know how to make this dynamic
const MAX_INDIR_SIZE = 256
const MAX_CORES = 32
type Indir struct {
Cmd uint32
Size uint32
RingIndex [MAX_INDIR_SIZE]uint32 // statically definded otherwise crash
}
type SetIndir struct {
Equal uint8 // used to set number of cores
Weight []uint32 // used to select cores
}
// Convert zero-terminated array of chars (string in C) to a Go string.
func goString(s []byte) string {
strEnd := bytes.IndexByte(s, 0)
@@ -426,7 +508,7 @@ func (e *Ethtool) ModuleEeprom(intf string) ([]byte, error) {
return eeprom.data[:eeprom.len], nil
}
// ModuleEeprom returns Eeprom information of the given interface name.
// ModuleEepromHex returns Eeprom information as hexadecimal string
func (e *Ethtool) ModuleEepromHex(intf string) (string, error) {
eeprom, _, err := e.getModuleEeprom(intf)
if err != nil {
@@ -461,6 +543,36 @@ func (e *Ethtool) DriverInfo(intf string) (DrvInfo, error) {
return drvInfo, nil
}
// GetIndir retrieves the indirection table of the given interface name.
func (e *Ethtool) GetIndir(intf string) (Indir, error) {
indir, err := e.getIndir(intf)
if err != nil {
return Indir{}, err
}
return indir, nil
}
// SetIndir sets the indirection table of the given interface from the SetIndir struct
func (e *Ethtool) SetIndir(intf string, setIndir SetIndir) (Indir, error) {
if setIndir.Equal != 0 && setIndir.Weight != nil {
return Indir{}, fmt.Errorf("equal and weight options are mutually exclusive")
}
indir, err := e.GetIndir(intf)
if err != nil {
return Indir{}, err
}
newindir, err := e.setIndir(intf, indir, setIndir)
if err != nil {
return Indir{}, err
}
return newindir, nil
}
// GetChannels returns the number of channels for the given interface name.
func (e *Ethtool) GetChannels(intf string) (Channels, error) {
channels, err := e.getChannels(intf)
@@ -586,6 +698,92 @@ func (e *Ethtool) getDriverInfo(intf string) (ethtoolDrvInfo, error) {
return drvinfo, nil
}
// parsing of do_grxfhindir from ethtool.c
func (e *Ethtool) getIndir(intf string) (Indir, error) {
indir_head := Indir{
Cmd: ETHTOOL_GRXFHINDIR,
Size: 0,
}
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&indir_head))); err != nil {
return Indir{}, err
}
indir := Indir{
Cmd: ETHTOOL_GRXFHINDIR,
Size: indir_head.Size,
}
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&indir))); err != nil {
return Indir{}, err
}
return indir, nil
}
// parsing of do_srxfhindir from ethtool.c
func (e *Ethtool) setIndir(intf string, indir Indir, setIndir SetIndir) (Indir, error) {
err := fillIndirTable(&indir.Size, indir.RingIndex[:], 0, 0, int(setIndir.Equal), setIndir.Weight, uint32(len(setIndir.Weight)))
if err != nil {
return Indir{}, err
}
if indir.Size == ETH_RXFH_INDIR_NO_CHANGE {
indir.Size = MAX_INDIR_SIZE
return indir, nil
}
indir.Cmd = ETHTOOL_SRXFHINDIR
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&indir))); err != nil {
return Indir{}, err
}
return indir, nil
}
func fillIndirTable(indirSize *uint32, indir []uint32, rxfhindirDefault int,
rxfhindirStart int, rxfhindirEqual int, rxfhindirWeight []uint32,
numWeights uint32) error {
switch {
case rxfhindirEqual != 0:
for i := uint32(0); i < *indirSize; i++ {
indir[i] = uint32(rxfhindirStart) + (i % uint32(rxfhindirEqual))
}
case rxfhindirWeight != nil:
var sum, partial uint32 = 0, 0
var j, weight uint32
for j = range numWeights {
weight = rxfhindirWeight[j]
sum += weight
}
if sum == 0 {
return fmt.Errorf("at least one weight must be non-zero")
}
if sum > *indirSize {
return fmt.Errorf("total weight exceeds the size of the indirection table")
}
j = ^uint32(0) // equivalent to -1 for unsigned
for i := uint32(0); i < *indirSize; i++ {
for i >= (*indirSize*partial)/sum {
j++
weight = rxfhindirWeight[j]
partial += weight
}
indir[i] = uint32(rxfhindirStart) + j
}
case rxfhindirDefault != 0:
*indirSize = 0
default:
*indirSize = ETH_RXFH_INDIR_NO_CHANGE
}
return nil
}
func (e *Ethtool) getChannels(intf string) (Channels, error) {
channels := Channels{
Cmd: ETHTOOL_GCHANNELS,
@@ -781,7 +979,7 @@ func (e *Ethtool) getNames(intf string, mask int) (map[string]uint, error) {
return nil, fmt.Errorf("ethtool currently doesn't support more than %d entries, received %d", MAX_GSTRINGS, length)
}
gstrings := ethtoolGStrings{
gstrings := EthtoolGStrings{
cmd: ETHTOOL_GSTRINGS,
string_set: uint32(mask),
len: length,
@@ -969,7 +1167,23 @@ func (e *Ethtool) LinkState(intf string) (uint32, error) {
}
// Stats retrieves stats of the given interface name.
// This maintains backward compatibility with existing code.
func (e *Ethtool) Stats(intf string) (map[string]uint64, error) {
// Create temporary buffers and delegate to StatsWithBuffer
gstrings := gstringsPool.Get().(*EthtoolGStrings)
stats := statsPool.Get().(*EthtoolStats)
defer func() {
gstringsPool.Put(gstrings)
statsPool.Put(stats)
}()
return e.StatsWithBuffer(intf, gstrings, stats)
}
// StatsWithBuffer retrieves stats of the given interface name using pre-allocated buffers.
// This allows the caller to control where the large structures are allocated,
// which can be useful to avoid heap allocations in Go 1.24+.
func (e *Ethtool) StatsWithBuffer(intf string, gstringsPtr *EthtoolGStrings, statsPtr *EthtoolStats) (map[string]uint64, error) {
drvinfo := ethtoolDrvInfo{
cmd: ETHTOOL_GDRVINFO,
}
@@ -978,41 +1192,37 @@ func (e *Ethtool) Stats(intf string) (map[string]uint64, error) {
return nil, err
}
if drvinfo.n_stats*ETH_GSTRING_LEN > MAX_GSTRINGS*ETH_GSTRING_LEN {
if drvinfo.n_stats > MAX_GSTRINGS {
return nil, fmt.Errorf("ethtool currently doesn't support more than %d entries, received %d", MAX_GSTRINGS, drvinfo.n_stats)
}
gstrings := ethtoolGStrings{
cmd: ETHTOOL_GSTRINGS,
string_set: ETH_SS_STATS,
len: drvinfo.n_stats,
data: [MAX_GSTRINGS * ETH_GSTRING_LEN]byte{},
}
gstringsPtr.cmd = ETHTOOL_GSTRINGS
gstringsPtr.string_set = ETH_SS_STATS
gstringsPtr.len = drvinfo.n_stats
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&gstrings))); err != nil {
if err := e.ioctl(intf, uintptr(unsafe.Pointer(gstringsPtr))); err != nil {
return nil, err
}
stats := ethtoolStats{
cmd: ETHTOOL_GSTATS,
n_stats: drvinfo.n_stats,
data: [MAX_GSTRINGS]uint64{},
}
statsPtr.cmd = ETHTOOL_GSTATS
statsPtr.n_stats = drvinfo.n_stats
if err := e.ioctl(intf, uintptr(unsafe.Pointer(&stats))); err != nil {
if err := e.ioctl(intf, uintptr(unsafe.Pointer(statsPtr))); err != nil {
return nil, err
}
result := make(map[string]uint64)
result := make(map[string]uint64, drvinfo.n_stats)
for i := 0; i != int(drvinfo.n_stats); i++ {
b := gstrings.data[i*ETH_GSTRING_LEN : i*ETH_GSTRING_LEN+ETH_GSTRING_LEN]
strEnd := strings.Index(string(b), "\x00")
b := gstringsPtr.data[i*ETH_GSTRING_LEN : (i+1)*ETH_GSTRING_LEN]
strEnd := bytes.IndexByte(b, 0)
if strEnd == -1 {
strEnd = ETH_GSTRING_LEN
}
key := string(b[:strEnd])
if len(key) != 0 {
result[key] = stats.data[i]
result[key] = statsPtr.data[i]
}
}
@@ -1024,6 +1234,20 @@ func (e *Ethtool) Close() {
unix.Close(e.fd)
}
// Identity the nic with blink duration, if not specify blink for 60 seconds
func (e *Ethtool) Identity(intf string, duration *time.Duration) error {
dur := uint32(DEFAULT_BLINK_DURATION.Seconds())
if duration != nil {
dur = uint32(duration.Seconds())
}
return e.identity(intf, IdentityConf{Duration: dur})
}
func (e *Ethtool) identity(intf string, identity IdentityConf) error {
identity.Cmd = ETHTOOL_PHYS_ID
return e.ioctl(intf, uintptr(unsafe.Pointer(&identity)))
}
// NewEthtool returns a new ethtool handler
func NewEthtool() (*Ethtool, error) {
fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM|unix.SOCK_CLOEXEC, unix.IPPROTO_IP)
@@ -1076,13 +1300,23 @@ func PermAddr(intf string) (string, error) {
return e.PermAddr(intf)
}
// Identity the nic with blink duration, if not specify blink infinity
func Identity(intf string, duration *time.Duration) error {
e, err := NewEthtool()
if err != nil {
return err
}
defer e.Close()
return e.Identity(intf, duration)
}
func supportedSpeeds(mask uint64) (ret []struct {
name string
mask uint64
speed uint64
}) {
for _, mode := range supportedCapabilities {
if ((1 << mode.mask) & mask) != 0 {
if mode.speed > 0 && ((1<<mode.mask)&mask) != 0 {
ret = append(ret, mode)
}
}

Some files were not shown because too many files have changed in this diff Show More