mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #22958 from Microsoft/hcs_rpc
Windows: Use the new HCS RPC API
This commit is contained in:
commit
c7ee503082
16 changed files with 2123 additions and 235 deletions
|
@ -43,7 +43,7 @@ esac
|
|||
|
||||
# the following lines are in sorted order, FYI
|
||||
clone git github.com/Azure/go-ansiterm 388960b655244e76e24c75f48631564eaefade62
|
||||
clone git github.com/Microsoft/hcsshim v0.2.2
|
||||
clone git github.com/Microsoft/hcsshim v0.3.0
|
||||
clone git github.com/Microsoft/go-winio v0.3.4
|
||||
clone git github.com/Sirupsen/logrus v0.10.0 # logrus is a common dependency among multiple deps
|
||||
clone git github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package libcontainerd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -29,76 +28,6 @@ const (
|
|||
ErrorInvalidObject = syscall.Errno(0x800710D8) // The object identifier does not represent a valid object
|
||||
)
|
||||
|
||||
type layer struct {
|
||||
ID string
|
||||
Path string
|
||||
}
|
||||
|
||||
type defConfig struct {
|
||||
DefFile string
|
||||
}
|
||||
|
||||
type portBinding struct {
|
||||
Protocol string
|
||||
InternalPort int
|
||||
ExternalPort int
|
||||
}
|
||||
|
||||
type natSettings struct {
|
||||
Name string
|
||||
PortBindings []portBinding
|
||||
}
|
||||
|
||||
type networkConnection struct {
|
||||
NetworkName string
|
||||
Nat natSettings
|
||||
}
|
||||
type networkSettings struct {
|
||||
MacAddress string
|
||||
}
|
||||
|
||||
type device struct {
|
||||
DeviceType string
|
||||
Connection interface{}
|
||||
Settings interface{}
|
||||
}
|
||||
|
||||
type mappedDir struct {
|
||||
HostPath string
|
||||
ContainerPath string
|
||||
ReadOnly bool
|
||||
}
|
||||
|
||||
type hvRuntime struct {
|
||||
ImagePath string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// TODO Windows: @darrenstahlmsft Add ProcessorCount
|
||||
type containerInit struct {
|
||||
SystemType string // HCS requires this to be hard-coded to "Container"
|
||||
Name string // Name of the container. We use the docker ID.
|
||||
Owner string // The management platform that created this container
|
||||
IsDummy bool // Used for development purposes.
|
||||
VolumePath string // Windows volume path for scratch space
|
||||
Devices []device // Devices used by the container
|
||||
IgnoreFlushesDuringBoot bool // Optimization hint for container startup in Windows
|
||||
LayerFolderPath string // Where the layer folders are located
|
||||
Layers []layer // List of storage layers
|
||||
ProcessorWeight uint64 `json:",omitempty"` // CPU Shares 0..10000 on Windows; where 0 will be omitted and HCS will default.
|
||||
ProcessorMaximum int64 `json:",omitempty"` // CPU maximum usage percent 1..100
|
||||
StorageIOPSMaximum uint64 `json:",omitempty"` // Maximum Storage IOPS
|
||||
StorageBandwidthMaximum uint64 `json:",omitempty"` // Maximum Storage Bandwidth in bytes per second
|
||||
StorageSandboxSize uint64 `json:",omitempty"` // Size in bytes that the container system drive should be expanded to if smaller
|
||||
MemoryMaximumInMB int64 `json:",omitempty"` // Maximum memory available to the container in Megabytes
|
||||
HostName string // Hostname
|
||||
MappedDirectories []mappedDir // List of mapped directories (volumes/mounts)
|
||||
SandboxPath string // Location of unmounted sandbox (used for Hyper-V containers)
|
||||
HvPartition bool // True if it a Hyper-V Container
|
||||
EndpointList []string // List of networking endpoints to be attached to container
|
||||
HvRuntime *hvRuntime // Hyper-V container settings
|
||||
Servicing bool // True if this container is for servicing
|
||||
}
|
||||
|
||||
// defaultOwner is a tag passed to HCS to allow it to differentiate between
|
||||
// container creator management stacks. We hard code "docker" in the case
|
||||
// of docker.
|
||||
|
@ -109,7 +38,7 @@ const defaultOwner = "docker"
|
|||
func (clnt *client) Create(containerID string, spec Spec, options ...CreateOption) error {
|
||||
logrus.Debugln("LCD client.Create() with spec", spec)
|
||||
|
||||
cu := &containerInit{
|
||||
configuration := &hcsshim.ContainerConfig{
|
||||
SystemType: "Container",
|
||||
Name: containerID,
|
||||
Owner: defaultOwner,
|
||||
|
@ -121,55 +50,55 @@ func (clnt *client) Create(containerID string, spec Spec, options ...CreateOptio
|
|||
}
|
||||
|
||||
if spec.Windows.Networking != nil {
|
||||
cu.EndpointList = spec.Windows.Networking.EndpointList
|
||||
configuration.EndpointList = spec.Windows.Networking.EndpointList
|
||||
}
|
||||
|
||||
if spec.Windows.Resources != nil {
|
||||
if spec.Windows.Resources.CPU != nil {
|
||||
if spec.Windows.Resources.CPU.Shares != nil {
|
||||
cu.ProcessorWeight = *spec.Windows.Resources.CPU.Shares
|
||||
configuration.ProcessorWeight = *spec.Windows.Resources.CPU.Shares
|
||||
}
|
||||
if spec.Windows.Resources.CPU.Percent != nil {
|
||||
cu.ProcessorMaximum = *spec.Windows.Resources.CPU.Percent * 100 // ProcessorMaximum is a value between 1 and 10000
|
||||
configuration.ProcessorMaximum = *spec.Windows.Resources.CPU.Percent * 100 // ProcessorMaximum is a value between 1 and 10000
|
||||
}
|
||||
}
|
||||
if spec.Windows.Resources.Memory != nil {
|
||||
if spec.Windows.Resources.Memory.Limit != nil {
|
||||
cu.MemoryMaximumInMB = *spec.Windows.Resources.Memory.Limit / 1024 / 1024
|
||||
configuration.MemoryMaximumInMB = *spec.Windows.Resources.Memory.Limit / 1024 / 1024
|
||||
}
|
||||
}
|
||||
if spec.Windows.Resources.Storage != nil {
|
||||
if spec.Windows.Resources.Storage.Bps != nil {
|
||||
cu.StorageBandwidthMaximum = *spec.Windows.Resources.Storage.Bps
|
||||
configuration.StorageBandwidthMaximum = *spec.Windows.Resources.Storage.Bps
|
||||
}
|
||||
if spec.Windows.Resources.Storage.Iops != nil {
|
||||
cu.StorageIOPSMaximum = *spec.Windows.Resources.Storage.Iops
|
||||
configuration.StorageIOPSMaximum = *spec.Windows.Resources.Storage.Iops
|
||||
}
|
||||
if spec.Windows.Resources.Storage.SandboxSize != nil {
|
||||
cu.StorageSandboxSize = *spec.Windows.Resources.Storage.SandboxSize
|
||||
configuration.StorageSandboxSize = *spec.Windows.Resources.Storage.SandboxSize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if spec.Windows.HvRuntime != nil {
|
||||
cu.HvPartition = true
|
||||
cu.HvRuntime = &hvRuntime{
|
||||
configuration.HvPartition = true
|
||||
configuration.HvRuntime = &hcsshim.HvRuntime{
|
||||
ImagePath: spec.Windows.HvRuntime.ImagePath,
|
||||
}
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
if s, ok := option.(*ServicingOption); ok {
|
||||
cu.Servicing = s.IsServicing
|
||||
break
|
||||
}
|
||||
if configuration.HvPartition {
|
||||
configuration.SandboxPath = filepath.Dir(spec.Windows.LayerFolder)
|
||||
} else {
|
||||
configuration.VolumePath = spec.Root.Path
|
||||
configuration.LayerFolderPath = spec.Windows.LayerFolder
|
||||
}
|
||||
|
||||
if cu.HvPartition {
|
||||
cu.SandboxPath = filepath.Dir(spec.Windows.LayerFolder)
|
||||
} else {
|
||||
cu.VolumePath = spec.Root.Path
|
||||
cu.LayerFolderPath = spec.Windows.LayerFolder
|
||||
for _, option := range options {
|
||||
if s, ok := option.(*ServicingOption); ok {
|
||||
configuration.Servicing = s.IsServicing
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, layerPath := range spec.Windows.LayerPaths {
|
||||
|
@ -178,33 +107,27 @@ func (clnt *client) Create(containerID string, spec Spec, options ...CreateOptio
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cu.Layers = append(cu.Layers, layer{
|
||||
configuration.Layers = append(configuration.Layers, hcsshim.Layer{
|
||||
ID: g.ToString(),
|
||||
Path: layerPath,
|
||||
})
|
||||
}
|
||||
|
||||
// Add the mounts (volumes, bind mounts etc) to the structure
|
||||
mds := make([]mappedDir, len(spec.Mounts))
|
||||
mds := make([]hcsshim.MappedDir, len(spec.Mounts))
|
||||
for i, mount := range spec.Mounts {
|
||||
mds[i] = mappedDir{
|
||||
mds[i] = hcsshim.MappedDir{
|
||||
HostPath: mount.Source,
|
||||
ContainerPath: mount.Destination,
|
||||
ReadOnly: mount.Readonly}
|
||||
}
|
||||
cu.MappedDirectories = mds
|
||||
configuration.MappedDirectories = mds
|
||||
|
||||
configurationb, err := json.Marshal(cu)
|
||||
hcsContainer, err := hcsshim.CreateContainer(containerID, configuration)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create the compute system
|
||||
configuration := string(configurationb)
|
||||
if err := hcsshim.CreateComputeSystem(containerID, configuration); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Construct a container object for calling start on it.
|
||||
container := &container{
|
||||
containerCommon: containerCommon{
|
||||
|
@ -218,7 +141,8 @@ func (clnt *client) Create(containerID string, spec Spec, options ...CreateOptio
|
|||
},
|
||||
processes: make(map[string]*process),
|
||||
},
|
||||
ociSpec: spec,
|
||||
ociSpec: spec,
|
||||
hcsContainer: hcsContainer,
|
||||
}
|
||||
|
||||
container.options = options
|
||||
|
@ -252,10 +176,17 @@ func (clnt *client) AddProcess(containerID, processFriendlyName string, procToAd
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
createProcessParms := hcsshim.CreateProcessParams{
|
||||
EmulateConsole: procToAdd.Terminal,
|
||||
ConsoleSize: procToAdd.InitialConsoleSize,
|
||||
// Note we always tell HCS to
|
||||
// create stdout as it's required regardless of '-i' or '-t' options, so that
|
||||
// docker can always grab the output through logs. We also tell HCS to always
|
||||
// create stdin, even if it's not used - it will be closed shortly. Stderr
|
||||
// is only created if it we're not -t.
|
||||
createProcessParms := hcsshim.ProcessConfig{
|
||||
EmulateConsole: procToAdd.Terminal,
|
||||
ConsoleSize: procToAdd.InitialConsoleSize,
|
||||
CreateStdInPipe: true,
|
||||
CreateStdOutPipe: true,
|
||||
CreateStdErrPipe: !procToAdd.Terminal,
|
||||
}
|
||||
|
||||
// Take working directory from the process to add if it is defined,
|
||||
|
@ -272,25 +203,24 @@ func (clnt *client) AddProcess(containerID, processFriendlyName string, procToAd
|
|||
|
||||
logrus.Debugf("commandLine: %s", createProcessParms.CommandLine)
|
||||
|
||||
// Start the command running in the container. Note we always tell HCS to
|
||||
// create stdout as it's required regardless of '-i' or '-t' options, so that
|
||||
// docker can always grab the output through logs. We also tell HCS to always
|
||||
// create stdin, even if it's not used - it will be closed shortly. Stderr
|
||||
// is only created if it we're not -t.
|
||||
// Start the command running in the container.
|
||||
var stdout, stderr io.ReadCloser
|
||||
var pid uint32
|
||||
iopipe := &IOPipe{Terminal: procToAdd.Terminal}
|
||||
pid, iopipe.Stdin, stdout, stderr, err = hcsshim.CreateProcessInComputeSystem(
|
||||
containerID,
|
||||
true,
|
||||
true,
|
||||
!procToAdd.Terminal,
|
||||
createProcessParms)
|
||||
var stdin io.WriteCloser
|
||||
newProcess, err := container.hcsContainer.CreateProcess(&createProcessParms)
|
||||
if err != nil {
|
||||
logrus.Errorf("AddProcess %s CreateProcessInComputeSystem() failed %s", containerID, err)
|
||||
logrus.Errorf("AddProcess %s CreateProcess() failed %s", containerID, err)
|
||||
return err
|
||||
}
|
||||
|
||||
stdin, stdout, stderr, err = newProcess.Stdio()
|
||||
if err != nil {
|
||||
logrus.Errorf("%s getting std pipes failed %s", containerID, err)
|
||||
return err
|
||||
}
|
||||
|
||||
iopipe := &IOPipe{Terminal: procToAdd.Terminal}
|
||||
iopipe.Stdin = createStdInCloser(stdin, newProcess)
|
||||
|
||||
// TEMP: Work around Windows BS/DEL behavior.
|
||||
iopipe.Stdin = fixStdinBackspaceBehavior(iopipe.Stdin, procToAdd.Terminal)
|
||||
|
||||
|
@ -302,17 +232,21 @@ func (clnt *client) AddProcess(containerID, processFriendlyName string, procToAd
|
|||
iopipe.Stderr = openReaderFromPipe(stderr)
|
||||
}
|
||||
|
||||
// Add the process to the containers list of processes
|
||||
container.processes[processFriendlyName] =
|
||||
&process{
|
||||
processCommon: processCommon{
|
||||
containerID: containerID,
|
||||
friendlyName: processFriendlyName,
|
||||
client: clnt,
|
||||
systemPid: pid,
|
||||
},
|
||||
commandLine: createProcessParms.CommandLine,
|
||||
}
|
||||
pid := newProcess.Pid()
|
||||
|
||||
proc := &process{
|
||||
processCommon: processCommon{
|
||||
containerID: containerID,
|
||||
friendlyName: processFriendlyName,
|
||||
client: clnt,
|
||||
systemPid: uint32(pid),
|
||||
},
|
||||
commandLine: createProcessParms.CommandLine,
|
||||
hcsProcess: newProcess,
|
||||
}
|
||||
|
||||
// Add the process to the container's list of processes
|
||||
container.processes[processFriendlyName] = proc
|
||||
|
||||
// Make sure the lock is not held while calling back into the daemon
|
||||
clnt.unlock(containerID)
|
||||
|
@ -326,7 +260,7 @@ func (clnt *client) AddProcess(containerID, processFriendlyName string, procToAd
|
|||
clnt.lock(containerID)
|
||||
|
||||
// Spin up a go routine waiting for exit to handle cleanup
|
||||
go container.waitExit(pid, processFriendlyName, false)
|
||||
go container.waitExit(proc, false)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -350,16 +284,17 @@ func (clnt *client) Signal(containerID string, sig int) error {
|
|||
cont.manualStopRequested = true
|
||||
|
||||
logrus.Debugf("lcd: Signal() containerID=%s sig=%d pid=%d", containerID, sig, cont.systemPid)
|
||||
context := fmt.Sprintf("Signal: sig=%d pid=%d", sig, cont.systemPid)
|
||||
|
||||
if syscall.Signal(sig) == syscall.SIGKILL {
|
||||
// Terminate the compute system
|
||||
if err := hcsshim.TerminateComputeSystem(containerID, hcsshim.TimeoutInfinite, context); err != nil {
|
||||
logrus.Errorf("Failed to terminate %s - %q", containerID, err)
|
||||
if err := cont.hcsContainer.Terminate(); err != nil {
|
||||
if err != hcsshim.ErrVmcomputeOperationPending {
|
||||
logrus.Errorf("Failed to terminate %s - %q", containerID, err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Terminate Process
|
||||
if err = hcsshim.TerminateProcessInComputeSystem(containerID, cont.systemPid); err != nil {
|
||||
if err := cont.hcsProcess.Kill(); err != nil {
|
||||
logrus.Warnf("Failed to terminate pid %d in %s: %q", cont.systemPid, containerID, err)
|
||||
// Ignore errors
|
||||
err = nil
|
||||
|
@ -380,15 +315,17 @@ func (clnt *client) Resize(containerID, processFriendlyName string, width, heigh
|
|||
return err
|
||||
}
|
||||
|
||||
h, w := uint16(height), uint16(width)
|
||||
|
||||
if processFriendlyName == InitFriendlyName {
|
||||
logrus.Debugln("Resizing systemPID in", containerID, cont.process.systemPid)
|
||||
return hcsshim.ResizeConsoleInComputeSystem(containerID, cont.process.systemPid, height, width)
|
||||
return cont.process.hcsProcess.ResizeConsole(w, h)
|
||||
}
|
||||
|
||||
for _, p := range cont.processes {
|
||||
if p.friendlyName == processFriendlyName {
|
||||
logrus.Debugln("Resizing exec'd process", containerID, p.systemPid)
|
||||
return hcsshim.ResizeConsoleInComputeSystem(containerID, p.systemPid, height, width)
|
||||
return p.hcsProcess.ResizeConsole(w, h)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ type container struct {
|
|||
ociSpec Spec
|
||||
|
||||
manualStopRequested bool
|
||||
hcsContainer hcsshim.Container
|
||||
}
|
||||
|
||||
func (ctr *container) newProcess(friendlyName string) *process {
|
||||
|
@ -40,7 +41,7 @@ func (ctr *container) start() error {
|
|||
// Start the container. If this is a servicing container, this call will block
|
||||
// until the container is done with the servicing execution.
|
||||
logrus.Debugln("Starting container ", ctr.containerID)
|
||||
if err = hcsshim.StartComputeSystem(ctr.containerID); err != nil {
|
||||
if err = ctr.hcsContainer.Start(); err != nil {
|
||||
logrus.Errorf("Failed to start compute system: %s", err)
|
||||
return err
|
||||
}
|
||||
|
@ -49,59 +50,61 @@ func (ctr *container) start() error {
|
|||
if s, ok := option.(*ServicingOption); ok && s.IsServicing {
|
||||
// Since the servicing operation is complete when StartCommputeSystem returns without error,
|
||||
// we can shutdown (which triggers merge) and exit early.
|
||||
const shutdownTimeout = 5 * 60 * 1000 // 4 minutes
|
||||
const terminateTimeout = 1 * 60 * 1000 // 1 minute
|
||||
if err := hcsshim.ShutdownComputeSystem(ctr.containerID, shutdownTimeout, ""); err != nil {
|
||||
logrus.Errorf("Failed during cleanup of servicing container: %s", err)
|
||||
// Terminate the container, ignoring errors.
|
||||
if err2 := hcsshim.TerminateComputeSystem(ctr.containerID, terminateTimeout, ""); err2 != nil {
|
||||
logrus.Errorf("Failed to terminate container %s after shutdown failure: %q", ctr.containerID, err2)
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return ctr.shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
createProcessParms := hcsshim.CreateProcessParams{
|
||||
// Note we always tell HCS to
|
||||
// create stdout as it's required regardless of '-i' or '-t' options, so that
|
||||
// docker can always grab the output through logs. We also tell HCS to always
|
||||
// create stdin, even if it's not used - it will be closed shortly. Stderr
|
||||
// is only created if it we're not -t.
|
||||
createProcessParms := &hcsshim.ProcessConfig{
|
||||
EmulateConsole: ctr.ociSpec.Process.Terminal,
|
||||
WorkingDirectory: ctr.ociSpec.Process.Cwd,
|
||||
ConsoleSize: ctr.ociSpec.Process.InitialConsoleSize,
|
||||
CreateStdInPipe: true,
|
||||
CreateStdOutPipe: true,
|
||||
CreateStdErrPipe: !ctr.ociSpec.Process.Terminal,
|
||||
}
|
||||
|
||||
// Configure the environment for the process
|
||||
createProcessParms.Environment = setupEnvironmentVariables(ctr.ociSpec.Process.Env)
|
||||
createProcessParms.CommandLine = strings.Join(ctr.ociSpec.Process.Args, " ")
|
||||
|
||||
iopipe := &IOPipe{Terminal: ctr.ociSpec.Process.Terminal}
|
||||
|
||||
// Start the command running in the container. Note we always tell HCS to
|
||||
// create stdout as it's required regardless of '-i' or '-t' options, so that
|
||||
// docker can always grab the output through logs. We also tell HCS to always
|
||||
// create stdin, even if it's not used - it will be closed shortly. Stderr
|
||||
// is only created if it we're not -t.
|
||||
var pid uint32
|
||||
var stdout, stderr io.ReadCloser
|
||||
pid, iopipe.Stdin, stdout, stderr, err = hcsshim.CreateProcessInComputeSystem(
|
||||
ctr.containerID,
|
||||
true,
|
||||
true,
|
||||
!ctr.ociSpec.Process.Terminal,
|
||||
createProcessParms)
|
||||
// Start the command running in the container.
|
||||
hcsProcess, err := ctr.hcsContainer.CreateProcess(createProcessParms)
|
||||
if err != nil {
|
||||
logrus.Errorf("CreateProcessInComputeSystem() failed %s", err)
|
||||
|
||||
// Explicitly terminate the compute system here.
|
||||
if err2 := hcsshim.TerminateComputeSystem(ctr.containerID, hcsshim.TimeoutInfinite, "CreateProcessInComputeSystem failed"); err2 != nil {
|
||||
// Ignore this error, there's not a lot we can do except log it
|
||||
logrus.Warnf("Failed to TerminateComputeSystem after a failed CreateProcessInComputeSystem. Ignoring this.", err2)
|
||||
logrus.Errorf("CreateProcess() failed %s", err)
|
||||
if err2 := ctr.terminate(); err2 != nil {
|
||||
logrus.Debugf("Failed to cleanup after a failed CreateProcess. Ignoring this. %s", err2)
|
||||
} else {
|
||||
logrus.Debugln("Cleaned up after failed CreateProcessInComputeSystem by calling TerminateComputeSystem")
|
||||
logrus.Debugln("Cleaned up after failed CreateProcess by calling Terminate")
|
||||
}
|
||||
return err
|
||||
}
|
||||
ctr.startedAt = time.Now()
|
||||
|
||||
// Save the hcs Process and PID
|
||||
ctr.process.friendlyName = InitFriendlyName
|
||||
pid := hcsProcess.Pid()
|
||||
ctr.process.hcsProcess = hcsProcess
|
||||
|
||||
var stdout, stderr io.ReadCloser
|
||||
var stdin io.WriteCloser
|
||||
stdin, stdout, stderr, err = hcsProcess.Stdio()
|
||||
if err != nil {
|
||||
logrus.Errorf("failed to get stdio pipes: %s", err)
|
||||
if err := ctr.terminate(); err != nil {
|
||||
logrus.Debugf("Failed to cleanup after a failed CreateProcess. Ignoring this. %s", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
iopipe := &IOPipe{Terminal: ctr.ociSpec.Process.Terminal}
|
||||
|
||||
iopipe.Stdin = createStdInCloser(stdin, hcsProcess)
|
||||
|
||||
// TEMP: Work around Windows BS/DEL behavior.
|
||||
iopipe.Stdin = fixStdinBackspaceBehavior(iopipe.Stdin, ctr.ociSpec.Process.Terminal)
|
||||
|
||||
|
@ -118,7 +121,7 @@ func (ctr *container) start() error {
|
|||
ctr.systemPid = uint32(pid)
|
||||
|
||||
// Spin up a go routine waiting for exit to handle cleanup
|
||||
go ctr.waitExit(pid, InitFriendlyName, true)
|
||||
go ctr.waitExit(&ctr.process, true)
|
||||
|
||||
ctr.client.appendContainer(ctr)
|
||||
|
||||
|
@ -140,17 +143,27 @@ func (ctr *container) start() error {
|
|||
// waitExit runs as a goroutine waiting for the process to exit. It's
|
||||
// equivalent to (in the linux containerd world) where events come in for
|
||||
// state change notifications from containerd.
|
||||
func (ctr *container) waitExit(pid uint32, processFriendlyName string, isFirstProcessToStart bool) error {
|
||||
logrus.Debugln("waitExit on pid", pid)
|
||||
func (ctr *container) waitExit(process *process, isFirstProcessToStart bool) error {
|
||||
logrus.Debugln("waitExit on pid", process.systemPid)
|
||||
|
||||
// Block indefinitely for the process to exit.
|
||||
exitCode, err := hcsshim.WaitForProcessInComputeSystem(ctr.containerID, pid, hcsshim.TimeoutInfinite)
|
||||
err := process.hcsProcess.Wait()
|
||||
if err != nil {
|
||||
if herr, ok := err.(*hcsshim.HcsError); ok && herr.Err != syscall.ERROR_BROKEN_PIPE {
|
||||
if herr, ok := err.(*hcsshim.ProcessError); ok && herr.Err != syscall.ERROR_BROKEN_PIPE {
|
||||
logrus.Warnf("WaitForProcessInComputeSystem failed (container may have been killed): %s", err)
|
||||
}
|
||||
// Fall through here, do not return. This ensures we attempt to continue the
|
||||
// shutdown in HCS nad tell the docker engine that the process/container
|
||||
// shutdown in HCS and tell the docker engine that the process/container
|
||||
// has exited to avoid a container being dropped on the floor.
|
||||
}
|
||||
|
||||
exitCode, err := process.hcsProcess.ExitCode()
|
||||
if err != nil {
|
||||
if herr, ok := err.(*hcsshim.ProcessError); ok && herr.Err != syscall.ERROR_BROKEN_PIPE {
|
||||
logrus.Warnf("Unable to get exit code from container %s", ctr.containerID)
|
||||
}
|
||||
// Fall through here, do not return. This ensures we attempt to continue the
|
||||
// shutdown in HCS and tell the docker engine that the process/container
|
||||
// has exited to avoid a container being dropped on the floor.
|
||||
}
|
||||
|
||||
|
@ -159,46 +172,35 @@ func (ctr *container) waitExit(pid uint32, processFriendlyName string, isFirstPr
|
|||
CommonStateInfo: CommonStateInfo{
|
||||
State: StateExit,
|
||||
ExitCode: uint32(exitCode),
|
||||
Pid: pid,
|
||||
ProcessID: processFriendlyName,
|
||||
Pid: process.systemPid,
|
||||
ProcessID: process.friendlyName,
|
||||
},
|
||||
UpdatePending: false,
|
||||
}
|
||||
|
||||
// But it could have been an exec'd process which exited
|
||||
if !isFirstProcessToStart {
|
||||
if err := process.hcsProcess.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
si.State = StateExitProcess
|
||||
} else {
|
||||
// Since this is the init process, always call into vmcompute.dll to
|
||||
// shutdown the container after we have completed.
|
||||
|
||||
propertyCheckFlag := 1 // Include update pending check.
|
||||
csProperties, err := hcsshim.GetComputeSystemProperties(ctr.containerID, uint32(propertyCheckFlag))
|
||||
updatePending, err := ctr.hcsContainer.HasPendingUpdates()
|
||||
if err != nil {
|
||||
logrus.Warnf("GetComputeSystemProperties failed (container may have been killed): %s", err)
|
||||
logrus.Warnf("HasPendingUpdates failed (container may have been killed): %s", err)
|
||||
} else {
|
||||
si.UpdatePending = csProperties.AreUpdatesPending
|
||||
si.UpdatePending = updatePending
|
||||
}
|
||||
|
||||
logrus.Debugf("Shutting down container %s", ctr.containerID)
|
||||
// Explicit timeout here rather than hcsshim.TimeoutInfinte to avoid a
|
||||
// (remote) possibility that ShutdownComputeSystem hangs indefinitely.
|
||||
const shutdownTimeout = 5 * 60 * 1000 // 5 minutes
|
||||
if err := hcsshim.ShutdownComputeSystem(ctr.containerID, shutdownTimeout, "waitExit"); err != nil {
|
||||
if herr, ok := err.(*hcsshim.HcsError); !ok ||
|
||||
(herr.Err != hcsshim.ERROR_SHUTDOWN_IN_PROGRESS &&
|
||||
herr.Err != ErrorBadPathname &&
|
||||
herr.Err != syscall.ERROR_PATH_NOT_FOUND) {
|
||||
logrus.Debugf("waitExit - error from ShutdownComputeSystem on %s %v. Calling TerminateComputeSystem", ctr.containerCommon, err)
|
||||
if err := hcsshim.TerminateComputeSystem(ctr.containerID, shutdownTimeout, "waitExit"); err != nil {
|
||||
logrus.Debugf("waitExit - ignoring error from TerminateComputeSystem %s %v", ctr.containerID, err)
|
||||
} else {
|
||||
logrus.Debugf("Successful TerminateComputeSystem after failed ShutdownComputeSystem on %s in waitExit", ctr.containerID)
|
||||
}
|
||||
}
|
||||
if err := ctr.shutdown(); err != nil {
|
||||
logrus.Debugf("Failed to shutdown container %s", ctr.containerID)
|
||||
} else {
|
||||
logrus.Debugf("Completed shutting down container %s", ctr.containerID)
|
||||
}
|
||||
if err := ctr.hcsContainer.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
|
||||
if !ctr.manualStopRequested && ctr.restartManager != nil {
|
||||
restart, wait, err := ctr.restartManager.ShouldRestart(uint32(exitCode), false, time.Since(ctr.startedAt))
|
||||
|
@ -227,6 +229,9 @@ func (ctr *container) waitExit(pid uint32, processFriendlyName string, isFirstPr
|
|||
// Remove process from list if we have exited
|
||||
// We need to do so here in case the Message Handler decides to restart it.
|
||||
if si.State == StateExit {
|
||||
if err := ctr.hcsContainer.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
ctr.client.deleteContainer(ctr.friendlyName)
|
||||
}
|
||||
}
|
||||
|
@ -240,3 +245,37 @@ func (ctr *container) waitExit(pid uint32, processFriendlyName string, isFirstPr
|
|||
logrus.Debugln("waitExit() completed OK")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ctr *container) shutdown() error {
|
||||
const shutdownTimeout = time.Minute * 5
|
||||
err := ctr.hcsContainer.Shutdown()
|
||||
if err == hcsshim.ErrVmcomputeOperationPending {
|
||||
// Explicit timeout to avoid a (remote) possibility that shutdown hangs indefinitely.
|
||||
err = ctr.hcsContainer.WaitTimeout(shutdownTimeout)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logrus.Debugf("error shutting down container %s %v calling terminate", ctr.containerID, err)
|
||||
if err := ctr.terminate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ctr *container) terminate() error {
|
||||
const terminateTimeout = time.Minute * 5
|
||||
err := ctr.hcsContainer.Terminate()
|
||||
|
||||
if err == hcsshim.ErrVmcomputeOperationPending {
|
||||
err = ctr.hcsContainer.WaitTimeout(terminateTimeout)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package libcontainerd
|
|||
import (
|
||||
"io"
|
||||
|
||||
"github.com/Microsoft/hcsshim"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
)
|
||||
|
||||
|
@ -14,6 +15,7 @@ type process struct {
|
|||
|
||||
// commandLine is to support returning summary information for docker top
|
||||
commandLine string
|
||||
hcsProcess hcsshim.Process
|
||||
}
|
||||
|
||||
func openReaderFromPipe(p io.ReadCloser) io.Reader {
|
||||
|
@ -57,3 +59,27 @@ func (w *delToBsWriter) Write(b []byte) (int, error) {
|
|||
}
|
||||
return w.WriteCloser.Write(bc)
|
||||
}
|
||||
|
||||
type stdInCloser struct {
|
||||
io.WriteCloser
|
||||
hcsshim.Process
|
||||
}
|
||||
|
||||
func createStdInCloser(pipe io.WriteCloser, process hcsshim.Process) *stdInCloser {
|
||||
return &stdInCloser{
|
||||
WriteCloser: pipe,
|
||||
Process: process,
|
||||
}
|
||||
}
|
||||
|
||||
func (stdin *stdInCloser) Close() error {
|
||||
if err := stdin.WriteCloser.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return stdin.Process.CloseStdin()
|
||||
}
|
||||
|
||||
func (stdin *stdInCloser) Write(p []byte) (n int, err error) {
|
||||
return stdin.WriteCloser.Write(p)
|
||||
}
|
||||
|
|
|
@ -62,20 +62,17 @@ func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err e
|
|||
}
|
||||
}()
|
||||
|
||||
err = winio.RunWithPrivileges([]string{winio.SeBackupPrivilege, winio.SeRestorePrivilege}, func() (err error) {
|
||||
createmode := uint32(syscall.CREATE_NEW)
|
||||
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
|
||||
err := os.Mkdir(path, 0)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
createmode = syscall.OPEN_EXISTING
|
||||
createmode := uint32(syscall.CREATE_NEW)
|
||||
if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
|
||||
err := os.Mkdir(path, 0)
|
||||
if err != nil && !os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
createmode = syscall.OPEN_EXISTING
|
||||
}
|
||||
|
||||
mode := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | winio.WRITE_DAC | winio.WRITE_OWNER | winio.ACCESS_SYSTEM_SECURITY)
|
||||
f, err = winio.OpenForBackup(path, mode, syscall.FILE_SHARE_READ, createmode)
|
||||
return
|
||||
})
|
||||
mode := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | winio.WRITE_DAC | winio.WRITE_OWNER | winio.ACCESS_SYSTEM_SECURITY)
|
||||
f, err = winio.OpenForBackup(path, mode, syscall.FILE_SHARE_READ, createmode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -113,9 +110,7 @@ func (w *baseLayerWriter) AddLink(name string, target string) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
return winio.RunWithPrivileges([]string{winio.SeBackupPrivilege, winio.SeRestorePrivilege}, func() (err error) {
|
||||
return os.Link(linktarget, linkpath)
|
||||
})
|
||||
return os.Link(linktarget, linkpath)
|
||||
}
|
||||
|
||||
func (w *baseLayerWriter) Remove(name string) error {
|
||||
|
@ -123,11 +118,7 @@ func (w *baseLayerWriter) Remove(name string) error {
|
|||
}
|
||||
|
||||
func (w *baseLayerWriter) Write(b []byte) (int, error) {
|
||||
var n int
|
||||
err := winio.RunWithPrivileges([]string{winio.SeBackupPrivilege, winio.SeRestorePrivilege}, func() (err error) {
|
||||
n, err = w.bw.Write(b)
|
||||
return
|
||||
})
|
||||
n, err := w.bw.Write(b)
|
||||
if err != nil {
|
||||
w.err = err
|
||||
}
|
||||
|
|
78
vendor/src/github.com/Microsoft/hcsshim/callback.go
vendored
Normal file
78
vendor/src/github.com/Microsoft/hcsshim/callback.go
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
package hcsshim
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
nextCallback uintptr
|
||||
callbackMap = map[uintptr]*notifcationWatcherContext{}
|
||||
callbackMapLock = sync.RWMutex{}
|
||||
|
||||
notificationWatcherCallback = syscall.NewCallback(notificationWatcher)
|
||||
|
||||
// Notifications for HCS_SYSTEM handles
|
||||
hcsNotificationSystemExited hcsNotification = 0x00000001
|
||||
hcsNotificationSystemCreateCompleted hcsNotification = 0x00000002
|
||||
hcsNotificationSystemStartCompleted hcsNotification = 0x00000003
|
||||
hcsNotificationSystemPauseCompleted hcsNotification = 0x00000004
|
||||
hcsNotificationSystemResumeCompleted hcsNotification = 0x00000005
|
||||
|
||||
// Notifications for HCS_PROCESS handles
|
||||
hcsNotificationProcessExited hcsNotification = 0x00010000
|
||||
|
||||
// Common notifications
|
||||
hcsNotificationInvalid hcsNotification = 0x00000000
|
||||
hcsNotificationServiceDisconnect hcsNotification = 0x01000000
|
||||
|
||||
// ErrUnexpectedContainerExit is the error returned when a container exits while waiting for
|
||||
// a different expected notification
|
||||
ErrUnexpectedContainerExit = errors.New("unexpected container exit")
|
||||
|
||||
// ErrUnexpectedProcessAbort is the error returned when communication with the compute service
|
||||
// is lost while waiting for a notification
|
||||
ErrUnexpectedProcessAbort = errors.New("lost communication with compute service")
|
||||
)
|
||||
|
||||
type hcsNotification uint32
|
||||
type notificationChannel chan error
|
||||
|
||||
type notifcationWatcherContext struct {
|
||||
channel notificationChannel
|
||||
expectedNotification hcsNotification
|
||||
handle hcsCallback
|
||||
}
|
||||
|
||||
func notificationWatcher(notificationType hcsNotification, callbackNumber uintptr, notificationStatus uintptr, notificationData *uint16) uintptr {
|
||||
var (
|
||||
result error
|
||||
completeWait = false
|
||||
)
|
||||
|
||||
callbackMapLock.RLock()
|
||||
context := callbackMap[callbackNumber]
|
||||
callbackMapLock.RUnlock()
|
||||
|
||||
if notificationType == context.expectedNotification {
|
||||
if int32(notificationStatus) < 0 {
|
||||
result = syscall.Errno(win32FromHresult(notificationStatus))
|
||||
} else {
|
||||
result = nil
|
||||
}
|
||||
completeWait = true
|
||||
} else if notificationType == hcsNotificationSystemExited {
|
||||
result = ErrUnexpectedContainerExit
|
||||
completeWait = true
|
||||
} else if notificationType == hcsNotificationServiceDisconnect {
|
||||
result = ErrUnexpectedProcessAbort
|
||||
completeWait = true
|
||||
}
|
||||
|
||||
if completeWait {
|
||||
context.channel <- result
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
513
vendor/src/github.com/Microsoft/hcsshim/container.go
vendored
Normal file
513
vendor/src/github.com/Microsoft/hcsshim/container.go
vendored
Normal file
|
@ -0,0 +1,513 @@
|
|||
package hcsshim
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultTimeout = time.Minute * 4
|
||||
|
||||
// ErrTimeout is an error encountered when waiting on a notification times out
|
||||
ErrTimeout = errors.New("hcsshim: timeout waiting for notification")
|
||||
)
|
||||
|
||||
type ContainerError struct {
|
||||
Container *container
|
||||
Operation string
|
||||
ExtraInfo string
|
||||
Err error
|
||||
}
|
||||
|
||||
type container struct {
|
||||
handle hcsSystem
|
||||
id string
|
||||
}
|
||||
|
||||
type containerProperties struct {
|
||||
ID string `json:"Id"`
|
||||
Name string
|
||||
SystemType string
|
||||
Owner string
|
||||
SiloGUID string `json:"SiloGuid,omitempty"`
|
||||
IsDummy bool `json:",omitempty"`
|
||||
RuntimeID string `json:"RuntimeId,omitempty"`
|
||||
Stopped bool `json:",omitempty"`
|
||||
ExitType string `json:",omitempty"`
|
||||
AreUpdatesPending bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
// CreateContainer creates a new container with the given configuration but does not start it.
|
||||
func CreateContainer(id string, c *ContainerConfig) (Container, error) {
|
||||
operation := "CreateContainer"
|
||||
title := "HCSShim::" + operation
|
||||
logrus.Debugf(title+" id=%s", id)
|
||||
|
||||
container := &container{
|
||||
id: id,
|
||||
}
|
||||
|
||||
configurationb, err := json.Marshal(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
configuration := string(configurationb)
|
||||
|
||||
var (
|
||||
handle hcsSystem
|
||||
resultp *uint16
|
||||
createError error
|
||||
)
|
||||
if hcsCallbacksSupported {
|
||||
var identity syscall.Handle
|
||||
createError = hcsCreateComputeSystem(id, configuration, identity, &handle, &resultp)
|
||||
} else {
|
||||
createError = hcsCreateComputeSystemTP5(id, configuration, &handle, &resultp)
|
||||
}
|
||||
container.handle = handle
|
||||
|
||||
err = processAsyncHcsResult(container, createError, resultp, hcsNotificationSystemCreateCompleted, &defaultTimeout)
|
||||
if err != nil {
|
||||
err := &ContainerError{Container: container, Operation: operation, ExtraInfo: configuration, Err: err}
|
||||
logrus.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded id=%s handle=%d", id, container.handle)
|
||||
runtime.SetFinalizer(container, closeContainer)
|
||||
return container, nil
|
||||
}
|
||||
|
||||
// OpenContainer opens an existing container by ID.
|
||||
func OpenContainer(id string) (Container, error) {
|
||||
operation := "OpenContainer"
|
||||
title := "HCSShim::" + operation
|
||||
logrus.Debugf(title+" id=%s", id)
|
||||
|
||||
container := &container{
|
||||
id: id,
|
||||
}
|
||||
|
||||
var (
|
||||
handle hcsSystem
|
||||
resultp *uint16
|
||||
)
|
||||
err := hcsOpenComputeSystem(id, &handle, &resultp)
|
||||
err = processHcsResult(err, resultp)
|
||||
if err != nil {
|
||||
err = &ContainerError{Container: container, Operation: operation, Err: err}
|
||||
logrus.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
container.handle = handle
|
||||
|
||||
logrus.Debugf(title+" succeeded id=%s handle=%d", id, handle)
|
||||
runtime.SetFinalizer(container, closeContainer)
|
||||
return container, nil
|
||||
}
|
||||
|
||||
// Start synchronously starts the container.
|
||||
func (container *container) Start() error {
|
||||
operation := "Start"
|
||||
title := "HCSShim::Container::" + operation
|
||||
logrus.Debugf(title+" id=%s", container.id)
|
||||
|
||||
var resultp *uint16
|
||||
err := hcsStartComputeSystemTP5(container.handle, nil, &resultp)
|
||||
err = processAsyncHcsResult(container, err, resultp, hcsNotificationSystemStartCompleted, &defaultTimeout)
|
||||
if err != nil {
|
||||
err := &ContainerError{Container: container, Operation: operation, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded id=%s", container.id)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shutdown requests a container shutdown, but it may not actually be shut down until Wait() succeeds.
|
||||
// It returns ErrVmcomputeOperationPending if the shutdown is in progress, nil if the shutdown is complete.
|
||||
func (container *container) Shutdown() error {
|
||||
operation := "Shutdown"
|
||||
title := "HCSShim::Container::" + operation
|
||||
logrus.Debugf(title+" id=%s", container.id)
|
||||
|
||||
var resultp *uint16
|
||||
err := hcsShutdownComputeSystemTP5(container.handle, nil, &resultp)
|
||||
err = processHcsResult(err, resultp)
|
||||
if err != nil {
|
||||
if err == ErrVmcomputeOperationPending {
|
||||
return ErrVmcomputeOperationPending
|
||||
}
|
||||
err = &ContainerError{Container: container, Operation: operation, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded id=%s", container.id)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Terminate requests a container terminate, but it may not actually be terminated until Wait() succeeds.
|
||||
// It returns ErrVmcomputeOperationPending if the shutdown is in progress, nil if the shutdown is complete.
|
||||
func (container *container) Terminate() error {
|
||||
operation := "Terminate"
|
||||
title := "HCSShim::Container::" + operation
|
||||
logrus.Debugf(title+" id=%s", container.id)
|
||||
|
||||
var resultp *uint16
|
||||
err := hcsTerminateComputeSystemTP5(container.handle, nil, &resultp)
|
||||
err = processHcsResult(err, resultp)
|
||||
if err != nil {
|
||||
if err == ErrVmcomputeOperationPending {
|
||||
return ErrVmcomputeOperationPending
|
||||
}
|
||||
err = &ContainerError{Container: container, Operation: operation, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded id=%s", container.id)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Wait synchronously waits for the container to shutdown or terminate.
|
||||
func (container *container) Wait() error {
|
||||
operation := "Wait"
|
||||
title := "HCSShim::Container::" + operation
|
||||
logrus.Debugf(title+" id=%s", container.id)
|
||||
|
||||
if hcsCallbacksSupported {
|
||||
err := registerAndWaitForCallback(container, hcsNotificationSystemExited)
|
||||
if err != nil {
|
||||
err := &ContainerError{Container: container, Operation: operation, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
_, err := container.waitTimeoutInternal(syscall.INFINITE)
|
||||
if err != nil {
|
||||
err := &ContainerError{Container: container, Operation: operation, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded id=%s", container.id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (container *container) waitTimeoutInternal(timeout uint32) (bool, error) {
|
||||
return waitTimeoutInternalHelper(container, timeout)
|
||||
}
|
||||
|
||||
// WaitTimeout synchronously waits for the container to terminate or the duration to elapse. It returns
|
||||
// ErrTimeout if the timeout duration expires before the container is shut down.
|
||||
func (container *container) WaitTimeout(timeout time.Duration) error {
|
||||
operation := "WaitTimeout"
|
||||
title := "HCSShim::Container::" + operation
|
||||
logrus.Debugf(title+" id=%s", container.id)
|
||||
|
||||
if hcsCallbacksSupported {
|
||||
err := registerAndWaitForCallbackTimeout(container, hcsNotificationSystemExited, timeout)
|
||||
if err == ErrTimeout {
|
||||
return ErrTimeout
|
||||
} else if err != nil {
|
||||
err := &ContainerError{Container: container, Operation: operation, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
finished, err := waitTimeoutHelper(container, timeout)
|
||||
if !finished {
|
||||
return ErrTimeout
|
||||
} else if err != nil {
|
||||
err := &ContainerError{Container: container, Operation: operation, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded id=%s", container.id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (container *container) hcsWait(timeout uint32) (bool, error) {
|
||||
var (
|
||||
resultp *uint16
|
||||
exitEvent syscall.Handle
|
||||
)
|
||||
|
||||
err := hcsCreateComputeSystemWait(container.handle, &exitEvent, &resultp)
|
||||
err = processHcsResult(err, resultp)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer syscall.CloseHandle(exitEvent)
|
||||
|
||||
return waitForSingleObject(exitEvent, timeout)
|
||||
}
|
||||
|
||||
func (container *container) properties() (*containerProperties, error) {
|
||||
var (
|
||||
resultp *uint16
|
||||
propertiesp *uint16
|
||||
)
|
||||
err := hcsGetComputeSystemProperties(container.handle, "", &propertiesp, &resultp)
|
||||
err = processHcsResult(err, resultp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if propertiesp == nil {
|
||||
return nil, errors.New("Unexpected result from hcsGetComputeSystemProperties, properties should never be nil")
|
||||
}
|
||||
propertiesRaw := convertAndFreeCoTaskMemBytes(propertiesp)
|
||||
|
||||
properties := &containerProperties{}
|
||||
if err := json.Unmarshal(propertiesRaw, properties); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return properties, nil
|
||||
}
|
||||
|
||||
// HasPendingUpdates returns true if the container has updates pending to install
|
||||
func (container *container) HasPendingUpdates() (bool, error) {
|
||||
operation := "HasPendingUpdates"
|
||||
title := "HCSShim::Container::" + operation
|
||||
logrus.Debugf(title+" id=%s", container.id)
|
||||
properties, err := container.properties()
|
||||
if err != nil {
|
||||
err := &ContainerError{Container: container, Operation: operation, Err: err}
|
||||
logrus.Error(err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded id=%s", container.id)
|
||||
return properties.AreUpdatesPending, nil
|
||||
}
|
||||
|
||||
// Pause pauses the execution of the container. This feature is not enabled in TP5.
|
||||
func (container *container) Pause() error {
|
||||
operation := "Pause"
|
||||
title := "HCSShim::Container::" + operation
|
||||
logrus.Debugf(title+" id=%s", container.id)
|
||||
|
||||
var resultp *uint16
|
||||
err := hcsPauseComputeSystemTP5(container.handle, nil, &resultp)
|
||||
err = processAsyncHcsResult(container, err, resultp, hcsNotificationSystemPauseCompleted, &defaultTimeout)
|
||||
if err != nil {
|
||||
err := &ContainerError{Container: container, Operation: operation, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded id=%s", container.id)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Resume resumes the execution of the container. This feature is not enabled in TP5.
|
||||
func (container *container) Resume() error {
|
||||
operation := "Resume"
|
||||
title := "HCSShim::Container::" + operation
|
||||
logrus.Debugf(title+" id=%s", container.id)
|
||||
var (
|
||||
resultp *uint16
|
||||
)
|
||||
|
||||
err := hcsResumeComputeSystemTP5(container.handle, nil, &resultp)
|
||||
err = processAsyncHcsResult(container, err, resultp, hcsNotificationSystemResumeCompleted, &defaultTimeout)
|
||||
if err != nil {
|
||||
err := &ContainerError{Container: container, Operation: operation, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded id=%s", container.id)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateProcess launches a new process within the container.
|
||||
func (container *container) CreateProcess(c *ProcessConfig) (Process, error) {
|
||||
operation := "CreateProcess"
|
||||
title := "HCSShim::Container::" + operation
|
||||
logrus.Debugf(title+" id=%s", container.id)
|
||||
var (
|
||||
processInfo hcsProcessInformation
|
||||
processHandle hcsProcess
|
||||
resultp *uint16
|
||||
)
|
||||
|
||||
// If we are not emulating a console, ignore any console size passed to us
|
||||
if !c.EmulateConsole {
|
||||
c.ConsoleSize[0] = 0
|
||||
c.ConsoleSize[1] = 0
|
||||
}
|
||||
|
||||
configurationb, err := json.Marshal(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
configuration := string(configurationb)
|
||||
|
||||
err = hcsCreateProcess(container.handle, configuration, &processInfo, &processHandle, &resultp)
|
||||
err = processHcsResult(err, resultp)
|
||||
if err != nil {
|
||||
err = &ContainerError{Container: container, Operation: operation, ExtraInfo: configuration, Err: err}
|
||||
logrus.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
process := &process{
|
||||
handle: processHandle,
|
||||
processID: int(processInfo.ProcessId),
|
||||
container: container,
|
||||
cachedPipes: &cachedPipes{
|
||||
stdIn: processInfo.StdInput,
|
||||
stdOut: processInfo.StdOutput,
|
||||
stdErr: processInfo.StdError,
|
||||
},
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded id=%s processid=%s", container.id, process.processID)
|
||||
runtime.SetFinalizer(process, closeProcess)
|
||||
return process, nil
|
||||
}
|
||||
|
||||
// OpenProcess gets an interface to an existing process within the container.
|
||||
func (container *container) OpenProcess(pid int) (Process, error) {
|
||||
operation := "OpenProcess"
|
||||
title := "HCSShim::Container::" + operation
|
||||
logrus.Debugf(title+" id=%s, processid=%d", container.id, pid)
|
||||
var (
|
||||
processHandle hcsProcess
|
||||
resultp *uint16
|
||||
)
|
||||
|
||||
err := hcsOpenProcess(container.handle, uint32(pid), &processHandle, &resultp)
|
||||
err = processHcsResult(err, resultp)
|
||||
if err != nil {
|
||||
err = &ContainerError{Container: container, Operation: operation, Err: err}
|
||||
logrus.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
process := &process{
|
||||
handle: processHandle,
|
||||
processID: pid,
|
||||
container: container,
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded id=%s processid=%s", container.id, process.processID)
|
||||
runtime.SetFinalizer(process, closeProcess)
|
||||
return process, nil
|
||||
}
|
||||
|
||||
// Close cleans up any state associated with the container but does not terminate or wait for it.
|
||||
func (container *container) Close() error {
|
||||
operation := "Close"
|
||||
title := "HCSShim::Container::" + operation
|
||||
logrus.Debugf(title+" id=%s", container.id)
|
||||
|
||||
// Don't double free this
|
||||
if container.handle == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := hcsCloseComputeSystem(container.handle); err != nil {
|
||||
err = &ContainerError{Container: container, Operation: operation, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
container.handle = 0
|
||||
|
||||
logrus.Debugf(title+" succeeded id=%s", container.id)
|
||||
return nil
|
||||
}
|
||||
|
||||
// closeContainer wraps container.Close for use by a finalizer
|
||||
func closeContainer(container *container) {
|
||||
container.Close()
|
||||
}
|
||||
|
||||
func (container *container) registerCallback(expectedNotification hcsNotification) (uintptr, error) {
|
||||
callbackMapLock.Lock()
|
||||
defer callbackMapLock.Unlock()
|
||||
|
||||
callbackNumber := nextCallback
|
||||
nextCallback++
|
||||
|
||||
context := ¬ifcationWatcherContext{
|
||||
expectedNotification: expectedNotification,
|
||||
channel: make(chan error, 1),
|
||||
}
|
||||
callbackMap[callbackNumber] = context
|
||||
|
||||
var callbackHandle hcsCallback
|
||||
err := hcsRegisterComputeSystemCallback(container.handle, notificationWatcherCallback, callbackNumber, &callbackHandle)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
context.handle = callbackHandle
|
||||
|
||||
return callbackNumber, nil
|
||||
}
|
||||
|
||||
func (container *container) unregisterCallback(callbackNumber uintptr) error {
|
||||
callbackMapLock.Lock()
|
||||
defer callbackMapLock.Unlock()
|
||||
|
||||
handle := callbackMap[callbackNumber].handle
|
||||
|
||||
if handle == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := hcsUnregisterComputeSystemCallback(handle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
callbackMap[callbackNumber] = nil
|
||||
|
||||
handle = 0
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *ContainerError) Error() string {
|
||||
if e == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
|
||||
if e.Container == nil {
|
||||
return "unexpected nil container for error: " + e.Err.Error()
|
||||
}
|
||||
|
||||
s := "container " + e.Container.id
|
||||
|
||||
if e.Operation != "" {
|
||||
s += " encountered an error during " + e.Operation
|
||||
}
|
||||
|
||||
if e.Err != nil {
|
||||
s += fmt.Sprintf(" failed in Win32: %s (0x%x)", e.Err, win32FromError(e.Err))
|
||||
}
|
||||
|
||||
if e.ExtraInfo != "" {
|
||||
s += " extra info: " + e.ExtraInfo
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
|
@ -112,7 +112,9 @@ func (r *FilterLayerReader) Close() (err error) {
|
|||
}
|
||||
|
||||
// NewLayerReader returns a new layer reader for reading the contents of an on-disk layer.
|
||||
func NewLayerReader(info DriverInfo, layerId string, parentLayerPaths []string) (LayerReader, error) {
|
||||
// The caller must have taken the SeBackupPrivilege privilege
|
||||
// to call this and any methods on the resulting LayerReader.
|
||||
func NewLayerReader(info DriverInfo, layerID string, parentLayerPaths []string) (LayerReader, error) {
|
||||
if procExportLayerBegin.Find() != nil {
|
||||
// The new layer reader is not available on this Windows build. Fall back to the
|
||||
// legacy export code path.
|
||||
|
@ -120,7 +122,7 @@ func NewLayerReader(info DriverInfo, layerId string, parentLayerPaths []string)
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = ExportLayer(info, layerId, path, parentLayerPaths)
|
||||
err = ExportLayer(info, layerID, path, parentLayerPaths)
|
||||
if err != nil {
|
||||
os.RemoveAll(path)
|
||||
return nil, err
|
||||
|
@ -137,7 +139,7 @@ func NewLayerReader(info DriverInfo, layerId string, parentLayerPaths []string)
|
|||
return nil, err
|
||||
}
|
||||
r := &FilterLayerReader{}
|
||||
err = exportLayerBegin(&infop, layerId, layers, &r.context)
|
||||
err = exportLayerBegin(&infop, layerID, layers, &r.context)
|
||||
if err != nil {
|
||||
return nil, makeError(err, "ExportLayerBegin", "")
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import (
|
|||
"fmt"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
//go:generate go run mksyscall_windows.go -output zhcsshim.go hcsshim.go
|
||||
|
@ -50,6 +52,40 @@ import (
|
|||
//sys waitForProcessInComputeSystem(id string, pid uint32, timeout uint32, exitCode *uint32) (hr error) = vmcompute.WaitForProcessInComputeSystem?
|
||||
//sys getComputeSystemProperties(id string, flags uint32, properties **uint16) (hr error) = vmcompute.GetComputeSystemProperties?
|
||||
|
||||
//sys hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) = vmcompute.HcsEnumerateComputeSystems?
|
||||
//sys hcsCreateComputeSystem(id string, configuration string, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsCreateComputeSystem?
|
||||
//sys hcsOpenComputeSystem(id string, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsOpenComputeSystem?
|
||||
//sys hcsCloseComputeSystem(computeSystem hcsSystem) (hr error) = vmcompute.HcsCloseComputeSystem?
|
||||
//sys hcsStartComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsStartComputeSystem?
|
||||
//sys hcsShutdownComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsShutdownComputeSystem?
|
||||
//sys hcsTerminateComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsTerminateComputeSystem?
|
||||
//sys hcsPauseComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsPauseComputeSystem?
|
||||
//sys hcsResumeComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsResumeComputeSystem?
|
||||
//sys hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetComputeSystemProperties?
|
||||
//sys hcsModifyComputeSystem(computeSystem hcsSystem, configuration string, result **uint16) (hr error) = vmcompute.HcsModifyComputeSystem?
|
||||
//sys hcsCreateComputeSystemWait(computeSystem hcsSystem, exitEvent *syscall.Handle, result **uint16) (hr error) = vmcompute.HcsCreateComputeSystemWait?
|
||||
//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 hcsCloseProcess(process hcsProcess) (hr error) = vmcompute.HcsCloseProcess?
|
||||
//sys hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) = vmcompute.HcsTerminateProcess?
|
||||
//sys hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) = vmcompute.HcsGetProcessInfo?
|
||||
//sys hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) = vmcompute.HcsGetProcessProperties?
|
||||
//sys hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) = vmcompute.HcsModifyProcess?
|
||||
//sys hcsCreateProcessWait(process hcsProcess, settings *syscall.Handle, result **uint16) (hr error) = vmcompute.HcsCreateProcessWait?
|
||||
//sys hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetServiceProperties?
|
||||
//sys hcsModifyServiceSettings(settings string, result **uint16) (hr error) = vmcompute.HcsModifyServiceSettings?
|
||||
|
||||
//sys hcsCreateComputeSystemTP5(id string, configuration string, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsCreateComputeSystem?
|
||||
//sys hcsStartComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) = vmcompute.HcsStartComputeSystem?
|
||||
//sys hcsShutdownComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) = vmcompute.HcsShutdownComputeSystem?
|
||||
//sys hcsTerminateComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) = vmcompute.HcsTerminateComputeSystem?
|
||||
//sys hcsPauseComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) = vmcompute.HcsPauseComputeSystem?
|
||||
//sys hcsResumeComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) = vmcompute.HcsResumeComputeSystem?
|
||||
//sys hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterComputeSystemCallback?
|
||||
//sys hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterComputeSystemCallback?
|
||||
//sys hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterProcessCallback?
|
||||
//sys hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterProcessCallback?
|
||||
|
||||
//sys _hnsCall(method string, path string, object string, response **uint16) (hr error) = vmcompute.HNSCall?
|
||||
|
||||
const (
|
||||
|
@ -60,6 +96,8 @@ const (
|
|||
ERROR_SHUTDOWN_IN_PROGRESS = syscall.Errno(1115)
|
||||
WSAEINVAL = syscall.Errno(10022)
|
||||
|
||||
ErrVmcomputeOperationPending = syscall.Errno(0xC0370103)
|
||||
|
||||
// Timeout on wait calls
|
||||
TimeoutInfinite = 0xFFFFFFFF
|
||||
)
|
||||
|
@ -70,6 +108,18 @@ type HcsError struct {
|
|||
Err error
|
||||
}
|
||||
|
||||
type hcsSystem syscall.Handle
|
||||
type hcsProcess syscall.Handle
|
||||
type hcsCallback syscall.Handle
|
||||
|
||||
type hcsProcessInformation struct {
|
||||
ProcessId uint32
|
||||
Reserved uint32
|
||||
StdInput syscall.Handle
|
||||
StdOutput syscall.Handle
|
||||
StdError syscall.Handle
|
||||
}
|
||||
|
||||
func makeError(err error, title, rest string) error {
|
||||
// Pass through DLL errors directly since they do not originate from HCS.
|
||||
if _, ok := err.(*syscall.DLLError); ok {
|
||||
|
@ -119,3 +169,15 @@ func convertAndFreeCoTaskMemString(buffer *uint16) string {
|
|||
coTaskMemFree(unsafe.Pointer(buffer))
|
||||
return str
|
||||
}
|
||||
|
||||
func convertAndFreeCoTaskMemBytes(buffer *uint16) []byte {
|
||||
return []byte(convertAndFreeCoTaskMemString(buffer))
|
||||
}
|
||||
|
||||
func processHcsResult(err error, resultp *uint16) error {
|
||||
if resultp != nil {
|
||||
result := convertAndFreeCoTaskMemString(resultp)
|
||||
logrus.Debugf("Result: %s", result)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -148,6 +148,8 @@ func (r *legacyLayerWriterWrapper) Close() error {
|
|||
}
|
||||
|
||||
// NewLayerWriter returns a new layer writer for creating a layer on disk.
|
||||
// The caller must have taken the SeBackupPrivilege and SeRestorePrivilege privileges
|
||||
// to call this and any methods on the resulting LayerWriter.
|
||||
func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string) (LayerWriter, error) {
|
||||
if len(parentLayerPaths) == 0 {
|
||||
// This is a base layer. It gets imported differently.
|
||||
|
|
147
vendor/src/github.com/Microsoft/hcsshim/interface.go
vendored
Normal file
147
vendor/src/github.com/Microsoft/hcsshim/interface.go
vendored
Normal file
|
@ -0,0 +1,147 @@
|
|||
package hcsshim
|
||||
|
||||
import (
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ProcessConfig is used as both the input of Container.CreateProcess
|
||||
// and to convert the parameters to JSON for passing onto the HCS
|
||||
type ProcessConfig struct {
|
||||
ApplicationName string
|
||||
CommandLine string
|
||||
WorkingDirectory string
|
||||
Environment map[string]string
|
||||
EmulateConsole bool
|
||||
CreateStdInPipe bool
|
||||
CreateStdOutPipe bool
|
||||
CreateStdErrPipe bool
|
||||
ConsoleSize [2]int
|
||||
}
|
||||
|
||||
type Layer struct {
|
||||
ID string
|
||||
Path string
|
||||
}
|
||||
|
||||
type MappedDir struct {
|
||||
HostPath string
|
||||
ContainerPath string
|
||||
ReadOnly bool
|
||||
}
|
||||
|
||||
type HvRuntime struct {
|
||||
ImagePath string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// ContainerConfig is used as both the input of CreateContainer
|
||||
// and to convert the parameters to JSON for passing onto the HCS
|
||||
// TODO Windows: @darrenstahlmsft Add ProcessorCount
|
||||
type ContainerConfig struct {
|
||||
SystemType string // HCS requires this to be hard-coded to "Container"
|
||||
Name string // Name of the container. We use the docker ID.
|
||||
Owner string // The management platform that created this container
|
||||
IsDummy bool // Used for development purposes.
|
||||
VolumePath string // Windows volume path for scratch space
|
||||
IgnoreFlushesDuringBoot bool // Optimization hint for container startup in Windows
|
||||
LayerFolderPath string // Where the layer folders are located
|
||||
Layers []Layer // List of storage layers
|
||||
ProcessorWeight uint64 `json:",omitempty"` // CPU Shares 0..10000 on Windows; where 0 will be omitted and HCS will default.
|
||||
ProcessorMaximum int64 `json:",omitempty"` // CPU maximum usage percent 1..100
|
||||
StorageIOPSMaximum uint64 `json:",omitempty"` // Maximum Storage IOPS
|
||||
StorageBandwidthMaximum uint64 `json:",omitempty"` // Maximum Storage Bandwidth in bytes per second
|
||||
StorageSandboxSize uint64 `json:",omitempty"` // Size in bytes that the container system drive should be expanded to if smaller
|
||||
MemoryMaximumInMB int64 `json:",omitempty"` // Maximum memory available to the container in Megabytes
|
||||
HostName string // Hostname
|
||||
MappedDirectories []MappedDir // List of mapped directories (volumes/mounts)
|
||||
SandboxPath string // Location of unmounted sandbox (used for Hyper-V containers)
|
||||
HvPartition bool // True if it a Hyper-V Container
|
||||
EndpointList []string // List of networking endpoints to be attached to container
|
||||
HvRuntime *HvRuntime // Hyper-V container settings
|
||||
Servicing bool // True if this container is for servicing
|
||||
}
|
||||
|
||||
const (
|
||||
notificationTypeNone string = "None"
|
||||
notificationTypeGracefulExit string = "GracefulExit"
|
||||
notificationTypeForcedExit string = "ForcedExit"
|
||||
notificationTypeUnexpectedExit string = "UnexpectedExit"
|
||||
notificationTypeReboot string = "Reboot"
|
||||
notificationTypeConstructed string = "Constructed"
|
||||
notificationTypeStarted string = "Started"
|
||||
notificationTypePaused string = "Paused"
|
||||
notificationTypeUnknown string = "Unknown"
|
||||
)
|
||||
|
||||
// Container represents a created (but not necessarily running) container.
|
||||
type Container interface {
|
||||
// Start synchronously starts the container.
|
||||
Start() error
|
||||
|
||||
// Shutdown requests a container shutdown, but it may not actually be shutdown until Wait() succeeds.
|
||||
Shutdown() error
|
||||
|
||||
// Terminate requests a container terminate, but it may not actually be terminated until Wait() succeeds.
|
||||
Terminate() error
|
||||
|
||||
// Waits synchronously waits for the container to shutdown or terminate.
|
||||
Wait() error
|
||||
|
||||
// WaitTimeout synchronously waits for the container to terminate or the duration to elapse. It
|
||||
// returns false if timeout occurs.
|
||||
WaitTimeout(time.Duration) error
|
||||
|
||||
// Pause pauses the execution of a container.
|
||||
Pause() error
|
||||
|
||||
// Resume resumes the execution of a container.
|
||||
Resume() error
|
||||
|
||||
// HasPendingUpdates returns true if the container has updates pending to install.
|
||||
HasPendingUpdates() (bool, error)
|
||||
|
||||
// CreateProcess launches a new process within the container.
|
||||
CreateProcess(c *ProcessConfig) (Process, error)
|
||||
|
||||
// OpenProcess gets an interface to an existing process within the container.
|
||||
OpenProcess(pid int) (Process, error)
|
||||
|
||||
// Close cleans up any state associated with the container but does not terminate or wait for it.
|
||||
Close() error
|
||||
}
|
||||
|
||||
// Process represents a running or exited process.
|
||||
type Process interface {
|
||||
// Pid returns the process ID of the process within the container.
|
||||
Pid() int
|
||||
|
||||
// Kill signals the process to terminate but does not wait for it to finish terminating.
|
||||
Kill() error
|
||||
|
||||
// Wait waits for the process to exit.
|
||||
Wait() error
|
||||
|
||||
// WaitTimeout waits for the process to exit or the duration to elapse. It returns
|
||||
// false if timeout occurs.
|
||||
WaitTimeout(time.Duration) error
|
||||
|
||||
// ExitCode returns the exit code of the process. The process must have
|
||||
// already terminated.
|
||||
ExitCode() (int, error)
|
||||
|
||||
// ResizeConsole resizes the console of the process.
|
||||
ResizeConsole(width, height uint16) error
|
||||
|
||||
// Stdio returns the stdin, stdout, and stderr pipes, respectively. Closing
|
||||
// these pipes does not close the underlying pipes; it should be possible to
|
||||
// call this multiple times to get multiple interfaces.
|
||||
Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, error)
|
||||
|
||||
// CloseStdin closes the write side of the stdin pipe so that the process is
|
||||
// notified on the read side that there is no more data in stdin.
|
||||
CloseStdin() error
|
||||
|
||||
// Close cleans up any state associated with the process but does not kill
|
||||
// or wait on it.
|
||||
Close() error
|
||||
}
|
|
@ -598,6 +598,19 @@ func (f *Fn) HasStringParam() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
var uniqDllFuncName = make(map[string]bool)
|
||||
|
||||
// IsNotDuplicate is true if f is not a duplicated function
|
||||
func (f *Fn) IsNotDuplicate() bool {
|
||||
funcName := f.DLLFuncName()
|
||||
if uniqDllFuncName[funcName] == false {
|
||||
uniqDllFuncName[funcName] = true
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// HelperName returns name of function f helper.
|
||||
func (f *Fn) HelperName() string {
|
||||
if !f.HasStringParam() {
|
||||
|
@ -748,6 +761,7 @@ const srcTemplate = `
|
|||
|
||||
package {{packagename}}
|
||||
|
||||
import "github.com/Microsoft/go-winio"
|
||||
import "unsafe"{{if syscalldot}}
|
||||
import "syscall"{{end}}
|
||||
|
||||
|
@ -764,7 +778,7 @@ var (
|
|||
{{define "dlls"}}{{range .DLLs}} mod{{.}} = {{syscalldot}}NewLazyDLL("{{.}}.dll")
|
||||
{{end}}{{end}}
|
||||
|
||||
{{define "funcnames"}}{{range .Funcs}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}")
|
||||
{{define "funcnames"}}{{range .Funcs}}{{if .IsNotDuplicate}} proc{{.DLLFuncName}} = mod{{.DLLName}}.NewProc("{{.DLLFuncName}}"){{end}}
|
||||
{{end}}{{end}}
|
||||
|
||||
{{define "helperbody"}}
|
||||
|
|
432
vendor/src/github.com/Microsoft/hcsshim/process.go
vendored
Normal file
432
vendor/src/github.com/Microsoft/hcsshim/process.go
vendored
Normal file
|
@ -0,0 +1,432 @@
|
|||
package hcsshim
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidProcessState = errors.New("the process is in an invalid state for the attempted operation")
|
||||
)
|
||||
|
||||
type ProcessError struct {
|
||||
Process *process
|
||||
Operation string
|
||||
Err error
|
||||
}
|
||||
|
||||
type process struct {
|
||||
handle hcsProcess
|
||||
processID int
|
||||
container *container
|
||||
cachedPipes *cachedPipes
|
||||
killCallbackNumber uintptr
|
||||
}
|
||||
|
||||
type cachedPipes struct {
|
||||
stdIn syscall.Handle
|
||||
stdOut syscall.Handle
|
||||
stdErr syscall.Handle
|
||||
}
|
||||
|
||||
type processModifyRequest struct {
|
||||
Operation string
|
||||
ConsoleSize *consoleSize `json:",omitempty"`
|
||||
CloseHandle *closeHandle `json:",omitempty"`
|
||||
}
|
||||
|
||||
type consoleSize struct {
|
||||
Height uint16
|
||||
Width uint16
|
||||
}
|
||||
|
||||
type closeHandle struct {
|
||||
Handle string
|
||||
}
|
||||
|
||||
type processStatus struct {
|
||||
ProcessId uint32
|
||||
Exited bool
|
||||
ExitCode uint32
|
||||
LastWaitResult int32
|
||||
}
|
||||
|
||||
const (
|
||||
stdIn string = "StdIn"
|
||||
stdOut string = "StdOut"
|
||||
stdErr string = "StdErr"
|
||||
)
|
||||
|
||||
const (
|
||||
modifyConsoleSize string = "ConsoleSize"
|
||||
modifyCloseHandle string = "CloseHandle"
|
||||
)
|
||||
|
||||
// Pid returns the process ID of the process within the container.
|
||||
func (process *process) Pid() int {
|
||||
return process.processID
|
||||
}
|
||||
|
||||
// Kill signals the process to terminate but does not wait for it to finish terminating.
|
||||
func (process *process) Kill() error {
|
||||
operation := "Kill"
|
||||
title := "HCSShim::Process::" + operation
|
||||
logrus.Debugf(title+" processid=%d", process.processID)
|
||||
|
||||
var resultp *uint16
|
||||
err := hcsTerminateProcess(process.handle, &resultp)
|
||||
err = processHcsResult(err, resultp)
|
||||
if err == ErrVmcomputeOperationPending {
|
||||
return ErrVmcomputeOperationPending
|
||||
} else if err != nil {
|
||||
err := &ProcessError{Operation: operation, Process: process, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded processid=%d", process.processID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Wait waits for the process to exit.
|
||||
func (process *process) Wait() error {
|
||||
operation := "Wait"
|
||||
title := "HCSShim::Process::" + operation
|
||||
logrus.Debugf(title+" processid=%d", process.processID)
|
||||
|
||||
if hcsCallbacksSupported {
|
||||
err := registerAndWaitForCallback(process, hcsNotificationProcessExited)
|
||||
if err != nil {
|
||||
err := &ProcessError{Operation: operation, Process: process, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
_, err := process.waitTimeoutInternal(syscall.INFINITE)
|
||||
if err != nil {
|
||||
err := &ProcessError{Operation: operation, Process: process, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded processid=%d", process.processID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitTimeout waits for the process to exit or the duration to elapse. It returns
|
||||
// false if timeout occurs.
|
||||
func (process *process) WaitTimeout(timeout time.Duration) error {
|
||||
operation := "WaitTimeout"
|
||||
title := "HCSShim::Process::" + operation
|
||||
logrus.Debugf(title+" processid=%d", process.processID)
|
||||
|
||||
if hcsCallbacksSupported {
|
||||
err := registerAndWaitForCallbackTimeout(process, hcsNotificationProcessExited, timeout)
|
||||
if err == ErrTimeout {
|
||||
return ErrTimeout
|
||||
} else if err != nil {
|
||||
err := &ProcessError{Operation: operation, Process: process, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
finished, err := waitTimeoutHelper(process, timeout)
|
||||
if !finished {
|
||||
return ErrTimeout
|
||||
} else if err != nil {
|
||||
err := &ProcessError{Operation: operation, Process: process, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded processid=%d", process.processID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (process *process) hcsWait(timeout uint32) (bool, error) {
|
||||
var (
|
||||
resultp *uint16
|
||||
exitEvent syscall.Handle
|
||||
)
|
||||
err := hcsCreateProcessWait(process.handle, &exitEvent, &resultp)
|
||||
err = processHcsResult(err, resultp)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer syscall.CloseHandle(exitEvent)
|
||||
|
||||
return waitForSingleObject(exitEvent, timeout)
|
||||
}
|
||||
|
||||
func (process *process) waitTimeoutInternal(timeout uint32) (bool, error) {
|
||||
return waitTimeoutInternalHelper(process, timeout)
|
||||
}
|
||||
|
||||
// ExitCode returns the exit code of the process. The process must have
|
||||
// already terminated.
|
||||
func (process *process) ExitCode() (int, error) {
|
||||
operation := "ExitCode"
|
||||
title := "HCSShim::Process::" + operation
|
||||
logrus.Debugf(title+" processid=%d", process.processID)
|
||||
|
||||
properties, err := process.properties()
|
||||
if err != nil {
|
||||
err := &ProcessError{Operation: operation, Process: process, Err: err}
|
||||
logrus.Error(err)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if properties.Exited == false {
|
||||
return 0, ErrInvalidProcessState
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded processid=%d exitCode=%d", process.processID, properties.ExitCode)
|
||||
return int(properties.ExitCode), nil
|
||||
}
|
||||
|
||||
// ResizeConsole resizes the console of the process.
|
||||
func (process *process) ResizeConsole(width, height uint16) error {
|
||||
operation := "ResizeConsole"
|
||||
title := "HCSShim::Process::" + operation
|
||||
logrus.Debugf(title+" processid=%d", process.processID)
|
||||
|
||||
modifyRequest := processModifyRequest{
|
||||
Operation: modifyConsoleSize,
|
||||
ConsoleSize: &consoleSize{
|
||||
Height: height,
|
||||
Width: width,
|
||||
},
|
||||
}
|
||||
|
||||
modifyRequestb, err := json.Marshal(modifyRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
modifyRequestStr := string(modifyRequestb)
|
||||
|
||||
var resultp *uint16
|
||||
err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp)
|
||||
err = processHcsResult(err, resultp)
|
||||
if err != nil {
|
||||
err := &ProcessError{Operation: operation, Process: process, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded processid=%d", process.processID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (process *process) properties() (*processStatus, error) {
|
||||
operation := "properties"
|
||||
title := "HCSShim::Process::" + operation
|
||||
logrus.Debugf(title+" processid=%d", process.processID)
|
||||
|
||||
var (
|
||||
resultp *uint16
|
||||
propertiesp *uint16
|
||||
)
|
||||
err := hcsGetProcessProperties(process.handle, &propertiesp, &resultp)
|
||||
err = processHcsResult(err, resultp)
|
||||
if err != nil {
|
||||
err := &ProcessError{Operation: operation, Process: process, Err: err}
|
||||
logrus.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if propertiesp == nil {
|
||||
return nil, errors.New("Unexpected result from hcsGetProcessProperties, properties should never be nil")
|
||||
}
|
||||
propertiesRaw := convertAndFreeCoTaskMemBytes(propertiesp)
|
||||
|
||||
properties := &processStatus{}
|
||||
if err := json.Unmarshal(propertiesRaw, properties); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded processid=%d, properties=%s", process.processID, propertiesRaw)
|
||||
return properties, nil
|
||||
}
|
||||
|
||||
// Stdio returns the stdin, stdout, and stderr pipes, respectively. Closing
|
||||
// these pipes does not close the underlying pipes; it should be possible to
|
||||
// call this multiple times to get multiple interfaces.
|
||||
func (process *process) Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, error) {
|
||||
operation := "Stdio"
|
||||
title := "HCSShim::Process::" + operation
|
||||
logrus.Debugf(title+" processid=%d", process.processID)
|
||||
|
||||
var stdIn, stdOut, stdErr syscall.Handle
|
||||
|
||||
if process.cachedPipes == nil {
|
||||
var (
|
||||
processInfo hcsProcessInformation
|
||||
resultp *uint16
|
||||
)
|
||||
err := hcsGetProcessInfo(process.handle, &processInfo, &resultp)
|
||||
err = processHcsResult(err, resultp)
|
||||
if err != nil {
|
||||
err = &ProcessError{Operation: operation, Process: process, Err: err}
|
||||
logrus.Error(err)
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
stdIn, stdOut, stdErr = processInfo.StdInput, processInfo.StdOutput, processInfo.StdError
|
||||
} else {
|
||||
// Use cached pipes
|
||||
stdIn, stdOut, stdErr = process.cachedPipes.stdIn, process.cachedPipes.stdOut, process.cachedPipes.stdErr
|
||||
|
||||
// Invalidate the cache
|
||||
process.cachedPipes = nil
|
||||
}
|
||||
|
||||
pipes, err := makeOpenFiles([]syscall.Handle{stdIn, stdOut, stdErr})
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded processid=%d", process.processID)
|
||||
return pipes[0], pipes[1], pipes[2], nil
|
||||
}
|
||||
|
||||
// CloseStdin closes the write side of the stdin pipe so that the process is
|
||||
// notified on the read side that there is no more data in stdin.
|
||||
func (process *process) CloseStdin() error {
|
||||
operation := "CloseStdin"
|
||||
title := "HCSShim::Process::" + operation
|
||||
logrus.Debugf(title+" processid=%d", process.processID)
|
||||
|
||||
modifyRequest := processModifyRequest{
|
||||
Operation: modifyCloseHandle,
|
||||
CloseHandle: &closeHandle{
|
||||
Handle: stdIn,
|
||||
},
|
||||
}
|
||||
|
||||
modifyRequestb, err := json.Marshal(modifyRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
modifyRequestStr := string(modifyRequestb)
|
||||
|
||||
var resultp *uint16
|
||||
err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp)
|
||||
err = processHcsResult(err, resultp)
|
||||
if err != nil {
|
||||
err = &ProcessError{Operation: operation, Process: process, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
logrus.Debugf(title+" succeeded processid=%d", process.processID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close cleans up any state associated with the process but does not kill
|
||||
// or wait on it.
|
||||
func (process *process) Close() error {
|
||||
operation := "Close"
|
||||
title := "HCSShim::Process::" + operation
|
||||
logrus.Debugf(title+" processid=%d", process.processID)
|
||||
|
||||
// Don't double free this
|
||||
if process.handle == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := hcsCloseProcess(process.handle); err != nil {
|
||||
err = &ProcessError{Operation: operation, Process: process, Err: err}
|
||||
logrus.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
process.handle = 0
|
||||
|
||||
logrus.Debugf(title+" succeeded processid=%d", process.processID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// closeProcess wraps process.Close for use by a finalizer
|
||||
func closeProcess(process *process) {
|
||||
process.Close()
|
||||
}
|
||||
|
||||
func (process *process) registerCallback(expectedNotification hcsNotification) (uintptr, error) {
|
||||
callbackMapLock.Lock()
|
||||
defer callbackMapLock.Unlock()
|
||||
|
||||
callbackNumber := nextCallback
|
||||
nextCallback++
|
||||
|
||||
context := ¬ifcationWatcherContext{
|
||||
expectedNotification: expectedNotification,
|
||||
channel: make(chan error, 1),
|
||||
}
|
||||
callbackMap[callbackNumber] = context
|
||||
|
||||
var callbackHandle hcsCallback
|
||||
err := hcsRegisterProcessCallback(process.handle, notificationWatcherCallback, callbackNumber, &callbackHandle)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
context.handle = callbackHandle
|
||||
|
||||
return callbackNumber, nil
|
||||
}
|
||||
|
||||
func (process *process) unregisterCallback(callbackNumber uintptr) error {
|
||||
callbackMapLock.Lock()
|
||||
defer callbackMapLock.Unlock()
|
||||
handle := callbackMap[callbackNumber].handle
|
||||
|
||||
if handle == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := hcsUnregisterProcessCallback(handle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
callbackMap[callbackNumber] = nil
|
||||
|
||||
handle = 0
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *ProcessError) Error() string {
|
||||
if e == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
|
||||
if e.Process == nil {
|
||||
return "Unexpected nil process for error: " + e.Err.Error()
|
||||
}
|
||||
|
||||
s := fmt.Sprintf("process %d", e.Process.processID)
|
||||
|
||||
if e.Process.container != nil {
|
||||
s += " in container " + e.Process.container.id
|
||||
}
|
||||
|
||||
if e.Operation != "" {
|
||||
s += " " + e.Operation
|
||||
}
|
||||
|
||||
if e.Err != nil {
|
||||
s += fmt.Sprintf(" failed in Win32: %s (0x%x)", e.Err, win32FromError(e.Err))
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
11
vendor/src/github.com/Microsoft/hcsshim/utils.go
vendored
Normal file
11
vendor/src/github.com/Microsoft/hcsshim/utils.go
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
package hcsshim
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
vmcomputedll = syscall.NewLazyDLL("vmcompute.dll")
|
||||
hcsCallbackAPI = vmcomputedll.NewProc("HcsRegisterComputeSystemCallback")
|
||||
hcsCallbacksSupported = hcsCallbackAPI.Find() == nil
|
||||
)
|
113
vendor/src/github.com/Microsoft/hcsshim/waithelper.go
vendored
Normal file
113
vendor/src/github.com/Microsoft/hcsshim/waithelper.go
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
package hcsshim
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
type waitable interface {
|
||||
waitTimeoutInternal(timeout uint32) (bool, error)
|
||||
hcsWait(timeout uint32) (bool, error)
|
||||
}
|
||||
|
||||
type callbackable interface {
|
||||
registerCallback(expectedNotification hcsNotification) (uintptr, error)
|
||||
unregisterCallback(callbackNumber uintptr) error
|
||||
}
|
||||
|
||||
func waitTimeoutHelper(object waitable, timeout time.Duration) (bool, error) {
|
||||
var (
|
||||
millis uint32
|
||||
)
|
||||
|
||||
for totalMillis := uint64(timeout / time.Millisecond); totalMillis > 0; totalMillis = totalMillis - uint64(millis) {
|
||||
if totalMillis >= syscall.INFINITE {
|
||||
millis = syscall.INFINITE - 1
|
||||
} else {
|
||||
millis = uint32(totalMillis)
|
||||
}
|
||||
|
||||
result, err := object.waitTimeoutInternal(millis)
|
||||
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func waitTimeoutInternalHelper(object waitable, timeout uint32) (bool, error) {
|
||||
return object.hcsWait(timeout)
|
||||
}
|
||||
|
||||
func waitForSingleObject(handle syscall.Handle, timeout uint32) (bool, error) {
|
||||
s, e := syscall.WaitForSingleObject(handle, timeout)
|
||||
switch s {
|
||||
case syscall.WAIT_OBJECT_0:
|
||||
return true, nil
|
||||
case syscall.WAIT_TIMEOUT:
|
||||
return false, nil
|
||||
default:
|
||||
return false, e
|
||||
}
|
||||
}
|
||||
|
||||
func processAsyncHcsResult(object callbackable, err error, resultp *uint16, expectedNotification hcsNotification, timeout *time.Duration) error {
|
||||
err = processHcsResult(err, resultp)
|
||||
if err == ErrVmcomputeOperationPending {
|
||||
if timeout != nil {
|
||||
err = registerAndWaitForCallbackTimeout(object, expectedNotification, *timeout)
|
||||
} else {
|
||||
err = registerAndWaitForCallback(object, expectedNotification)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func registerAndWaitForCallbackTimeout(object callbackable, expectedNotification hcsNotification, timeout time.Duration) error {
|
||||
callbackNumber, err := object.registerCallback(expectedNotification)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer object.unregisterCallback(callbackNumber)
|
||||
|
||||
return waitForNotificationTimeout(callbackNumber, timeout)
|
||||
}
|
||||
|
||||
func registerAndWaitForCallback(object callbackable, expectedNotification hcsNotification) error {
|
||||
callbackNumber, err := object.registerCallback(expectedNotification)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer object.unregisterCallback(callbackNumber)
|
||||
|
||||
return waitForNotification(callbackNumber)
|
||||
}
|
||||
|
||||
func waitForNotificationTimeout(callbackNumber uintptr, timeout time.Duration) error {
|
||||
callbackMapLock.RLock()
|
||||
channel := callbackMap[callbackNumber].channel
|
||||
callbackMapLock.RUnlock()
|
||||
|
||||
timer := time.NewTimer(timeout)
|
||||
defer timer.Stop()
|
||||
|
||||
select {
|
||||
case err := <-channel:
|
||||
return err
|
||||
case <-timer.C:
|
||||
return ErrTimeout
|
||||
}
|
||||
}
|
||||
|
||||
func waitForNotification(callbackNumber uintptr) error {
|
||||
callbackMapLock.RLock()
|
||||
channel := callbackMap[callbackNumber].channel
|
||||
callbackMapLock.RUnlock()
|
||||
|
||||
select {
|
||||
case err := <-channel:
|
||||
return err
|
||||
}
|
||||
}
|
533
vendor/src/github.com/Microsoft/hcsshim/zhcsshim.go
vendored
533
vendor/src/github.com/Microsoft/hcsshim/zhcsshim.go
vendored
|
@ -2,11 +2,8 @@
|
|||
|
||||
package hcsshim
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
)
|
||||
import "github.com/Microsoft/go-winio"
|
||||
import "unsafe"
|
||||
import "syscall"
|
||||
|
||||
var _ unsafe.Pointer
|
||||
|
@ -49,7 +46,34 @@ var (
|
|||
procTerminateProcessInComputeSystem = modvmcompute.NewProc("TerminateProcessInComputeSystem")
|
||||
procWaitForProcessInComputeSystem = modvmcompute.NewProc("WaitForProcessInComputeSystem")
|
||||
procGetComputeSystemProperties = modvmcompute.NewProc("GetComputeSystemProperties")
|
||||
procHNSCall = modvmcompute.NewProc("HNSCall")
|
||||
procHcsEnumerateComputeSystems = modvmcompute.NewProc("HcsEnumerateComputeSystems")
|
||||
procHcsCreateComputeSystem = modvmcompute.NewProc("HcsCreateComputeSystem")
|
||||
procHcsOpenComputeSystem = modvmcompute.NewProc("HcsOpenComputeSystem")
|
||||
procHcsCloseComputeSystem = modvmcompute.NewProc("HcsCloseComputeSystem")
|
||||
procHcsStartComputeSystem = modvmcompute.NewProc("HcsStartComputeSystem")
|
||||
procHcsShutdownComputeSystem = modvmcompute.NewProc("HcsShutdownComputeSystem")
|
||||
procHcsTerminateComputeSystem = modvmcompute.NewProc("HcsTerminateComputeSystem")
|
||||
procHcsPauseComputeSystem = modvmcompute.NewProc("HcsPauseComputeSystem")
|
||||
procHcsResumeComputeSystem = modvmcompute.NewProc("HcsResumeComputeSystem")
|
||||
procHcsGetComputeSystemProperties = modvmcompute.NewProc("HcsGetComputeSystemProperties")
|
||||
procHcsModifyComputeSystem = modvmcompute.NewProc("HcsModifyComputeSystem")
|
||||
procHcsCreateComputeSystemWait = modvmcompute.NewProc("HcsCreateComputeSystemWait")
|
||||
procHcsCreateProcess = modvmcompute.NewProc("HcsCreateProcess")
|
||||
procHcsOpenProcess = modvmcompute.NewProc("HcsOpenProcess")
|
||||
procHcsCloseProcess = modvmcompute.NewProc("HcsCloseProcess")
|
||||
procHcsTerminateProcess = modvmcompute.NewProc("HcsTerminateProcess")
|
||||
procHcsGetProcessInfo = modvmcompute.NewProc("HcsGetProcessInfo")
|
||||
procHcsGetProcessProperties = modvmcompute.NewProc("HcsGetProcessProperties")
|
||||
procHcsModifyProcess = modvmcompute.NewProc("HcsModifyProcess")
|
||||
procHcsCreateProcessWait = modvmcompute.NewProc("HcsCreateProcessWait")
|
||||
procHcsGetServiceProperties = modvmcompute.NewProc("HcsGetServiceProperties")
|
||||
procHcsModifyServiceSettings = modvmcompute.NewProc("HcsModifyServiceSettings")
|
||||
|
||||
procHcsRegisterComputeSystemCallback = modvmcompute.NewProc("HcsRegisterComputeSystemCallback")
|
||||
procHcsUnregisterComputeSystemCallback = modvmcompute.NewProc("HcsUnregisterComputeSystemCallback")
|
||||
procHcsRegisterProcessCallback = modvmcompute.NewProc("HcsRegisterProcessCallback")
|
||||
procHcsUnregisterProcessCallback = modvmcompute.NewProc("HcsUnregisterProcessCallback")
|
||||
procHNSCall = modvmcompute.NewProc("HNSCall")
|
||||
)
|
||||
|
||||
func coTaskMemFree(buffer unsafe.Pointer) {
|
||||
|
@ -734,6 +758,503 @@ func _getComputeSystemProperties(id *uint16, flags uint32, properties **uint16)
|
|||
return
|
||||
}
|
||||
|
||||
func hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(query)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsEnumerateComputeSystems(_p0, computeSystems, result)
|
||||
}
|
||||
|
||||
func _hcsEnumerateComputeSystems(query *uint16, computeSystems **uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsEnumerateComputeSystems.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsEnumerateComputeSystems.Addr(), 3, uintptr(unsafe.Pointer(query)), uintptr(unsafe.Pointer(computeSystems)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsCreateComputeSystem(id string, configuration string, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(id)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
var _p1 *uint16
|
||||
_p1, hr = syscall.UTF16PtrFromString(configuration)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsCreateComputeSystem(_p0, _p1, identity, computeSystem, result)
|
||||
}
|
||||
|
||||
func _hcsCreateComputeSystem(id *uint16, configuration *uint16, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) {
|
||||
if hr = procHcsCreateComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall6(procHcsCreateComputeSystem.Addr(), 5, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(configuration)), uintptr(identity), uintptr(unsafe.Pointer(computeSystem)), uintptr(unsafe.Pointer(result)), 0)
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsOpenComputeSystem(id string, computeSystem *hcsSystem, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(id)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsOpenComputeSystem(_p0, computeSystem, result)
|
||||
}
|
||||
|
||||
func _hcsOpenComputeSystem(id *uint16, computeSystem *hcsSystem, result **uint16) (hr error) {
|
||||
if hr = procHcsOpenComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsOpenComputeSystem.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(computeSystem)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsCloseComputeSystem(computeSystem hcsSystem) (hr error) {
|
||||
if hr = procHcsCloseComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsCloseComputeSystem.Addr(), 1, uintptr(computeSystem), 0, 0)
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsStartComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(options)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsStartComputeSystem(computeSystem, _p0, result)
|
||||
}
|
||||
|
||||
func _hcsStartComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsStartComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsStartComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsShutdownComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(options)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsShutdownComputeSystem(computeSystem, _p0, result)
|
||||
}
|
||||
|
||||
func _hcsShutdownComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsShutdownComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsShutdownComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsTerminateComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(options)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsTerminateComputeSystem(computeSystem, _p0, result)
|
||||
}
|
||||
|
||||
func _hcsTerminateComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsTerminateComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsTerminateComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsPauseComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(options)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsPauseComputeSystem(computeSystem, _p0, result)
|
||||
}
|
||||
|
||||
func _hcsPauseComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsPauseComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsPauseComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsResumeComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(options)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsResumeComputeSystem(computeSystem, _p0, result)
|
||||
}
|
||||
|
||||
func _hcsResumeComputeSystem(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsResumeComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsResumeComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery string, properties **uint16, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(propertyQuery)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsGetComputeSystemProperties(computeSystem, _p0, properties, result)
|
||||
}
|
||||
|
||||
func _hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery *uint16, properties **uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsGetComputeSystemProperties.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall6(procHcsGetComputeSystemProperties.Addr(), 4, uintptr(computeSystem), uintptr(unsafe.Pointer(propertyQuery)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)), 0, 0)
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsModifyComputeSystem(computeSystem hcsSystem, configuration string, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(configuration)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsModifyComputeSystem(computeSystem, _p0, result)
|
||||
}
|
||||
|
||||
func _hcsModifyComputeSystem(computeSystem hcsSystem, configuration *uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsModifyComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsModifyComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(configuration)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsCreateComputeSystemWait(computeSystem hcsSystem, exitEvent *syscall.Handle, result **uint16) (hr error) {
|
||||
if hr = procHcsCreateComputeSystemWait.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsCreateComputeSystemWait.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(exitEvent)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsCreateProcess(computeSystem hcsSystem, processParameters string, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(processParameters)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsCreateProcess(computeSystem, _p0, processInformation, process, result)
|
||||
}
|
||||
|
||||
func _hcsCreateProcess(computeSystem hcsSystem, processParameters *uint16, processInformation *hcsProcessInformation, process *hcsProcess, result **uint16) (hr error) {
|
||||
if hr = procHcsCreateProcess.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall6(procHcsCreateProcess.Addr(), 5, uintptr(computeSystem), uintptr(unsafe.Pointer(processParameters)), uintptr(unsafe.Pointer(processInformation)), uintptr(unsafe.Pointer(process)), uintptr(unsafe.Pointer(result)), 0)
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsOpenProcess(computeSystem hcsSystem, pid uint32, process *hcsProcess, result **uint16) (hr error) {
|
||||
if hr = procHcsOpenProcess.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall6(procHcsOpenProcess.Addr(), 4, uintptr(computeSystem), uintptr(pid), uintptr(unsafe.Pointer(process)), uintptr(unsafe.Pointer(result)), 0, 0)
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsCloseProcess(process hcsProcess) (hr error) {
|
||||
if hr = procHcsCloseProcess.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsCloseProcess.Addr(), 1, uintptr(process), 0, 0)
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) {
|
||||
if hr = procHcsTerminateProcess.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsTerminateProcess.Addr(), 2, uintptr(process), uintptr(unsafe.Pointer(result)), 0)
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) {
|
||||
if hr = procHcsGetProcessInfo.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsGetProcessInfo.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(processInformation)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsGetProcessProperties.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsGetProcessProperties.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(processProperties)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(settings)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsModifyProcess(process, _p0, result)
|
||||
}
|
||||
|
||||
func _hcsModifyProcess(process hcsProcess, settings *uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsModifyProcess.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsModifyProcess.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsCreateProcessWait(process hcsProcess, settings *syscall.Handle, result **uint16) (hr error) {
|
||||
if hr = procHcsCreateProcessWait.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsCreateProcessWait.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(propertyQuery)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsGetServiceProperties(_p0, properties, result)
|
||||
}
|
||||
|
||||
func _hcsGetServiceProperties(propertyQuery *uint16, properties **uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsGetServiceProperties.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsGetServiceProperties.Addr(), 3, uintptr(unsafe.Pointer(propertyQuery)), uintptr(unsafe.Pointer(properties)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsModifyServiceSettings(settings string, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(settings)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsModifyServiceSettings(_p0, result)
|
||||
}
|
||||
|
||||
func _hcsModifyServiceSettings(settings *uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsModifyServiceSettings.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsModifyServiceSettings.Addr(), 2, uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)), 0)
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsCreateComputeSystemTP5(id string, configuration string, computeSystem *hcsSystem, result **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(id)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
var _p1 *uint16
|
||||
_p1, hr = syscall.UTF16PtrFromString(configuration)
|
||||
if hr != nil {
|
||||
return
|
||||
}
|
||||
return _hcsCreateComputeSystemTP5(_p0, _p1, computeSystem, result)
|
||||
}
|
||||
|
||||
func _hcsCreateComputeSystemTP5(id *uint16, configuration *uint16, computeSystem *hcsSystem, result **uint16) (hr error) {
|
||||
if hr = procHcsCreateComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall6(procHcsCreateComputeSystem.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(configuration)), uintptr(unsafe.Pointer(computeSystem)), uintptr(unsafe.Pointer(result)), 0, 0)
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsStartComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsStartComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsStartComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsShutdownComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsShutdownComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsShutdownComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsTerminateComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsTerminateComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsTerminateComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsPauseComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsPauseComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsPauseComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsResumeComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
|
||||
if hr = procHcsResumeComputeSystem.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsResumeComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) {
|
||||
if hr = procHcsRegisterComputeSystemCallback.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall6(procHcsRegisterComputeSystemCallback.Addr(), 4, uintptr(computeSystem), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0)
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) {
|
||||
if hr = procHcsUnregisterComputeSystemCallback.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsUnregisterComputeSystemCallback.Addr(), 1, uintptr(callbackHandle), 0, 0)
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) {
|
||||
if hr = procHcsRegisterProcessCallback.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall6(procHcsRegisterProcessCallback.Addr(), 4, uintptr(process), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0)
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) {
|
||||
if hr = procHcsUnregisterProcessCallback.Find(); hr != nil {
|
||||
return
|
||||
}
|
||||
r0, _, _ := syscall.Syscall(procHcsUnregisterProcessCallback.Addr(), 1, uintptr(callbackHandle), 0, 0)
|
||||
if int32(r0) < 0 {
|
||||
hr = syscall.Errno(win32FromHresult(r0))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func _hnsCall(method string, path string, object string, response **uint16) (hr error) {
|
||||
var _p0 *uint16
|
||||
_p0, hr = syscall.UTF16PtrFromString(method)
|
||||
|
|
Loading…
Add table
Reference in a new issue