summaryrefslogtreecommitdiff
path: root/vendor/github.com/Microsoft/hcsshim
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/Microsoft/hcsshim')
-rw-r--r--vendor/github.com/Microsoft/hcsshim/LICENSE21
-rw-r--r--vendor/github.com/Microsoft/hcsshim/README.md12
-rw-r--r--vendor/github.com/Microsoft/hcsshim/activatelayer.go28
-rw-r--r--vendor/github.com/Microsoft/hcsshim/baselayer.go183
-rw-r--r--vendor/github.com/Microsoft/hcsshim/callback.go79
-rw-r--r--vendor/github.com/Microsoft/hcsshim/cgo.go7
-rw-r--r--vendor/github.com/Microsoft/hcsshim/container.go794
-rw-r--r--vendor/github.com/Microsoft/hcsshim/createlayer.go27
-rw-r--r--vendor/github.com/Microsoft/hcsshim/createsandboxlayer.go35
-rw-r--r--vendor/github.com/Microsoft/hcsshim/deactivatelayer.go26
-rw-r--r--vendor/github.com/Microsoft/hcsshim/destroylayer.go27
-rw-r--r--vendor/github.com/Microsoft/hcsshim/errors.go239
-rw-r--r--vendor/github.com/Microsoft/hcsshim/expandsandboxsize.go26
-rw-r--r--vendor/github.com/Microsoft/hcsshim/exportlayer.go156
-rw-r--r--vendor/github.com/Microsoft/hcsshim/getlayermountpath.go55
-rw-r--r--vendor/github.com/Microsoft/hcsshim/getsharedbaseimages.go22
-rw-r--r--vendor/github.com/Microsoft/hcsshim/guid.go19
-rw-r--r--vendor/github.com/Microsoft/hcsshim/hcsshim.go166
-rw-r--r--vendor/github.com/Microsoft/hcsshim/hnsendpoint.go318
-rw-r--r--vendor/github.com/Microsoft/hcsshim/hnsfuncs.go40
-rw-r--r--vendor/github.com/Microsoft/hcsshim/hnsnetwork.go142
-rw-r--r--vendor/github.com/Microsoft/hcsshim/hnspolicy.go95
-rw-r--r--vendor/github.com/Microsoft/hcsshim/hnspolicylist.go196
-rw-r--r--vendor/github.com/Microsoft/hcsshim/importlayer.go212
-rw-r--r--vendor/github.com/Microsoft/hcsshim/interface.go187
-rw-r--r--vendor/github.com/Microsoft/hcsshim/layerexists.go30
-rw-r--r--vendor/github.com/Microsoft/hcsshim/layerutils.go111
-rw-r--r--vendor/github.com/Microsoft/hcsshim/legacy.go741
-rw-r--r--vendor/github.com/Microsoft/hcsshim/nametoguid.go20
-rw-r--r--vendor/github.com/Microsoft/hcsshim/preparelayer.go46
-rw-r--r--vendor/github.com/Microsoft/hcsshim/process.go384
-rw-r--r--vendor/github.com/Microsoft/hcsshim/processimage.go23
-rw-r--r--vendor/github.com/Microsoft/hcsshim/unpreparelayer.go27
-rw-r--r--vendor/github.com/Microsoft/hcsshim/utils.go33
-rw-r--r--vendor/github.com/Microsoft/hcsshim/version.go7
-rw-r--r--vendor/github.com/Microsoft/hcsshim/waithelper.go63
-rw-r--r--vendor/github.com/Microsoft/hcsshim/zhcsshim.go1042
37 files changed, 5639 insertions, 0 deletions
diff --git a/vendor/github.com/Microsoft/hcsshim/LICENSE b/vendor/github.com/Microsoft/hcsshim/LICENSE
new file mode 100644
index 000000000..49d21669a
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Microsoft
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE. \ No newline at end of file
diff --git a/vendor/github.com/Microsoft/hcsshim/README.md b/vendor/github.com/Microsoft/hcsshim/README.md
new file mode 100644
index 000000000..30991a12e
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/README.md
@@ -0,0 +1,12 @@
+# hcsshim
+
+This package supports launching Windows Server containers from Go. It is
+primarily used in the [Docker Engine](https://github.com/docker/docker) project,
+but it can be freely used by other projects as well.
+
+This project has adopted the [Microsoft Open Source Code of
+Conduct](https://opensource.microsoft.com/codeofconduct/). For more information
+see the [Code of Conduct
+FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact
+[opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional
+questions or comments.
diff --git a/vendor/github.com/Microsoft/hcsshim/activatelayer.go b/vendor/github.com/Microsoft/hcsshim/activatelayer.go
new file mode 100644
index 000000000..6d824d7a7
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/activatelayer.go
@@ -0,0 +1,28 @@
+package hcsshim
+
+import "github.com/sirupsen/logrus"
+
+// ActivateLayer will find the layer with the given id and mount it's filesystem.
+// For a read/write layer, the mounted filesystem will appear as a volume on the
+// host, while a read-only layer is generally expected to be a no-op.
+// An activated layer must later be deactivated via DeactivateLayer.
+func ActivateLayer(info DriverInfo, id string) error {
+ title := "hcsshim::ActivateLayer "
+ logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id)
+
+ infop, err := convertDriverInfo(info)
+ if err != nil {
+ logrus.Error(err)
+ return err
+ }
+
+ err = activateLayer(&infop, id)
+ if err != nil {
+ err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+" - succeeded id=%s flavour=%d", id, info.Flavour)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/baselayer.go b/vendor/github.com/Microsoft/hcsshim/baselayer.go
new file mode 100644
index 000000000..9babd4e18
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/baselayer.go
@@ -0,0 +1,183 @@
+package hcsshim
+
+import (
+ "errors"
+ "os"
+ "path/filepath"
+ "syscall"
+
+ "github.com/Microsoft/go-winio"
+)
+
+type baseLayerWriter struct {
+ root string
+ f *os.File
+ bw *winio.BackupFileWriter
+ err error
+ hasUtilityVM bool
+ dirInfo []dirInfo
+}
+
+type dirInfo struct {
+ path string
+ fileInfo winio.FileBasicInfo
+}
+
+// reapplyDirectoryTimes reapplies directory modification, creation, etc. times
+// after processing of the directory tree has completed. The times are expected
+// to be ordered such that parent directories come before child directories.
+func reapplyDirectoryTimes(dis []dirInfo) error {
+ for i := range dis {
+ di := &dis[len(dis)-i-1] // reverse order: process child directories first
+ f, err := winio.OpenForBackup(di.path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.FILE_SHARE_READ, syscall.OPEN_EXISTING)
+ if err != nil {
+ return err
+ }
+
+ err = winio.SetFileBasicInfo(f, &di.fileInfo)
+ f.Close()
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (w *baseLayerWriter) closeCurrentFile() error {
+ if w.f != nil {
+ err := w.bw.Close()
+ err2 := w.f.Close()
+ w.f = nil
+ w.bw = nil
+ if err != nil {
+ return err
+ }
+ if err2 != nil {
+ return err2
+ }
+ }
+ return nil
+}
+
+func (w *baseLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) (err error) {
+ defer func() {
+ if err != nil {
+ w.err = err
+ }
+ }()
+
+ err = w.closeCurrentFile()
+ if err != nil {
+ return err
+ }
+
+ if filepath.ToSlash(name) == `UtilityVM/Files` {
+ w.hasUtilityVM = true
+ }
+
+ path := filepath.Join(w.root, name)
+ path, err = makeLongAbsPath(path)
+ if err != nil {
+ return err
+ }
+
+ var f *os.File
+ defer func() {
+ if f != nil {
+ f.Close()
+ }
+ }()
+
+ 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
+ if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
+ w.dirInfo = append(w.dirInfo, dirInfo{path, *fileInfo})
+ }
+ }
+
+ 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 makeError(err, "Failed to OpenForBackup", path)
+ }
+
+ err = winio.SetFileBasicInfo(f, fileInfo)
+ if err != nil {
+ return makeError(err, "Failed to SetFileBasicInfo", path)
+ }
+
+ w.f = f
+ w.bw = winio.NewBackupFileWriter(f, true)
+ f = nil
+ return nil
+}
+
+func (w *baseLayerWriter) AddLink(name string, target string) (err error) {
+ defer func() {
+ if err != nil {
+ w.err = err
+ }
+ }()
+
+ err = w.closeCurrentFile()
+ if err != nil {
+ return err
+ }
+
+ linkpath, err := makeLongAbsPath(filepath.Join(w.root, name))
+ if err != nil {
+ return err
+ }
+
+ linktarget, err := makeLongAbsPath(filepath.Join(w.root, target))
+ if err != nil {
+ return err
+ }
+
+ return os.Link(linktarget, linkpath)
+}
+
+func (w *baseLayerWriter) Remove(name string) error {
+ return errors.New("base layer cannot have tombstones")
+}
+
+func (w *baseLayerWriter) Write(b []byte) (int, error) {
+ n, err := w.bw.Write(b)
+ if err != nil {
+ w.err = err
+ }
+ return n, err
+}
+
+func (w *baseLayerWriter) Close() error {
+ err := w.closeCurrentFile()
+ if err != nil {
+ return err
+ }
+ if w.err == nil {
+ // Restore the file times of all the directories, since they may have
+ // been modified by creating child directories.
+ err = reapplyDirectoryTimes(w.dirInfo)
+ if err != nil {
+ return err
+ }
+
+ err = ProcessBaseLayer(w.root)
+ if err != nil {
+ return err
+ }
+
+ if w.hasUtilityVM {
+ err = ProcessUtilityVMImage(filepath.Join(w.root, "UtilityVM"))
+ if err != nil {
+ return err
+ }
+ }
+ }
+ return w.err
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/callback.go b/vendor/github.com/Microsoft/hcsshim/callback.go
new file mode 100644
index 000000000..e8c2b00c8
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/callback.go
@@ -0,0 +1,79 @@
+package hcsshim
+
+import (
+ "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
+)
+
+type hcsNotification uint32
+type notificationChannel chan error
+
+type notifcationWatcherContext struct {
+ channels notificationChannels
+ handle hcsCallback
+}
+
+type notificationChannels map[hcsNotification]notificationChannel
+
+func newChannels() notificationChannels {
+ channels := make(notificationChannels)
+
+ channels[hcsNotificationSystemExited] = make(notificationChannel, 1)
+ channels[hcsNotificationSystemCreateCompleted] = make(notificationChannel, 1)
+ channels[hcsNotificationSystemStartCompleted] = make(notificationChannel, 1)
+ channels[hcsNotificationSystemPauseCompleted] = make(notificationChannel, 1)
+ channels[hcsNotificationSystemResumeCompleted] = make(notificationChannel, 1)
+ channels[hcsNotificationProcessExited] = make(notificationChannel, 1)
+ channels[hcsNotificationServiceDisconnect] = make(notificationChannel, 1)
+ return channels
+}
+func closeChannels(channels notificationChannels) {
+ close(channels[hcsNotificationSystemExited])
+ close(channels[hcsNotificationSystemCreateCompleted])
+ close(channels[hcsNotificationSystemStartCompleted])
+ close(channels[hcsNotificationSystemPauseCompleted])
+ close(channels[hcsNotificationSystemResumeCompleted])
+ close(channels[hcsNotificationProcessExited])
+ close(channels[hcsNotificationServiceDisconnect])
+}
+
+func notificationWatcher(notificationType hcsNotification, callbackNumber uintptr, notificationStatus uintptr, notificationData *uint16) uintptr {
+ var result error
+ if int32(notificationStatus) < 0 {
+ result = syscall.Errno(win32FromHresult(notificationStatus))
+ }
+
+ callbackMapLock.RLock()
+ context := callbackMap[callbackNumber]
+ callbackMapLock.RUnlock()
+
+ if context == nil {
+ return 0
+ }
+
+ context.channels[notificationType] <- result
+
+ return 0
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/cgo.go b/vendor/github.com/Microsoft/hcsshim/cgo.go
new file mode 100644
index 000000000..200333233
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/cgo.go
@@ -0,0 +1,7 @@
+package hcsshim
+
+import "C"
+
+// This import is needed to make the library compile as CGO because HCSSHIM
+// only works with CGO due to callbacks from HCS comming back from a C thread
+// which is not supported without CGO. See https://github.com/golang/go/issues/10973
diff --git a/vendor/github.com/Microsoft/hcsshim/container.go b/vendor/github.com/Microsoft/hcsshim/container.go
new file mode 100644
index 000000000..b924d39f4
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/container.go
@@ -0,0 +1,794 @@
+package hcsshim
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+ "sync"
+ "syscall"
+ "time"
+
+ "github.com/sirupsen/logrus"
+)
+
+var (
+ defaultTimeout = time.Minute * 4
+)
+
+const (
+ pendingUpdatesQuery = `{ "PropertyTypes" : ["PendingUpdates"]}`
+ statisticsQuery = `{ "PropertyTypes" : ["Statistics"]}`
+ processListQuery = `{ "PropertyTypes" : ["ProcessList"]}`
+ mappedVirtualDiskQuery = `{ "PropertyTypes" : ["MappedVirtualDisk"]}`
+)
+
+type container struct {
+ handleLock sync.RWMutex
+ handle hcsSystem
+ id string
+ callbackNumber uintptr
+}
+
+// ContainerProperties holds the properties for a container and the processes running in that container
+type ContainerProperties struct {
+ ID string `json:"Id"`
+ Name string
+ SystemType string
+ Owner string
+ SiloGUID string `json:"SiloGuid,omitempty"`
+ RuntimeID string `json:"RuntimeId,omitempty"`
+ IsRuntimeTemplate bool `json:",omitempty"`
+ RuntimeImagePath string `json:",omitempty"`
+ Stopped bool `json:",omitempty"`
+ ExitType string `json:",omitempty"`
+ AreUpdatesPending bool `json:",omitempty"`
+ ObRoot string `json:",omitempty"`
+ Statistics Statistics `json:",omitempty"`
+ ProcessList []ProcessListItem `json:",omitempty"`
+ MappedVirtualDiskControllers map[int]MappedVirtualDiskController `json:",omitempty"`
+}
+
+// MemoryStats holds the memory statistics for a container
+type MemoryStats struct {
+ UsageCommitBytes uint64 `json:"MemoryUsageCommitBytes,omitempty"`
+ UsageCommitPeakBytes uint64 `json:"MemoryUsageCommitPeakBytes,omitempty"`
+ UsagePrivateWorkingSetBytes uint64 `json:"MemoryUsagePrivateWorkingSetBytes,omitempty"`
+}
+
+// ProcessorStats holds the processor statistics for a container
+type ProcessorStats struct {
+ TotalRuntime100ns uint64 `json:",omitempty"`
+ RuntimeUser100ns uint64 `json:",omitempty"`
+ RuntimeKernel100ns uint64 `json:",omitempty"`
+}
+
+// StorageStats holds the storage statistics for a container
+type StorageStats struct {
+ ReadCountNormalized uint64 `json:",omitempty"`
+ ReadSizeBytes uint64 `json:",omitempty"`
+ WriteCountNormalized uint64 `json:",omitempty"`
+ WriteSizeBytes uint64 `json:",omitempty"`
+}
+
+// NetworkStats holds the network statistics for a container
+type NetworkStats struct {
+ BytesReceived uint64 `json:",omitempty"`
+ BytesSent uint64 `json:",omitempty"`
+ PacketsReceived uint64 `json:",omitempty"`
+ PacketsSent uint64 `json:",omitempty"`
+ DroppedPacketsIncoming uint64 `json:",omitempty"`
+ DroppedPacketsOutgoing uint64 `json:",omitempty"`
+ EndpointId string `json:",omitempty"`
+ InstanceId string `json:",omitempty"`
+}
+
+// Statistics is the structure returned by a statistics call on a container
+type Statistics struct {
+ Timestamp time.Time `json:",omitempty"`
+ ContainerStartTime time.Time `json:",omitempty"`
+ Uptime100ns uint64 `json:",omitempty"`
+ Memory MemoryStats `json:",omitempty"`
+ Processor ProcessorStats `json:",omitempty"`
+ Storage StorageStats `json:",omitempty"`
+ Network []NetworkStats `json:",omitempty"`
+}
+
+// ProcessList is the structure of an item returned by a ProcessList call on a container
+type ProcessListItem struct {
+ CreateTimestamp time.Time `json:",omitempty"`
+ ImageName string `json:",omitempty"`
+ KernelTime100ns uint64 `json:",omitempty"`
+ MemoryCommitBytes uint64 `json:",omitempty"`
+ MemoryWorkingSetPrivateBytes uint64 `json:",omitempty"`
+ MemoryWorkingSetSharedBytes uint64 `json:",omitempty"`
+ ProcessId uint32 `json:",omitempty"`
+ UserTime100ns uint64 `json:",omitempty"`
+}
+
+// MappedVirtualDiskController is the structure of an item returned by a MappedVirtualDiskList call on a container
+type MappedVirtualDiskController struct {
+ MappedVirtualDisks map[int]MappedVirtualDisk `json:",omitempty"`
+}
+
+// Type of Request Support in ModifySystem
+type RequestType string
+
+// Type of Resource Support in ModifySystem
+type ResourceType string
+
+// RequestType const
+const (
+ Add RequestType = "Add"
+ Remove RequestType = "Remove"
+ Network ResourceType = "Network"
+)
+
+// ResourceModificationRequestResponse is the structure used to send request to the container to modify the system
+// Supported resource types are Network and Request Types are Add/Remove
+type ResourceModificationRequestResponse struct {
+ Resource ResourceType `json:"ResourceType"`
+ Data interface{} `json:"Settings"`
+ Request RequestType `json:"RequestType,omitempty"`
+}
+
+// createContainerAdditionalJSON is read from the environment at initialisation
+// time. It allows an environment variable to define additional JSON which
+// is merged in the CreateContainer call to HCS.
+var createContainerAdditionalJSON string
+
+func init() {
+ createContainerAdditionalJSON = os.Getenv("HCSSHIM_CREATECONTAINER_ADDITIONALJSON")
+}
+
+// CreateContainer creates a new container with the given configuration but does not start it.
+func CreateContainer(id string, c *ContainerConfig) (Container, error) {
+ return createContainerWithJSON(id, c, "")
+}
+
+// CreateContainerWithJSON creates a new container with the given configuration but does not start it.
+// It is identical to CreateContainer except that optional additional JSON can be merged before passing to HCS.
+func CreateContainerWithJSON(id string, c *ContainerConfig, additionalJSON string) (Container, error) {
+ return createContainerWithJSON(id, c, additionalJSON)
+}
+
+func createContainerWithJSON(id string, c *ContainerConfig, additionalJSON string) (Container, error) {
+ operation := "CreateContainer"
+ title := "HCSShim::" + operation
+
+ container := &container{
+ id: id,
+ }
+
+ configurationb, err := json.Marshal(c)
+ if err != nil {
+ return nil, err
+ }
+
+ configuration := string(configurationb)
+ logrus.Debugf(title+" id=%s config=%s", id, configuration)
+
+ // Merge any additional JSON. Priority is given to what is passed in explicitly,
+ // falling back to what's set in the environment.
+ if additionalJSON == "" && createContainerAdditionalJSON != "" {
+ additionalJSON = createContainerAdditionalJSON
+ }
+ if additionalJSON != "" {
+ configurationMap := map[string]interface{}{}
+ if err := json.Unmarshal([]byte(configuration), &configurationMap); err != nil {
+ return nil, fmt.Errorf("failed to unmarshal %s: %s", configuration, err)
+ }
+
+ additionalMap := map[string]interface{}{}
+ if err := json.Unmarshal([]byte(additionalJSON), &additionalMap); err != nil {
+ return nil, fmt.Errorf("failed to unmarshal %s: %s", additionalJSON, err)
+ }
+
+ mergedMap := mergeMaps(additionalMap, configurationMap)
+ mergedJSON, err := json.Marshal(mergedMap)
+ if err != nil {
+ return nil, fmt.Errorf("failed to marshal merged configuration map %+v: %s", mergedMap, err)
+ }
+
+ configuration = string(mergedJSON)
+ logrus.Debugf(title+" id=%s merged config=%s", id, configuration)
+ }
+
+ var (
+ resultp *uint16
+ identity syscall.Handle
+ )
+ createError := hcsCreateComputeSystem(id, configuration, identity, &container.handle, &resultp)
+
+ if createError == nil || IsPending(createError) {
+ if err := container.registerCallback(); err != nil {
+ return nil, makeContainerError(container, operation, "", err)
+ }
+ }
+
+ err = processAsyncHcsResult(createError, resultp, container.callbackNumber, hcsNotificationSystemCreateCompleted, &defaultTimeout)
+ if err != nil {
+ return nil, makeContainerError(container, operation, configuration, err)
+ }
+
+ logrus.Debugf(title+" succeeded id=%s handle=%d", id, container.handle)
+ return container, nil
+}
+
+// mergeMaps recursively merges map `fromMap` into map `ToMap`. Any pre-existing values
+// in ToMap are overwritten. Values in fromMap are added to ToMap.
+// From http://stackoverflow.com/questions/40491438/merging-two-json-strings-in-golang
+func mergeMaps(fromMap, ToMap interface{}) interface{} {
+ switch fromMap := fromMap.(type) {
+ case map[string]interface{}:
+ ToMap, ok := ToMap.(map[string]interface{})
+ if !ok {
+ return fromMap
+ }
+ for keyToMap, valueToMap := range ToMap {
+ if valueFromMap, ok := fromMap[keyToMap]; ok {
+ fromMap[keyToMap] = mergeMaps(valueFromMap, valueToMap)
+ } else {
+ fromMap[keyToMap] = valueToMap
+ }
+ }
+ case nil:
+ // merge(nil, map[string]interface{...}) -> map[string]interface{...}
+ ToMap, ok := ToMap.(map[string]interface{})
+ if ok {
+ return ToMap
+ }
+ }
+ return fromMap
+}
+
+// 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 {
+ return nil, makeContainerError(container, operation, "", err)
+ }
+
+ container.handle = handle
+
+ if err := container.registerCallback(); err != nil {
+ return nil, makeContainerError(container, operation, "", err)
+ }
+
+ logrus.Debugf(title+" succeeded id=%s handle=%d", id, handle)
+ return container, nil
+}
+
+// GetContainers gets a list of the containers on the system that match the query
+func GetContainers(q ComputeSystemQuery) ([]ContainerProperties, error) {
+ operation := "GetContainers"
+ title := "HCSShim::" + operation
+
+ queryb, err := json.Marshal(q)
+ if err != nil {
+ return nil, err
+ }
+
+ query := string(queryb)
+ logrus.Debugf(title+" query=%s", query)
+
+ var (
+ resultp *uint16
+ computeSystemsp *uint16
+ )
+ err = hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp)
+ err = processHcsResult(err, resultp)
+ if err != nil {
+ return nil, err
+ }
+
+ if computeSystemsp == nil {
+ return nil, ErrUnexpectedValue
+ }
+ computeSystemsRaw := convertAndFreeCoTaskMemBytes(computeSystemsp)
+ computeSystems := []ContainerProperties{}
+ if err := json.Unmarshal(computeSystemsRaw, &computeSystems); err != nil {
+ return nil, err
+ }
+
+ logrus.Debugf(title + " succeeded")
+ return computeSystems, nil
+}
+
+// Start synchronously starts the container.
+func (container *container) Start() error {
+ container.handleLock.RLock()
+ defer container.handleLock.RUnlock()
+ operation := "Start"
+ title := "HCSShim::Container::" + operation
+ logrus.Debugf(title+" id=%s", container.id)
+
+ if container.handle == 0 {
+ return makeContainerError(container, operation, "", ErrAlreadyClosed)
+ }
+
+ var resultp *uint16
+ err := hcsStartComputeSystem(container.handle, "", &resultp)
+ err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemStartCompleted, &defaultTimeout)
+ if err != nil {
+ return makeContainerError(container, operation, "", err)
+ }
+
+ logrus.Debugf(title+" succeeded id=%s", container.id)
+ return nil
+}
+
+// Shutdown requests a container shutdown, if IsPending() on the error returned is true,
+// it may not actually be shut down until Wait() succeeds.
+func (container *container) Shutdown() error {
+ container.handleLock.RLock()
+ defer container.handleLock.RUnlock()
+ operation := "Shutdown"
+ title := "HCSShim::Container::" + operation
+ logrus.Debugf(title+" id=%s", container.id)
+
+ if container.handle == 0 {
+ return makeContainerError(container, operation, "", ErrAlreadyClosed)
+ }
+
+ var resultp *uint16
+ err := hcsShutdownComputeSystem(container.handle, "", &resultp)
+ err = processHcsResult(err, resultp)
+ if err != nil {
+ return makeContainerError(container, operation, "", err)
+ }
+
+ logrus.Debugf(title+" succeeded id=%s", container.id)
+ return nil
+}
+
+// Terminate requests a container terminate, if IsPending() on the error returned is true,
+// it may not actually be shut down until Wait() succeeds.
+func (container *container) Terminate() error {
+ container.handleLock.RLock()
+ defer container.handleLock.RUnlock()
+ operation := "Terminate"
+ title := "HCSShim::Container::" + operation
+ logrus.Debugf(title+" id=%s", container.id)
+
+ if container.handle == 0 {
+ return makeContainerError(container, operation, "", ErrAlreadyClosed)
+ }
+
+ var resultp *uint16
+ err := hcsTerminateComputeSystem(container.handle, "", &resultp)
+ err = processHcsResult(err, resultp)
+ if err != nil {
+ return makeContainerError(container, operation, "", 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)
+
+ err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, nil)
+ if err != nil {
+ return makeContainerError(container, operation, "", err)
+ }
+
+ logrus.Debugf(title+" succeeded id=%s", container.id)
+ return nil
+}
+
+// WaitTimeout synchronously waits for the container to terminate or the duration to elapse.
+// If the timeout expires, IsTimeout(err) == true
+func (container *container) WaitTimeout(timeout time.Duration) error {
+ operation := "WaitTimeout"
+ title := "HCSShim::Container::" + operation
+ logrus.Debugf(title+" id=%s", container.id)
+
+ err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, &timeout)
+ if err != nil {
+ return makeContainerError(container, operation, "", err)
+ }
+
+ logrus.Debugf(title+" succeeded id=%s", container.id)
+ return nil
+}
+
+func (container *container) properties(query string) (*ContainerProperties, error) {
+ var (
+ resultp *uint16
+ propertiesp *uint16
+ )
+ err := hcsGetComputeSystemProperties(container.handle, query, &propertiesp, &resultp)
+ err = processHcsResult(err, resultp)
+ if err != nil {
+ return nil, err
+ }
+
+ if propertiesp == nil {
+ return nil, ErrUnexpectedValue
+ }
+ 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) {
+ container.handleLock.RLock()
+ defer container.handleLock.RUnlock()
+ operation := "HasPendingUpdates"
+ title := "HCSShim::Container::" + operation
+ logrus.Debugf(title+" id=%s", container.id)
+
+ if container.handle == 0 {
+ return false, makeContainerError(container, operation, "", ErrAlreadyClosed)
+ }
+
+ properties, err := container.properties(pendingUpdatesQuery)
+ if err != nil {
+ return false, makeContainerError(container, operation, "", err)
+ }
+
+ logrus.Debugf(title+" succeeded id=%s", container.id)
+ return properties.AreUpdatesPending, nil
+}
+
+// Statistics returns statistics for the container
+func (container *container) Statistics() (Statistics, error) {
+ container.handleLock.RLock()
+ defer container.handleLock.RUnlock()
+ operation := "Statistics"
+ title := "HCSShim::Container::" + operation
+ logrus.Debugf(title+" id=%s", container.id)
+
+ if container.handle == 0 {
+ return Statistics{}, makeContainerError(container, operation, "", ErrAlreadyClosed)
+ }
+
+ properties, err := container.properties(statisticsQuery)
+ if err != nil {
+ return Statistics{}, makeContainerError(container, operation, "", err)
+ }
+
+ logrus.Debugf(title+" succeeded id=%s", container.id)
+ return properties.Statistics, nil
+}
+
+// ProcessList returns an array of ProcessListItems for the container
+func (container *container) ProcessList() ([]ProcessListItem, error) {
+ container.handleLock.RLock()
+ defer container.handleLock.RUnlock()
+ operation := "ProcessList"
+ title := "HCSShim::Container::" + operation
+ logrus.Debugf(title+" id=%s", container.id)
+
+ if container.handle == 0 {
+ return nil, makeContainerError(container, operation, "", ErrAlreadyClosed)
+ }
+
+ properties, err := container.properties(processListQuery)
+ if err != nil {
+ return nil, makeContainerError(container, operation, "", err)
+ }
+
+ logrus.Debugf(title+" succeeded id=%s", container.id)
+ return properties.ProcessList, nil
+}
+
+// MappedVirtualDisks returns a map of the controllers and the disks mapped
+// to a container.
+//
+// Example of JSON returned by the query.
+//{
+// "Id":"1126e8d7d279c707a666972a15976371d365eaf622c02cea2c442b84f6f550a3_svm",
+// "SystemType":"Container",
+// "RuntimeOsType":"Linux",
+// "RuntimeId":"00000000-0000-0000-0000-000000000000",
+// "State":"Running",
+// "MappedVirtualDiskControllers":{
+// "0":{
+// "MappedVirtualDisks":{
+// "2":{
+// "HostPath":"C:\\lcow\\lcow\\scratch\\1126e8d7d279c707a666972a15976371d365eaf622c02cea2c442b84f6f550a3.vhdx",
+// "ContainerPath":"/mnt/gcs/LinuxServiceVM/scratch",
+// "Lun":2,
+// "CreateInUtilityVM":true
+// },
+// "3":{
+// "HostPath":"C:\\lcow\\lcow\\1126e8d7d279c707a666972a15976371d365eaf622c02cea2c442b84f6f550a3\\sandbox.vhdx",
+// "Lun":3,
+// "CreateInUtilityVM":true,
+// "AttachOnly":true
+// }
+// }
+// }
+// }
+//}
+func (container *container) MappedVirtualDisks() (map[int]MappedVirtualDiskController, error) {
+ container.handleLock.RLock()
+ defer container.handleLock.RUnlock()
+ operation := "MappedVirtualDiskList"
+ title := "HCSShim::Container::" + operation
+ logrus.Debugf(title+" id=%s", container.id)
+
+ if container.handle == 0 {
+ return nil, makeContainerError(container, operation, "", ErrAlreadyClosed)
+ }
+
+ properties, err := container.properties(mappedVirtualDiskQuery)
+ if err != nil {
+ return nil, makeContainerError(container, operation, "", err)
+ }
+
+ logrus.Debugf(title+" succeeded id=%s", container.id)
+ return properties.MappedVirtualDiskControllers, nil
+}
+
+// Pause pauses the execution of the container. This feature is not enabled in TP5.
+func (container *container) Pause() error {
+ container.handleLock.RLock()
+ defer container.handleLock.RUnlock()
+ operation := "Pause"
+ title := "HCSShim::Container::" + operation
+ logrus.Debugf(title+" id=%s", container.id)
+
+ if container.handle == 0 {
+ return makeContainerError(container, operation, "", ErrAlreadyClosed)
+ }
+
+ var resultp *uint16
+ err := hcsPauseComputeSystem(container.handle, "", &resultp)
+ err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemPauseCompleted, &defaultTimeout)
+ if err != nil {
+ return makeContainerError(container, operation, "", 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 {
+ container.handleLock.RLock()
+ defer container.handleLock.RUnlock()
+ operation := "Resume"
+ title := "HCSShim::Container::" + operation
+ logrus.Debugf(title+" id=%s", container.id)
+
+ if container.handle == 0 {
+ return makeContainerError(container, operation, "", ErrAlreadyClosed)
+ }
+
+ var resultp *uint16
+ err := hcsResumeComputeSystem(container.handle, "", &resultp)
+ err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemResumeCompleted, &defaultTimeout)
+ if err != nil {
+ return makeContainerError(container, operation, "", 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) {
+ container.handleLock.RLock()
+ defer container.handleLock.RUnlock()
+ operation := "CreateProcess"
+ title := "HCSShim::Container::" + operation
+ var (
+ processInfo hcsProcessInformation
+ processHandle hcsProcess
+ resultp *uint16
+ )
+
+ if container.handle == 0 {
+ return nil, makeContainerError(container, operation, "", ErrAlreadyClosed)
+ }
+
+ // 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, makeContainerError(container, operation, "", err)
+ }
+
+ configuration := string(configurationb)
+ logrus.Debugf(title+" id=%s config=%s", container.id, configuration)
+
+ err = hcsCreateProcess(container.handle, configuration, &processInfo, &processHandle, &resultp)
+ err = processHcsResult(err, resultp)
+ if err != nil {
+ return nil, makeContainerError(container, operation, configuration, err)
+ }
+
+ process := &process{
+ handle: processHandle,
+ processID: int(processInfo.ProcessId),
+ container: container,
+ cachedPipes: &cachedPipes{
+ stdIn: processInfo.StdInput,
+ stdOut: processInfo.StdOutput,
+ stdErr: processInfo.StdError,
+ },
+ }
+
+ if err := process.registerCallback(); err != nil {
+ return nil, makeContainerError(container, operation, "", err)
+ }
+
+ logrus.Debugf(title+" succeeded id=%s processid=%d", container.id, process.processID)
+ return process, nil
+}
+
+// OpenProcess gets an interface to an existing process within the container.
+func (container *container) OpenProcess(pid int) (Process, error) {
+ container.handleLock.RLock()
+ defer container.handleLock.RUnlock()
+ operation := "OpenProcess"
+ title := "HCSShim::Container::" + operation
+ logrus.Debugf(title+" id=%s, processid=%d", container.id, pid)
+ var (
+ processHandle hcsProcess
+ resultp *uint16
+ )
+
+ if container.handle == 0 {
+ return nil, makeContainerError(container, operation, "", ErrAlreadyClosed)
+ }
+
+ err := hcsOpenProcess(container.handle, uint32(pid), &processHandle, &resultp)
+ err = processHcsResult(err, resultp)
+ if err != nil {
+ return nil, makeContainerError(container, operation, "", err)
+ }
+
+ process := &process{
+ handle: processHandle,
+ processID: pid,
+ container: container,
+ }
+
+ if err := process.registerCallback(); err != nil {
+ return nil, makeContainerError(container, operation, "", err)
+ }
+
+ logrus.Debugf(title+" succeeded id=%s processid=%s", container.id, process.processID)
+ 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 {
+ container.handleLock.Lock()
+ defer container.handleLock.Unlock()
+ 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 := container.unregisterCallback(); err != nil {
+ return makeContainerError(container, operation, "", err)
+ }
+
+ if err := hcsCloseComputeSystem(container.handle); err != nil {
+ return makeContainerError(container, operation, "", err)
+ }
+
+ container.handle = 0
+
+ logrus.Debugf(title+" succeeded id=%s", container.id)
+ return nil
+}
+
+func (container *container) registerCallback() error {
+ context := &notifcationWatcherContext{
+ channels: newChannels(),
+ }
+
+ callbackMapLock.Lock()
+ callbackNumber := nextCallback
+ nextCallback++
+ callbackMap[callbackNumber] = context
+ callbackMapLock.Unlock()
+
+ var callbackHandle hcsCallback
+ err := hcsRegisterComputeSystemCallback(container.handle, notificationWatcherCallback, callbackNumber, &callbackHandle)
+ if err != nil {
+ return err
+ }
+ context.handle = callbackHandle
+ container.callbackNumber = callbackNumber
+
+ return nil
+}
+
+func (container *container) unregisterCallback() error {
+ callbackNumber := container.callbackNumber
+
+ callbackMapLock.RLock()
+ context := callbackMap[callbackNumber]
+ callbackMapLock.RUnlock()
+
+ if context == nil {
+ return nil
+ }
+
+ handle := context.handle
+
+ if handle == 0 {
+ return nil
+ }
+
+ // hcsUnregisterComputeSystemCallback has its own syncronization
+ // to wait for all callbacks to complete. We must NOT hold the callbackMapLock.
+ err := hcsUnregisterComputeSystemCallback(handle)
+ if err != nil {
+ return err
+ }
+
+ closeChannels(context.channels)
+
+ callbackMapLock.Lock()
+ callbackMap[callbackNumber] = nil
+ callbackMapLock.Unlock()
+
+ handle = 0
+
+ return nil
+}
+
+// Modifies the System by sending a request to HCS
+func (container *container) Modify(config *ResourceModificationRequestResponse) error {
+ container.handleLock.RLock()
+ defer container.handleLock.RUnlock()
+ operation := "Modify"
+ title := "HCSShim::Container::" + operation
+
+ if container.handle == 0 {
+ return makeContainerError(container, operation, "", ErrAlreadyClosed)
+ }
+
+ requestJSON, err := json.Marshal(config)
+ if err != nil {
+ return err
+ }
+
+ requestString := string(requestJSON)
+ logrus.Debugf(title+" id=%s request=%s", container.id, requestString)
+
+ var resultp *uint16
+ err = hcsModifyComputeSystem(container.handle, requestString, &resultp)
+ err = processHcsResult(err, resultp)
+ if err != nil {
+ return makeContainerError(container, operation, "", err)
+ }
+ logrus.Debugf(title+" succeeded id=%s", container.id)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/createlayer.go b/vendor/github.com/Microsoft/hcsshim/createlayer.go
new file mode 100644
index 000000000..035d9c394
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/createlayer.go
@@ -0,0 +1,27 @@
+package hcsshim
+
+import "github.com/sirupsen/logrus"
+
+// CreateLayer creates a new, empty, read-only layer on the filesystem based on
+// the parent layer provided.
+func CreateLayer(info DriverInfo, id, parent string) error {
+ title := "hcsshim::CreateLayer "
+ logrus.Debugf(title+"Flavour %d ID %s parent %s", info.Flavour, id, parent)
+
+ // Convert info to API calling convention
+ infop, err := convertDriverInfo(info)
+ if err != nil {
+ logrus.Error(err)
+ return err
+ }
+
+ err = createLayer(&infop, id, parent)
+ if err != nil {
+ err = makeErrorf(err, title, "id=%s parent=%s flavour=%d", id, parent, info.Flavour)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+" - succeeded id=%s parent=%s flavour=%d", id, parent, info.Flavour)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/createsandboxlayer.go b/vendor/github.com/Microsoft/hcsshim/createsandboxlayer.go
new file mode 100644
index 000000000..7a6a8854c
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/createsandboxlayer.go
@@ -0,0 +1,35 @@
+package hcsshim
+
+import "github.com/sirupsen/logrus"
+
+// CreateSandboxLayer creates and populates new read-write layer for use by a container.
+// This requires both the id of the direct parent layer, as well as the full list
+// of paths to all parent layers up to the base (and including the direct parent
+// whose id was provided).
+func CreateSandboxLayer(info DriverInfo, layerId, parentId string, parentLayerPaths []string) error {
+ title := "hcsshim::CreateSandboxLayer "
+ logrus.Debugf(title+"layerId %s parentId %s", layerId, parentId)
+
+ // Generate layer descriptors
+ layers, err := layerPathsToDescriptors(parentLayerPaths)
+ if err != nil {
+ return err
+ }
+
+ // Convert info to API calling convention
+ infop, err := convertDriverInfo(info)
+ if err != nil {
+ logrus.Error(err)
+ return err
+ }
+
+ err = createSandboxLayer(&infop, layerId, parentId, layers)
+ if err != nil {
+ err = makeErrorf(err, title, "layerId=%s parentId=%s", layerId, parentId)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"- succeeded layerId=%s parentId=%s", layerId, parentId)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/deactivatelayer.go b/vendor/github.com/Microsoft/hcsshim/deactivatelayer.go
new file mode 100644
index 000000000..fd785030f
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/deactivatelayer.go
@@ -0,0 +1,26 @@
+package hcsshim
+
+import "github.com/sirupsen/logrus"
+
+// DeactivateLayer will dismount a layer that was mounted via ActivateLayer.
+func DeactivateLayer(info DriverInfo, id string) error {
+ title := "hcsshim::DeactivateLayer "
+ logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id)
+
+ // Convert info to API calling convention
+ infop, err := convertDriverInfo(info)
+ if err != nil {
+ logrus.Error(err)
+ return err
+ }
+
+ err = deactivateLayer(&infop, id)
+ if err != nil {
+ err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"succeeded flavour=%d id=%s", info.Flavour, id)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/destroylayer.go b/vendor/github.com/Microsoft/hcsshim/destroylayer.go
new file mode 100644
index 000000000..b1e3b89fc
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/destroylayer.go
@@ -0,0 +1,27 @@
+package hcsshim
+
+import "github.com/sirupsen/logrus"
+
+// DestroyLayer will remove the on-disk files representing the layer with the given
+// id, including that layer's containing folder, if any.
+func DestroyLayer(info DriverInfo, id string) error {
+ title := "hcsshim::DestroyLayer "
+ logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id)
+
+ // Convert info to API calling convention
+ infop, err := convertDriverInfo(info)
+ if err != nil {
+ logrus.Error(err)
+ return err
+ }
+
+ err = destroyLayer(&infop, id)
+ if err != nil {
+ err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"succeeded flavour=%d id=%s", info.Flavour, id)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/errors.go b/vendor/github.com/Microsoft/hcsshim/errors.go
new file mode 100644
index 000000000..d2f9cc8bd
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/errors.go
@@ -0,0 +1,239 @@
+package hcsshim
+
+import (
+ "errors"
+ "fmt"
+ "syscall"
+)
+
+var (
+ // ErrComputeSystemDoesNotExist is an error encountered when the container being operated on no longer exists
+ ErrComputeSystemDoesNotExist = syscall.Errno(0xc037010e)
+
+ // ErrElementNotFound is an error encountered when the object being referenced does not exist
+ ErrElementNotFound = syscall.Errno(0x490)
+
+ // ErrElementNotFound is an error encountered when the object being referenced does not exist
+ ErrNotSupported = syscall.Errno(0x32)
+
+ // ErrInvalidData is an error encountered when the request being sent to hcs is invalid/unsupported
+ // decimal -2147024883 / hex 0x8007000d
+ ErrInvalidData = syscall.Errno(0xd)
+
+ // ErrHandleClose is an error encountered when the handle generating the notification being waited on has been closed
+ ErrHandleClose = errors.New("hcsshim: the handle generating this notification has been closed")
+
+ // ErrAlreadyClosed is an error encountered when using a handle that has been closed by the Close method
+ ErrAlreadyClosed = errors.New("hcsshim: the handle has already been closed")
+
+ // ErrInvalidNotificationType is an error encountered when an invalid notification type is used
+ ErrInvalidNotificationType = errors.New("hcsshim: invalid notification type")
+
+ // ErrInvalidProcessState is an error encountered when the process is not in a valid state for the requested operation
+ ErrInvalidProcessState = errors.New("the process is in an invalid state for the attempted operation")
+
+ // ErrTimeout is an error encountered when waiting on a notification times out
+ ErrTimeout = errors.New("hcsshim: timeout waiting for notification")
+
+ // ErrUnexpectedContainerExit is the error encountered when a container exits while waiting for
+ // a different expected notification
+ ErrUnexpectedContainerExit = errors.New("unexpected container exit")
+
+ // ErrUnexpectedProcessAbort is the error encountered when communication with the compute service
+ // is lost while waiting for a notification
+ ErrUnexpectedProcessAbort = errors.New("lost communication with compute service")
+
+ // ErrUnexpectedValue is an error encountered when hcs returns an invalid value
+ ErrUnexpectedValue = errors.New("unexpected value returned from hcs")
+
+ // ErrVmcomputeAlreadyStopped is an error encountered when a shutdown or terminate request is made on a stopped container
+ ErrVmcomputeAlreadyStopped = syscall.Errno(0xc0370110)
+
+ // ErrVmcomputeOperationPending is an error encountered when the operation is being completed asynchronously
+ ErrVmcomputeOperationPending = syscall.Errno(0xC0370103)
+
+ // ErrVmcomputeOperationInvalidState is an error encountered when the compute system is not in a valid state for the requested operation
+ ErrVmcomputeOperationInvalidState = syscall.Errno(0xc0370105)
+
+ // ErrProcNotFound is an error encountered when the the process cannot be found
+ ErrProcNotFound = syscall.Errno(0x7f)
+
+ // ErrVmcomputeOperationAccessIsDenied is an error which can be encountered when enumerating compute systems in RS1/RS2
+ // builds when the underlying silo might be in the process of terminating. HCS was fixed in RS3.
+ ErrVmcomputeOperationAccessIsDenied = syscall.Errno(0x5)
+
+ // ErrVmcomputeInvalidJSON is an error encountered when the compute system does not support/understand the messages sent by management
+ ErrVmcomputeInvalidJSON = syscall.Errno(0xc037010d)
+
+ // ErrVmcomputeUnknownMessage is an error encountered guest compute system doesn't support the message
+ ErrVmcomputeUnknownMessage = syscall.Errno(0xc037010b)
+
+ // ErrNotSupported is an error encountered when hcs doesn't support the request
+ ErrPlatformNotSupported = errors.New("unsupported platform request")
+)
+
+// ProcessError is an error encountered in HCS during an operation on a Process object
+type ProcessError struct {
+ Process *process
+ Operation string
+ ExtraInfo string
+ Err error
+}
+
+// ContainerError is an error encountered in HCS during an operation on a Container object
+type ContainerError struct {
+ Container *container
+ Operation string
+ ExtraInfo string
+ Err error
+}
+
+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
+ }
+
+ switch e.Err.(type) {
+ case nil:
+ break
+ case syscall.Errno:
+ s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, win32FromError(e.Err))
+ default:
+ s += fmt.Sprintf(": %s", e.Err.Error())
+ }
+
+ if e.ExtraInfo != "" {
+ s += " extra info: " + e.ExtraInfo
+ }
+
+ return s
+}
+
+func makeContainerError(container *container, operation string, extraInfo string, err error) error {
+ // Don't double wrap errors
+ if _, ok := err.(*ContainerError); ok {
+ return err
+ }
+ containerError := &ContainerError{Container: container, Operation: operation, ExtraInfo: extraInfo, Err: err}
+ return containerError
+}
+
+func (e *ProcessError) Error() string {
+ 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 += " encountered an error during " + e.Operation
+ }
+
+ switch e.Err.(type) {
+ case nil:
+ break
+ case syscall.Errno:
+ s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, win32FromError(e.Err))
+ default:
+ s += fmt.Sprintf(": %s", e.Err.Error())
+ }
+
+ return s
+}
+
+func makeProcessError(process *process, operation string, extraInfo string, err error) error {
+ // Don't double wrap errors
+ if _, ok := err.(*ProcessError); ok {
+ return err
+ }
+ processError := &ProcessError{Process: process, Operation: operation, ExtraInfo: extraInfo, Err: err}
+ return processError
+}
+
+// IsNotExist checks if an error is caused by the Container or Process not existing.
+// Note: Currently, ErrElementNotFound can mean that a Process has either
+// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
+// will currently return true when the error is ErrElementNotFound or ErrProcNotFound.
+func IsNotExist(err error) bool {
+ err = getInnerError(err)
+ return err == ErrComputeSystemDoesNotExist ||
+ err == ErrElementNotFound ||
+ err == ErrProcNotFound
+}
+
+// IsAlreadyClosed checks if an error is caused by the Container or Process having been
+// already closed by a call to the Close() method.
+func IsAlreadyClosed(err error) bool {
+ err = getInnerError(err)
+ return err == ErrAlreadyClosed
+}
+
+// IsPending returns a boolean indicating whether the error is that
+// the requested operation is being completed in the background.
+func IsPending(err error) bool {
+ err = getInnerError(err)
+ return err == ErrVmcomputeOperationPending
+}
+
+// IsTimeout returns a boolean indicating whether the error is caused by
+// a timeout waiting for the operation to complete.
+func IsTimeout(err error) bool {
+ err = getInnerError(err)
+ return err == ErrTimeout
+}
+
+// IsAlreadyStopped returns a boolean indicating whether the error is caused by
+// a Container or Process being already stopped.
+// Note: Currently, ErrElementNotFound can mean that a Process has either
+// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
+// will currently return true when the error is ErrElementNotFound or ErrProcNotFound.
+func IsAlreadyStopped(err error) bool {
+ err = getInnerError(err)
+ return err == ErrVmcomputeAlreadyStopped ||
+ err == ErrElementNotFound ||
+ err == ErrProcNotFound
+}
+
+// IsNotSupported returns a boolean indicating whether the error is caused by
+// unsupported platform requests
+// Note: Currently Unsupported platform requests can be mean either
+// ErrVmcomputeInvalidJSON, ErrInvalidData, ErrNotSupported or ErrVmcomputeUnknownMessage
+// is thrown from the Platform
+func IsNotSupported(err error) bool {
+ err = getInnerError(err)
+ // If Platform doesn't recognize or support the request sent, below errors are seen
+ return err == ErrVmcomputeInvalidJSON ||
+ err == ErrInvalidData ||
+ err == ErrNotSupported ||
+ err == ErrVmcomputeUnknownMessage
+}
+
+func getInnerError(err error) error {
+ switch pe := err.(type) {
+ case nil:
+ return nil
+ case *ContainerError:
+ err = pe.Err
+ case *ProcessError:
+ err = pe.Err
+ }
+ return err
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/expandsandboxsize.go b/vendor/github.com/Microsoft/hcsshim/expandsandboxsize.go
new file mode 100644
index 000000000..6946c6a84
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/expandsandboxsize.go
@@ -0,0 +1,26 @@
+package hcsshim
+
+import "github.com/sirupsen/logrus"
+
+// ExpandSandboxSize expands the size of a layer to at least size bytes.
+func ExpandSandboxSize(info DriverInfo, layerId string, size uint64) error {
+ title := "hcsshim::ExpandSandboxSize "
+ logrus.Debugf(title+"layerId=%s size=%d", layerId, size)
+
+ // Convert info to API calling convention
+ infop, err := convertDriverInfo(info)
+ if err != nil {
+ logrus.Error(err)
+ return err
+ }
+
+ err = expandSandboxSize(&infop, layerId, size)
+ if err != nil {
+ err = makeErrorf(err, title, "layerId=%s size=%d", layerId, size)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"- succeeded layerId=%s size=%d", layerId, size)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/exportlayer.go b/vendor/github.com/Microsoft/hcsshim/exportlayer.go
new file mode 100644
index 000000000..d7025f20b
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/exportlayer.go
@@ -0,0 +1,156 @@
+package hcsshim
+
+import (
+ "io"
+ "io/ioutil"
+ "os"
+ "syscall"
+
+ "github.com/Microsoft/go-winio"
+ "github.com/sirupsen/logrus"
+)
+
+// ExportLayer will create a folder at exportFolderPath and fill that folder with
+// the transport format version of the layer identified by layerId. This transport
+// format includes any metadata required for later importing the layer (using
+// ImportLayer), and requires the full list of parent layer paths in order to
+// perform the export.
+func ExportLayer(info DriverInfo, layerId string, exportFolderPath string, parentLayerPaths []string) error {
+ title := "hcsshim::ExportLayer "
+ logrus.Debugf(title+"flavour %d layerId %s folder %s", info.Flavour, layerId, exportFolderPath)
+
+ // Generate layer descriptors
+ layers, err := layerPathsToDescriptors(parentLayerPaths)
+ if err != nil {
+ return err
+ }
+
+ // Convert info to API calling convention
+ infop, err := convertDriverInfo(info)
+ if err != nil {
+ logrus.Error(err)
+ return err
+ }
+
+ err = exportLayer(&infop, layerId, exportFolderPath, layers)
+ if err != nil {
+ err = makeErrorf(err, title, "layerId=%s flavour=%d folder=%s", layerId, info.Flavour, exportFolderPath)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"succeeded flavour=%d layerId=%s folder=%s", info.Flavour, layerId, exportFolderPath)
+ return nil
+}
+
+type LayerReader interface {
+ Next() (string, int64, *winio.FileBasicInfo, error)
+ Read(b []byte) (int, error)
+ Close() error
+}
+
+// FilterLayerReader provides an interface for extracting the contents of an on-disk layer.
+type FilterLayerReader struct {
+ context uintptr
+}
+
+// Next reads the next available file from a layer, ensuring that parent directories are always read
+// before child files and directories.
+//
+// Next returns the file's relative path, size, and basic file metadata. Read() should be used to
+// extract a Win32 backup stream with the remainder of the metadata and the data.
+func (r *FilterLayerReader) Next() (string, int64, *winio.FileBasicInfo, error) {
+ var fileNamep *uint16
+ fileInfo := &winio.FileBasicInfo{}
+ var deleted uint32
+ var fileSize int64
+ err := exportLayerNext(r.context, &fileNamep, fileInfo, &fileSize, &deleted)
+ if err != nil {
+ if err == syscall.ERROR_NO_MORE_FILES {
+ err = io.EOF
+ } else {
+ err = makeError(err, "ExportLayerNext", "")
+ }
+ return "", 0, nil, err
+ }
+ fileName := convertAndFreeCoTaskMemString(fileNamep)
+ if deleted != 0 {
+ fileInfo = nil
+ }
+ if fileName[0] == '\\' {
+ fileName = fileName[1:]
+ }
+ return fileName, fileSize, fileInfo, nil
+}
+
+// Read reads from the current file's Win32 backup stream.
+func (r *FilterLayerReader) Read(b []byte) (int, error) {
+ var bytesRead uint32
+ err := exportLayerRead(r.context, b, &bytesRead)
+ if err != nil {
+ return 0, makeError(err, "ExportLayerRead", "")
+ }
+ if bytesRead == 0 {
+ return 0, io.EOF
+ }
+ return int(bytesRead), nil
+}
+
+// Close frees resources associated with the layer reader. It will return an
+// error if there was an error while reading the layer or of the layer was not
+// completely read.
+func (r *FilterLayerReader) Close() (err error) {
+ if r.context != 0 {
+ err = exportLayerEnd(r.context)
+ if err != nil {
+ err = makeError(err, "ExportLayerEnd", "")
+ }
+ r.context = 0
+ }
+ return
+}
+
+// NewLayerReader returns a new layer reader for reading the contents of an on-disk layer.
+// 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.
+ path, err := ioutil.TempDir("", "hcs")
+ if err != nil {
+ return nil, err
+ }
+ err = ExportLayer(info, layerID, path, parentLayerPaths)
+ if err != nil {
+ os.RemoveAll(path)
+ return nil, err
+ }
+ return &legacyLayerReaderWrapper{newLegacyLayerReader(path)}, nil
+ }
+
+ layers, err := layerPathsToDescriptors(parentLayerPaths)
+ if err != nil {
+ return nil, err
+ }
+ infop, err := convertDriverInfo(info)
+ if err != nil {
+ return nil, err
+ }
+ r := &FilterLayerReader{}
+ err = exportLayerBegin(&infop, layerID, layers, &r.context)
+ if err != nil {
+ return nil, makeError(err, "ExportLayerBegin", "")
+ }
+ return r, err
+}
+
+type legacyLayerReaderWrapper struct {
+ *legacyLayerReader
+}
+
+func (r *legacyLayerReaderWrapper) Close() error {
+ err := r.legacyLayerReader.Close()
+ os.RemoveAll(r.root)
+ return err
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/getlayermountpath.go b/vendor/github.com/Microsoft/hcsshim/getlayermountpath.go
new file mode 100644
index 000000000..89f8079d0
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/getlayermountpath.go
@@ -0,0 +1,55 @@
+package hcsshim
+
+import (
+ "syscall"
+
+ "github.com/sirupsen/logrus"
+)
+
+// GetLayerMountPath will look for a mounted layer with the given id and return
+// the path at which that layer can be accessed. This path may be a volume path
+// if the layer is a mounted read-write layer, otherwise it is expected to be the
+// folder path at which the layer is stored.
+func GetLayerMountPath(info DriverInfo, id string) (string, error) {
+ title := "hcsshim::GetLayerMountPath "
+ logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id)
+
+ // Convert info to API calling convention
+ infop, err := convertDriverInfo(info)
+ if err != nil {
+ logrus.Error(err)
+ return "", err
+ }
+
+ var mountPathLength uintptr
+ mountPathLength = 0
+
+ // Call the procedure itself.
+ logrus.Debugf("Calling proc (1)")
+ err = getLayerMountPath(&infop, id, &mountPathLength, nil)
+ if err != nil {
+ err = makeErrorf(err, title, "(first call) id=%s flavour=%d", id, info.Flavour)
+ logrus.Error(err)
+ return "", err
+ }
+
+ // Allocate a mount path of the returned length.
+ if mountPathLength == 0 {
+ return "", nil
+ }
+ mountPathp := make([]uint16, mountPathLength)
+ mountPathp[0] = 0
+
+ // Call the procedure again
+ logrus.Debugf("Calling proc (2)")
+ err = getLayerMountPath(&infop, id, &mountPathLength, &mountPathp[0])
+ if err != nil {
+ err = makeErrorf(err, title, "(second call) id=%s flavour=%d", id, info.Flavour)
+ logrus.Error(err)
+ return "", err
+ }
+
+ path := syscall.UTF16ToString(mountPathp[0:])
+ logrus.Debugf(title+"succeeded flavour=%d id=%s path=%s", info.Flavour, id, path)
+ return path, nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/getsharedbaseimages.go b/vendor/github.com/Microsoft/hcsshim/getsharedbaseimages.go
new file mode 100644
index 000000000..05d3d9532
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/getsharedbaseimages.go
@@ -0,0 +1,22 @@
+package hcsshim
+
+import "github.com/sirupsen/logrus"
+
+// GetSharedBaseImages will enumerate the images stored in the common central
+// image store and return descriptive info about those images for the purpose
+// of registering them with the graphdriver, graph, and tagstore.
+func GetSharedBaseImages() (imageData string, err error) {
+ title := "hcsshim::GetSharedBaseImages "
+
+ logrus.Debugf("Calling proc")
+ var buffer *uint16
+ err = getBaseImages(&buffer)
+ if err != nil {
+ err = makeError(err, title, "")
+ logrus.Error(err)
+ return
+ }
+ imageData = convertAndFreeCoTaskMemString(buffer)
+ logrus.Debugf(title+" - succeeded output=%s", imageData)
+ return
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/guid.go b/vendor/github.com/Microsoft/hcsshim/guid.go
new file mode 100644
index 000000000..620aba123
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/guid.go
@@ -0,0 +1,19 @@
+package hcsshim
+
+import (
+ "crypto/sha1"
+ "fmt"
+)
+
+type GUID [16]byte
+
+func NewGUID(source string) *GUID {
+ h := sha1.Sum([]byte(source))
+ var g GUID
+ copy(g[0:], h[0:16])
+ return &g
+}
+
+func (g *GUID) ToString() string {
+ return fmt.Sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x-%02x", g[3], g[2], g[1], g[0], g[5], g[4], g[7], g[6], g[8:10], g[10:])
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/hcsshim.go b/vendor/github.com/Microsoft/hcsshim/hcsshim.go
new file mode 100644
index 000000000..236ba1fa3
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/hcsshim.go
@@ -0,0 +1,166 @@
+// Shim for the Host Compute Service (HCS) to manage Windows Server
+// containers and Hyper-V containers.
+
+package hcsshim
+
+import (
+ "fmt"
+ "syscall"
+ "unsafe"
+
+ "github.com/sirupsen/logrus"
+)
+
+//go:generate go run mksyscall_windows.go -output zhcsshim.go hcsshim.go
+
+//sys coTaskMemFree(buffer unsafe.Pointer) = ole32.CoTaskMemFree
+//sys SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) = iphlpapi.SetCurrentThreadCompartmentId
+
+//sys activateLayer(info *driverInfo, id string) (hr error) = vmcompute.ActivateLayer?
+//sys copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CopyLayer?
+//sys createLayer(info *driverInfo, id string, parent string) (hr error) = vmcompute.CreateLayer?
+//sys createSandboxLayer(info *driverInfo, id string, parent string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.CreateSandboxLayer?
+//sys expandSandboxSize(info *driverInfo, id string, size uint64) (hr error) = vmcompute.ExpandSandboxSize?
+//sys deactivateLayer(info *driverInfo, id string) (hr error) = vmcompute.DeactivateLayer?
+//sys destroyLayer(info *driverInfo, id string) (hr error) = vmcompute.DestroyLayer?
+//sys exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ExportLayer?
+//sys getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) = vmcompute.GetLayerMountPath?
+//sys getBaseImages(buffer **uint16) (hr error) = vmcompute.GetBaseImages?
+//sys importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.ImportLayer?
+//sys layerExists(info *driverInfo, id string, exists *uint32) (hr error) = vmcompute.LayerExists?
+//sys nameToGuid(name string, guid *GUID) (hr error) = vmcompute.NameToGuid?
+//sys prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) = vmcompute.PrepareLayer?
+//sys unprepareLayer(info *driverInfo, id string) (hr error) = vmcompute.UnprepareLayer?
+//sys processBaseImage(path string) (hr error) = vmcompute.ProcessBaseImage?
+//sys processUtilityImage(path string) (hr error) = vmcompute.ProcessUtilityImage?
+
+//sys importLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) = vmcompute.ImportLayerBegin?
+//sys importLayerNext(context uintptr, fileName string, fileInfo *winio.FileBasicInfo) (hr error) = vmcompute.ImportLayerNext?
+//sys importLayerWrite(context uintptr, buffer []byte) (hr error) = vmcompute.ImportLayerWrite?
+//sys importLayerEnd(context uintptr) (hr error) = vmcompute.ImportLayerEnd?
+
+//sys exportLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) = vmcompute.ExportLayerBegin?
+//sys exportLayerNext(context uintptr, fileName **uint16, fileInfo *winio.FileBasicInfo, fileSize *int64, deleted *uint32) (hr error) = vmcompute.ExportLayerNext?
+//sys exportLayerRead(context uintptr, buffer []byte, bytesRead *uint32) (hr error) = vmcompute.ExportLayerRead?
+//sys exportLayerEnd(context uintptr) (hr error) = vmcompute.ExportLayerEnd?
+
+//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 hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterComputeSystemCallback?
+//sys hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterComputeSystemCallback?
+
+//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 hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetServiceProperties?
+//sys hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterProcessCallback?
+//sys hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterProcessCallback?
+
+//sys hcsModifyServiceSettings(settings string, result **uint16) (hr error) = vmcompute.HcsModifyServiceSettings?
+
+//sys _hnsCall(method string, path string, object string, response **uint16) (hr error) = vmcompute.HNSCall?
+
+const (
+ // Specific user-visible exit codes
+ WaitErrExecFailed = 32767
+
+ ERROR_GEN_FAILURE = syscall.Errno(31)
+ ERROR_SHUTDOWN_IN_PROGRESS = syscall.Errno(1115)
+ WSAEINVAL = syscall.Errno(10022)
+
+ // Timeout on wait calls
+ TimeoutInfinite = 0xFFFFFFFF
+)
+
+type HcsError struct {
+ title string
+ rest string
+ 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 {
+ return err
+ }
+ return &HcsError{title, rest, err}
+}
+
+func makeErrorf(err error, title, format string, a ...interface{}) error {
+ return makeError(err, title, fmt.Sprintf(format, a...))
+}
+
+func win32FromError(err error) uint32 {
+ if herr, ok := err.(*HcsError); ok {
+ return win32FromError(herr.Err)
+ }
+ if code, ok := err.(syscall.Errno); ok {
+ return uint32(code)
+ }
+ return uint32(ERROR_GEN_FAILURE)
+}
+
+func win32FromHresult(hr uintptr) uintptr {
+ if hr&0x1fff0000 == 0x00070000 {
+ return hr & 0xffff
+ }
+ return hr
+}
+
+func (e *HcsError) Error() string {
+ s := e.title
+ if len(s) > 0 && s[len(s)-1] != ' ' {
+ s += " "
+ }
+ s += fmt.Sprintf("failed in Win32: %s (0x%x)", e.Err, win32FromError(e.Err))
+ if e.rest != "" {
+ if e.rest[0] != ' ' {
+ s += " "
+ }
+ s += e.rest
+ }
+ return s
+}
+
+func convertAndFreeCoTaskMemString(buffer *uint16) string {
+ str := syscall.UTF16ToString((*[1 << 30]uint16)(unsafe.Pointer(buffer))[:])
+ 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
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go b/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go
new file mode 100644
index 000000000..92afc0c24
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/hnsendpoint.go
@@ -0,0 +1,318 @@
+package hcsshim
+
+import (
+ "encoding/json"
+ "fmt"
+ "net"
+
+ "github.com/sirupsen/logrus"
+)
+
+// HNSEndpoint represents a network endpoint in HNS
+type HNSEndpoint struct {
+ Id string `json:"ID,omitempty"`
+ Name string `json:",omitempty"`
+ VirtualNetwork string `json:",omitempty"`
+ VirtualNetworkName string `json:",omitempty"`
+ Policies []json.RawMessage `json:",omitempty"`
+ MacAddress string `json:",omitempty"`
+ IPAddress net.IP `json:",omitempty"`
+ DNSSuffix string `json:",omitempty"`
+ DNSServerList string `json:",omitempty"`
+ GatewayAddress string `json:",omitempty"`
+ EnableInternalDNS bool `json:",omitempty"`
+ DisableICC bool `json:",omitempty"`
+ PrefixLength uint8 `json:",omitempty"`
+ IsRemoteEndpoint bool `json:",omitempty"`
+}
+
+//SystemType represents the type of the system on which actions are done
+type SystemType string
+
+// SystemType const
+const (
+ ContainerType SystemType = "Container"
+ VirtualMachineType SystemType = "VirtualMachine"
+ HostType SystemType = "Host"
+)
+
+// EndpointAttachDetachRequest is the structure used to send request to the container to modify the system
+// Supported resource types are Network and Request Types are Add/Remove
+type EndpointAttachDetachRequest struct {
+ ContainerID string `json:"ContainerId,omitempty"`
+ SystemType SystemType `json:"SystemType"`
+ CompartmentID uint16 `json:"CompartmentId,omitempty"`
+ VirtualNICName string `json:"VirtualNicName,omitempty"`
+}
+
+// EndpointResquestResponse is object to get the endpoint request response
+type EndpointResquestResponse struct {
+ Success bool
+ Error string
+}
+
+// HNSEndpointRequest makes a HNS call to modify/query a network endpoint
+func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) {
+ endpoint := &HNSEndpoint{}
+ err := hnsCall(method, "/endpoints/"+path, request, &endpoint)
+ if err != nil {
+ return nil, err
+ }
+
+ return endpoint, nil
+}
+
+// HNSListEndpointRequest makes a HNS call to query the list of available endpoints
+func HNSListEndpointRequest() ([]HNSEndpoint, error) {
+ var endpoint []HNSEndpoint
+ err := hnsCall("GET", "/endpoints/", "", &endpoint)
+ if err != nil {
+ return nil, err
+ }
+
+ return endpoint, nil
+}
+
+// HotAttachEndpoint makes a HCS Call to attach the endpoint to the container
+func HotAttachEndpoint(containerID string, endpointID string) error {
+ return modifyNetworkEndpoint(containerID, endpointID, Add)
+}
+
+// HotDetachEndpoint makes a HCS Call to detach the endpoint from the container
+func HotDetachEndpoint(containerID string, endpointID string) error {
+ return modifyNetworkEndpoint(containerID, endpointID, Remove)
+}
+
+// ModifyContainer corresponding to the container id, by sending a request
+func modifyContainer(id string, request *ResourceModificationRequestResponse) error {
+ container, err := OpenContainer(id)
+ if err != nil {
+ if IsNotExist(err) {
+ return ErrComputeSystemDoesNotExist
+ }
+ return getInnerError(err)
+ }
+ defer container.Close()
+ err = container.Modify(request)
+ if err != nil {
+ if IsNotSupported(err) {
+ return ErrPlatformNotSupported
+ }
+ return getInnerError(err)
+ }
+
+ return nil
+}
+
+func modifyNetworkEndpoint(containerID string, endpointID string, request RequestType) error {
+ requestMessage := &ResourceModificationRequestResponse{
+ Resource: Network,
+ Request: request,
+ Data: endpointID,
+ }
+ err := modifyContainer(containerID, requestMessage)
+
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// GetHNSEndpointByID get the Endpoint by ID
+func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) {
+ return HNSEndpointRequest("GET", endpointID, "")
+}
+
+// GetHNSEndpointByName gets the endpoint filtered by Name
+func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) {
+ hnsResponse, err := HNSListEndpointRequest()
+ if err != nil {
+ return nil, err
+ }
+ for _, hnsEndpoint := range hnsResponse {
+ if hnsEndpoint.Name == endpointName {
+ return &hnsEndpoint, nil
+ }
+ }
+ return nil, fmt.Errorf("Endpoint %v not found", endpointName)
+}
+
+// Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods
+func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) {
+ operation := "Create"
+ title := "HCSShim::HNSEndpoint::" + operation
+ logrus.Debugf(title+" id=%s", endpoint.Id)
+
+ jsonString, err := json.Marshal(endpoint)
+ if err != nil {
+ return nil, err
+ }
+ return HNSEndpointRequest("POST", "", string(jsonString))
+}
+
+// Delete Endpoint by sending EndpointRequest to HNS
+func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) {
+ operation := "Delete"
+ title := "HCSShim::HNSEndpoint::" + operation
+ logrus.Debugf(title+" id=%s", endpoint.Id)
+
+ return HNSEndpointRequest("DELETE", endpoint.Id, "")
+}
+
+// Update Endpoint
+func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) {
+ operation := "Update"
+ title := "HCSShim::HNSEndpoint::" + operation
+ logrus.Debugf(title+" id=%s", endpoint.Id)
+ jsonString, err := json.Marshal(endpoint)
+ if err != nil {
+ return nil, err
+ }
+ err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint)
+
+ return endpoint, err
+}
+
+// ContainerHotAttach attaches an endpoint to a running container
+func (endpoint *HNSEndpoint) ContainerHotAttach(containerID string) error {
+ operation := "ContainerHotAttach"
+ title := "HCSShim::HNSEndpoint::" + operation
+ logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID)
+
+ return modifyNetworkEndpoint(containerID, endpoint.Id, Add)
+}
+
+// ContainerHotDetach detaches an endpoint from a running container
+func (endpoint *HNSEndpoint) ContainerHotDetach(containerID string) error {
+ operation := "ContainerHotDetach"
+ title := "HCSShim::HNSEndpoint::" + operation
+ logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID)
+
+ return modifyNetworkEndpoint(containerID, endpoint.Id, Remove)
+}
+
+// ApplyACLPolicy applies Acl Policy on the Endpoint
+func (endpoint *HNSEndpoint) ApplyACLPolicy(policy *ACLPolicy) error {
+ operation := "ApplyACLPolicy"
+ title := "HCSShim::HNSEndpoint::" + operation
+ logrus.Debugf(title+" id=%s", endpoint.Id)
+
+ jsonString, err := json.Marshal(policy)
+ if err != nil {
+ return err
+ }
+ endpoint.Policies[0] = jsonString
+ _, err = endpoint.Update()
+ return err
+}
+
+// ContainerAttach attaches an endpoint to container
+func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error {
+ operation := "ContainerAttach"
+ title := "HCSShim::HNSEndpoint::" + operation
+ logrus.Debugf(title+" id=%s", endpoint.Id)
+
+ requestMessage := &EndpointAttachDetachRequest{
+ ContainerID: containerID,
+ CompartmentID: compartmentID,
+ SystemType: ContainerType,
+ }
+ response := &EndpointResquestResponse{}
+ jsonString, err := json.Marshal(requestMessage)
+ if err != nil {
+ return err
+ }
+ return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
+}
+
+// ContainerDetach detaches an endpoint from container
+func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error {
+ operation := "ContainerDetach"
+ title := "HCSShim::HNSEndpoint::" + operation
+ logrus.Debugf(title+" id=%s", endpoint.Id)
+
+ requestMessage := &EndpointAttachDetachRequest{
+ ContainerID: containerID,
+ SystemType: ContainerType,
+ }
+ response := &EndpointResquestResponse{}
+
+ jsonString, err := json.Marshal(requestMessage)
+ if err != nil {
+ return err
+ }
+ return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
+}
+
+// HostAttach attaches a nic on the host
+func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error {
+ operation := "HostAttach"
+ title := "HCSShim::HNSEndpoint::" + operation
+ logrus.Debugf(title+" id=%s", endpoint.Id)
+ requestMessage := &EndpointAttachDetachRequest{
+ CompartmentID: compartmentID,
+ SystemType: HostType,
+ }
+ response := &EndpointResquestResponse{}
+
+ jsonString, err := json.Marshal(requestMessage)
+ if err != nil {
+ return err
+ }
+ return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
+
+}
+
+// HostDetach detaches a nic on the host
+func (endpoint *HNSEndpoint) HostDetach() error {
+ operation := "HostDetach"
+ title := "HCSShim::HNSEndpoint::" + operation
+ logrus.Debugf(title+" id=%s", endpoint.Id)
+ requestMessage := &EndpointAttachDetachRequest{
+ SystemType: HostType,
+ }
+ response := &EndpointResquestResponse{}
+
+ jsonString, err := json.Marshal(requestMessage)
+ if err != nil {
+ return err
+ }
+ return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
+}
+
+// VirtualMachineNICAttach attaches a endpoint to a virtual machine
+func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error {
+ operation := "VirtualMachineNicAttach"
+ title := "HCSShim::HNSEndpoint::" + operation
+ logrus.Debugf(title+" id=%s", endpoint.Id)
+ requestMessage := &EndpointAttachDetachRequest{
+ VirtualNICName: virtualMachineNICName,
+ SystemType: VirtualMachineType,
+ }
+ response := &EndpointResquestResponse{}
+
+ jsonString, err := json.Marshal(requestMessage)
+ if err != nil {
+ return err
+ }
+ return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
+}
+
+// VirtualMachineNICDetach detaches a endpoint from a virtual machine
+func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error {
+ operation := "VirtualMachineNicDetach"
+ title := "HCSShim::HNSEndpoint::" + operation
+ logrus.Debugf(title+" id=%s", endpoint.Id)
+
+ requestMessage := &EndpointAttachDetachRequest{
+ SystemType: VirtualMachineType,
+ }
+ response := &EndpointResquestResponse{}
+
+ jsonString, err := json.Marshal(requestMessage)
+ if err != nil {
+ return err
+ }
+ return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/hnsfuncs.go b/vendor/github.com/Microsoft/hcsshim/hnsfuncs.go
new file mode 100644
index 000000000..2c1b979ae
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/hnsfuncs.go
@@ -0,0 +1,40 @@
+package hcsshim
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/sirupsen/logrus"
+)
+
+func hnsCall(method, path, request string, returnResponse interface{}) error {
+ var responseBuffer *uint16
+ logrus.Debugf("[%s]=>[%s] Request : %s", method, path, request)
+
+ err := _hnsCall(method, path, request, &responseBuffer)
+ if err != nil {
+ return makeError(err, "hnsCall ", "")
+ }
+ response := convertAndFreeCoTaskMemString(responseBuffer)
+
+ hnsresponse := &hnsResponse{}
+ if err = json.Unmarshal([]byte(response), &hnsresponse); err != nil {
+ return err
+ }
+
+ if !hnsresponse.Success {
+ return fmt.Errorf("HNS failed with error : %s", hnsresponse.Error)
+ }
+
+ if len(hnsresponse.Output) == 0 {
+ return nil
+ }
+
+ logrus.Debugf("Network Response : %s", hnsresponse.Output)
+ err = json.Unmarshal(hnsresponse.Output, returnResponse)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/hnsnetwork.go b/vendor/github.com/Microsoft/hcsshim/hnsnetwork.go
new file mode 100644
index 000000000..3345bfa3f
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/hnsnetwork.go
@@ -0,0 +1,142 @@
+package hcsshim
+
+import (
+ "encoding/json"
+ "fmt"
+ "net"
+
+ "github.com/sirupsen/logrus"
+)
+
+// Subnet is assoicated with a network and represents a list
+// of subnets available to the network
+type Subnet struct {
+ AddressPrefix string `json:",omitempty"`
+ GatewayAddress string `json:",omitempty"`
+ Policies []json.RawMessage `json:",omitempty"`
+}
+
+// MacPool is assoicated with a network and represents a list
+// of macaddresses available to the network
+type MacPool struct {
+ StartMacAddress string `json:",omitempty"`
+ EndMacAddress string `json:",omitempty"`
+}
+
+// HNSNetwork represents a network in HNS
+type HNSNetwork struct {
+ Id string `json:"ID,omitempty"`
+ Name string `json:",omitempty"`
+ Type string `json:",omitempty"`
+ NetworkAdapterName string `json:",omitempty"`
+ SourceMac string `json:",omitempty"`
+ Policies []json.RawMessage `json:",omitempty"`
+ MacPools []MacPool `json:",omitempty"`
+ Subnets []Subnet `json:",omitempty"`
+ DNSSuffix string `json:",omitempty"`
+ DNSServerList string `json:",omitempty"`
+ DNSServerCompartment uint32 `json:",omitempty"`
+ ManagementIP string `json:",omitempty"`
+ AutomaticDNS bool `json:",omitempty"`
+}
+
+type hnsNetworkResponse struct {
+ Success bool
+ Error string
+ Output HNSNetwork
+}
+
+type hnsResponse struct {
+ Success bool
+ Error string
+ Output json.RawMessage
+}
+
+// HNSNetworkRequest makes a call into HNS to update/query a single network
+func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) {
+ var network HNSNetwork
+ err := hnsCall(method, "/networks/"+path, request, &network)
+ if err != nil {
+ return nil, err
+ }
+
+ return &network, nil
+}
+
+// HNSListNetworkRequest makes a HNS call to query the list of available networks
+func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) {
+ var network []HNSNetwork
+ err := hnsCall(method, "/networks/"+path, request, &network)
+ if err != nil {
+ return nil, err
+ }
+
+ return network, nil
+}
+
+// GetHNSNetworkByID
+func GetHNSNetworkByID(networkID string) (*HNSNetwork, error) {
+ return HNSNetworkRequest("GET", networkID, "")
+}
+
+// GetHNSNetworkName filtered by Name
+func GetHNSNetworkByName(networkName string) (*HNSNetwork, error) {
+ hsnnetworks, err := HNSListNetworkRequest("GET", "", "")
+ if err != nil {
+ return nil, err
+ }
+ for _, hnsnetwork := range hsnnetworks {
+ if hnsnetwork.Name == networkName {
+ return &hnsnetwork, nil
+ }
+ }
+ return nil, fmt.Errorf("Network %v not found", networkName)
+}
+
+// Create Network by sending NetworkRequest to HNS.
+func (network *HNSNetwork) Create() (*HNSNetwork, error) {
+ operation := "Create"
+ title := "HCSShim::HNSNetwork::" + operation
+ logrus.Debugf(title+" id=%s", network.Id)
+
+ jsonString, err := json.Marshal(network)
+ if err != nil {
+ return nil, err
+ }
+ return HNSNetworkRequest("POST", "", string(jsonString))
+}
+
+// Delete Network by sending NetworkRequest to HNS
+func (network *HNSNetwork) Delete() (*HNSNetwork, error) {
+ operation := "Delete"
+ title := "HCSShim::HNSNetwork::" + operation
+ logrus.Debugf(title+" id=%s", network.Id)
+
+ return HNSNetworkRequest("DELETE", network.Id, "")
+}
+
+// Creates an endpoint on the Network.
+func (network *HNSNetwork) NewEndpoint(ipAddress net.IP, macAddress net.HardwareAddr) *HNSEndpoint {
+ return &HNSEndpoint{
+ VirtualNetwork: network.Id,
+ IPAddress: ipAddress,
+ MacAddress: string(macAddress),
+ }
+}
+
+func (network *HNSNetwork) CreateEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) {
+ operation := "CreateEndpoint"
+ title := "HCSShim::HNSNetwork::" + operation
+ logrus.Debugf(title+" id=%s, endpointId=%s", network.Id, endpoint.Id)
+
+ endpoint.VirtualNetwork = network.Id
+ return endpoint.Create()
+}
+
+func (network *HNSNetwork) CreateRemoteEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) {
+ operation := "CreateRemoteEndpoint"
+ title := "HCSShim::HNSNetwork::" + operation
+ logrus.Debugf(title+" id=%s", network.Id)
+ endpoint.IsRemoteEndpoint = true
+ return network.CreateEndpoint(endpoint)
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/hnspolicy.go b/vendor/github.com/Microsoft/hcsshim/hnspolicy.go
new file mode 100644
index 000000000..ecfbf0eda
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/hnspolicy.go
@@ -0,0 +1,95 @@
+package hcsshim
+
+// Type of Request Support in ModifySystem
+type PolicyType string
+
+// RequestType const
+const (
+ Nat PolicyType = "NAT"
+ ACL PolicyType = "ACL"
+ PA PolicyType = "PA"
+ VLAN PolicyType = "VLAN"
+ VSID PolicyType = "VSID"
+ VNet PolicyType = "VNET"
+ L2Driver PolicyType = "L2Driver"
+ Isolation PolicyType = "Isolation"
+ QOS PolicyType = "QOS"
+ OutboundNat PolicyType = "OutBoundNAT"
+ ExternalLoadBalancer PolicyType = "ELB"
+ Route PolicyType = "ROUTE"
+)
+
+type NatPolicy struct {
+ Type PolicyType `json:"Type"`
+ Protocol string
+ InternalPort uint16
+ ExternalPort uint16
+}
+
+type QosPolicy struct {
+ Type PolicyType `json:"Type"`
+ MaximumOutgoingBandwidthInBytes uint64
+}
+
+type IsolationPolicy struct {
+ Type PolicyType `json:"Type"`
+ VLAN uint
+ VSID uint
+ InDefaultIsolation bool
+}
+
+type VlanPolicy struct {
+ Type PolicyType `json:"Type"`
+ VLAN uint
+}
+
+type VsidPolicy struct {
+ Type PolicyType `json:"Type"`
+ VSID uint
+}
+
+type PaPolicy struct {
+ Type PolicyType `json:"Type"`
+ PA string `json:"PA"`
+}
+
+type OutboundNatPolicy struct {
+ Policy
+ VIP string `json:"VIP,omitempty"`
+ Exceptions []string `json:"ExceptionList,omitempty"`
+}
+
+type ActionType string
+type DirectionType string
+type RuleType string
+
+const (
+ Allow ActionType = "Allow"
+ Block ActionType = "Block"
+
+ In DirectionType = "In"
+ Out DirectionType = "Out"
+
+ Host RuleType = "Host"
+ Switch RuleType = "Switch"
+)
+
+type ACLPolicy struct {
+ Type PolicyType `json:"Type"`
+ Protocol uint16
+ InternalPort uint16
+ Action ActionType
+ Direction DirectionType
+ LocalAddress string
+ RemoteAddress string
+ LocalPort uint16
+ RemotePort uint16
+ RuleType RuleType `json:"RuleType,omitempty"`
+
+ Priority uint16
+ ServiceName string
+}
+
+type Policy struct {
+ Type PolicyType `json:"Type"`
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go b/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go
new file mode 100644
index 000000000..15653b4f4
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/hnspolicylist.go
@@ -0,0 +1,196 @@
+package hcsshim
+
+import (
+ "encoding/json"
+
+ "github.com/sirupsen/logrus"
+)
+
+// RoutePolicy is a structure defining schema for Route based Policy
+type RoutePolicy struct {
+ Policy
+ DestinationPrefix string `json:"DestinationPrefix,omitempty"`
+ NextHop string `json:"NextHop,omitempty"`
+ EncapEnabled bool `json:"NeedEncap,omitempty"`
+}
+
+// ELBPolicy is a structure defining schema for ELB LoadBalancing based Policy
+type ELBPolicy struct {
+ LBPolicy
+ SourceVIP string `json:"SourceVIP,omitempty"`
+ VIPs []string `json:"VIPs,omitempty"`
+ ILB bool `json:"ILB,omitempty"`
+}
+
+// LBPolicy is a structure defining schema for LoadBalancing based Policy
+type LBPolicy struct {
+ Policy
+ Protocol uint16 `json:"Protocol,omitempty"`
+ InternalPort uint16
+ ExternalPort uint16
+}
+
+// PolicyList is a structure defining schema for Policy list request
+type PolicyList struct {
+ ID string `json:"ID,omitempty"`
+ EndpointReferences []string `json:"References,omitempty"`
+ Policies []json.RawMessage `json:"Policies,omitempty"`
+}
+
+// HNSPolicyListRequest makes a call into HNS to update/query a single network
+func HNSPolicyListRequest(method, path, request string) (*PolicyList, error) {
+ var policy PolicyList
+ err := hnsCall(method, "/policylists/"+path, request, &policy)
+ if err != nil {
+ return nil, err
+ }
+
+ return &policy, nil
+}
+
+// HNSListPolicyListRequest gets all the policy list
+func HNSListPolicyListRequest() ([]PolicyList, error) {
+ var plist []PolicyList
+ err := hnsCall("GET", "/policylists/", "", &plist)
+ if err != nil {
+ return nil, err
+ }
+
+ return plist, nil
+}
+
+// PolicyListRequest makes a HNS call to modify/query a network policy list
+func PolicyListRequest(method, path, request string) (*PolicyList, error) {
+ policylist := &PolicyList{}
+ err := hnsCall(method, "/policylists/"+path, request, &policylist)
+ if err != nil {
+ return nil, err
+ }
+
+ return policylist, nil
+}
+
+// GetPolicyListByID get the policy list by ID
+func GetPolicyListByID(policyListID string) (*PolicyList, error) {
+ return PolicyListRequest("GET", policyListID, "")
+}
+
+// Create PolicyList by sending PolicyListRequest to HNS.
+func (policylist *PolicyList) Create() (*PolicyList, error) {
+ operation := "Create"
+ title := "HCSShim::PolicyList::" + operation
+ logrus.Debugf(title+" id=%s", policylist.ID)
+ jsonString, err := json.Marshal(policylist)
+ if err != nil {
+ return nil, err
+ }
+ return PolicyListRequest("POST", "", string(jsonString))
+}
+
+// Delete deletes PolicyList
+func (policylist *PolicyList) Delete() (*PolicyList, error) {
+ operation := "Delete"
+ title := "HCSShim::PolicyList::" + operation
+ logrus.Debugf(title+" id=%s", policylist.ID)
+
+ return PolicyListRequest("DELETE", policylist.ID, "")
+}
+
+// AddEndpoint add an endpoint to a Policy List
+func (policylist *PolicyList) AddEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) {
+ operation := "AddEndpoint"
+ title := "HCSShim::PolicyList::" + operation
+ logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id)
+
+ _, err := policylist.Delete()
+ if err != nil {
+ return nil, err
+ }
+
+ // Add Endpoint to the Existing List
+ policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
+
+ return policylist.Create()
+}
+
+// RemoveEndpoint removes an endpoint from the Policy List
+func (policylist *PolicyList) RemoveEndpoint(endpoint *HNSEndpoint) (*PolicyList, error) {
+ operation := "RemoveEndpoint"
+ title := "HCSShim::PolicyList::" + operation
+ logrus.Debugf(title+" id=%s, endpointId:%s", policylist.ID, endpoint.Id)
+
+ _, err := policylist.Delete()
+ if err != nil {
+ return nil, err
+ }
+
+ elementToRemove := "/endpoints/" + endpoint.Id
+
+ var references []string
+
+ for _, endpointReference := range policylist.EndpointReferences {
+ if endpointReference == elementToRemove {
+ continue
+ }
+ references = append(references, endpointReference)
+ }
+ policylist.EndpointReferences = references
+ return policylist.Create()
+}
+
+// AddLoadBalancer policy list for the specified endpoints
+func AddLoadBalancer(endpoints []HNSEndpoint, isILB bool, vip string, protocol uint16, internalPort uint16, externalPort uint16) (*PolicyList, error) {
+ operation := "AddLoadBalancer"
+ title := "HCSShim::PolicyList::" + operation
+ logrus.Debugf(title+" Vip:%s", vip)
+
+ policylist := &PolicyList{}
+
+ elbPolicy := &ELBPolicy{
+ VIPs: []string{vip},
+ ILB: isILB,
+ }
+ elbPolicy.Type = ExternalLoadBalancer
+ elbPolicy.Protocol = protocol
+ elbPolicy.InternalPort = internalPort
+ elbPolicy.ExternalPort = externalPort
+
+ for _, endpoint := range endpoints {
+ policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
+ }
+
+ jsonString, err := json.Marshal(elbPolicy)
+ if err != nil {
+ return nil, err
+ }
+ policylist.Policies = append(policylist.Policies, jsonString)
+ return policylist.Create()
+}
+
+// AddRoute adds route policy list for the specified endpoints
+func AddRoute(endpoints []HNSEndpoint, destinationPrefix string, nextHop string, encapEnabled bool) (*PolicyList, error) {
+ operation := "AddRoute"
+ title := "HCSShim::PolicyList::" + operation
+ logrus.Debugf(title+" destinationPrefix:%s", destinationPrefix)
+
+ policylist := &PolicyList{}
+
+ rPolicy := &RoutePolicy{
+ DestinationPrefix: destinationPrefix,
+ NextHop: nextHop,
+ EncapEnabled: encapEnabled,
+ }
+ rPolicy.Type = Route
+
+ for _, endpoint := range endpoints {
+ policylist.EndpointReferences = append(policylist.EndpointReferences, "/endpoints/"+endpoint.Id)
+ }
+
+ jsonString, err := json.Marshal(rPolicy)
+ if err != nil {
+ return nil, err
+ }
+
+ policylist.Policies = append(policylist.Policies, jsonString)
+ return policylist.Create()
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/importlayer.go b/vendor/github.com/Microsoft/hcsshim/importlayer.go
new file mode 100644
index 000000000..3aed14376
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/importlayer.go
@@ -0,0 +1,212 @@
+package hcsshim
+
+import (
+ "errors"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+
+ "github.com/Microsoft/go-winio"
+ "github.com/sirupsen/logrus"
+)
+
+// ImportLayer will take the contents of the folder at importFolderPath and import
+// that into a layer with the id layerId. Note that in order to correctly populate
+// the layer and interperet the transport format, all parent layers must already
+// be present on the system at the paths provided in parentLayerPaths.
+func ImportLayer(info DriverInfo, layerID string, importFolderPath string, parentLayerPaths []string) error {
+ title := "hcsshim::ImportLayer "
+ logrus.Debugf(title+"flavour %d layerId %s folder %s", info.Flavour, layerID, importFolderPath)
+
+ // Generate layer descriptors
+ layers, err := layerPathsToDescriptors(parentLayerPaths)
+ if err != nil {
+ return err
+ }
+
+ // Convert info to API calling convention
+ infop, err := convertDriverInfo(info)
+ if err != nil {
+ logrus.Error(err)
+ return err
+ }
+
+ err = importLayer(&infop, layerID, importFolderPath, layers)
+ if err != nil {
+ err = makeErrorf(err, title, "layerId=%s flavour=%d folder=%s", layerID, info.Flavour, importFolderPath)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"succeeded flavour=%d layerId=%s folder=%s", info.Flavour, layerID, importFolderPath)
+ return nil
+}
+
+// LayerWriter is an interface that supports writing a new container image layer.
+type LayerWriter interface {
+ // Add adds a file to the layer with given metadata.
+ Add(name string, fileInfo *winio.FileBasicInfo) error
+ // AddLink adds a hard link to the layer. The target must already have been added.
+ AddLink(name string, target string) error
+ // Remove removes a file that was present in a parent layer from the layer.
+ Remove(name string) error
+ // Write writes data to the current file. The data must be in the format of a Win32
+ // backup stream.
+ Write(b []byte) (int, error)
+ // Close finishes the layer writing process and releases any resources.
+ Close() error
+}
+
+// FilterLayerWriter provides an interface to write the contents of a layer to the file system.
+type FilterLayerWriter struct {
+ context uintptr
+}
+
+// Add adds a file or directory to the layer. The file's parent directory must have already been added.
+//
+// name contains the file's relative path. fileInfo contains file times and file attributes; the rest
+// of the file metadata and the file data must be written as a Win32 backup stream to the Write() method.
+// winio.BackupStreamWriter can be used to facilitate this.
+func (w *FilterLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error {
+ if name[0] != '\\' {
+ name = `\` + name
+ }
+ err := importLayerNext(w.context, name, fileInfo)
+ if err != nil {
+ return makeError(err, "ImportLayerNext", "")
+ }
+ return nil
+}
+
+// AddLink adds a hard link to the layer. The target of the link must have already been added.
+func (w *FilterLayerWriter) AddLink(name string, target string) error {
+ return errors.New("hard links not yet supported")
+}
+
+// Remove removes a file from the layer. The file must have been present in the parent layer.
+//
+// name contains the file's relative path.
+func (w *FilterLayerWriter) Remove(name string) error {
+ if name[0] != '\\' {
+ name = `\` + name
+ }
+ err := importLayerNext(w.context, name, nil)
+ if err != nil {
+ return makeError(err, "ImportLayerNext", "")
+ }
+ return nil
+}
+
+// Write writes more backup stream data to the current file.
+func (w *FilterLayerWriter) Write(b []byte) (int, error) {
+ err := importLayerWrite(w.context, b)
+ if err != nil {
+ err = makeError(err, "ImportLayerWrite", "")
+ return 0, err
+ }
+ return len(b), err
+}
+
+// Close completes the layer write operation. The error must be checked to ensure that the
+// operation was successful.
+func (w *FilterLayerWriter) Close() (err error) {
+ if w.context != 0 {
+ err = importLayerEnd(w.context)
+ if err != nil {
+ err = makeError(err, "ImportLayerEnd", "")
+ }
+ w.context = 0
+ }
+ return
+}
+
+type legacyLayerWriterWrapper struct {
+ *legacyLayerWriter
+ info DriverInfo
+ layerID string
+ path string
+ parentLayerPaths []string
+}
+
+func (r *legacyLayerWriterWrapper) Close() error {
+ defer os.RemoveAll(r.root)
+ err := r.legacyLayerWriter.Close()
+ if err != nil {
+ return err
+ }
+
+ // Use the original path here because ImportLayer does not support long paths for the source in TP5.
+ // But do use a long path for the destination to work around another bug with directories
+ // with MAX_PATH - 12 < length < MAX_PATH.
+ info := r.info
+ fullPath, err := makeLongAbsPath(filepath.Join(info.HomeDir, r.layerID))
+ if err != nil {
+ return err
+ }
+
+ info.HomeDir = ""
+ if err = ImportLayer(info, fullPath, r.path, r.parentLayerPaths); err != nil {
+ return err
+ }
+ // Add any hard links that were collected.
+ for _, lnk := range r.PendingLinks {
+ if err = os.Remove(lnk.Path); err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ if err = os.Link(lnk.Target, lnk.Path); err != nil {
+ return err
+ }
+ }
+ // Prepare the utility VM for use if one is present in the layer.
+ if r.HasUtilityVM {
+ err = ProcessUtilityVMImage(filepath.Join(fullPath, "UtilityVM"))
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// 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.
+ return &baseLayerWriter{
+ root: filepath.Join(info.HomeDir, layerID),
+ }, nil
+ }
+
+ if procImportLayerBegin.Find() != nil {
+ // The new layer reader is not available on this Windows build. Fall back to the
+ // legacy export code path.
+ path, err := ioutil.TempDir("", "hcs")
+ if err != nil {
+ return nil, err
+ }
+ return &legacyLayerWriterWrapper{
+ legacyLayerWriter: newLegacyLayerWriter(path, parentLayerPaths, filepath.Join(info.HomeDir, layerID)),
+ info: info,
+ layerID: layerID,
+ path: path,
+ parentLayerPaths: parentLayerPaths,
+ }, nil
+ }
+ layers, err := layerPathsToDescriptors(parentLayerPaths)
+ if err != nil {
+ return nil, err
+ }
+
+ infop, err := convertDriverInfo(info)
+ if err != nil {
+ return nil, err
+ }
+
+ w := &FilterLayerWriter{}
+ err = importLayerBegin(&infop, layerID, layers, &w.context)
+ if err != nil {
+ return nil, makeError(err, "ImportLayerStart", "")
+ }
+ return w, nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/interface.go b/vendor/github.com/Microsoft/hcsshim/interface.go
new file mode 100644
index 000000000..9fc7852e4
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/interface.go
@@ -0,0 +1,187 @@
+package hcsshim
+
+import (
+ "encoding/json"
+ "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 `json:",omitempty"`
+ CommandLine string `json:",omitempty"`
+ CommandArgs []string `json:",omitempty"` // Used by Linux Containers on Windows
+ User string `json:",omitempty"`
+ WorkingDirectory string `json:",omitempty"`
+ Environment map[string]string `json:",omitempty"`
+ EmulateConsole bool `json:",omitempty"`
+ CreateStdInPipe bool `json:",omitempty"`
+ CreateStdOutPipe bool `json:",omitempty"`
+ CreateStdErrPipe bool `json:",omitempty"`
+ ConsoleSize [2]uint `json:",omitempty"`
+ CreateInUtilityVm bool `json:",omitempty"` // Used by Linux Containers on Windows
+ OCISpecification *json.RawMessage `json:",omitempty"` // Used by Linux Containers on Windows
+}
+
+type Layer struct {
+ ID string
+ Path string
+}
+
+type MappedDir struct {
+ HostPath string
+ ContainerPath string
+ ReadOnly bool
+ BandwidthMaximum uint64
+ IOPSMaximum uint64
+}
+
+type MappedPipe struct {
+ HostPath string
+ ContainerPipeName string
+}
+
+type HvRuntime struct {
+ ImagePath string `json:",omitempty"`
+ SkipTemplate bool `json:",omitempty"`
+ LinuxInitrdFile string `json:",omitempty"` // File under ImagePath on host containing an initrd image for starting a Linux utility VM
+ LinuxKernelFile string `json:",omitempty"` // File under ImagePath on host containing a kernel for starting a Linux utility VM
+ LinuxBootParameters string `json:",omitempty"` // Additional boot parameters for starting a Linux Utility VM in initrd mode
+ BootSource string `json:",omitempty"` // "Vhd" for Linux Utility VM booting from VHD
+ WritableBootSource bool `json:",omitempty"` // Linux Utility VM booting from VHD
+}
+
+type MappedVirtualDisk struct {
+ HostPath string `json:",omitempty"` // Path to VHD on the host
+ ContainerPath string // Platform-specific mount point path in the container
+ CreateInUtilityVM bool `json:",omitempty"`
+ ReadOnly bool `json:",omitempty"`
+ Cache string `json:",omitempty"` // "" (Unspecified); "Disabled"; "Enabled"; "Private"; "PrivateAllowSharing"
+ AttachOnly bool `json:",omitempty:`
+}
+
+// ContainerConfig is used as both the input of CreateContainer
+// and to convert the parameters to JSON for passing onto the HCS
+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 `json:",omitempty"` // The management platform that created this container
+ VolumePath string `json:",omitempty"` // Windows volume path for scratch space. Used by Windows Server Containers only. Format \\?\\Volume{GUID}
+ IgnoreFlushesDuringBoot bool `json:",omitempty"` // Optimization hint for container startup in Windows
+ LayerFolderPath string `json:",omitempty"` // Where the layer folders are located. Used by Windows Server Containers only. Format %root%\windowsfilter\containerID
+ Layers []Layer // List of storage layers. Required for Windows Server and Hyper-V Containers. Format ID=GUID;Path=%root%\windowsfilter\layerID
+ Credentials string `json:",omitempty"` // Credentials information
+ ProcessorCount uint32 `json:",omitempty"` // Number of processors to assign to the container.
+ ProcessorWeight uint64 `json:",omitempty"` // CPU shares (relative weight to other containers with cpu shares). Range is from 1 to 10000. A value of 0 results in default shares.
+ ProcessorMaximum int64 `json:",omitempty"` // Specifies the portion of processor cycles that this container can use as a percentage times 100. Range is from 1 to 10000. A value of 0 results in no limit.
+ 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 `json:",omitempty"` // Hostname
+ MappedDirectories []MappedDir `json:",omitempty"` // List of mapped directories (volumes/mounts)
+ MappedPipes []MappedPipe `json:",omitempty"` // List of mapped Windows named pipes
+ HvPartition bool // True if it a Hyper-V Container
+ NetworkSharedContainerName string `json:",omitempty"` // Name (ID) of the container that we will share the network stack with.
+ EndpointList []string `json:",omitempty"` // List of networking endpoints to be attached to container
+ HvRuntime *HvRuntime `json:",omitempty"` // Hyper-V container settings. Used by Hyper-V containers only. Format ImagePath=%root%\BaseLayerID\UtilityVM
+ Servicing bool `json:",omitempty"` // True if this container is for servicing
+ AllowUnqualifiedDNSQuery bool `json:",omitempty"` // True to allow unqualified DNS name resolution
+ DNSSearchList string `json:",omitempty"` // Comma seperated list of DNS suffixes to use for name resolution
+ ContainerType string `json:",omitempty"` // "Linux" for Linux containers on Windows. Omitted otherwise.
+ TerminateOnLastHandleClosed bool `json:",omitempty"` // Should HCS terminate the container once all handles have been closed
+ MappedVirtualDisks []MappedVirtualDisk `json:",omitempty"` // Array of virtual disks to mount at start
+}
+
+type ComputeSystemQuery struct {
+ IDs []string `json:"Ids,omitempty"`
+ Types []string `json:",omitempty"`
+ Names []string `json:",omitempty"`
+ Owners []string `json:",omitempty"`
+}
+
+// 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)
+
+ // Statistics returns statistics for a container.
+ Statistics() (Statistics, error)
+
+ // ProcessList returns details for the processes in a container.
+ ProcessList() ([]ProcessListItem, error)
+
+ // MappedVirtualDisks returns virtual disks mapped to a utility VM, indexed by controller
+ MappedVirtualDisks() (map[int]MappedVirtualDiskController, 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
+
+ // Modify the System
+ Modify(config *ResourceModificationRequestResponse) 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
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/layerexists.go b/vendor/github.com/Microsoft/hcsshim/layerexists.go
new file mode 100644
index 000000000..fe46f404c
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/layerexists.go
@@ -0,0 +1,30 @@
+package hcsshim
+
+import "github.com/sirupsen/logrus"
+
+// LayerExists will return true if a layer with the given id exists and is known
+// to the system.
+func LayerExists(info DriverInfo, id string) (bool, error) {
+ title := "hcsshim::LayerExists "
+ logrus.Debugf(title+"Flavour %d ID %s", info.Flavour, id)
+
+ // Convert info to API calling convention
+ infop, err := convertDriverInfo(info)
+ if err != nil {
+ logrus.Error(err)
+ return false, err
+ }
+
+ // Call the procedure itself.
+ var exists uint32
+
+ err = layerExists(&infop, id, &exists)
+ if err != nil {
+ err = makeErrorf(err, title, "id=%s flavour=%d", id, info.Flavour)
+ logrus.Error(err)
+ return false, err
+ }
+
+ logrus.Debugf(title+"succeeded flavour=%d id=%s exists=%d", info.Flavour, id, exists)
+ return exists != 0, nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/layerutils.go b/vendor/github.com/Microsoft/hcsshim/layerutils.go
new file mode 100644
index 000000000..c0e550377
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/layerutils.go
@@ -0,0 +1,111 @@
+package hcsshim
+
+// This file contains utility functions to support storage (graph) related
+// functionality.
+
+import (
+ "path/filepath"
+ "syscall"
+
+ "github.com/sirupsen/logrus"
+)
+
+/* To pass into syscall, we need a struct matching the following:
+enum GraphDriverType
+{
+ DiffDriver,
+ FilterDriver
+};
+
+struct DriverInfo {
+ GraphDriverType Flavour;
+ LPCWSTR HomeDir;
+};
+*/
+type DriverInfo struct {
+ Flavour int
+ HomeDir string
+}
+
+type driverInfo struct {
+ Flavour int
+ HomeDirp *uint16
+}
+
+func convertDriverInfo(info DriverInfo) (driverInfo, error) {
+ homedirp, err := syscall.UTF16PtrFromString(info.HomeDir)
+ if err != nil {
+ logrus.Debugf("Failed conversion of home to pointer for driver info: %s", err.Error())
+ return driverInfo{}, err
+ }
+
+ return driverInfo{
+ Flavour: info.Flavour,
+ HomeDirp: homedirp,
+ }, nil
+}
+
+/* To pass into syscall, we need a struct matching the following:
+typedef struct _WC_LAYER_DESCRIPTOR {
+
+ //
+ // The ID of the layer
+ //
+
+ GUID LayerId;
+
+ //
+ // Additional flags
+ //
+
+ union {
+ struct {
+ ULONG Reserved : 31;
+ ULONG Dirty : 1; // Created from sandbox as a result of snapshot
+ };
+ ULONG Value;
+ } Flags;
+
+ //
+ // Path to the layer root directory, null-terminated
+ //
+
+ PCWSTR Path;
+
+} WC_LAYER_DESCRIPTOR, *PWC_LAYER_DESCRIPTOR;
+*/
+type WC_LAYER_DESCRIPTOR struct {
+ LayerId GUID
+ Flags uint32
+ Pathp *uint16
+}
+
+func layerPathsToDescriptors(parentLayerPaths []string) ([]WC_LAYER_DESCRIPTOR, error) {
+ // Array of descriptors that gets constructed.
+ var layers []WC_LAYER_DESCRIPTOR
+
+ for i := 0; i < len(parentLayerPaths); i++ {
+ // Create a layer descriptor, using the folder name
+ // as the source for a GUID LayerId
+ _, folderName := filepath.Split(parentLayerPaths[i])
+ g, err := NameToGuid(folderName)
+ if err != nil {
+ logrus.Debugf("Failed to convert name to guid %s", err)
+ return nil, err
+ }
+
+ p, err := syscall.UTF16PtrFromString(parentLayerPaths[i])
+ if err != nil {
+ logrus.Debugf("Failed conversion of parentLayerPath to pointer %s", err)
+ return nil, err
+ }
+
+ layers = append(layers, WC_LAYER_DESCRIPTOR{
+ LayerId: g,
+ Flags: 0,
+ Pathp: p,
+ })
+ }
+
+ return layers, nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/legacy.go b/vendor/github.com/Microsoft/hcsshim/legacy.go
new file mode 100644
index 000000000..c7f6073ac
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/legacy.go
@@ -0,0 +1,741 @@
+package hcsshim
+
+import (
+ "bufio"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+ "strings"
+ "syscall"
+
+ "github.com/Microsoft/go-winio"
+)
+
+var errorIterationCanceled = errors.New("")
+
+var mutatedUtilityVMFiles = map[string]bool{
+ `EFI\Microsoft\Boot\BCD`: true,
+ `EFI\Microsoft\Boot\BCD.LOG`: true,
+ `EFI\Microsoft\Boot\BCD.LOG1`: true,
+ `EFI\Microsoft\Boot\BCD.LOG2`: true,
+}
+
+const (
+ filesPath = `Files`
+ hivesPath = `Hives`
+ utilityVMPath = `UtilityVM`
+ utilityVMFilesPath = `UtilityVM\Files`
+)
+
+func openFileOrDir(path string, mode uint32, createDisposition uint32) (file *os.File, err error) {
+ return winio.OpenForBackup(path, mode, syscall.FILE_SHARE_READ, createDisposition)
+}
+
+func makeLongAbsPath(path string) (string, error) {
+ if strings.HasPrefix(path, `\\?\`) || strings.HasPrefix(path, `\\.\`) {
+ return path, nil
+ }
+ if !filepath.IsAbs(path) {
+ absPath, err := filepath.Abs(path)
+ if err != nil {
+ return "", err
+ }
+ path = absPath
+ }
+ if strings.HasPrefix(path, `\\`) {
+ return `\\?\UNC\` + path[2:], nil
+ }
+ return `\\?\` + path, nil
+}
+
+func hasPathPrefix(p, prefix string) bool {
+ return strings.HasPrefix(p, prefix) && len(p) > len(prefix) && p[len(prefix)] == '\\'
+}
+
+type fileEntry struct {
+ path string
+ fi os.FileInfo
+ err error
+}
+
+type legacyLayerReader struct {
+ root string
+ result chan *fileEntry
+ proceed chan bool
+ currentFile *os.File
+ backupReader *winio.BackupFileReader
+}
+
+// newLegacyLayerReader returns a new LayerReader that can read the Windows
+// container layer transport format from disk.
+func newLegacyLayerReader(root string) *legacyLayerReader {
+ r := &legacyLayerReader{
+ root: root,
+ result: make(chan *fileEntry),
+ proceed: make(chan bool),
+ }
+ go r.walk()
+ return r
+}
+
+func readTombstones(path string) (map[string]([]string), error) {
+ tf, err := os.Open(filepath.Join(path, "tombstones.txt"))
+ if err != nil {
+ return nil, err
+ }
+ defer tf.Close()
+ s := bufio.NewScanner(tf)
+ if !s.Scan() || s.Text() != "\xef\xbb\xbfVersion 1.0" {
+ return nil, errors.New("Invalid tombstones file")
+ }
+
+ ts := make(map[string]([]string))
+ for s.Scan() {
+ t := filepath.Join(filesPath, s.Text()[1:]) // skip leading `\`
+ dir := filepath.Dir(t)
+ ts[dir] = append(ts[dir], t)
+ }
+ if err = s.Err(); err != nil {
+ return nil, err
+ }
+
+ return ts, nil
+}
+
+func (r *legacyLayerReader) walkUntilCancelled() error {
+ root, err := makeLongAbsPath(r.root)
+ if err != nil {
+ return err
+ }
+
+ r.root = root
+ ts, err := readTombstones(r.root)
+ if err != nil {
+ return err
+ }
+
+ err = filepath.Walk(r.root, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ if path == r.root || path == filepath.Join(r.root, "tombstones.txt") || strings.HasSuffix(path, ".$wcidirs$") {
+ return nil
+ }
+
+ r.result <- &fileEntry{path, info, nil}
+ if !<-r.proceed {
+ return errorIterationCanceled
+ }
+
+ // List all the tombstones.
+ if info.IsDir() {
+ relPath, err := filepath.Rel(r.root, path)
+ if err != nil {
+ return err
+ }
+ if dts, ok := ts[relPath]; ok {
+ for _, t := range dts {
+ r.result <- &fileEntry{filepath.Join(r.root, t), nil, nil}
+ if !<-r.proceed {
+ return errorIterationCanceled
+ }
+ }
+ }
+ }
+ return nil
+ })
+ if err == errorIterationCanceled {
+ return nil
+ }
+ if err == nil {
+ return io.EOF
+ }
+ return err
+}
+
+func (r *legacyLayerReader) walk() {
+ defer close(r.result)
+ if !<-r.proceed {
+ return
+ }
+
+ err := r.walkUntilCancelled()
+ if err != nil {
+ for {
+ r.result <- &fileEntry{err: err}
+ if !<-r.proceed {
+ return
+ }
+ }
+ }
+}
+
+func (r *legacyLayerReader) reset() {
+ if r.backupReader != nil {
+ r.backupReader.Close()
+ r.backupReader = nil
+ }
+ if r.currentFile != nil {
+ r.currentFile.Close()
+ r.currentFile = nil
+ }
+}
+
+func findBackupStreamSize(r io.Reader) (int64, error) {
+ br := winio.NewBackupStreamReader(r)
+ for {
+ hdr, err := br.Next()
+ if err != nil {
+ if err == io.EOF {
+ err = nil
+ }
+ return 0, err
+ }
+ if hdr.Id == winio.BackupData {
+ return hdr.Size, nil
+ }
+ }
+}
+
+func (r *legacyLayerReader) Next() (path string, size int64, fileInfo *winio.FileBasicInfo, err error) {
+ r.reset()
+ r.proceed <- true
+ fe := <-r.result
+ if fe == nil {
+ err = errors.New("LegacyLayerReader closed")
+ return
+ }
+ if fe.err != nil {
+ err = fe.err
+ return
+ }
+
+ path, err = filepath.Rel(r.root, fe.path)
+ if err != nil {
+ return
+ }
+
+ if fe.fi == nil {
+ // This is a tombstone. Return a nil fileInfo.
+ return
+ }
+
+ if fe.fi.IsDir() && hasPathPrefix(path, filesPath) {
+ fe.path += ".$wcidirs$"
+ }
+
+ f, err := openFileOrDir(fe.path, syscall.GENERIC_READ, syscall.OPEN_EXISTING)
+ if err != nil {
+ return
+ }
+ defer func() {
+ if f != nil {
+ f.Close()
+ }
+ }()
+
+ fileInfo, err = winio.GetFileBasicInfo(f)
+ if err != nil {
+ return
+ }
+
+ if !hasPathPrefix(path, filesPath) {
+ size = fe.fi.Size()
+ r.backupReader = winio.NewBackupFileReader(f, false)
+ if path == hivesPath || path == filesPath {
+ // The Hives directory has a non-deterministic file time because of the
+ // nature of the import process. Use the times from System_Delta.
+ var g *os.File
+ g, err = os.Open(filepath.Join(r.root, hivesPath, `System_Delta`))
+ if err != nil {
+ return
+ }
+ attr := fileInfo.FileAttributes
+ fileInfo, err = winio.GetFileBasicInfo(g)
+ g.Close()
+ if err != nil {
+ return
+ }
+ fileInfo.FileAttributes = attr
+ }
+
+ // The creation time and access time get reset for files outside of the Files path.
+ fileInfo.CreationTime = fileInfo.LastWriteTime
+ fileInfo.LastAccessTime = fileInfo.LastWriteTime
+
+ } else {
+ // The file attributes are written before the backup stream.
+ var attr uint32
+ err = binary.Read(f, binary.LittleEndian, &attr)
+ if err != nil {
+ return
+ }
+ fileInfo.FileAttributes = uintptr(attr)
+ beginning := int64(4)
+
+ // Find the accurate file size.
+ if !fe.fi.IsDir() {
+ size, err = findBackupStreamSize(f)
+ if err != nil {
+ err = &os.PathError{Op: "findBackupStreamSize", Path: fe.path, Err: err}
+ return
+ }
+ }
+
+ // Return back to the beginning of the backup stream.
+ _, err = f.Seek(beginning, 0)
+ if err != nil {
+ return
+ }
+ }
+
+ r.currentFile = f
+ f = nil
+ return
+}
+
+func (r *legacyLayerReader) Read(b []byte) (int, error) {
+ if r.backupReader == nil {
+ if r.currentFile == nil {
+ return 0, io.EOF
+ }
+ return r.currentFile.Read(b)
+ }
+ return r.backupReader.Read(b)
+}
+
+func (r *legacyLayerReader) Seek(offset int64, whence int) (int64, error) {
+ if r.backupReader == nil {
+ if r.currentFile == nil {
+ return 0, errors.New("no current file")
+ }
+ return r.currentFile.Seek(offset, whence)
+ }
+ return 0, errors.New("seek not supported on this stream")
+}
+
+func (r *legacyLayerReader) Close() error {
+ r.proceed <- false
+ <-r.result
+ r.reset()
+ return nil
+}
+
+type pendingLink struct {
+ Path, Target string
+}
+
+type legacyLayerWriter struct {
+ root string
+ parentRoots []string
+ destRoot string
+ currentFile *os.File
+ backupWriter *winio.BackupFileWriter
+ tombstones []string
+ pathFixed bool
+ HasUtilityVM bool
+ uvmDi []dirInfo
+ addedFiles map[string]bool
+ PendingLinks []pendingLink
+}
+
+// newLegacyLayerWriter returns a LayerWriter that can write the contaler layer
+// transport format to disk.
+func newLegacyLayerWriter(root string, parentRoots []string, destRoot string) *legacyLayerWriter {
+ return &legacyLayerWriter{
+ root: root,
+ parentRoots: parentRoots,
+ destRoot: destRoot,
+ addedFiles: make(map[string]bool),
+ }
+}
+
+func (w *legacyLayerWriter) init() error {
+ if !w.pathFixed {
+ path, err := makeLongAbsPath(w.root)
+ if err != nil {
+ return err
+ }
+ for i, p := range w.parentRoots {
+ w.parentRoots[i], err = makeLongAbsPath(p)
+ if err != nil {
+ return err
+ }
+ }
+ destPath, err := makeLongAbsPath(w.destRoot)
+ if err != nil {
+ return err
+ }
+ w.root = path
+ w.destRoot = destPath
+ w.pathFixed = true
+ }
+ return nil
+}
+
+func (w *legacyLayerWriter) initUtilityVM() error {
+ if !w.HasUtilityVM {
+ err := os.Mkdir(filepath.Join(w.destRoot, utilityVMPath), 0)
+ if err != nil {
+ return err
+ }
+ // Server 2016 does not support multiple layers for the utility VM, so
+ // clone the utility VM from the parent layer into this layer. Use hard
+ // links to avoid unnecessary copying, since most of the files are
+ // immutable.
+ err = cloneTree(filepath.Join(w.parentRoots[0], utilityVMFilesPath), filepath.Join(w.destRoot, utilityVMFilesPath), mutatedUtilityVMFiles)
+ if err != nil {
+ return fmt.Errorf("cloning the parent utility VM image failed: %s", err)
+ }
+ w.HasUtilityVM = true
+ }
+ return nil
+}
+
+func (w *legacyLayerWriter) reset() {
+ if w.backupWriter != nil {
+ w.backupWriter.Close()
+ w.backupWriter = nil
+ }
+ if w.currentFile != nil {
+ w.currentFile.Close()
+ w.currentFile = nil
+ }
+}
+
+// copyFileWithMetadata copies a file using the backup/restore APIs in order to preserve metadata
+func copyFileWithMetadata(srcPath, destPath string, isDir bool) (fileInfo *winio.FileBasicInfo, err error) {
+ createDisposition := uint32(syscall.CREATE_NEW)
+ if isDir {
+ err = os.Mkdir(destPath, 0)
+ if err != nil {
+ return nil, err
+ }
+ createDisposition = syscall.OPEN_EXISTING
+ }
+
+ src, err := openFileOrDir(srcPath, syscall.GENERIC_READ|winio.ACCESS_SYSTEM_SECURITY, syscall.OPEN_EXISTING)
+ if err != nil {
+ return nil, err
+ }
+ defer src.Close()
+ srcr := winio.NewBackupFileReader(src, true)
+ defer srcr.Close()
+
+ fileInfo, err = winio.GetFileBasicInfo(src)
+ if err != nil {
+ return nil, err
+ }
+
+ dest, err := openFileOrDir(destPath, syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, createDisposition)
+ if err != nil {
+ return nil, err
+ }
+ defer dest.Close()
+
+ err = winio.SetFileBasicInfo(dest, fileInfo)
+ if err != nil {
+ return nil, err
+ }
+
+ destw := winio.NewBackupFileWriter(dest, true)
+ defer func() {
+ cerr := destw.Close()
+ if err == nil {
+ err = cerr
+ }
+ }()
+
+ _, err = io.Copy(destw, srcr)
+ if err != nil {
+ return nil, err
+ }
+
+ return fileInfo, nil
+}
+
+// cloneTree clones a directory tree using hard links. It skips hard links for
+// the file names in the provided map and just copies those files.
+func cloneTree(srcPath, destPath string, mutatedFiles map[string]bool) error {
+ var di []dirInfo
+ err := filepath.Walk(srcPath, func(srcFilePath string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+
+ relPath, err := filepath.Rel(srcPath, srcFilePath)
+ if err != nil {
+ return err
+ }
+ destFilePath := filepath.Join(destPath, relPath)
+
+ // Directories, reparse points, and files that will be mutated during
+ // utility VM import must be copied. All other files can be hard linked.
+ isReparsePoint := info.Sys().(*syscall.Win32FileAttributeData).FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0
+ if info.IsDir() || isReparsePoint || mutatedFiles[relPath] {
+ fi, err := copyFileWithMetadata(srcFilePath, destFilePath, info.IsDir())
+ if err != nil {
+ return err
+ }
+ if info.IsDir() && !isReparsePoint {
+ di = append(di, dirInfo{path: destFilePath, fileInfo: *fi})
+ }
+ } else {
+ err = os.Link(srcFilePath, destFilePath)
+ if err != nil {
+ return err
+ }
+ }
+
+ // Don't recurse on reparse points.
+ if info.IsDir() && isReparsePoint {
+ return filepath.SkipDir
+ }
+
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+
+ return reapplyDirectoryTimes(di)
+}
+
+func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) error {
+ w.reset()
+ err := w.init()
+ if err != nil {
+ return err
+ }
+
+ if name == utilityVMPath {
+ return w.initUtilityVM()
+ }
+
+ if hasPathPrefix(name, utilityVMPath) {
+ if !w.HasUtilityVM {
+ return errors.New("missing UtilityVM directory")
+ }
+ if !hasPathPrefix(name, utilityVMFilesPath) && name != utilityVMFilesPath {
+ return errors.New("invalid UtilityVM layer")
+ }
+ path := filepath.Join(w.destRoot, name)
+ createDisposition := uint32(syscall.OPEN_EXISTING)
+ if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
+ st, err := os.Lstat(path)
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ if st != nil {
+ // Delete the existing file/directory if it is not the same type as this directory.
+ existingAttr := st.Sys().(*syscall.Win32FileAttributeData).FileAttributes
+ if (uint32(fileInfo.FileAttributes)^existingAttr)&(syscall.FILE_ATTRIBUTE_DIRECTORY|syscall.FILE_ATTRIBUTE_REPARSE_POINT) != 0 {
+ if err = os.RemoveAll(path); err != nil {
+ return err
+ }
+ st = nil
+ }
+ }
+ if st == nil {
+ if err = os.Mkdir(path, 0); err != nil {
+ return err
+ }
+ }
+ if fileInfo.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
+ w.uvmDi = append(w.uvmDi, dirInfo{path: path, fileInfo: *fileInfo})
+ }
+ } else {
+ // Overwrite any existing hard link.
+ err = os.Remove(path)
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ createDisposition = syscall.CREATE_NEW
+ }
+
+ f, err := openFileOrDir(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER|winio.ACCESS_SYSTEM_SECURITY, createDisposition)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if f != nil {
+ f.Close()
+ os.Remove(path)
+ }
+ }()
+
+ err = winio.SetFileBasicInfo(f, fileInfo)
+ if err != nil {
+ return err
+ }
+
+ w.backupWriter = winio.NewBackupFileWriter(f, true)
+ w.currentFile = f
+ w.addedFiles[name] = true
+ f = nil
+ return nil
+ }
+
+ path := filepath.Join(w.root, name)
+ if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 {
+ err := os.Mkdir(path, 0)
+ if err != nil {
+ return err
+ }
+ path += ".$wcidirs$"
+ }
+
+ f, err := openFileOrDir(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.CREATE_NEW)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if f != nil {
+ f.Close()
+ os.Remove(path)
+ }
+ }()
+
+ strippedFi := *fileInfo
+ strippedFi.FileAttributes = 0
+ err = winio.SetFileBasicInfo(f, &strippedFi)
+ if err != nil {
+ return err
+ }
+
+ if hasPathPrefix(name, hivesPath) {
+ w.backupWriter = winio.NewBackupFileWriter(f, false)
+ } else {
+ // The file attributes are written before the stream.
+ err = binary.Write(f, binary.LittleEndian, uint32(fileInfo.FileAttributes))
+ if err != nil {
+ return err
+ }
+ }
+
+ w.currentFile = f
+ w.addedFiles[name] = true
+ f = nil
+ return nil
+}
+
+func (w *legacyLayerWriter) AddLink(name string, target string) error {
+ w.reset()
+ err := w.init()
+ if err != nil {
+ return err
+ }
+
+ var roots []string
+ if hasPathPrefix(target, filesPath) {
+ // Look for cross-layer hard link targets in the parent layers, since
+ // nothing is in the destination path yet.
+ roots = w.parentRoots
+ } else if hasPathPrefix(target, utilityVMFilesPath) {
+ // Since the utility VM is fully cloned into the destination path
+ // already, look for cross-layer hard link targets directly in the
+ // destination path.
+ roots = []string{w.destRoot}
+ }
+
+ if roots == nil || (!hasPathPrefix(name, filesPath) && !hasPathPrefix(name, utilityVMFilesPath)) {
+ return errors.New("invalid hard link in layer")
+ }
+
+ // Find to try the target of the link in a previously added file. If that
+ // fails, search in parent layers.
+ var selectedRoot string
+ if _, ok := w.addedFiles[target]; ok {
+ selectedRoot = w.destRoot
+ } else {
+ for _, r := range roots {
+ if _, err = os.Lstat(filepath.Join(r, target)); err != nil {
+ if !os.IsNotExist(err) {
+ return err
+ }
+ } else {
+ selectedRoot = r
+ break
+ }
+ }
+ if selectedRoot == "" {
+ return fmt.Errorf("failed to find link target for '%s' -> '%s'", name, target)
+ }
+ }
+ // The link can't be written until after the ImportLayer call.
+ w.PendingLinks = append(w.PendingLinks, pendingLink{
+ Path: filepath.Join(w.destRoot, name),
+ Target: filepath.Join(selectedRoot, target),
+ })
+ w.addedFiles[name] = true
+ return nil
+}
+
+func (w *legacyLayerWriter) Remove(name string) error {
+ if hasPathPrefix(name, filesPath) {
+ w.tombstones = append(w.tombstones, name[len(filesPath)+1:])
+ } else if hasPathPrefix(name, utilityVMFilesPath) {
+ err := w.initUtilityVM()
+ if err != nil {
+ return err
+ }
+ // Make sure the path exists; os.RemoveAll will not fail if the file is
+ // already gone, and this needs to be a fatal error for diagnostics
+ // purposes.
+ path := filepath.Join(w.destRoot, name)
+ if _, err := os.Lstat(path); err != nil {
+ return err
+ }
+ err = os.RemoveAll(path)
+ if err != nil {
+ return err
+ }
+ } else {
+ return fmt.Errorf("invalid tombstone %s", name)
+ }
+
+ return nil
+}
+
+func (w *legacyLayerWriter) Write(b []byte) (int, error) {
+ if w.backupWriter == nil {
+ if w.currentFile == nil {
+ return 0, errors.New("closed")
+ }
+ return w.currentFile.Write(b)
+ }
+ return w.backupWriter.Write(b)
+}
+
+func (w *legacyLayerWriter) Close() error {
+ w.reset()
+ err := w.init()
+ if err != nil {
+ return err
+ }
+ tf, err := os.Create(filepath.Join(w.root, "tombstones.txt"))
+ if err != nil {
+ return err
+ }
+ defer tf.Close()
+ _, err = tf.Write([]byte("\xef\xbb\xbfVersion 1.0\n"))
+ if err != nil {
+ return err
+ }
+ for _, t := range w.tombstones {
+ _, err = tf.Write([]byte(filepath.Join(`\`, t) + "\n"))
+ if err != nil {
+ return err
+ }
+ }
+ if w.HasUtilityVM {
+ err = reapplyDirectoryTimes(w.uvmDi)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/nametoguid.go b/vendor/github.com/Microsoft/hcsshim/nametoguid.go
new file mode 100644
index 000000000..b7c6d020c
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/nametoguid.go
@@ -0,0 +1,20 @@
+package hcsshim
+
+import "github.com/sirupsen/logrus"
+
+// NameToGuid converts the given string into a GUID using the algorithm in the
+// Host Compute Service, ensuring GUIDs generated with the same string are common
+// across all clients.
+func NameToGuid(name string) (id GUID, err error) {
+ title := "hcsshim::NameToGuid "
+ logrus.Debugf(title+"Name %s", name)
+
+ err = nameToGuid(name, &id)
+ if err != nil {
+ err = makeErrorf(err, title, "name=%s", name)
+ logrus.Error(err)
+ return
+ }
+
+ return
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/preparelayer.go b/vendor/github.com/Microsoft/hcsshim/preparelayer.go
new file mode 100644
index 000000000..5c5b61841
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/preparelayer.go
@@ -0,0 +1,46 @@
+package hcsshim
+
+import (
+ "sync"
+
+ "github.com/sirupsen/logrus"
+)
+
+var prepareLayerLock sync.Mutex
+
+// PrepareLayer finds a mounted read-write layer matching layerId and enables the
+// the filesystem filter for use on that layer. This requires the paths to all
+// parent layers, and is necessary in order to view or interact with the layer
+// as an actual filesystem (reading and writing files, creating directories, etc).
+// Disabling the filter must be done via UnprepareLayer.
+func PrepareLayer(info DriverInfo, layerId string, parentLayerPaths []string) error {
+ title := "hcsshim::PrepareLayer "
+ logrus.Debugf(title+"flavour %d layerId %s", info.Flavour, layerId)
+
+ // Generate layer descriptors
+ layers, err := layerPathsToDescriptors(parentLayerPaths)
+ if err != nil {
+ return err
+ }
+
+ // Convert info to API calling convention
+ infop, err := convertDriverInfo(info)
+ if err != nil {
+ logrus.Error(err)
+ return err
+ }
+
+ // This lock is a temporary workaround for a Windows bug. Only allowing one
+ // call to prepareLayer at a time vastly reduces the chance of a timeout.
+ prepareLayerLock.Lock()
+ defer prepareLayerLock.Unlock()
+ err = prepareLayer(&infop, layerId, layers)
+ if err != nil {
+ err = makeErrorf(err, title, "layerId=%s flavour=%d", layerId, info.Flavour)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"succeeded flavour=%d layerId=%s", info.Flavour, layerId)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/process.go b/vendor/github.com/Microsoft/hcsshim/process.go
new file mode 100644
index 000000000..faee2cfee
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/process.go
@@ -0,0 +1,384 @@
+package hcsshim
+
+import (
+ "encoding/json"
+ "io"
+ "sync"
+ "syscall"
+ "time"
+
+ "github.com/sirupsen/logrus"
+)
+
+// ContainerError is an error encountered in HCS
+type process struct {
+ handleLock sync.RWMutex
+ handle hcsProcess
+ processID int
+ container *container
+ cachedPipes *cachedPipes
+ callbackNumber 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 {
+ process.handleLock.RLock()
+ defer process.handleLock.RUnlock()
+ operation := "Kill"
+ title := "HCSShim::Process::" + operation
+ logrus.Debugf(title+" processid=%d", process.processID)
+
+ if process.handle == 0 {
+ return makeProcessError(process, operation, "", ErrAlreadyClosed)
+ }
+
+ var resultp *uint16
+ err := hcsTerminateProcess(process.handle, &resultp)
+ err = processHcsResult(err, resultp)
+ if err != nil {
+ return makeProcessError(process, operation, "", 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)
+
+ err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, nil)
+ if err != nil {
+ return makeProcessError(process, operation, "", 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)
+
+ err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, &timeout)
+ if err != nil {
+ return makeProcessError(process, operation, "", err)
+ }
+
+ logrus.Debugf(title+" succeeded processid=%d", process.processID)
+ return nil
+}
+
+// ExitCode returns the exit code of the process. The process must have
+// already terminated.
+func (process *process) ExitCode() (int, error) {
+ process.handleLock.RLock()
+ defer process.handleLock.RUnlock()
+ operation := "ExitCode"
+ title := "HCSShim::Process::" + operation
+ logrus.Debugf(title+" processid=%d", process.processID)
+
+ if process.handle == 0 {
+ return 0, makeProcessError(process, operation, "", ErrAlreadyClosed)
+ }
+
+ properties, err := process.properties()
+ if err != nil {
+ return 0, makeProcessError(process, operation, "", err)
+ }
+
+ if properties.Exited == false {
+ return 0, makeProcessError(process, operation, "", ErrInvalidProcessState)
+ }
+
+ if properties.LastWaitResult != 0 {
+ return 0, makeProcessError(process, operation, "", syscall.Errno(properties.LastWaitResult))
+ }
+
+ 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 {
+ process.handleLock.RLock()
+ defer process.handleLock.RUnlock()
+ operation := "ResizeConsole"
+ title := "HCSShim::Process::" + operation
+ logrus.Debugf(title+" processid=%d", process.processID)
+
+ if process.handle == 0 {
+ return makeProcessError(process, operation, "", ErrAlreadyClosed)
+ }
+
+ 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 {
+ return makeProcessError(process, operation, "", 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 {
+ return nil, err
+ }
+
+ if propertiesp == nil {
+ return nil, ErrUnexpectedValue
+ }
+ 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) {
+ process.handleLock.RLock()
+ defer process.handleLock.RUnlock()
+ operation := "Stdio"
+ title := "HCSShim::Process::" + operation
+ logrus.Debugf(title+" processid=%d", process.processID)
+
+ if process.handle == 0 {
+ return nil, nil, nil, makeProcessError(process, operation, "", ErrAlreadyClosed)
+ }
+
+ 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 {
+ return nil, nil, nil, makeProcessError(process, operation, "", 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, makeProcessError(process, operation, "", 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 {
+ process.handleLock.RLock()
+ defer process.handleLock.RUnlock()
+ operation := "CloseStdin"
+ title := "HCSShim::Process::" + operation
+ logrus.Debugf(title+" processid=%d", process.processID)
+
+ if process.handle == 0 {
+ return makeProcessError(process, operation, "", ErrAlreadyClosed)
+ }
+
+ 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 {
+ return makeProcessError(process, operation, "", 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 {
+ process.handleLock.Lock()
+ defer process.handleLock.Unlock()
+ 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 := process.unregisterCallback(); err != nil {
+ return makeProcessError(process, operation, "", err)
+ }
+
+ if err := hcsCloseProcess(process.handle); err != nil {
+ return makeProcessError(process, operation, "", err)
+ }
+
+ process.handle = 0
+
+ logrus.Debugf(title+" succeeded processid=%d", process.processID)
+ return nil
+}
+
+func (process *process) registerCallback() error {
+ context := &notifcationWatcherContext{
+ channels: newChannels(),
+ }
+
+ callbackMapLock.Lock()
+ callbackNumber := nextCallback
+ nextCallback++
+ callbackMap[callbackNumber] = context
+ callbackMapLock.Unlock()
+
+ var callbackHandle hcsCallback
+ err := hcsRegisterProcessCallback(process.handle, notificationWatcherCallback, callbackNumber, &callbackHandle)
+ if err != nil {
+ return err
+ }
+ context.handle = callbackHandle
+ process.callbackNumber = callbackNumber
+
+ return nil
+}
+
+func (process *process) unregisterCallback() error {
+ callbackNumber := process.callbackNumber
+
+ callbackMapLock.RLock()
+ context := callbackMap[callbackNumber]
+ callbackMapLock.RUnlock()
+
+ if context == nil {
+ return nil
+ }
+
+ handle := context.handle
+
+ if handle == 0 {
+ return nil
+ }
+
+ // hcsUnregisterProcessCallback has its own syncronization
+ // to wait for all callbacks to complete. We must NOT hold the callbackMapLock.
+ err := hcsUnregisterProcessCallback(handle)
+ if err != nil {
+ return err
+ }
+
+ closeChannels(context.channels)
+
+ callbackMapLock.Lock()
+ callbackMap[callbackNumber] = nil
+ callbackMapLock.Unlock()
+
+ handle = 0
+
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/processimage.go b/vendor/github.com/Microsoft/hcsshim/processimage.go
new file mode 100644
index 000000000..fadb1b92c
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/processimage.go
@@ -0,0 +1,23 @@
+package hcsshim
+
+import "os"
+
+// ProcessBaseLayer post-processes a base layer that has had its files extracted.
+// The files should have been extracted to <path>\Files.
+func ProcessBaseLayer(path string) error {
+ err := processBaseImage(path)
+ if err != nil {
+ return &os.PathError{Op: "ProcessBaseLayer", Path: path, Err: err}
+ }
+ return nil
+}
+
+// ProcessUtilityVMImage post-processes a utility VM image that has had its files extracted.
+// The files should have been extracted to <path>\Files.
+func ProcessUtilityVMImage(path string) error {
+ err := processUtilityImage(path)
+ if err != nil {
+ return &os.PathError{Op: "ProcessUtilityVMImage", Path: path, Err: err}
+ }
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/unpreparelayer.go b/vendor/github.com/Microsoft/hcsshim/unpreparelayer.go
new file mode 100644
index 000000000..e8a3b507b
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/unpreparelayer.go
@@ -0,0 +1,27 @@
+package hcsshim
+
+import "github.com/sirupsen/logrus"
+
+// UnprepareLayer disables the filesystem filter for the read-write layer with
+// the given id.
+func UnprepareLayer(info DriverInfo, layerId string) error {
+ title := "hcsshim::UnprepareLayer "
+ logrus.Debugf(title+"flavour %d layerId %s", info.Flavour, layerId)
+
+ // Convert info to API calling convention
+ infop, err := convertDriverInfo(info)
+ if err != nil {
+ logrus.Error(err)
+ return err
+ }
+
+ err = unprepareLayer(&infop, layerId)
+ if err != nil {
+ err = makeErrorf(err, title, "layerId=%s flavour=%d", layerId, info.Flavour)
+ logrus.Error(err)
+ return err
+ }
+
+ logrus.Debugf(title+"succeeded flavour %d layerId=%s", info.Flavour, layerId)
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/utils.go b/vendor/github.com/Microsoft/hcsshim/utils.go
new file mode 100644
index 000000000..bd6e2d94a
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/utils.go
@@ -0,0 +1,33 @@
+package hcsshim
+
+import (
+ "io"
+ "syscall"
+
+ "github.com/Microsoft/go-winio"
+)
+
+// makeOpenFiles calls winio.MakeOpenFile for each handle in a slice but closes all the handles
+// if there is an error.
+func makeOpenFiles(hs []syscall.Handle) (_ []io.ReadWriteCloser, err error) {
+ fs := make([]io.ReadWriteCloser, len(hs))
+ for i, h := range hs {
+ if h != syscall.Handle(0) {
+ if err == nil {
+ fs[i], err = winio.MakeOpenFile(h)
+ }
+ if err != nil {
+ syscall.Close(h)
+ }
+ }
+ }
+ if err != nil {
+ for _, f := range fs {
+ if f != nil {
+ f.Close()
+ }
+ }
+ return nil, err
+ }
+ return fs, nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/version.go b/vendor/github.com/Microsoft/hcsshim/version.go
new file mode 100644
index 000000000..ae10c23d4
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/version.go
@@ -0,0 +1,7 @@
+package hcsshim
+
+// IsTP4 returns whether the currently running Windows build is at least TP4.
+func IsTP4() bool {
+ // HNSCall was not present in TP4
+ return procHNSCall.Find() != nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/waithelper.go b/vendor/github.com/Microsoft/hcsshim/waithelper.go
new file mode 100644
index 000000000..b7be20ea0
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/waithelper.go
@@ -0,0 +1,63 @@
+package hcsshim
+
+import (
+ "time"
+
+ "github.com/sirupsen/logrus"
+)
+
+func processAsyncHcsResult(err error, resultp *uint16, callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error {
+ err = processHcsResult(err, resultp)
+ if IsPending(err) {
+ return waitForNotification(callbackNumber, expectedNotification, timeout)
+ }
+
+ return err
+}
+
+func waitForNotification(callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error {
+ callbackMapLock.RLock()
+ channels := callbackMap[callbackNumber].channels
+ callbackMapLock.RUnlock()
+
+ expectedChannel := channels[expectedNotification]
+ if expectedChannel == nil {
+ logrus.Errorf("unknown notification type in waitForNotification %x", expectedNotification)
+ return ErrInvalidNotificationType
+ }
+
+ var c <-chan time.Time
+ if timeout != nil {
+ timer := time.NewTimer(*timeout)
+ c = timer.C
+ defer timer.Stop()
+ }
+
+ select {
+ case err, ok := <-expectedChannel:
+ if !ok {
+ return ErrHandleClose
+ }
+ return err
+ case err, ok := <-channels[hcsNotificationSystemExited]:
+ if !ok {
+ return ErrHandleClose
+ }
+ // If the expected notification is hcsNotificationSystemExited which of the two selects
+ // chosen is random. Return the raw error if hcsNotificationSystemExited is expected
+ if channels[hcsNotificationSystemExited] == expectedChannel {
+ return err
+ }
+ return ErrUnexpectedContainerExit
+ case _, ok := <-channels[hcsNotificationServiceDisconnect]:
+ if !ok {
+ return ErrHandleClose
+ }
+ // hcsNotificationServiceDisconnect should never be an expected notification
+ // it does not need the same handling as hcsNotificationSystemExited
+ return ErrUnexpectedProcessAbort
+ case <-c:
+ return ErrTimeout
+ }
+ return nil
+}
diff --git a/vendor/github.com/Microsoft/hcsshim/zhcsshim.go b/vendor/github.com/Microsoft/hcsshim/zhcsshim.go
new file mode 100644
index 000000000..5d1a851ae
--- /dev/null
+++ b/vendor/github.com/Microsoft/hcsshim/zhcsshim.go
@@ -0,0 +1,1042 @@
+// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT
+
+package hcsshim
+
+import (
+ "syscall"
+ "unsafe"
+
+ "github.com/Microsoft/go-winio"
+ "golang.org/x/sys/windows"
+)
+
+var _ unsafe.Pointer
+
+// Do the interface allocations only once for common
+// Errno values.
+const (
+ errnoERROR_IO_PENDING = 997
+)
+
+var (
+ errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
+)
+
+// errnoErr returns common boxed Errno values, to prevent
+// allocations at runtime.
+func errnoErr(e syscall.Errno) error {
+ switch e {
+ case 0:
+ return nil
+ case errnoERROR_IO_PENDING:
+ return errERROR_IO_PENDING
+ }
+ // TODO: add more here, after collecting data on the common
+ // error values see on Windows. (perhaps when running
+ // all.bat?)
+ return e
+}
+
+var (
+ modole32 = windows.NewLazySystemDLL("ole32.dll")
+ modiphlpapi = windows.NewLazySystemDLL("iphlpapi.dll")
+ modvmcompute = windows.NewLazySystemDLL("vmcompute.dll")
+
+ procCoTaskMemFree = modole32.NewProc("CoTaskMemFree")
+ procSetCurrentThreadCompartmentId = modiphlpapi.NewProc("SetCurrentThreadCompartmentId")
+ procActivateLayer = modvmcompute.NewProc("ActivateLayer")
+ procCopyLayer = modvmcompute.NewProc("CopyLayer")
+ procCreateLayer = modvmcompute.NewProc("CreateLayer")
+ procCreateSandboxLayer = modvmcompute.NewProc("CreateSandboxLayer")
+ procExpandSandboxSize = modvmcompute.NewProc("ExpandSandboxSize")
+ procDeactivateLayer = modvmcompute.NewProc("DeactivateLayer")
+ procDestroyLayer = modvmcompute.NewProc("DestroyLayer")
+ procExportLayer = modvmcompute.NewProc("ExportLayer")
+ procGetLayerMountPath = modvmcompute.NewProc("GetLayerMountPath")
+ procGetBaseImages = modvmcompute.NewProc("GetBaseImages")
+ procImportLayer = modvmcompute.NewProc("ImportLayer")
+ procLayerExists = modvmcompute.NewProc("LayerExists")
+ procNameToGuid = modvmcompute.NewProc("NameToGuid")
+ procPrepareLayer = modvmcompute.NewProc("PrepareLayer")
+ procUnprepareLayer = modvmcompute.NewProc("UnprepareLayer")
+ procProcessBaseImage = modvmcompute.NewProc("ProcessBaseImage")
+ procProcessUtilityImage = modvmcompute.NewProc("ProcessUtilityImage")
+ procImportLayerBegin = modvmcompute.NewProc("ImportLayerBegin")
+ procImportLayerNext = modvmcompute.NewProc("ImportLayerNext")
+ procImportLayerWrite = modvmcompute.NewProc("ImportLayerWrite")
+ procImportLayerEnd = modvmcompute.NewProc("ImportLayerEnd")
+ procExportLayerBegin = modvmcompute.NewProc("ExportLayerBegin")
+ procExportLayerNext = modvmcompute.NewProc("ExportLayerNext")
+ procExportLayerRead = modvmcompute.NewProc("ExportLayerRead")
+ procExportLayerEnd = modvmcompute.NewProc("ExportLayerEnd")
+ 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")
+ procHcsRegisterComputeSystemCallback = modvmcompute.NewProc("HcsRegisterComputeSystemCallback")
+ procHcsUnregisterComputeSystemCallback = modvmcompute.NewProc("HcsUnregisterComputeSystemCallback")
+ 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")
+ procHcsGetServiceProperties = modvmcompute.NewProc("HcsGetServiceProperties")
+ procHcsRegisterProcessCallback = modvmcompute.NewProc("HcsRegisterProcessCallback")
+ procHcsUnregisterProcessCallback = modvmcompute.NewProc("HcsUnregisterProcessCallback")
+ procHcsModifyServiceSettings = modvmcompute.NewProc("HcsModifyServiceSettings")
+ procHNSCall = modvmcompute.NewProc("HNSCall")
+)
+
+func coTaskMemFree(buffer unsafe.Pointer) {
+ syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(buffer), 0, 0)
+ return
+}
+
+func SetCurrentThreadCompartmentId(compartmentId uint32) (hr error) {
+ r0, _, _ := syscall.Syscall(procSetCurrentThreadCompartmentId.Addr(), 1, uintptr(compartmentId), 0, 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func activateLayer(info *driverInfo, id string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _activateLayer(info, _p0)
+}
+
+func _activateLayer(info *driverInfo, id *uint16) (hr error) {
+ if hr = procActivateLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procActivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func copyLayer(info *driverInfo, srcId string, dstId string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(srcId)
+ if hr != nil {
+ return
+ }
+ var _p1 *uint16
+ _p1, hr = syscall.UTF16PtrFromString(dstId)
+ if hr != nil {
+ return
+ }
+ return _copyLayer(info, _p0, _p1, descriptors)
+}
+
+func _copyLayer(info *driverInfo, srcId *uint16, dstId *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p2 *WC_LAYER_DESCRIPTOR
+ if len(descriptors) > 0 {
+ _p2 = &descriptors[0]
+ }
+ if hr = procCopyLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procCopyLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(srcId)), uintptr(unsafe.Pointer(dstId)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func createLayer(info *driverInfo, id string, parent string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ var _p1 *uint16
+ _p1, hr = syscall.UTF16PtrFromString(parent)
+ if hr != nil {
+ return
+ }
+ return _createLayer(info, _p0, _p1)
+}
+
+func _createLayer(info *driverInfo, id *uint16, parent *uint16) (hr error) {
+ if hr = procCreateLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procCreateLayer.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(parent)))
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func createSandboxLayer(info *driverInfo, id string, parent string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ var _p1 *uint16
+ _p1, hr = syscall.UTF16PtrFromString(parent)
+ if hr != nil {
+ return
+ }
+ return _createSandboxLayer(info, _p0, _p1, descriptors)
+}
+
+func _createSandboxLayer(info *driverInfo, id *uint16, parent *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p2 *WC_LAYER_DESCRIPTOR
+ if len(descriptors) > 0 {
+ _p2 = &descriptors[0]
+ }
+ if hr = procCreateSandboxLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procCreateSandboxLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(parent)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func expandSandboxSize(info *driverInfo, id string, size uint64) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _expandSandboxSize(info, _p0, size)
+}
+
+func _expandSandboxSize(info *driverInfo, id *uint16, size uint64) (hr error) {
+ if hr = procExpandSandboxSize.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procExpandSandboxSize.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(size))
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func deactivateLayer(info *driverInfo, id string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _deactivateLayer(info, _p0)
+}
+
+func _deactivateLayer(info *driverInfo, id *uint16) (hr error) {
+ if hr = procDeactivateLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procDeactivateLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func destroyLayer(info *driverInfo, id string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _destroyLayer(info, _p0)
+}
+
+func _destroyLayer(info *driverInfo, id *uint16) (hr error) {
+ if hr = procDestroyLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procDestroyLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func exportLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ var _p1 *uint16
+ _p1, hr = syscall.UTF16PtrFromString(path)
+ if hr != nil {
+ return
+ }
+ return _exportLayer(info, _p0, _p1, descriptors)
+}
+
+func _exportLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p2 *WC_LAYER_DESCRIPTOR
+ if len(descriptors) > 0 {
+ _p2 = &descriptors[0]
+ }
+ if hr = procExportLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procExportLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func getLayerMountPath(info *driverInfo, id string, length *uintptr, buffer *uint16) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _getLayerMountPath(info, _p0, length, buffer)
+}
+
+func _getLayerMountPath(info *driverInfo, id *uint16, length *uintptr, buffer *uint16) (hr error) {
+ if hr = procGetLayerMountPath.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procGetLayerMountPath.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(length)), uintptr(unsafe.Pointer(buffer)), 0, 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func getBaseImages(buffer **uint16) (hr error) {
+ if hr = procGetBaseImages.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procGetBaseImages.Addr(), 1, uintptr(unsafe.Pointer(buffer)), 0, 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func importLayer(info *driverInfo, id string, path string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ var _p1 *uint16
+ _p1, hr = syscall.UTF16PtrFromString(path)
+ if hr != nil {
+ return
+ }
+ return _importLayer(info, _p0, _p1, descriptors)
+}
+
+func _importLayer(info *driverInfo, id *uint16, path *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p2 *WC_LAYER_DESCRIPTOR
+ if len(descriptors) > 0 {
+ _p2 = &descriptors[0]
+ }
+ if hr = procImportLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procImportLayer.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(_p2)), uintptr(len(descriptors)), 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func layerExists(info *driverInfo, id string, exists *uint32) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _layerExists(info, _p0, exists)
+}
+
+func _layerExists(info *driverInfo, id *uint16, exists *uint32) (hr error) {
+ if hr = procLayerExists.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procLayerExists.Addr(), 3, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(exists)))
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func nameToGuid(name string, guid *GUID) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(name)
+ if hr != nil {
+ return
+ }
+ return _nameToGuid(_p0, guid)
+}
+
+func _nameToGuid(name *uint16, guid *GUID) (hr error) {
+ if hr = procNameToGuid.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procNameToGuid.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(guid)), 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func prepareLayer(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _prepareLayer(info, _p0, descriptors)
+}
+
+func _prepareLayer(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR) (hr error) {
+ var _p1 *WC_LAYER_DESCRIPTOR
+ if len(descriptors) > 0 {
+ _p1 = &descriptors[0]
+ }
+ if hr = procPrepareLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procPrepareLayer.Addr(), 4, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), 0, 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func unprepareLayer(info *driverInfo, id string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _unprepareLayer(info, _p0)
+}
+
+func _unprepareLayer(info *driverInfo, id *uint16) (hr error) {
+ if hr = procUnprepareLayer.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procUnprepareLayer.Addr(), 2, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func processBaseImage(path string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(path)
+ if hr != nil {
+ return
+ }
+ return _processBaseImage(_p0)
+}
+
+func _processBaseImage(path *uint16) (hr error) {
+ if hr = procProcessBaseImage.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procProcessBaseImage.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func processUtilityImage(path string) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(path)
+ if hr != nil {
+ return
+ }
+ return _processUtilityImage(_p0)
+}
+
+func _processUtilityImage(path *uint16) (hr error) {
+ if hr = procProcessUtilityImage.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procProcessUtilityImage.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func importLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _importLayerBegin(info, _p0, descriptors, context)
+}
+
+func _importLayerBegin(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) {
+ var _p1 *WC_LAYER_DESCRIPTOR
+ if len(descriptors) > 0 {
+ _p1 = &descriptors[0]
+ }
+ if hr = procImportLayerBegin.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procImportLayerBegin.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), uintptr(unsafe.Pointer(context)), 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func importLayerNext(context uintptr, fileName string, fileInfo *winio.FileBasicInfo) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(fileName)
+ if hr != nil {
+ return
+ }
+ return _importLayerNext(context, _p0, fileInfo)
+}
+
+func _importLayerNext(context uintptr, fileName *uint16, fileInfo *winio.FileBasicInfo) (hr error) {
+ if hr = procImportLayerNext.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procImportLayerNext.Addr(), 3, uintptr(context), uintptr(unsafe.Pointer(fileName)), uintptr(unsafe.Pointer(fileInfo)))
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func importLayerWrite(context uintptr, buffer []byte) (hr error) {
+ var _p0 *byte
+ if len(buffer) > 0 {
+ _p0 = &buffer[0]
+ }
+ if hr = procImportLayerWrite.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procImportLayerWrite.Addr(), 3, uintptr(context), uintptr(unsafe.Pointer(_p0)), uintptr(len(buffer)))
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func importLayerEnd(context uintptr) (hr error) {
+ if hr = procImportLayerEnd.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procImportLayerEnd.Addr(), 1, uintptr(context), 0, 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func exportLayerBegin(info *driverInfo, id string, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(id)
+ if hr != nil {
+ return
+ }
+ return _exportLayerBegin(info, _p0, descriptors, context)
+}
+
+func _exportLayerBegin(info *driverInfo, id *uint16, descriptors []WC_LAYER_DESCRIPTOR, context *uintptr) (hr error) {
+ var _p1 *WC_LAYER_DESCRIPTOR
+ if len(descriptors) > 0 {
+ _p1 = &descriptors[0]
+ }
+ if hr = procExportLayerBegin.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procExportLayerBegin.Addr(), 5, uintptr(unsafe.Pointer(info)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(_p1)), uintptr(len(descriptors)), uintptr(unsafe.Pointer(context)), 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func exportLayerNext(context uintptr, fileName **uint16, fileInfo *winio.FileBasicInfo, fileSize *int64, deleted *uint32) (hr error) {
+ if hr = procExportLayerNext.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procExportLayerNext.Addr(), 5, uintptr(context), uintptr(unsafe.Pointer(fileName)), uintptr(unsafe.Pointer(fileInfo)), uintptr(unsafe.Pointer(fileSize)), uintptr(unsafe.Pointer(deleted)), 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func exportLayerRead(context uintptr, buffer []byte, bytesRead *uint32) (hr error) {
+ var _p0 *byte
+ if len(buffer) > 0 {
+ _p0 = &buffer[0]
+ }
+ if hr = procExportLayerRead.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procExportLayerRead.Addr(), 4, uintptr(context), uintptr(unsafe.Pointer(_p0)), uintptr(len(buffer)), uintptr(unsafe.Pointer(bytesRead)), 0, 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}
+
+func exportLayerEnd(context uintptr) (hr error) {
+ if hr = procExportLayerEnd.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall(procExportLayerEnd.Addr(), 1, uintptr(context), 0, 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ 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 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 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 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 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 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 _hnsCall(method string, path string, object string, response **uint16) (hr error) {
+ var _p0 *uint16
+ _p0, hr = syscall.UTF16PtrFromString(method)
+ if hr != nil {
+ return
+ }
+ var _p1 *uint16
+ _p1, hr = syscall.UTF16PtrFromString(path)
+ if hr != nil {
+ return
+ }
+ var _p2 *uint16
+ _p2, hr = syscall.UTF16PtrFromString(object)
+ if hr != nil {
+ return
+ }
+ return __hnsCall(_p0, _p1, _p2, response)
+}
+
+func __hnsCall(method *uint16, path *uint16, object *uint16, response **uint16) (hr error) {
+ if hr = procHNSCall.Find(); hr != nil {
+ return
+ }
+ r0, _, _ := syscall.Syscall6(procHNSCall.Addr(), 4, uintptr(unsafe.Pointer(method)), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(object)), uintptr(unsafe.Pointer(response)), 0, 0)
+ if int32(r0) < 0 {
+ hr = syscall.Errno(win32FromHresult(r0))
+ }
+ return
+}