Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feature: add support for resource pools #2232

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion container.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func CreateContainer(id string, c *ContainerConfig) (Container, error) {
return nil, fmt.Errorf("failed to merge additional JSON '%s': %w", createContainerAdditionalJSON, err)
}

system, err := hcs.CreateComputeSystem(context.Background(), id, fullConfig)
system, err := hcs.CreateComputeSystem(context.Background(), id, fullConfig, nil)
if err != nil {
return nil, err
}
Expand Down
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ require (
go.etcd.io/bbolt v1.3.10
go.opencensus.io v0.24.0
go.uber.org/mock v0.4.0
golang.org/x/sync v0.7.0
golang.org/x/sync v0.8.0
golang.org/x/sys v0.23.0
golang.org/x/tools v0.24.0
google.golang.org/grpc v1.65.0
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1
google.golang.org/protobuf v1.34.2
Expand Down Expand Up @@ -106,11 +107,10 @@ require (
go.opentelemetry.io/otel/metric v1.21.0 // indirect
go.opentelemetry.io/otel/sdk v1.21.0 // indirect
go.opentelemetry.io/otel/trace v1.21.0 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
golang.org/x/crypto v0.26.0 // indirect
golang.org/x/mod v0.20.0 // indirect
golang.org/x/net v0.28.0 // indirect
golang.org/x/text v0.17.0 // indirect
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
24 changes: 12 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -312,8 +312,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
Expand All @@ -323,8 +323,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand All @@ -340,8 +340,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand All @@ -351,8 +351,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down Expand Up @@ -390,8 +390,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand All @@ -405,8 +405,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
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=
Expand Down
6 changes: 6 additions & 0 deletions internal/annotations/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,10 @@ const (
// UVMConsolePipe is the name of the named pipe that the UVM console is connected to. This works only for non-SNP
// scenario, for SNP use a debugger.
UVMConsolePipe = "io.microsoft.virtualmachine.console.pipe"

// HRMCPUJobName specifies the job name of the HRM CPU job object that the underlying HCS system should be bound to.
HRMCPUJobName = "io.microsoft.virtualmachine.hrm.cpu-job-name"

// HRMMemoryJobName specifies the job name of the HRM memory job object that the underlying HCS system should be bound to.
HRMMemoryJobName = "io.microsoft.virtualmachine.hrm.memory-job-name"
)
65 changes: 65 additions & 0 deletions internal/computecore/callback.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//go:build windows

package computecore

import "golang.org/x/sys/windows"

// Callback functions must be converted to a uintptr via [windows.NewCallback] before being
// passed to a syscall.
//
// Additionally, [windows.NewCallback] expects functions to return a uintptr result,
// so callbacks must be modified ahead of time.
//
// Create a dedicated type uintptr for each callback to ensure type safety.

// The `void* context` parameter is for an arbitrary payload to passed into the callback,
// allowing for operation-specific data to be provided to a more generic callback.

type (
// Function type for the completion callback of an operation.
//
// typedef void (CALLBACK *HCS_OPERATION_COMPLETION)(
// _In_ HCS_OPERATION operation,
// _In_opt_ void* context
// );
HCSOperationCompletion func(op HCSOperation, hcsContext uintptr)

hcsOperationCompletionUintptr uintptr
)

func (f HCSOperationCompletion) asCallback() hcsOperationCompletionUintptr {

Check failure on line 30 in internal/computecore/callback.go

View workflow job for this annotation

GitHub Actions / lint (windows)

func `HCSOperationCompletion.asCallback` is unused (unused)
if f == nil {
return hcsOperationCompletionUintptr(0)
}
return hcsOperationCompletionUintptr(windows.NewCallback(
func(op HCSOperation, hcsContext uintptr) uintptr {
f(op, hcsContext)
return 0
},
))
}

type (
// Function type for compute system event callbacks.
//
// typedef void (CALLBACK *HCS_EVENT_CALLBACK)(
// _In_ HCS_EVENT* event,
// _In_opt_ void* context
// );
HCSEventCallback func(event *HCSEvent, hcsContext uintptr)

hcsEventCallbackUintptr uintptr

Check failure on line 51 in internal/computecore/callback.go

View workflow job for this annotation

GitHub Actions / lint (windows)

type `hcsEventCallbackUintptr` is unused (unused)
)

func (f HCSEventCallback) asCallback() hcsEventCallbackUintptr {

Check failure on line 54 in internal/computecore/callback.go

View workflow job for this annotation

GitHub Actions / lint (windows)

func `HCSEventCallback.asCallback` is unused (unused)
if f == nil {
return hcsEventCallbackUintptr(0)
}
return hcsEventCallbackUintptr(windows.NewCallback(
// NewCallback expects a function with one uintptr-sized result
func(event *HCSEvent, hcsContext uintptr) uintptr {
f(event, hcsContext)
return 0
},
))
}
130 changes: 130 additions & 0 deletions internal/computecore/computecore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
//go:build windows

package computecore

import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"strings"
"syscall"
"time"

"github.com/Microsoft/hcsshim/internal/interop"
"github.com/Microsoft/hcsshim/internal/log"
"github.com/Microsoft/hcsshim/internal/logfields"
"github.com/Microsoft/hcsshim/internal/oc"
"github.com/Microsoft/hcsshim/internal/timeout"

"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
"golang.org/x/sys/windows"
)

//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go ./*.go

//sys hcsCreateComputeSystem(id string, configuration string, operation HCSOperation, security_descriptor *uint32, computeSystem *HCSSystem) (hr error) = computecore.HcsCreateComputeSystem?

type (
HCSSystem syscall.Handle
)

func HcsCreateComputeSystem(ctx context.Context, id string, configuration string, operation HCSOperation, securityDescriptor *uint32) (computeSystem HCSSystem, result string, hr error) {
log.G(ctx).WithField("id", id).Debug("computecore.HcsCreateComputeSystem")
ctx, span := oc.StartSpan(ctx, "computecore::HcsCreateComputeSystem")
defer func() {
if result != "" {
span.AddAttributes(trace.StringAttribute("resultDocument", result))
}
if !errors.Is(hr, windows.ERROR_VMCOMPUTE_OPERATION_PENDING) {
oc.SetSpanStatus(span, hr)
}
span.End()
}()
span.AddAttributes(
trace.StringAttribute("id", id),
trace.StringAttribute("configuration", configuration),
)

log.G(ctx).WithField("id", id).Debug("computecore.execute")
return computeSystem, result, execute(ctx, timeout.SystemCreate, func() error {
var resultp *uint16
err := hcsCreateComputeSystem(id, configuration, operation, securityDescriptor, &computeSystem)
if resultp != nil {

Check failure on line 55 in internal/computecore/computecore.go

View workflow job for this annotation

GitHub Actions / lint (windows)

nilness: impossible condition: nil != nil (govet)
result = interop.ConvertAndFreeCoTaskMemString(resultp)
}

log.G(ctx).Debug("waiting for operation result")
// FIXME: here we synchronously wait for operation result, but in the future we should probably switch
// to notification model.
if opResult, opErr := operation.WaitForResult(ctx); opErr != nil {
log.G(ctx).WithError(opErr).Error("Failed to wait for operation result")
return opErr
} else {
log.G(ctx).WithField("result", opResult).Debug("operation completed")
}
return err
})
}

func bufferToString(buffer *uint16) string {
if buffer == nil {
return ""
}
return interop.ConvertAndFreeCoTaskMemString(buffer)
}

func encode(v any) (string, error) {

Check failure on line 79 in internal/computecore/computecore.go

View workflow job for this annotation

GitHub Actions / lint (windows)

func `encode` is unused (unused)
// TODO: pool of encoders/buffers
buf := &bytes.Buffer{}
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
enc.SetIndent("", "")

if err := enc.Encode(v); err != nil {
return "", fmt.Errorf("json encoding: %w", err)
}

// encoder.Encode appends a newline to the end
return strings.TrimSpace(buf.String()), nil
}

func execute(ctx context.Context, timeout time.Duration, f func() error) error {
now := time.Now()
if timeout > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, timeout)
defer cancel()
}

deadline, ok := ctx.Deadline()
trueTimeout := timeout
if ok {
trueTimeout = deadline.Sub(now)
log.G(ctx).WithFields(logrus.Fields{
logfields.Timeout: trueTimeout,
"desiredTimeout": timeout,
}).Trace("Executing syscall with deadline")
}

done := make(chan error, 1)
go func() {
done <- f()
}()

select {
case <-ctx.Done():
if errors.Is(ctx.Err(), context.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 " +
"stuck in the platform API for a significant length of time.")
}
return ctx.Err()
case err := <-done:
return err
}

}
1 change: 1 addition & 0 deletions internal/computecore/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package computecore
Loading
Loading