Browse code

Handle plugin shutdown when liveRestore is set.

When daemon has liveRestore set, daemon shutdown should not shutdown
plugins. Fixes #24759

Signed-off-by: Anusha Ragunathan <anusha@docker.com>
(cherry picked from commit 4a44cf1d4c8e540b67aaa3834291a964c6ab7524)
Signed-off-by: Tibor Vass <tibor@docker.com>

Anusha Ragunathan authored on 2016/07/23 00:53:26
Showing 4 changed files
... ...
@@ -653,6 +653,9 @@ func (daemon *Daemon) Shutdown() error {
653 653
 	daemon.shutdown = true
654 654
 	// Keep mounts and networking running on daemon shutdown if
655 655
 	// we are to keep containers running and restore them.
656
+
657
+	pluginShutdown()
658
+
656 659
 	if daemon.configStore.LiveRestore && daemon.containers != nil {
657 660
 		// check if there are any running containers, if none we should do some cleanup
658 661
 		if ls, err := daemon.Containers(&types.ContainerListOptions{}); len(ls) != 0 || err != nil {
... ...
@@ -689,8 +692,6 @@ func (daemon *Daemon) Shutdown() error {
689 689
 		}
690 690
 	}
691 691
 
692
-	pluginShutdown()
693
-
694 692
 	if err := daemon.cleanupMounts(); err != nil {
695 693
 		return err
696 694
 	}
... ...
@@ -74,8 +74,9 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithPluginDisabled(c *check.C) {
74 74
 	c.Assert(out, checker.Contains, "false")
75 75
 }
76 76
 
77
-// TestDaemonShutdownLiveRestoreWithPlugins leaves plugin running.
78
-func (s *DockerDaemonSuite) TestDaemonShutdownLiveRestoreWithPlugins(c *check.C) {
77
+// TestDaemonKillLiveRestoreWithPlugins SIGKILLs daemon started with --live-restore.
78
+// Plugins should continue to run.
79
+func (s *DockerDaemonSuite) TestDaemonKillLiveRestoreWithPlugins(c *check.C) {
79 80
 	if err := s.d.Start("--live-restore"); err != nil {
80 81
 		c.Fatalf("Could not start daemon: %v", err)
81 82
 	}
... ...
@@ -104,6 +105,37 @@ func (s *DockerDaemonSuite) TestDaemonShutdownLiveRestoreWithPlugins(c *check.C)
104 104
 	}
105 105
 }
106 106
 
107
+// TestDaemonShutdownLiveRestoreWithPlugins SIGTERMs daemon started with --live-restore.
108
+// Plugins should continue to run.
109
+func (s *DockerDaemonSuite) TestDaemonShutdownLiveRestoreWithPlugins(c *check.C) {
110
+	if err := s.d.Start("--live-restore"); err != nil {
111
+		c.Fatalf("Could not start daemon: %v", err)
112
+	}
113
+	if out, err := s.d.Cmd("plugin", "install", "--grant-all-permissions", pluginName); err != nil {
114
+		c.Fatalf("Could not install plugin: %v %s", err, out)
115
+	}
116
+	defer func() {
117
+		if err := s.d.Restart("--live-restore"); err != nil {
118
+			c.Fatalf("Could not restart daemon: %v", err)
119
+		}
120
+		if out, err := s.d.Cmd("plugin", "disable", pluginName); err != nil {
121
+			c.Fatalf("Could not disable plugin: %v %s", err, out)
122
+		}
123
+		if out, err := s.d.Cmd("plugin", "remove", pluginName); err != nil {
124
+			c.Fatalf("Could not remove plugin: %v %s", err, out)
125
+		}
126
+	}()
127
+
128
+	if err := s.d.cmd.Process.Signal(os.Interrupt); err != nil {
129
+		c.Fatalf("Could not kill daemon: %v", err)
130
+	}
131
+
132
+	cmd := exec.Command("pgrep", "-f", "plugin-no-remove")
133
+	if out, ec, err := runCommandWithOutput(cmd); ec != 0 {
134
+		c.Fatalf("Expected exit code '0', got %d err: %v output: %s ", ec, err, out)
135
+	}
136
+}
137
+
107 138
 // TestDaemonShutdownWithPlugins shuts down running plugins.
108 139
 func (s *DockerDaemonSuite) TestDaemonShutdownWithPlugins(c *check.C) {
109 140
 	if err := s.d.Start(); err != nil {
... ...
@@ -319,7 +319,7 @@ func (pm *Manager) init() error {
319 319
 			if requiresManualRestore {
320 320
 				// if liveRestore is not enabled, the plugin will be stopped now so we should enable it
321 321
 				if err := pm.enable(p); err != nil {
322
-					logrus.Errorf("Error restoring plugin '%s': %s", p.Name(), err)
322
+					logrus.Errorf("Error enabling plugin '%s': %s", p.Name(), err)
323 323
 				}
324 324
 			}
325 325
 		}(p)
... ...
@@ -135,12 +135,16 @@ func (pm *Manager) Shutdown() {
135 135
 
136 136
 	pm.shutdown = true
137 137
 	for _, p := range pm.plugins {
138
+		if pm.liveRestore && p.P.Active {
139
+			logrus.Debug("Plugin active when liveRestore is set, skipping shutdown")
140
+			continue
141
+		}
138 142
 		if p.restartManager != nil {
139 143
 			if err := p.restartManager.Cancel(); err != nil {
140 144
 				logrus.Error(err)
141 145
 			}
142 146
 		}
143
-		if pm.containerdClient != nil {
147
+		if pm.containerdClient != nil && p.P.Active {
144 148
 			p.exitChan = make(chan bool)
145 149
 			err := pm.containerdClient.Signal(p.P.ID, int(syscall.SIGTERM))
146 150
 			if err != nil {
... ...
@@ -157,6 +161,10 @@ func (pm *Manager) Shutdown() {
157 157
 				}
158 158
 			}
159 159
 			close(p.exitChan)
160
+			pm.Lock()
161
+			p.P.Active = false
162
+			pm.save()
163
+			pm.Unlock()
160 164
 		}
161 165
 		if err := os.RemoveAll(p.runtimeSourcePath); err != nil {
162 166
 			logrus.Errorf("Remove plugin runtime failed with error: %v", err)