Signed-off-by: John Howard <jhoward@microsoft.com>
| ... | ... |
@@ -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. |