Browse code

Windows: Remove servicing mode

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

John Howard authored on 2018/02/10 03:08:47
Showing 7 changed files
... ...
@@ -111,10 +111,7 @@ func (daemon *Daemon) ProcessEvent(id string, e libcontainerd.EventType, ei libc
111 111
 			}
112 112
 
113 113
 			daemon.setStateCounter(c)
114
-			if err := c.CheckpointTo(daemon.containersReplica); err != nil {
115
-				return err
116
-			}
117
-			return daemon.postRunProcessing(c, ei)
114
+			return c.CheckpointTo(daemon.containersReplica)
118 115
 		}
119 116
 
120 117
 		if execConfig := c.ExecCommands.Get(ei.ProcessID); execConfig != nil {
121 118
deleted file mode 100644
... ...
@@ -1,11 +0,0 @@
1
-package daemon // import "github.com/docker/docker/daemon"
2
-
3
-import (
4
-	"github.com/docker/docker/container"
5
-	"github.com/docker/docker/libcontainerd"
6
-)
7
-
8
-// postRunProcessing perfoms any processing needed on the container after it has stopped.
9
-func (daemon *Daemon) postRunProcessing(_ *container.Container, _ libcontainerd.EventInfo) error {
10
-	return nil
11
-}
12 1
deleted file mode 100644
... ...
@@ -1,53 +0,0 @@
1
-package daemon // import "github.com/docker/docker/daemon"
2
-
3
-import (
4
-	"context"
5
-
6
-	"github.com/docker/docker/container"
7
-	"github.com/docker/docker/libcontainerd"
8
-	"github.com/pkg/errors"
9
-	"github.com/sirupsen/logrus"
10
-)
11
-
12
-// postRunProcessing starts a servicing container if required
13
-func (daemon *Daemon) postRunProcessing(c *container.Container, ei libcontainerd.EventInfo) error {
14
-	if ei.ExitCode == 0 && ei.UpdatePending {
15
-		spec, err := daemon.createSpec(c)
16
-		if err != nil {
17
-			return err
18
-		}
19
-		// Turn on servicing
20
-		spec.Windows.Servicing = true
21
-
22
-		copts, err := daemon.getLibcontainerdCreateOptions(c)
23
-		if err != nil {
24
-			return err
25
-		}
26
-
27
-		// Create a new servicing container, which will start, complete the
28
-		// update, and merge back the results if it succeeded, all as part of
29
-		// the below function call.
30
-		ctx := context.Background()
31
-		svcID := c.ID + "_servicing"
32
-		logger := logrus.WithField("container", svcID)
33
-		if err := daemon.containerd.Create(ctx, svcID, spec, copts); err != nil {
34
-			c.SetExitCode(-1)
35
-			return errors.Wrap(err, "post-run update servicing failed")
36
-		}
37
-		_, err = daemon.containerd.Start(ctx, svcID, "", false, nil)
38
-		if err != nil {
39
-			logger.WithError(err).Warn("failed to run servicing container")
40
-			if err := daemon.containerd.Delete(ctx, svcID); err != nil {
41
-				logger.WithError(err).Warn("failed to delete servicing container")
42
-			}
43
-		} else {
44
-			if _, _, err := daemon.containerd.DeleteTask(ctx, svcID); err != nil {
45
-				logger.WithError(err).Warn("failed to delete servicing container task")
46
-			}
47
-			if err := daemon.containerd.Delete(ctx, svcID); err != nil {
48
-				logger.WithError(err).Warn("failed to delete servicing container")
49
-			}
50
-		}
51
-	}
52
-	return nil
53
-}
... ...
@@ -326,9 +326,6 @@ func (daemon *Daemon) createSpecWindowsFields(c *container.Container, s *specs.S
326 326
 		s.Windows.CredentialSpec = cs
327 327
 	}
328 328
 
329
-	// Assume we are not starting a container for a servicing operation
330
-	s.Windows.Servicing = false
331
-
332 329
 	return nil
333 330
 }
334 331
 
... ...
@@ -4237,35 +4237,6 @@ func (s *DockerSuite) TestRunCredentialSpecWellFormed(c *check.C) {
4237 4237
 	dockerCmd(c, "run", `--security-opt=credentialspec=file://valid.json`, "busybox", "true")
4238 4238
 }
4239 4239
 
4240
-// Windows specific test to ensure that a servicing app container is started
4241
-// if necessary once a container exits. It does this by forcing a no-op
4242
-// servicing event and verifying the event from Hyper-V-Compute
4243
-func (s *DockerSuite) TestRunServicingContainer(c *check.C) {
4244
-	testRequires(c, DaemonIsWindows, SameHostDaemon)
4245
-
4246
-	// This functionality does not exist in post-RS3 builds.
4247
-	// Note we get the version number from the full build string, as Windows
4248
-	// reports Windows 8 version 6.2 build 9200 from non-manifested binaries.
4249
-	// Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx
4250
-	v, err := kernel.GetKernelVersion()
4251
-	c.Assert(err, checker.IsNil)
4252
-	build, _ := strconv.Atoi(strings.Split(strings.SplitN(v.String(), " ", 3)[2][1:], ".")[0])
4253
-	if build > 16299 {
4254
-		c.Skip("Disabled on post-RS3 builds")
4255
-	}
4256
-
4257
-	out := cli.DockerCmd(c, "run", "-d", testEnv.PlatformDefaults.BaseImage, "cmd", "/c", "mkdir c:\\programdata\\Microsoft\\Windows\\ContainerUpdates\\000_000_d99f45d0-ffc8-4af7-bd9c-ea6a62e035c9_200 && sc control cexecsvc 255").Combined()
4258
-	containerID := strings.TrimSpace(out)
4259
-	cli.WaitExited(c, containerID, 60*time.Second)
4260
-
4261
-	result := icmd.RunCommand("powershell", "echo", `(Get-WinEvent -ProviderName "Microsoft-Windows-Hyper-V-Compute" -FilterXPath 'Event[System[EventID=2010]]' -MaxEvents 1).Message`)
4262
-	result.Assert(c, icmd.Success)
4263
-	out2 := result.Combined()
4264
-	c.Assert(out2, checker.Contains, `"Servicing":true`, check.Commentf("Servicing container does not appear to have been started: %s", out2))
4265
-	c.Assert(out2, checker.Contains, `Windows Container (Servicing)`, check.Commentf("Didn't find 'Windows Container (Servicing): %s", out2))
4266
-	c.Assert(out2, checker.Contains, containerID+"_servicing", check.Commentf("Didn't find '%s_servicing': %s", containerID+"_servicing", out2))
4267
-}
4268
-
4269 4240
 func (s *DockerSuite) TestRunDuplicateMount(c *check.C) {
4270 4241
 	testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
4271 4242
 
... ...
@@ -82,7 +82,7 @@ func (c *client) Version(ctx context.Context) (containerd.Version, error) {
82 82
 // |                 | Isolation=Process                          | Isolation=Hyper-V                                 |
83 83
 // +-----------------+--------------------------------------------+---------------------------------------------------+
84 84
 // | VolumePath      | \\?\\Volume{GUIDa}                         |                                                   |
85
-// | LayerFolderPath | %root%\windowsfilter\containerID           | %root%\windowsfilter\containerID (servicing only) |
85
+// | LayerFolderPath | %root%\windowsfilter\containerID           |                                                   |
86 86
 // | Layers[]        | ID=GUIDb;Path=%root%\windowsfilter\layerID | ID=GUIDb;Path=%root%\windowsfilter\layerID        |
87 87
 // | HvRuntime       |                                            | ImagePath=%root%\BaseLayerID\UtilityVM            |
88 88
 // +-----------------+--------------------------------------------+---------------------------------------------------+
... ...
@@ -104,7 +104,6 @@ func (c *client) Version(ctx context.Context) (containerd.Version, error) {
104 104
 //	"MappedDirectories": [],
105 105
 //	"HvPartition": false,
106 106
 //	"EndpointList": ["eef2649d-bb17-4d53-9937-295a8efe6f2c"],
107
-//	"Servicing": false
108 107
 //}
109 108
 //
110 109
 // Isolation=Hyper-V example:
... ...
@@ -126,7 +125,6 @@ func (c *client) Version(ctx context.Context) (containerd.Version, error) {
126 126
 //	"HvRuntime": {
127 127
 //		"ImagePath": "C:\\\\control\\\\windowsfilter\\\\65bf96e5760a09edf1790cb229e2dfb2dbd0fcdc0bf7451bae099106bfbfea0c\\\\UtilityVM"
128 128
 //	},
129
-//	"Servicing": false
130 129
 //}
131 130
 func (c *client) Create(_ context.Context, id string, spec *specs.Spec, runtimeOptions interface{}) error {
132 131
 	if ctr := c.getContainer(id); ctr != nil {
... ...
@@ -155,7 +153,6 @@ func (c *client) createWindows(id string, spec *specs.Spec, runtimeOptions inter
155 155
 		IgnoreFlushesDuringBoot: spec.Windows.IgnoreFlushesDuringBoot,
156 156
 		HostName:                spec.Hostname,
157 157
 		HvPartition:             false,
158
-		Servicing:               spec.Windows.Servicing,
159 158
 	}
160 159
 
161 160
 	if spec.Windows.Resources != nil {
... ...
@@ -324,9 +321,6 @@ func (c *client) createWindows(id string, spec *specs.Spec, runtimeOptions inter
324 324
 		waitCh:       make(chan struct{}),
325 325
 	}
326 326
 
327
-	// Start the container. If this is a servicing container, this call
328
-	// will block until the container is done with the servicing
329
-	// execution.
330 327
 	logger.Debug("starting container")
331 328
 	if err = hcsContainer.Start(); err != nil {
332 329
 		c.logger.WithError(err).Error("failed to start container")
... ...
@@ -525,9 +519,7 @@ func (c *client) createLinux(id string, spec *specs.Spec, runtimeOptions interfa
525 525
 		waitCh:       make(chan struct{}),
526 526
 	}
527 527
 
528
-	// Start the container. If this is a servicing container, this call
529
-	// will block until the container is done with the servicing
530
-	// execution.
528
+	// Start the container.
531 529
 	logger.Debug("starting container")
532 530
 	if err = hcsContainer.Start(); err != nil {
533 531
 		c.logger.WithError(err).Error("failed to start container")
... ...
@@ -588,14 +580,14 @@ func (c *client) Start(_ context.Context, id, _ string, withStdin bool, attachSt
588 588
 	)
589 589
 	if ctr.ociSpec.Process != nil {
590 590
 		emulateConsole = ctr.ociSpec.Process.Terminal
591
-		createStdErrPipe = !ctr.ociSpec.Process.Terminal && !ctr.ociSpec.Windows.Servicing
591
+		createStdErrPipe = !ctr.ociSpec.Process.Terminal
592 592
 	}
593 593
 
594 594
 	createProcessParms := &hcsshim.ProcessConfig{
595 595
 		EmulateConsole:   emulateConsole,
596 596
 		WorkingDirectory: ctr.ociSpec.Process.Cwd,
597
-		CreateStdInPipe:  !ctr.ociSpec.Windows.Servicing,
598
-		CreateStdOutPipe: !ctr.ociSpec.Windows.Servicing,
597
+		CreateStdInPipe:  true,
598
+		CreateStdOutPipe: true,
599 599
 		CreateStdErrPipe: createStdErrPipe,
600 600
 	}
601 601
 
... ...
@@ -655,21 +647,6 @@ func (c *client) Start(_ context.Context, id, _ string, withStdin bool, attachSt
655 655
 	}
656 656
 	logger.WithField("pid", p.pid).Debug("init process started")
657 657
 
658
-	// If this is a servicing container, wait on the process synchronously here and
659
-	// if it succeeds, wait for it cleanly shutdown and merge into the parent container.
660
-	if ctr.ociSpec.Windows.Servicing {
661
-		// reapProcess takes the lock
662
-		ctr.Unlock()
663
-		defer ctr.Lock()
664
-		exitCode := c.reapProcess(ctr, p)
665
-
666
-		if exitCode != 0 {
667
-			return -1, errors.Errorf("libcontainerd: servicing container %s returned non-zero exit code %d", ctr.id, exitCode)
668
-		}
669
-
670
-		return p.pid, nil
671
-	}
672
-
673 658
 	dio, err := newIOFromProcess(newProcess, ctr.ociSpec.Process.Terminal)
674 659
 	if err != nil {
675 660
 		logger.WithError(err).Error("failed to get stdio pipes")
... ...
@@ -1275,7 +1252,6 @@ func (c *client) reapProcess(ctr *container, p *process) int {
1275 1275
 		eventErr = fmt.Errorf("hcsProcess.Close() failed %s", err)
1276 1276
 	}
1277 1277
 
1278
-	var pendingUpdates bool
1279 1278
 	if p.id == InitProcessName {
1280 1279
 		// Update container status
1281 1280
 		ctr.Lock()
... ...
@@ -1285,16 +1261,6 @@ func (c *client) reapProcess(ctr *container, p *process) int {
1285 1285
 		close(ctr.waitCh)
1286 1286
 		ctr.Unlock()
1287 1287
 
1288
-		// Handle any servicing
1289
-		if exitCode == 0 && ctr.isWindows && !ctr.ociSpec.Windows.Servicing {
1290
-			pendingUpdates, err = ctr.hcsContainer.HasPendingUpdates()
1291
-			logger.Infof("Pending updates: %v", pendingUpdates)
1292
-			if err != nil {
1293
-				logger.WithError(err).
1294
-					Warnf("failed to check for pending updates (container may have been killed)")
1295
-			}
1296
-		}
1297
-
1298 1288
 		if err := c.shutdownContainer(ctr); err != nil {
1299 1289
 			exitCode = -1
1300 1290
 			logger.WithError(err).Warn("failed to shutdown container")
... ...
@@ -1320,37 +1286,34 @@ func (c *client) reapProcess(ctr *container, p *process) int {
1320 1320
 		}
1321 1321
 	}
1322 1322
 
1323
-	if !(ctr.isWindows && ctr.ociSpec.Windows.Servicing) {
1324
-		c.eventQ.append(ctr.id, func() {
1325
-			ei := EventInfo{
1326
-				ContainerID:   ctr.id,
1327
-				ProcessID:     p.id,
1328
-				Pid:           uint32(p.pid),
1329
-				ExitCode:      uint32(exitCode),
1330
-				ExitedAt:      exitedAt,
1331
-				UpdatePending: pendingUpdates,
1332
-				Error:         eventErr,
1333
-			}
1334
-			c.logger.WithFields(logrus.Fields{
1323
+	c.eventQ.append(ctr.id, func() {
1324
+		ei := EventInfo{
1325
+			ContainerID: ctr.id,
1326
+			ProcessID:   p.id,
1327
+			Pid:         uint32(p.pid),
1328
+			ExitCode:    uint32(exitCode),
1329
+			ExitedAt:    exitedAt,
1330
+			Error:       eventErr,
1331
+		}
1332
+		c.logger.WithFields(logrus.Fields{
1333
+			"container":  ctr.id,
1334
+			"event":      EventExit,
1335
+			"event-info": ei,
1336
+		}).Info("sending event")
1337
+		err := c.backend.ProcessEvent(ctr.id, EventExit, ei)
1338
+		if err != nil {
1339
+			c.logger.WithError(err).WithFields(logrus.Fields{
1335 1340
 				"container":  ctr.id,
1336 1341
 				"event":      EventExit,
1337 1342
 				"event-info": ei,
1338
-			}).Info("sending event")
1339
-			err := c.backend.ProcessEvent(ctr.id, EventExit, ei)
1340
-			if err != nil {
1341
-				c.logger.WithError(err).WithFields(logrus.Fields{
1342
-					"container":  ctr.id,
1343
-					"event":      EventExit,
1344
-					"event-info": ei,
1345
-				}).Error("failed to process event")
1346
-			}
1347
-			if p.id != InitProcessName {
1348
-				ctr.Lock()
1349
-				delete(ctr.execs, p.id)
1350
-				ctr.Unlock()
1351
-			}
1352
-		})
1353
-	}
1343
+			}).Error("failed to process event")
1344
+		}
1345
+		if p.id != InitProcessName {
1346
+			ctr.Lock()
1347
+			delete(ctr.execs, p.id)
1348
+			ctr.Unlock()
1349
+		}
1350
+	})
1354 1351
 
1355 1352
 	return exitCode
1356 1353
 }
... ...
@@ -71,9 +71,7 @@ type EventInfo struct {
71 71
 	ExitCode    uint32
72 72
 	ExitedAt    time.Time
73 73
 	OOMKilled   bool
74
-	// Windows Only field
75
-	UpdatePending bool
76
-	Error         error
74
+	Error       error
77 75
 }
78 76
 
79 77
 // Backend defines callbacks that the client of the library needs to implement.