Преглед изворни кода

Default GW support for overlay networks

Signed-off-by: msabansal <sabansal@microsoft.com>
msabansal пре 8 година
родитељ
комит
261fedba8c
25 измењених фајлова са 912 додато и 746 уклоњено
  1. 2 2
      libnetwork/Godeps/Godeps.json
  2. 23 12
      libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/baselayer.go
  3. 135 78
      libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/container.go
  4. 20 5
      libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/errors.go
  5. 6 23
      libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/hcsshim.go
  6. 3 2
      libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/hnsfuncs.go
  7. 34 13
      libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/importlayer.go
  8. 19 9
      libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/interface.go
  9. 315 33
      libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/legacy.go
  10. 11 1
      libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/preparelayer.go
  11. 48 46
      libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/process.go
  12. 0 6
      libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/utils.go
  13. 7 71
      libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/waithelper.go
  14. 75 379
      libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/zhcsshim.go
  15. 20 4
      libnetwork/default_gateway.go
  16. 6 0
      libnetwork/default_gateway_freebsd.go
  17. 6 0
      libnetwork/default_gateway_linux.go
  18. 6 0
      libnetwork/default_gateway_solaris.go
  19. 16 1
      libnetwork/default_gateway_windows.go
  20. 6 0
      libnetwork/drivers/windows/labels.go
  21. 0 2
      libnetwork/drivers/windows/overlay/joinleave_windows.go
  22. 79 34
      libnetwork/drivers/windows/windows.go
  23. 0 25
      libnetwork/endpoint_info.go
  24. 30 0
      libnetwork/endpoint_info_unix.go
  25. 45 0
      libnetwork/endpoint_info_windows.go

+ 2 - 2
libnetwork/Godeps/Godeps.json

@@ -26,8 +26,8 @@
 		},
 		{
 			"ImportPath": "github.com/Microsoft/hcsshim",
-			"Comment": "v0.5.1",
-			"Rev": "523023ef1ef8ec08b23bbff88ab68552c5f1a6d7"
+			"Comment": "v0.5.6",
+			"Rev": "e439b7d2b63f036d3a50c93a9e0b154a0d50e788"
 		},
 		{
 			"ImportPath": "github.com/Sirupsen/logrus",

+ 23 - 12
libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/baselayer.go

@@ -23,6 +23,26 @@ type dirInfo struct {
 	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()
@@ -142,18 +162,9 @@ func (w *baseLayerWriter) Close() error {
 	if w.err == nil {
 		// Restore the file times of all the directories, since they may have
 		// been modified by creating child directories.
-		for i := range w.dirInfo {
-			di := &w.dirInfo[len(w.dirInfo)-i-1]
-			f, err := winio.OpenForBackup(di.path, uint32(syscall.GENERIC_READ|syscall.GENERIC_WRITE), syscall.FILE_SHARE_READ, syscall.OPEN_EXISTING)
-			if err != nil {
-				return makeError(err, "Failed to OpenForBackup", di.path)
-			}
-
-			err = winio.SetFileBasicInfo(f, &di.fileInfo)
-			f.Close()
-			if err != nil {
-				return makeError(err, "Failed to SetFileBasicInfo", di.path)
-			}
+		err = reapplyDirectoryTimes(w.dirInfo)
+		if err != nil {
+			return err
 		}
 
 		err = ProcessBaseLayer(w.root)

+ 135 - 78
libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/container.go

@@ -3,6 +3,7 @@ package hcsshim
 import (
 	"encoding/json"
 	"runtime"
+	"sync"
 	"syscall"
 	"time"
 
@@ -20,12 +21,14 @@ const (
 )
 
 type container struct {
+	handleLock     sync.RWMutex
 	handle         hcsSystem
 	id             string
 	callbackNumber uintptr
 }
 
-type containerProperties struct {
+// 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
@@ -33,6 +36,8 @@ type containerProperties struct {
 	SiloGUID          string            `json:"SiloGuid,omitempty"`
 	IsDummy           bool              `json:",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"`
@@ -116,20 +121,15 @@ func CreateContainer(id string, c *ContainerConfig) (Container, error) {
 	logrus.Debugf(title+" id=%s config=%s", id, configuration)
 
 	var (
-		resultp     *uint16
-		createError error
+		resultp  *uint16
+		identity syscall.Handle
 	)
-	if hcsCallbacksSupported {
-		var 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)
-			}
+	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)
 		}
-	} else {
-		createError = hcsCreateComputeSystemTP5(id, configuration, &container.handle, &resultp)
 	}
 
 	err = processAsyncHcsResult(createError, resultp, container.callbackNumber, hcsNotificationSystemCreateCompleted, &defaultTimeout)
@@ -164,19 +164,61 @@ func OpenContainer(id string) (Container, error) {
 
 	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)
 	runtime.SetFinalizer(container, closeContainer)
 	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 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 := hcsStartComputeSystemTP5(container.handle, nil, &resultp)
+	err := hcsStartComputeSystem(container.handle, "", &resultp)
 	err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemStartCompleted, &defaultTimeout)
 	if err != nil {
 		return makeContainerError(container, operation, "", err)
@@ -189,12 +231,18 @@ func (container *container) Start() error {
 // 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 := hcsShutdownComputeSystemTP5(container.handle, nil, &resultp)
+	err := hcsShutdownComputeSystem(container.handle, "", &resultp)
 	err = processHcsResult(err, resultp)
 	if err != nil {
 		return makeContainerError(container, operation, "", err)
@@ -207,12 +255,18 @@ func (container *container) Shutdown() error {
 // 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 := hcsTerminateComputeSystemTP5(container.handle, nil, &resultp)
+	err := hcsTerminateComputeSystem(container.handle, "", &resultp)
 	err = processHcsResult(err, resultp)
 	if err != nil {
 		return makeContainerError(container, operation, "", err)
@@ -228,26 +282,15 @@ func (container *container) Wait() error {
 	title := "HCSShim::Container::" + operation
 	logrus.Debugf(title+" id=%s", container.id)
 
-	if hcsCallbacksSupported {
-		err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, nil)
-		if err != nil {
-			return makeContainerError(container, operation, "", err)
-		}
-	} else {
-		_, err := container.waitTimeoutInternal(syscall.INFINITE)
-		if err != nil {
-			return makeContainerError(container, operation, "", err)
-		}
+	err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, nil)
+	if err != nil {
+		return makeContainerError(container, operation, "", err)
 	}
 
 	logrus.Debugf(title+" succeeded id=%s", container.id)
 	return nil
 }
 
-func (container *container) waitTimeoutInternal(timeout uint32) (bool, error) {
-	return waitTimeoutInternalHelper(container, timeout)
-}
-
 // WaitTimeout synchronously waits for the container to terminate or the duration to elapse.
 // If the timeout expires, IsTimeout(err) == true
 func (container *container) WaitTimeout(timeout time.Duration) error {
@@ -255,42 +298,16 @@ func (container *container) WaitTimeout(timeout time.Duration) error {
 	title := "HCSShim::Container::" + operation
 	logrus.Debugf(title+" id=%s", container.id)
 
-	if hcsCallbacksSupported {
-		err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, &timeout)
-		if err != nil {
-			return makeContainerError(container, operation, "", err)
-		}
-	} else {
-		finished, err := waitTimeoutHelper(container, timeout)
-		if !finished {
-			err = ErrTimeout
-		}
-		if err != nil {
-			return makeContainerError(container, operation, "", err)
-		}
+	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) hcsWait(timeout uint32) (bool, error) {
-	var (
-		resultp   *uint16
-		exitEvent syscall.Handle
-	)
-
-	err := hcsCreateComputeSystemWait(container.handle, &exitEvent, &resultp)
-	err = processHcsResult(err, resultp)
-	if err != nil {
-		return false, err
-	}
-	defer syscall.CloseHandle(exitEvent)
-
-	return waitForSingleObject(exitEvent, timeout)
-}
-
-func (container *container) properties(query string) (*containerProperties, error) {
+func (container *container) properties(query string) (*ContainerProperties, error) {
 	var (
 		resultp     *uint16
 		propertiesp *uint16
@@ -305,7 +322,7 @@ func (container *container) properties(query string) (*containerProperties, erro
 		return nil, ErrUnexpectedValue
 	}
 	propertiesRaw := convertAndFreeCoTaskMemBytes(propertiesp)
-	properties := &containerProperties{}
+	properties := &ContainerProperties{}
 	if err := json.Unmarshal(propertiesRaw, properties); err != nil {
 		return nil, err
 	}
@@ -314,9 +331,16 @@ func (container *container) properties(query string) (*containerProperties, erro
 
 // 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)
@@ -328,9 +352,16 @@ func (container *container) HasPendingUpdates() (bool, error) {
 
 // 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)
@@ -342,9 +373,16 @@ func (container *container) Statistics() (Statistics, error) {
 
 // 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)
@@ -356,12 +394,18 @@ func (container *container) ProcessList() ([]ProcessListItem, error) {
 
 // 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 := hcsPauseComputeSystemTP5(container.handle, nil, &resultp)
+	err := hcsPauseComputeSystem(container.handle, "", &resultp)
 	err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemPauseCompleted, &defaultTimeout)
 	if err != nil {
 		return makeContainerError(container, operation, "", err)
@@ -373,14 +417,18 @@ func (container *container) Pause() error {
 
 // 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)
-	var (
-		resultp *uint16
-	)
 
-	err := hcsResumeComputeSystemTP5(container.handle, nil, &resultp)
+	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)
@@ -392,6 +440,8 @@ func (container *container) Resume() error {
 
 // 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 (
@@ -400,6 +450,10 @@ func (container *container) CreateProcess(c *ProcessConfig) (Process, error) {
 		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
@@ -431,10 +485,8 @@ func (container *container) CreateProcess(c *ProcessConfig) (Process, error) {
 		},
 	}
 
-	if hcsCallbacksSupported {
-		if err := process.registerCallback(); err != nil {
-			return nil, makeContainerError(container, operation, "", err)
-		}
+	if err := process.registerCallback(); err != nil {
+		return nil, makeContainerError(container, operation, "", err)
 	}
 
 	logrus.Debugf(title+" succeeded id=%s processid=%s", container.id, process.processID)
@@ -444,6 +496,8 @@ func (container *container) CreateProcess(c *ProcessConfig) (Process, error) {
 
 // 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)
@@ -452,6 +506,10 @@ func (container *container) OpenProcess(pid int) (Process, error) {
 		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 {
@@ -464,10 +522,8 @@ func (container *container) OpenProcess(pid int) (Process, error) {
 		container: container,
 	}
 
-	if hcsCallbacksSupported {
-		if err := process.registerCallback(); err != nil {
-			return nil, makeContainerError(container, operation, "", err)
-		}
+	if err := process.registerCallback(); err != nil {
+		return nil, makeContainerError(container, operation, "", err)
 	}
 
 	logrus.Debugf(title+" succeeded id=%s processid=%s", container.id, process.processID)
@@ -477,6 +533,8 @@ func (container *container) OpenProcess(pid int) (Process, error) {
 
 // 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)
@@ -486,10 +544,8 @@ func (container *container) Close() error {
 		return nil
 	}
 
-	if hcsCallbacksSupported {
-		if err := container.unregisterCallback(); err != nil {
-			return makeContainerError(container, operation, "", err)
-		}
+	if err := container.unregisterCallback(); err != nil {
+		return makeContainerError(container, operation, "", err)
 	}
 
 	if err := hcsCloseComputeSystem(container.handle); err != nil {
@@ -497,6 +553,7 @@ func (container *container) Close() error {
 	}
 
 	container.handle = 0
+	runtime.SetFinalizer(container, nil)
 
 	logrus.Debugf(title+" succeeded id=%s", container.id)
 	return nil

+ 20 - 5
libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/errors.go

@@ -16,6 +16,9 @@ var (
 	// 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")
 
@@ -80,8 +83,13 @@ func (e *ContainerError) Error() string {
 		s += " encountered an error during " + e.Operation
 	}
 
-	if e.Err != nil {
-		s += fmt.Sprintf(" failed in Win32: %s (0x%x)", e.Err, win32FromError(e.Err))
+	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 != "" {
@@ -116,16 +124,16 @@ func (e *ProcessError) Error() string {
 	}
 
 	if e.Operation != "" {
-		s += " " + e.Operation
+		s += " encountered an error during " + e.Operation
 	}
 
 	switch e.Err.(type) {
 	case nil:
 		break
 	case syscall.Errno:
-		s += fmt.Sprintf(" failed in Win32: %s (0x%x)", e.Err, win32FromError(e.Err))
+		s += fmt.Sprintf(": failure in a Windows system call: %s (0x%x)", e.Err, win32FromError(e.Err))
 	default:
-		s += fmt.Sprintf(" failed: %s", e.Error())
+		s += fmt.Sprintf(": %s", e.Err.Error())
 	}
 
 	return s
@@ -151,6 +159,13 @@ func IsNotExist(err error) bool {
 		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 {

+ 6 - 23
libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/hcsshim.go

@@ -1,4 +1,4 @@
-// Shim for the Host Compute Service (HSC) to manage Windows Server
+// Shim for the Host Compute Service (HCS) to manage Windows Server
 // containers and Hyper-V containers.
 
 package hcsshim
@@ -44,16 +44,6 @@ import (
 //sys exportLayerRead(context uintptr, buffer []byte, bytesRead *uint32) (hr error) = vmcompute.ExportLayerRead?
 //sys exportLayerEnd(context uintptr) (hr error) = vmcompute.ExportLayerEnd?
 
-//sys createComputeSystem(id string, configuration string) (hr error) = vmcompute.CreateComputeSystem?
-//sys createProcessWithStdHandlesInComputeSystem(id string, paramsJson string, pid *uint32, stdin *syscall.Handle, stdout *syscall.Handle, stderr *syscall.Handle) (hr error) = vmcompute.CreateProcessWithStdHandlesInComputeSystem?
-//sys resizeConsoleInComputeSystem(id string, pid uint32, height uint16, width uint16, flags uint32) (hr error) = vmcompute.ResizeConsoleInComputeSystem?
-//sys shutdownComputeSystem(id string, timeout uint32) (hr error) = vmcompute.ShutdownComputeSystem?
-//sys startComputeSystem(id string) (hr error) = vmcompute.StartComputeSystem?
-//sys terminateComputeSystem(id string) (hr error) = vmcompute.TerminateComputeSystem?
-//sys terminateProcessInComputeSystem(id string, pid uint32) (hr error) = vmcompute.TerminateProcessInComputeSystem?
-//sys waitForProcessInComputeSystem(id string, pid uint32, timeout uint32, exitCode *uint32) (hr error) = vmcompute.WaitForProcessInComputeSystem?
-//sys getComputeSystemProperties(id string, flags uint32, properties **uint16) (hr error) = vmcompute.GetComputeSystemProperties?
-
 //sys hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) = vmcompute.HcsEnumerateComputeSystems?
 //sys hcsCreateComputeSystem(id string, configuration string, identity syscall.Handle, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsCreateComputeSystem?
 //sys hcsOpenComputeSystem(id string, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsOpenComputeSystem?
@@ -65,7 +55,9 @@ import (
 //sys hcsResumeComputeSystem(computeSystem hcsSystem, options string, result **uint16) (hr error) = vmcompute.HcsResumeComputeSystem?
 //sys hcsGetComputeSystemProperties(computeSystem hcsSystem, propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetComputeSystemProperties?
 //sys hcsModifyComputeSystem(computeSystem hcsSystem, configuration string, result **uint16) (hr error) = vmcompute.HcsModifyComputeSystem?
-//sys hcsCreateComputeSystemWait(computeSystem hcsSystem, exitEvent *syscall.Handle, result **uint16) (hr error) = vmcompute.HcsCreateComputeSystemWait?
+//sys 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?
@@ -73,21 +65,12 @@ import (
 //sys hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) = vmcompute.HcsGetProcessInfo?
 //sys hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) = vmcompute.HcsGetProcessProperties?
 //sys hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) = vmcompute.HcsModifyProcess?
-//sys hcsCreateProcessWait(process hcsProcess, settings *syscall.Handle, result **uint16) (hr error) = vmcompute.HcsCreateProcessWait?
 //sys hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) = vmcompute.HcsGetServiceProperties?
-//sys hcsModifyServiceSettings(settings string, result **uint16) (hr error) = vmcompute.HcsModifyServiceSettings?
-
-//sys hcsCreateComputeSystemTP5(id string, configuration string, computeSystem *hcsSystem, result **uint16) (hr error) = vmcompute.HcsCreateComputeSystem?
-//sys hcsStartComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) = vmcompute.HcsStartComputeSystem?
-//sys hcsShutdownComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) = vmcompute.HcsShutdownComputeSystem?
-//sys hcsTerminateComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) = vmcompute.HcsTerminateComputeSystem?
-//sys hcsPauseComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) = vmcompute.HcsPauseComputeSystem?
-//sys hcsResumeComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) = vmcompute.HcsResumeComputeSystem?
-//sys hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterComputeSystemCallback?
-//sys hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterComputeSystemCallback?
 //sys hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) = vmcompute.HcsRegisterProcessCallback?
 //sys hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) = vmcompute.HcsUnregisterProcessCallback?
 
+//sys hcsModifyServiceSettings(settings string, result **uint16) (hr error) = vmcompute.HcsModifyServiceSettings?
+
 //sys _hnsCall(method string, path string, object string, response **uint16) (hr error) = vmcompute.HNSCall?
 
 const (

+ 3 - 2
libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/hnsfuncs.go

@@ -52,7 +52,7 @@ type MacPool struct {
 
 // HNSNetwork represents a network in HNS
 type HNSNetwork struct {
-	Id                   string            `json:",omitempty"`
+	Id                   string            `json:"ID,omitempty"`
 	Name                 string            `json:",omitempty"`
 	Type                 string            `json:",omitempty"`
 	NetworkAdapterName   string            `json:",omitempty"`
@@ -68,7 +68,7 @@ type HNSNetwork struct {
 
 // HNSEndpoint represents a network endpoint in HNS
 type HNSEndpoint struct {
-	Id                 string            `json:",omitempty"`
+	Id                 string            `json:"ID,omitempty"`
 	Name               string            `json:",omitempty"`
 	VirtualNetwork     string            `json:",omitempty"`
 	VirtualNetworkName string            `json:",omitempty"`
@@ -79,6 +79,7 @@ type HNSEndpoint struct {
 	DNSServerList      string            `json:",omitempty"`
 	GatewayAddress     string            `json:",omitempty"`
 	EnableInternalDNS  bool              `json:",omitempty"`
+	DisableICC         bool              `json:",omitempty"`
 	PrefixLength       uint8             `json:",omitempty"`
 	IsRemoteEndpoint   bool              `json:",omitempty"`
 }

+ 34 - 13
libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/importlayer.go

@@ -130,21 +130,42 @@ type legacyLayerWriterWrapper struct {
 }
 
 func (r *legacyLayerWriterWrapper) Close() error {
+	defer os.RemoveAll(r.root)
 	err := r.legacyLayerWriter.Close()
-	if err == nil {
-		var fullPath string
-		// 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 {
-			info.HomeDir = ""
-			err = ImportLayer(info, fullPath, r.path, r.parentLayerPaths)
+	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
 		}
 	}
-	os.RemoveAll(r.root)
-	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.
@@ -166,7 +187,7 @@ func NewLayerWriter(info DriverInfo, layerID string, parentLayerPaths []string)
 			return nil, err
 		}
 		return &legacyLayerWriterWrapper{
-			legacyLayerWriter: newLegacyLayerWriter(path),
+			legacyLayerWriter: newLegacyLayerWriter(path, parentLayerPaths, filepath.Join(info.HomeDir, layerID)),
 			info:              info,
 			layerID:           layerID,
 			path:              path,

+ 19 - 9
libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/interface.go

@@ -10,13 +10,14 @@ import (
 type ProcessConfig struct {
 	ApplicationName  string
 	CommandLine      string
+	User             string
 	WorkingDirectory string
 	Environment      map[string]string
 	EmulateConsole   bool
 	CreateStdInPipe  bool
 	CreateStdOutPipe bool
 	CreateStdErrPipe bool
-	ConsoleSize      [2]int
+	ConsoleSize      [2]uint
 }
 
 type Layer struct {
@@ -25,9 +26,11 @@ type Layer struct {
 }
 
 type MappedDir struct {
-	HostPath      string
-	ContainerPath string
-	ReadOnly      bool
+	HostPath         string
+	ContainerPath    string
+	ReadOnly         bool
+	BandwidthMaximum uint64
+	IOPSMaximum      uint64
 }
 
 type HvRuntime struct {
@@ -42,10 +45,10 @@ type ContainerConfig struct {
 	Name                     string      // Name of the container. We use the docker ID.
 	Owner                    string      // The management platform that created this container
 	IsDummy                  bool        // Used for development purposes.
-	VolumePath               string      // Windows volume path for scratch space
+	VolumePath               string      `json:",omitempty"` // Windows volume path for scratch space. Used by Windows Server Containers only. Format \\?\\Volume{GUID}
 	IgnoreFlushesDuringBoot  bool        // Optimization hint for container startup in Windows
-	LayerFolderPath          string      // Where the layer folders are located
-	Layers                   []Layer     // List of storage layers
+	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 0..10000 on Windows; where 0 will be omitted and HCS will default.
@@ -56,14 +59,21 @@ type ContainerConfig struct {
 	MemoryMaximumInMB        int64       `json:",omitempty"` // Maximum memory available to the container in Megabytes
 	HostName                 string      // Hostname
 	MappedDirectories        []MappedDir // List of mapped directories (volumes/mounts)
-	SandboxPath              string      // Location of unmounted sandbox (used for Hyper-V containers)
+	SandboxPath              string      `json:",omitempty"` // Location of unmounted sandbox. Used by Hyper-V containers only. Format %root%\windowsfilter
 	HvPartition              bool        // True if it a Hyper-V Container
 	EndpointList             []string    // List of networking endpoints to be attached to container
-	HvRuntime                *HvRuntime  // Hyper-V container settings
+	HvRuntime                *HvRuntime  `json:",omitempty"` // Hyper-V container settings. Used by Hyper-V containers only. Format ImagePath=%root%\BaseLayerID\UtilityVM
 	Servicing                bool        // True if this container is for servicing
 	AllowUnqualifiedDNSQuery bool        // True to allow unqualified DNS name resolution
 }
 
+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.

+ 315 - 33
libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/legacy.go

@@ -16,6 +16,13 @@ import (
 
 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,
+}
+
 func openFileOrDir(path string, mode uint32, createDisposition uint32) (file *os.File, err error) {
 	return winio.OpenForBackup(path, mode, syscall.FILE_SHARE_READ, createDisposition)
 }
@@ -49,17 +56,15 @@ type legacyLayerReader struct {
 	proceed      chan bool
 	currentFile  *os.File
 	backupReader *winio.BackupFileReader
-	isTP4Format  bool
 }
 
 // newLegacyLayerReader returns a new LayerReader that can read the Windows
-// TP4 transport format from disk.
+// container layer transport format from disk.
 func newLegacyLayerReader(root string) *legacyLayerReader {
 	r := &legacyLayerReader{
-		root:        root,
-		result:      make(chan *fileEntry),
-		proceed:     make(chan bool),
-		isTP4Format: IsTP4(),
+		root:    root,
+		result:  make(chan *fileEntry),
+		proceed: make(chan bool),
 	}
 	go r.walk()
 	return r
@@ -251,17 +256,14 @@ func (r *legacyLayerReader) Next() (path string, size int64, fileInfo *winio.Fil
 		fileInfo.LastAccessTime = fileInfo.LastWriteTime
 
 	} else {
-		beginning := int64(0)
-		if !r.isTP4Format {
-			// In TP5, the file attributes were added before the backup stream
-			var attr uint32
-			err = binary.Read(f, binary.LittleEndian, &attr)
-			if err != nil {
-				return
-			}
-			fileInfo.FileAttributes = uintptr(attr)
-			beginning = 4
+		// 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() {
@@ -301,21 +303,32 @@ func (r *legacyLayerReader) Close() error {
 	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
-	isTP4Format  bool
 	pathFixed    bool
+	HasUtilityVM bool
+	uvmDi        []dirInfo
+	addedFiles   map[string]bool
+	PendingLinks []pendingLink
 }
 
-// newLegacyLayerWriter returns a LayerWriter that can write the TP4 transport format
-// to disk.
-func newLegacyLayerWriter(root string) *legacyLayerWriter {
+// 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,
-		isTP4Format: IsTP4(),
+		parentRoots: parentRoots,
+		destRoot:    destRoot,
+		addedFiles:  make(map[string]bool),
 	}
 }
 
@@ -325,12 +338,42 @@ func (w *legacyLayerWriter) init() error {
 		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, `UtilityVM`), 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], `UtilityVM\Files`), filepath.Join(w.destRoot, `UtilityVM\Files`), 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()
@@ -342,15 +385,180 @@ func (w *legacyLayerWriter) reset() {
 	}
 }
 
+// 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
 	}
-	path := filepath.Join(w.root, name)
 
-	createDisposition := uint32(syscall.CREATE_NEW)
+	if name == `UtilityVM` {
+		return w.initUtilityVM()
+	}
+
+	if strings.HasPrefix(name, `UtilityVM\`) {
+		if !w.HasUtilityVM {
+			return errors.New("missing UtilityVM directory")
+		}
+		if !strings.HasPrefix(name, `UtilityVM\Files\`) && name != `UtilityVM\Files` {
+			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 {
@@ -359,7 +567,7 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
 		path += ".$wcidirs$"
 	}
 
-	f, err := openFileOrDir(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, createDisposition)
+	f, err := openFileOrDir(path, syscall.GENERIC_READ|syscall.GENERIC_WRITE, syscall.CREATE_NEW)
 	if err != nil {
 		return err
 	}
@@ -380,29 +588,97 @@ func (w *legacyLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo) erro
 	if strings.HasPrefix(name, `Hives\`) {
 		w.backupWriter = winio.NewBackupFileWriter(f, false)
 	} else {
-		if !w.isTP4Format {
-			// In TP5, the file attributes were added to the header
-			err = binary.Write(f, binary.LittleEndian, uint32(fileInfo.FileAttributes))
-			if err != nil {
-				return err
-			}
+		// 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 {
-	return errors.New("hard links not supported with legacy writer")
+	w.reset()
+	err := w.init()
+	if err != nil {
+		return err
+	}
+
+	var requiredPrefix string
+	var roots []string
+	if prefix := `Files\`; strings.HasPrefix(name, prefix) {
+		requiredPrefix = prefix
+		// Look for cross-layer hard link targets in the parent layers, since
+		// nothing is in the destination path yet.
+		roots = w.parentRoots
+	} else if prefix := `UtilityVM\Files\`; strings.HasPrefix(name, prefix) {
+		requiredPrefix = prefix
+		// 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 requiredPrefix == "" || !strings.HasPrefix(target, requiredPrefix) {
+		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 !strings.HasPrefix(name, `Files\`) {
+	if strings.HasPrefix(name, `Files\`) {
+		w.tombstones = append(w.tombstones, name[len(`Files\`):])
+	} else if strings.HasPrefix(name, `UtilityVM\Files\`) {
+		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)
 	}
-	w.tombstones = append(w.tombstones, name[len(`Files\`):])
+
 	return nil
 }
 
@@ -437,5 +713,11 @@ func (w *legacyLayerWriter) Close() error {
 			return err
 		}
 	}
+	if w.HasUtilityVM {
+		err = reapplyDirectoryTimes(w.uvmDi)
+		if err != nil {
+			return err
+		}
+	}
 	return nil
 }

+ 11 - 1
libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/preparelayer.go

@@ -1,6 +1,12 @@
 package hcsshim
 
-import "github.com/Sirupsen/logrus"
+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
@@ -24,6 +30,10 @@ func PrepareLayer(info DriverInfo, layerId string, parentLayerPaths []string) er
 		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)

+ 48 - 46
libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/process.go

@@ -3,6 +3,8 @@ package hcsshim
 import (
 	"encoding/json"
 	"io"
+	"runtime"
+	"sync"
 	"syscall"
 	"time"
 
@@ -11,6 +13,7 @@ import (
 
 // ContainerError is an error encountered in HCS
 type process struct {
+	handleLock     sync.RWMutex
 	handle         hcsProcess
 	processID      int
 	container      *container
@@ -64,10 +67,16 @@ func (process *process) Pid() int {
 
 // 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)
@@ -85,16 +94,9 @@ func (process *process) Wait() error {
 	title := "HCSShim::Process::" + operation
 	logrus.Debugf(title+" processid=%d", process.processID)
 
-	if hcsCallbacksSupported {
-		err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, nil)
-		if err != nil {
-			return makeProcessError(process, operation, "", err)
-		}
-	} else {
-		_, err := process.waitTimeoutInternal(syscall.INFINITE)
-		if err != nil {
-			return makeProcessError(process, operation, "", err)
-		}
+	err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, nil)
+	if err != nil {
+		return makeProcessError(process, operation, "", err)
 	}
 
 	logrus.Debugf(title+" succeeded processid=%d", process.processID)
@@ -108,51 +110,28 @@ func (process *process) WaitTimeout(timeout time.Duration) error {
 	title := "HCSShim::Process::" + operation
 	logrus.Debugf(title+" processid=%d", process.processID)
 
-	if hcsCallbacksSupported {
-		err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, &timeout)
-		if err != nil {
-			return makeProcessError(process, operation, "", err)
-		}
-	} else {
-		finished, err := waitTimeoutHelper(process, timeout)
-		if !finished {
-			err = ErrTimeout
-		}
-		if err != nil {
-			return makeProcessError(process, operation, "", err)
-		}
+	err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, &timeout)
+	if err != nil {
+		return makeProcessError(process, operation, "", err)
 	}
 
 	logrus.Debugf(title+" succeeded processid=%d", process.processID)
 	return nil
 }
 
-func (process *process) hcsWait(timeout uint32) (bool, error) {
-	var (
-		resultp   *uint16
-		exitEvent syscall.Handle
-	)
-	err := hcsCreateProcessWait(process.handle, &exitEvent, &resultp)
-	err = processHcsResult(err, resultp)
-	if err != nil {
-		return false, err
-	}
-	defer syscall.CloseHandle(exitEvent)
-
-	return waitForSingleObject(exitEvent, timeout)
-}
-
-func (process *process) waitTimeoutInternal(timeout uint32) (bool, error) {
-	return waitTimeoutInternalHelper(process, timeout)
-}
-
 // ExitCode returns the exit code of the process. The process must have
 // already terminated.
 func (process *process) ExitCode() (int, error) {
+	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)
@@ -162,16 +141,26 @@ func (process *process) ExitCode() (int, error) {
 		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{
@@ -231,10 +220,16 @@ func (process *process) properties() (*processStatus, error) {
 // 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 {
@@ -269,10 +264,16 @@ func (process *process) Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, e
 // 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{
@@ -301,6 +302,8 @@ func (process *process) CloseStdin() error {
 // 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)
@@ -310,10 +313,8 @@ func (process *process) Close() error {
 		return nil
 	}
 
-	if hcsCallbacksSupported {
-		if err := process.unregisterCallback(); err != nil {
-			return makeProcessError(process, operation, "", err)
-		}
+	if err := process.unregisterCallback(); err != nil {
+		return makeProcessError(process, operation, "", err)
 	}
 
 	if err := hcsCloseProcess(process.handle); err != nil {
@@ -321,6 +322,7 @@ func (process *process) Close() error {
 	}
 
 	process.handle = 0
+	runtime.SetFinalizer(process, nil)
 
 	logrus.Debugf(title+" succeeded processid=%d", process.processID)
 	return nil

+ 0 - 6
libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/utils.go

@@ -7,12 +7,6 @@ import (
 	"github.com/Microsoft/go-winio"
 )
 
-var (
-	vmcomputedll          = syscall.NewLazyDLL("vmcompute.dll")
-	hcsCallbackAPI        = vmcomputedll.NewProc("HcsRegisterComputeSystemCallback")
-	hcsCallbacksSupported = hcsCallbackAPI.Find() == nil
-)
-
 // 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) {

+ 7 - 71
libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/waithelper.go

@@ -1,52 +1,10 @@
 package hcsshim
 
 import (
-	"github.com/Sirupsen/logrus"
-	"syscall"
 	"time"
-)
-
-type waitable interface {
-	waitTimeoutInternal(timeout uint32) (bool, error)
-	hcsWait(timeout uint32) (bool, error)
-}
-
-func waitTimeoutHelper(object waitable, timeout time.Duration) (bool, error) {
-	var (
-		millis uint32
-	)
-
-	for totalMillis := uint64(timeout / time.Millisecond); totalMillis > 0; totalMillis = totalMillis - uint64(millis) {
-		if totalMillis >= syscall.INFINITE {
-			millis = syscall.INFINITE - 1
-		} else {
-			millis = uint32(totalMillis)
-		}
-
-		result, err := object.waitTimeoutInternal(millis)
-
-		if err != nil {
-			return result, err
-		}
-	}
-	return true, nil
-}
-
-func waitTimeoutInternalHelper(object waitable, timeout uint32) (bool, error) {
-	return object.hcsWait(timeout)
-}
 
-func waitForSingleObject(handle syscall.Handle, timeout uint32) (bool, error) {
-	s, e := syscall.WaitForSingleObject(handle, timeout)
-	switch s {
-	case syscall.WAIT_OBJECT_0:
-		return true, nil
-	case syscall.WAIT_TIMEOUT:
-		return false, nil
-	default:
-		return false, e
-	}
-}
+	"github.com/Sirupsen/logrus"
+)
 
 func processAsyncHcsResult(err error, resultp *uint16, callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error {
 	err = processHcsResult(err, resultp)
@@ -68,37 +26,13 @@ func waitForNotification(callbackNumber uintptr, expectedNotification hcsNotific
 		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 <-timer.C:
-			return ErrTimeout
-		}
 	}
+
 	select {
 	case err, ok := <-expectedChannel:
 		if !ok {
@@ -122,5 +56,7 @@ func waitForNotification(callbackNumber uintptr, expectedNotification hcsNotific
 		// hcsNotificationServiceDisconnect should never be an expected notification
 		// it does not need the same handling as hcsNotificationSystemExited
 		return ErrUnexpectedProcessAbort
+	case <-c:
+		return ErrTimeout
 	}
 }

+ 75 - 379
libnetwork/Godeps/_workspace/src/github.com/Microsoft/hcsshim/zhcsshim.go

@@ -13,69 +13,57 @@ var (
 	modiphlpapi  = syscall.NewLazyDLL("iphlpapi.dll")
 	modvmcompute = syscall.NewLazyDLL("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")
-	procCreateComputeSystem                        = modvmcompute.NewProc("CreateComputeSystem")
-	procCreateProcessWithStdHandlesInComputeSystem = modvmcompute.NewProc("CreateProcessWithStdHandlesInComputeSystem")
-	procResizeConsoleInComputeSystem               = modvmcompute.NewProc("ResizeConsoleInComputeSystem")
-	procShutdownComputeSystem                      = modvmcompute.NewProc("ShutdownComputeSystem")
-	procStartComputeSystem                         = modvmcompute.NewProc("StartComputeSystem")
-	procTerminateComputeSystem                     = modvmcompute.NewProc("TerminateComputeSystem")
-	procTerminateProcessInComputeSystem            = modvmcompute.NewProc("TerminateProcessInComputeSystem")
-	procWaitForProcessInComputeSystem              = modvmcompute.NewProc("WaitForProcessInComputeSystem")
-	procGetComputeSystemProperties                 = modvmcompute.NewProc("GetComputeSystemProperties")
-	procHcsEnumerateComputeSystems                 = modvmcompute.NewProc("HcsEnumerateComputeSystems")
-	procHcsCreateComputeSystem                     = modvmcompute.NewProc("HcsCreateComputeSystem")
-	procHcsOpenComputeSystem                       = modvmcompute.NewProc("HcsOpenComputeSystem")
-	procHcsCloseComputeSystem                      = modvmcompute.NewProc("HcsCloseComputeSystem")
-	procHcsStartComputeSystem                      = modvmcompute.NewProc("HcsStartComputeSystem")
-	procHcsShutdownComputeSystem                   = modvmcompute.NewProc("HcsShutdownComputeSystem")
-	procHcsTerminateComputeSystem                  = modvmcompute.NewProc("HcsTerminateComputeSystem")
-	procHcsPauseComputeSystem                      = modvmcompute.NewProc("HcsPauseComputeSystem")
-	procHcsResumeComputeSystem                     = modvmcompute.NewProc("HcsResumeComputeSystem")
-	procHcsGetComputeSystemProperties              = modvmcompute.NewProc("HcsGetComputeSystemProperties")
-	procHcsModifyComputeSystem                     = modvmcompute.NewProc("HcsModifyComputeSystem")
-	procHcsCreateComputeSystemWait                 = modvmcompute.NewProc("HcsCreateComputeSystemWait")
-	procHcsCreateProcess                           = modvmcompute.NewProc("HcsCreateProcess")
-	procHcsOpenProcess                             = modvmcompute.NewProc("HcsOpenProcess")
-	procHcsCloseProcess                            = modvmcompute.NewProc("HcsCloseProcess")
-	procHcsTerminateProcess                        = modvmcompute.NewProc("HcsTerminateProcess")
-	procHcsGetProcessInfo                          = modvmcompute.NewProc("HcsGetProcessInfo")
-	procHcsGetProcessProperties                    = modvmcompute.NewProc("HcsGetProcessProperties")
-	procHcsModifyProcess                           = modvmcompute.NewProc("HcsModifyProcess")
-	procHcsCreateProcessWait                       = modvmcompute.NewProc("HcsCreateProcessWait")
-	procHcsGetServiceProperties                    = modvmcompute.NewProc("HcsGetServiceProperties")
-	procHcsModifyServiceSettings                   = modvmcompute.NewProc("HcsModifyServiceSettings")
-
+	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")
 )
 
@@ -599,196 +587,6 @@ func exportLayerEnd(context uintptr) (hr error) {
 	return
 }
 
-func createComputeSystem(id string, configuration string) (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 _createComputeSystem(_p0, _p1)
-}
-
-func _createComputeSystem(id *uint16, configuration *uint16) (hr error) {
-	if hr = procCreateComputeSystem.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall(procCreateComputeSystem.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(configuration)), 0)
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func createProcessWithStdHandlesInComputeSystem(id string, paramsJson string, pid *uint32, stdin *syscall.Handle, stdout *syscall.Handle, stderr *syscall.Handle) (hr error) {
-	var _p0 *uint16
-	_p0, hr = syscall.UTF16PtrFromString(id)
-	if hr != nil {
-		return
-	}
-	var _p1 *uint16
-	_p1, hr = syscall.UTF16PtrFromString(paramsJson)
-	if hr != nil {
-		return
-	}
-	return _createProcessWithStdHandlesInComputeSystem(_p0, _p1, pid, stdin, stdout, stderr)
-}
-
-func _createProcessWithStdHandlesInComputeSystem(id *uint16, paramsJson *uint16, pid *uint32, stdin *syscall.Handle, stdout *syscall.Handle, stderr *syscall.Handle) (hr error) {
-	if hr = procCreateProcessWithStdHandlesInComputeSystem.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall6(procCreateProcessWithStdHandlesInComputeSystem.Addr(), 6, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(paramsJson)), uintptr(unsafe.Pointer(pid)), uintptr(unsafe.Pointer(stdin)), uintptr(unsafe.Pointer(stdout)), uintptr(unsafe.Pointer(stderr)))
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func resizeConsoleInComputeSystem(id string, pid uint32, height uint16, width uint16, flags uint32) (hr error) {
-	var _p0 *uint16
-	_p0, hr = syscall.UTF16PtrFromString(id)
-	if hr != nil {
-		return
-	}
-	return _resizeConsoleInComputeSystem(_p0, pid, height, width, flags)
-}
-
-func _resizeConsoleInComputeSystem(id *uint16, pid uint32, height uint16, width uint16, flags uint32) (hr error) {
-	if hr = procResizeConsoleInComputeSystem.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall6(procResizeConsoleInComputeSystem.Addr(), 5, uintptr(unsafe.Pointer(id)), uintptr(pid), uintptr(height), uintptr(width), uintptr(flags), 0)
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func shutdownComputeSystem(id string, timeout uint32) (hr error) {
-	var _p0 *uint16
-	_p0, hr = syscall.UTF16PtrFromString(id)
-	if hr != nil {
-		return
-	}
-	return _shutdownComputeSystem(_p0, timeout)
-}
-
-func _shutdownComputeSystem(id *uint16, timeout uint32) (hr error) {
-	if hr = procShutdownComputeSystem.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall(procShutdownComputeSystem.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(timeout), 0)
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func startComputeSystem(id string) (hr error) {
-	var _p0 *uint16
-	_p0, hr = syscall.UTF16PtrFromString(id)
-	if hr != nil {
-		return
-	}
-	return _startComputeSystem(_p0)
-}
-
-func _startComputeSystem(id *uint16) (hr error) {
-	if hr = procStartComputeSystem.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall(procStartComputeSystem.Addr(), 1, uintptr(unsafe.Pointer(id)), 0, 0)
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func terminateComputeSystem(id string) (hr error) {
-	var _p0 *uint16
-	_p0, hr = syscall.UTF16PtrFromString(id)
-	if hr != nil {
-		return
-	}
-	return _terminateComputeSystem(_p0)
-}
-
-func _terminateComputeSystem(id *uint16) (hr error) {
-	if hr = procTerminateComputeSystem.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall(procTerminateComputeSystem.Addr(), 1, uintptr(unsafe.Pointer(id)), 0, 0)
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func terminateProcessInComputeSystem(id string, pid uint32) (hr error) {
-	var _p0 *uint16
-	_p0, hr = syscall.UTF16PtrFromString(id)
-	if hr != nil {
-		return
-	}
-	return _terminateProcessInComputeSystem(_p0, pid)
-}
-
-func _terminateProcessInComputeSystem(id *uint16, pid uint32) (hr error) {
-	if hr = procTerminateProcessInComputeSystem.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall(procTerminateProcessInComputeSystem.Addr(), 2, uintptr(unsafe.Pointer(id)), uintptr(pid), 0)
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func waitForProcessInComputeSystem(id string, pid uint32, timeout uint32, exitCode *uint32) (hr error) {
-	var _p0 *uint16
-	_p0, hr = syscall.UTF16PtrFromString(id)
-	if hr != nil {
-		return
-	}
-	return _waitForProcessInComputeSystem(_p0, pid, timeout, exitCode)
-}
-
-func _waitForProcessInComputeSystem(id *uint16, pid uint32, timeout uint32, exitCode *uint32) (hr error) {
-	if hr = procWaitForProcessInComputeSystem.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall6(procWaitForProcessInComputeSystem.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(pid), uintptr(timeout), uintptr(unsafe.Pointer(exitCode)), 0, 0)
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func getComputeSystemProperties(id string, flags uint32, properties **uint16) (hr error) {
-	var _p0 *uint16
-	_p0, hr = syscall.UTF16PtrFromString(id)
-	if hr != nil {
-		return
-	}
-	return _getComputeSystemProperties(_p0, flags, properties)
-}
-
-func _getComputeSystemProperties(id *uint16, flags uint32, properties **uint16) (hr error) {
-	if hr = procGetComputeSystemProperties.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall(procGetComputeSystemProperties.Addr(), 3, uintptr(unsafe.Pointer(id)), uintptr(flags), uintptr(unsafe.Pointer(properties)))
-	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)
@@ -1005,11 +803,22 @@ func _hcsModifyComputeSystem(computeSystem hcsSystem, configuration *uint16, res
 	return
 }
 
-func hcsCreateComputeSystemWait(computeSystem hcsSystem, exitEvent *syscall.Handle, result **uint16) (hr error) {
-	if hr = procHcsCreateComputeSystemWait.Find(); hr != nil {
+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(procHcsCreateComputeSystemWait.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(exitEvent)), uintptr(unsafe.Pointer(result)))
+	r0, _, _ := syscall.Syscall(procHcsUnregisterComputeSystemCallback.Addr(), 1, uintptr(callbackHandle), 0, 0)
 	if int32(r0) < 0 {
 		hr = syscall.Errno(win32FromHresult(r0))
 	}
@@ -1111,17 +920,6 @@ func _hcsModifyProcess(process hcsProcess, settings *uint16, result **uint16) (h
 	return
 }
 
-func hcsCreateProcessWait(process hcsProcess, settings *syscall.Handle, result **uint16) (hr error) {
-	if hr = procHcsCreateProcessWait.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall(procHcsCreateProcessWait.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)))
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
 func hcsGetServiceProperties(propertyQuery string, properties **uint16, result **uint16) (hr error) {
 	var _p0 *uint16
 	_p0, hr = syscall.UTF16PtrFromString(propertyQuery)
@@ -1142,144 +940,42 @@ func _hcsGetServiceProperties(propertyQuery *uint16, properties **uint16, result
 	return
 }
 
-func hcsModifyServiceSettings(settings string, result **uint16) (hr error) {
-	var _p0 *uint16
-	_p0, hr = syscall.UTF16PtrFromString(settings)
-	if hr != nil {
-		return
-	}
-	return _hcsModifyServiceSettings(_p0, result)
-}
-
-func _hcsModifyServiceSettings(settings *uint16, result **uint16) (hr error) {
-	if hr = procHcsModifyServiceSettings.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall(procHcsModifyServiceSettings.Addr(), 2, uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)), 0)
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func hcsCreateComputeSystemTP5(id string, configuration string, computeSystem *hcsSystem, result **uint16) (hr error) {
-	var _p0 *uint16
-	_p0, hr = syscall.UTF16PtrFromString(id)
-	if hr != nil {
-		return
-	}
-	var _p1 *uint16
-	_p1, hr = syscall.UTF16PtrFromString(configuration)
-	if hr != nil {
-		return
-	}
-	return _hcsCreateComputeSystemTP5(_p0, _p1, computeSystem, result)
-}
-
-func _hcsCreateComputeSystemTP5(id *uint16, configuration *uint16, computeSystem *hcsSystem, result **uint16) (hr error) {
-	if hr = procHcsCreateComputeSystem.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall6(procHcsCreateComputeSystem.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(configuration)), uintptr(unsafe.Pointer(computeSystem)), uintptr(unsafe.Pointer(result)), 0, 0)
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func hcsStartComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
-	if hr = procHcsStartComputeSystem.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall(procHcsStartComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func hcsShutdownComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
-	if hr = procHcsShutdownComputeSystem.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall(procHcsShutdownComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func hcsTerminateComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
-	if hr = procHcsTerminateComputeSystem.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall(procHcsTerminateComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func hcsPauseComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
-	if hr = procHcsPauseComputeSystem.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall(procHcsPauseComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func hcsResumeComputeSystemTP5(computeSystem hcsSystem, options *uint16, result **uint16) (hr error) {
-	if hr = procHcsResumeComputeSystem.Find(); hr != nil {
-		return
-	}
-	r0, _, _ := syscall.Syscall(procHcsResumeComputeSystem.Addr(), 3, uintptr(computeSystem), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
-	if int32(r0) < 0 {
-		hr = syscall.Errno(win32FromHresult(r0))
-	}
-	return
-}
-
-func hcsRegisterComputeSystemCallback(computeSystem hcsSystem, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) {
-	if hr = procHcsRegisterComputeSystemCallback.Find(); hr != nil {
+func hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) {
+	if hr = procHcsRegisterProcessCallback.Find(); hr != nil {
 		return
 	}
-	r0, _, _ := syscall.Syscall6(procHcsRegisterComputeSystemCallback.Addr(), 4, uintptr(computeSystem), uintptr(callback), uintptr(context), uintptr(unsafe.Pointer(callbackHandle)), 0, 0)
+	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 hcsUnregisterComputeSystemCallback(callbackHandle hcsCallback) (hr error) {
-	if hr = procHcsUnregisterComputeSystemCallback.Find(); hr != nil {
+func hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) {
+	if hr = procHcsUnregisterProcessCallback.Find(); hr != nil {
 		return
 	}
-	r0, _, _ := syscall.Syscall(procHcsUnregisterComputeSystemCallback.Addr(), 1, uintptr(callbackHandle), 0, 0)
+	r0, _, _ := syscall.Syscall(procHcsUnregisterProcessCallback.Addr(), 1, uintptr(callbackHandle), 0, 0)
 	if int32(r0) < 0 {
 		hr = syscall.Errno(win32FromHresult(r0))
 	}
 	return
 }
 
-func hcsRegisterProcessCallback(process hcsProcess, callback uintptr, context uintptr, callbackHandle *hcsCallback) (hr error) {
-	if hr = procHcsRegisterProcessCallback.Find(); hr != nil {
+func hcsModifyServiceSettings(settings string, result **uint16) (hr error) {
+	var _p0 *uint16
+	_p0, hr = syscall.UTF16PtrFromString(settings)
+	if 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
+	return _hcsModifyServiceSettings(_p0, result)
 }
 
-func hcsUnregisterProcessCallback(callbackHandle hcsCallback) (hr error) {
-	if hr = procHcsUnregisterProcessCallback.Find(); hr != nil {
+func _hcsModifyServiceSettings(settings *uint16, result **uint16) (hr error) {
+	if hr = procHcsModifyServiceSettings.Find(); hr != nil {
 		return
 	}
-	r0, _, _ := syscall.Syscall(procHcsUnregisterProcessCallback.Addr(), 1, uintptr(callbackHandle), 0, 0)
+	r0, _, _ := syscall.Syscall(procHcsModifyServiceSettings.Addr(), 2, uintptr(unsafe.Pointer(settings)), uintptr(unsafe.Pointer(result)), 0)
 	if int32(r0) < 0 {
 		hr = syscall.Errno(win32FromHresult(r0))
 	}

+ 20 - 4
libnetwork/default_gateway.go

@@ -2,13 +2,14 @@ package libnetwork
 
 import (
 	"fmt"
+	"strings"
 
+	"github.com/docker/libnetwork/netlabel"
 	"github.com/docker/libnetwork/types"
 )
 
 const (
-	libnGWNetwork = "docker_gwbridge"
-	gwEPlen       = 12
+	gwEPlen = 12
 )
 
 var procGwNetwork = make(chan (bool), 1)
@@ -52,6 +53,21 @@ func (sb *sandbox) setupDefaultGW() error {
 		eplen = len(sb.containerID)
 	}
 
+	sbLabels := sb.Labels()
+
+	if sbLabels[netlabel.PortMap] != nil {
+		createOptions = append(createOptions, CreateOptionPortMapping(sbLabels[netlabel.PortMap].([]types.PortBinding)))
+	}
+
+	if sbLabels[netlabel.ExposedPorts] != nil {
+		createOptions = append(createOptions, CreateOptionExposedPorts(sbLabels[netlabel.ExposedPorts].([]types.TransportPort)))
+	}
+
+	epOption := getPlatformOption()
+	if epOption != nil {
+		createOptions = append(createOptions, epOption)
+	}
+
 	newEp, err := n.CreateEndpoint("gateway_"+sb.containerID[0:eplen], createOptions...)
 	if err != nil {
 		return fmt.Errorf("container %s: endpoint create on GW Network failed: %v", sb.containerID, err)
@@ -119,7 +135,7 @@ func (sb *sandbox) needDefaultGW() bool {
 
 func (sb *sandbox) getEndpointInGWNetwork() *endpoint {
 	for _, ep := range sb.getConnectedEndpoints() {
-		if ep.getNetwork().name == libnGWNetwork {
+		if ep.getNetwork().name == libnGWNetwork && strings.HasPrefix(ep.Name(), "gateway_") {
 			return ep
 		}
 	}
@@ -127,7 +143,7 @@ func (sb *sandbox) getEndpointInGWNetwork() *endpoint {
 }
 
 func (ep *endpoint) endpointInGWNetwork() bool {
-	if ep.getNetwork().name == libnGWNetwork {
+	if ep.getNetwork().name == libnGWNetwork && strings.HasPrefix(ep.Name(), "gateway_") {
 		return true
 	}
 	return false

+ 6 - 0
libnetwork/default_gateway_freebsd.go

@@ -2,6 +2,12 @@ package libnetwork
 
 import "github.com/docker/libnetwork/types"
 
+const libnGWNetwork = "docker_gwbridge"
+
+func getPlatformOption() EndpointOption {
+	return nil
+}
+
 func (c *controller) createGWNetwork() (Network, error) {
 	return nil, types.NotImplementedErrorf("default gateway functionality is not implemented in freebsd")
 }

+ 6 - 0
libnetwork/default_gateway_linux.go

@@ -7,6 +7,12 @@ import (
 	"github.com/docker/libnetwork/drivers/bridge"
 )
 
+const libnGWNetwork = "docker_gwbridge"
+
+func getPlatformOption() EndpointOption {
+	return nil
+}
+
 func (c *controller) createGWNetwork() (Network, error) {
 	netOption := map[string]string{
 		bridge.BridgeName:         libnGWNetwork,

+ 6 - 0
libnetwork/default_gateway_solaris.go

@@ -7,6 +7,12 @@ import (
 	"github.com/docker/libnetwork/drivers/solaris/bridge"
 )
 
+const libnGWNetwork = "docker_gwbridge"
+
+func getPlatformOption() EndpointOption {
+	return nil
+}
+
 func (c *controller) createGWNetwork() (Network, error) {
 	netOption := map[string]string{
 		bridge.BridgeName:         libnGWNetwork,

+ 16 - 1
libnetwork/default_gateway_windows.go

@@ -1,6 +1,21 @@
 package libnetwork
 
-import "github.com/docker/libnetwork/types"
+import (
+	windriver "github.com/docker/libnetwork/drivers/windows"
+	"github.com/docker/libnetwork/options"
+	"github.com/docker/libnetwork/types"
+)
+
+const libnGWNetwork = "nat"
+
+func getPlatformOption() EndpointOption {
+
+	epOption := options.Generic{
+		windriver.DisableICC: true,
+		windriver.DisableDNS: true,
+	}
+	return EndpointOptionGeneric(epOption)
+}
 
 func (c *controller) createGWNetwork() (Network, error) {
 	return nil, types.NotImplementedErrorf("default gateway functionality is not implemented in windows")

+ 6 - 0
libnetwork/drivers/windows/labels.go

@@ -30,4 +30,10 @@ const (
 
 	// SourceMac of the network
 	SourceMac = "com.docker.network.windowsshim.sourcemac"
+
+	// DisableICC label
+	DisableICC = "com.docker.network.windowsshim.disableicc"
+
+	// DisableDNS label
+	DisableDNS = "com.docker.network.windowsshim.disable_dns"
 )

+ 0 - 2
libnetwork/drivers/windows/overlay/joinleave_windows.go

@@ -44,8 +44,6 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
 		logrus.Errorf("overlay: Failed adding table entry to joininfo: %v", err)
 	}
 
-	jinfo.DisableGatewayService()
-
 	d.pushLocalEndpointEvent("join", nid, eid)
 
 	return nil

+ 79 - 34
libnetwork/drivers/windows/windows.go

@@ -44,21 +44,28 @@ type networkConfiguration struct {
 }
 
 // endpointConfiguration represents the user specified configuration for the sandbox endpoint
-type endpointConfiguration struct {
-	MacAddress   net.HardwareAddr
+type endpointOption struct {
+	MacAddress  net.HardwareAddr
+	QosPolicies []types.QosPolicy
+	DNSServers  []string
+	DisableDNS  bool
+	DisableICC  bool
+}
+
+type endpointConnectivity struct {
 	PortBindings []types.PortBinding
 	ExposedPorts []types.TransportPort
-	QosPolicies  []types.QosPolicy
-	DNSServers   []string
 }
 
 type hnsEndpoint struct {
-	id          string
-	profileID   string
-	macAddress  net.HardwareAddr
-	config      *endpointConfiguration // User specified parameters
-	portMapping []types.PortBinding    // Operation port bindings
-	addr        *net.IPNet
+	id             string
+	profileID      string
+	macAddress     net.HardwareAddr
+	epOption       *endpointOption       // User specified parameters
+	epConnectivity *endpointConnectivity // User specified parameters
+	portMapping    []types.PortBinding   // Operation port bindings
+	addr           *net.IPNet
+	gateway        net.IP
 }
 
 type hnsNetwork struct {
@@ -391,12 +398,12 @@ func parsePortBindingPolicies(policies []json.RawMessage) ([]types.PortBinding,
 	return bindings, nil
 }
 
-func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfiguration, error) {
+func parseEndpointOptions(epOptions map[string]interface{}) (*endpointOption, error) {
 	if epOptions == nil {
 		return nil, nil
 	}
 
-	ec := &endpointConfiguration{}
+	ec := &endpointOption{}
 
 	if opt, ok := epOptions[netlabel.MacAddress]; ok {
 		if mac, ok := opt.(net.HardwareAddr); ok {
@@ -406,33 +413,33 @@ func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfigurat
 		}
 	}
 
-	if opt, ok := epOptions[netlabel.PortMap]; ok {
-		if bs, ok := opt.([]types.PortBinding); ok {
-			ec.PortBindings = bs
+	if opt, ok := epOptions[QosPolicies]; ok {
+		if policies, ok := opt.([]types.QosPolicy); ok {
+			ec.QosPolicies = policies
 		} else {
 			return nil, fmt.Errorf("Invalid endpoint configuration")
 		}
 	}
 
-	if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
-		if ports, ok := opt.([]types.TransportPort); ok {
-			ec.ExposedPorts = ports
+	if opt, ok := epOptions[netlabel.DNSServers]; ok {
+		if dns, ok := opt.([]string); ok {
+			ec.DNSServers = dns
 		} else {
 			return nil, fmt.Errorf("Invalid endpoint configuration")
 		}
 	}
 
-	if opt, ok := epOptions[QosPolicies]; ok {
-		if policies, ok := opt.([]types.QosPolicy); ok {
-			ec.QosPolicies = policies
+	if opt, ok := epOptions[DisableICC]; ok {
+		if disableICC, ok := opt.(bool); ok {
+			ec.DisableICC = disableICC
 		} else {
 			return nil, fmt.Errorf("Invalid endpoint configuration")
 		}
 	}
 
-	if opt, ok := epOptions[netlabel.DNSServers]; ok {
-		if dns, ok := opt.([]string); ok {
-			ec.DNSServers = dns
+	if opt, ok := epOptions[DisableDNS]; ok {
+		if disableDNS, ok := opt.(bool); ok {
+			ec.DisableDNS = disableDNS
 		} else {
 			return nil, fmt.Errorf("Invalid endpoint configuration")
 		}
@@ -441,6 +448,31 @@ func parseEndpointOptions(epOptions map[string]interface{}) (*endpointConfigurat
 	return ec, nil
 }
 
+func parseEndpointConnectivity(epOptions map[string]interface{}) (*endpointConnectivity, error) {
+	if epOptions == nil {
+		return nil, nil
+	}
+
+	ec := &endpointConnectivity{}
+
+	if opt, ok := epOptions[netlabel.PortMap]; ok {
+		if bs, ok := opt.([]types.PortBinding); ok {
+			ec.PortBindings = bs
+		} else {
+			return nil, fmt.Errorf("Invalid endpoint configuration")
+		}
+	}
+
+	if opt, ok := epOptions[netlabel.ExposedPorts]; ok {
+		if ports, ok := opt.([]types.TransportPort); ok {
+			ec.ExposedPorts = ports
+		} else {
+			return nil, fmt.Errorf("Invalid endpoint configuration")
+		}
+	}
+	return ec, nil
+}
+
 func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]interface{}) error {
 	n, err := d.getNetwork(nid)
 	if err != nil {
@@ -457,7 +489,8 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
 		VirtualNetwork: n.config.HnsID,
 	}
 
-	ec, err := parseEndpointOptions(epOptions)
+	epOption, err := parseEndpointOptions(epOptions)
+	epConnectivity, err := parseEndpointConnectivity(epOptions)
 
 	macAddress := ifInfo.MacAddress()
 	// Use the macaddress if it was provided
@@ -465,12 +498,12 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
 		endpointStruct.MacAddress = strings.Replace(macAddress.String(), ":", "-", -1)
 	}
 
-	endpointStruct.Policies, err = convertPortBindings(ec.PortBindings)
+	endpointStruct.Policies, err = convertPortBindings(epConnectivity.PortBindings)
 	if err != nil {
 		return err
 	}
 
-	qosPolicies, err := convertQosPolicies(ec.QosPolicies)
+	qosPolicies, err := convertQosPolicies(epOption.QosPolicies)
 	if err != nil {
 		return err
 	}
@@ -480,12 +513,14 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
 		endpointStruct.IPAddress = ifInfo.Address().IP
 	}
 
-	endpointStruct.DNSServerList = strings.Join(ec.DNSServers, ",")
+	endpointStruct.DNSServerList = strings.Join(epOption.DNSServers, ",")
 
-	if n.driver.name == "nat" {
+	if n.driver.name == "nat" && !epOption.DisableDNS {
 		endpointStruct.EnableInternalDNS = true
 	}
 
+	endpointStruct.DisableICC = epOption.DisableICC
+
 	configurationb, err := json.Marshal(endpointStruct)
 	if err != nil {
 		return err
@@ -508,8 +543,13 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
 		macAddress: mac,
 	}
 
+	if hnsresponse.GatewayAddress != "" {
+		endpoint.gateway = net.ParseIP(hnsresponse.GatewayAddress)
+	}
+
 	endpoint.profileID = hnsresponse.Id
-	endpoint.config = ec
+	endpoint.epConnectivity = epConnectivity
+	endpoint.epOption = epOption
 	endpoint.portMapping, err = parsePortBindingPolicies(hnsresponse.Policies)
 
 	if err != nil {
@@ -572,10 +612,10 @@ func (d *driver) EndpointOperInfo(nid, eid string) (map[string]interface{}, erro
 	}
 
 	data["hnsid"] = ep.profileID
-	if ep.config.ExposedPorts != nil {
+	if ep.epConnectivity.ExposedPorts != nil {
 		// Return a copy of the config data
-		epc := make([]types.TransportPort, 0, len(ep.config.ExposedPorts))
-		for _, tp := range ep.config.ExposedPorts {
+		epc := make([]types.TransportPort, 0, len(ep.epConnectivity.ExposedPorts))
+		for _, tp := range ep.epConnectivity.ExposedPorts {
 			epc = append(epc, tp.GetCopy())
 		}
 		data[netlabel.ExposedPorts] = epc
@@ -604,7 +644,12 @@ func (d *driver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo,
 	}
 
 	// Ensure that the endpoint exists
-	_, err = network.getEndpoint(eid)
+	endpoint, err := network.getEndpoint(eid)
+	if err != nil {
+		return err
+	}
+
+	err = jinfo.SetGateway(endpoint.gateway)
 	if err != nil {
 		return err
 	}

+ 0 - 25
libnetwork/endpoint_info.go

@@ -205,31 +205,6 @@ func (ep *endpoint) Info() EndpointInfo {
 	return nil
 }
 
-func (ep *endpoint) DriverInfo() (map[string]interface{}, error) {
-	ep, err := ep.retrieveFromStore()
-	if err != nil {
-		return nil, err
-	}
-
-	if sb, ok := ep.getSandbox(); ok {
-		if gwep := sb.getEndpointInGWNetwork(); gwep != nil && gwep.ID() != ep.ID() {
-			return gwep.DriverInfo()
-		}
-	}
-
-	n, err := ep.getNetworkFromStore()
-	if err != nil {
-		return nil, fmt.Errorf("could not find network in store for driver info: %v", err)
-	}
-
-	driver, err := n.driver(true)
-	if err != nil {
-		return nil, fmt.Errorf("failed to get driver info: %v", err)
-	}
-
-	return driver.EndpointOperInfo(n.ID(), ep.ID())
-}
-
 func (ep *endpoint) Iface() InterfaceInfo {
 	ep.Lock()
 	defer ep.Unlock()

+ 30 - 0
libnetwork/endpoint_info_unix.go

@@ -0,0 +1,30 @@
+// +build !windows
+
+package libnetwork
+
+import "fmt"
+
+func (ep *endpoint) DriverInfo() (map[string]interface{}, error) {
+	ep, err := ep.retrieveFromStore()
+	if err != nil {
+		return nil, err
+	}
+
+	if sb, ok := ep.getSandbox(); ok {
+		if gwep := sb.getEndpointInGWNetwork(); gwep != nil && gwep.ID() != ep.ID() {
+			return gwep.DriverInfo()
+		}
+	}
+
+	n, err := ep.getNetworkFromStore()
+	if err != nil {
+		return nil, fmt.Errorf("could not find network in store for driver info: %v", err)
+	}
+
+	driver, err := n.driver(true)
+	if err != nil {
+		return nil, fmt.Errorf("failed to get driver info: %v", err)
+	}
+
+	return driver.EndpointOperInfo(n.ID(), ep.ID())
+}

+ 45 - 0
libnetwork/endpoint_info_windows.go

@@ -0,0 +1,45 @@
+// +build windows
+
+package libnetwork
+
+import "fmt"
+
+func (ep *endpoint) DriverInfo() (map[string]interface{}, error) {
+	ep, err := ep.retrieveFromStore()
+	if err != nil {
+		return nil, err
+	}
+
+	var gwDriverInfo map[string]interface{}
+	if sb, ok := ep.getSandbox(); ok {
+		if gwep := sb.getEndpointInGWNetwork(); gwep != nil && gwep.ID() != ep.ID() {
+
+			gwDriverInfo, err = gwep.DriverInfo()
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	n, err := ep.getNetworkFromStore()
+	if err != nil {
+		return nil, fmt.Errorf("could not find network in store for driver info: %v", err)
+	}
+
+	driver, err := n.driver(true)
+	if err != nil {
+		return nil, fmt.Errorf("failed to get driver info: %v", err)
+	}
+
+	epInfo, err := driver.EndpointOperInfo(n.ID(), ep.ID())
+	if err != nil {
+		return nil, err
+	}
+
+	if epInfo != nil {
+		epInfo["GW_INFO"] = gwDriverInfo
+		return epInfo, nil
+	}
+
+	return gwDriverInfo, nil
+}