Jelajahi Sumber

Release the network attachment on allocation failure

- otherwise the attachment task will stay in store and
  consume IP addresses and there is no way to remove it.

Signed-off-by: Alessandro Boch <aboch@docker.com>
Alessandro Boch 8 tahun lalu
induk
melakukan
9e74ea8594
2 mengubah file dengan 38 tambahan dan 1 penghapusan
  1. 14 1
      daemon/cluster/cluster.go
  2. 24 0
      integration-cli/docker_cli_swarm_test.go

+ 14 - 1
daemon/cluster/cluster.go

@@ -1697,18 +1697,31 @@ func (c *Cluster) AttachNetwork(target string, containerID string, addresses []s
 	close(attachCompleteCh)
 	c.Unlock()
 
-	logrus.Debugf("Successfully attached to network %s with tid %s", target, taskID)
+	logrus.Debugf("Successfully attached to network %s with task id %s", target, taskID)
+
+	release := func() {
+		ctx, cancel := c.getRequestContext()
+		defer cancel()
+		if err := agent.ResourceAllocator().DetachNetwork(ctx, taskID); err != nil {
+			logrus.Errorf("Failed remove network attachment %s to network %s on allocation failure: %v",
+				taskID, target, err)
+		}
+	}
 
 	var config *network.NetworkingConfig
 	select {
 	case config = <-attachWaitCh:
 	case <-ctx.Done():
+		release()
 		return nil, fmt.Errorf("attaching to network failed, make sure your network options are correct and check manager logs: %v", ctx.Err())
 	}
 
 	c.Lock()
 	c.attachers[aKey].config = config
 	c.Unlock()
+
+	logrus.Debugf("Successfully allocated resources on network %s for task id %s", target, taskID)
+
 	return config, nil
 }
 

+ 24 - 0
integration-cli/docker_cli_swarm_test.go

@@ -420,6 +420,30 @@ func (s *DockerSwarmSuite) TestOverlayAttachableOnSwarmLeave(c *check.C) {
 	c.Assert(out, checker.Not(checker.Contains), nwName)
 }
 
+func (s *DockerSwarmSuite) TestOverlayAttachableReleaseResourcesOnFailure(c *check.C) {
+	d := s.AddDaemon(c, true, true)
+
+	// Create attachable network
+	out, err := d.Cmd("network", "create", "-d", "overlay", "--attachable", "--subnet", "10.10.9.0/24", "ovnet")
+	c.Assert(err, checker.IsNil, check.Commentf(out))
+
+	// Attach a container with specific IP
+	out, err = d.Cmd("run", "-d", "--network", "ovnet", "--name", "c1", "--ip", "10.10.9.33", "busybox", "top")
+	c.Assert(err, checker.IsNil, check.Commentf(out))
+
+	// Attempt to attach another contianer with same IP, must fail
+	_, err = d.Cmd("run", "-d", "--network", "ovnet", "--name", "c2", "--ip", "10.10.9.33", "busybox", "top")
+	c.Assert(err, checker.NotNil)
+
+	// Remove first container
+	out, err = d.Cmd("rm", "-f", "c1")
+	c.Assert(err, checker.IsNil, check.Commentf(out))
+
+	// Verify the network can be removed, no phantom network attachment task left over
+	out, err = d.Cmd("network", "rm", "ovnet")
+	c.Assert(err, checker.IsNil, check.Commentf(out))
+}
+
 func (s *DockerSwarmSuite) TestSwarmRemoveInternalNetwork(c *check.C) {
 	d := s.AddDaemon(c, true, true)