Browse code

Merge pull request #39108 from Microsoft/jjh/lcowrs5plus

LCOW: (Experimental) Require RS5+ builds

Brian Goff authored on 2019/04/19 13:10:25
Showing 12 changed files
... ...
@@ -3,6 +3,7 @@ package system // import "github.com/docker/docker/pkg/system"
3 3
 import (
4 4
 	"os"
5 5
 
6
+	"github.com/Microsoft/hcsshim/osversion"
6 7
 	"github.com/sirupsen/logrus"
7 8
 )
8 9
 
... ...
@@ -15,10 +16,10 @@ var (
15 15
 	containerdRuntimeSupported = false
16 16
 )
17 17
 
18
-// InitLCOW sets whether LCOW is supported or not
18
+// InitLCOW sets whether LCOW is supported or not. Requires RS5+
19 19
 func InitLCOW(experimental bool) {
20 20
 	v := GetOSVersion()
21
-	if experimental && v.Build >= 16299 {
21
+	if experimental && v.Build >= osversion.RS5 {
22 22
 		lcowSupported = true
23 23
 	}
24 24
 }
... ...
@@ -1,5 +1,5 @@
1 1
 github.com/Azure/go-ansiterm                        d6e3b3328b783f23731bc4d058875b0371ff8109
2
-github.com/Microsoft/hcsshim                        ba3d6667710fa905116f39a19d059c4c1016be7c
2
+github.com/Microsoft/hcsshim                        672e52e9209d1e53718c1b6a7d68cc9272654ab5
3 3
 github.com/Microsoft/go-winio                       c599b533b43b1363d7d7c6cfda5ede70ed73ff13
4 4
 github.com/docker/libtrust                          9cbd2a1374f46905c68a4eb3694a130610adc62a
5 5
 github.com/go-check/check                           4ed411733c5785b40214c70bce814c3a3a689609 https://github.com/cpuguy83/check.git
6 6
deleted file mode 100644
... ...
@@ -1,100 +0,0 @@
1
-package guestrequest
2
-
3
-import (
4
-	"github.com/Microsoft/hcsshim/internal/schema2"
5
-)
6
-
7
-// Arguably, many of these (at least CombinedLayers) should have been generated
8
-// by swagger.
9
-//
10
-// This will also change package name due to an inbound breaking change.
11
-
12
-// This class is used by a modify request to add or remove a combined layers
13
-// structure in the guest. For windows, the GCS applies a filter in ContainerRootPath
14
-// using the specified layers as the parent content. Ignores property ScratchPath
15
-// since the container path is already the scratch path. For linux, the GCS unions
16
-// the specified layers and ScratchPath together, placing the resulting union
17
-// filesystem at ContainerRootPath.
18
-type CombinedLayers struct {
19
-	ContainerRootPath string            `json:"ContainerRootPath,omitempty"`
20
-	Layers            []hcsschema.Layer `json:"Layers,omitempty"`
21
-	ScratchPath       string            `json:"ScratchPath,omitempty"`
22
-}
23
-
24
-// Defines the schema for hosted settings passed to GCS and/or OpenGCS
25
-
26
-// SCSI. Scratch space for remote file-system commands, or R/W layer for containers
27
-type LCOWMappedVirtualDisk struct {
28
-	MountPath  string `json:"MountPath,omitempty"` // /tmp/scratch for an LCOW utility VM being used as a service VM
29
-	Lun        uint8  `json:"Lun,omitempty"`
30
-	Controller uint8  `json:"Controller,omitempty"`
31
-	ReadOnly   bool   `json:"ReadOnly,omitempty"`
32
-}
33
-
34
-type WCOWMappedVirtualDisk struct {
35
-	ContainerPath string `json:"ContainerPath,omitempty"`
36
-	Lun           int32  `json:"Lun,omitempty"`
37
-}
38
-
39
-type LCOWMappedDirectory struct {
40
-	MountPath string `json:"MountPath,omitempty"`
41
-	Port      int32  `json:"Port,omitempty"`
42
-	ShareName string `json:"ShareName,omitempty"` // If empty not using ANames (not currently supported)
43
-	ReadOnly  bool   `json:"ReadOnly,omitempty"`
44
-}
45
-
46
-// Read-only layers over VPMem
47
-type LCOWMappedVPMemDevice struct {
48
-	DeviceNumber uint32 `json:"DeviceNumber,omitempty"`
49
-	MountPath    string `json:"MountPath,omitempty"` // /tmp/pN
50
-}
51
-
52
-type LCOWNetworkAdapter struct {
53
-	NamespaceID     string `json:",omitempty"`
54
-	ID              string `json:",omitempty"`
55
-	MacAddress      string `json:",omitempty"`
56
-	IPAddress       string `json:",omitempty"`
57
-	PrefixLength    uint8  `json:",omitempty"`
58
-	GatewayAddress  string `json:",omitempty"`
59
-	DNSSuffix       string `json:",omitempty"`
60
-	DNSServerList   string `json:",omitempty"`
61
-	EnableLowMetric bool   `json:",omitempty"`
62
-	EncapOverhead   uint16 `json:",omitempty"`
63
-}
64
-
65
-type ResourceType string
66
-
67
-const (
68
-	// These are constants for v2 schema modify guest requests.
69
-	ResourceTypeMappedDirectory   ResourceType = "MappedDirectory"
70
-	ResourceTypeMappedVirtualDisk ResourceType = "MappedVirtualDisk"
71
-	ResourceTypeNetwork           ResourceType = "Network"
72
-	ResourceTypeNetworkNamespace  ResourceType = "NetworkNamespace"
73
-	ResourceTypeCombinedLayers    ResourceType = "CombinedLayers"
74
-	ResourceTypeVPMemDevice       ResourceType = "VPMemDevice"
75
-)
76
-
77
-// GuestRequest is for modify commands passed to the guest.
78
-type GuestRequest struct {
79
-	RequestType  string       `json:"RequestType,omitempty"`
80
-	ResourceType ResourceType `json:"ResourceType,omitempty"`
81
-	Settings     interface{}  `json:"Settings,omitempty"`
82
-}
83
-
84
-type NetworkModifyRequest struct {
85
-	AdapterId   string      `json:"AdapterId,omitempty"`
86
-	RequestType string      `json:"RequestType,omitempty"`
87
-	Settings    interface{} `json:"Settings,omitempty"`
88
-}
89
-
90
-type RS4NetworkModifyRequest struct {
91
-	AdapterInstanceId string      `json:"AdapterInstanceId,omitempty"`
92
-	RequestType       string      `json:"RequestType,omitempty"`
93
-	Settings          interface{} `json:"Settings,omitempty"`
94
-}
95
-
96
-// SignalProcessOptions is the options passed to either WCOW or LCOW
97
-// to signal a given process.
98
-type SignalProcessOptions struct {
99
-	Signal int `json:,omitempty`
100
-}
... ...
@@ -1,10 +1,12 @@
1 1
 package hcs
2 2
 
3 3
 import (
4
+	"fmt"
4 5
 	"sync"
5 6
 	"syscall"
6 7
 
7 8
 	"github.com/Microsoft/hcsshim/internal/interop"
9
+	"github.com/Microsoft/hcsshim/internal/logfields"
8 10
 	"github.com/sirupsen/logrus"
9 11
 )
10 12
 
... ...
@@ -40,16 +42,61 @@ var (
40 40
 )
41 41
 
42 42
 type hcsNotification uint32
43
+
44
+func (hn hcsNotification) String() string {
45
+	switch hn {
46
+	case hcsNotificationSystemExited:
47
+		return "SystemExited"
48
+	case hcsNotificationSystemCreateCompleted:
49
+		return "SystemCreateCompleted"
50
+	case hcsNotificationSystemStartCompleted:
51
+		return "SystemStartCompleted"
52
+	case hcsNotificationSystemPauseCompleted:
53
+		return "SystemPauseCompleted"
54
+	case hcsNotificationSystemResumeCompleted:
55
+		return "SystemResumeCompleted"
56
+	case hcsNotificationSystemCrashReport:
57
+		return "SystemCrashReport"
58
+	case hcsNotificationSystemSiloJobCreated:
59
+		return "SystemSiloJobCreated"
60
+	case hcsNotificationSystemSaveCompleted:
61
+		return "SystemSaveCompleted"
62
+	case hcsNotificationSystemRdpEnhancedModeStateChanged:
63
+		return "SystemRdpEnhancedModeStateChanged"
64
+	case hcsNotificationSystemShutdownFailed:
65
+		return "SystemShutdownFailed"
66
+	case hcsNotificationSystemGetPropertiesCompleted:
67
+		return "SystemGetPropertiesCompleted"
68
+	case hcsNotificationSystemModifyCompleted:
69
+		return "SystemModifyCompleted"
70
+	case hcsNotificationSystemCrashInitiated:
71
+		return "SystemCrashInitiated"
72
+	case hcsNotificationSystemGuestConnectionClosed:
73
+		return "SystemGuestConnectionClosed"
74
+	case hcsNotificationProcessExited:
75
+		return "ProcessExited"
76
+	case hcsNotificationInvalid:
77
+		return "Invalid"
78
+	case hcsNotificationServiceDisconnect:
79
+		return "ServiceDisconnect"
80
+	default:
81
+		return fmt.Sprintf("Unknown: %d", hn)
82
+	}
83
+}
84
+
43 85
 type notificationChannel chan error
44 86
 
45 87
 type notifcationWatcherContext struct {
46 88
 	channels notificationChannels
47 89
 	handle   hcsCallback
90
+
91
+	systemID  string
92
+	processID int
48 93
 }
49 94
 
50 95
 type notificationChannels map[hcsNotification]notificationChannel
51 96
 
52
-func newChannels() notificationChannels {
97
+func newSystemChannels() notificationChannels {
53 98
 	channels := make(notificationChannels)
54 99
 
55 100
 	channels[hcsNotificationSystemExited] = make(notificationChannel, 1)
... ...
@@ -57,17 +104,14 @@ func newChannels() notificationChannels {
57 57
 	channels[hcsNotificationSystemStartCompleted] = make(notificationChannel, 1)
58 58
 	channels[hcsNotificationSystemPauseCompleted] = make(notificationChannel, 1)
59 59
 	channels[hcsNotificationSystemResumeCompleted] = make(notificationChannel, 1)
60
+
61
+	return channels
62
+}
63
+
64
+func newProcessChannels() notificationChannels {
65
+	channels := make(notificationChannels)
66
+
60 67
 	channels[hcsNotificationProcessExited] = make(notificationChannel, 1)
61
-	channels[hcsNotificationServiceDisconnect] = make(notificationChannel, 1)
62
-	channels[hcsNotificationSystemCrashReport] = make(notificationChannel, 1)
63
-	channels[hcsNotificationSystemSiloJobCreated] = make(notificationChannel, 1)
64
-	channels[hcsNotificationSystemSaveCompleted] = make(notificationChannel, 1)
65
-	channels[hcsNotificationSystemRdpEnhancedModeStateChanged] = make(notificationChannel, 1)
66
-	channels[hcsNotificationSystemShutdownFailed] = make(notificationChannel, 1)
67
-	channels[hcsNotificationSystemGetPropertiesCompleted] = make(notificationChannel, 1)
68
-	channels[hcsNotificationSystemModifyCompleted] = make(notificationChannel, 1)
69
-	channels[hcsNotificationSystemCrashInitiated] = make(notificationChannel, 1)
70
-	channels[hcsNotificationSystemGuestConnectionClosed] = make(notificationChannel, 1)
71 68
 
72 69
 	return channels
73 70
 }
... ...
@@ -92,12 +136,28 @@ func notificationWatcher(notificationType hcsNotification, callbackNumber uintpt
92 92
 		return 0
93 93
 	}
94 94
 
95
+	log := logrus.WithFields(logrus.Fields{
96
+		"notification-type": notificationType.String(),
97
+		"system-id":         context.systemID,
98
+	})
99
+	if context.processID != 0 {
100
+		log.Data[logfields.ProcessID] = context.processID
101
+	}
102
+	log.Debug("")
103
+
104
+	// The HCS notification system can grow overtime. We explicitly opt-in to
105
+	// the notifications we would like to handle, all others we simply return.
106
+	// This means that as it grows we don't have issues associated with new
107
+	// notification types the code didn't know about.
108
+	switch notificationType {
109
+	case hcsNotificationSystemExited, hcsNotificationSystemCreateCompleted, hcsNotificationSystemStartCompleted, hcsNotificationSystemPauseCompleted, hcsNotificationSystemResumeCompleted:
110
+	case hcsNotificationProcessExited:
111
+	default:
112
+		return 0
113
+	}
114
+
95 115
 	if channel, ok := context.channels[notificationType]; ok {
96 116
 		channel <- result
97
-	} else {
98
-		logrus.WithFields(logrus.Fields{
99
-			"notification-type": notificationType,
100
-		}).Warn("Received a callback of an unsupported type")
101 117
 	}
102 118
 
103 119
 	return 0
... ...
@@ -272,6 +272,13 @@ func IsNotSupported(err error) bool {
272 272
 		err == ErrVmcomputeUnknownMessage
273 273
 }
274 274
 
275
+// IsOperationInvalidState returns true when err is caused by
276
+// `ErrVmcomputeOperationInvalidState`.
277
+func IsOperationInvalidState(err error) bool {
278
+	err = getInnerError(err)
279
+	return err == ErrVmcomputeOperationInvalidState
280
+}
281
+
275 282
 func getInnerError(err error) error {
276 283
 	switch pe := err.(type) {
277 284
 	case nil:
... ...
@@ -27,7 +27,7 @@ import (
27 27
 //sys hcsOpenProcess(computeSystem hcsSystem, pid uint32, process *hcsProcess, result **uint16) (hr error) = vmcompute.HcsOpenProcess?
28 28
 //sys hcsCloseProcess(process hcsProcess) (hr error) = vmcompute.HcsCloseProcess?
29 29
 //sys hcsTerminateProcess(process hcsProcess, result **uint16) (hr error) = vmcompute.HcsTerminateProcess?
30
-//sys hcsSignalProcess(process hcsProcess, options string, result **uint16) (hr error) = vmcompute.HcsTerminateProcess?
30
+//sys hcsSignalProcess(process hcsProcess, options string, result **uint16) (hr error) = vmcompute.HcsSignalProcess?
31 31
 //sys hcsGetProcessInfo(process hcsProcess, processInformation *hcsProcessInformation, result **uint16) (hr error) = vmcompute.HcsGetProcessInfo?
32 32
 //sys hcsGetProcessProperties(process hcsProcess, processProperties **uint16, result **uint16) (hr error) = vmcompute.HcsGetProcessProperties?
33 33
 //sys hcsModifyProcess(process hcsProcess, settings string, result **uint16) (hr error) = vmcompute.HcsModifyProcess?
... ...
@@ -7,7 +7,6 @@ import (
7 7
 	"syscall"
8 8
 	"time"
9 9
 
10
-	"github.com/Microsoft/hcsshim/internal/guestrequest"
11 10
 	"github.com/Microsoft/hcsshim/internal/interop"
12 11
 	"github.com/Microsoft/hcsshim/internal/logfields"
13 12
 	"github.com/sirupsen/logrus"
... ...
@@ -112,7 +111,11 @@ func (process *Process) logOperationEnd(operation string, err error) {
112 112
 }
113 113
 
114 114
 // Signal signals the process with `options`.
115
-func (process *Process) Signal(options guestrequest.SignalProcessOptions) (err error) {
115
+//
116
+// For LCOW `guestrequest.SignalProcessOptionsLCOW`.
117
+//
118
+// For WCOW `guestrequest.SignalProcessOptionsWCOW`.
119
+func (process *Process) Signal(options interface{}) (err error) {
116 120
 	process.handleLock.RLock()
117 121
 	defer process.handleLock.RUnlock()
118 122
 
... ...
@@ -189,7 +192,7 @@ func (process *Process) Wait() (err error) {
189 189
 
190 190
 	<-process.waitBlock
191 191
 	if process.waitError != nil {
192
-		return makeProcessError(process, operation, err, nil)
192
+		return makeProcessError(process, operation, process.waitError, nil)
193 193
 	}
194 194
 	return nil
195 195
 }
... ...
@@ -432,7 +435,9 @@ func (process *Process) Close() (err error) {
432 432
 
433 433
 func (process *Process) registerCallback() error {
434 434
 	context := &notifcationWatcherContext{
435
-		channels: newChannels(),
435
+		channels:  newProcessChannels(),
436
+		systemID:  process.SystemID(),
437
+		processID: process.processID,
436 438
 	}
437 439
 
438 440
 	callbackMapLock.Lock()
... ...
@@ -414,18 +414,19 @@ func (computeSystem *System) Properties(types ...schema1.PropertyType) (_ *schem
414 414
 	computeSystem.logOperationBegin(operation)
415 415
 	defer func() { computeSystem.logOperationEnd(operation, err) }()
416 416
 
417
-	queryj, err := json.Marshal(schema1.PropertyQuery{types})
417
+	queryBytes, err := json.Marshal(schema1.PropertyQuery{PropertyTypes: types})
418 418
 	if err != nil {
419 419
 		return nil, makeSystemError(computeSystem, "Properties", "", err, nil)
420 420
 	}
421 421
 
422
+	queryString := string(queryBytes)
422 423
 	logrus.WithFields(computeSystem.logctx).
423
-		WithField(logfields.JSON, queryj).
424
+		WithField(logfields.JSON, queryString).
424 425
 		Debug("HCS ComputeSystem Properties Query")
425 426
 
426 427
 	var resultp, propertiesp *uint16
427 428
 	syscallWatcher(computeSystem.logctx, func() {
428
-		err = hcsGetComputeSystemProperties(computeSystem.handle, string(queryj), &propertiesp, &resultp)
429
+		err = hcsGetComputeSystemProperties(computeSystem.handle, string(queryString), &propertiesp, &resultp)
429 430
 	})
430 431
 	events := processHcsResult(resultp)
431 432
 	if err != nil {
... ...
@@ -625,7 +626,8 @@ func (computeSystem *System) Close() (err error) {
625 625
 
626 626
 func (computeSystem *System) registerCallback() error {
627 627
 	context := &notifcationWatcherContext{
628
-		channels: newChannels(),
628
+		channels: newSystemChannels(),
629
+		systemID: computeSystem.id,
629 630
 	}
630 631
 
631 632
 	callbackMapLock.Lock()
... ...
@@ -56,13 +56,13 @@ var (
56 56
 	procHcsOpenProcess                     = modvmcompute.NewProc("HcsOpenProcess")
57 57
 	procHcsCloseProcess                    = modvmcompute.NewProc("HcsCloseProcess")
58 58
 	procHcsTerminateProcess                = modvmcompute.NewProc("HcsTerminateProcess")
59
-
60
-	procHcsGetProcessInfo            = modvmcompute.NewProc("HcsGetProcessInfo")
61
-	procHcsGetProcessProperties      = modvmcompute.NewProc("HcsGetProcessProperties")
62
-	procHcsModifyProcess             = modvmcompute.NewProc("HcsModifyProcess")
63
-	procHcsGetServiceProperties      = modvmcompute.NewProc("HcsGetServiceProperties")
64
-	procHcsRegisterProcessCallback   = modvmcompute.NewProc("HcsRegisterProcessCallback")
65
-	procHcsUnregisterProcessCallback = modvmcompute.NewProc("HcsUnregisterProcessCallback")
59
+	procHcsSignalProcess                   = modvmcompute.NewProc("HcsSignalProcess")
60
+	procHcsGetProcessInfo                  = modvmcompute.NewProc("HcsGetProcessInfo")
61
+	procHcsGetProcessProperties            = modvmcompute.NewProc("HcsGetProcessProperties")
62
+	procHcsModifyProcess                   = modvmcompute.NewProc("HcsModifyProcess")
63
+	procHcsGetServiceProperties            = modvmcompute.NewProc("HcsGetServiceProperties")
64
+	procHcsRegisterProcessCallback         = modvmcompute.NewProc("HcsRegisterProcessCallback")
65
+	procHcsUnregisterProcessCallback       = modvmcompute.NewProc("HcsUnregisterProcessCallback")
66 66
 )
67 67
 
68 68
 func hcsEnumerateComputeSystems(query string, computeSystems **uint16, result **uint16) (hr error) {
... ...
@@ -417,10 +417,10 @@ func hcsSignalProcess(process hcsProcess, options string, result **uint16) (hr e
417 417
 }
418 418
 
419 419
 func _hcsSignalProcess(process hcsProcess, options *uint16, result **uint16) (hr error) {
420
-	if hr = procHcsTerminateProcess.Find(); hr != nil {
420
+	if hr = procHcsSignalProcess.Find(); hr != nil {
421 421
 		return
422 422
 	}
423
-	r0, _, _ := syscall.Syscall(procHcsTerminateProcess.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
423
+	r0, _, _ := syscall.Syscall(procHcsSignalProcess.Addr(), 3, uintptr(process), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(result)))
424 424
 	if int32(r0) < 0 {
425 425
 		if r0&0x1fff0000 == 0x00070000 {
426 426
 			r0 &= 0xffff
427 427
new file mode 100644
... ...
@@ -0,0 +1,51 @@
0
+package osversion
1
+
2
+import (
3
+	"fmt"
4
+
5
+	"golang.org/x/sys/windows"
6
+)
7
+
8
+// OSVersion is a wrapper for Windows version information
9
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
10
+type OSVersion struct {
11
+	Version      uint32
12
+	MajorVersion uint8
13
+	MinorVersion uint8
14
+	Build        uint16
15
+}
16
+
17
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
18
+type osVersionInfoEx struct {
19
+	OSVersionInfoSize uint32
20
+	MajorVersion      uint32
21
+	MinorVersion      uint32
22
+	BuildNumber       uint32
23
+	PlatformID        uint32
24
+	CSDVersion        [128]uint16
25
+	ServicePackMajor  uint16
26
+	ServicePackMinor  uint16
27
+	SuiteMask         uint16
28
+	ProductType       byte
29
+	Reserve           byte
30
+}
31
+
32
+// Get gets the operating system version on Windows.
33
+// The calling application must be manifested to get the correct version information.
34
+func Get() OSVersion {
35
+	var err error
36
+	osv := OSVersion{}
37
+	osv.Version, err = windows.GetVersion()
38
+	if err != nil {
39
+		// GetVersion never fails.
40
+		panic(err)
41
+	}
42
+	osv.MajorVersion = uint8(osv.Version & 0xFF)
43
+	osv.MinorVersion = uint8(osv.Version >> 8 & 0xFF)
44
+	osv.Build = uint16(osv.Version >> 16)
45
+	return osv
46
+}
47
+
48
+func (osv OSVersion) ToString() string {
49
+	return fmt.Sprintf("%d.%d.%d", osv.MajorVersion, osv.MinorVersion, osv.Build)
50
+}
0 51
new file mode 100644
... ...
@@ -0,0 +1,23 @@
0
+package osversion
1
+
2
+const (
3
+	// RS1 (version 1607, codename "Redstone 1") corresponds to Windows Server
4
+	// 2016 (ltsc2016) and Windows 10 (Anniversary Update).
5
+	RS1 = 14393
6
+
7
+	// RS2 (version 1703, codename "Redstone 2") was a client-only update, and
8
+	// corresponds to Windows 10 (Creators Update).
9
+	RS2 = 15063
10
+
11
+	// RS3 (version 1709, codename "Redstone 3") corresponds to Windows Server
12
+	// 1709 (Semi-Annual Channel (SAC)), and Windows 10 (Fall Creators Update).
13
+	RS3 = 16299
14
+
15
+	// RS4 (version 1803, codename "Redstone 4") corresponds to Windows Server
16
+	// 1809 (Semi-Annual Channel (SAC)), and Windows 10 (April 2018 Update).
17
+	RS4 = 17134
18
+
19
+	// RS5 (version 1809, codename "Redstone 5") corresponds to Windows Server
20
+	// 2019 (ltsc2019), and Windows 10 (October 2018 Update).
21
+	RS5 = 17763
22
+)
... ...
@@ -10,7 +10,7 @@ github.com/hashicorp/errwrap 7554cd9344cec97297fa6649b055a8c98c2a1e55
10 10
 github.com/hashicorp/go-multierror ed905158d87462226a13fe39ddf685ea65f1c11f
11 11
 github.com/konsorten/go-windows-terminal-sequences v1.0.1
12 12
 github.com/linuxkit/virtsock 8e79449dea0735c1c056d814934dd035734cc97c
13
-github.com/Microsoft/go-winio c599b533b43b1363d7d7c6cfda5ede70ed73ff13
13
+github.com/Microsoft/go-winio 84b4ab48a50763fe7b3abcef38e5205c12027fac
14 14
 github.com/Microsoft/opengcs v0.3.9
15 15
 github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
16 16
 github.com/opencontainers/runc 12f6a991201fdb8f82579582d5e00e28fba06d0a