소스 검색

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>
Anusha Ragunathan 9 년 전
부모
커밋
4a44cf1d4c
4개의 변경된 파일47개의 추가작업 그리고 6개의 파일을 삭제
  1. 3 2
      daemon/daemon.go
  2. 34 2
      integration-cli/docker_cli_daemon_experimental_test.go
  3. 1 1
      plugin/manager.go
  4. 9 1
      plugin/manager_linux.go

+ 3 - 2
daemon/daemon.go

@@ -651,6 +651,9 @@ func (daemon *Daemon) Shutdown() error {
 	daemon.shutdown = true
 	// Keep mounts and networking running on daemon shutdown if
 	// we are to keep containers running and restore them.
+
+	pluginShutdown()
+
 	if daemon.configStore.LiveRestore && daemon.containers != nil {
 		// check if there are any running containers, if none we should do some cleanup
 		if ls, err := daemon.Containers(&types.ContainerListOptions{}); len(ls) != 0 || err != nil {
@@ -687,8 +690,6 @@ func (daemon *Daemon) Shutdown() error {
 		}
 	}
 
-	pluginShutdown()
-
 	if err := daemon.cleanupMounts(); err != nil {
 		return err
 	}

+ 34 - 2
integration-cli/docker_cli_daemon_experimental_test.go

@@ -74,8 +74,9 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithPluginDisabled(c *check.C) {
 	c.Assert(out, checker.Contains, "false")
 }
 
-// TestDaemonShutdownLiveRestoreWithPlugins leaves plugin running.
-func (s *DockerDaemonSuite) TestDaemonShutdownLiveRestoreWithPlugins(c *check.C) {
+// TestDaemonKillLiveRestoreWithPlugins SIGKILLs daemon started with --live-restore.
+// Plugins should continue to run.
+func (s *DockerDaemonSuite) TestDaemonKillLiveRestoreWithPlugins(c *check.C) {
 	if err := s.d.Start("--live-restore"); err != nil {
 		c.Fatalf("Could not start daemon: %v", err)
 	}
@@ -104,6 +105,37 @@ func (s *DockerDaemonSuite) TestDaemonShutdownLiveRestoreWithPlugins(c *check.C)
 	}
 }
 
+// TestDaemonShutdownLiveRestoreWithPlugins SIGTERMs daemon started with --live-restore.
+// Plugins should continue to run.
+func (s *DockerDaemonSuite) TestDaemonShutdownLiveRestoreWithPlugins(c *check.C) {
+	if err := s.d.Start("--live-restore"); err != nil {
+		c.Fatalf("Could not start daemon: %v", err)
+	}
+	if out, err := s.d.Cmd("plugin", "install", "--grant-all-permissions", pluginName); err != nil {
+		c.Fatalf("Could not install plugin: %v %s", err, out)
+	}
+	defer func() {
+		if err := s.d.Restart("--live-restore"); err != nil {
+			c.Fatalf("Could not restart daemon: %v", err)
+		}
+		if out, err := s.d.Cmd("plugin", "disable", pluginName); err != nil {
+			c.Fatalf("Could not disable plugin: %v %s", err, out)
+		}
+		if out, err := s.d.Cmd("plugin", "remove", pluginName); err != nil {
+			c.Fatalf("Could not remove plugin: %v %s", err, out)
+		}
+	}()
+
+	if err := s.d.cmd.Process.Signal(os.Interrupt); err != nil {
+		c.Fatalf("Could not kill daemon: %v", err)
+	}
+
+	cmd := exec.Command("pgrep", "-f", "plugin-no-remove")
+	if out, ec, err := runCommandWithOutput(cmd); ec != 0 {
+		c.Fatalf("Expected exit code '0', got %d err: %v output: %s ", ec, err, out)
+	}
+}
+
 // TestDaemonShutdownWithPlugins shuts down running plugins.
 func (s *DockerDaemonSuite) TestDaemonShutdownWithPlugins(c *check.C) {
 	if err := s.d.Start(); err != nil {

+ 1 - 1
plugin/manager.go

@@ -319,7 +319,7 @@ func (pm *Manager) init() error {
 			if requiresManualRestore {
 				// if liveRestore is not enabled, the plugin will be stopped now so we should enable it
 				if err := pm.enable(p); err != nil {
-					logrus.Errorf("Error restoring plugin '%s': %s", p.Name(), err)
+					logrus.Errorf("Error enabling plugin '%s': %s", p.Name(), err)
 				}
 			}
 		}(p)

+ 9 - 1
plugin/manager_linux.go

@@ -135,12 +135,16 @@ func (pm *Manager) Shutdown() {
 
 	pm.shutdown = true
 	for _, p := range pm.plugins {
+		if pm.liveRestore && p.P.Active {
+			logrus.Debug("Plugin active when liveRestore is set, skipping shutdown")
+			continue
+		}
 		if p.restartManager != nil {
 			if err := p.restartManager.Cancel(); err != nil {
 				logrus.Error(err)
 			}
 		}
-		if pm.containerdClient != nil {
+		if pm.containerdClient != nil && p.P.Active {
 			p.exitChan = make(chan bool)
 			err := pm.containerdClient.Signal(p.P.ID, int(syscall.SIGTERM))
 			if err != nil {
@@ -157,6 +161,10 @@ func (pm *Manager) Shutdown() {
 				}
 			}
 			close(p.exitChan)
+			pm.Lock()
+			p.P.Active = false
+			pm.save()
+			pm.Unlock()
 		}
 		if err := os.RemoveAll(p.runtimeSourcePath); err != nil {
 			logrus.Errorf("Remove plugin runtime failed with error: %v", err)