fix(deps): update module github.com/microsoft/hcsshim to v0.15.0-rc.3

Signed-off-by: Mend Renovate <bot@renovateapp.com>
This commit is contained in:
Mend Renovate
2026-07-26 17:28:16 +00:00
parent 1ec4fe3f2d
commit 4c87a4dad1
55 changed files with 881 additions and 130 deletions

2
go.mod
View File

@@ -16,7 +16,7 @@ require (
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c
github.com/Graylog2/go-gelf v0.0.0-20191017102106-1550ee647df0 // head of v2 branch
github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29 // see https://github.com/microsoft/hcsshim/pull/2545
github.com/Microsoft/hcsshim v0.15.0-rc.1
github.com/Microsoft/hcsshim v0.15.0-rc.3
github.com/RackSec/srslog v0.0.0-20180709174129-a4725f04ec91
github.com/aws/aws-sdk-go-v2 v1.43.0
github.com/aws/aws-sdk-go-v2/config v1.32.31

4
go.sum
View File

@@ -58,8 +58,8 @@ github.com/Masterminds/semver/v3 v3.5.0 h1:kQceYJfbupGfZOKZQg0kou0DgAKhzDg2NZPAw
github.com/Masterminds/semver/v3 v3.5.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29 h1:0kQAzHq8vLs7Pptv+7TxjdETLf/nIqJpIB4oC6Ba4vY=
github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29/go.mod h1:ZWa7ssZJT30CCDGJ7fk/2SBTq9BIQrrVjrcss0UW2s0=
github.com/Microsoft/hcsshim v0.15.0-rc.1 h1:FbbwtQmiD+BVHynGkx5S65JkLyhkEiiTP8nrpmg2SZw=
github.com/Microsoft/hcsshim v0.15.0-rc.1/go.mod h1:HWvvUPIy9HF6LotILj1G4VyS065rcLQ6tqj6tMUdOfI=
github.com/Microsoft/hcsshim v0.15.0-rc.3 h1:ZTNzOp0QwJ1EiL3zopSOawIG0j7zAvzJx0rBmcR6HJ0=
github.com/Microsoft/hcsshim v0.15.0-rc.3/go.mod h1:VhDiwXgb8cEJxO9H57YL4NNIYqvZKpqvSDcimLyo7m8=
github.com/ProtonMail/go-crypto v1.4.1 h1:9RfcZHqEQUvP8RzecWEUafnZVtEvrBVL9BiF67IQOfM=
github.com/ProtonMail/go-crypto v1.4.1/go.mod h1:e1OaTyu5SYVrO9gKOEhTc+5UcXtTUa+P3uLudwcgPqo=
github.com/RackSec/srslog v0.0.0-20180709174129-a4725f04ec91 h1:vX+gnvBc56EbWYrmlhYbFYRaeikAke1GL84N4BEYOFE=

View File

@@ -4,6 +4,11 @@
*.so
*.dylib
# manifest related generated files
*.syso
manifest.xml
*.exe.manifest
# Ignore vscode setting files
.vscode/
.idea/
@@ -51,3 +56,5 @@ go.work.sum
# keys and related artifacts
*.pem
*.cose
rust/target/

View File

@@ -6,7 +6,7 @@ generators = ["go", "go-grpc"]
before = ["./protobuf"]
# defaults are "/usr/local/include" and "/usr/include", which don't exist on Windows.
# override defaults to supress errors about non-existant directories.
# override defaults to supress errors about non-existent directories.
after = []
# This section maps protobuf imports to Go packages.
@@ -19,7 +19,8 @@ prefixes = [
"github.com/Microsoft/hcsshim/internal/shimdiag",
"github.com/Microsoft/hcsshim/internal/extendedtask",
"github.com/Microsoft/hcsshim/internal/computeagent",
"github.com/Microsoft/hcsshim/internal/controller",
"github.com/Microsoft/hcsshim/internal/ncproxyttrpc",
"github.com/Microsoft/hcsshim/internal/vmservice",
"github.com/Microsoft/hcsshim/pkg/migration",
]
generators = ["go", "go-ttrpc"]

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/main/core/runtime/v2/README.md).
For info on the [Runtime V2 API](https://github.com/containerd/containerd/blob/main/docs/runtime-v2.md).
Contrary to the typical Linux architecture of shim -> runc, the runhcs shim is used both to launch and manage the lifetime of containers.
@@ -68,6 +68,105 @@ To trial using the shim out with ctr.exe:
C:\> ctr.exe run --runtime io.containerd.runhcs.v1 --rm mcr.microsoft.com/windows/nanoserver:2004 windows-test cmd /c "echo Hello World!"
```
### Containerd Shim V2
The V2 shims are the rewrite of the Windows containerd shim. The V1 shim
([`containerd-shim-runhcs-v1`](./cmd/containerd-shim-runhcs-v1)) is a single, monolithic
binary that handles LCOW (Linux Containers on Windows), Hyper-V WCOW (Windows Containers on Windows), process-isolated
WCOW and host-process containers. In the V2 model that monolith is split into focused,
per-platform shims, each backed 1:1 by a sandbox.
V2 shims are used with containerd in the same way as the V1 shim, but the
API surface they expose is different. The V1 shim implemented only the containerd
[Task API](https://github.com/containerd/containerd/blob/main/docs/runtime-v2.md),
and used it to manage both the sandbox lifecycle and the container/process (task)
lifecycle through a single service. Each V2 shim instead splits these responsibilities
across the two APIs that containerd now provides for this purpose: the
[Sandbox API](https://github.com/containerd/containerd/blob/main/docs/sandbox-api.md)
is used to manage the sandbox, while the
[Task API](https://github.com/containerd/containerd/blob/main/docs/runtime-v2.md)
is used to manage containers and processes running inside it. Internally each V2 shim
implements these as separate sandbox and task services, alongside an auxiliary
`shimdiag` service used for diagnostics.
All three shims honor the same CRI pod model. A task annotated with
`"io.kubernetes.cri.container-type": "sandbox"` is treated as the pause/infra container
that creates the pod; sibling workload tasks set `"io.kubernetes.cri.container-type":
"container"` and reference their pause via `"io.kubernetes.cri.sandbox-id"`. What a
"sandbox" *physically* corresponds to depends on the shim, and is described in each
subsection below.
#### containerd-shim-lcow-v2
- **Purpose:** Runs Linux Containers on Windows (LCOW) — a Linux utility VM hosting Linux
containers.
- **Sandbox:** The Linux UVM. Each shim instance is backed 1:1 by a single UVM. This shim supports running
*multiple pods in the same UVM*, so a single shim instance may host more than one
CRI pods.
- **Tasks:** Linux containers and processes running inside the UVM, identified via the
same CRI annotations described above.
- **Implementation:** [`./cmd/containerd-shim-lcow-v2`](./cmd/containerd-shim-lcow-v2).
- **Build Tag:** lcow
- **Platform requirement:** Windows Server 2025 (build 26100) or later.
#### containerd-shim-wcow-v2
- **Purpose:** Runs Hyper-V isolated Windows containers (WCOW) — a Windows utility VM hosting
Process and/or Host Process Containers inside it.
- **Sandbox:** The Windows utility VM (UVM). Each shim instance is backed 1:1 by a single UVM.
- **Tasks:** the Windows containers and processes running inside the UVM, identified
via the standard CRI annotations described above.
- **Implementation:** coming soon.
- **Build Tag:** wcow
#### containerd-shim-process-v2
- **Purpose:** Runs Process-isolated Windows Server containers and Host
Process Containers — workloads that execute directly on the host with no utility VM.
- **Sandbox:** A *pause container*. The pause container is a minimal, long-lived
container that owns the pod's shared resources (such as the network namespace) and
keeps them alive while sibling workload containers are started, stopped or replaced.
This is the standard Kubernetes pod model: the pause container is the sandbox that
the rest of the pod attaches to.
- **Tasks:** the actual workload containers belonging to the pod, linked back to the
pause via the `io.kubernetes.cri.sandbox-id` annotation.
- **Implementation:** coming soon.
- **Build Tag:** process
##### Building
The V2 shim sources are guarded by the build tags as mentioned above, so the tag must be passed
to `go build`. For example the `LCOW` shim has `lcow` tag-
```powershell
C:\> $env:GOOS="windows"
C:\> go build -tags lcow .\cmd\containerd-shim-lcow-v2
```
Place the resulting `containerd-shim-lcow-v2.exe` in the same directory as `containerd.exe`,
the same as for the V1 shim.
##### Running unit tests
The shim's unit tests (and the rest of the tagged packages) are run with the
shim specific build tag:
```powershell
C:\> go test -tags lcow ./...
```
##### Running parity tests
The repository ships parity tests under [`./test/parity`](./test/parity) that feed
identical inputs through the legacy V1 and the new V2 pipelines and assert that the
resulting HCS ComputeSystem documents are equivalent. They live in the `test` Go
module and are also built with the build tag:
```powershell
C:\> cd test
C:\> go test -tags lcow ./parity/...
```
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.10
// protoc-gen-go v1.36.11
// protoc v5.26.0
// source: github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options/runhcs.proto
@@ -187,8 +187,9 @@ type Options struct {
// no_inherit_host_timezone specifies to skip inheriting the hosts time zone for WCOW UVMs and instead default to
// UTC.
NoInheritHostTimezone bool `protobuf:"varint,19,opt,name=no_inherit_host_timezone,json=noInheritHostTimezone,proto3" json:"no_inherit_host_timezone,omitempty"`
// scrub_logs enables removing environment variables and other potentially sensitive information from logs
ScrubLogs bool `protobuf:"varint,20,opt,name=scrub_logs,json=scrubLogs,proto3" json:"scrub_logs,omitempty"`
// scrub_logs controls removing environment variables and other potentially sensitive information from logs.
// If unset, scrubbing is enabled by default. Set explicitly to false to disable.
ScrubLogs *bool `protobuf:"varint,20,opt,name=scrub_logs,json=scrubLogs,proto3,oneof" json:"scrub_logs,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@@ -357,8 +358,8 @@ func (x *Options) GetNoInheritHostTimezone() bool {
}
func (x *Options) GetScrubLogs() bool {
if x != nil {
return x.ScrubLogs
if x != nil && x.ScrubLogs != nil {
return *x.ScrubLogs
}
return false
}
@@ -477,7 +478,7 @@ var File_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_options_runh
const file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_options_runhcs_proto_rawDesc = "" +
"\n" +
"Ogithub.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options/runhcs.proto\x12\x14containerd.runhcs.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"\xd9\t\n" +
"Ogithub.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options/runhcs.proto\x12\x14containerd.runhcs.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"\xed\t\n" +
"\aOptions\x12\x14\n" +
"\x05debug\x18\x01 \x01(\bR\x05debug\x12F\n" +
"\n" +
@@ -501,9 +502,9 @@ const file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_options_ru
"\tlog_level\x18\x10 \x01(\tR\blogLevel\x124\n" +
"\x17io_retry_timeout_in_sec\x18\x11 \x01(\x05R\x13ioRetryTimeoutInSec\x12\x82\x01\n" +
"\x1ddefault_container_annotations\x18\x12 \x03(\v2>.containerd.runhcs.v1.Options.DefaultContainerAnnotationsEntryR\x1bdefaultContainerAnnotations\x127\n" +
"\x18no_inherit_host_timezone\x18\x13 \x01(\bR\x15noInheritHostTimezone\x12\x1d\n" +
"\x18no_inherit_host_timezone\x18\x13 \x01(\bR\x15noInheritHostTimezone\x12\"\n" +
"\n" +
"scrub_logs\x18\x14 \x01(\bR\tscrubLogs\x1aN\n" +
"scrub_logs\x18\x14 \x01(\bH\x00R\tscrubLogs\x88\x01\x01\x1aN\n" +
" DefaultContainerAnnotationsEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\")\n" +
@@ -514,7 +515,8 @@ const file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_options_ru
"\x10SandboxIsolation\x12\v\n" +
"\aPROCESS\x10\x00\x12\x0e\n" +
"\n" +
"HYPERVISOR\x10\x01\"\xb6\x03\n" +
"HYPERVISOR\x10\x01B\r\n" +
"\v_scrub_logs\"\xb6\x03\n" +
"\x0eProcessDetails\x12\x1d\n" +
"\n" +
"image_name\x18\x01 \x01(\tR\timageName\x129\n" +
@@ -570,6 +572,7 @@ func file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_options_run
if File_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_options_runhcs_proto != nil {
return
}
file_github_com_Microsoft_hcsshim_cmd_containerd_shim_runhcs_v1_options_runhcs_proto_msgTypes[0].OneofWrappers = []any{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{

View File

@@ -105,8 +105,9 @@ message Options {
// UTC.
bool no_inherit_host_timezone = 19;
// scrub_logs enables removing environment variables and other potentially sensitive information from logs
bool scrub_logs = 20;
// scrub_logs controls removing environment variables and other potentially sensitive information from logs.
// If unset, scrubbing is enabled by default. Set explicitly to false to disable.
optional bool scrub_logs = 20;
}
// ProcessDetails contains additional information about a process. This is the additional

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.10
// protoc-gen-go v1.36.11
// protoc v5.26.0
// source: github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/stats/stats.proto

View File

@@ -18,12 +18,12 @@ import (
// NamespaceResourceEndpoint represents an Endpoint attached to a Namespace.
type NamespaceResourceEndpoint struct {
Id string `json:"ID,"`
Id string `json:"ID"`
}
// NamespaceResourceContainer represents a Container attached to a Namespace.
type NamespaceResourceContainer struct {
Id string `json:"ID,"`
Id string `json:"ID"`
}
// NamespaceResourceType determines whether the Namespace resource is a Container or Endpoint.
@@ -38,8 +38,8 @@ var (
// NamespaceResource is associated with a namespace
type NamespaceResource struct {
Type NamespaceResourceType `json:","` // Container, Endpoint
Data json.RawMessage `json:","`
Type NamespaceResourceType `json:""` // Container, Endpoint
Data json.RawMessage `json:""`
}
// NamespaceType determines whether the Namespace is for a Host or Guest

View File

@@ -127,8 +127,8 @@ const (
// AclPolicySetting creates firewall rules on an endpoint
type AclPolicySetting struct {
Protocols string `json:",omitempty"` // EX: 6 (TCP), 17 (UDP), 1 (ICMPv4), 58 (ICMPv6), 2 (IGMP)
Action ActionType `json:","`
Direction DirectionType `json:","`
Action ActionType `json:""`
Direction DirectionType `json:""`
LocalAddresses string `json:",omitempty"`
RemoteAddresses string `json:",omitempty"`
LocalPorts string `json:",omitempty"`
@@ -161,8 +161,8 @@ type SDNRoutePolicySetting struct {
// NetworkACLPolicySetting creates ACL rules on a network
type NetworkACLPolicySetting struct {
Protocols string `json:",omitempty"` // EX: 6 (TCP), 17 (UDP), 1 (ICMPv4), 58 (ICMPv6), 2 (IGMP)
Action ActionType `json:","`
Direction DirectionType `json:","`
Action ActionType `json:""`
Direction DirectionType `json:""`
LocalAddresses string `json:",omitempty"`
RemoteAddresses string `json:",omitempty"`
LocalPorts string `json:",omitempty"`
@@ -267,12 +267,12 @@ type LayerConstraintNetworkPolicySetting struct {
// VlanPolicySetting isolates a subnet with VLAN tagging.
type VlanPolicySetting struct {
IsolationId uint32 `json:","`
IsolationId uint32 `json:""`
}
// VsidPolicySetting isolates a subnet with VSID tagging.
type VsidPolicySetting struct {
IsolationId uint32 `json:","`
IsolationId uint32 `json:""`
}
// RemoteSubnetRoutePolicySetting creates remote subnet route rules on a network
@@ -330,7 +330,7 @@ type L4ProxyPolicySetting struct {
type TierAclRule struct {
Id string `json:",omitempty"`
Protocols string `json:",omitempty"`
TierAclRuleAction ActionType `json:","`
TierAclRuleAction ActionType `json:""`
LocalAddresses string `json:",omitempty"`
RemoteAddresses string `json:",omitempty"`
LocalPorts string `json:",omitempty"`
@@ -340,8 +340,8 @@ type TierAclRule struct {
// TierAclPolicySetting represents a Tier containing ACLs
type TierAclPolicySetting struct {
Name string `json:","`
Direction DirectionType `json:","`
Name string `json:""`
Direction DirectionType `json:""`
Order uint16 `json:""`
TierAclRules []TierAclRule `json:",omitempty"`
}

View File

@@ -8,8 +8,17 @@ import (
"github.com/Microsoft/hcsshim/internal/hcs/schema1"
hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2"
"github.com/Microsoft/hcsshim/internal/jobobject"
)
// MigrationState captures the host-side identifiers needed to rebind a
// process during live migration. Zero fields mean the host doesn't use the
// corresponding facility (e.g. vsock or a GCS bridge).
type MigrationState struct {
StdinPort, StdoutPort, StderrPort uint32
WaitCallID int64
}
// Process is the interface for an OS process running in a container or utility VM.
type Process interface {
// Close releases resources associated with the process and closes the
@@ -27,6 +36,10 @@ type Process interface {
CloseStderr(ctx context.Context) error
// Pid returns the process ID.
Pid() int
// MigrationState returns the host-side identifiers (vsock stdio ports
// and GCS bridge wait-call id) needed by the live-migration save path.
// Zero fields indicate the host doesn't use those facilities.
MigrationState() MigrationState
// Stdio returns the stdio streams for a process. These may be nil if a stream
// was not requested during CreateProcess.
Stdio() (_ io.Writer, _ io.Reader, _ io.Reader)
@@ -96,4 +109,10 @@ type Container interface {
WaitError() error
// Modify sends a request to modify container resources
Modify(ctx context.Context, config interface{}) error
// SetCPUGroupAffinities pins the container's processes to the given CPU
// group affinities. It exists because CPU affinity is not part of the HCS
// container Processor schema and must be applied out of band (on the silo's
// job object for process-isolated Windows containers). Implementations that
// do not support setting CPU affinity return errdefs.ErrNotImplemented.
SetCPUGroupAffinities(ctx context.Context, affinities []jobobject.GroupAffinity) error
}

View File

@@ -57,6 +57,12 @@ func (process *Process) Pid() int {
return process.processID
}
// MigrationState returns the zero value: HCS processes route stdio over
// named pipes and don't use a GCS bridge.
func (process *Process) MigrationState() cow.MigrationState {
return cow.MigrationState{}
}
// SystemID returns the ID of the process's compute system.
func (process *Process) SystemID() string {
return process.system.ID()

View File

@@ -222,6 +222,7 @@ type GuestDefinedCapabilities struct {
DeleteContainerStateSupported bool `json:",omitempty"`
UpdateContainerSupported bool `json:",omitempty"`
LogForwardingSupported bool `json:",omitempty"`
HostProcessContainerSupported bool `json:",omitempty"`
}
// GuestConnectionInfo is the structure of an iterm return by a GuestConnection call on a utility VM

View File

@@ -9,7 +9,7 @@
package hcsschema
// ComPort specifies the named pipe that will be used for the port, with empty string indicating a disconnected port.
// ComPort specifies the named pipe that will be used for the port, with empty string indicating a disconnected port.
type ComPort struct {
NamedPipe string `json:"NamedPipe,omitempty"`

View File

@@ -9,6 +9,15 @@
package hcsschema
// IsolationType describes the isolation mode of a container.
type IsolationType string
const (
// IsolationTypeHostProcess is a privileged (Windows) HostProcess
// container that shares the host namespace.
IsolationTypeHostProcess IsolationType = "HostProcess"
)
type Container struct {
GuestOs *GuestOs `json:"GuestOs,omitempty"`
@@ -33,4 +42,6 @@ type Container struct {
AssignedDevices []Device `json:"AssignedDevices,omitempty"`
AdditionalDeviceNamespace *ContainerDefinitionDevice `json:"AdditionalDeviceNamespace,omitempty"`
IsolationType IsolationType `json:"IsolationType,omitempty"`
}

View File

@@ -9,7 +9,7 @@
package hcsschema
// memory usage as viewed from within the container
// memory usage as viewed from within the container
type ContainerMemoryInformation struct {
TotalPhysicalBytes int32 `json:"TotalPhysicalBytes,omitempty"`

View File

@@ -9,7 +9,7 @@
package hcsschema
// Information about the guest.
// Information about the guest.
type GuestConnectionInfo struct {
// Each schema version x.y stands for the range of versions a.b where a==x and b<=y. This list comes from the SupportedSchemaVersions field in GcsCapabilities.

View File

@@ -9,7 +9,7 @@
package hcsschema
// HvSocket configuration for a VM
// HvSocket configuration for a VM
type HvSocket2 struct {
HvSocketConfig *HvSocketSystemConfig `json:"HvSocketConfig,omitempty"`
}

View File

@@ -9,8 +9,8 @@
package hcsschema
// This class defines address settings applied to a VM
// by the GCS every time a VM starts or restores.
// This class defines address settings applied to a VM
// by the GCS every time a VM starts or restores.
type HvSocketAddress struct {
LocalAddress string `json:"LocalAddress,omitempty"`
ParentAddress string `json:"ParentAddress,omitempty"`

View File

@@ -9,7 +9,7 @@
package hcsschema
// This is the HCS Schema version of the HvSocket configuration. The VMWP version is located in Config.Devices.IC in V1.
// This is the HCS Schema version of the HvSocket configuration. The VMWP version is located in Config.Devices.IC in V1.
type HvSocketSystemConfig struct {
// SDDL string that HvSocket will check before allowing a host process to bind to an unlisted service for this specific container/VM (not wildcard binds).

View File

@@ -9,7 +9,7 @@
package hcsschema
// Memory runtime statistics
// Memory runtime statistics
type MemoryStats struct {
MemoryUsageCommitBytes uint64 `json:"MemoryUsageCommitBytes,omitempty"`

View File

@@ -0,0 +1,199 @@
package hcsschema
import (
"encoding/json"
"time"
)
// MigrationInitializeOptions is a set of options for the migration workflow.
type MigrationInitializeOptions struct {
// Origin is the side of migration the workflow is performed on.
Origin MigrationOrigin `json:"Origin,omitempty"`
// MemoryTransport specifies the settings for memory transfer during migration. On source, this
// setting is required when migration is started. On destination, this setting is required when
// migration is initiated.
MemoryTransport MigrationMemoryTransport `json:"MemoryTransport,omitempty"`
// MemoryTransferThrottleParams specifies settings for throttling during memory transfer.
MemoryTransferThrottleParams *MemoryMigrationTransferThrottleParams `json:"MemoryTransferThrottleParams,omitempty"`
// CompressionSettings specifies additional settings when compression is enabled.
CompressionSettings *MigrationCompressionSettings `json:"CompressionSettings,omitempty"`
// ChecksumVerification enables memory checksum verification.
ChecksumVerification bool `json:"ChecksumVerification,omitempty"`
// PerfTracingEnabled enables performance tracing during migration.
PerfTracingEnabled bool `json:"PerfTracingEnabled,omitempty"`
// CancelIfBlackoutThresholdExceeds cancels the operation if the blackout threshold is exceeded.
CancelIfBlackoutThresholdExceeds bool `json:"CancelIfBlackoutThresholdExceeds,omitempty"`
// PrepareMemoryTransferMode extends timeout for cross-version live migration.
PrepareMemoryTransferMode bool `json:"PrepareMemoryTransferMode,omitempty"`
// CompatibilityData is the compatibility information required for the destination VM.
CompatibilityData *CompatibilityInfo `json:"CompatibilityData,omitempty"`
}
// MigrationFinalizedOptions is a set of additional options used for HcsLiveMigrationFinalization.
type MigrationFinalizedOptions struct {
// Origin is the side of migration the workflow is performed on.
Origin MigrationOrigin `json:"Origin,omitempty"`
// FinalizedOperation is the final state transition for the VM as part of concluding the LM workflow.
FinalizedOperation MigrationFinalOperation `json:"FinalizedOperation,omitempty"`
}
// MigrationStartOptions specifies options for starting a migration.
type MigrationStartOptions struct {
// NetworkSettings specifies network settings for the socket provided.
NetworkSettings *MigrationNetworkSettings `json:"NetworkSettings,omitempty"`
}
// MigrationTransferOptions specifies options for the migration transfer phase.
type MigrationTransferOptions struct {
// Origin is the side of migration the workflow is performed on.
Origin MigrationOrigin `json:"Origin,omitempty"`
}
// StartOptions specifies options for starting a compute system.
type StartOptions struct {
// DestinationMigrationOptions specifies settings to use when starting a migration on the destination side.
DestinationMigrationOptions *MigrationStartOptions `json:"DestinationMigrationOptions,omitempty"`
}
// MigrationOrigin indicates where migration is initiated from.
type MigrationOrigin string
const (
// MigrationOriginSource indicates the source side of migration.
MigrationOriginSource MigrationOrigin = "Source"
// MigrationOriginDestination indicates the destination side of migration.
MigrationOriginDestination MigrationOrigin = "Destination"
)
// MigrationMemoryTransport is the transport protocol used for memory transfer during migration.
type MigrationMemoryTransport string
const (
// MigrationMemoryTransportTCP indicates the VM memory is copied over a TCP/IP connection.
MigrationMemoryTransportTCP MigrationMemoryTransport = "TCP"
)
// MemoryMigrationTransferThrottleParams specifies settings for migration memory transfer throttling.
type MemoryMigrationTransferThrottleParams struct {
// SkipThrottling indicates whether throttling should be skipped.
SkipThrottling *bool `json:"SkipThrottling,omitempty"`
// ThrottlingScale is the scale of the throttling as a percentage (1-100).
ThrottlingScale *float64 `json:"ThrottlingScale,omitempty"`
// MinimumThrottlePercentage is the minimum percentage to which memory transfer can be throttled.
MinimumThrottlePercentage *uint8 `json:"MinimumThrottlePercentage,omitempty"`
// TargetNumberOfBrownoutTransferPasses is the number of passes targeted before the VM enters blackout.
TargetNumberOfBrownoutTransferPasses *uint32 `json:"TargetNumberOfBrownoutTransferPasses,omitempty"`
// StartingBrownoutPassNumberForThrottling is the transfer pass where throttling begins.
StartingBrownoutPassNumberForThrottling *uint32 `json:"StartingBrownoutPassNumberForThrottling,omitempty"`
// MaximumNumberOfBrownoutTransferPasses is the maximum number of passes before forcing blackout.
MaximumNumberOfBrownoutTransferPasses *uint32 `json:"MaximumNumberOfBrownoutTransferPasses,omitempty"`
// TargetBlackoutTransferTime is the expected duration for blackout transfer time.
TargetBlackoutTransferTime *uint32 `json:"TargetBlackoutTransferTime,omitempty"`
// BlackoutTimeThresholdForCancellingMigration is the blackout duration threshold for cancelling migration.
BlackoutTimeThresholdForCancellingMigration *uint32 `json:"BlackoutTimeThresholdForCancellingMigration,omitempty"`
}
// MigrationCompressionSettings specifies compression settings for migration.
type MigrationCompressionSettings struct {
// ThrottleWorkerCount is the [de]compression thread count. Values higher than what the host
// and VM configuration can support will be adjusted. The value should be non-zero.
ThrottleWorkerCount *uint32 `json:"ThrottleWorkerCount,omitempty"`
}
// CompatibilityInfo is opaque VM compatibility data, primarily used in migration.
type CompatibilityInfo struct {
// Data is the raw compatibility information.
Data []byte `json:"Data,omitempty"`
}
// MigrationFinalOperation is the final operation performed on the compute system to finalize the live migration workflow.
type MigrationFinalOperation string
const (
// MigrationFinalOperationResume resumes the VM.
MigrationFinalOperationResume MigrationFinalOperation = "Resume"
// MigrationFinalOperationStop stops the VM.
MigrationFinalOperationStop MigrationFinalOperation = "Stop"
)
// MigrationNetworkSettings specifies the transport protocol for network connection provided by client.
type MigrationNetworkSettings struct {
// SessionID is the session ID associated with the socket connection between source and destination.
SessionID uint32 `json:"SessionId,omitempty"`
}
// OperationSystemMigrationNotificationInfo is a notification payload describing
// the current state of an in-progress live migration operation. It is emitted
// by HCS over the migration notification channel as the workflow progresses.
type OperationSystemMigrationNotificationInfo struct {
// Origin indicates which side of the live migration this notification
// pertains to (source or destination).
Origin MigrationOrigin `json:"Origin,omitempty"`
// Event is the type of live migration event being reported.
Event MigrationEvent `json:"Event,omitempty"`
// Result is an optional outcome accompanying the event. It is typically
// populated for terminal events.
Result MigrationResult `json:"Result,omitempty"`
// AdditionalDetails carries extra event-specific information whose schema
// depends on the event being reported. HCS models this as the schema `Any`
// type; we keep it as raw JSON so callers can decode it into the concrete
// event-specific struct (e.g. BlackoutExitedEventDetails for
// MigrationEventBlackoutExited) once they have inspected Event.
AdditionalDetails json.RawMessage `json:"AdditionalDetails,omitempty"`
}
// BlackoutExitedEventDetails carries additional details reported alongside
// MigrationEventBlackoutExited, describing the blackout that just ended.
// Mirrors the HCS MigrationBlackoutExitedEventDetails schema.
type BlackoutExitedEventDetails struct {
// BlackoutDurationMilliseconds is the duration of the blackout phase, in milliseconds.
BlackoutDurationMilliseconds uint64 `json:"BlackoutDurationMilliseconds,omitempty"`
// BlackoutStopTimestamp is the timestamp at which the blackout phase ended.
BlackoutStopTimestamp time.Time `json:"BlackoutStopTimestamp,omitempty"`
}
// MigrationEvent describes a live migration event reported by HCS.
type MigrationEvent string
const (
// MigrationEventUnknown indicates an unspecified or unrecognized event.
MigrationEventUnknown MigrationEvent = "Unknown"
// MigrationEventMigrationDone indicates that migration has completed.
MigrationEventMigrationDone MigrationEvent = "MigrationDone"
// MigrationEventBlackoutStarted indicates that the VM has entered the blackout phase.
MigrationEventBlackoutStarted MigrationEvent = "BlackoutStarted"
// MigrationEventOfflineDone indicates that taking the VM offline has completed.
MigrationEventOfflineDone MigrationEvent = "OfflineDone"
// MigrationEventBlackoutExited indicates that the VM has successfully started
// again after the blackout phase.
MigrationEventBlackoutExited MigrationEvent = "BlackoutExited"
// MigrationEventSetupDone indicates that the live migration setup has completed.
MigrationEventSetupDone MigrationEvent = "SetupDone"
// MigrationEventTransferInProgress indicates that the VM is still transferring
// memory and other necessary state.
MigrationEventTransferInProgress MigrationEvent = "TransferInProgress"
// MigrationEventMigrationRecoveryDone indicates that migration recovery has been performed.
MigrationEventMigrationRecoveryDone MigrationEvent = "MigrationRecoveryDone"
// MigrationEventMigrationFailed indicates that migration failed.
MigrationEventMigrationFailed MigrationEvent = "MigrationFailed"
)
// MigrationResult describes the possible result of a migration operation.
type MigrationResult string
const (
// MigrationResultInvalid indicates an invalid or unspecified result.
MigrationResultInvalid MigrationResult = "Invalid"
// MigrationResultSuccess indicates the migration operation succeeded.
MigrationResultSuccess MigrationResult = "Success"
// MigrationResultMigrationCancelled indicates the migration was cancelled.
MigrationResultMigrationCancelled MigrationResult = "MigrationCancelled"
// MigrationResultGuestInitiatedCancellation indicates the guest initiated the cancellation.
MigrationResultGuestInitiatedCancellation MigrationResult = "GuestInitiatedCancellation"
// MigrationResultSourceMigrationFailed indicates the migration failed on the source side.
MigrationResultSourceMigrationFailed MigrationResult = "SourceMigrationFailed"
// MigrationResultDestinationMigrationFailed indicates the migration failed on the destination side.
MigrationResultDestinationMigrationFailed MigrationResult = "DestinationMigrationFailed"
// MigrationResultMigrationRecoveryFailed indicates the migration recovery failed.
MigrationResultMigrationRecoveryFailed MigrationResult = "MigrationRecoveryFailed"
)

View File

@@ -12,10 +12,10 @@
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"`
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

@@ -9,7 +9,7 @@
package hcsschema
// Notification data that is indicated to components running in the Virtual Machine.
// Notification data that is indicated to components running in the Virtual Machine.
type PauseNotification struct {
Reason string `json:"Reason,omitempty"`
}

View File

@@ -9,7 +9,7 @@
package hcsschema
// Options for HcsPauseComputeSystem
// Options for HcsPauseComputeSystem
type PauseOptions struct {
SuspensionLevel string `json:"SuspensionLevel,omitempty"`

View File

@@ -19,16 +19,7 @@ type Plan9Share struct {
Port int32 `json:"Port,omitempty"`
// Flags are marked private. Until they are exported correctly
//
// ReadOnly 0x00000001
// LinuxMetadata 0x00000004
// CaseSensitive 0x00000008
Flags int32 `json:"Flags,omitempty"`
ReadOnly bool `json:"ReadOnly,omitempty"`
UseShareRootIdentity bool `json:"UseShareRootIdentity,omitempty"`
Flags Plan9ShareFlags `json:"Flags,omitempty"`
AllowedFiles []string `json:"AllowedFiles,omitempty"`
}

View File

@@ -0,0 +1,38 @@
/*
* 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
// Plan9ShareFlags is a bitfield controlling Plan9 share behavior.
type Plan9ShareFlags int32
const (
// Plan9ShareFlagsNone indicates no flags are set.
Plan9ShareFlagsNone Plan9ShareFlags = 0x00000000
// Plan9ShareFlagsReadOnly makes the share read-only.
Plan9ShareFlagsReadOnly Plan9ShareFlags = 0x00000001
// Plan9ShareFlagsLinuxMetadata enables writing Linux metadata.
Plan9ShareFlagsLinuxMetadata Plan9ShareFlags = 0x00000004
// Plan9ShareFlagsCaseSensitive creates directories in case-sensitive mode.
Plan9ShareFlagsCaseSensitive Plan9ShareFlags = 0x00000008
// Plan9ShareFlagsUseShareRootIdentity uses the identity of the share root
// when opening.
Plan9ShareFlagsUseShareRootIdentity Plan9ShareFlags = 0x00000010
// Plan9ShareFlagsRestrictFileAccess enables single-file mapping mode.
Plan9ShareFlagsRestrictFileAccess Plan9ShareFlags = 0x00000080
// Plan9ShareFlagsUnlimitedConnections allows multiple connections to this
// share.
Plan9ShareFlagsUnlimitedConnections Plan9ShareFlags = 0x00000100
)

View File

@@ -13,7 +13,7 @@ import (
"time"
)
// Information about a process running in a container
// Information about a process running in a container
type ProcessDetails struct {
ProcessId int32 `json:"ProcessId,omitempty"`

View File

@@ -3,7 +3,7 @@
*
* 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)
*/

View File

@@ -9,7 +9,7 @@
package hcsschema
// CPU runtime statistics
// CPU runtime statistics
type ProcessorStats struct {
TotalRuntime100ns uint64 `json:"TotalRuntime100ns,omitempty"`

View File

@@ -10,6 +10,8 @@
package hcsschema
import (
"encoding/json"
v1 "github.com/containerd/cgroups/v3/cgroup1/stats"
)
@@ -50,7 +52,15 @@ type Properties struct {
GuestConnectionInfo *GuestConnectionInfo `json:"GuestConnectionInfo,omitempty"`
// PropertyResponses maps requested property names to their associated response objects.
PropertyResponses map[string]PropertyResponse `json:"PropertyResponses,omitempty"`
// Metrics is not part of the API for HCS but this is used for LCOW v2 to
// return the full cgroup metrics from the guest.
Metrics *v1.Metrics `json:"LCOWMetrics,omitempty"`
}
// PropertyResponse is the response object associated with a property query.
type PropertyResponse struct {
Response json.RawMessage `json:"Response,omitempty"`
}

View File

@@ -9,7 +9,11 @@
package hcsschema
// By default the basic properties will be returned. This query provides a way to request specific properties.
// By default the basic properties will be returned. This query provides a way to request specific properties.
type PropertyQuery struct {
PropertyTypes []PropertyType `json:"PropertyTypes,omitempty"`
// Queries is a new property request object, introduced in version 2.5, which takes the
// names of the properties and their associated query objects if needed.
Queries map[string]interface{} `json:"Queries,omitempty"`
}

View File

@@ -9,7 +9,7 @@
package hcsschema
// Silo job information
// Silo job information
type SiloProperties struct {
Enabled bool `json:"Enabled,omitempty"`

View File

@@ -13,7 +13,7 @@ import (
"time"
)
// Runtime statistics for a container
// Runtime statistics for a container
type Statistics struct {
Timestamp time.Time `json:"Timestamp,omitempty"`

View File

@@ -18,4 +18,7 @@ type Storage struct {
Path string `json:"Path,omitempty"`
QoS *StorageQoS `json:"QoS,omitempty"`
// Path to the root of the container's filesystem. This is useful in case of HostProcess containers where the container rootfs is different from C:\.
PrivilegedContainerRootPath string `json:"PrivilegedContainerRootPath,omitempty"`
}

View File

@@ -9,7 +9,7 @@
package hcsschema
// Storage runtime statistics
// Storage runtime statistics
type StorageStats struct {
ReadCountNormalized uint64 `json:"ReadCountNormalized,omitempty"`

View File

@@ -12,7 +12,7 @@
package hcsschema
type Topology struct {
Memory *VirtualMachineMemory `json:"Memory,omitempty"`
Processor *VirtualMachineProcessor `json:"Processor,omitempty"`
Numa *Numa `json:"Numa,omitempty"`
Memory *VirtualMachineMemory `json:"Memory,omitempty"`
Processor *VirtualMachineProcessor `json:"Processor,omitempty"`
Numa *Numa `json:"Numa,omitempty"`
}

View File

@@ -15,15 +15,18 @@ package hcsschema
type VirtualMachine struct {
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"`
DebugOptions *DebugOptions `json:"DebugOptions,omitempty"`
GuestConnection *GuestConnection `json:"GuestConnection,omitempty"`
SecuritySettings *SecuritySettings `json:"SecuritySettings,omitempty"`
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"`
DebugOptions *DebugOptions `json:"DebugOptions,omitempty"`
GuestConnection *GuestConnection `json:"GuestConnection,omitempty"`
SecuritySettings *SecuritySettings `json:"SecuritySettings,omitempty"`
ResourcePartitionId string `json:"ResourcePartitionId,omitempty"`
// Live migration options to be used on destination.
MigrationOptions *MigrationInitializeOptions `json:"MigrationOptions,omitempty"`
}

View File

@@ -15,7 +15,7 @@ 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"`
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).
@@ -27,7 +27,7 @@ type VirtualMachineMemory struct {
// 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"`
HighMMIOBaseInMB uint64 `json:"HighMmioBaseInMB,omitempty"`
HighMMIOGapInMB uint64 `json:"HighMmioGapInMB,omitempty"`
SlitType *VirtualSlitType `json:"SlitType,omitempty"`
}

View File

@@ -12,10 +12,10 @@
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"`
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

@@ -12,6 +12,6 @@ package hcsschema
// 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"`
Functions []VirtualPciFunction `json:",omitempty"`
PropagateNumaAffinity *bool `json:"PropagateNumaAffinity,omitempty"`
}

View File

@@ -191,7 +191,7 @@ func GetComputeSystems(ctx context.Context, q schema1.ComputeSystemQuery) ([]sch
return computeSystems, nil
}
// Start synchronously starts the computeSystem.
// Start synchronously starts the computeSystem using HCS V1 API.
func (computeSystem *System) Start(ctx context.Context) (err error) {
operation := "hcs::System::Start"
@@ -379,6 +379,20 @@ func (computeSystem *System) Properties(ctx context.Context, types ...schema1.Pr
return properties, nil
}
// openSilo opens the container's server silo job object by its well-known name
// (`\Container_<id>`). HCS owns the silo; the only way to open it from the shim is
// by name, and only while running as SYSTEM. The caller owns the returned handle and
// must Close it.
//
// In the future we can make use of some new functionality in HCS that allows you to
// pass a job object for HCS to use for the container.
func (computeSystem *System) openSilo(ctx context.Context) (*jobobject.JobObject, error) {
return jobobject.Open(ctx, &jobobject.Options{
UseNTVariant: true,
Name: siloNameFmt(computeSystem.id),
})
}
// queryInProc handles querying for container properties without reaching out to HCS. `props`
// will be updated to contain any data returned from the queries present in `types`. If any properties
// failed to be queried they will be tallied up and returned in as the first return value. Failures on
@@ -389,14 +403,7 @@ func (computeSystem *System) queryInProc(
props *hcsschema.Properties,
types []hcsschema.PropertyType,
) ([]hcsschema.PropertyType, error) {
// In the future we can make use of some new functionality in the HCS that allows you
// to pass a job object for HCS to use for the container. Currently, the only way we'll
// be able to open the job/silo is if we're running as SYSTEM.
jobOptions := &jobobject.Options{
UseNTVariant: true,
Name: siloNameFmt(computeSystem.id),
}
job, err := jobobject.Open(ctx, jobOptions)
job, err := computeSystem.openSilo(ctx)
if err != nil {
return nil, err
}
@@ -490,6 +497,48 @@ func (computeSystem *System) statisticsInProc(job *jobobject.JobObject) (*hcssch
}, nil
}
// SetCPUGroupAffinities pins the container's server silo to the given processor
// group affinities. HCS does not expose a CPU-affinity field on the container Processor
// schema, so for process-isolated (Argon) containers we set the affinity directly on the
// silo's job object via SetInformationJobObject(JobObjectGroupInformationEx).
//
// HCS owns the silo; we only open a transient handle (by the silo's well-known job name,
// the same handle queryInProc opens) to record the affinity property. The kernel enforces
// it on every process that joins the silo via AssignProcessToJobObject — including the init
// process at Start and any descendants it spawns.
//
// This must be called after the compute system is created but before it is started, so the
// affinity is already recorded on the job when HCS assigns the init process. Applying it to
// an already-running silo is also safe: the kernel re-applies the mask to current members and
// migrates threads at the next scheduling dispatch.
//
// It implements the cow.Container interface.
func (computeSystem *System) SetCPUGroupAffinities(ctx context.Context, affinities []jobobject.GroupAffinity) error {
computeSystem.handleLock.RLock()
defer computeSystem.handleLock.RUnlock()
// Guard the compute system's lifecycle while we touch its silo: the RLock blocks
// a concurrent Close(), and handle == 0 means it is already torn down.
if computeSystem.handle == 0 {
return fmt.Errorf("set cpu group affinities on %s silo: %w", computeSystem.ID(), ErrAlreadyClosed)
}
// The silo job object only exists for containers, not VM-based compute systems.
if computeSystem.typ != "container" {
return fmt.Errorf("cpu group affinities are only supported on container compute systems, got %q", computeSystem.typ)
}
job, err := computeSystem.openSilo(ctx)
if err != nil {
return fmt.Errorf("open %s silo: %w", computeSystem.ID(), err)
}
defer job.Close()
if err := job.SetCPUGroupAffinities(affinities); err != nil {
return fmt.Errorf("set cpu group affinities on %s silo: %w", computeSystem.ID(), err)
}
return nil
}
// hcsPropertiesV2Query is a helper to make a HcsGetComputeSystemProperties call using the V2 schema property types.
func (computeSystem *System) hcsPropertiesV2Query(ctx context.Context, types []hcsschema.PropertyType) (*hcsschema.Properties, error) {
operation := "hcs::System::PropertiesV2"
@@ -574,6 +623,54 @@ func (computeSystem *System) PropertiesV2(ctx context.Context, types ...hcsschem
return hcsProperties, nil
}
// PropertiesV3 returns the requested compute system properties using a V2 schema property query.
// Unlike [System.PropertiesV2], this method accepts a full [hcsschema.PropertyQuery] directly,
// giving the caller more control over the query structure. The query is forwarded to HCS as-is
// without any in-proc optimisations such as that is V2.
func (computeSystem *System) PropertiesV3(ctx context.Context, query *hcsschema.PropertyQuery) (_ *hcsschema.Properties, err error) {
operation := "hcs::System::PropertiesV3"
ctx, span := oc.StartSpan(ctx, operation)
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("cid", computeSystem.id))
computeSystem.handleLock.RLock()
defer computeSystem.handleLock.RUnlock()
if computeSystem.handle == 0 {
return nil, makeSystemError(computeSystem, operation, ErrAlreadyClosed, nil)
}
log.G(ctx).WithFields(logrus.Fields{
logfields.ContainerID: computeSystem.id,
"propertyTypes": query.PropertyTypes,
"propertyQueries": query.Queries,
}).Debug("querying compute system properties via PropertiesV3")
queryBytes, err := json.Marshal(query)
if err != nil {
return nil, makeSystemError(computeSystem, operation, err, nil)
}
propertiesJSON, resultJSON, err := vmcompute.HcsGetComputeSystemProperties(ctx, computeSystem.handle, string(queryBytes))
events := processHcsResult(ctx, resultJSON)
if err != nil {
return nil, makeSystemError(computeSystem, operation, err, events)
}
if propertiesJSON == "" {
return nil, ErrUnexpectedValue
}
props := &hcsschema.Properties{}
if err := json.Unmarshal([]byte(propertiesJSON), props); err != nil {
return nil, makeSystemError(computeSystem, operation, err, nil)
}
return props, nil
}
// Pause pauses the execution of the computeSystem. This feature is not enabled in TP5.
func (computeSystem *System) Pause(ctx context.Context) (err error) {
operation := "hcs::System::Pause"

View File

@@ -28,11 +28,22 @@ type JobObject struct {
handleLock sync.RWMutex
}
// GroupAffinity specifies a processor group and an affinity mask within that group.
// It corresponds to the Win32 GROUP_AFFINITY structure and is used for multi-group
// CPU affinity on machines with more than 64 logical processors (WS2022+).
type GroupAffinity struct {
// Mask is the bitmask of processors within Group.
Mask uint64
// Group is the processor group number (0-based).
Group uint16
}
// JobLimits represents the resource constraints that can be applied to a job object.
type JobLimits struct {
CPULimit uint32
CPUWeight uint32
CPUAffinity uint64
CPUAffinity uint64 // legacy single-group (group 0) affinity mask; use GroupAffinities when non-empty
GroupAffinities []GroupAffinity // multi-processor-group affinity (WS2022+); takes precedence over CPUAffinity
MemoryLimitInBytes uint64
MaxIOPS int64
MaxBandwidth int64

View File

@@ -3,10 +3,12 @@
package jobobject
import (
"context"
"errors"
"fmt"
"unsafe"
"github.com/Microsoft/hcsshim/internal/log"
"github.com/Microsoft/hcsshim/internal/winapi"
"golang.org/x/sys/windows"
)
@@ -20,7 +22,7 @@ func isFlagSet(flag, controlFlags uint32) bool {
}
// SetResourceLimits sets resource limits on the job object (cpu, memory, storage).
func (job *JobObject) SetResourceLimits(limits *JobLimits) error {
func (job *JobObject) SetResourceLimits(ctx context.Context, limits *JobLimits) error {
// Go through and check what limits were specified and apply them to the job.
if limits.MemoryLimitInBytes != 0 {
if err := job.SetMemoryLimit(limits.MemoryLimitInBytes); err != nil {
@@ -38,7 +40,15 @@ func (job *JobObject) SetResourceLimits(limits *JobLimits) error {
}
}
if limits.CPUAffinity != 0 {
if len(limits.GroupAffinities) > 0 && limits.CPUAffinity != 0 {
log.G(ctx).WithField("limits", log.Format(ctx, limits)).Warn("both group and CPU affinity set; CPU affinity will be overridden")
}
if len(limits.GroupAffinities) > 0 {
if err := job.SetCPUGroupAffinities(limits.GroupAffinities); err != nil {
return fmt.Errorf("failed to set job object cpu group affinities: %w", err)
}
} else if limits.CPUAffinity != 0 {
if err := job.SetCPUAffinity(limits.CPUAffinity); err != nil {
return fmt.Errorf("failed to set job object cpu affinity: %w", err)
}
@@ -141,8 +151,89 @@ func (job *JobObject) GetCPULimit(rateControlType CPURateControlType) (uint32, e
return info.Value, nil
}
// SetCPUGroupAffinities sets the processor group affinities for the job object using
// JobObjectGroupInformationEx, which supports multi-processor-group machines (WS2022+).
// Each entry in affinities specifies a processor group number and a bitmask of processors
// within that group. affinities must be non-empty.
// https://learn.microsoft.com/en-us/windows/win32/api/jobapi2/nf-jobapi2-setinformationjobobject
func (job *JobObject) SetCPUGroupAffinities(affinities []GroupAffinity) error {
if len(affinities) == 0 {
return errors.New("affinities must be non-empty")
}
winapiAffinities := make([]winapi.GROUP_AFFINITY, len(affinities))
for i, a := range affinities {
winapiAffinities[i] = winapi.GROUP_AFFINITY{
Mask: uintptr(a.Mask),
Group: a.Group,
}
}
job.handleLock.RLock()
defer job.handleLock.RUnlock()
if job.handle == 0 {
return ErrAlreadyClosed
}
if _, err := windows.SetInformationJobObject(
job.handle,
windows.JobObjectGroupInformationEx,
uintptr(unsafe.Pointer(&winapiAffinities[0])),
uint32(len(winapiAffinities))*uint32(unsafe.Sizeof(winapiAffinities[0])),
); err != nil {
return fmt.Errorf("failed to set cpu group affinities on job object: %w", err)
}
return nil
}
// GetCPUGroupAffinities returns the processor group affinities set on the job object.
// https://learn.microsoft.com/en-us/windows/win32/api/jobapi2/nf-jobapi2-queryinformationjobobject
func (job *JobObject) GetCPUGroupAffinities() ([]GroupAffinity, error) {
job.handleLock.RLock()
defer job.handleLock.RUnlock()
if job.handle == 0 {
return nil, ErrAlreadyClosed
}
// QueryInformationJobObject(JobObjectGroupInformationEx) returns one
// GROUP_AFFINITY per processor group assigned to the job. Most machines
// have a single processor group; start with 1 and grow on
// ERROR_INSUFFICIENT_BUFFER.
count := uint32(1)
for {
winapiAffinities := make([]winapi.GROUP_AFFINITY, count)
var returnLen uint32
err := winapi.QueryInformationJobObject(
job.handle,
windows.JobObjectGroupInformationEx,
unsafe.Pointer(&winapiAffinities[0]),
count*uint32(unsafe.Sizeof(winapiAffinities[0])),
&returnLen,
)
if err == nil {
actualCount := returnLen / uint32(unsafe.Sizeof(winapiAffinities[0]))
result := make([]GroupAffinity, actualCount)
for i, a := range winapiAffinities[:actualCount] {
result[i] = GroupAffinity{Mask: uint64(a.Mask), Group: a.Group}
}
return result, nil
}
if !errors.Is(err, windows.ERROR_INSUFFICIENT_BUFFER) {
return nil, fmt.Errorf("failed to query cpu group affinities on job object: %w", err)
}
newCount := returnLen / uint32(unsafe.Sizeof(winapiAffinities[0]))
if newCount <= count {
return nil, fmt.Errorf("failed to query cpu group affinities on job object: buffer size did not grow (%d -> %d entries)", count, newCount)
}
count = newCount
}
}
// SetCPUAffinity sets the processor affinity for the job object.
// The affinity is passed in as a bitmask.
// Note: this uses JOB_OBJECT_LIMIT_AFFINITY which is restricted to processor group 0.
// For machines with more than 64 logical processors, use SetCPUGroupAffinities instead.
func (job *JobObject) SetCPUAffinity(affinityBitMask uint64) error {
info, err := job.getExtendedInformation()
if err != nil {

View File

@@ -107,8 +107,8 @@ func (h *Hook) encode(e *logrus.Entry) {
switch vv := v.(type) {
// built in types
// "json" marshals errors as "{}", so leave alone here
case bool, string, error, uintptr,
case bool, string, uintptr,
error, // "json" marshals errors as "{}", so leave alone here
int8, int16, int32, int64, int,
uint8, uint32, uint64, uint,
float32, float64:

View File

@@ -29,7 +29,13 @@ var (
_scrub atomic.Bool
)
// SetScrubbing enables scrubbing
func init() {
// Scrubbing is enabled by default to prevent sensitive information
// (such as environment variables containing secrets) from leaking to logs.
_scrub.Store(true)
}
// SetScrubbing enables or disables scrubbing of potentially sensitive information from logging.
func SetScrubbing(enable bool) { _scrub.Store(enable) }
// IsScrubbingEnabled checks if scrubbing is enabled
@@ -174,6 +180,19 @@ func isRequestBase(m genMap) bool {
return a && c
}
// ScrubCreateOptions scrubs a JSON-encoded CreateOptions struct,
// removing sensitive fields (env vars, annotations) from the embedded OCI Spec.
func ScrubCreateOptions(b []byte) ([]byte, error) {
return scrubBytes(b, scrubCreateOptions)
}
func scrubCreateOptions(m genMap) error {
if spec, ok := index(m, "Spec"); ok {
return scrubOCISpec(spec)
}
return nil
}
// combination `m, ok := m[s]` and `m, ok := m.(genMap)`
func index(m genMap, s string) (genMap, bool) {
if m, ok := m[s]; ok {

View File

@@ -7,13 +7,17 @@ const (
Namespace = "namespace"
Operation = "operation"
ID = "id"
ContainerID = "cid"
ExecID = "eid"
ProcessID = "pid"
TaskID = "tid"
UVMID = "uvm-id"
SandboxID = "sandbox-id"
ID = "id"
ContainerID = "cid"
GCSContainerID = "gcs_container_id"
ExecID = "eid"
NamespaceID = "namespace-id"
PodID = "pod-id"
ProcessID = "pid"
SandboxID = "sandbox-id"
TaskID = "tid"
UVMID = "uvm-id"
VirtualSandboxID = "virtual-sandbox-id"
// networking and IO
@@ -22,6 +26,13 @@ const (
Bytes = "bytes"
Pipe = "pipe"
// SCSI Constants
Controller = "controller"
LUN = "lun"
DiskType = "disk-type"
Partition = "partition"
// Common Misc
Attempt = "attemptNo"
@@ -70,6 +81,12 @@ const (
ShimPid = "shim-pid"
TaskPid = "task-pid"
// vpci device
VMBusGUID = "vmBusGUID"
DeviceID = "deviceInstanceID"
VFIndex = "virtualFunctionIndex"
// sandbox
NetNsPath = "net-ns-path"
@@ -88,6 +105,11 @@ const (
VMShimOperation = "vmshim-op"
// migration
SessionID = "session-id"
Action = "action"
// logging and tracing
TraceID = "traceID"

View File

@@ -9,6 +9,7 @@ import (
"syscall"
"unsafe"
"github.com/Microsoft/go-winio/vhd"
"github.com/Microsoft/hcsshim/internal/hcserror"
"github.com/Microsoft/hcsshim/internal/oc"
"go.opencensus.io/trace"
@@ -75,7 +76,7 @@ func attachVhd(path string) (syscall.Handle, error) {
if err != nil {
return 0, &os.PathError{Op: "OpenVirtualDisk", Path: path, Err: err}
}
err = attachVirtualDisk(handle, 0, 0, 0, 0, 0)
err = vhd.AttachVirtualDisk(handle, vhd.AttachVirtualDiskFlagBypassDefaultEncryptionPolicy, nil)
if err != nil {
syscall.Close(handle)
return 0, &os.PathError{Op: "AttachVirtualDisk", Path: path, Err: err}

View File

@@ -155,6 +155,10 @@ func NewLayerWriter(ctx context.Context, path string, parentLayerPaths []string)
}
w, err := newLegacyLayerWriter(importPath, parentLayerPaths, path)
if err != nil {
// Clean up the temporary import directory so it is not leaked when
// the writer fails to initialize (matches NewLayerReader's handling
// of exportPath).
os.RemoveAll(importPath)
return nil, err
}
return &legacyLayerWriterWrapper{

View File

@@ -436,13 +436,32 @@ func (w *legacyLayerWriter) initUtilityVM() error {
return nil
}
func (w *legacyLayerWriter) reset() error {
err := w.bufWriter.Flush()
if err != nil {
func (w *legacyLayerWriter) reset() (err error) {
// Always close the current backup writer and file handle, even if an error
// occurs below (e.g. bufWriter.Flush fails with ENOSPC when the disk is
// full). Leaving these handles open on Windows prevents the temporary
// import directory (defaults to SystemTemp, i.e. C:\Windows\SystemTemp\hcs*)
// from being removed by the deferred os.RemoveAll in legacyLayerWriterWrapper.Close,
// which leaks the directory and compounds disk-space exhaustion.
defer func() {
if w.backupWriter != nil {
w.backupWriter.Close()
w.backupWriter = nil
}
if w.currentFile != nil {
w.currentFile.Close()
w.currentFile = nil
w.currentFileName = ""
w.currentFileRoot = nil
}
w.currentIsDir = false
}()
if err = w.bufWriter.Flush(); err != nil {
return err
}
w.bufWriter.Reset(io.Discard)
if w.currentIsDir {
if w.currentIsDir && w.currentFile != nil {
r := w.currentFile
br := winio.NewBackupStreamReader(r)
// Seek to the beginning of the backup stream, skipping the fileattrs
@@ -475,16 +494,6 @@ func (w *legacyLayerWriter) reset() error {
}
w.currentIsDir = false
}
if w.backupWriter != nil {
w.backupWriter.Close()
w.backupWriter = nil
}
if w.currentFile != nil {
w.currentFile.Close()
w.currentFile = nil
w.currentFileName = ""
w.currentFileRoot = nil
}
return nil
}

View File

@@ -3,7 +3,9 @@
package cimwriter
import (
"fmt"
"sync"
"unsafe"
"github.com/sirupsen/logrus"
"golang.org/x/sys/windows"
@@ -53,7 +55,12 @@ var load = sync.OnceValue(func() error {
var buf [windows.MAX_PATH]uint16
n, _ := windows.GetModuleFileName(windows.Handle(modcimwriter.Handle()), &buf[0], uint32(len(buf)))
if n > 0 {
logrus.WithField("path", windows.UTF16ToString(buf[:n])).Info("loaded cimwriter.dll")
path := windows.UTF16ToString(buf[:n])
fields := logrus.Fields{"path": path}
if ver, err := getFileVersion(path); err == nil {
fields["version"] = ver
}
logrus.WithFields(fields).Info("loaded cimwriter.dll")
}
return nil
})
@@ -62,3 +69,31 @@ var load = sync.OnceValue(func() error {
func Supported() bool {
return load() == nil
}
// getFileVersion returns the file version string (e.g. "10.0.26100.1") for the given path.
func getFileVersion(path string) (string, error) {
size, err := windows.GetFileVersionInfoSize(path, nil)
if err != nil {
return "", err
}
data := make([]byte, size)
if err := windows.GetFileVersionInfo(path, 0, size, unsafe.Pointer(&data[0])); err != nil {
return "", err
}
var info *windows.VS_FIXEDFILEINFO
var infoLen uint32
if err := windows.VerQueryValue(unsafe.Pointer(&data[0]), `\`, unsafe.Pointer(&info), &infoLen); err != nil {
return "", err
}
return formatFileVersion(info), nil
}
// formatFileVersion formats the file version from a VS_FIXEDFILEINFO as "major.minor.build.revision".
// See https://learn.microsoft.com/en-us/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo
func formatFileVersion(info *windows.VS_FIXEDFILEINFO) string {
major := info.FileVersionMS >> 16
minor := info.FileVersionMS & 0xffff
build := info.FileVersionLS >> 16
revision := info.FileVersionLS & 0xffff
return fmt.Sprintf("%d.%d.%d.%d", major, minor, build, revision)
}

View File

@@ -0,0 +1,21 @@
package winapi
// BOOL GetProcessGroupAffinity(
// [in] HANDLE hProcess,
// [in, out] PUSHORT GroupCount,
// [out] PUSHORT GroupArray
// );
//
//sys GetProcessGroupAffinity(process windows.Handle, groupCount *uint16, groupArray *uint16) (err error) = kernel32.GetProcessGroupAffinity
// BOOL GetProcessAffinityMask(
// [in] HANDLE hProcess,
// [out] PDWORD_PTR lpProcessAffinityMask,
// [out] PDWORD_PTR lpSystemAffinityMask
// );
//
//sys GetProcessAffinityMask(process windows.Handle, processAffinityMask *uintptr, systemAffinityMask *uintptr) (err error) = kernel32.GetProcessAffinityMask
// WORD GetActiveProcessorGroupCount();
//
//sys GetActiveProcessorGroupCount() (amount uint16) = kernel32.GetActiveProcessorGroupCount

View File

@@ -98,6 +98,26 @@ type JOBOBJECT_BASIC_PROCESS_ID_LIST struct {
ProcessIdList [1]uintptr
}
// GROUP_AFFINITY specifies a processor group and an affinity mask for that group.
// Mirrors the Win32 _GROUP_AFFINITY structure.
//
// Processor group support was introduced in Windows 7 / Windows Server 2008 R2
// to handle machines with more than 64 logical processors. The structure is used
// with SetInformationJobObject(JobObjectGroupInformationEx) and
// QueryInformationJobObject(JobObjectGroupInformationEx), both available since
// Windows 7 / Windows Server 2008 R2.
//
// For job object silos (containers), multi-processor-group affinity requires
// Windows Server 2022 (build 20348) or later.
//
// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/miniport/ns-miniport-_group_affinity
// https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups
type GROUP_AFFINITY struct {
Mask uintptr // KAFFINITY = ULONG_PTR: bitmask of processors in Group
Group uint16 // Processor group number
Reserved [3]uint16 // Must be zero
}
// AllPids returns all the process Ids in the job object.
func (p *JOBOBJECT_BASIC_PROCESS_ID_LIST) AllPids() []uintptr {
return (*[(1 << 27) - 1]uintptr)(unsafe.Pointer(&p.ProcessIdList[0]))[:p.NumberOfProcessIdsInList:p.NumberOfProcessIdsInList]

View File

@@ -63,6 +63,9 @@ var (
procCreatePseudoConsole = modkernel32.NewProc("CreatePseudoConsole")
procCreateRemoteThread = modkernel32.NewProc("CreateRemoteThread")
procGetActiveProcessorCount = modkernel32.NewProc("GetActiveProcessorCount")
procGetActiveProcessorGroupCount = modkernel32.NewProc("GetActiveProcessorGroupCount")
procGetProcessAffinityMask = modkernel32.NewProc("GetProcessAffinityMask")
procGetProcessGroupAffinity = modkernel32.NewProc("GetProcessGroupAffinity")
procIsProcessInJob = modkernel32.NewProc("IsProcessInJob")
procLocalAlloc = modkernel32.NewProc("LocalAlloc")
procLocalFree = modkernel32.NewProc("LocalFree")
@@ -270,6 +273,28 @@ func GetActiveProcessorCount(groupNumber uint16) (amount uint32) {
return
}
func GetActiveProcessorGroupCount() (amount uint16) {
r0, _, _ := syscall.SyscallN(procGetActiveProcessorGroupCount.Addr())
amount = uint16(r0)
return
}
func GetProcessAffinityMask(process windows.Handle, processAffinityMask *uintptr, systemAffinityMask *uintptr) (err error) {
r1, _, e1 := syscall.SyscallN(procGetProcessAffinityMask.Addr(), uintptr(process), uintptr(unsafe.Pointer(processAffinityMask)), uintptr(unsafe.Pointer(systemAffinityMask)))
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func GetProcessGroupAffinity(process windows.Handle, groupCount *uint16, groupArray *uint16) (err error) {
r1, _, e1 := syscall.SyscallN(procGetProcessGroupAffinity.Addr(), uintptr(process), uintptr(unsafe.Pointer(groupCount)), uintptr(unsafe.Pointer(groupArray)))
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func IsProcessInJob(procHandle windows.Handle, jobHandle windows.Handle, result *int32) (err error) {
r1, _, e1 := syscall.SyscallN(procIsProcessInJob.Addr(), uintptr(procHandle), uintptr(jobHandle), uintptr(unsafe.Pointer(result)))
if r1 == 0 {

4
vendor/modules.txt vendored
View File

@@ -111,8 +111,8 @@ github.com/Microsoft/go-winio/pkg/fs
github.com/Microsoft/go-winio/pkg/guid
github.com/Microsoft/go-winio/pkg/security
github.com/Microsoft/go-winio/vhd
# github.com/Microsoft/hcsshim v0.15.0-rc.1
## explicit; go 1.24.0
# github.com/Microsoft/hcsshim v0.15.0-rc.3
## explicit; go 1.25.0
github.com/Microsoft/hcsshim
github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options
github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/stats