forked from microsoft/hcsshim
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Hamza El-Saawy <hamzaelsaawy@microsoft.com>
- Loading branch information
Showing
13 changed files
with
926 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
//go:build windows | ||
|
||
package computecore | ||
|
||
import "golang.org/x/sys/windows" | ||
|
||
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) | ||
|
||
hcsOperationCompletionPtr uintptr | ||
) | ||
|
||
func (f HCSOperationCompletion) asCallback() hcsOperationCompletionPtr { | ||
if f == nil { | ||
return hcsOperationCompletionPtr(0) | ||
} | ||
return hcsOperationCompletionPtr(windows.NewCallback( | ||
// NewCallback expects a function with one uintptr-sized result | ||
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) | ||
|
||
hcsEventCallbackPtr uintptr | ||
) | ||
|
||
func (f HCSEventCallback) asCallback() hcsEventCallbackPtr { | ||
if f == nil { | ||
return hcsEventCallbackPtr(0) | ||
} | ||
return hcsEventCallbackPtr(windows.NewCallback( | ||
// NewCallback expects a function with one uintptr-sized result | ||
func(event *HCSEvent, hcsContext uintptr) uintptr { | ||
f(event, hcsContext) | ||
return 0 | ||
}, | ||
)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
//go:build windows | ||
|
||
package computecore | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"strings" | ||
|
||
"go.opencensus.io/trace" | ||
"golang.org/x/sys/windows" | ||
|
||
hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" | ||
"github.com/Microsoft/hcsshim/internal/interop" | ||
"github.com/Microsoft/hcsshim/internal/log" | ||
"github.com/Microsoft/hcsshim/internal/oc" | ||
) | ||
|
||
// TODO: HcsSetComputeSystemCallback & HcsSetProcessCallback | ||
|
||
type ( | ||
// Handle to a compute HCSSystem. | ||
HCSSystem windows.Handle | ||
|
||
// Handle to a HCSProcess running in a compute system. | ||
HCSProcess windows.Handle | ||
|
||
// Handle to a HCSCallback registered on a compute system or process handle. | ||
HCSCallback windows.Handle | ||
) | ||
|
||
//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go ./*.go | ||
|
||
// HRESULT WINAPI | ||
// HcsEnumerateComputeSystems( | ||
// _In_opt_ PCWSTR query, | ||
// _In_ HCS_OPERATION operation | ||
// ); | ||
//sys hcsEnumerateComputeSystems(query string, operation HCSOperation) (hr error) = computecore.HcsEnumerateComputeSystems? | ||
|
||
func EnumerateComputeSystems(ctx context.Context, query *hcsschema.SystemQuery) (properties []hcsschema.Properties, err error) { | ||
ctx, span := oc.StartSpan(ctx, "computecore::HcsEnumerateComputeSystems", oc.WithClientSpanKind) | ||
defer func() { | ||
if len(properties) != 0 { | ||
span.AddAttributes(trace.StringAttribute("properties", log.Format(ctx, properties))) | ||
} | ||
oc.SetSpanStatus(span, err) | ||
span.End() | ||
}() | ||
|
||
return parseResults[[]hcsschema.Properties](runOperation( | ||
ctx, | ||
func(_ context.Context, op HCSOperation) (err error) { | ||
q := "" | ||
if query != nil { | ||
q, err = encode(query) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
tryAddAttributes(ctx, trace.StringAttribute("query", q)) | ||
return hcsEnumerateComputeSystems(q, op) | ||
}, | ||
)) | ||
} | ||
|
||
func parseResults[T any](result string, err error) (v T, _ error) { | ||
if err != nil { | ||
// TODO: try to parse result as ResultError | ||
return v, err | ||
} | ||
err = json.Unmarshal([]byte(result), &v) | ||
return v, err | ||
} | ||
|
||
func runOperation(ctx context.Context, f func(ctx context.Context, op HCSOperation) error) (result string, err error) { | ||
// don't use operation callback, since it will fail if the compute system has a callback | ||
op, err := EmptyOperation(ctx) | ||
if err != nil { | ||
return "", fmt.Errorf("operation creation: %w", err) | ||
} | ||
defer op.Close() //nolint:staticcheck // ignore close error | ||
|
||
if err := f(ctx, op); err != nil { | ||
return "", err | ||
} | ||
|
||
result, err = op.WaitForOperationResult(ctx, 0) | ||
return result, err | ||
} | ||
|
||
func tryAddAttributes(ctx context.Context, attributes ...trace.Attribute) { | ||
if s := trace.FromContext(ctx); s != nil { | ||
s.AddAttributes(attributes...) | ||
} | ||
} | ||
|
||
func bufferToString(buffer *uint16) string { | ||
if buffer == nil { | ||
return "" | ||
} | ||
return interop.ConvertAndFreeCoTaskMemString(buffer) | ||
} | ||
|
||
func encode(v any) (string, error) { | ||
// 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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
// This package provides bindings and utility functions for dealing with ComputeCore.dll Win32 APIs. | ||
package computecore |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
//go:build windows | ||
|
||
package computecore | ||
|
||
import "golang.org/x/sys/windows" | ||
|
||
const hcsHResultPrefix = 0x80370000 | ||
|
||
// HCS specific error codes. | ||
// | ||
// See [documentation] for more info. | ||
// | ||
// [documentation]: https://learn.microsoft.com/en-us/virtualization/api/hcs/reference/hcshresult | ||
const ( | ||
// The virtual machine or container exited unexpectedly while starting. | ||
HCS_E_TERMINATED_DURING_START = windows.Errno(hcsHResultPrefix + 0x0100) | ||
|
||
// The container operating system does not match the host operating system. | ||
HCS_E_IMAGE_MISMATCH = windows.Errno(hcsHResultPrefix + 0x0101) | ||
|
||
// The virtual machine could not be started because a required feature is not installed. | ||
HCS_E_HYPERV_NOT_INSTALLED = windows.Errno(hcsHResultPrefix + 0x0102) | ||
|
||
// The requested virtual machine or container operation is not valid in the current state. | ||
HCS_E_INVALID_STATE = windows.Errno(hcsHResultPrefix + 0x0105) | ||
|
||
// The virtual machine or container exited unexpectedly. | ||
HCS_E_UNEXPECTED_EXIT = windows.Errno(hcsHResultPrefix + 0x0106) | ||
|
||
// The virtual machine or container was forcefully exited. | ||
HCS_E_TERMINATED = windows.Errno(hcsHResultPrefix + 0x0107) | ||
|
||
// A connection could not be established with the container or virtual machine. | ||
HCS_E_CONNECT_FAILED = windows.Errno(hcsHResultPrefix + 0x0108) | ||
|
||
// The operation timed out because a response was not received from the virtual machine or container. | ||
HCS_E_CONNECTION_TIMEOUT = windows.Errno(hcsHResultPrefix + 0x0109) | ||
|
||
// The connection with the virtual machine or container was closed. | ||
HCS_E_CONNECTION_CLOSED = windows.Errno(hcsHResultPrefix + 0x010A) | ||
|
||
// An unknown internal message was received by the virtual machine or container. | ||
HCS_E_UNKNOWN_MESSAGE = windows.Errno(hcsHResultPrefix + 0x010B) | ||
|
||
// The virtual machine or container does not support an available version of the communication protocol with the host. | ||
HCS_E_UNSUPPORTED_PROTOCOL_VERSION = windows.Errno(hcsHResultPrefix + 0x010C) | ||
|
||
// The virtual machine or container JSON document is invalid. | ||
HCS_E_INVALID_JSON = windows.Errno(hcsHResultPrefix + 0x010D) | ||
|
||
// A virtual machine or container with the specified identifier does not exist. | ||
HCS_E_SYSTEM_NOT_FOUND = windows.Errno(hcsHResultPrefix + 0x010E) | ||
|
||
// A virtual machine or container with the specified identifier already exists. | ||
HCS_E_SYSTEM_ALREADY_EXISTS = windows.Errno(hcsHResultPrefix + 0x010F) | ||
|
||
// The virtual machine or container with the specified identifier is not running. | ||
HCS_E_SYSTEM_ALREADY_STOPPED = windows.Errno(hcsHResultPrefix + 0x0110) | ||
|
||
// A communication protocol error has occurred between the virtual machine or container and the host. | ||
HCS_E_PROTOCOL_ERROR = windows.Errno(hcsHResultPrefix + 0x0111) | ||
|
||
// The container image contains a layer with an unrecognized format. | ||
HCS_E_INVALID_LAYER = windows.Errno(hcsHResultPrefix + 0x0112) | ||
|
||
// To use this container image, you must join the Windows Insider Program. | ||
// Please see https://go.microsoft.com/fwlink/?linkid=850659 for more information. | ||
HCS_E_WINDOWS_INSIDER_REQUIRED = windows.Errno(hcsHResultPrefix + 0x0113) | ||
|
||
// The operation could not be started because a required feature is not installed. | ||
HCS_E_SERVICE_NOT_AVAILABLE = windows.Errno(hcsHResultPrefix + 0x0114) | ||
|
||
// The operation has not started. | ||
HCS_E_OPERATION_NOT_STARTED = windows.Errno(hcsHResultPrefix + 0x0115) | ||
|
||
// The operation is already running. | ||
HCS_E_OPERATION_ALREADY_STARTED = windows.Errno(hcsHResultPrefix + 0x0116) | ||
|
||
// The operation is still running. | ||
HCS_E_OPERATION_PENDING = windows.Errno(hcsHResultPrefix + 0x0117) | ||
|
||
// The operation did not complete in time. | ||
HCS_E_OPERATION_TIMEOUT = windows.Errno(hcsHResultPrefix + 0x0118) | ||
|
||
// An event callback has already been registered on this handle. | ||
HCS_E_OPERATION_SYSTEM_CALLBACK_ALREADY_SET = windows.Errno(hcsHResultPrefix + 0x0119) | ||
|
||
// Not enough memory available to return the result of the operation. | ||
HCS_E_OPERATION_RESULT_ALLOCATION_FAILED = windows.Errno(hcsHResultPrefix + 0x011A) | ||
|
||
// Insufficient privileges. | ||
// Only administrators or users that are members of the Hyper-V Administrators user group are permitted to access virtual machines or containers. | ||
// To add yourself to the Hyper-V Administrators user group, please see https://aka.ms/hcsadmin for more information. | ||
HCS_E_ACCESS_DENIED = windows.Errno(hcsHResultPrefix + 0x011B) | ||
|
||
// The virtual machine or container reported a critical error and was stopped or restarted. | ||
HCS_E_GUEST_CRITICAL_ERROR = windows.Errno(hcsHResultPrefix + 0x011C) | ||
|
||
// The process information is not available. | ||
HCS_E_PROCESS_INFO_NOT_AVAILABLE = windows.Errno(hcsHResultPrefix + 0x011D) | ||
|
||
// The host compute system service has disconnected unexpectedly. | ||
HCS_E_SERVICE_DISCONNECT = windows.Errno(hcsHResultPrefix + 0x011E) | ||
|
||
// The process has already exited. | ||
HCS_E_PROCESS_ALREADY_STOPPED = windows.Errno(hcsHResultPrefix + 0x011F) | ||
|
||
// The virtual machine or container is not configured to perform the operation. | ||
HCS_E_SYSTEM_NOT_CONFIGURED_FOR_OPERATION = windows.Errno(hcsHResultPrefix + 0x0120) | ||
|
||
// The operation has already been cancelled. | ||
HCS_E_OPERATION_ALREADY_CANCELLED = windows.Errno(hcsHResultPrefix + 0x0121) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
//go:build windows | ||
|
||
package computecore | ||
|
||
// typedef struct HCS_EVENT | ||
// { | ||
// HCS_EVENT_TYPE Type; | ||
// PCWSTR EventData; | ||
// HCS_OPERATION Operation; | ||
// } HCS_EVENT; | ||
// | ||
// https://learn.microsoft.com/en-us/virtualization/api/hcs/reference/hcs_event | ||
type HCSEvent struct { | ||
Type HCSEventType | ||
// eventData provides additional data for the event as a JSON document. | ||
// | ||
// the type of JSON document depends on the event type: | ||
// | ||
// HcsEventSystemExited github.com/Microsoft/hcsshim/internal/hcs/schema2.SystemExitStatus | ||
// HcsEventSystemCrashInitiated github.com/Microsoft/hcsshim/internal/hcs/schema2.CrashReport | ||
// HcsEventSystemCrashReport github.com/Microsoft/hcsshim/internal/hcs/schema2.CrashReport | ||
// HcsEventProcessExited github.com/Microsoft/hcsshim/internal/hcs/schema2.ProcessStatus | ||
EventData *uint16 | ||
// Handle to a completed operation, if Type is eventOperationCallback. | ||
// This is only possible when HcsSetComputeSystemCallback has specified event option HcsEventOptionEnableOperationCallbacks. | ||
Operation HCSOperation | ||
} | ||
|
||
//go:generate go run golang.org/x/tools/cmd/stringer -type=HCSEventType -trimprefix=Event event.go | ||
|
||
// HCSEventType indicates the event type for callbacks registered by hcsSetComputeSystemCallback or hcsSetProcessCallback. | ||
// | ||
// See [documentation] for more info. | ||
// | ||
// [documentation]: https://learn.microsoft.com/en-us/virtualization/api/hcs/reference/hcs_event_type | ||
type HCSEventType int32 | ||
|
||
const ( | ||
EventInvalid = HCSEventType(0x00000000) | ||
EventSystemExited = HCSEventType(0x00000001) | ||
EventSystemCrashInitiated = HCSEventType(0x00000002) | ||
EventSystemCrashReport = HCSEventType(0x00000003) | ||
EventSystemRdpEnhancedModeStateChanged = HCSEventType(0x00000004) | ||
EventSystemSiloJobCreated = HCSEventType(0x00000005) | ||
EventSystemGuestConnectionClosed = HCSEventType(0x00000006) | ||
EventProcessExited = HCSEventType(0x00010000) | ||
EventOperationCallback = HCSEventType(0x01000000) | ||
EventServiceDisconnect = HCSEventType(0x02000000) | ||
) | ||
|
||
//go:generate go run golang.org/x/tools/cmd/stringer -type=HCSEventOptions -trimprefix=EventOption event.go | ||
|
||
// HCSEventOptions defines the options for an event callback registration, used in HcsSetComputeSystemCallback and HcsSetProcessCallback. | ||
// | ||
// See [documentation] for more info. | ||
// | ||
// [documentation]: https://learn.microsoft.com/en-us/virtualization/api/hcs/reference/hcs_event_options | ||
type HCSEventOptions int32 | ||
|
||
const ( | ||
EventOptionNone = HCSEventOptions(0x00000000) | ||
EventOptionEnableOperationCallbacks = HCSEventOptions(0x00000001) | ||
) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.