Browse code

Revendor Microsoft/HCSShim v0.5.7

Signed-off-by: John Howard <jhoward@microsoft.com>

John Howard authored on 2016/11/09 04:36:07
Showing 7 changed files
... ...
@@ -1,6 +1,6 @@
1 1
 # the following lines are in sorted order, FYI
2 2
 github.com/Azure/go-ansiterm 388960b655244e76e24c75f48631564eaefade62
3
-github.com/Microsoft/hcsshim v0.5.2
3
+github.com/Microsoft/hcsshim v0.5.7
4 4
 github.com/Microsoft/go-winio v0.3.5
5 5
 github.com/Sirupsen/logrus f76d643702a30fbffecdfe50831e11881c96ceb3 https://github.com/aaronlehmann/logrus
6 6
 github.com/davecgh/go-spew 6d212800a42e8ab5c146b8ace3490ee17e5225f9
... ...
@@ -27,7 +27,8 @@ type container struct {
27 27
 	callbackNumber uintptr
28 28
 }
29 29
 
30
-type containerProperties struct {
30
+// ContainerProperties holds the properties for a container and the processes running in that container
31
+type ContainerProperties struct {
31 32
 	ID                string `json:"Id"`
32 33
 	Name              string
33 34
 	SystemType        string
... ...
@@ -35,6 +36,8 @@ type containerProperties struct {
35 35
 	SiloGUID          string            `json:"SiloGuid,omitempty"`
36 36
 	IsDummy           bool              `json:",omitempty"`
37 37
 	RuntimeID         string            `json:"RuntimeId,omitempty"`
38
+	IsRuntimeTemplate bool              `json:",omitempty"`
39
+	RuntimeImagePath  string            `json:",omitempty"`
38 40
 	Stopped           bool              `json:",omitempty"`
39 41
 	ExitType          string            `json:",omitempty"`
40 42
 	AreUpdatesPending bool              `json:",omitempty"`
... ...
@@ -161,11 +164,47 @@ func OpenContainer(id string) (Container, error) {
161 161
 
162 162
 	container.handle = handle
163 163
 
164
+	if err := container.registerCallback(); err != nil {
165
+		return nil, makeContainerError(container, operation, "", err)
166
+	}
167
+
164 168
 	logrus.Debugf(title+" succeeded id=%s handle=%d", id, handle)
165 169
 	runtime.SetFinalizer(container, closeContainer)
166 170
 	return container, nil
167 171
 }
168 172
 
173
+// GetContainers gets a list of the containers on the system that match the query
174
+func GetContainers(q ComputeSystemQuery) ([]ContainerProperties, error) {
175
+	operation := "GetContainers"
176
+	title := "HCSShim::" + operation
177
+
178
+	queryb, err := json.Marshal(q)
179
+	if err != nil {
180
+		return nil, err
181
+	}
182
+
183
+	query := string(queryb)
184
+	logrus.Debugf(title+" query=%s", query)
185
+
186
+	var (
187
+		resultp         *uint16
188
+		computeSystemsp *uint16
189
+	)
190
+	err = hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp)
191
+	err = processHcsResult(err, resultp)
192
+	if computeSystemsp == nil {
193
+		return nil, ErrUnexpectedValue
194
+	}
195
+	computeSystemsRaw := convertAndFreeCoTaskMemBytes(computeSystemsp)
196
+	computeSystems := []ContainerProperties{}
197
+	if err := json.Unmarshal(computeSystemsRaw, &computeSystems); err != nil {
198
+		return nil, err
199
+	}
200
+
201
+	logrus.Debugf(title + " succeeded")
202
+	return computeSystems, nil
203
+}
204
+
169 205
 // Start synchronously starts the container.
170 206
 func (container *container) Start() error {
171 207
 	container.handleLock.RLock()
... ...
@@ -175,7 +214,7 @@ func (container *container) Start() error {
175 175
 	logrus.Debugf(title+" id=%s", container.id)
176 176
 
177 177
 	if container.handle == 0 {
178
-		return makeContainerError(container, operation, "", ErrInvalidHandle)
178
+		return makeContainerError(container, operation, "", ErrAlreadyClosed)
179 179
 	}
180 180
 
181 181
 	var resultp *uint16
... ...
@@ -199,7 +238,7 @@ func (container *container) Shutdown() error {
199 199
 	logrus.Debugf(title+" id=%s", container.id)
200 200
 
201 201
 	if container.handle == 0 {
202
-		return makeContainerError(container, operation, "", ErrInvalidHandle)
202
+		return makeContainerError(container, operation, "", ErrAlreadyClosed)
203 203
 	}
204 204
 
205 205
 	var resultp *uint16
... ...
@@ -223,7 +262,7 @@ func (container *container) Terminate() error {
223 223
 	logrus.Debugf(title+" id=%s", container.id)
224 224
 
225 225
 	if container.handle == 0 {
226
-		return makeContainerError(container, operation, "", ErrInvalidHandle)
226
+		return makeContainerError(container, operation, "", ErrAlreadyClosed)
227 227
 	}
228 228
 
229 229
 	var resultp *uint16
... ...
@@ -268,7 +307,7 @@ func (container *container) WaitTimeout(timeout time.Duration) error {
268 268
 	return nil
269 269
 }
270 270
 
271
-func (container *container) properties(query string) (*containerProperties, error) {
271
+func (container *container) properties(query string) (*ContainerProperties, error) {
272 272
 	var (
273 273
 		resultp     *uint16
274 274
 		propertiesp *uint16
... ...
@@ -283,7 +322,7 @@ func (container *container) properties(query string) (*containerProperties, erro
283 283
 		return nil, ErrUnexpectedValue
284 284
 	}
285 285
 	propertiesRaw := convertAndFreeCoTaskMemBytes(propertiesp)
286
-	properties := &containerProperties{}
286
+	properties := &ContainerProperties{}
287 287
 	if err := json.Unmarshal(propertiesRaw, properties); err != nil {
288 288
 		return nil, err
289 289
 	}
... ...
@@ -299,7 +338,7 @@ func (container *container) HasPendingUpdates() (bool, error) {
299 299
 	logrus.Debugf(title+" id=%s", container.id)
300 300
 
301 301
 	if container.handle == 0 {
302
-		return false, makeContainerError(container, operation, "", ErrInvalidHandle)
302
+		return false, makeContainerError(container, operation, "", ErrAlreadyClosed)
303 303
 	}
304 304
 
305 305
 	properties, err := container.properties(pendingUpdatesQuery)
... ...
@@ -320,7 +359,7 @@ func (container *container) Statistics() (Statistics, error) {
320 320
 	logrus.Debugf(title+" id=%s", container.id)
321 321
 
322 322
 	if container.handle == 0 {
323
-		return Statistics{}, makeContainerError(container, operation, "", ErrInvalidHandle)
323
+		return Statistics{}, makeContainerError(container, operation, "", ErrAlreadyClosed)
324 324
 	}
325 325
 
326 326
 	properties, err := container.properties(statisticsQuery)
... ...
@@ -341,7 +380,7 @@ func (container *container) ProcessList() ([]ProcessListItem, error) {
341 341
 	logrus.Debugf(title+" id=%s", container.id)
342 342
 
343 343
 	if container.handle == 0 {
344
-		return nil, makeContainerError(container, operation, "", ErrInvalidHandle)
344
+		return nil, makeContainerError(container, operation, "", ErrAlreadyClosed)
345 345
 	}
346 346
 
347 347
 	properties, err := container.properties(processListQuery)
... ...
@@ -362,7 +401,7 @@ func (container *container) Pause() error {
362 362
 	logrus.Debugf(title+" id=%s", container.id)
363 363
 
364 364
 	if container.handle == 0 {
365
-		return makeContainerError(container, operation, "", ErrInvalidHandle)
365
+		return makeContainerError(container, operation, "", ErrAlreadyClosed)
366 366
 	}
367 367
 
368 368
 	var resultp *uint16
... ...
@@ -385,7 +424,7 @@ func (container *container) Resume() error {
385 385
 	logrus.Debugf(title+" id=%s", container.id)
386 386
 
387 387
 	if container.handle == 0 {
388
-		return makeContainerError(container, operation, "", ErrInvalidHandle)
388
+		return makeContainerError(container, operation, "", ErrAlreadyClosed)
389 389
 	}
390 390
 
391 391
 	var resultp *uint16
... ...
@@ -412,7 +451,7 @@ func (container *container) CreateProcess(c *ProcessConfig) (Process, error) {
412 412
 	)
413 413
 
414 414
 	if container.handle == 0 {
415
-		return nil, makeContainerError(container, operation, "", ErrInvalidHandle)
415
+		return nil, makeContainerError(container, operation, "", ErrAlreadyClosed)
416 416
 	}
417 417
 
418 418
 	// If we are not emulating a console, ignore any console size passed to us
... ...
@@ -468,7 +507,7 @@ func (container *container) OpenProcess(pid int) (Process, error) {
468 468
 	)
469 469
 
470 470
 	if container.handle == 0 {
471
-		return nil, makeContainerError(container, operation, "", ErrInvalidHandle)
471
+		return nil, makeContainerError(container, operation, "", ErrAlreadyClosed)
472 472
 	}
473 473
 
474 474
 	err := hcsOpenProcess(container.handle, uint32(pid), &processHandle, &resultp)
... ...
@@ -514,6 +553,7 @@ func (container *container) Close() error {
514 514
 	}
515 515
 
516 516
 	container.handle = 0
517
+	runtime.SetFinalizer(container, nil)
517 518
 
518 519
 	logrus.Debugf(title+" succeeded id=%s", container.id)
519 520
 	return nil
... ...
@@ -16,8 +16,8 @@ var (
16 16
 	// ErrHandleClose is an error encountered when the handle generating the notification being waited on has been closed
17 17
 	ErrHandleClose = errors.New("hcsshim: the handle generating this notification has been closed")
18 18
 
19
-	// ErrInvalidHandle is an error encountered when using an invalid handle
20
-	ErrInvalidHandle = errors.New("hcsshim: the handle is invalid")
19
+	// ErrAlreadyClosed is an error encountered when using a handle that has been closed by the Close method
20
+	ErrAlreadyClosed = errors.New("hcsshim: the handle has already been closed")
21 21
 
22 22
 	// ErrInvalidNotificationType is an error encountered when an invalid notification type is used
23 23
 	ErrInvalidNotificationType = errors.New("hcsshim: invalid notification type")
... ...
@@ -159,6 +159,13 @@ func IsNotExist(err error) bool {
159 159
 		err == ErrProcNotFound
160 160
 }
161 161
 
162
+// IsAlreadyClosed checks if an error is caused by the Container or Process having been
163
+// already closed by a call to the Close() method.
164
+func IsAlreadyClosed(err error) bool {
165
+	err = getInnerError(err)
166
+	return err == ErrAlreadyClosed
167
+}
168
+
162 169
 // IsPending returns a boolean indicating whether the error is that
163 170
 // the requested operation is being completed in the background.
164 171
 func IsPending(err error) bool {
... ...
@@ -52,7 +52,7 @@ type MacPool struct {
52 52
 
53 53
 // HNSNetwork represents a network in HNS
54 54
 type HNSNetwork struct {
55
-	Id                   string            `json:",omitempty"`
55
+	Id                   string            `json:"ID,omitempty"`
56 56
 	Name                 string            `json:",omitempty"`
57 57
 	Type                 string            `json:",omitempty"`
58 58
 	NetworkAdapterName   string            `json:",omitempty"`
... ...
@@ -68,7 +68,7 @@ type HNSNetwork struct {
68 68
 
69 69
 // HNSEndpoint represents a network endpoint in HNS
70 70
 type HNSEndpoint struct {
71
-	Id                 string            `json:",omitempty"`
71
+	Id                 string            `json:"ID,omitempty"`
72 72
 	Name               string            `json:",omitempty"`
73 73
 	VirtualNetwork     string            `json:",omitempty"`
74 74
 	VirtualNetworkName string            `json:",omitempty"`
... ...
@@ -79,6 +79,7 @@ type HNSEndpoint struct {
79 79
 	DNSServerList      string            `json:",omitempty"`
80 80
 	GatewayAddress     string            `json:",omitempty"`
81 81
 	EnableInternalDNS  bool              `json:",omitempty"`
82
+	DisableICC         bool              `json:",omitempty"`
82 83
 	PrefixLength       uint8             `json:",omitempty"`
83 84
 	IsRemoteEndpoint   bool              `json:",omitempty"`
84 85
 }
... ...
@@ -10,6 +10,7 @@ import (
10 10
 type ProcessConfig struct {
11 11
 	ApplicationName  string
12 12
 	CommandLine      string
13
+	User             string
13 14
 	WorkingDirectory string
14 15
 	Environment      map[string]string
15 16
 	EmulateConsole   bool
... ...
@@ -66,6 +67,13 @@ type ContainerConfig struct {
66 66
 	AllowUnqualifiedDNSQuery bool        // True to allow unqualified DNS name resolution
67 67
 }
68 68
 
69
+type ComputeSystemQuery struct {
70
+	IDs    []string `json:"Ids,omitempty"`
71
+	Types  []string `json:",omitempty"`
72
+	Names  []string `json:",omitempty"`
73
+	Owners []string `json:",omitempty"`
74
+}
75
+
69 76
 // Container represents a created (but not necessarily running) container.
70 77
 type Container interface {
71 78
 	// Start synchronously starts the container.
... ...
@@ -3,6 +3,7 @@ package hcsshim
3 3
 import (
4 4
 	"encoding/json"
5 5
 	"io"
6
+	"runtime"
6 7
 	"sync"
7 8
 	"syscall"
8 9
 	"time"
... ...
@@ -73,7 +74,7 @@ func (process *process) Kill() error {
73 73
 	logrus.Debugf(title+" processid=%d", process.processID)
74 74
 
75 75
 	if process.handle == 0 {
76
-		return makeProcessError(process, operation, "", ErrInvalidHandle)
76
+		return makeProcessError(process, operation, "", ErrAlreadyClosed)
77 77
 	}
78 78
 
79 79
 	var resultp *uint16
... ...
@@ -128,7 +129,7 @@ func (process *process) ExitCode() (int, error) {
128 128
 	logrus.Debugf(title+" processid=%d", process.processID)
129 129
 
130 130
 	if process.handle == 0 {
131
-		return 0, makeProcessError(process, operation, "", ErrInvalidHandle)
131
+		return 0, makeProcessError(process, operation, "", ErrAlreadyClosed)
132 132
 	}
133 133
 
134 134
 	properties, err := process.properties()
... ...
@@ -157,7 +158,7 @@ func (process *process) ResizeConsole(width, height uint16) error {
157 157
 	logrus.Debugf(title+" processid=%d", process.processID)
158 158
 
159 159
 	if process.handle == 0 {
160
-		return makeProcessError(process, operation, "", ErrInvalidHandle)
160
+		return makeProcessError(process, operation, "", ErrAlreadyClosed)
161 161
 	}
162 162
 
163 163
 	modifyRequest := processModifyRequest{
... ...
@@ -226,7 +227,7 @@ func (process *process) Stdio() (io.WriteCloser, io.ReadCloser, io.ReadCloser, e
226 226
 	logrus.Debugf(title+" processid=%d", process.processID)
227 227
 
228 228
 	if process.handle == 0 {
229
-		return nil, nil, nil, makeProcessError(process, operation, "", ErrInvalidHandle)
229
+		return nil, nil, nil, makeProcessError(process, operation, "", ErrAlreadyClosed)
230 230
 	}
231 231
 
232 232
 	var stdIn, stdOut, stdErr syscall.Handle
... ...
@@ -270,7 +271,7 @@ func (process *process) CloseStdin() error {
270 270
 	logrus.Debugf(title+" processid=%d", process.processID)
271 271
 
272 272
 	if process.handle == 0 {
273
-		return makeProcessError(process, operation, "", ErrInvalidHandle)
273
+		return makeProcessError(process, operation, "", ErrAlreadyClosed)
274 274
 	}
275 275
 
276 276
 	modifyRequest := processModifyRequest{
... ...
@@ -321,6 +322,7 @@ func (process *process) Close() error {
321 321
 	}
322 322
 
323 323
 	process.handle = 0
324
+	runtime.SetFinalizer(process, nil)
324 325
 
325 326
 	logrus.Debugf(title+" succeeded processid=%d", process.processID)
326 327
 	return nil
... ...
@@ -26,37 +26,13 @@ func waitForNotification(callbackNumber uintptr, expectedNotification hcsNotific
26 26
 		return ErrInvalidNotificationType
27 27
 	}
28 28
 
29
+	var c <-chan time.Time
29 30
 	if timeout != nil {
30 31
 		timer := time.NewTimer(*timeout)
32
+		c = timer.C
31 33
 		defer timer.Stop()
32
-
33
-		select {
34
-		case err, ok := <-expectedChannel:
35
-			if !ok {
36
-				return ErrHandleClose
37
-			}
38
-			return err
39
-		case err, ok := <-channels[hcsNotificationSystemExited]:
40
-			if !ok {
41
-				return ErrHandleClose
42
-			}
43
-			// If the expected notification is hcsNotificationSystemExited which of the two selects
44
-			// chosen is random. Return the raw error if hcsNotificationSystemExited is expected
45
-			if channels[hcsNotificationSystemExited] == expectedChannel {
46
-				return err
47
-			}
48
-			return ErrUnexpectedContainerExit
49
-		case _, ok := <-channels[hcsNotificationServiceDisconnect]:
50
-			if !ok {
51
-				return ErrHandleClose
52
-			}
53
-			// hcsNotificationServiceDisconnect should never be an expected notification
54
-			// it does not need the same handling as hcsNotificationSystemExited
55
-			return ErrUnexpectedProcessAbort
56
-		case <-timer.C:
57
-			return ErrTimeout
58
-		}
59 34
 	}
35
+
60 36
 	select {
61 37
 	case err, ok := <-expectedChannel:
62 38
 		if !ok {
... ...
@@ -80,5 +56,7 @@ func waitForNotification(callbackNumber uintptr, expectedNotification hcsNotific
80 80
 		// hcsNotificationServiceDisconnect should never be an expected notification
81 81
 		// it does not need the same handling as hcsNotificationSystemExited
82 82
 		return ErrUnexpectedProcessAbort
83
+	case <-c:
84
+		return ErrTimeout
83 85
 	}
84 86
 }