1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Bump hcsshim to get some fixes.

This also requires bumping winio.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
Brian Goff 2021-04-07 22:45:33 +00:00
parent 2acab355ec
commit 452f82d5fc
85 changed files with 2449 additions and 459 deletions

View file

@ -1,6 +1,6 @@
github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109 github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109
github.com/Microsoft/hcsshim 380508768ed2619a4777f268c6443017bb76b04e # v0.8.10 github.com/Microsoft/hcsshim e811ee705ec77df2ae28857ade553043fb564d91 # v0.8.16
github.com/Microsoft/go-winio 5b44b70ab3ab4d291a7c1d28afe7b4afeced0ed4 # v0.4.15 github.com/Microsoft/go-winio d1ffc52c73318019ce58aaa5282588c52df029b7 # v0.4.16
github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
github.com/golang/gddo 72a348e765d293ed6d1ded7b699591f14d6cd921 github.com/golang/gddo 72a348e765d293ed6d1ded7b699591f14d6cd921
github.com/google/uuid 0cd6bf5da1e1c83f8b45653022c74f71af0538a4 # v1.1.1 github.com/google/uuid 0cd6bf5da1e1c83f8b45653022c74f71af0538a4 # v1.1.1

View file

@ -3,7 +3,7 @@ module github.com/Microsoft/go-winio
go 1.12 go 1.12
require ( require (
github.com/pkg/errors v0.8.1 github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.4.1 github.com/sirupsen/logrus v1.4.1
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3
) )

View file

@ -429,10 +429,10 @@ type PipeConfig struct {
// when the pipe is in message mode. // when the pipe is in message mode.
MessageMode bool MessageMode bool
// InputBufferSize specifies the size the input buffer, in bytes. // InputBufferSize specifies the size of the input buffer, in bytes.
InputBufferSize int32 InputBufferSize int32
// OutputBufferSize specifies the size the input buffer, in bytes. // OutputBufferSize specifies the size of the output buffer, in bytes.
OutputBufferSize int32 OutputBufferSize int32
} }

View file

@ -2,150 +2,323 @@
package vhd package vhd
import "syscall" import (
"fmt"
"syscall"
"github.com/Microsoft/go-winio/pkg/guid"
"github.com/pkg/errors"
"golang.org/x/sys/windows"
)
//go:generate go run mksyscall_windows.go -output zvhd.go vhd.go //go:generate go run mksyscall_windows.go -output zvhd.go vhd.go
//sys createVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, flags uint32, providerSpecificFlags uint32, parameters *createVirtualDiskParameters, o *syscall.Overlapped, handle *syscall.Handle) (err error) [failretval != 0] = VirtDisk.CreateVirtualDisk //sys createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (err error) [failretval != 0] = virtdisk.CreateVirtualDisk
//sys openVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, flags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (err error) [failretval != 0] = VirtDisk.OpenVirtualDisk //sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (err error) [failretval != 0] = virtdisk.OpenVirtualDisk
//sys detachVirtualDisk(handle syscall.Handle, flags uint32, providerSpecificFlags uint32) (err error) [failretval != 0] = VirtDisk.DetachVirtualDisk //sys attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (err error) [failretval != 0] = virtdisk.AttachVirtualDisk
//sys detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (err error) [failretval != 0] = virtdisk.DetachVirtualDisk
type virtualStorageType struct { //sys getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (err error) [failretval != 0] = virtdisk.GetVirtualDiskPhysicalPath
DeviceID uint32
VendorID [16]byte
}
type ( type (
createVirtualDiskFlag uint32 CreateVirtualDiskFlag uint32
VirtualDiskAccessMask uint32
VirtualDiskFlag uint32 VirtualDiskFlag uint32
AttachVirtualDiskFlag uint32
DetachVirtualDiskFlag uint32
VirtualDiskAccessMask uint32
) )
const ( type VirtualStorageType struct {
// Flags for creating a VHD (not exported) DeviceID uint32
createVirtualDiskFlagNone createVirtualDiskFlag = 0 VendorID guid.GUID
createVirtualDiskFlagFullPhysicalAllocation createVirtualDiskFlag = 1 }
createVirtualDiskFlagPreventWritesToSourceDisk createVirtualDiskFlag = 2
createVirtualDiskFlagDoNotCopyMetadataFromParent createVirtualDiskFlag = 4
// Access Mask for opening a VHD type CreateVersion2 struct {
VirtualDiskAccessNone VirtualDiskAccessMask = 0 UniqueID guid.GUID
VirtualDiskAccessAttachRO VirtualDiskAccessMask = 65536
VirtualDiskAccessAttachRW VirtualDiskAccessMask = 131072
VirtualDiskAccessDetach VirtualDiskAccessMask = 262144
VirtualDiskAccessGetInfo VirtualDiskAccessMask = 524288
VirtualDiskAccessCreate VirtualDiskAccessMask = 1048576
VirtualDiskAccessMetaOps VirtualDiskAccessMask = 2097152
VirtualDiskAccessRead VirtualDiskAccessMask = 851968
VirtualDiskAccessAll VirtualDiskAccessMask = 4128768
VirtualDiskAccessWritable VirtualDiskAccessMask = 3276800
// Flags for opening a VHD
OpenVirtualDiskFlagNone VirtualDiskFlag = 0
OpenVirtualDiskFlagNoParents VirtualDiskFlag = 0x1
OpenVirtualDiskFlagBlankFile VirtualDiskFlag = 0x2
OpenVirtualDiskFlagBootDrive VirtualDiskFlag = 0x4
OpenVirtualDiskFlagCachedIO VirtualDiskFlag = 0x8
OpenVirtualDiskFlagCustomDiffChain VirtualDiskFlag = 0x10
OpenVirtualDiskFlagParentCachedIO VirtualDiskFlag = 0x20
OpenVirtualDiskFlagVhdSetFileOnly VirtualDiskFlag = 0x40
OpenVirtualDiskFlagIgnoreRelativeParentLocator VirtualDiskFlag = 0x80
OpenVirtualDiskFlagNoWriteHardening VirtualDiskFlag = 0x100
)
type createVersion2 struct {
UniqueID [16]byte // GUID
MaximumSize uint64 MaximumSize uint64
BlockSizeInBytes uint32 BlockSizeInBytes uint32
SectorSizeInBytes uint32 SectorSizeInBytes uint32
PhysicalSectorSizeInByte uint32
ParentPath *uint16 // string ParentPath *uint16 // string
SourcePath *uint16 // string SourcePath *uint16 // string
OpenFlags uint32 OpenFlags uint32
ParentVirtualStorageType virtualStorageType ParentVirtualStorageType VirtualStorageType
SourceVirtualStorageType virtualStorageType SourceVirtualStorageType VirtualStorageType
ResiliencyGUID [16]byte // GUID ResiliencyGUID guid.GUID
} }
type createVirtualDiskParameters struct { type CreateVirtualDiskParameters struct {
Version uint32 // Must always be set to 2 Version uint32 // Must always be set to 2
Version2 createVersion2 Version2 CreateVersion2
} }
type openVersion2 struct { type OpenVersion2 struct {
GetInfoOnly int32 // bool but 4-byte aligned GetInfoOnly bool
ReadOnly int32 // bool but 4-byte aligned ReadOnly bool
ResiliencyGUID [16]byte // GUID ResiliencyGUID guid.GUID
} }
type openVirtualDiskParameters struct { type OpenVirtualDiskParameters struct {
Version uint32 // Must always be set to 2 Version uint32 // Must always be set to 2
Version2 openVersion2 Version2 OpenVersion2
} }
// CreateVhdx will create a simple vhdx file at the given path using default values. type AttachVersion2 struct {
RestrictedOffset uint64
RestrictedLength uint64
}
type AttachVirtualDiskParameters struct {
Version uint32 // Must always be set to 2
Version2 AttachVersion2
}
const (
VIRTUAL_STORAGE_TYPE_DEVICE_VHDX = 0x3
// Access Mask for opening a VHD
VirtualDiskAccessNone VirtualDiskAccessMask = 0x00000000
VirtualDiskAccessAttachRO VirtualDiskAccessMask = 0x00010000
VirtualDiskAccessAttachRW VirtualDiskAccessMask = 0x00020000
VirtualDiskAccessDetach VirtualDiskAccessMask = 0x00040000
VirtualDiskAccessGetInfo VirtualDiskAccessMask = 0x00080000
VirtualDiskAccessCreate VirtualDiskAccessMask = 0x00100000
VirtualDiskAccessMetaOps VirtualDiskAccessMask = 0x00200000
VirtualDiskAccessRead VirtualDiskAccessMask = 0x000d0000
VirtualDiskAccessAll VirtualDiskAccessMask = 0x003f0000
VirtualDiskAccessWritable VirtualDiskAccessMask = 0x00320000
// Flags for creating a VHD
CreateVirtualDiskFlagNone CreateVirtualDiskFlag = 0x0
CreateVirtualDiskFlagFullPhysicalAllocation CreateVirtualDiskFlag = 0x1
CreateVirtualDiskFlagPreventWritesToSourceDisk CreateVirtualDiskFlag = 0x2
CreateVirtualDiskFlagDoNotCopyMetadataFromParent CreateVirtualDiskFlag = 0x4
CreateVirtualDiskFlagCreateBackingStorage CreateVirtualDiskFlag = 0x8
CreateVirtualDiskFlagUseChangeTrackingSourceLimit CreateVirtualDiskFlag = 0x10
CreateVirtualDiskFlagPreserveParentChangeTrackingState CreateVirtualDiskFlag = 0x20
CreateVirtualDiskFlagVhdSetUseOriginalBackingStorage CreateVirtualDiskFlag = 0x40
CreateVirtualDiskFlagSparseFile CreateVirtualDiskFlag = 0x80
CreateVirtualDiskFlagPmemCompatible CreateVirtualDiskFlag = 0x100
CreateVirtualDiskFlagSupportCompressedVolumes CreateVirtualDiskFlag = 0x200
// Flags for opening a VHD
OpenVirtualDiskFlagNone VirtualDiskFlag = 0x00000000
OpenVirtualDiskFlagNoParents VirtualDiskFlag = 0x00000001
OpenVirtualDiskFlagBlankFile VirtualDiskFlag = 0x00000002
OpenVirtualDiskFlagBootDrive VirtualDiskFlag = 0x00000004
OpenVirtualDiskFlagCachedIO VirtualDiskFlag = 0x00000008
OpenVirtualDiskFlagCustomDiffChain VirtualDiskFlag = 0x00000010
OpenVirtualDiskFlagParentCachedIO VirtualDiskFlag = 0x00000020
OpenVirtualDiskFlagVhdsetFileOnly VirtualDiskFlag = 0x00000040
OpenVirtualDiskFlagIgnoreRelativeParentLocator VirtualDiskFlag = 0x00000080
OpenVirtualDiskFlagNoWriteHardening VirtualDiskFlag = 0x00000100
OpenVirtualDiskFlagSupportCompressedVolumes VirtualDiskFlag = 0x00000200
// Flags for attaching a VHD
AttachVirtualDiskFlagNone AttachVirtualDiskFlag = 0x00000000
AttachVirtualDiskFlagReadOnly AttachVirtualDiskFlag = 0x00000001
AttachVirtualDiskFlagNoDriveLetter AttachVirtualDiskFlag = 0x00000002
AttachVirtualDiskFlagPermanentLifetime AttachVirtualDiskFlag = 0x00000004
AttachVirtualDiskFlagNoLocalHost AttachVirtualDiskFlag = 0x00000008
AttachVirtualDiskFlagNoSecurityDescriptor AttachVirtualDiskFlag = 0x00000010
AttachVirtualDiskFlagBypassDefaultEncryptionPolicy AttachVirtualDiskFlag = 0x00000020
AttachVirtualDiskFlagNonPnp AttachVirtualDiskFlag = 0x00000040
AttachVirtualDiskFlagRestrictedRange AttachVirtualDiskFlag = 0x00000080
AttachVirtualDiskFlagSinglePartition AttachVirtualDiskFlag = 0x00000100
AttachVirtualDiskFlagRegisterVolume AttachVirtualDiskFlag = 0x00000200
// Flags for detaching a VHD
DetachVirtualDiskFlagNone DetachVirtualDiskFlag = 0x0
)
// CreateVhdx is a helper function to create a simple vhdx file at the given path using
// default values.
func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error { func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error {
var ( params := CreateVirtualDiskParameters{
defaultType virtualStorageType
handle syscall.Handle
)
parameters := createVirtualDiskParameters{
Version: 2, Version: 2,
Version2: createVersion2{ Version2: CreateVersion2{
MaximumSize: uint64(maxSizeInGb) * 1024 * 1024 * 1024, MaximumSize: uint64(maxSizeInGb) * 1024 * 1024 * 1024,
BlockSizeInBytes: blockSizeInMb * 1024 * 1024, BlockSizeInBytes: blockSizeInMb * 1024 * 1024,
}, },
} }
if err := createVirtualDisk( handle, err := CreateVirtualDisk(path, VirtualDiskAccessNone, CreateVirtualDiskFlagNone, &params)
&defaultType, if err != nil {
path,
uint32(VirtualDiskAccessNone),
nil,
uint32(createVirtualDiskFlagNone),
0,
&parameters,
nil,
&handle); err != nil {
return err return err
} }
if err := syscall.CloseHandle(handle); err != nil { if err := syscall.CloseHandle(handle); err != nil {
return err return err
} }
return nil return nil
} }
// DetachVhd detaches a mounted container layer vhd found at `path`. // DetachVirtualDisk detaches a virtual hard disk by handle.
func DetachVirtualDisk(handle syscall.Handle) (err error) {
if err := detachVirtualDisk(handle, 0, 0); err != nil {
return errors.Wrap(err, "failed to detach virtual disk")
}
return nil
}
// DetachVhd detaches a vhd found at `path`.
func DetachVhd(path string) error { func DetachVhd(path string) error {
handle, err := OpenVirtualDisk( handle, err := OpenVirtualDisk(
path, path,
VirtualDiskAccessNone, VirtualDiskAccessNone,
OpenVirtualDiskFlagCachedIO|OpenVirtualDiskFlagIgnoreRelativeParentLocator) OpenVirtualDiskFlagCachedIO|OpenVirtualDiskFlagIgnoreRelativeParentLocator,
)
if err != nil { if err != nil {
return err return err
} }
defer syscall.CloseHandle(handle) defer syscall.CloseHandle(handle)
return detachVirtualDisk(handle, 0, 0) return DetachVirtualDisk(handle)
}
// AttachVirtualDisk attaches a virtual hard disk for use.
func AttachVirtualDisk(handle syscall.Handle, attachVirtualDiskFlag AttachVirtualDiskFlag, parameters *AttachVirtualDiskParameters) (err error) {
if parameters.Version != 2 {
return fmt.Errorf("only version 2 VHDs are supported, found version: %d", parameters.Version)
}
if err := attachVirtualDisk(
handle,
nil,
uint32(attachVirtualDiskFlag),
0,
parameters,
nil,
); err != nil {
return errors.Wrap(err, "failed to attach virtual disk")
}
return nil
}
// AttachVhd attaches a virtual hard disk at `path` for use.
func AttachVhd(path string) (err error) {
handle, err := OpenVirtualDisk(
path,
VirtualDiskAccessNone,
OpenVirtualDiskFlagCachedIO|OpenVirtualDiskFlagIgnoreRelativeParentLocator,
)
if err != nil {
return err
}
defer syscall.CloseHandle(handle)
params := AttachVirtualDiskParameters{Version: 2}
if err := AttachVirtualDisk(
handle,
AttachVirtualDiskFlagNone,
&params,
); err != nil {
return errors.Wrap(err, "failed to attach virtual disk")
}
return nil
} }
// OpenVirtualDisk obtains a handle to a VHD opened with supplied access mask and flags. // OpenVirtualDisk obtains a handle to a VHD opened with supplied access mask and flags.
func OpenVirtualDisk(path string, accessMask VirtualDiskAccessMask, flag VirtualDiskFlag) (syscall.Handle, error) { func OpenVirtualDisk(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask, openVirtualDiskFlags VirtualDiskFlag) (syscall.Handle, error) {
var ( parameters := OpenVirtualDiskParameters{Version: 2}
defaultType virtualStorageType handle, err := OpenVirtualDiskWithParameters(
handle syscall.Handle vhdPath,
) virtualDiskAccessMask,
parameters := openVirtualDiskParameters{Version: 2} openVirtualDiskFlags,
if err := openVirtualDisk(
&defaultType,
path,
uint32(accessMask),
uint32(flag),
&parameters, &parameters,
&handle); err != nil { )
if err != nil {
return 0, err return 0, err
} }
return handle, nil return handle, nil
} }
// OpenVirtualDiskWithParameters obtains a handle to a VHD opened with supplied access mask, flags and parameters.
func OpenVirtualDiskWithParameters(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask, openVirtualDiskFlags VirtualDiskFlag, parameters *OpenVirtualDiskParameters) (syscall.Handle, error) {
var (
handle syscall.Handle
defaultType VirtualStorageType
)
if parameters.Version != 2 {
return handle, fmt.Errorf("only version 2 VHDs are supported, found version: %d", parameters.Version)
}
if err := openVirtualDisk(
&defaultType,
vhdPath,
uint32(virtualDiskAccessMask),
uint32(openVirtualDiskFlags),
parameters,
&handle,
); err != nil {
return 0, errors.Wrap(err, "failed to open virtual disk")
}
return handle, nil
}
// CreateVirtualDisk creates a virtual harddisk and returns a handle to the disk.
func CreateVirtualDisk(path string, virtualDiskAccessMask VirtualDiskAccessMask, createVirtualDiskFlags CreateVirtualDiskFlag, parameters *CreateVirtualDiskParameters) (syscall.Handle, error) {
var (
handle syscall.Handle
defaultType VirtualStorageType
)
if parameters.Version != 2 {
return handle, fmt.Errorf("only version 2 VHDs are supported, found version: %d", parameters.Version)
}
if err := createVirtualDisk(
&defaultType,
path,
uint32(virtualDiskAccessMask),
nil,
uint32(createVirtualDiskFlags),
0,
parameters,
nil,
&handle,
); err != nil {
return handle, errors.Wrap(err, "failed to create virtual disk")
}
return handle, nil
}
// GetVirtualDiskPhysicalPath takes a handle to a virtual hard disk and returns the physical
// path of the disk on the machine. This path is in the form \\.\PhysicalDriveX where X is an integer
// that represents the particular enumeration of the physical disk on the caller's system.
func GetVirtualDiskPhysicalPath(handle syscall.Handle) (_ string, err error) {
var (
diskPathSizeInBytes uint32 = 256 * 2 // max path length 256 wide chars
diskPhysicalPathBuf [256]uint16
)
if err := getVirtualDiskPhysicalPath(
handle,
&diskPathSizeInBytes,
&diskPhysicalPathBuf[0],
); err != nil {
return "", errors.Wrap(err, "failed to get disk physical path")
}
return windows.UTF16ToString(diskPhysicalPathBuf[:]), nil
}
// CreateDiffVhd is a helper function to create a differencing virtual disk.
func CreateDiffVhd(diffVhdPath, baseVhdPath string, blockSizeInMB uint32) error {
// Setting `ParentPath` is how to signal to create a differencing disk.
createParams := &CreateVirtualDiskParameters{
Version: 2,
Version2: CreateVersion2{
ParentPath: windows.StringToUTF16Ptr(baseVhdPath),
BlockSizeInBytes: blockSizeInMB * 1024 * 1024,
OpenFlags: uint32(OpenVirtualDiskFlagCachedIO),
},
}
vhdHandle, err := CreateVirtualDisk(
diffVhdPath,
VirtualDiskAccessNone,
CreateVirtualDiskFlagNone,
createParams,
)
if err != nil {
return fmt.Errorf("failed to create differencing vhd: %s", err)
}
if err := syscall.CloseHandle(vhdHandle); err != nil {
return fmt.Errorf("failed to close differencing vhd handle: %s", err)
}
return nil
}

View file

@ -37,24 +37,26 @@ func errnoErr(e syscall.Errno) error {
} }
var ( var (
modVirtDisk = windows.NewLazySystemDLL("VirtDisk.dll") modvirtdisk = windows.NewLazySystemDLL("virtdisk.dll")
procCreateVirtualDisk = modVirtDisk.NewProc("CreateVirtualDisk") procCreateVirtualDisk = modvirtdisk.NewProc("CreateVirtualDisk")
procOpenVirtualDisk = modVirtDisk.NewProc("OpenVirtualDisk") procOpenVirtualDisk = modvirtdisk.NewProc("OpenVirtualDisk")
procDetachVirtualDisk = modVirtDisk.NewProc("DetachVirtualDisk") procAttachVirtualDisk = modvirtdisk.NewProc("AttachVirtualDisk")
procDetachVirtualDisk = modvirtdisk.NewProc("DetachVirtualDisk")
procGetVirtualDiskPhysicalPath = modvirtdisk.NewProc("GetVirtualDiskPhysicalPath")
) )
func createVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, flags uint32, providerSpecificFlags uint32, parameters *createVirtualDiskParameters, o *syscall.Overlapped, handle *syscall.Handle) (err error) { func createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (err error) {
var _p0 *uint16 var _p0 *uint16
_p0, err = syscall.UTF16PtrFromString(path) _p0, err = syscall.UTF16PtrFromString(path)
if err != nil { if err != nil {
return return
} }
return _createVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, securityDescriptor, flags, providerSpecificFlags, parameters, o, handle) return _createVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, securityDescriptor, createVirtualDiskFlags, providerSpecificFlags, parameters, overlapped, handle)
} }
func _createVirtualDisk(virtualStorageType *virtualStorageType, path *uint16, virtualDiskAccessMask uint32, securityDescriptor *uintptr, flags uint32, providerSpecificFlags uint32, parameters *createVirtualDiskParameters, o *syscall.Overlapped, handle *syscall.Handle) (err error) { func _createVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (err error) {
r1, _, e1 := syscall.Syscall9(procCreateVirtualDisk.Addr(), 9, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(unsafe.Pointer(securityDescriptor)), uintptr(flags), uintptr(providerSpecificFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(handle))) r1, _, e1 := syscall.Syscall9(procCreateVirtualDisk.Addr(), 9, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(unsafe.Pointer(securityDescriptor)), uintptr(createVirtualDiskFlags), uintptr(providerSpecificFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(handle)))
if r1 != 0 { if r1 != 0 {
if e1 != 0 { if e1 != 0 {
err = errnoErr(e1) err = errnoErr(e1)
@ -65,17 +67,17 @@ func _createVirtualDisk(virtualStorageType *virtualStorageType, path *uint16, vi
return return
} }
func openVirtualDisk(virtualStorageType *virtualStorageType, path string, virtualDiskAccessMask uint32, flags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (err error) { func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (err error) {
var _p0 *uint16 var _p0 *uint16
_p0, err = syscall.UTF16PtrFromString(path) _p0, err = syscall.UTF16PtrFromString(path)
if err != nil { if err != nil {
return return
} }
return _openVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, flags, parameters, handle) return _openVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, openVirtualDiskFlags, parameters, handle)
} }
func _openVirtualDisk(virtualStorageType *virtualStorageType, path *uint16, virtualDiskAccessMask uint32, flags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (err error) { func _openVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (err error) {
r1, _, e1 := syscall.Syscall6(procOpenVirtualDisk.Addr(), 6, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(flags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(handle))) r1, _, e1 := syscall.Syscall6(procOpenVirtualDisk.Addr(), 6, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(openVirtualDiskFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(handle)))
if r1 != 0 { if r1 != 0 {
if e1 != 0 { if e1 != 0 {
err = errnoErr(e1) err = errnoErr(e1)
@ -86,8 +88,32 @@ func _openVirtualDisk(virtualStorageType *virtualStorageType, path *uint16, virt
return return
} }
func detachVirtualDisk(handle syscall.Handle, flags uint32, providerSpecificFlags uint32) (err error) { func attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (err error) {
r1, _, e1 := syscall.Syscall(procDetachVirtualDisk.Addr(), 3, uintptr(handle), uintptr(flags), uintptr(providerSpecificFlags)) r1, _, e1 := syscall.Syscall6(procAttachVirtualDisk.Addr(), 6, uintptr(handle), uintptr(unsafe.Pointer(securityDescriptor)), uintptr(attachVirtualDiskFlag), uintptr(providerSpecificFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(overlapped)))
if r1 != 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (err error) {
r1, _, e1 := syscall.Syscall(procDetachVirtualDisk.Addr(), 3, uintptr(handle), uintptr(detachVirtualDiskFlags), uintptr(providerSpecificFlags))
if r1 != 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (err error) {
r1, _, e1 := syscall.Syscall(procGetVirtualDiskPhysicalPath.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(diskPathSizeInBytes)), uintptr(unsafe.Pointer(buffer)))
if r1 != 0 { if r1 != 0 {
if e1 != 0 { if e1 != 0 {
err = errnoErr(e1) err = errnoErr(e1)

View file

@ -1,6 +1,6 @@
# hcsshim # hcsshim
[![Build status](https://ci.appveyor.com/api/projects/status/nbcw28mnkqml0loa/branch/master?svg=true)](https://ci.appveyor.com/project/WindowsVirtualization/hcsshim/branch/master) [![Build status](https://github.com/microsoft/hcsshim/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/microsoft/hcsshim/actions?query=branch%3Amaster)
This package contains the Golang interface for using the Windows [Host Compute Service](https://techcommunity.microsoft.com/t5/containers/introducing-the-host-compute-service-hcs/ba-p/382332) (HCS) to launch and manage [Windows Containers](https://docs.microsoft.com/en-us/virtualization/windowscontainers/about/). It also contains other helpers and functions for managing Windows Containers such as the Golang interface for the Host Network Service (HNS). This package contains the Golang interface for using the Windows [Host Compute Service](https://techcommunity.microsoft.com/t5/containers/introducing-the-host-compute-service-hcs/ba-p/382332) (HCS) to launch and manage [Windows Containers](https://docs.microsoft.com/en-us/virtualization/windowscontainers/about/). It also contains other helpers and functions for managing Windows Containers such as the Golang interface for the Host Network Service (HNS).

View file

@ -5,14 +5,15 @@ package options
import ( import (
fmt "fmt" fmt "fmt"
proto "github.com/gogo/protobuf/proto"
_ "github.com/gogo/protobuf/types"
github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
io "io" io "io"
math "math" math "math"
reflect "reflect" reflect "reflect"
strings "strings" strings "strings"
time "time" time "time"
proto "github.com/gogo/protobuf/proto"
_ "github.com/gogo/protobuf/types"
github_com_gogo_protobuf_types "github.com/gogo/protobuf/types"
) )
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
@ -115,7 +116,26 @@ type Options struct {
VmMemorySizeInMb int32 `protobuf:"varint,9,opt,name=vm_memory_size_in_mb,json=vmMemorySizeInMb,proto3" json:"vm_memory_size_in_mb,omitempty"` VmMemorySizeInMb int32 `protobuf:"varint,9,opt,name=vm_memory_size_in_mb,json=vmMemorySizeInMb,proto3" json:"vm_memory_size_in_mb,omitempty"`
// GPUVHDPath is the path to the gpu vhd to add to the uvm // GPUVHDPath is the path to the gpu vhd to add to the uvm
// when a container requests a gpu // when a container requests a gpu
GPUVHDPath string `protobuf:"bytes,10,opt,name=GPUVHDPath,proto3" json:"GPUVHDPath,omitempty"` GPUVHDPath string `protobuf:"bytes,10,opt,name=GPUVHDPath,proto3" json:"GPUVHDPath,omitempty"`
// scale_cpu_limits_to_sandbox indicates that container CPU limits should
// be adjusted to account for the difference in number of cores between the
// host and UVM.
ScaleCpuLimitsToSandbox bool `protobuf:"varint,11,opt,name=scale_cpu_limits_to_sandbox,json=scaleCpuLimitsToSandbox,proto3" json:"scale_cpu_limits_to_sandbox,omitempty"`
// default_container_scratch_size_in_gb is the default scratch size (sandbox.vhdx)
// to be used for containers. Every container will get a sandbox of `size_in_gb` assigned
// instead of the default of 20GB.
DefaultContainerScratchSizeInGb int32 `protobuf:"varint,12,opt,name=default_container_scratch_size_in_gb,json=defaultContainerScratchSizeInGb,proto3" json:"default_container_scratch_size_in_gb,omitempty"`
// default_vm_scratch_size_in_gb is the default scratch size (sandbox.vhdx)
// to be used for the UVM. This only applies to WCOW as LCOW doesn't mount a scratch
// specifically for the UVM.
DefaultVmScratchSizeInGb int32 `protobuf:"varint,13,opt,name=default_vm_scratch_size_in_gb,json=defaultVmScratchSizeInGb,proto3" json:"default_vm_scratch_size_in_gb,omitempty"`
// share_scratch specifies if we'd like to reuse scratch space between multiple containers.
// This currently only affects LCOW. The sandbox containers scratch space is re-used for all
// subsequent containers launched in the pod.
ShareScratch bool `protobuf:"varint,14,opt,name=share_scratch,json=shareScratch,proto3" json:"share_scratch,omitempty"`
//NCProxyAddr is the address of the network configuration proxy service. If omitted
// the network is setup locally.
NCProxyAddr string `protobuf:"bytes,15,opt,name=NCProxyAddr,proto3" json:"NCProxyAddr,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@ -214,56 +234,64 @@ func init() {
} }
var fileDescriptor_b643df6839c75082 = []byte{ var fileDescriptor_b643df6839c75082 = []byte{
// 775 bytes of a gzipped FileDescriptorProto // 899 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0xcd, 0x6f, 0xdb, 0x36, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0x5b, 0x6f, 0xdb, 0x36,
0x1c, 0xb5, 0x1a, 0x7f, 0xe9, 0xd7, 0x25, 0x75, 0x38, 0x1f, 0x84, 0x6c, 0xb3, 0x8d, 0xf4, 0xd0, 0x18, 0x86, 0xad, 0x26, 0x71, 0xac, 0x2f, 0x71, 0xe2, 0x70, 0x06, 0x26, 0xa4, 0xab, 0x6d, 0xa4,
0x14, 0x6b, 0xa4, 0xa4, 0x3b, 0xee, 0x34, 0xc7, 0xce, 0xaa, 0x61, 0x49, 0x04, 0x39, 0x6b, 0xf7, 0x03, 0x9a, 0x62, 0x8d, 0x94, 0x74, 0x97, 0x1b, 0x30, 0xd4, 0x87, 0xb4, 0x1e, 0x9a, 0x44, 0x90,
0x71, 0x20, 0xf4, 0xc1, 0xc8, 0x44, 0x4d, 0x51, 0x20, 0x69, 0x2f, 0xee, 0x69, 0x7f, 0xc2, 0xfe, 0xb3, 0x74, 0x87, 0x0b, 0x42, 0x07, 0x5a, 0x16, 0x6a, 0x8a, 0x02, 0x49, 0x7b, 0x71, 0xaf, 0xf6,
0xa8, 0x1d, 0x72, 0xdc, 0x71, 0xc0, 0x80, 0x6c, 0xf5, 0x5f, 0x32, 0x90, 0x92, 0xd2, 0xad, 0x08, 0x13, 0xf6, 0xb3, 0x72, 0xb9, 0xcb, 0x0d, 0x03, 0xb2, 0xd5, 0xbf, 0x64, 0x10, 0x45, 0xb9, 0x5d,
0x76, 0xe9, 0xc9, 0xd4, 0x7b, 0x8f, 0xef, 0xf7, 0xc1, 0x07, 0xc3, 0x45, 0x46, 0xd5, 0x7c, 0x19, 0x10, 0xec, 0x66, 0x57, 0xa6, 0xde, 0xef, 0xe1, 0xcb, 0x8f, 0x87, 0xd7, 0x70, 0x11, 0x27, 0x72,
0xbb, 0x09, 0x67, 0xde, 0x19, 0x4d, 0x04, 0x97, 0xfc, 0x4a, 0x79, 0xf3, 0x44, 0xca, 0x39, 0x65, 0x32, 0x0b, 0xec, 0x90, 0x51, 0xe7, 0x2c, 0x09, 0x39, 0x13, 0x6c, 0x2c, 0x9d, 0x49, 0x28, 0xc4,
0x5e, 0xc2, 0x52, 0x2f, 0xe1, 0xb9, 0x8a, 0x68, 0x4e, 0x44, 0x7a, 0xa8, 0xb1, 0x43, 0xb1, 0xcc, 0x24, 0xa1, 0x4e, 0x48, 0x23, 0x27, 0x64, 0xa9, 0xf4, 0x93, 0x94, 0xf0, 0xe8, 0x28, 0xd7, 0x8e,
0xe7, 0x89, 0x3c, 0x5c, 0x1d, 0x7b, 0xbc, 0x50, 0x94, 0xe7, 0xd2, 0x2b, 0x11, 0xb7, 0x10, 0x5c, 0xf8, 0x2c, 0x9d, 0x84, 0xe2, 0x68, 0x7e, 0xe2, 0xb0, 0x4c, 0x26, 0x2c, 0x15, 0x4e, 0xa1, 0xd8,
0x71, 0xd4, 0x7f, 0xa7, 0x77, 0x2b, 0x62, 0x75, 0xbc, 0xd7, 0xcf, 0x78, 0xc6, 0x8d, 0xc0, 0xd3, 0x19, 0x67, 0x92, 0xa1, 0xe6, 0x07, 0xde, 0xd6, 0x85, 0xf9, 0xc9, 0x7e, 0x33, 0x66, 0x31, 0x53,
0xa7, 0x52, 0xbb, 0x37, 0xcc, 0x38, 0xcf, 0x16, 0xc4, 0x33, 0x5f, 0xf1, 0xf2, 0xca, 0x53, 0x94, 0x80, 0x93, 0x8f, 0x0a, 0x76, 0xbf, 0x1d, 0x33, 0x16, 0x4f, 0x89, 0xa3, 0xbe, 0x82, 0xd9, 0xd8,
0x11, 0xa9, 0x22, 0x56, 0x94, 0x82, 0xfd, 0xdf, 0x9a, 0xd0, 0xb9, 0x28, 0xab, 0xa0, 0x3e, 0xb4, 0x91, 0x09, 0x25, 0x42, 0xfa, 0x34, 0x2b, 0x80, 0x83, 0x3f, 0xaa, 0xb0, 0x79, 0x51, 0xac, 0x82,
0x52, 0x12, 0x2f, 0x33, 0xc7, 0x1a, 0x59, 0x07, 0xdd, 0xb0, 0xfc, 0x40, 0xa7, 0x00, 0xe6, 0x80, 0x9a, 0xb0, 0x11, 0x91, 0x60, 0x16, 0x5b, 0x46, 0xc7, 0x38, 0xac, 0x79, 0xc5, 0x07, 0x3a, 0x05,
0xd5, 0xba, 0x20, 0xce, 0x83, 0x91, 0x75, 0xb0, 0xf3, 0xfc, 0x89, 0x7b, 0x5f, 0x0f, 0x6e, 0x65, 0x50, 0x03, 0x2c, 0x17, 0x19, 0xb1, 0x1e, 0x74, 0x8c, 0xc3, 0x9d, 0xe7, 0x4f, 0xec, 0xfb, 0x7a,
0xe4, 0x4e, 0xb4, 0xfe, 0x72, 0x5d, 0x90, 0xd0, 0x4e, 0xeb, 0x23, 0x7a, 0x0c, 0xdb, 0x82, 0x64, 0xb0, 0xb5, 0x91, 0xdd, 0xcf, 0xf9, 0xcb, 0x45, 0x46, 0x3c, 0x33, 0x2a, 0x87, 0xe8, 0x31, 0xd4,
0x54, 0x2a, 0xb1, 0xc6, 0x82, 0x73, 0xe5, 0x6c, 0x8d, 0xac, 0x03, 0x3b, 0xfc, 0xa8, 0x06, 0x43, 0x39, 0x89, 0x13, 0x21, 0xf9, 0x02, 0x73, 0xc6, 0xa4, 0xb5, 0xd6, 0x31, 0x0e, 0x4d, 0x6f, 0xbb,
0xce, 0x95, 0x16, 0xc9, 0x28, 0x4f, 0x63, 0x7e, 0x8d, 0x29, 0x8b, 0x32, 0xe2, 0x34, 0x4b, 0x51, 0x14, 0x3d, 0xc6, 0x64, 0x0e, 0x09, 0x3f, 0x8d, 0x02, 0x76, 0x8d, 0x13, 0xea, 0xc7, 0xc4, 0x5a,
0x05, 0xfa, 0x1a, 0x43, 0x4f, 0xa1, 0x57, 0x8b, 0x8a, 0x45, 0xa4, 0xae, 0xb8, 0x60, 0x4e, 0xcb, 0x2f, 0x20, 0x2d, 0x0e, 0x73, 0x0d, 0x3d, 0x85, 0x46, 0x09, 0x65, 0x53, 0x5f, 0x8e, 0x19, 0xa7,
0xe8, 0x1e, 0x55, 0x78, 0x50, 0xc1, 0xe8, 0x27, 0xd8, 0xbd, 0xf3, 0x93, 0x7c, 0x11, 0xe9, 0xfe, 0xd6, 0x86, 0xe2, 0x76, 0xb5, 0xee, 0x6a, 0x19, 0xfd, 0x04, 0x7b, 0x2b, 0x3f, 0xc1, 0xa6, 0x7e,
0x9c, 0xb6, 0x99, 0xc1, 0xfd, 0xff, 0x19, 0x66, 0x55, 0xc5, 0xfa, 0x56, 0x58, 0xd7, 0xbc, 0x43, 0xde, 0x9f, 0x55, 0x55, 0x7b, 0xb0, 0xff, 0x7b, 0x0f, 0x23, 0xbd, 0x62, 0x39, 0xcb, 0x2b, 0xd7,
0x90, 0x07, 0xfd, 0x98, 0x73, 0x85, 0xaf, 0xe8, 0x82, 0x48, 0x33, 0x13, 0x2e, 0x22, 0x35, 0x77, 0x5c, 0x29, 0xc8, 0x81, 0x66, 0xc0, 0x98, 0xc4, 0xe3, 0x64, 0x4a, 0x84, 0xda, 0x13, 0xce, 0x7c,
0x3a, 0xa6, 0x97, 0x5d, 0xcd, 0x9d, 0x6a, 0x4a, 0x4f, 0x16, 0x44, 0x6a, 0x8e, 0x9e, 0x01, 0x5a, 0x39, 0xb1, 0x36, 0x55, 0x2f, 0x7b, 0x79, 0xed, 0x34, 0x2f, 0xe5, 0x3b, 0x73, 0x7d, 0x39, 0x41,
0x31, 0x5c, 0x08, 0x9e, 0x10, 0x29, 0xb9, 0xc0, 0x09, 0x5f, 0xe6, 0xca, 0xe9, 0x8e, 0xac, 0x83, 0xcf, 0x00, 0xcd, 0x29, 0xce, 0x38, 0x0b, 0x89, 0x10, 0x8c, 0xe3, 0x90, 0xcd, 0x52, 0x69, 0xd5,
0x56, 0xd8, 0x5b, 0xb1, 0xa0, 0x26, 0x4e, 0x34, 0x8e, 0x5c, 0xe8, 0xaf, 0x18, 0x66, 0x84, 0x71, 0x3a, 0xc6, 0xe1, 0x86, 0xd7, 0x98, 0x53, 0xb7, 0x2c, 0xf4, 0x72, 0x1d, 0xd9, 0xd0, 0x9c, 0x53,
0xb1, 0xc6, 0x92, 0xbe, 0x21, 0x98, 0xe6, 0x98, 0xc5, 0x8e, 0x5d, 0xeb, 0xcf, 0x0c, 0x35, 0xa3, 0x4c, 0x09, 0x65, 0x7c, 0x81, 0x45, 0xf2, 0x8e, 0xe0, 0x24, 0xc5, 0x34, 0xb0, 0xcc, 0x92, 0x3f,
0x6f, 0x88, 0x9f, 0x9f, 0xc5, 0x68, 0x00, 0xf0, 0x75, 0xf0, 0xdd, 0xcb, 0x17, 0x13, 0x5d, 0xcb, 0x53, 0xa5, 0x51, 0xf2, 0x8e, 0x0c, 0xd3, 0xb3, 0x00, 0xb5, 0x00, 0x5e, 0xba, 0xdf, 0x5d, 0xbd,
0x01, 0xd3, 0xc4, 0xbf, 0x90, 0xfd, 0xa7, 0x60, 0xdf, 0x3d, 0x0c, 0xb2, 0xa1, 0x75, 0x1e, 0xf8, 0xea, 0xe7, 0x6b, 0x59, 0xa0, 0x9a, 0xf8, 0x48, 0x41, 0x5f, 0xc3, 0x43, 0x11, 0xfa, 0x53, 0x82,
0xc1, 0xb4, 0xd7, 0x40, 0x5d, 0x68, 0x9e, 0xfa, 0xdf, 0x4e, 0x7b, 0x16, 0xea, 0xc0, 0xd6, 0xf4, 0xc3, 0x6c, 0x86, 0xa7, 0x09, 0x4d, 0xa4, 0xc0, 0x92, 0x61, 0xbd, 0x2d, 0x6b, 0x4b, 0x5d, 0xfa,
0xf2, 0x55, 0xef, 0xc1, 0xbe, 0x07, 0xbd, 0xf7, 0xe7, 0x47, 0x0f, 0xa1, 0x13, 0x84, 0x17, 0x27, 0xa7, 0x0a, 0xe9, 0x65, 0xb3, 0xd7, 0x0a, 0xb8, 0x64, 0xfa, 0x1c, 0xd0, 0x19, 0x7c, 0x1e, 0x91,
0xd3, 0xd9, 0xac, 0xd7, 0x40, 0x3b, 0x00, 0x2f, 0x7e, 0x08, 0xa6, 0xe1, 0x4b, 0x7f, 0x76, 0x11, 0xb1, 0x3f, 0x9b, 0x4a, 0xbc, 0x3a, 0x37, 0x2c, 0x42, 0xee, 0xcb, 0x70, 0xb2, 0xea, 0x2e, 0x0e,
0xf6, 0xac, 0xfd, 0x3f, 0xb7, 0x60, 0xa7, 0x6a, 0x7f, 0x42, 0x54, 0x44, 0x17, 0x12, 0x7d, 0x06, 0xac, 0x6d, 0xd5, 0x5d, 0x5b, 0xb3, 0xbd, 0x12, 0x1d, 0x15, 0x64, 0xd1, 0xec, 0xcb, 0x00, 0x7d,
0x60, 0x9e, 0x10, 0xe7, 0x11, 0x23, 0x26, 0x52, 0x76, 0x68, 0x1b, 0xe4, 0x3c, 0x62, 0x04, 0x9d, 0x03, 0x8f, 0x4a, 0xbb, 0x39, 0xbd, 0xcf, 0xa7, 0xae, 0x7c, 0x2c, 0x0d, 0x5d, 0xd1, 0xbb, 0x06,
0x00, 0x24, 0x82, 0x44, 0x8a, 0xa4, 0x38, 0x52, 0x26, 0x56, 0x0f, 0x9f, 0xef, 0xb9, 0x65, 0x5c, 0xf9, 0x4b, 0x99, 0xf8, 0x9c, 0x94, 0x73, 0xad, 0x1d, 0xd5, 0xff, 0xb6, 0x12, 0x35, 0x8c, 0x3a,
0xdd, 0x3a, 0xae, 0xee, 0x65, 0x1d, 0xd7, 0x71, 0xf7, 0xe6, 0x76, 0xd8, 0xf8, 0xf5, 0xaf, 0xa1, 0xb0, 0x75, 0xde, 0x73, 0x39, 0xbb, 0x5e, 0xbc, 0x88, 0x22, 0x6e, 0xed, 0xaa, 0x33, 0xf9, 0x58,
0x15, 0xda, 0xd5, 0xbd, 0xaf, 0x14, 0xfa, 0x1c, 0xd0, 0x6b, 0x22, 0x72, 0xb2, 0xc0, 0x3a, 0xd7, 0x3a, 0x78, 0x0a, 0xe6, 0xea, 0xb5, 0x22, 0x13, 0x36, 0xce, 0xdd, 0xa1, 0x3b, 0x68, 0x54, 0x50,
0xf8, 0xf8, 0xe8, 0x08, 0xe7, 0xd2, 0x04, 0xab, 0x19, 0x3e, 0x2a, 0x19, 0xed, 0x70, 0x7c, 0x74, 0x0d, 0xd6, 0x4f, 0x87, 0xaf, 0x07, 0x0d, 0x03, 0x6d, 0xc2, 0xda, 0xe0, 0xf2, 0x4d, 0xe3, 0xc1,
0x74, 0x2e, 0x91, 0x0b, 0x1f, 0x57, 0xcb, 0x4c, 0x38, 0x63, 0x54, 0xe1, 0x78, 0xad, 0x88, 0x34, 0x81, 0x03, 0x8d, 0xbb, 0x8f, 0x02, 0x6d, 0xc1, 0xa6, 0xeb, 0x5d, 0xf4, 0x06, 0xa3, 0x51, 0xa3,
0x09, 0x6b, 0x86, 0xbb, 0x25, 0x75, 0x62, 0x98, 0xb1, 0x26, 0xd0, 0x29, 0x8c, 0x2a, 0xfd, 0xcf, 0x82, 0x76, 0x00, 0x5e, 0xfd, 0xe0, 0x0e, 0xbc, 0xab, 0xe1, 0xe8, 0xc2, 0x6b, 0x18, 0x07, 0x7f,
0x5c, 0xbc, 0xa6, 0x79, 0x86, 0x25, 0x51, 0xb8, 0x10, 0x74, 0x15, 0x29, 0x52, 0x5d, 0x6e, 0x99, 0xae, 0xc1, 0x8e, 0xbe, 0xd3, 0x3e, 0x91, 0x7e, 0x32, 0x15, 0xe8, 0x11, 0x80, 0x7a, 0xd7, 0x38,
0xcb, 0x9f, 0x96, 0xba, 0x57, 0xa5, 0x6c, 0x46, 0x54, 0x50, 0x8a, 0x4a, 0x9f, 0x09, 0x0c, 0xef, 0xf5, 0x29, 0x51, 0x39, 0x33, 0x3d, 0x53, 0x29, 0xe7, 0x3e, 0x25, 0xa8, 0x07, 0x10, 0x72, 0xe2,
0xf1, 0x91, 0xf3, 0x48, 0x90, 0xb4, 0xb2, 0x69, 0x1b, 0x9b, 0x4f, 0xde, 0xb7, 0x99, 0x19, 0x4d, 0x4b, 0x12, 0x61, 0x5f, 0xaa, 0xac, 0x6d, 0x3d, 0xdf, 0xb7, 0x8b, 0x0c, 0xdb, 0x65, 0x86, 0xed,
0xe9, 0xf2, 0x0c, 0xa0, 0x0a, 0x0e, 0xa6, 0xa9, 0x89, 0xd8, 0xf6, 0x78, 0x7b, 0x73, 0x3b, 0xb4, 0xcb, 0x32, 0xc3, 0xdd, 0xda, 0xcd, 0x6d, 0xbb, 0xf2, 0xeb, 0x5f, 0x6d, 0xc3, 0x33, 0xf5, 0xbc,
0xab, 0xb5, 0xfb, 0x93, 0xd0, 0xae, 0x04, 0x7e, 0x8a, 0x9e, 0x40, 0x6f, 0x29, 0x89, 0xf8, 0xcf, 0x17, 0x12, 0x7d, 0x01, 0xe8, 0x2d, 0xe1, 0x29, 0x99, 0xe2, 0x3c, 0xec, 0xf8, 0xe4, 0xf8, 0x18,
0x5a, 0xba, 0xa6, 0xc8, 0xb6, 0xc6, 0xdf, 0x2d, 0xe5, 0x31, 0x74, 0xc8, 0x35, 0x49, 0xb4, 0xa7, 0xa7, 0x42, 0xa5, 0x6d, 0xdd, 0xdb, 0x2d, 0x2a, 0xb9, 0xc3, 0xc9, 0xf1, 0xf1, 0xb9, 0x40, 0x36,
0xce, 0x95, 0x3d, 0x86, 0xcd, 0xed, 0xb0, 0x3d, 0xbd, 0x26, 0x89, 0x3f, 0x09, 0xdb, 0x9a, 0xf2, 0x7c, 0xa2, 0x5f, 0x58, 0xc8, 0x28, 0x4d, 0x24, 0x0e, 0x16, 0x92, 0x08, 0x15, 0xbb, 0x75, 0x6f,
0xd3, 0x71, 0x7a, 0xf3, 0x76, 0xd0, 0xf8, 0xe3, 0xed, 0xa0, 0xf1, 0xcb, 0x66, 0x60, 0xdd, 0x6c, 0xaf, 0x28, 0xf5, 0x54, 0xa5, 0x9b, 0x17, 0xd0, 0x29, 0x74, 0x34, 0xff, 0x33, 0xe3, 0x6f, 0x93,
0x06, 0xd6, 0xef, 0x9b, 0x81, 0xf5, 0xf7, 0x66, 0x60, 0xfd, 0xf8, 0xcd, 0x87, 0xff, 0xb9, 0x7d, 0x34, 0xc6, 0x82, 0x48, 0x9c, 0xf1, 0x64, 0xee, 0x4b, 0xa2, 0x27, 0x6f, 0xa8, 0xc9, 0x9f, 0x15,
0x59, 0xfd, 0x7e, 0xdf, 0x88, 0xdb, 0xe6, 0xdd, 0xbf, 0xf8, 0x27, 0x00, 0x00, 0xff, 0xff, 0x75, 0xdc, 0x9b, 0x02, 0x1b, 0x11, 0xe9, 0x16, 0x50, 0xe1, 0xd3, 0x87, 0xf6, 0x3d, 0x3e, 0xea, 0xf2,
0x1f, 0x14, 0xf4, 0x33, 0x05, 0x00, 0x00, 0x22, 0x6d, 0x53, 0x55, 0x36, 0x0f, 0xef, 0xda, 0x8c, 0x14, 0x53, 0xb8, 0x3c, 0x03, 0xd0, 0x69,
0xc2, 0x49, 0xa4, 0x72, 0x57, 0xef, 0xd6, 0x97, 0xb7, 0x6d, 0x53, 0x1f, 0xfb, 0xb0, 0xef, 0x99,
0x1a, 0x18, 0x46, 0xe8, 0x09, 0x34, 0x66, 0x82, 0xf0, 0x7f, 0x1d, 0x4b, 0x4d, 0x2d, 0x52, 0xcf,
0xf5, 0x0f, 0x87, 0xf2, 0x18, 0x36, 0xc9, 0x35, 0x09, 0x73, 0xcf, 0x3c, 0x6c, 0x66, 0x17, 0x96,
0xb7, 0xed, 0xea, 0xe0, 0x9a, 0x84, 0xc3, 0xbe, 0x57, 0xcd, 0x4b, 0xc3, 0xa8, 0x1b, 0xdd, 0xbc,
0x6f, 0x55, 0x7e, 0x7f, 0xdf, 0xaa, 0xfc, 0xb2, 0x6c, 0x19, 0x37, 0xcb, 0x96, 0xf1, 0xdb, 0xb2,
0x65, 0xfc, 0xbd, 0x6c, 0x19, 0x3f, 0x7e, 0xfb, 0xff, 0xff, 0xf1, 0xbf, 0xd2, 0xbf, 0xdf, 0x57,
0x82, 0xaa, 0xba, 0xf7, 0x2f, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0xc9, 0x0d, 0x33, 0xad, 0x48,
0x06, 0x00, 0x00,
} }
func (m *Options) Marshal() (dAtA []byte, err error) { func (m *Options) Marshal() (dAtA []byte, err error) {
@ -341,6 +369,42 @@ func (m *Options) MarshalTo(dAtA []byte) (int, error) {
i = encodeVarintRunhcs(dAtA, i, uint64(len(m.GPUVHDPath))) i = encodeVarintRunhcs(dAtA, i, uint64(len(m.GPUVHDPath)))
i += copy(dAtA[i:], m.GPUVHDPath) i += copy(dAtA[i:], m.GPUVHDPath)
} }
if m.ScaleCpuLimitsToSandbox {
dAtA[i] = 0x58
i++
if m.ScaleCpuLimitsToSandbox {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
if m.DefaultContainerScratchSizeInGb != 0 {
dAtA[i] = 0x60
i++
i = encodeVarintRunhcs(dAtA, i, uint64(m.DefaultContainerScratchSizeInGb))
}
if m.DefaultVmScratchSizeInGb != 0 {
dAtA[i] = 0x68
i++
i = encodeVarintRunhcs(dAtA, i, uint64(m.DefaultVmScratchSizeInGb))
}
if m.ShareScratch {
dAtA[i] = 0x70
i++
if m.ShareScratch {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
if len(m.NCProxyAddr) > 0 {
dAtA[i] = 0x7a
i++
i = encodeVarintRunhcs(dAtA, i, uint64(len(m.NCProxyAddr)))
i += copy(dAtA[i:], m.NCProxyAddr)
}
if m.XXX_unrecognized != nil { if m.XXX_unrecognized != nil {
i += copy(dAtA[i:], m.XXX_unrecognized) i += copy(dAtA[i:], m.XXX_unrecognized)
} }
@ -468,6 +532,22 @@ func (m *Options) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovRunhcs(uint64(l)) n += 1 + l + sovRunhcs(uint64(l))
} }
if m.ScaleCpuLimitsToSandbox {
n += 2
}
if m.DefaultContainerScratchSizeInGb != 0 {
n += 1 + sovRunhcs(uint64(m.DefaultContainerScratchSizeInGb))
}
if m.DefaultVmScratchSizeInGb != 0 {
n += 1 + sovRunhcs(uint64(m.DefaultVmScratchSizeInGb))
}
if m.ShareScratch {
n += 2
}
l = len(m.NCProxyAddr)
if l > 0 {
n += 1 + l + sovRunhcs(uint64(l))
}
if m.XXX_unrecognized != nil { if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized) n += len(m.XXX_unrecognized)
} }
@ -542,6 +622,11 @@ func (this *Options) String() string {
`VmProcessorCount:` + fmt.Sprintf("%v", this.VmProcessorCount) + `,`, `VmProcessorCount:` + fmt.Sprintf("%v", this.VmProcessorCount) + `,`,
`VmMemorySizeInMb:` + fmt.Sprintf("%v", this.VmMemorySizeInMb) + `,`, `VmMemorySizeInMb:` + fmt.Sprintf("%v", this.VmMemorySizeInMb) + `,`,
`GPUVHDPath:` + fmt.Sprintf("%v", this.GPUVHDPath) + `,`, `GPUVHDPath:` + fmt.Sprintf("%v", this.GPUVHDPath) + `,`,
`ScaleCpuLimitsToSandbox:` + fmt.Sprintf("%v", this.ScaleCpuLimitsToSandbox) + `,`,
`DefaultContainerScratchSizeInGb:` + fmt.Sprintf("%v", this.DefaultContainerScratchSizeInGb) + `,`,
`DefaultVmScratchSizeInGb:` + fmt.Sprintf("%v", this.DefaultVmScratchSizeInGb) + `,`,
`ShareScratch:` + fmt.Sprintf("%v", this.ShareScratch) + `,`,
`NCProxyAddr:` + fmt.Sprintf("%v", this.NCProxyAddr) + `,`,
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
`}`, `}`,
}, "") }, "")
@ -859,6 +944,116 @@ func (m *Options) Unmarshal(dAtA []byte) error {
} }
m.GPUVHDPath = string(dAtA[iNdEx:postIndex]) m.GPUVHDPath = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 11:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ScaleCpuLimitsToSandbox", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRunhcs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.ScaleCpuLimitsToSandbox = bool(v != 0)
case 12:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field DefaultContainerScratchSizeInGb", wireType)
}
m.DefaultContainerScratchSizeInGb = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRunhcs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.DefaultContainerScratchSizeInGb |= int32(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 13:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field DefaultVmScratchSizeInGb", wireType)
}
m.DefaultVmScratchSizeInGb = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRunhcs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.DefaultVmScratchSizeInGb |= int32(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 14:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ShareScratch", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRunhcs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.ShareScratch = bool(v != 0)
case 15:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field NCProxyAddr", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRunhcs
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthRunhcs
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthRunhcs
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.NCProxyAddr = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipRunhcs(dAtA[iNdEx:]) skippy, err := skipRunhcs(dAtA[iNdEx:])

View file

@ -62,7 +62,30 @@ message Options {
// GPUVHDPath is the path to the gpu vhd to add to the uvm // GPUVHDPath is the path to the gpu vhd to add to the uvm
// when a container requests a gpu // when a container requests a gpu
string GPUVHDPath = 10; string GPUVHDPath = 10;
// scale_cpu_limits_to_sandbox indicates that container CPU limits should
// be adjusted to account for the difference in number of cores between the
// host and UVM.
bool scale_cpu_limits_to_sandbox = 11;
// default_container_scratch_size_in_gb is the default scratch size (sandbox.vhdx)
// to be used for containers. Every container will get a sandbox of `size_in_gb` assigned
// instead of the default of 20GB.
int32 default_container_scratch_size_in_gb = 12;
// default_vm_scratch_size_in_gb is the default scratch size (sandbox.vhdx)
// to be used for the UVM. This only applies to WCOW as LCOW doesn't mount a scratch
// specifically for the UVM.
int32 default_vm_scratch_size_in_gb = 13;
// share_scratch specifies if we'd like to reuse scratch space between multiple containers.
// This currently only affects LCOW. The sandbox containers scratch space is re-used for all
// subsequent containers launched in the pod.
bool share_scratch = 14;
//NCProxyAddr is the address of the network configuration proxy service. If omitted
// the network is setup locally.
string NCProxyAddr = 15;
} }
// ProcessDetails contains additional information about a process. This is the additional // ProcessDetails contains additional information about a process. This is the additional

View file

@ -0,0 +1,38 @@
package computestorage
import (
"context"
"encoding/json"
"github.com/Microsoft/hcsshim/internal/oc"
"github.com/pkg/errors"
"go.opencensus.io/trace"
)
// AttachLayerStorageFilter sets up the layer storage filter on a writable
// container layer.
//
// `layerPath` is a path to a directory the writable layer is mounted. If the
// path does not end in a `\` the platform will append it automatically.
//
// `layerData` is the parent read-only layer data.
func AttachLayerStorageFilter(ctx context.Context, layerPath string, layerData LayerData) (err error) {
title := "hcsshim.AttachLayerStorageFilter"
ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(
trace.StringAttribute("layerPath", layerPath),
)
bytes, err := json.Marshal(layerData)
if err != nil {
return err
}
err = hcsAttachLayerStorageFilter(layerPath, string(bytes))
if err != nil {
return errors.Wrap(err, "failed to attach layer storage filter")
}
return nil
}

View file

@ -0,0 +1,26 @@
package computestorage
import (
"context"
"github.com/Microsoft/hcsshim/internal/oc"
"github.com/pkg/errors"
"go.opencensus.io/trace"
)
// DestroyLayer deletes a container layer.
//
// `layerPath` is a path to a directory containing the layer to export.
func DestroyLayer(ctx context.Context, layerPath string) (err error) {
title := "hcsshim.DestroyLayer"
ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("layerPath", layerPath))
err = hcsDestroyLayer(layerPath)
if err != nil {
return errors.Wrap(err, "failed to destroy layer")
}
return nil
}

View file

@ -0,0 +1,26 @@
package computestorage
import (
"context"
"github.com/Microsoft/hcsshim/internal/oc"
"github.com/pkg/errors"
"go.opencensus.io/trace"
)
// DetachLayerStorageFilter detaches the layer storage filter on a writable container layer.
//
// `layerPath` is a path to a directory containing the layer to export.
func DetachLayerStorageFilter(ctx context.Context, layerPath string) (err error) {
title := "hcsshim.DetachLayerStorageFilter"
ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("layerPath", layerPath))
err = hcsDetachLayerStorageFilter(layerPath)
if err != nil {
return errors.Wrap(err, "failed to detach layer storage filter")
}
return nil
}

View file

@ -0,0 +1,46 @@
package computestorage
import (
"context"
"encoding/json"
"github.com/Microsoft/hcsshim/internal/oc"
"github.com/pkg/errors"
"go.opencensus.io/trace"
)
// ExportLayer exports a container layer.
//
// `layerPath` is a path to a directory containing the layer to export.
//
// `exportFolderPath` is a pre-existing folder to export the layer to.
//
// `layerData` is the parent layer data.
//
// `options` are the export options applied to the exported layer.
func ExportLayer(ctx context.Context, layerPath, exportFolderPath string, layerData LayerData, options ExportLayerOptions) (err error) {
title := "hcsshim.ExportLayer"
ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(
trace.StringAttribute("layerPath", layerPath),
trace.StringAttribute("exportFolderPath", exportFolderPath),
)
ldbytes, err := json.Marshal(layerData)
if err != nil {
return err
}
obytes, err := json.Marshal(options)
if err != nil {
return err
}
err = hcsExportLayer(layerPath, exportFolderPath, string(ldbytes), string(obytes))
if err != nil {
return errors.Wrap(err, "failed to export layer")
}
return nil
}

View file

@ -0,0 +1,26 @@
package computestorage
import (
"context"
"github.com/Microsoft/hcsshim/internal/oc"
"github.com/pkg/errors"
"go.opencensus.io/trace"
"golang.org/x/sys/windows"
)
// FormatWritableLayerVhd formats a virtual disk for use as a writable container layer.
//
// If the VHD is not mounted it will be temporarily mounted.
func FormatWritableLayerVhd(ctx context.Context, vhdHandle windows.Handle) (err error) {
title := "hcsshim.FormatWritableLayerVhd"
ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
err = hcsFormatWritableLayerVhd(vhdHandle)
if err != nil {
return errors.Wrap(err, "failed to format writable layer vhd")
}
return nil
}

View file

@ -0,0 +1,193 @@
package computestorage
import (
"context"
"os"
"path/filepath"
"syscall"
"github.com/Microsoft/go-winio/pkg/security"
"github.com/Microsoft/go-winio/vhd"
"github.com/pkg/errors"
"golang.org/x/sys/windows"
)
const defaultVHDXBlockSizeInMB = 1
// SetupContainerBaseLayer is a helper to setup a containers scratch. It
// will create and format the vhdx's inside and the size is configurable with the sizeInGB
// parameter.
//
// `layerPath` is the path to the base container layer on disk.
//
// `baseVhdPath` is the path to where the base vhdx for the base layer should be created.
//
// `diffVhdPath` is the path where the differencing disk for the base layer should be created.
//
// `sizeInGB` is the size in gigabytes to make the base vhdx.
func SetupContainerBaseLayer(ctx context.Context, layerPath, baseVhdPath, diffVhdPath string, sizeInGB uint64) (err error) {
var (
hivesPath = filepath.Join(layerPath, "Hives")
layoutPath = filepath.Join(layerPath, "Layout")
)
// We need to remove the hives directory and layout file as `SetupBaseOSLayer` fails if these files
// already exist. `SetupBaseOSLayer` will create these files internally. We also remove the base and
// differencing disks if they exist in case we're asking for a different size.
if _, err := os.Stat(hivesPath); err == nil {
if err := os.RemoveAll(hivesPath); err != nil {
return errors.Wrap(err, "failed to remove prexisting hives directory")
}
}
if _, err := os.Stat(layoutPath); err == nil {
if err := os.RemoveAll(layoutPath); err != nil {
return errors.Wrap(err, "failed to remove prexisting layout file")
}
}
if _, err := os.Stat(baseVhdPath); err == nil {
if err := os.RemoveAll(baseVhdPath); err != nil {
return errors.Wrap(err, "failed to remove base vhdx path")
}
}
if _, err := os.Stat(diffVhdPath); err == nil {
if err := os.RemoveAll(diffVhdPath); err != nil {
return errors.Wrap(err, "failed to remove differencing vhdx")
}
}
createParams := &vhd.CreateVirtualDiskParameters{
Version: 2,
Version2: vhd.CreateVersion2{
MaximumSize: sizeInGB * 1024 * 1024 * 1024,
BlockSizeInBytes: defaultVHDXBlockSizeInMB * 1024 * 1024,
},
}
handle, err := vhd.CreateVirtualDisk(baseVhdPath, vhd.VirtualDiskAccessNone, vhd.CreateVirtualDiskFlagNone, createParams)
if err != nil {
return errors.Wrap(err, "failed to create vhdx")
}
defer func() {
if err != nil {
_ = syscall.CloseHandle(handle)
os.RemoveAll(baseVhdPath)
os.RemoveAll(diffVhdPath)
}
}()
if err = FormatWritableLayerVhd(ctx, windows.Handle(handle)); err != nil {
return err
}
// Base vhd handle must be closed before calling SetupBaseLayer in case of Container layer
if err = syscall.CloseHandle(handle); err != nil {
return errors.Wrap(err, "failed to close vhdx handle")
}
options := OsLayerOptions{
Type: OsLayerTypeContainer,
}
// SetupBaseOSLayer expects an empty vhd handle for a container layer and will
// error out otherwise.
if err = SetupBaseOSLayer(ctx, layerPath, 0, options); err != nil {
return err
}
// Create the differencing disk that will be what's copied for the final rw layer
// for a container.
if err = vhd.CreateDiffVhd(diffVhdPath, baseVhdPath, defaultVHDXBlockSizeInMB); err != nil {
return errors.Wrap(err, "failed to create differencing disk")
}
if err = security.GrantVmGroupAccess(baseVhdPath); err != nil {
return errors.Wrapf(err, "failed to grant vm group access to %s", baseVhdPath)
}
if err = security.GrantVmGroupAccess(diffVhdPath); err != nil {
return errors.Wrapf(err, "failed to grant vm group access to %s", diffVhdPath)
}
return nil
}
// SetupUtilityVMBaseLayer is a helper to setup a UVMs scratch space. It will create and format
// the vhdx inside and the size is configurable by the sizeInGB parameter.
//
// `uvmPath` is the path to the UtilityVM filesystem.
//
// `baseVhdPath` is the path to where the base vhdx for the UVM should be created.
//
// `diffVhdPath` is the path where the differencing disk for the UVM should be created.
//
// `sizeInGB` specifies the size in gigabytes to make the base vhdx.
func SetupUtilityVMBaseLayer(ctx context.Context, uvmPath, baseVhdPath, diffVhdPath string, sizeInGB uint64) (err error) {
// Remove the base and differencing disks if they exist in case we're asking for a different size.
if _, err := os.Stat(baseVhdPath); err == nil {
if err := os.RemoveAll(baseVhdPath); err != nil {
return errors.Wrap(err, "failed to remove base vhdx")
}
}
if _, err := os.Stat(diffVhdPath); err == nil {
if err := os.RemoveAll(diffVhdPath); err != nil {
return errors.Wrap(err, "failed to remove differencing vhdx")
}
}
// Just create the vhdx for utilityVM layer, no need to format it.
createParams := &vhd.CreateVirtualDiskParameters{
Version: 2,
Version2: vhd.CreateVersion2{
MaximumSize: sizeInGB * 1024 * 1024 * 1024,
BlockSizeInBytes: defaultVHDXBlockSizeInMB * 1024 * 1024,
},
}
handle, err := vhd.CreateVirtualDisk(baseVhdPath, vhd.VirtualDiskAccessNone, vhd.CreateVirtualDiskFlagNone, createParams)
if err != nil {
return errors.Wrap(err, "failed to create vhdx")
}
defer func() {
if err != nil {
_ = syscall.CloseHandle(handle)
os.RemoveAll(baseVhdPath)
os.RemoveAll(diffVhdPath)
}
}()
// If it is a UtilityVM layer then the base vhdx must be attached when calling
// `SetupBaseOSLayer`
attachParams := &vhd.AttachVirtualDiskParameters{
Version: 2,
}
if err := vhd.AttachVirtualDisk(handle, vhd.AttachVirtualDiskFlagNone, attachParams); err != nil {
return errors.Wrapf(err, "failed to attach virtual disk")
}
options := OsLayerOptions{
Type: OsLayerTypeVM,
}
if err := SetupBaseOSLayer(ctx, uvmPath, windows.Handle(handle), options); err != nil {
return err
}
// Detach and close the handle after setting up the layer as we don't need the handle
// for anything else and we no longer need to be attached either.
if err = vhd.DetachVirtualDisk(handle); err != nil {
return errors.Wrap(err, "failed to detach vhdx")
}
if err = syscall.CloseHandle(handle); err != nil {
return errors.Wrap(err, "failed to close vhdx handle")
}
// Create the differencing disk that will be what's copied for the final rw layer
// for a container.
if err = vhd.CreateDiffVhd(diffVhdPath, baseVhdPath, defaultVHDXBlockSizeInMB); err != nil {
return errors.Wrap(err, "failed to create differencing disk")
}
if err := security.GrantVmGroupAccess(baseVhdPath); err != nil {
return errors.Wrapf(err, "failed to grant vm group access to %s", baseVhdPath)
}
if err := security.GrantVmGroupAccess(diffVhdPath); err != nil {
return errors.Wrapf(err, "failed to grant vm group access to %s", diffVhdPath)
}
return nil
}

View file

@ -0,0 +1,41 @@
package computestorage
import (
"context"
"encoding/json"
"github.com/Microsoft/hcsshim/internal/oc"
"github.com/pkg/errors"
"go.opencensus.io/trace"
)
// ImportLayer imports a container layer.
//
// `layerPath` is a path to a directory to import the layer to. If the directory
// does not exist it will be automatically created.
//
// `sourceFolderpath` is a pre-existing folder that contains the layer to
// import.
//
// `layerData` is the parent layer data.
func ImportLayer(ctx context.Context, layerPath, sourceFolderPath string, layerData LayerData) (err error) {
title := "hcsshim.ImportLayer"
ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(
trace.StringAttribute("layerPath", layerPath),
trace.StringAttribute("sourceFolderPath", sourceFolderPath),
)
bytes, err := json.Marshal(layerData)
if err != nil {
return err
}
err = hcsImportLayer(layerPath, sourceFolderPath, string(bytes))
if err != nil {
return errors.Wrap(err, "failed to import layer")
}
return nil
}

View file

@ -0,0 +1,38 @@
package computestorage
import (
"context"
"encoding/json"
"github.com/Microsoft/hcsshim/internal/oc"
"github.com/pkg/errors"
"go.opencensus.io/trace"
)
// InitializeWritableLayer initializes a writable layer for a container.
//
// `layerPath` is a path to a directory the layer is mounted. If the
// path does not end in a `\` the platform will append it automatically.
//
// `layerData` is the parent read-only layer data.
func InitializeWritableLayer(ctx context.Context, layerPath string, layerData LayerData) (err error) {
title := "hcsshim.InitializeWritableLayer"
ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(
trace.StringAttribute("layerPath", layerPath),
)
bytes, err := json.Marshal(layerData)
if err != nil {
return err
}
// Options are not used in the platform as of RS5
err = hcsInitializeWritableLayer(layerPath, string(bytes), "")
if err != nil {
return errors.Wrap(err, "failed to intitialize container layer")
}
return nil
}

View file

@ -0,0 +1,27 @@
package computestorage
import (
"context"
"github.com/Microsoft/hcsshim/internal/interop"
"github.com/Microsoft/hcsshim/internal/oc"
"github.com/pkg/errors"
"go.opencensus.io/trace"
"golang.org/x/sys/windows"
)
// GetLayerVhdMountPath returns the volume path for a virtual disk of a writable container layer.
func GetLayerVhdMountPath(ctx context.Context, vhdHandle windows.Handle) (path string, err error) {
title := "hcsshim.GetLayerVhdMountPath"
ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
var mountPath *uint16
err = hcsGetLayerVhdMountPath(vhdHandle, &mountPath)
if err != nil {
return "", errors.Wrap(err, "failed to get vhd mount path")
}
path = interop.ConvertAndFreeCoTaskMemString(mountPath)
return path, nil
}

View file

@ -0,0 +1,74 @@
package computestorage
import (
"context"
"encoding/json"
"github.com/Microsoft/hcsshim/internal/oc"
"github.com/Microsoft/hcsshim/osversion"
"github.com/pkg/errors"
"go.opencensus.io/trace"
"golang.org/x/sys/windows"
)
// SetupBaseOSLayer sets up a layer that contains a base OS for a container.
//
// `layerPath` is a path to a directory containing the layer.
//
// `vhdHandle` is an empty file handle of `options.Type == OsLayerTypeContainer`
// or else it is a file handle to the 'SystemTemplateBase.vhdx' if `options.Type
// == OsLayerTypeVm`.
//
// `options` are the options applied while processing the layer.
func SetupBaseOSLayer(ctx context.Context, layerPath string, vhdHandle windows.Handle, options OsLayerOptions) (err error) {
title := "hcsshim.SetupBaseOSLayer"
ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(
trace.StringAttribute("layerPath", layerPath),
)
bytes, err := json.Marshal(options)
if err != nil {
return err
}
err = hcsSetupBaseOSLayer(layerPath, vhdHandle, string(bytes))
if err != nil {
return errors.Wrap(err, "failed to setup base OS layer")
}
return nil
}
// SetupBaseOSVolume sets up a volume that contains a base OS for a container.
//
// `layerPath` is a path to a directory containing the layer.
//
// `volumePath` is the path to the volume to be used for setup.
//
// `options` are the options applied while processing the layer.
func SetupBaseOSVolume(ctx context.Context, layerPath, volumePath string, options OsLayerOptions) (err error) {
if osversion.Get().Build < 19645 {
return errors.New("SetupBaseOSVolume is not present on builds older than 19645")
}
title := "hcsshim.SetupBaseOSVolume"
ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(
trace.StringAttribute("layerPath", layerPath),
trace.StringAttribute("volumePath", volumePath),
)
bytes, err := json.Marshal(options)
if err != nil {
return err
}
err = hcsSetupBaseOSVolume(layerPath, volumePath, string(bytes))
if err != nil {
return errors.Wrap(err, "failed to setup base OS layer")
}
return nil
}

View file

@ -0,0 +1,50 @@
// Package computestorage is a wrapper around the HCS storage APIs. These are new storage APIs introduced
// separate from the original graphdriver calls intended to give more freedom around creating
// and managing container layers and scratch spaces.
package computestorage
import (
hcsschema "github.com/Microsoft/hcsshim/internal/schema2"
)
//go:generate go run ../mksyscall_windows.go -output zsyscall_windows.go storage.go
//sys hcsImportLayer(layerPath string, sourceFolderPath string, layerData string) (hr error) = computestorage.HcsImportLayer?
//sys hcsExportLayer(layerPath string, exportFolderPath string, layerData string, options string) (hr error) = computestorage.HcsExportLayer?
//sys hcsDestroyLayer(layerPath string) (hr error) = computestorage.HcsDestoryLayer?
//sys hcsSetupBaseOSLayer(layerPath string, handle windows.Handle, options string) (hr error) = computestorage.HcsSetupBaseOSLayer?
//sys hcsInitializeWritableLayer(writableLayerPath string, layerData string, options string) (hr error) = computestorage.HcsInitializeWritableLayer?
//sys hcsAttachLayerStorageFilter(layerPath string, layerData string) (hr error) = computestorage.HcsAttachLayerStorageFilter?
//sys hcsDetachLayerStorageFilter(layerPath string) (hr error) = computestorage.HcsDetachLayerStorageFilter?
//sys hcsFormatWritableLayerVhd(handle windows.Handle) (hr error) = computestorage.HcsFormatWritableLayerVhd?
//sys hcsGetLayerVhdMountPath(vhdHandle windows.Handle, mountPath **uint16) (hr error) = computestorage.HcsGetLayerVhdMountPath?
//sys hcsSetupBaseOSVolume(layerPath string, volumePath string, options string) (hr error) = computestorage.HcsSetupBaseOSVolume?
// LayerData is the data used to describe parent layer information.
type LayerData struct {
SchemaVersion hcsschema.Version `json:"SchemaVersion,omitempty"`
Layers []hcsschema.Layer `json:"Layers,omitempty"`
}
// ExportLayerOptions are the set of options that are used with the `computestorage.HcsExportLayer` syscall.
type ExportLayerOptions struct {
IsWritableLayer bool `json:"IsWritableLayer,omitempty"`
}
// OsLayerType is the type of layer being operated on.
type OsLayerType string
const (
// OsLayerTypeContainer is a container layer.
OsLayerTypeContainer OsLayerType = "Container"
// OsLayerTypeVM is a virtual machine layer.
OsLayerTypeVM OsLayerType = "Vm"
)
// OsLayerOptions are the set of options that are used with the `SetupBaseOSLayer` and
// `SetupBaseOSVolume` calls.
type OsLayerOptions struct {
Type OsLayerType `json:"Type,omitempty"`
DisableCiCacheOptimization bool `json:"DisableCiCacheOptimization,omitempty"`
SkipUpdateBcdForBoot bool `json:"SkipUpdateBcdForBoot,omitempty"`
}

View file

@ -0,0 +1,319 @@
// Code generated mksyscall_windows.exe DO NOT EDIT
package computestorage
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return nil
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modcomputestorage = windows.NewLazySystemDLL("computestorage.dll")
procHcsImportLayer = modcomputestorage.NewProc("HcsImportLayer")
procHcsExportLayer = modcomputestorage.NewProc("HcsExportLayer")
procHcsDestoryLayer = modcomputestorage.NewProc("HcsDestoryLayer")
procHcsSetupBaseOSLayer = modcomputestorage.NewProc("HcsSetupBaseOSLayer")
procHcsInitializeWritableLayer = modcomputestorage.NewProc("HcsInitializeWritableLayer")
procHcsAttachLayerStorageFilter = modcomputestorage.NewProc("HcsAttachLayerStorageFilter")
procHcsDetachLayerStorageFilter = modcomputestorage.NewProc("HcsDetachLayerStorageFilter")
procHcsFormatWritableLayerVhd = modcomputestorage.NewProc("HcsFormatWritableLayerVhd")
procHcsGetLayerVhdMountPath = modcomputestorage.NewProc("HcsGetLayerVhdMountPath")
procHcsSetupBaseOSVolume = modcomputestorage.NewProc("HcsSetupBaseOSVolume")
)
func hcsImportLayer(layerPath string, sourceFolderPath string, layerData string) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(layerPath)
if hr != nil {
return
}
var _p1 *uint16
_p1, hr = syscall.UTF16PtrFromString(sourceFolderPath)
if hr != nil {
return
}
var _p2 *uint16
_p2, hr = syscall.UTF16PtrFromString(layerData)
if hr != nil {
return
}
return _hcsImportLayer(_p0, _p1, _p2)
}
func _hcsImportLayer(layerPath *uint16, sourceFolderPath *uint16, layerData *uint16) (hr error) {
if hr = procHcsImportLayer.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsImportLayer.Addr(), 3, uintptr(unsafe.Pointer(layerPath)), uintptr(unsafe.Pointer(sourceFolderPath)), uintptr(unsafe.Pointer(layerData)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsExportLayer(layerPath string, exportFolderPath string, layerData string, options string) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(layerPath)
if hr != nil {
return
}
var _p1 *uint16
_p1, hr = syscall.UTF16PtrFromString(exportFolderPath)
if hr != nil {
return
}
var _p2 *uint16
_p2, hr = syscall.UTF16PtrFromString(layerData)
if hr != nil {
return
}
var _p3 *uint16
_p3, hr = syscall.UTF16PtrFromString(options)
if hr != nil {
return
}
return _hcsExportLayer(_p0, _p1, _p2, _p3)
}
func _hcsExportLayer(layerPath *uint16, exportFolderPath *uint16, layerData *uint16, options *uint16) (hr error) {
if hr = procHcsExportLayer.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall6(procHcsExportLayer.Addr(), 4, uintptr(unsafe.Pointer(layerPath)), uintptr(unsafe.Pointer(exportFolderPath)), uintptr(unsafe.Pointer(layerData)), uintptr(unsafe.Pointer(options)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsDestroyLayer(layerPath string) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(layerPath)
if hr != nil {
return
}
return _hcsDestroyLayer(_p0)
}
func _hcsDestroyLayer(layerPath *uint16) (hr error) {
if hr = procHcsDestoryLayer.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsDestoryLayer.Addr(), 1, uintptr(unsafe.Pointer(layerPath)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsSetupBaseOSLayer(layerPath string, handle windows.Handle, options string) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(layerPath)
if hr != nil {
return
}
var _p1 *uint16
_p1, hr = syscall.UTF16PtrFromString(options)
if hr != nil {
return
}
return _hcsSetupBaseOSLayer(_p0, handle, _p1)
}
func _hcsSetupBaseOSLayer(layerPath *uint16, handle windows.Handle, options *uint16) (hr error) {
if hr = procHcsSetupBaseOSLayer.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsSetupBaseOSLayer.Addr(), 3, uintptr(unsafe.Pointer(layerPath)), uintptr(handle), uintptr(unsafe.Pointer(options)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsInitializeWritableLayer(writableLayerPath string, layerData string, options string) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(writableLayerPath)
if hr != nil {
return
}
var _p1 *uint16
_p1, hr = syscall.UTF16PtrFromString(layerData)
if hr != nil {
return
}
var _p2 *uint16
_p2, hr = syscall.UTF16PtrFromString(options)
if hr != nil {
return
}
return _hcsInitializeWritableLayer(_p0, _p1, _p2)
}
func _hcsInitializeWritableLayer(writableLayerPath *uint16, layerData *uint16, options *uint16) (hr error) {
if hr = procHcsInitializeWritableLayer.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsInitializeWritableLayer.Addr(), 3, uintptr(unsafe.Pointer(writableLayerPath)), uintptr(unsafe.Pointer(layerData)), uintptr(unsafe.Pointer(options)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsAttachLayerStorageFilter(layerPath string, layerData string) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(layerPath)
if hr != nil {
return
}
var _p1 *uint16
_p1, hr = syscall.UTF16PtrFromString(layerData)
if hr != nil {
return
}
return _hcsAttachLayerStorageFilter(_p0, _p1)
}
func _hcsAttachLayerStorageFilter(layerPath *uint16, layerData *uint16) (hr error) {
if hr = procHcsAttachLayerStorageFilter.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsAttachLayerStorageFilter.Addr(), 2, uintptr(unsafe.Pointer(layerPath)), uintptr(unsafe.Pointer(layerData)), 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsDetachLayerStorageFilter(layerPath string) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(layerPath)
if hr != nil {
return
}
return _hcsDetachLayerStorageFilter(_p0)
}
func _hcsDetachLayerStorageFilter(layerPath *uint16) (hr error) {
if hr = procHcsDetachLayerStorageFilter.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsDetachLayerStorageFilter.Addr(), 1, uintptr(unsafe.Pointer(layerPath)), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsFormatWritableLayerVhd(handle windows.Handle) (hr error) {
if hr = procHcsFormatWritableLayerVhd.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsFormatWritableLayerVhd.Addr(), 1, uintptr(handle), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsGetLayerVhdMountPath(vhdHandle windows.Handle, mountPath **uint16) (hr error) {
if hr = procHcsGetLayerVhdMountPath.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsGetLayerVhdMountPath.Addr(), 2, uintptr(vhdHandle), uintptr(unsafe.Pointer(mountPath)), 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsSetupBaseOSVolume(layerPath string, volumePath string, options string) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(layerPath)
if hr != nil {
return
}
var _p1 *uint16
_p1, hr = syscall.UTF16PtrFromString(volumePath)
if hr != nil {
return
}
var _p2 *uint16
_p2, hr = syscall.UTF16PtrFromString(options)
if hr != nil {
return
}
return _hcsSetupBaseOSVolume(_p0, _p1, _p2)
}
func _hcsSetupBaseOSVolume(layerPath *uint16, volumePath *uint16, options *uint16) (hr error) {
if hr = procHcsSetupBaseOSVolume.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsSetupBaseOSVolume.Addr(), 3, uintptr(unsafe.Pointer(layerPath)), uintptr(unsafe.Pointer(volumePath)), uintptr(unsafe.Pointer(options)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}

View file

@ -83,7 +83,6 @@ type NetworkNotFoundError = hns.NetworkNotFoundError
type ProcessError struct { type ProcessError struct {
Process *process Process *process
Operation string Operation string
ExtraInfo string
Err error Err error
Events []hcs.ErrorEvent Events []hcs.ErrorEvent
} }
@ -92,7 +91,6 @@ type ProcessError struct {
type ContainerError struct { type ContainerError struct {
Container *container Container *container
Operation string Operation string
ExtraInfo string
Err error Err error
Events []hcs.ErrorEvent Events []hcs.ErrorEvent
} }
@ -125,22 +123,9 @@ func (e *ContainerError) Error() string {
s += "\n" + ev.String() s += "\n" + ev.String()
} }
if e.ExtraInfo != "" {
s += " extra info: " + e.ExtraInfo
}
return s return s
} }
func makeContainerError(container *container, operation string, extraInfo string, err error) error {
// Don't double wrap errors
if _, ok := err.(*ContainerError); ok {
return err
}
containerError := &ContainerError{Container: container, Operation: operation, ExtraInfo: extraInfo, Err: err}
return containerError
}
func (e *ProcessError) Error() string { func (e *ProcessError) Error() string {
if e == nil { if e == nil {
return "<nil>" return "<nil>"
@ -171,15 +156,6 @@ func (e *ProcessError) Error() string {
return s return s
} }
func makeProcessError(process *process, operation string, extraInfo string, err error) error {
// Don't double wrap errors
if _, ok := err.(*ProcessError); ok {
return err
}
processError := &ProcessError{Process: process, Operation: operation, ExtraInfo: extraInfo, Err: err}
return processError
}
// IsNotExist checks if an error is caused by the Container or Process not existing. // IsNotExist checks if an error is caused by the Container or Process not existing.
// Note: Currently, ErrElementNotFound can mean that a Process has either // Note: Currently, ErrElementNotFound can mean that a Process has either
// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist // already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
@ -230,6 +206,18 @@ func IsNotSupported(err error) bool {
return hcs.IsNotSupported(getInnerError(err)) return hcs.IsNotSupported(getInnerError(err))
} }
// IsOperationInvalidState returns true when err is caused by
// `ErrVmcomputeOperationInvalidState`.
func IsOperationInvalidState(err error) bool {
return hcs.IsOperationInvalidState(getInnerError(err))
}
// IsAccessIsDenied returns true when err is caused by
// `ErrVmcomputeOperationAccessIsDenied`.
func IsAccessIsDenied(err error) bool {
return hcs.IsAccessIsDenied(getInnerError(err))
}
func getInnerError(err error) error { func getInnerError(err error) error {
switch pe := err.(type) { switch pe := err.(type) {
case nil: case nil:
@ -244,7 +232,7 @@ func getInnerError(err error) error {
func convertSystemError(err error, c *container) error { func convertSystemError(err error, c *container) error {
if serr, ok := err.(*hcs.SystemError); ok { if serr, ok := err.(*hcs.SystemError); ok {
return &ContainerError{Container: c, Operation: serr.Op, ExtraInfo: serr.Extra, Err: serr.Err, Events: serr.Events} return &ContainerError{Container: c, Operation: serr.Op, Err: serr.Err, Events: serr.Events}
} }
return err return err
} }

View file

@ -514,6 +514,45 @@ func (w *Writer) lookup(name string, mustExist bool) (*inode, *inode, string, er
return dir, child, childname, nil return dir, child, childname, nil
} }
// CreateWithParents adds a file to the file system creating the parent directories in the path if
// they don't exist (like `mkdir -p`). These non existing parent directories are created
// with the same permissions as that of it's parent directory. It is expected that the a
// call to make these parent directories will be made at a later point with the correct
// permissions, at that time the permissions of these directories will be updated.
func (w *Writer) CreateWithParents(name string, f *File) error {
// go through the directories in the path one by one and create the
// parent directories if they don't exist.
cleanname := path.Clean("/" + name)[1:]
parentDirs, _ := path.Split(cleanname)
currentPath := ""
root := w.root()
dirname := ""
for parentDirs != "" {
dirname, parentDirs = splitFirst(parentDirs)
currentPath += "/" + dirname
if _, ok := root.Children[dirname]; !ok {
f := &File{
Mode: root.Mode,
Atime: time.Now(),
Mtime: time.Now(),
Ctime: time.Now(),
Crtime: time.Now(),
Size: 0,
Uid: root.Uid,
Gid: root.Gid,
Devmajor: root.Devmajor,
Devminor: root.Devminor,
Xattrs: make(map[string][]byte),
}
if err := w.Create(currentPath, f); err != nil {
return fmt.Errorf("failed while creating parent directories: %w", err)
}
}
root = root.Children[dirname]
}
return w.Create(name, f)
}
// Create adds a file to the file system. // Create adds a file to the file system.
func (w *Writer) Create(name string, f *File) error { func (w *Writer) Create(name string, f *File) error {
if err := w.finishInode(); err != nil { if err := w.finishInode(); err != nil {
@ -693,7 +732,7 @@ func (w *Writer) seekBlock(block uint32) {
func (w *Writer) nextBlock() { func (w *Writer) nextBlock() {
if w.pos%blockSize != 0 { if w.pos%blockSize != 0 {
// Simplify callers; w.err is updated on failure. // Simplify callers; w.err is updated on failure.
w.zero(blockSize - w.pos%blockSize) _, _ = w.zero(blockSize - w.pos%blockSize)
} }
} }
@ -743,7 +782,7 @@ func (w *Writer) writeExtents(inode *inode) error {
extents [4]format.ExtentLeafNode extents [4]format.ExtentLeafNode
} }
fillExtents(&root.hdr, root.extents[:extents], startBlock, 0, blocks) fillExtents(&root.hdr, root.extents[:extents], startBlock, 0, blocks)
binary.Write(&b, binary.LittleEndian, root) _ = binary.Write(&b, binary.LittleEndian, root)
} else if extents <= 4*extentsPerBlock { } else if extents <= 4*extentsPerBlock {
const extentsPerBlock = blockSize/extentNodeSize - 1 const extentsPerBlock = blockSize/extentNodeSize - 1
extentBlocks := extents/extentsPerBlock + 1 extentBlocks := extents/extentsPerBlock + 1
@ -778,12 +817,12 @@ func (w *Writer) writeExtents(inode *inode) error {
offset := i * extentsPerBlock * maxBlocksPerExtent offset := i * extentsPerBlock * maxBlocksPerExtent
fillExtents(&node.hdr, node.extents[:extentsInBlock], startBlock+offset, offset, blocks) fillExtents(&node.hdr, node.extents[:extentsInBlock], startBlock+offset, offset, blocks)
binary.Write(&b2, binary.LittleEndian, node) _ = binary.Write(&b2, binary.LittleEndian, node)
if _, err := w.write(b2.Next(blockSize)); err != nil { if _, err := w.write(b2.Next(blockSize)); err != nil {
return err return err
} }
} }
binary.Write(&b, binary.LittleEndian, root) _ = binary.Write(&b, binary.LittleEndian, root)
} else { } else {
panic("file too big") panic("file too big")
} }
@ -924,7 +963,13 @@ func (w *Writer) writeDirectory(dir, parent *inode) error {
children = append(children, name) children = append(children, name)
} }
sort.Slice(children, func(i, j int) bool { sort.Slice(children, func(i, j int) bool {
return dir.Children[children[i]].Number < dir.Children[children[j]].Number left_num := dir.Children[children[i]].Number
right_num := dir.Children[children[j]].Number
if left_num == right_num {
return children[i] < children[j]
}
return left_num < right_num
}) })
for _, name := range children { for _, name := range children {
@ -945,7 +990,24 @@ func (w *Writer) writeDirectoryRecursive(dir, parent *inode) error {
if err := w.writeDirectory(dir, parent); err != nil { if err := w.writeDirectory(dir, parent); err != nil {
return err return err
} }
for _, child := range dir.Children {
// Follow e2fsck's convention and sort the children by inode number.
var children []string
for name := range dir.Children {
children = append(children, name)
}
sort.Slice(children, func(i, j int) bool {
left_num := dir.Children[children[i]].Number
right_num := dir.Children[children[j]].Number
if left_num == right_num {
return children[i] < children[j]
}
return left_num < right_num
})
for _, name := range children {
child := dir.Children[name]
if child.IsDir() { if child.IsDir() {
if err := w.writeDirectoryRecursive(child, dir); err != nil { if err := w.writeDirectoryRecursive(child, dir); err != nil {
return err return err
@ -998,12 +1060,12 @@ func (w *Writer) writeInodeTable(tableSize uint32) error {
binary.LittleEndian.PutUint32(binode.Block[4:], dev) binary.LittleEndian.PutUint32(binode.Block[4:], dev)
} }
binary.Write(&b, binary.LittleEndian, binode) _ = binary.Write(&b, binary.LittleEndian, binode)
b.Truncate(inodeUsedSize) b.Truncate(inodeUsedSize)
n, _ := b.Write(inode.XattrInline) n, _ := b.Write(inode.XattrInline)
io.CopyN(&b, zero, int64(inodeExtraSize-n)) _, _ = io.CopyN(&b, zero, int64(inodeExtraSize-n))
} else { } else {
io.CopyN(&b, zero, inodeSize) _, _ = io.CopyN(&b, zero, inodeSize)
} }
if _, err := w.write(b.Next(inodeSize)); err != nil { if _, err := w.write(b.Next(inodeSize)); err != nil {
return err return err
@ -1136,7 +1198,7 @@ func (w *Writer) Close() error {
diskSize = minSize diskSize = minSize
} }
usedGdBlocks := (groups-1)/groupDescriptorSize + 1 usedGdBlocks := (groups-1)/groupsPerDescriptorBlock + 1
if usedGdBlocks > w.gdBlocks { if usedGdBlocks > w.gdBlocks {
return exceededMaxSizeError{w.maxDiskSize} return exceededMaxSizeError{w.maxDiskSize}
} }
@ -1253,7 +1315,7 @@ func (w *Writer) Close() error {
if w.supportInlineData { if w.supportInlineData {
sb.FeatureIncompat |= format.IncompatInlineData sb.FeatureIncompat |= format.IncompatInlineData
} }
binary.Write(b, binary.LittleEndian, sb) _ = binary.Write(b, binary.LittleEndian, sb)
w.seekBlock(0) w.seekBlock(0)
if _, err := w.write(blk[:]); err != nil { if _, err := w.write(blk[:]); err != nil {
return err return err

View file

@ -5,10 +5,12 @@ import (
"bufio" "bufio"
"encoding/binary" "encoding/binary"
"io" "io"
"os"
"path" "path"
"strings" "strings"
"github.com/Microsoft/hcsshim/ext4/internal/compactext4" "github.com/Microsoft/hcsshim/ext4/internal/compactext4"
"github.com/Microsoft/hcsshim/ext4/internal/format"
) )
type params struct { type params struct {
@ -146,7 +148,7 @@ func Convert(r io.Reader, w io.ReadWriteSeeker, options ...Option) error {
} }
f.Mode &= ^compactext4.TypeMask f.Mode &= ^compactext4.TypeMask
f.Mode |= typ f.Mode |= typ
err = fs.Create(hdr.Name, f) err = fs.CreateWithParents(hdr.Name, f)
if err != nil { if err != nil {
return err return err
} }
@ -172,3 +174,36 @@ func Convert(r io.Reader, w io.ReadWriteSeeker, options ...Option) error {
} }
return nil return nil
} }
// ReadExt4SuperBlock reads and returns ext4 super block from VHD
//
// The layout on disk is as follows:
// | Group 0 padding | - 1024 bytes
// | ext4 SuperBlock | - 1 block
// | Group Descriptors | - many blocks
// | Reserved GDT Blocks | - many blocks
// | Data Block Bitmap | - 1 block
// | inode Bitmap | - 1 block
// | inode Table | - many blocks
// | Data Blocks | - many blocks
//
// More details can be found here https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout
//
// Our goal is to skip the Group 0 padding, read and return the ext4 SuperBlock
func ReadExt4SuperBlock(vhdPath string) (*format.SuperBlock, error) {
vhd, err := os.OpenFile(vhdPath, os.O_RDONLY, 0)
if err != nil {
return nil, err
}
defer vhd.Close()
// Skip padding at the start
if _, err := vhd.Seek(1024, io.SeekStart); err != nil {
return nil, err
}
var sb format.SuperBlock
if err := binary.Read(vhd, binary.LittleEndian, &sb); err != nil {
return nil, err
}
return &sb, nil
}

View file

@ -56,7 +56,7 @@ func calculateCheckSum(footer *vhdFooter) uint32 {
footer.Checksum = 0 footer.Checksum = 0
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
binary.Write(buf, binary.BigEndian, footer) _ = binary.Write(buf, binary.BigEndian, footer)
var chk uint32 var chk uint32
bufBytes := buf.Bytes() bufBytes := buf.Bytes()

View file

@ -3,33 +3,20 @@ module github.com/Microsoft/hcsshim
go 1.13 go 1.13
require ( require (
github.com/Microsoft/go-winio v0.4.15-0.20200908182639-5b44b70ab3ab github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1 github.com/containerd/console v1.0.1
github.com/containerd/containerd v1.3.2 github.com/containerd/containerd v1.5.0-beta.4
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc // indirect github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 // indirect github.com/containerd/ttrpc v1.0.2
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3 github.com/containerd/typeurl v1.0.1
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de github.com/gogo/protobuf v1.3.2
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d
github.com/gogo/protobuf v1.3.1
github.com/golang/protobuf v1.3.2 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2 // indirect
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f // indirect
github.com/opencontainers/runtime-spec v1.0.2
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7 // indirect github.com/sirupsen/logrus v1.7.0
github.com/sirupsen/logrus v1.4.2
github.com/stretchr/testify v1.4.0 // indirect
github.com/urfave/cli v1.22.2 github.com/urfave/cli v1.22.2
go.opencensus.io v0.22.0 go.opencensus.io v0.22.3
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 // indirect golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
golang.org/x/sync v0.0.0-20190423024810-112230192c58 golang.org/x/sys v0.0.0-20210324051608-47abb6519492
golang.org/x/sys v0.0.0-20200120151820-655fe14d7479 google.golang.org/grpc v1.33.2
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 // indirect
google.golang.org/grpc v1.23.1
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/yaml.v2 v2.2.8 // indirect
gotest.tools v2.2.0+incompatible // indirect
) )

View file

@ -40,6 +40,9 @@ func HNSListEndpointRequest() ([]HNSEndpoint, error) {
// HotAttachEndpoint makes a HCS Call to attach the endpoint to the container // HotAttachEndpoint makes a HCS Call to attach the endpoint to the container
func HotAttachEndpoint(containerID string, endpointID string) error { func HotAttachEndpoint(containerID string, endpointID string) error {
endpoint, err := GetHNSEndpointByID(endpointID) endpoint, err := GetHNSEndpointByID(endpointID)
if err != nil {
return err
}
isAttached, err := endpoint.IsAttached(containerID) isAttached, err := endpoint.IsAttached(containerID)
if isAttached { if isAttached {
return err return err
@ -50,6 +53,9 @@ func HotAttachEndpoint(containerID string, endpointID string) error {
// HotDetachEndpoint makes a HCS Call to detach the endpoint from the container // HotDetachEndpoint makes a HCS Call to detach the endpoint from the container
func HotDetachEndpoint(containerID string, endpointID string) error { func HotDetachEndpoint(containerID string, endpointID string) error {
endpoint, err := GetHNSEndpointByID(endpointID) endpoint, err := GetHNSEndpointByID(endpointID)
if err != nil {
return err
}
isAttached, err := endpoint.IsAttached(containerID) isAttached, err := endpoint.IsAttached(containerID)
if !isAttached { if !isAttached {
return err return err

View file

@ -80,4 +80,6 @@ type Container interface {
// container to be terminated by some error condition (including calling // container to be terminated by some error condition (including calling
// Close). // Close).
Wait() error Wait() error
// Modify sends a request to modify container resources
Modify(ctx context.Context, config interface{}) error
} }

View file

@ -106,6 +106,7 @@ func newSystemChannels() notificationChannels {
hcsNotificationSystemStartCompleted, hcsNotificationSystemStartCompleted,
hcsNotificationSystemPauseCompleted, hcsNotificationSystemPauseCompleted,
hcsNotificationSystemResumeCompleted, hcsNotificationSystemResumeCompleted,
hcsNotificationSystemSaveCompleted,
} { } {
channels[notif] = make(notificationChannel, 1) channels[notif] = make(notificationChannel, 1)
} }

View file

@ -171,7 +171,6 @@ type SystemError struct {
ID string ID string
Op string Op string
Err error Err error
Extra string
Events []ErrorEvent Events []ErrorEvent
} }
@ -182,9 +181,6 @@ func (e *SystemError) Error() string {
for _, ev := range e.Events { for _, ev := range e.Events {
s += "\n" + ev.String() s += "\n" + ev.String()
} }
if e.Extra != "" {
s += "\n(extra info: " + e.Extra + ")"
}
return s return s
} }
@ -198,7 +194,7 @@ func (e *SystemError) Timeout() bool {
return ok && err.Timeout() return ok && err.Timeout()
} }
func makeSystemError(system *System, op string, extra string, err error, events []ErrorEvent) error { func makeSystemError(system *System, op string, err error, events []ErrorEvent) error {
// Don't double wrap errors // Don't double wrap errors
if _, ok := err.(*SystemError); ok { if _, ok := err.(*SystemError); ok {
return err return err
@ -206,7 +202,6 @@ func makeSystemError(system *System, op string, extra string, err error, events
return &SystemError{ return &SystemError{
ID: system.ID(), ID: system.ID(),
Op: op, Op: op,
Extra: extra,
Err: err, Err: err,
Events: events, Events: events,
} }
@ -312,6 +307,13 @@ func IsOperationInvalidState(err error) bool {
return err == ErrVmcomputeOperationInvalidState return err == ErrVmcomputeOperationInvalidState
} }
// IsAccessIsDenied returns true when err is caused by
// `ErrVmcomputeOperationAccessIsDenied`.
func IsAccessIsDenied(err error) bool {
err = getInnerError(err)
return err == ErrVmcomputeOperationAccessIsDenied
}
func getInnerError(err error) error { func getInnerError(err error) error {
switch pe := err.(type) { switch pe := err.(type) {
case nil: case nil:
@ -325,12 +327,3 @@ func getInnerError(err error) error {
} }
return err return err
} }
func getOperationLogResult(err error) (string, error) {
switch err {
case nil:
return "Success", nil
default:
return "Error", err
}
}

View file

@ -64,11 +64,7 @@ type processStatus struct {
LastWaitResult int32 LastWaitResult int32
} }
const ( const stdIn string = "StdIn"
stdIn string = "StdIn"
stdOut string = "StdOut"
stdErr string = "StdErr"
)
const ( const (
modifyConsoleSize string = "ConsoleSize" modifyConsoleSize string = "ConsoleSize"
@ -176,8 +172,10 @@ func (process *Process) waitBackground() {
trace.Int64Attribute("pid", int64(process.processID))) trace.Int64Attribute("pid", int64(process.processID)))
var ( var (
err error err error
exitCode = -1 exitCode = -1
propertiesJSON string
resultJSON string
) )
err = waitForNotification(ctx, process.callbackNumber, hcsNotificationProcessExited, nil) err = waitForNotification(ctx, process.callbackNumber, hcsNotificationProcessExited, nil)
@ -190,15 +188,15 @@ func (process *Process) waitBackground() {
// Make sure we didnt race with Close() here // Make sure we didnt race with Close() here
if process.handle != 0 { if process.handle != 0 {
propertiesJSON, resultJSON, err := vmcompute.HcsGetProcessProperties(ctx, process.handle) propertiesJSON, resultJSON, err = vmcompute.HcsGetProcessProperties(ctx, process.handle)
events := processHcsResult(ctx, resultJSON) events := processHcsResult(ctx, resultJSON)
if err != nil { if err != nil {
err = makeProcessError(process, operation, err, events) err = makeProcessError(process, operation, err, events) //nolint:ineffassign
} else { } else {
properties := &processStatus{} properties := &processStatus{}
err = json.Unmarshal([]byte(propertiesJSON), properties) err = json.Unmarshal([]byte(propertiesJSON), properties)
if err != nil { if err != nil {
err = makeProcessError(process, operation, err, nil) err = makeProcessError(process, operation, err, nil) //nolint:ineffassign
} else { } else {
if properties.LastWaitResult != 0 { if properties.LastWaitResult != 0 {
log.G(ctx).WithField("wait-result", properties.LastWaitResult).Warning("non-zero last wait result") log.G(ctx).WithField("wait-result", properties.LastWaitResult).Warning("non-zero last wait result")
@ -468,7 +466,7 @@ func (process *Process) unregisterCallback(ctx context.Context) error {
delete(callbackMap, callbackNumber) delete(callbackMap, callbackNumber)
callbackMapLock.Unlock() callbackMapLock.Unlock()
handle = 0 handle = 0 //nolint:ineffassign
return nil return nil
} }

View file

@ -1,5 +0,0 @@
package hcs
//go:generate go run ../../mksyscall_windows.go -output zsyscall_windows.go syscall.go
//sys hcsFormatWritableLayerVhd(handle uintptr) (hr error) = computestorage.HcsFormatWritableLayerVhd

View file

@ -73,8 +73,8 @@ func CreateComputeSystem(ctx context.Context, id string, hcsDocumentInterface in
if err = computeSystem.registerCallback(ctx); err != nil { if err = computeSystem.registerCallback(ctx); err != nil {
// Terminate the compute system if it still exists. We're okay to // Terminate the compute system if it still exists. We're okay to
// ignore a failure here. // ignore a failure here.
computeSystem.Terminate(ctx) _ = computeSystem.Terminate(ctx)
return nil, makeSystemError(computeSystem, operation, "", err, nil) return nil, makeSystemError(computeSystem, operation, err, nil)
} }
} }
@ -83,9 +83,9 @@ func CreateComputeSystem(ctx context.Context, id string, hcsDocumentInterface in
if err == ErrTimeout { if err == ErrTimeout {
// Terminate the compute system if it still exists. We're okay to // Terminate the compute system if it still exists. We're okay to
// ignore a failure here. // ignore a failure here.
computeSystem.Terminate(ctx) _ = computeSystem.Terminate(ctx)
} }
return nil, makeSystemError(computeSystem, operation, hcsDocument, err, events) return nil, makeSystemError(computeSystem, operation, err, events)
} }
go computeSystem.waitBackground() go computeSystem.waitBackground()
if err = computeSystem.getCachedProperties(ctx); err != nil { if err = computeSystem.getCachedProperties(ctx); err != nil {
@ -102,7 +102,7 @@ func OpenComputeSystem(ctx context.Context, id string) (*System, error) {
handle, resultJSON, err := vmcompute.HcsOpenComputeSystem(ctx, id) handle, resultJSON, err := vmcompute.HcsOpenComputeSystem(ctx, id)
events := processHcsResult(ctx, resultJSON) events := processHcsResult(ctx, resultJSON)
if err != nil { if err != nil {
return nil, makeSystemError(computeSystem, operation, "", err, events) return nil, makeSystemError(computeSystem, operation, err, events)
} }
computeSystem.handle = handle computeSystem.handle = handle
defer func() { defer func() {
@ -111,7 +111,7 @@ func OpenComputeSystem(ctx context.Context, id string) (*System, error) {
} }
}() }()
if err = computeSystem.registerCallback(ctx); err != nil { if err = computeSystem.registerCallback(ctx); err != nil {
return nil, makeSystemError(computeSystem, operation, "", err, nil) return nil, makeSystemError(computeSystem, operation, err, nil)
} }
go computeSystem.waitBackground() go computeSystem.waitBackground()
if err = computeSystem.getCachedProperties(ctx); err != nil { if err = computeSystem.getCachedProperties(ctx); err != nil {
@ -187,13 +187,13 @@ func (computeSystem *System) Start(ctx context.Context) (err error) {
defer computeSystem.handleLock.RUnlock() defer computeSystem.handleLock.RUnlock()
if computeSystem.handle == 0 { if computeSystem.handle == 0 {
return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) return makeSystemError(computeSystem, operation, ErrAlreadyClosed, nil)
} }
resultJSON, err := vmcompute.HcsStartComputeSystem(ctx, computeSystem.handle, "") resultJSON, err := vmcompute.HcsStartComputeSystem(ctx, computeSystem.handle, "")
events, err := processAsyncHcsResult(ctx, err, resultJSON, computeSystem.callbackNumber, hcsNotificationSystemStartCompleted, &timeout.SystemStart) events, err := processAsyncHcsResult(ctx, err, resultJSON, computeSystem.callbackNumber, hcsNotificationSystemStartCompleted, &timeout.SystemStart)
if err != nil { if err != nil {
return makeSystemError(computeSystem, operation, "", err, events) return makeSystemError(computeSystem, operation, err, events)
} }
return nil return nil
@ -220,7 +220,7 @@ func (computeSystem *System) Shutdown(ctx context.Context) error {
switch err { switch err {
case nil, ErrVmcomputeAlreadyStopped, ErrComputeSystemDoesNotExist, ErrVmcomputeOperationPending: case nil, ErrVmcomputeAlreadyStopped, ErrComputeSystemDoesNotExist, ErrVmcomputeOperationPending:
default: default:
return makeSystemError(computeSystem, operation, "", err, events) return makeSystemError(computeSystem, operation, err, events)
} }
return nil return nil
} }
@ -241,7 +241,7 @@ func (computeSystem *System) Terminate(ctx context.Context) error {
switch err { switch err {
case nil, ErrVmcomputeAlreadyStopped, ErrComputeSystemDoesNotExist, ErrVmcomputeOperationPending: case nil, ErrVmcomputeAlreadyStopped, ErrComputeSystemDoesNotExist, ErrVmcomputeOperationPending:
default: default:
return makeSystemError(computeSystem, operation, "", err, events) return makeSystemError(computeSystem, operation, err, events)
} }
return nil return nil
} }
@ -263,10 +263,10 @@ func (computeSystem *System) waitBackground() {
log.G(ctx).Debug("system exited") log.G(ctx).Debug("system exited")
case ErrVmcomputeUnexpectedExit: case ErrVmcomputeUnexpectedExit:
log.G(ctx).Debug("unexpected system exit") log.G(ctx).Debug("unexpected system exit")
computeSystem.exitError = makeSystemError(computeSystem, operation, "", err, nil) computeSystem.exitError = makeSystemError(computeSystem, operation, err, nil)
err = nil err = nil
default: default:
err = makeSystemError(computeSystem, operation, "", err, nil) err = makeSystemError(computeSystem, operation, err, nil)
} }
computeSystem.closedWaitOnce.Do(func() { computeSystem.closedWaitOnce.Do(func() {
computeSystem.waitError = err computeSystem.waitError = err
@ -304,13 +304,13 @@ func (computeSystem *System) Properties(ctx context.Context, types ...schema1.Pr
queryBytes, err := json.Marshal(schema1.PropertyQuery{PropertyTypes: types}) queryBytes, err := json.Marshal(schema1.PropertyQuery{PropertyTypes: types})
if err != nil { if err != nil {
return nil, makeSystemError(computeSystem, operation, "", err, nil) return nil, makeSystemError(computeSystem, operation, err, nil)
} }
propertiesJSON, resultJSON, err := vmcompute.HcsGetComputeSystemProperties(ctx, computeSystem.handle, string(queryBytes)) propertiesJSON, resultJSON, err := vmcompute.HcsGetComputeSystemProperties(ctx, computeSystem.handle, string(queryBytes))
events := processHcsResult(ctx, resultJSON) events := processHcsResult(ctx, resultJSON)
if err != nil { if err != nil {
return nil, makeSystemError(computeSystem, operation, "", err, events) return nil, makeSystemError(computeSystem, operation, err, events)
} }
if propertiesJSON == "" { if propertiesJSON == "" {
@ -318,7 +318,7 @@ func (computeSystem *System) Properties(ctx context.Context, types ...schema1.Pr
} }
properties := &schema1.ContainerProperties{} properties := &schema1.ContainerProperties{}
if err := json.Unmarshal([]byte(propertiesJSON), properties); err != nil { if err := json.Unmarshal([]byte(propertiesJSON), properties); err != nil {
return nil, makeSystemError(computeSystem, operation, "", err, nil) return nil, makeSystemError(computeSystem, operation, err, nil)
} }
return properties, nil return properties, nil
@ -333,13 +333,13 @@ func (computeSystem *System) PropertiesV2(ctx context.Context, types ...hcsschem
queryBytes, err := json.Marshal(hcsschema.PropertyQuery{PropertyTypes: types}) queryBytes, err := json.Marshal(hcsschema.PropertyQuery{PropertyTypes: types})
if err != nil { if err != nil {
return nil, makeSystemError(computeSystem, operation, "", err, nil) return nil, makeSystemError(computeSystem, operation, err, nil)
} }
propertiesJSON, resultJSON, err := vmcompute.HcsGetComputeSystemProperties(ctx, computeSystem.handle, string(queryBytes)) propertiesJSON, resultJSON, err := vmcompute.HcsGetComputeSystemProperties(ctx, computeSystem.handle, string(queryBytes))
events := processHcsResult(ctx, resultJSON) events := processHcsResult(ctx, resultJSON)
if err != nil { if err != nil {
return nil, makeSystemError(computeSystem, operation, "", err, events) return nil, makeSystemError(computeSystem, operation, err, events)
} }
if propertiesJSON == "" { if propertiesJSON == "" {
@ -347,7 +347,7 @@ func (computeSystem *System) PropertiesV2(ctx context.Context, types ...hcsschem
} }
properties := &hcsschema.Properties{} properties := &hcsschema.Properties{}
if err := json.Unmarshal([]byte(propertiesJSON), properties); err != nil { if err := json.Unmarshal([]byte(propertiesJSON), properties); err != nil {
return nil, makeSystemError(computeSystem, operation, "", err, nil) return nil, makeSystemError(computeSystem, operation, err, nil)
} }
return properties, nil return properties, nil
@ -368,13 +368,13 @@ func (computeSystem *System) Pause(ctx context.Context) (err error) {
defer computeSystem.handleLock.RUnlock() defer computeSystem.handleLock.RUnlock()
if computeSystem.handle == 0 { if computeSystem.handle == 0 {
return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) return makeSystemError(computeSystem, operation, ErrAlreadyClosed, nil)
} }
resultJSON, err := vmcompute.HcsPauseComputeSystem(ctx, computeSystem.handle, "") resultJSON, err := vmcompute.HcsPauseComputeSystem(ctx, computeSystem.handle, "")
events, err := processAsyncHcsResult(ctx, err, resultJSON, computeSystem.callbackNumber, hcsNotificationSystemPauseCompleted, &timeout.SystemPause) events, err := processAsyncHcsResult(ctx, err, resultJSON, computeSystem.callbackNumber, hcsNotificationSystemPauseCompleted, &timeout.SystemPause)
if err != nil { if err != nil {
return makeSystemError(computeSystem, operation, "", err, events) return makeSystemError(computeSystem, operation, err, events)
} }
return nil return nil
@ -395,13 +395,45 @@ func (computeSystem *System) Resume(ctx context.Context) (err error) {
defer computeSystem.handleLock.RUnlock() defer computeSystem.handleLock.RUnlock()
if computeSystem.handle == 0 { if computeSystem.handle == 0 {
return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) return makeSystemError(computeSystem, operation, ErrAlreadyClosed, nil)
} }
resultJSON, err := vmcompute.HcsResumeComputeSystem(ctx, computeSystem.handle, "") resultJSON, err := vmcompute.HcsResumeComputeSystem(ctx, computeSystem.handle, "")
events, err := processAsyncHcsResult(ctx, err, resultJSON, computeSystem.callbackNumber, hcsNotificationSystemResumeCompleted, &timeout.SystemResume) events, err := processAsyncHcsResult(ctx, err, resultJSON, computeSystem.callbackNumber, hcsNotificationSystemResumeCompleted, &timeout.SystemResume)
if err != nil { if err != nil {
return makeSystemError(computeSystem, operation, "", err, events) return makeSystemError(computeSystem, operation, err, events)
}
return nil
}
// Save the compute system
func (computeSystem *System) Save(ctx context.Context, options interface{}) (err error) {
operation := "hcsshim::System::Save"
// hcsSaveComputeSystemContext is an async peration. Start the outer span
// here to measure the full save time.
ctx, span := trace.StartSpan(ctx, operation)
defer span.End()
defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("cid", computeSystem.id))
saveOptions, err := json.Marshal(options)
if err != nil {
return err
}
computeSystem.handleLock.RLock()
defer computeSystem.handleLock.RUnlock()
if computeSystem.handle == 0 {
return makeSystemError(computeSystem, operation, ErrAlreadyClosed, nil)
}
result, err := vmcompute.HcsSaveComputeSystem(ctx, computeSystem.handle, string(saveOptions))
events, err := processAsyncHcsResult(ctx, err, result, computeSystem.callbackNumber, hcsNotificationSystemSaveCompleted, &timeout.SystemSave)
if err != nil {
return makeSystemError(computeSystem, operation, err, events)
} }
return nil return nil
@ -412,19 +444,19 @@ func (computeSystem *System) createProcess(ctx context.Context, operation string
defer computeSystem.handleLock.RUnlock() defer computeSystem.handleLock.RUnlock()
if computeSystem.handle == 0 { if computeSystem.handle == 0 {
return nil, nil, makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) return nil, nil, makeSystemError(computeSystem, operation, ErrAlreadyClosed, nil)
} }
configurationb, err := json.Marshal(c) configurationb, err := json.Marshal(c)
if err != nil { if err != nil {
return nil, nil, makeSystemError(computeSystem, operation, "", err, nil) return nil, nil, makeSystemError(computeSystem, operation, err, nil)
} }
configuration := string(configurationb) configuration := string(configurationb)
processInfo, processHandle, resultJSON, err := vmcompute.HcsCreateProcess(ctx, computeSystem.handle, configuration) processInfo, processHandle, resultJSON, err := vmcompute.HcsCreateProcess(ctx, computeSystem.handle, configuration)
events := processHcsResult(ctx, resultJSON) events := processHcsResult(ctx, resultJSON)
if err != nil { if err != nil {
return nil, nil, makeSystemError(computeSystem, operation, configuration, err, events) return nil, nil, makeSystemError(computeSystem, operation, err, events)
} }
log.G(ctx).WithField("pid", processInfo.ProcessId).Debug("created process pid") log.G(ctx).WithField("pid", processInfo.ProcessId).Debug("created process pid")
@ -446,7 +478,7 @@ func (computeSystem *System) CreateProcess(ctx context.Context, c interface{}) (
pipes, err := makeOpenFiles([]syscall.Handle{processInfo.StdInput, processInfo.StdOutput, processInfo.StdError}) pipes, err := makeOpenFiles([]syscall.Handle{processInfo.StdInput, processInfo.StdOutput, processInfo.StdError})
if err != nil { if err != nil {
return nil, makeSystemError(computeSystem, operation, "", err, nil) return nil, makeSystemError(computeSystem, operation, err, nil)
} }
process.stdin = pipes[0] process.stdin = pipes[0]
process.stdout = pipes[1] process.stdout = pipes[1]
@ -454,7 +486,7 @@ func (computeSystem *System) CreateProcess(ctx context.Context, c interface{}) (
process.hasCachedStdio = true process.hasCachedStdio = true
if err = process.registerCallback(ctx); err != nil { if err = process.registerCallback(ctx); err != nil {
return nil, makeSystemError(computeSystem, operation, "", err, nil) return nil, makeSystemError(computeSystem, operation, err, nil)
} }
go process.waitBackground() go process.waitBackground()
@ -469,18 +501,18 @@ func (computeSystem *System) OpenProcess(ctx context.Context, pid int) (*Process
operation := "hcsshim::System::OpenProcess" operation := "hcsshim::System::OpenProcess"
if computeSystem.handle == 0 { if computeSystem.handle == 0 {
return nil, makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) return nil, makeSystemError(computeSystem, operation, ErrAlreadyClosed, nil)
} }
processHandle, resultJSON, err := vmcompute.HcsOpenProcess(ctx, computeSystem.handle, uint32(pid)) processHandle, resultJSON, err := vmcompute.HcsOpenProcess(ctx, computeSystem.handle, uint32(pid))
events := processHcsResult(ctx, resultJSON) events := processHcsResult(ctx, resultJSON)
if err != nil { if err != nil {
return nil, makeSystemError(computeSystem, operation, "", err, events) return nil, makeSystemError(computeSystem, operation, err, events)
} }
process := newProcess(processHandle, pid, computeSystem) process := newProcess(processHandle, pid, computeSystem)
if err = process.registerCallback(ctx); err != nil { if err = process.registerCallback(ctx); err != nil {
return nil, makeSystemError(computeSystem, operation, "", err, nil) return nil, makeSystemError(computeSystem, operation, err, nil)
} }
go process.waitBackground() go process.waitBackground()
@ -504,12 +536,12 @@ func (computeSystem *System) Close() (err error) {
} }
if err = computeSystem.unregisterCallback(ctx); err != nil { if err = computeSystem.unregisterCallback(ctx); err != nil {
return makeSystemError(computeSystem, operation, "", err, nil) return makeSystemError(computeSystem, operation, err, nil)
} }
err = vmcompute.HcsCloseComputeSystem(ctx, computeSystem.handle) err = vmcompute.HcsCloseComputeSystem(ctx, computeSystem.handle)
if err != nil { if err != nil {
return makeSystemError(computeSystem, operation, "", err, nil) return makeSystemError(computeSystem, operation, err, nil)
} }
computeSystem.handle = 0 computeSystem.handle = 0
@ -573,7 +605,7 @@ func (computeSystem *System) unregisterCallback(ctx context.Context) error {
delete(callbackMap, callbackNumber) delete(callbackMap, callbackNumber)
callbackMapLock.Unlock() callbackMapLock.Unlock()
handle = 0 handle = 0 //nolint:ineffassign
return nil return nil
} }
@ -586,7 +618,7 @@ func (computeSystem *System) Modify(ctx context.Context, config interface{}) err
operation := "hcsshim::System::Modify" operation := "hcsshim::System::Modify"
if computeSystem.handle == 0 { if computeSystem.handle == 0 {
return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) return makeSystemError(computeSystem, operation, ErrAlreadyClosed, nil)
} }
requestBytes, err := json.Marshal(config) requestBytes, err := json.Marshal(config)
@ -598,7 +630,7 @@ func (computeSystem *System) Modify(ctx context.Context, config interface{}) err
resultJSON, err := vmcompute.HcsModifyComputeSystem(ctx, computeSystem.handle, requestJSON) resultJSON, err := vmcompute.HcsModifyComputeSystem(ctx, computeSystem.handle, requestJSON)
events := processHcsResult(ctx, resultJSON) events := processHcsResult(ctx, resultJSON)
if err != nil { if err != nil {
return makeSystemError(computeSystem, operation, requestJSON, err, events) return makeSystemError(computeSystem, operation, err, events)
} }
return nil return nil

View file

@ -7,6 +7,7 @@ import (
"github.com/Microsoft/go-winio" "github.com/Microsoft/go-winio"
diskutil "github.com/Microsoft/go-winio/vhd" diskutil "github.com/Microsoft/go-winio/vhd"
"github.com/Microsoft/hcsshim/computestorage"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
@ -36,7 +37,7 @@ func makeOpenFiles(hs []syscall.Handle) (_ []io.ReadWriteCloser, err error) {
return fs, nil return fs, nil
} }
// creates a VHD formatted with NTFS of size `sizeGB` at the given `vhdPath`. // CreateNTFSVHD creates a VHD formatted with NTFS of size `sizeGB` at the given `vhdPath`.
func CreateNTFSVHD(ctx context.Context, vhdPath string, sizeGB uint32) (err error) { func CreateNTFSVHD(ctx context.Context, vhdPath string, sizeGB uint32) (err error) {
if err := diskutil.CreateVhdx(vhdPath, sizeGB, 1); err != nil { if err := diskutil.CreateVhdx(vhdPath, sizeGB, 1); err != nil {
return errors.Wrap(err, "failed to create VHD") return errors.Wrap(err, "failed to create VHD")
@ -53,7 +54,7 @@ func CreateNTFSVHD(ctx context.Context, vhdPath string, sizeGB uint32) (err erro
} }
}() }()
if err := hcsFormatWritableLayerVhd(uintptr(vhd)); err != nil { if err := computestorage.FormatWritableLayerVhd(ctx, windows.Handle(vhd)); err != nil {
return errors.Wrap(err, "failed to format VHD") return errors.Wrap(err, "failed to format VHD")
} }

View file

@ -65,5 +65,4 @@ func waitForNotification(ctx context.Context, callbackNumber uintptr, expectedNo
case <-c: case <-c:
return ErrTimeout return ErrTimeout
} }
return nil
} }

View file

@ -1,54 +0,0 @@
// Code generated mksyscall_windows.exe DO NOT EDIT
package hcs
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return nil
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modcomputestorage = windows.NewLazySystemDLL("computestorage.dll")
procHcsFormatWritableLayerVhd = modcomputestorage.NewProc("HcsFormatWritableLayerVhd")
)
func hcsFormatWritableLayerVhd(handle uintptr) (hr error) {
r0, _, _ := syscall.Syscall(procHcsFormatWritableLayerVhd.Addr(), 1, uintptr(handle), 0, 0)
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}

View file

@ -39,12 +39,6 @@ type HNSNetwork struct {
AutomaticDNS bool `json:",omitempty"` AutomaticDNS bool `json:",omitempty"`
} }
type hnsNetworkResponse struct {
Success bool
Error string
Output HNSNetwork
}
type hnsResponse struct { type hnsResponse struct {
Success bool Success bool
Error string Error string

View file

@ -27,9 +27,10 @@ type namespaceResourceRequest struct {
} }
type Namespace struct { type Namespace struct {
ID string ID string
IsDefault bool `json:",omitempty"` IsDefault bool `json:",omitempty"`
ResourceList []NamespaceResource `json:",omitempty"` ResourceList []NamespaceResource `json:",omitempty"`
CompartmentId uint32 `json:",omitempty"`
} }
func issueNamespaceRequest(id *string, method, subpath string, request interface{}) (*Namespace, error) { func issueNamespaceRequest(id *string, method, subpath string, request interface{}) (*Namespace, error) {

View file

@ -76,7 +76,7 @@ func openRelativeInternal(path string, root *os.File, accessMask uint32, shareFl
} }
oa.Length = unsafe.Sizeof(oa) oa.Length = unsafe.Sizeof(oa)
oa.ObjectName = uintptr(unsafe.Pointer(pathUnicode)) oa.ObjectName = pathUnicode
oa.RootDirectory = uintptr(root.Fd()) oa.RootDirectory = uintptr(root.Fd())
oa.Attributes = winapi.OBJ_DONT_REPARSE oa.Attributes = winapi.OBJ_DONT_REPARSE
status := winapi.NtCreateFile( status := winapi.NtCreateFile(
@ -177,7 +177,7 @@ func LinkRelative(oldname string, oldroot *os.File, newname string, newroot *os.
linkinfo := (*winapi.FileLinkInformation)(unsafe.Pointer(linkinfoBuffer)) linkinfo := (*winapi.FileLinkInformation)(unsafe.Pointer(linkinfoBuffer))
linkinfo.RootDirectory = parent.Fd() linkinfo.RootDirectory = parent.Fd()
linkinfo.FileNameLength = uint32(len(newbase16) * 2) linkinfo.FileNameLength = uint32(len(newbase16) * 2)
copy((*[32768]uint16)(unsafe.Pointer(&linkinfo.FileName[0]))[:], newbase16) copy(winapi.Uint16BufferToSlice(&linkinfo.FileName[0], len(newbase16)), newbase16)
var iosb winapi.IOStatusBlock var iosb winapi.IOStatusBlock
status := winapi.NtSetInformationFile( status := winapi.NtSetInformationFile(
@ -244,7 +244,7 @@ func RemoveRelative(path string, root *os.File) error {
err = deleteOnClose(f) err = deleteOnClose(f)
if err == syscall.ERROR_ACCESS_DENIED { if err == syscall.ERROR_ACCESS_DENIED {
// Maybe the file is marked readonly. Clear the bit and retry. // Maybe the file is marked readonly. Clear the bit and retry.
clearReadOnly(f) _ = clearReadOnly(f)
err = deleteOnClose(f) err = deleteOnClose(f)
} }
} }

View file

@ -119,9 +119,9 @@ type PropertyType string
const ( const (
PropertyTypeStatistics PropertyType = "Statistics" // V1 and V2 PropertyTypeStatistics PropertyType = "Statistics" // V1 and V2
PropertyTypeProcessList = "ProcessList" // V1 and V2 PropertyTypeProcessList PropertyType = "ProcessList" // V1 and V2
PropertyTypeMappedVirtualDisk = "MappedVirtualDisk" // Not supported in V2 schema call PropertyTypeMappedVirtualDisk PropertyType = "MappedVirtualDisk" // Not supported in V2 schema call
PropertyTypeGuestConnection = "GuestConnection" // V1 and V2. Nil return from HCS before RS5 PropertyTypeGuestConnection PropertyType = "GuestConnection" // V1 and V2. Nil return from HCS before RS5
) )
type PropertyQuery struct { type PropertyQuery struct {
@ -218,6 +218,7 @@ type GuestDefinedCapabilities struct {
SignalProcessSupported bool `json:",omitempty"` SignalProcessSupported bool `json:",omitempty"`
DumpStacksSupported bool `json:",omitempty"` DumpStacksSupported bool `json:",omitempty"`
DeleteContainerStateSupported bool `json:",omitempty"` DeleteContainerStateSupported bool `json:",omitempty"`
UpdateContainerSupported bool `json:",omitempty"`
} }
// GuestConnectionInfo is the structure of an iterm return by a GuestConnection call on a utility VM // GuestConnectionInfo is the structure of an iterm return by a GuestConnection call on a utility VM

View file

@ -0,0 +1,15 @@
/*
* HCS API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
// CPU groups allow Hyper-V administrators to better manage and allocate the host's CPU resources across guest virtual machines
type CpuGroup struct {
Id string `json:"Id,omitempty"`
}

View file

@ -0,0 +1,15 @@
/*
* HCS API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type CpuGroupAffinity struct {
LogicalProcessorCount int32 `json:"LogicalProcessorCount,omitempty"`
LogicalProcessors []int32 `json:"LogicalProcessors,omitempty"`
}

View file

@ -0,0 +1,18 @@
/*
* HCS API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type CpuGroupConfig struct {
GroupId string `json:"GroupId,omitempty"`
Affinity *CpuGroupAffinity `json:"Affinity,omitempty"`
GroupProperties []CpuGroupProperty `json:"GroupProperties,omitempty"`
// Hypervisor CPU group IDs exposed to clients
HypervisorGroupId int32 `json:"HypervisorGroupId,omitempty"`
}

View file

@ -0,0 +1,15 @@
/*
* HCS API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
// Structure used to return cpu groups for a Service property query
type CpuGroupConfigurations struct {
CpuGroups []CpuGroupConfig `json:"CpuGroups,omitempty"`
}

View file

@ -0,0 +1,18 @@
/*
* HCS API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type CPUGroupOperation string
const (
CreateGroup CPUGroupOperation = "CreateGroup"
DeleteGroup CPUGroupOperation = "DeleteGroup"
SetProperty CPUGroupOperation = "SetProperty"
)

View file

@ -0,0 +1,15 @@
/*
* HCS API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type CpuGroupProperty struct {
PropertyCode uint32 `json:"PropertyCode,omitempty"`
PropertyValue uint32 `json:"PropertyValue,omitempty"`
}

View file

@ -0,0 +1,17 @@
/*
* HCS API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
// Create group operation settings
type CreateGroupOperation struct {
GroupId string `json:"GroupId,omitempty"`
LogicalProcessorCount uint32 `json:"LogicalProcessorCount,omitempty"`
LogicalProcessors []uint32 `json:"LogicalProcessors,omitempty"`
}

View file

@ -0,0 +1,15 @@
/*
* HCS API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
// Delete group operation settings
type DeleteGroupOperation struct {
GroupId string `json:"GroupId,omitempty"`
}

View file

@ -13,8 +13,8 @@ type DeviceType string
const ( const (
ClassGUID DeviceType = "ClassGuid" ClassGUID DeviceType = "ClassGuid"
DeviceInstance = "DeviceInstance" DeviceInstance DeviceType = "DeviceInstance"
GPUMirror = "GpuMirror" GPUMirror DeviceType = "GpuMirror"
) )
type Device struct { type Device struct {

View file

@ -0,0 +1,16 @@
/*
* HCS API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
// Structure used to request a service processor modification
type HostProcessorModificationRequest struct {
Operation CPUGroupOperation `json:"Operation,omitempty"`
OperationDetails interface{} `json:"OperationDetails,omitempty"`
}

View file

@ -19,4 +19,10 @@ type HvSocketServiceConfig struct {
// If true, HvSocket will process wildcard binds for this service/system combination. Wildcard binds are secured in the registry at SOFTWARE/Microsoft/Windows NT/CurrentVersion/Virtualization/HvSocket/WildcardDescriptors // If true, HvSocket will process wildcard binds for this service/system combination. Wildcard binds are secured in the registry at SOFTWARE/Microsoft/Windows NT/CurrentVersion/Virtualization/HvSocket/WildcardDescriptors
AllowWildcardBinds bool `json:"AllowWildcardBinds,omitempty"` AllowWildcardBinds bool `json:"AllowWildcardBinds,omitempty"`
// Disabled controls whether the HvSocket service is accepting connection requests.
// This set to true will make the service refuse all incoming connections as well as cancel
// any connections already established. The service itself will still be active however
// and can be re-enabled at a future time.
Disabled bool `json:"Disabled,omitempty"`
} }

View file

@ -0,0 +1,42 @@
/*
* HCS API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type InterruptModerationName string
// The valid interrupt moderation modes for I/O virtualization (IOV) offloading.
const (
DefaultName InterruptModerationName = "Default"
AdaptiveName InterruptModerationName = "Adaptive"
OffName InterruptModerationName = "Off"
LowName InterruptModerationName = "Low"
MediumName InterruptModerationName = "Medium"
HighName InterruptModerationName = "High"
)
type InterruptModerationValue uint32
const (
DefaultValue InterruptModerationValue = iota
AdaptiveValue
OffValue
LowValue InterruptModerationValue = 100
MediumValue InterruptModerationValue = 200
HighValue InterruptModerationValue = 300
)
var InterruptModerationValueToName = map[InterruptModerationValue]InterruptModerationName{
DefaultValue: DefaultName,
AdaptiveValue: AdaptiveName,
OffValue: OffName,
LowValue: LowName,
MediumValue: MediumName,
HighValue: HighName,
}

View file

@ -0,0 +1,22 @@
/*
* HCS API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
type IovSettings struct {
// The weight assigned to this port for I/O virtualization (IOV) offloading.
// Setting this to 0 disables IOV offloading.
OffloadWeight *uint32 `json:"OffloadWeight,omitempty"`
// The number of queue pairs requested for this port for I/O virtualization (IOV) offloading.
QueuePairsRequested *uint32 `json:"QueuePairsRequested,omitempty"`
// The interrupt moderation mode for I/O virtualization (IOV) offloading.
InterruptModeration *InterruptModerationName `json:"InterruptModeration,omitempty"`
}

View file

@ -11,8 +11,8 @@ package hcsschema
type LogicalProcessor struct { type LogicalProcessor struct {
LpIndex uint32 `json:"LpIndex,omitempty"` LpIndex uint32 `json:"LpIndex,omitempty"`
NodeNumber uint8 `json:"NodeNumber, omitempty"` NodeNumber uint8 `json:"NodeNumber,omitempty"`
PackageId uint32 `json:"PackageId, omitempty"` PackageId uint32 `json:"PackageId,omitempty"`
CoreId uint32 `json:"CoreId, omitempty"` CoreId uint32 `json:"CoreId,omitempty"`
RootVpIndex int32 `json:"RootVpIndex, omitempty"` RootVpIndex int32 `json:"RootVpIndex,omitempty"`
} }

View file

@ -11,6 +11,7 @@ package hcsschema
type NetworkAdapter struct { type NetworkAdapter struct {
EndpointId string `json:"EndpointId,omitempty"` EndpointId string `json:"EndpointId,omitempty"`
MacAddress string `json:"MacAddress,omitempty"` MacAddress string `json:"MacAddress,omitempty"`
// The I/O virtualization (IOV) offloading configuration.
IovSettings *IovSettings `json:"IovSettings,omitempty"`
} }

View file

@ -22,4 +22,5 @@ const (
PTGuestConnection PropertyType = "GuestConnection" PTGuestConnection PropertyType = "GuestConnection"
PTICHeartbeatStatus PropertyType = "ICHeartbeatStatus" PTICHeartbeatStatus PropertyType = "ICHeartbeatStatus"
PTProcessorTopology PropertyType = "ProcessorTopology" PTProcessorTopology PropertyType = "ProcessorTopology"
PTCPUGroup PropertyType = "CpuGroup"
) )

View file

@ -0,0 +1,22 @@
/*
* HCS API
*
* No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
*
* API version: 2.4
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package hcsschema
// ProcessorLimits is used when modifying processor scheduling limits of a virtual machine.
type ProcessorLimits struct {
// Maximum amount of host CPU resources that the virtual machine can use.
Limit uint64 `json:"Limit,omitempty"`
// Value describing the relative priority of this virtual machine compared to other virtual machines.
Weight uint64 `json:"Weight,omitempty"`
// Minimum amount of host CPU resources that the virtual machine is guaranteed.
Reservation uint64 `json:"Reservation,omitempty"`
// Provides the target maximum CPU frequency, in MHz, for a virtual machine.
MaximumFrequencyMHz uint32 `json:"MaximumFrequencyMHz,omitempty"`
}

View file

@ -29,6 +29,9 @@ var (
// SystemResume is the timeout for resuming a compute system // SystemResume is the timeout for resuming a compute system
SystemResume time.Duration = defaultTimeout SystemResume time.Duration = defaultTimeout
// SystemSave is the timeout for saving a compute system
SystemSave time.Duration = defaultTimeout
// SyscallWatcher is the timeout before warning of a potential stuck platform syscall. // SyscallWatcher is the timeout before warning of a potential stuck platform syscall.
SyscallWatcher time.Duration = defaultTimeout SyscallWatcher time.Duration = defaultTimeout
@ -51,6 +54,7 @@ func init() {
SystemStart = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMSTART", SystemStart) SystemStart = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMSTART", SystemStart)
SystemPause = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMPAUSE", SystemPause) SystemPause = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMPAUSE", SystemPause)
SystemResume = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMRESUME", SystemResume) SystemResume = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMRESUME", SystemResume)
SystemSave = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSTEMSAVE", SystemSave)
SyscallWatcher = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSCALLWATCHER", SyscallWatcher) SyscallWatcher = durationFromEnvironment("HCSSHIM_TIMEOUT_SYSCALLWATCHER", SyscallWatcher)
Tar2VHD = durationFromEnvironment("HCSSHIM_TIMEOUT_TAR2VHD", Tar2VHD) Tar2VHD = durationFromEnvironment("HCSSHIM_TIMEOUT_TAR2VHD", Tar2VHD)
ExternalCommandToStart = durationFromEnvironment("HCSSHIM_TIMEOUT_EXTERNALCOMMANDSTART", ExternalCommandToStart) ExternalCommandToStart = durationFromEnvironment("HCSSHIM_TIMEOUT_EXTERNALCOMMANDSTART", ExternalCommandToStart)

View file

@ -29,6 +29,7 @@ import (
//sys hcsModifyServiceSettings(settings string, result **uint16) (hr error) = vmcompute.HcsModifyServiceSettings? //sys hcsModifyServiceSettings(settings string, result **uint16) (hr error) = vmcompute.HcsModifyServiceSettings?
//sys hcsRegisterComputeSystemCallback(computeSystem HcsSystem, callback uintptr, context uintptr, callbackHandle *HcsCallback) (hr error) = vmcompute.HcsRegisterComputeSystemCallback? //sys hcsRegisterComputeSystemCallback(computeSystem HcsSystem, callback uintptr, context uintptr, callbackHandle *HcsCallback) (hr error) = vmcompute.HcsRegisterComputeSystemCallback?
//sys hcsUnregisterComputeSystemCallback(callbackHandle HcsCallback) (hr error) = vmcompute.HcsUnregisterComputeSystemCallback? //sys hcsUnregisterComputeSystemCallback(callbackHandle HcsCallback) (hr error) = vmcompute.HcsUnregisterComputeSystemCallback?
//sys hcsSaveComputeSystem(computeSystem HcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsSaveComputeSystem?
//sys hcsCreateProcess(computeSystem HcsSystem, processParameters string, processInformation *HcsProcessInformation, process *HcsProcess, result **uint16) (hr error) = vmcompute.HcsCreateProcess? //sys hcsCreateProcess(computeSystem HcsSystem, processParameters string, processInformation *HcsProcessInformation, process *HcsProcess, result **uint16) (hr error) = vmcompute.HcsCreateProcess?
//sys hcsOpenProcess(computeSystem HcsSystem, pid uint32, process *HcsProcess, result **uint16) (hr error) = vmcompute.HcsOpenProcess? //sys hcsOpenProcess(computeSystem HcsSystem, pid uint32, process *HcsProcess, result **uint16) (hr error) = vmcompute.HcsOpenProcess?
@ -61,7 +62,7 @@ type HcsCallback syscall.Handle
type HcsProcessInformation struct { type HcsProcessInformation struct {
// ProcessId is the pid of the created process. // ProcessId is the pid of the created process.
ProcessId uint32 ProcessId uint32
reserved uint32 reserved uint32 //nolint:structcheck
// StdInput is the handle associated with the stdin of the process. // StdInput is the handle associated with the stdin of the process.
StdInput syscall.Handle StdInput syscall.Handle
// StdOutput is the handle associated with the stdout of the process. // StdOutput is the handle associated with the stdout of the process.
@ -585,3 +586,25 @@ func HcsUnregisterProcessCallback(ctx gcontext.Context, callbackHandle HcsCallba
return hcsUnregisterProcessCallback(callbackHandle) return hcsUnregisterProcessCallback(callbackHandle)
}) })
} }
func HcsSaveComputeSystem(ctx gcontext.Context, computeSystem HcsSystem, options string) (result string, hr error) {
ctx, span := trace.StartSpan(ctx, "HcsSaveComputeSystem")
defer span.End()
defer func() {
if result != "" {
span.AddAttributes(trace.StringAttribute("result", result))
}
if hr != errVmcomputeOperationPending {
oc.SetSpanStatus(span, hr)
}
}()
return result, execute(ctx, timeout.SyscallWatcher, func() error {
var resultp *uint16
err := hcsSaveComputeSystem(computeSystem, options, &resultp)
if resultp != nil {
result = interop.ConvertAndFreeCoTaskMemString(resultp)
}
return err
})
}

View file

@ -53,6 +53,7 @@ var (
procHcsModifyServiceSettings = modvmcompute.NewProc("HcsModifyServiceSettings") procHcsModifyServiceSettings = modvmcompute.NewProc("HcsModifyServiceSettings")
procHcsRegisterComputeSystemCallback = modvmcompute.NewProc("HcsRegisterComputeSystemCallback") procHcsRegisterComputeSystemCallback = modvmcompute.NewProc("HcsRegisterComputeSystemCallback")
procHcsUnregisterComputeSystemCallback = modvmcompute.NewProc("HcsUnregisterComputeSystemCallback") procHcsUnregisterComputeSystemCallback = modvmcompute.NewProc("HcsUnregisterComputeSystemCallback")
procHcsSaveComputeSystem = modvmcompute.NewProc("HcsSaveComputeSystem")
procHcsCreateProcess = modvmcompute.NewProc("HcsCreateProcess") procHcsCreateProcess = modvmcompute.NewProc("HcsCreateProcess")
procHcsOpenProcess = modvmcompute.NewProc("HcsOpenProcess") procHcsOpenProcess = modvmcompute.NewProc("HcsOpenProcess")
procHcsCloseProcess = modvmcompute.NewProc("HcsCloseProcess") procHcsCloseProcess = modvmcompute.NewProc("HcsCloseProcess")
@ -366,6 +367,29 @@ func hcsUnregisterComputeSystemCallback(callbackHandle HcsCallback) (hr error) {
return return
} }
func hcsSaveComputeSystem(computeSystem HcsSystem, options string, result **uint16) (hr error) {
var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(options)
if hr != nil {
return
}
return _hcsSaveComputeSystem(computeSystem, _p0, result)
}
func _hcsSaveComputeSystem(computeSystem HcsSystem, options *uint16, result **uint16) (hr error) {
if hr = procHcsSaveComputeSystem.Find(); hr != nil {
return
}
r0, _, _ := syscall.Syscall(procHcsSaveComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
if int32(r0) < 0 {
if r0&0x1fff0000 == 0x00070000 {
r0 &= 0xffff
}
hr = syscall.Errno(r0)
}
return
}
func hcsCreateProcess(computeSystem HcsSystem, processParameters string, processInformation *HcsProcessInformation, process *HcsProcess, result **uint16) (hr error) { func hcsCreateProcess(computeSystem HcsSystem, processParameters string, processInformation *HcsProcessInformation, process *HcsProcess, result **uint16) (hr error) {
var _p0 *uint16 var _p0 *uint16
_p0, hr = syscall.UTF16PtrFromString(processParameters) _p0, hr = syscall.UTF16PtrFromString(processParameters)

View file

@ -14,7 +14,7 @@ import (
// An activated layer must later be deactivated via DeactivateLayer. // An activated layer must later be deactivated via DeactivateLayer.
func ActivateLayer(ctx context.Context, path string) (err error) { func ActivateLayer(ctx context.Context, path string) (err error) {
title := "hcsshim::ActivateLayer" title := "hcsshim::ActivateLayer"
ctx, span := trace.StartSpan(ctx, title) ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End() defer span.End()
defer func() { oc.SetSpanStatus(span, err) }() defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("path", path)) span.AddAttributes(trace.StringAttribute("path", path))

View file

@ -12,7 +12,7 @@ import (
// the parent layer provided. // the parent layer provided.
func CreateLayer(ctx context.Context, path, parent string) (err error) { func CreateLayer(ctx context.Context, path, parent string) (err error) {
title := "hcsshim::CreateLayer" title := "hcsshim::CreateLayer"
ctx, span := trace.StartSpan(ctx, title) ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End() defer span.End()
defer func() { oc.SetSpanStatus(span, err) }() defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes( span.AddAttributes(

View file

@ -11,7 +11,7 @@ import (
// DeactivateLayer will dismount a layer that was mounted via ActivateLayer. // DeactivateLayer will dismount a layer that was mounted via ActivateLayer.
func DeactivateLayer(ctx context.Context, path string) (err error) { func DeactivateLayer(ctx context.Context, path string) (err error) {
title := "hcsshim::DeactivateLayer" title := "hcsshim::DeactivateLayer"
ctx, span := trace.StartSpan(ctx, title) ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End() defer span.End()
defer func() { oc.SetSpanStatus(span, err) }() defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("path", path)) span.AddAttributes(trace.StringAttribute("path", path))

View file

@ -12,7 +12,7 @@ import (
// path, including that layer's containing folder, if any. // path, including that layer's containing folder, if any.
func DestroyLayer(ctx context.Context, path string) (err error) { func DestroyLayer(ctx context.Context, path string) (err error) {
title := "hcsshim::DestroyLayer" title := "hcsshim::DestroyLayer"
ctx, span := trace.StartSpan(ctx, title) ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End() defer span.End()
defer func() { oc.SetSpanStatus(span, err) }() defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("path", path)) span.AddAttributes(trace.StringAttribute("path", path))

View file

@ -21,8 +21,7 @@ func GetLayerMountPath(ctx context.Context, path string) (_ string, err error) {
defer func() { oc.SetSpanStatus(span, err) }() defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("path", path)) span.AddAttributes(trace.StringAttribute("path", path))
var mountPathLength uintptr var mountPathLength uintptr = 0
mountPathLength = 0
// Call the procedure itself. // Call the procedure itself.
log.G(ctx).Debug("Calling proc (1)") log.G(ctx).Debug("Calling proc (1)")

View file

@ -14,7 +14,7 @@ import (
// of registering them with the graphdriver, graph, and tagstore. // of registering them with the graphdriver, graph, and tagstore.
func GetSharedBaseImages(ctx context.Context) (_ string, err error) { func GetSharedBaseImages(ctx context.Context) (_ string, err error) {
title := "hcsshim::GetSharedBaseImages" title := "hcsshim::GetSharedBaseImages"
ctx, span := trace.StartSpan(ctx, title) ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End() defer span.End()
defer func() { oc.SetSpanStatus(span, err) }() defer func() { oc.SetSpanStatus(span, err) }()

View file

@ -11,7 +11,7 @@ import (
// GrantVmAccess adds access to a file for a given VM // GrantVmAccess adds access to a file for a given VM
func GrantVmAccess(ctx context.Context, vmid string, filepath string) (err error) { func GrantVmAccess(ctx context.Context, vmid string, filepath string) (err error) {
title := "hcsshim::GrantVmAccess" title := "hcsshim::GrantVmAccess"
ctx, span := trace.StartSpan(ctx, title) ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End() defer span.End()
defer func() { oc.SetSpanStatus(span, err) }() defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes( span.AddAttributes(

View file

@ -12,7 +12,7 @@ import (
// to the system. // to the system.
func LayerExists(ctx context.Context, path string) (_ bool, err error) { func LayerExists(ctx context.Context, path string) (_ bool, err error) {
title := "hcsshim::LayerExists" title := "hcsshim::LayerExists"
ctx, span := trace.StartSpan(ctx, title) ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End() defer span.End()
defer func() { oc.SetSpanStatus(span, err) }() defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("path", path)) span.AddAttributes(trace.StringAttribute("path", path))

View file

@ -390,7 +390,7 @@ func (w *legacyLayerWriter) CloseRoots() {
w.destRoot = nil w.destRoot = nil
} }
for i := range w.parentRoots { for i := range w.parentRoots {
w.parentRoots[i].Close() _ = w.parentRoots[i].Close()
} }
w.parentRoots = nil w.parentRoots = nil
} }
@ -640,7 +640,7 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
defer func() { defer func() {
if f != nil { if f != nil {
f.Close() f.Close()
safefile.RemoveRelative(name, w.destRoot) _ = safefile.RemoveRelative(name, w.destRoot)
} }
}() }()
@ -676,7 +676,7 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
defer func() { defer func() {
if f != nil { if f != nil {
f.Close() f.Close()
safefile.RemoveRelative(fname, w.root) _ = safefile.RemoveRelative(fname, w.root)
} }
}() }()

View file

@ -14,7 +14,7 @@ import (
// across all clients. // across all clients.
func NameToGuid(ctx context.Context, name string) (_ guid.GUID, err error) { func NameToGuid(ctx context.Context, name string) (_ guid.GUID, err error) {
title := "hcsshim::NameToGuid" title := "hcsshim::NameToGuid"
ctx, span := trace.StartSpan(ctx, title) ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End() defer span.End()
defer func() { oc.SetSpanStatus(span, err) }() defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("name", name)) span.AddAttributes(trace.StringAttribute("name", name))

View file

@ -12,7 +12,7 @@ import (
// The files should have been extracted to <path>\Files. // The files should have been extracted to <path>\Files.
func ProcessBaseLayer(ctx context.Context, path string) (err error) { func ProcessBaseLayer(ctx context.Context, path string) (err error) {
title := "hcsshim::ProcessBaseLayer" title := "hcsshim::ProcessBaseLayer"
ctx, span := trace.StartSpan(ctx, title) ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End() defer span.End()
defer func() { oc.SetSpanStatus(span, err) }() defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("path", path)) span.AddAttributes(trace.StringAttribute("path", path))
@ -28,7 +28,7 @@ func ProcessBaseLayer(ctx context.Context, path string) (err error) {
// The files should have been extracted to <path>\Files. // The files should have been extracted to <path>\Files.
func ProcessUtilityVMImage(ctx context.Context, path string) (err error) { func ProcessUtilityVMImage(ctx context.Context, path string) (err error) {
title := "hcsshim::ProcessUtilityVMImage" title := "hcsshim::ProcessUtilityVMImage"
ctx, span := trace.StartSpan(ctx, title) ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End() defer span.End()
defer func() { oc.SetSpanStatus(span, err) }() defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("path", path)) span.AddAttributes(trace.StringAttribute("path", path))

View file

@ -12,7 +12,7 @@ import (
// the given id. // the given id.
func UnprepareLayer(ctx context.Context, path string) (err error) { func UnprepareLayer(ctx context.Context, path string) (err error) {
title := "hcsshim::UnprepareLayer" title := "hcsshim::UnprepareLayer"
ctx, span := trace.StartSpan(ctx, title) ctx, span := trace.StartSpan(ctx, title) //nolint:ineffassign,staticcheck
defer span.End() defer span.End()
defer func() { oc.SetSpanStatus(span, err) }() defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("path", path)) span.AddAttributes(trace.StringAttribute("path", path))

View file

@ -31,6 +31,43 @@ const (
STATUS_NO_MORE_ENTRIES = 0x8000001a STATUS_NO_MORE_ENTRIES = 0x8000001a
) )
// Select entries from FILE_INFO_BY_HANDLE_CLASS.
//
// C declaration:
// typedef enum _FILE_INFO_BY_HANDLE_CLASS {
// FileBasicInfo,
// FileStandardInfo,
// FileNameInfo,
// FileRenameInfo,
// FileDispositionInfo,
// FileAllocationInfo,
// FileEndOfFileInfo,
// FileStreamInfo,
// FileCompressionInfo,
// FileAttributeTagInfo,
// FileIdBothDirectoryInfo,
// FileIdBothDirectoryRestartInfo,
// FileIoPriorityHintInfo,
// FileRemoteProtocolInfo,
// FileFullDirectoryInfo,
// FileFullDirectoryRestartInfo,
// FileStorageInfo,
// FileAlignmentInfo,
// FileIdInfo,
// FileIdExtdDirectoryInfo,
// FileIdExtdDirectoryRestartInfo,
// FileDispositionInfoEx,
// FileRenameInfoEx,
// FileCaseSensitiveInfo,
// FileNormalizedNameInfo,
// MaximumFileInfoByHandleClass
// } FILE_INFO_BY_HANDLE_CLASS, *PFILE_INFO_BY_HANDLE_CLASS;
//
// Documentation: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ne-minwinbase-file_info_by_handle_class
const (
FileIdInfo = 18
)
type FileDispositionInformationEx struct { type FileDispositionInformationEx struct {
Flags uintptr Flags uintptr
} }
@ -42,7 +79,7 @@ type IOStatusBlock struct {
type ObjectAttributes struct { type ObjectAttributes struct {
Length uintptr Length uintptr
RootDirectory uintptr RootDirectory uintptr
ObjectName uintptr ObjectName *UnicodeString
Attributes uintptr Attributes uintptr
SecurityDescriptor uintptr SecurityDescriptor uintptr
SecurityQoS uintptr SecurityQoS uintptr
@ -59,3 +96,15 @@ type FileLinkInformation struct {
FileNameLength uint32 FileNameLength uint32
FileName [1]uint16 FileName [1]uint16
} }
// C declaration:
// typedef struct _FILE_ID_INFO {
// ULONGLONG VolumeSerialNumber;
// FILE_ID_128 FileId;
// } FILE_ID_INFO, *PFILE_ID_INFO;
//
// Documentation: https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_id_info
type FILE_ID_INFO struct {
VolumeSerialNumber uint64
FileID [16]byte
}

View file

@ -0,0 +1,3 @@
package winapi
//sys GetQueuedCompletionStatus(cphandle windows.Handle, qty *uint32, key *uintptr, overlapped **windows.Overlapped, timeout uint32) (err error)

View file

@ -1,32 +1,41 @@
package winapi package winapi
import ( import (
"unsafe"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
// Messages that can be received from an assigned io completion port. // Messages that can be received from an assigned io completion port.
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_associate_completion_port // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_associate_completion_port
const ( const (
JOB_OBJECT_MSG_END_OF_JOB_TIME = 1 JOB_OBJECT_MSG_END_OF_JOB_TIME uint32 = 1
JOB_OBJECT_MSG_END_OF_PROCESS_TIME = 2 JOB_OBJECT_MSG_END_OF_PROCESS_TIME uint32 = 2
JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT = 3 JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT uint32 = 3
JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO = 4 JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO uint32 = 4
JOB_OBJECT_MSG_NEW_PROCESS = 6 JOB_OBJECT_MSG_NEW_PROCESS uint32 = 6
JOB_OBJECT_MSG_EXIT_PROCESS = 7 JOB_OBJECT_MSG_EXIT_PROCESS uint32 = 7
JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS = 8 JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS uint32 = 8
JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT = 9 JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT uint32 = 9
JOB_OBJECT_MSG_JOB_MEMORY_LIMIT = 10 JOB_OBJECT_MSG_JOB_MEMORY_LIMIT uint32 = 10
JOB_OBJECT_MSG_NOTIFICATION_LIMIT = 11 JOB_OBJECT_MSG_NOTIFICATION_LIMIT uint32 = 11
) )
// Access rights for creating or opening job objects.
//
// https://docs.microsoft.com/en-us/windows/win32/procthread/job-object-security-and-access-rights
const JOB_OBJECT_ALL_ACCESS = 0x1F001F
// IO limit flags // IO limit flags
// //
// https://docs.microsoft.com/en-us/windows/win32/api/jobapi2/ns-jobapi2-jobobject_io_rate_control_information // https://docs.microsoft.com/en-us/windows/win32/api/jobapi2/ns-jobapi2-jobobject_io_rate_control_information
const JOB_OBJECT_IO_RATE_CONTROL_ENABLE = 0x1 const JOB_OBJECT_IO_RATE_CONTROL_ENABLE = 0x1
const JOBOBJECT_IO_ATTRIBUTION_CONTROL_ENABLE uint32 = 0x1
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_cpu_rate_control_information // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_cpu_rate_control_information
const ( const (
JOB_OBJECT_CPU_RATE_CONTROL_ENABLE = 1 << iota JOB_OBJECT_CPU_RATE_CONTROL_ENABLE uint32 = 1 << iota
JOB_OBJECT_CPU_RATE_CONTROL_WEIGHT_BASED JOB_OBJECT_CPU_RATE_CONTROL_WEIGHT_BASED
JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP
JOB_OBJECT_CPU_RATE_CONTROL_NOTIFY JOB_OBJECT_CPU_RATE_CONTROL_NOTIFY
@ -41,7 +50,9 @@ const (
JobObjectBasicProcessIdList uint32 = 3 JobObjectBasicProcessIdList uint32 = 3
JobObjectBasicAndIoAccountingInformation uint32 = 8 JobObjectBasicAndIoAccountingInformation uint32 = 8
JobObjectLimitViolationInformation uint32 = 13 JobObjectLimitViolationInformation uint32 = 13
JobObjectMemoryUsageInformation uint32 = 28
JobObjectNotificationLimitInformation2 uint32 = 33 JobObjectNotificationLimitInformation2 uint32 = 33
JobObjectIoAttribution uint32 = 42
) )
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_basic_limit_information // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_basic_limit_information
@ -60,7 +71,7 @@ type JOBOBJECT_BASIC_LIMIT_INFORMATION struct {
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_cpu_rate_control_information // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_cpu_rate_control_information
type JOBOBJECT_CPU_RATE_CONTROL_INFORMATION struct { type JOBOBJECT_CPU_RATE_CONTROL_INFORMATION struct {
ControlFlags uint32 ControlFlags uint32
Rate uint32 Value uint32
} }
// https://docs.microsoft.com/en-us/windows/win32/api/jobapi2/ns-jobapi2-jobobject_io_rate_control_information // https://docs.microsoft.com/en-us/windows/win32/api/jobapi2/ns-jobapi2-jobobject_io_rate_control_information
@ -80,9 +91,68 @@ type JOBOBJECT_BASIC_PROCESS_ID_LIST struct {
ProcessIdList [1]uintptr ProcessIdList [1]uintptr
} }
// 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]
}
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_basic_accounting_information
type JOBOBJECT_BASIC_ACCOUNTING_INFORMATION struct {
TotalUserTime int64
TotalKernelTime int64
ThisPeriodTotalUserTime int64
ThisPeriodTotalKernelTime int64
TotalPageFaultCount uint32
TotalProcesses uint32
ActiveProcesses uint32
TotalTerminateProcesses uint32
}
//https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_basic_and_io_accounting_information
type JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION struct {
BasicInfo JOBOBJECT_BASIC_ACCOUNTING_INFORMATION
IoInfo windows.IO_COUNTERS
}
// typedef struct _JOBOBJECT_MEMORY_USAGE_INFORMATION {
// ULONG64 JobMemory;
// ULONG64 PeakJobMemoryUsed;
// } JOBOBJECT_MEMORY_USAGE_INFORMATION, *PJOBOBJECT_MEMORY_USAGE_INFORMATION;
//
type JOBOBJECT_MEMORY_USAGE_INFORMATION struct {
JobMemory uint64
PeakJobMemoryUsed uint64
}
// typedef struct _JOBOBJECT_IO_ATTRIBUTION_STATS {
// ULONG_PTR IoCount;
// ULONGLONG TotalNonOverlappedQueueTime;
// ULONGLONG TotalNonOverlappedServiceTime;
// ULONGLONG TotalSize;
// } JOBOBJECT_IO_ATTRIBUTION_STATS, *PJOBOBJECT_IO_ATTRIBUTION_STATS;
//
type JOBOBJECT_IO_ATTRIBUTION_STATS struct {
IoCount uintptr
TotalNonOverlappedQueueTime uint64
TotalNonOverlappedServiceTime uint64
TotalSize uint64
}
// typedef struct _JOBOBJECT_IO_ATTRIBUTION_INFORMATION {
// ULONG ControlFlags;
// JOBOBJECT_IO_ATTRIBUTION_STATS ReadStats;
// JOBOBJECT_IO_ATTRIBUTION_STATS WriteStats;
// } JOBOBJECT_IO_ATTRIBUTION_INFORMATION, *PJOBOBJECT_IO_ATTRIBUTION_INFORMATION;
//
type JOBOBJECT_IO_ATTRIBUTION_INFORMATION struct {
ControlFlags uint32
ReadStats JOBOBJECT_IO_ATTRIBUTION_STATS
WriteStats JOBOBJECT_IO_ATTRIBUTION_STATS
}
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_associate_completion_port // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_associate_completion_port
type JOBOBJECT_ASSOCIATE_COMPLETION_PORT struct { type JOBOBJECT_ASSOCIATE_COMPLETION_PORT struct {
CompletionKey uintptr CompletionKey windows.Handle
CompletionPort windows.Handle CompletionPort windows.Handle
} }
@ -118,3 +188,28 @@ type JOBOBJECT_ASSOCIATE_COMPLETION_PORT struct {
// ); // );
// //
//sys SetIoRateControlInformationJobObject(jobHandle windows.Handle, ioRateControlInfo *JOBOBJECT_IO_RATE_CONTROL_INFORMATION) (ret uint32, err error) = kernel32.SetIoRateControlInformationJobObject //sys SetIoRateControlInformationJobObject(jobHandle windows.Handle, ioRateControlInfo *JOBOBJECT_IO_RATE_CONTROL_INFORMATION) (ret uint32, err error) = kernel32.SetIoRateControlInformationJobObject
// DWORD QueryIoRateControlInformationJobObject(
// HANDLE hJob,
// PCWSTR VolumeName,
// JOBOBJECT_IO_RATE_CONTROL_INFORMATION **InfoBlocks,
// ULONG *InfoBlockCount
// );
//sys QueryIoRateControlInformationJobObject(jobHandle windows.Handle, volumeName *uint16, ioRateControlInfo **JOBOBJECT_IO_RATE_CONTROL_INFORMATION, infoBlockCount *uint32) (ret uint32, err error) = kernel32.QueryIoRateControlInformationJobObject
// NTSTATUS
// NtOpenJobObject (
// _Out_ PHANDLE JobHandle,
// _In_ ACCESS_MASK DesiredAccess,
// _In_ POBJECT_ATTRIBUTES ObjectAttributes
// );
//sys NtOpenJobObject(jobHandle *windows.Handle, desiredAccess uint32, objAttributes *ObjectAttributes) (status uint32) = ntdll.NtOpenJobObject
// NTSTATUS
// NTAPI
// NtCreateJobObject (
// _Out_ PHANDLE JobHandle,
// _In_ ACCESS_MASK DesiredAccess,
// _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes
// );
//sys NtCreateJobObject(jobHandle *windows.Handle, desiredAccess uint32, objAttributes *ObjectAttributes) (status uint32) = ntdll.NtCreateJobObject

View file

@ -9,3 +9,19 @@ package winapi
//sys LocalAlloc(flags uint32, size int) (ptr uintptr) = kernel32.LocalAlloc //sys LocalAlloc(flags uint32, size int) (ptr uintptr) = kernel32.LocalAlloc
//sys LocalFree(ptr uintptr) = kernel32.LocalFree //sys LocalFree(ptr uintptr) = kernel32.LocalFree
// BOOL QueryWorkingSet(
// HANDLE hProcess,
// PVOID pv,
// DWORD cb
// );
//sys QueryWorkingSet(handle windows.Handle, pv uintptr, cb uint32) (err error) = psapi.QueryWorkingSet
type PSAPI_WORKING_SET_INFORMATION struct {
NumberOfEntries uintptr
WorkingSetInfo [1]PSAPI_WORKING_SET_BLOCK
}
type PSAPI_WORKING_SET_BLOCK struct {
Flags uintptr
}

View file

@ -0,0 +1,3 @@
package winapi
//sys SetJobCompartmentId(handle windows.Handle, compartmentId uint32) (win32Err error) = iphlpapi.SetJobCompartmentId

View file

@ -8,4 +8,4 @@ package winapi
// LPWSTR lpBuffer, // LPWSTR lpBuffer,
// LPWSTR *lpFilePart // LPWSTR *lpFilePart
// ); // );
//sys SearchPath(lpPath *uint16, lpFileName *uint16, lpExtension *uint16, nBufferLength uint32, lpBuffer *uint16, lpFilePath **uint16) (size uint32, err error) = kernel32.SearchPathW //sys SearchPath(lpPath *uint16, lpFileName *uint16, lpExtension *uint16, nBufferLength uint32, lpBuffer *uint16, lpFilePath *uint16) (size uint32, err error) = kernel32.SearchPathW

View file

@ -1,3 +1,10 @@
package winapi package winapi
const PROCESS_ALL_ACCESS uint32 = 2097151 const PROCESS_ALL_ACCESS uint32 = 2097151
// DWORD GetProcessImageFileNameW(
// HANDLE hProcess,
// LPWSTR lpImageFileName,
// DWORD nSize
// );
//sys GetProcessImageFileName(hProcess windows.Handle, imageFileName *uint16, nSize uint32) (size uint32, err error) = kernel32.GetProcessImageFileNameW

View file

@ -0,0 +1,52 @@
package winapi
import "golang.org/x/sys/windows"
const SystemProcessInformation = 5
const STATUS_INFO_LENGTH_MISMATCH = 0xC0000004
// __kernel_entry NTSTATUS NtQuerySystemInformation(
// SYSTEM_INFORMATION_CLASS SystemInformationClass,
// PVOID SystemInformation,
// ULONG SystemInformationLength,
// PULONG ReturnLength
// );
//sys NtQuerySystemInformation(systemInfoClass int, systemInformation uintptr, systemInfoLength uint32, returnLength *uint32) (status uint32) = ntdll.NtQuerySystemInformation
type SYSTEM_PROCESS_INFORMATION struct {
NextEntryOffset uint32 // ULONG
NumberOfThreads uint32 // ULONG
WorkingSetPrivateSize int64 // LARGE_INTEGER
HardFaultCount uint32 // ULONG
NumberOfThreadsHighWatermark uint32 // ULONG
CycleTime uint64 // ULONGLONG
CreateTime int64 // LARGE_INTEGER
UserTime int64 // LARGE_INTEGER
KernelTime int64 // LARGE_INTEGER
ImageName UnicodeString // UNICODE_STRING
BasePriority int32 // KPRIORITY
UniqueProcessID windows.Handle // HANDLE
InheritedFromUniqueProcessID windows.Handle // HANDLE
HandleCount uint32 // ULONG
SessionID uint32 // ULONG
UniqueProcessKey *uint32 // ULONG_PTR
PeakVirtualSize uintptr // SIZE_T
VirtualSize uintptr // SIZE_T
PageFaultCount uint32 // ULONG
PeakWorkingSetSize uintptr // SIZE_T
WorkingSetSize uintptr // SIZE_T
QuotaPeakPagedPoolUsage uintptr // SIZE_T
QuotaPagedPoolUsage uintptr // SIZE_T
QuotaPeakNonPagedPoolUsage uintptr // SIZE_T
QuotaNonPagedPoolUsage uintptr // SIZE_T
PagefileUsage uintptr // SIZE_T
PeakPagefileUsage uintptr // SIZE_T
PrivatePageCount uintptr // SIZE_T
ReadOperationCount int64 // LARGE_INTEGER
WriteOperationCount int64 // LARGE_INTEGER
OtherOperationCount int64 // LARGE_INTEGER
ReadTransferCount int64 // LARGE_INTEGER
WriteTransferCount int64 // LARGE_INTEGER
OtherTransferCount int64 // LARGE_INTEGER
}

View file

@ -0,0 +1,12 @@
package winapi
// HANDLE CreateRemoteThread(
// HANDLE hProcess,
// LPSECURITY_ATTRIBUTES lpThreadAttributes,
// SIZE_T dwStackSize,
// LPTHREAD_START_ROUTINE lpStartAddress,
// LPVOID lpParameter,
// DWORD dwCreationFlags,
// LPDWORD lpThreadId
// );
//sys CreateRemoteThread(process windows.Handle, sa *windows.SecurityAttributes, stackSize uint32, startAddr uintptr, parameter uintptr, creationFlags uint32, threadID *uint32) (handle windows.Handle, err error) = kernel32.CreateRemoteThread

View file

@ -2,11 +2,24 @@ package winapi
import ( import (
"errors" "errors"
"reflect"
"syscall" "syscall"
"unicode/utf16"
"unsafe" "unsafe"
"golang.org/x/sys/windows"
) )
// Uint16BufferToSlice wraps a uint16 pointer-and-length into a slice
// for easier interop with Go APIs
func Uint16BufferToSlice(buffer *uint16, bufferLength int) (result []uint16) {
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&result))
hdr.Data = uintptr(unsafe.Pointer(buffer))
hdr.Cap = bufferLength
hdr.Len = bufferLength
return
}
type UnicodeString struct { type UnicodeString struct {
Length uint16 Length uint16
MaximumLength uint16 MaximumLength uint16
@ -15,28 +28,30 @@ type UnicodeString struct {
//String converts a UnicodeString to a golang string //String converts a UnicodeString to a golang string
func (uni UnicodeString) String() string { func (uni UnicodeString) String() string {
p := (*[0xffff]uint16)(unsafe.Pointer(uni.Buffer))
// UnicodeString is not guaranteed to be null terminated, therefore // UnicodeString is not guaranteed to be null terminated, therefore
// use the UnicodeString's Length field // use the UnicodeString's Length field
lengthInChars := uni.Length / 2 return syscall.UTF16ToString(Uint16BufferToSlice(uni.Buffer, int(uni.Length/2)))
return syscall.UTF16ToString(p[:lengthInChars])
} }
// NewUnicodeString allocates a new UnicodeString and copies `s` into // NewUnicodeString allocates a new UnicodeString and copies `s` into
// the buffer of the new UnicodeString. // the buffer of the new UnicodeString.
func NewUnicodeString(s string) (*UnicodeString, error) { func NewUnicodeString(s string) (*UnicodeString, error) {
ws := utf16.Encode(([]rune)(s)) // Get length of original `s` to use in the UnicodeString since the `buf`
if len(ws) > 32767 { // created later will have an additional trailing null character
length := len(s)
if length > 32767 {
return nil, syscall.ENAMETOOLONG return nil, syscall.ENAMETOOLONG
} }
uni := &UnicodeString{ buf, err := windows.UTF16FromString(s)
Length: uint16(len(ws) * 2), if err != nil {
MaximumLength: uint16(len(ws) * 2), return nil, err
Buffer: &make([]uint16, len(ws))[0], }
uni := &UnicodeString{
Length: uint16(length * 2),
MaximumLength: uint16(length * 2),
Buffer: &buf[0],
} }
copy((*[32768]uint16)(unsafe.Pointer(uni.Buffer))[:], ws)
return uni, nil return uni, nil
} }

View file

@ -2,4 +2,4 @@
// be thought of as an extension to golang.org/x/sys/windows. // be thought of as an extension to golang.org/x/sys/windows.
package winapi package winapi
//go:generate go run ..\..\mksyscall_windows.go -output zsyscall_windows.go jobobject.go path.go logon.go memory.go processor.go devices.go filesystem.go errors.go //go:generate go run ..\..\mksyscall_windows.go -output zsyscall_windows.go system.go net.go path.go thread.go iocp.go jobobject.go logon.go memory.go process.go processor.go devices.go filesystem.go errors.go

View file

@ -37,32 +37,95 @@ func errnoErr(e syscall.Errno) error {
} }
var ( var (
modntdll = windows.NewLazySystemDLL("ntdll.dll")
modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
modkernel32 = windows.NewLazySystemDLL("kernel32.dll") modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
modpsapi = windows.NewLazySystemDLL("psapi.dll")
modcfgmgr32 = windows.NewLazySystemDLL("cfgmgr32.dll") modcfgmgr32 = windows.NewLazySystemDLL("cfgmgr32.dll")
modntdll = windows.NewLazySystemDLL("ntdll.dll")
procIsProcessInJob = modkernel32.NewProc("IsProcessInJob") procNtQuerySystemInformation = modntdll.NewProc("NtQuerySystemInformation")
procQueryInformationJobObject = modkernel32.NewProc("QueryInformationJobObject") procSetJobCompartmentId = modiphlpapi.NewProc("SetJobCompartmentId")
procOpenJobObjectW = modkernel32.NewProc("OpenJobObjectW") procSearchPathW = modkernel32.NewProc("SearchPathW")
procSetIoRateControlInformationJobObject = modkernel32.NewProc("SetIoRateControlInformationJobObject") procCreateRemoteThread = modkernel32.NewProc("CreateRemoteThread")
procSearchPathW = modkernel32.NewProc("SearchPathW") procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
procLogonUserW = modadvapi32.NewProc("LogonUserW") procIsProcessInJob = modkernel32.NewProc("IsProcessInJob")
procRtlMoveMemory = modkernel32.NewProc("RtlMoveMemory") procQueryInformationJobObject = modkernel32.NewProc("QueryInformationJobObject")
procLocalAlloc = modkernel32.NewProc("LocalAlloc") procOpenJobObjectW = modkernel32.NewProc("OpenJobObjectW")
procLocalFree = modkernel32.NewProc("LocalFree") procSetIoRateControlInformationJobObject = modkernel32.NewProc("SetIoRateControlInformationJobObject")
procGetActiveProcessorCount = modkernel32.NewProc("GetActiveProcessorCount") procQueryIoRateControlInformationJobObject = modkernel32.NewProc("QueryIoRateControlInformationJobObject")
procCM_Get_Device_ID_List_SizeA = modcfgmgr32.NewProc("CM_Get_Device_ID_List_SizeA") procNtOpenJobObject = modntdll.NewProc("NtOpenJobObject")
procCM_Get_Device_ID_ListA = modcfgmgr32.NewProc("CM_Get_Device_ID_ListA") procNtCreateJobObject = modntdll.NewProc("NtCreateJobObject")
procCM_Locate_DevNodeW = modcfgmgr32.NewProc("CM_Locate_DevNodeW") procLogonUserW = modadvapi32.NewProc("LogonUserW")
procCM_Get_DevNode_PropertyW = modcfgmgr32.NewProc("CM_Get_DevNode_PropertyW") procRtlMoveMemory = modkernel32.NewProc("RtlMoveMemory")
procNtCreateFile = modntdll.NewProc("NtCreateFile") procLocalAlloc = modkernel32.NewProc("LocalAlloc")
procNtSetInformationFile = modntdll.NewProc("NtSetInformationFile") procLocalFree = modkernel32.NewProc("LocalFree")
procNtOpenDirectoryObject = modntdll.NewProc("NtOpenDirectoryObject") procQueryWorkingSet = modpsapi.NewProc("QueryWorkingSet")
procNtQueryDirectoryObject = modntdll.NewProc("NtQueryDirectoryObject") procGetProcessImageFileNameW = modkernel32.NewProc("GetProcessImageFileNameW")
procRtlNtStatusToDosError = modntdll.NewProc("RtlNtStatusToDosError") procGetActiveProcessorCount = modkernel32.NewProc("GetActiveProcessorCount")
procCM_Get_Device_ID_List_SizeA = modcfgmgr32.NewProc("CM_Get_Device_ID_List_SizeA")
procCM_Get_Device_ID_ListA = modcfgmgr32.NewProc("CM_Get_Device_ID_ListA")
procCM_Locate_DevNodeW = modcfgmgr32.NewProc("CM_Locate_DevNodeW")
procCM_Get_DevNode_PropertyW = modcfgmgr32.NewProc("CM_Get_DevNode_PropertyW")
procNtCreateFile = modntdll.NewProc("NtCreateFile")
procNtSetInformationFile = modntdll.NewProc("NtSetInformationFile")
procNtOpenDirectoryObject = modntdll.NewProc("NtOpenDirectoryObject")
procNtQueryDirectoryObject = modntdll.NewProc("NtQueryDirectoryObject")
procRtlNtStatusToDosError = modntdll.NewProc("RtlNtStatusToDosError")
) )
func NtQuerySystemInformation(systemInfoClass int, systemInformation uintptr, systemInfoLength uint32, returnLength *uint32) (status uint32) {
r0, _, _ := syscall.Syscall6(procNtQuerySystemInformation.Addr(), 4, uintptr(systemInfoClass), uintptr(systemInformation), uintptr(systemInfoLength), uintptr(unsafe.Pointer(returnLength)), 0, 0)
status = uint32(r0)
return
}
func SetJobCompartmentId(handle windows.Handle, compartmentId uint32) (win32Err error) {
r0, _, _ := syscall.Syscall(procSetJobCompartmentId.Addr(), 2, uintptr(handle), uintptr(compartmentId), 0)
if r0 != 0 {
win32Err = syscall.Errno(r0)
}
return
}
func SearchPath(lpPath *uint16, lpFileName *uint16, lpExtension *uint16, nBufferLength uint32, lpBuffer *uint16, lpFilePath *uint16) (size uint32, err error) {
r0, _, e1 := syscall.Syscall6(procSearchPathW.Addr(), 6, uintptr(unsafe.Pointer(lpPath)), uintptr(unsafe.Pointer(lpFileName)), uintptr(unsafe.Pointer(lpExtension)), uintptr(nBufferLength), uintptr(unsafe.Pointer(lpBuffer)), uintptr(unsafe.Pointer(lpFilePath)))
size = uint32(r0)
if size == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func CreateRemoteThread(process windows.Handle, sa *windows.SecurityAttributes, stackSize uint32, startAddr uintptr, parameter uintptr, creationFlags uint32, threadID *uint32) (handle windows.Handle, err error) {
r0, _, e1 := syscall.Syscall9(procCreateRemoteThread.Addr(), 7, uintptr(process), uintptr(unsafe.Pointer(sa)), uintptr(stackSize), uintptr(startAddr), uintptr(parameter), uintptr(creationFlags), uintptr(unsafe.Pointer(threadID)), 0, 0)
handle = windows.Handle(r0)
if handle == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func GetQueuedCompletionStatus(cphandle windows.Handle, qty *uint32, key *uintptr, overlapped **windows.Overlapped, timeout uint32) (err error) {
r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0)
if r1 == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func IsProcessInJob(procHandle windows.Handle, jobHandle windows.Handle, result *bool) (err error) { func IsProcessInJob(procHandle windows.Handle, jobHandle windows.Handle, result *bool) (err error) {
r1, _, e1 := syscall.Syscall(procIsProcessInJob.Addr(), 3, uintptr(procHandle), uintptr(jobHandle), uintptr(unsafe.Pointer(result))) r1, _, e1 := syscall.Syscall(procIsProcessInJob.Addr(), 3, uintptr(procHandle), uintptr(jobHandle), uintptr(unsafe.Pointer(result)))
if r1 == 0 { if r1 == 0 {
@ -119,10 +182,10 @@ func SetIoRateControlInformationJobObject(jobHandle windows.Handle, ioRateContro
return return
} }
func SearchPath(lpPath *uint16, lpFileName *uint16, lpExtension *uint16, nBufferLength uint32, lpBuffer *uint16, lpFilePath **uint16) (size uint32, err error) { func QueryIoRateControlInformationJobObject(jobHandle windows.Handle, volumeName *uint16, ioRateControlInfo **JOBOBJECT_IO_RATE_CONTROL_INFORMATION, infoBlockCount *uint32) (ret uint32, err error) {
r0, _, e1 := syscall.Syscall6(procSearchPathW.Addr(), 6, uintptr(unsafe.Pointer(lpPath)), uintptr(unsafe.Pointer(lpFileName)), uintptr(unsafe.Pointer(lpExtension)), uintptr(nBufferLength), uintptr(unsafe.Pointer(lpBuffer)), uintptr(unsafe.Pointer(lpFilePath))) r0, _, e1 := syscall.Syscall6(procQueryIoRateControlInformationJobObject.Addr(), 4, uintptr(jobHandle), uintptr(unsafe.Pointer(volumeName)), uintptr(unsafe.Pointer(ioRateControlInfo)), uintptr(unsafe.Pointer(infoBlockCount)), 0, 0)
size = uint32(r0) ret = uint32(r0)
if size == 0 { if ret == 0 {
if e1 != 0 { if e1 != 0 {
err = errnoErr(e1) err = errnoErr(e1)
} else { } else {
@ -132,6 +195,18 @@ func SearchPath(lpPath *uint16, lpFileName *uint16, lpExtension *uint16, nBuffer
return return
} }
func NtOpenJobObject(jobHandle *windows.Handle, desiredAccess uint32, objAttributes *ObjectAttributes) (status uint32) {
r0, _, _ := syscall.Syscall(procNtOpenJobObject.Addr(), 3, uintptr(unsafe.Pointer(jobHandle)), uintptr(desiredAccess), uintptr(unsafe.Pointer(objAttributes)))
status = uint32(r0)
return
}
func NtCreateJobObject(jobHandle *windows.Handle, desiredAccess uint32, objAttributes *ObjectAttributes) (status uint32) {
r0, _, _ := syscall.Syscall(procNtCreateJobObject.Addr(), 3, uintptr(unsafe.Pointer(jobHandle)), uintptr(desiredAccess), uintptr(unsafe.Pointer(objAttributes)))
status = uint32(r0)
return
}
func LogonUser(username *uint16, domain *uint16, password *uint16, logonType uint32, logonProvider uint32, token *windows.Token) (err error) { func LogonUser(username *uint16, domain *uint16, password *uint16, logonType uint32, logonProvider uint32, token *windows.Token) (err error) {
r1, _, e1 := syscall.Syscall6(procLogonUserW.Addr(), 6, uintptr(unsafe.Pointer(username)), uintptr(unsafe.Pointer(domain)), uintptr(unsafe.Pointer(password)), uintptr(logonType), uintptr(logonProvider), uintptr(unsafe.Pointer(token))) r1, _, e1 := syscall.Syscall6(procLogonUserW.Addr(), 6, uintptr(unsafe.Pointer(username)), uintptr(unsafe.Pointer(domain)), uintptr(unsafe.Pointer(password)), uintptr(logonType), uintptr(logonProvider), uintptr(unsafe.Pointer(token)))
if r1 == 0 { if r1 == 0 {
@ -167,6 +242,31 @@ func LocalFree(ptr uintptr) {
return return
} }
func QueryWorkingSet(handle windows.Handle, pv uintptr, cb uint32) (err error) {
r1, _, e1 := syscall.Syscall(procQueryWorkingSet.Addr(), 3, uintptr(handle), uintptr(pv), uintptr(cb))
if r1 == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func GetProcessImageFileName(hProcess windows.Handle, imageFileName *uint16, nSize uint32) (size uint32, err error) {
r0, _, e1 := syscall.Syscall(procGetProcessImageFileNameW.Addr(), 3, uintptr(hProcess), uintptr(unsafe.Pointer(imageFileName)), uintptr(nSize))
size = uint32(r0)
if size == 0 {
if e1 != 0 {
err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
}
return
}
func GetActiveProcessorCount(groupNumber uint16) (amount uint32) { func GetActiveProcessorCount(groupNumber uint16) (amount uint32) {
r0, _, _ := syscall.Syscall(procGetActiveProcessorCount.Addr(), 1, uintptr(groupNumber), 0, 0) r0, _, _ := syscall.Syscall(procGetActiveProcessorCount.Addr(), 1, uintptr(groupNumber), 0, 0)
amount = uint32(r0) amount = uint32(r0)

View file

@ -15,21 +15,6 @@ type OSVersion struct {
Build uint16 Build uint16
} }
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
type osVersionInfoEx struct {
OSVersionInfoSize uint32
MajorVersion uint32
MinorVersion uint32
BuildNumber uint32
PlatformID uint32
CSDVersion [128]uint16
ServicePackMajor uint16
ServicePackMinor uint16
SuiteMask uint16
ProductType byte
Reserve byte
}
// Get gets the operating system version on Windows. // Get gets the operating system version on Windows.
// The calling application must be manifested to get the correct version information. // The calling application must be manifested to get the correct version information.
func Get() OSVersion { func Get() OSVersion {

View file

@ -32,4 +32,7 @@ const (
// V20H1 (version 2004) corresponds to Windows Server 2004 (semi-annual // V20H1 (version 2004) corresponds to Windows Server 2004 (semi-annual
// channel). // channel).
V20H1 = 19041 V20H1 = 19041
// V20H2 corresponds to Windows Server 20H2 (semi-annual channel).
V20H2 = 19042
) )