Browse code

Fix endpoint leave failure for --net=host mode

When a container is started with `--net=host` with
a particular name and it is subsequently destroyed,
then all subsequent creations of the container with
the same name will fail. This is because in `--net=host`
the namespace is shared i.e the host namespace so
trying to destroy the host namespace by calling
`LeaveAll` will fail and the endpoint is left with
the dangling state. So the fix is, for this mode, do
not attempt to destroy the namespace but just cleanup
the endpoint state and return.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>

Jana Radhakrishnan authored on 2015/06/25 02:23:00
Showing 5 changed files
... ...
@@ -1003,33 +1003,47 @@ func (container *Container) ReleaseNetwork() {
1003 1003
 		return
1004 1004
 	}
1005 1005
 
1006
-	err := container.daemon.netController.LeaveAll(container.ID)
1007
-	if err != nil {
1008
-		logrus.Errorf("Leave all failed for  %s: %v", container.ID, err)
1009
-		return
1010
-	}
1011
-
1012 1006
 	eid := container.NetworkSettings.EndpointID
1013 1007
 	nid := container.NetworkSettings.NetworkID
1014 1008
 
1015 1009
 	container.NetworkSettings = &network.Settings{}
1016 1010
 
1017
-	// In addition to leaving all endpoints, delete implicitly created endpoint
1018
-	if container.Config.PublishService == "" && eid != "" && nid != "" {
1019
-		n, err := container.daemon.netController.NetworkByID(nid)
1020
-		if err != nil {
1021
-			logrus.Errorf("error locating network id %s: %v", nid, err)
1011
+	if nid == "" || eid == "" {
1012
+		return
1013
+	}
1014
+
1015
+	n, err := container.daemon.netController.NetworkByID(nid)
1016
+	if err != nil {
1017
+		logrus.Errorf("error locating network id %s: %v", nid, err)
1018
+		return
1019
+	}
1020
+
1021
+	ep, err := n.EndpointByID(eid)
1022
+	if err != nil {
1023
+		logrus.Errorf("error locating endpoint id %s: %v", eid, err)
1024
+		return
1025
+	}
1026
+
1027
+	switch {
1028
+	case container.hostConfig.NetworkMode.IsHost():
1029
+		if err := ep.Leave(container.ID); err != nil {
1030
+			logrus.Errorf("Error leaving endpoint id %s for container %s: %v", eid, container.ID, err)
1022 1031
 			return
1023 1032
 		}
1024
-		ep, err := n.EndpointByID(eid)
1025
-		if err != nil {
1026
-			logrus.Errorf("error locating endpoint id %s: %v", eid, err)
1033
+	default:
1034
+		if err := container.daemon.netController.LeaveAll(container.ID); err != nil {
1035
+			logrus.Errorf("Leave all failed for  %s: %v", container.ID, err)
1027 1036
 			return
1028 1037
 		}
1038
+	}
1039
+
1040
+	// In addition to leaving all endpoints, delete implicitly created endpoint
1041
+	if container.Config.PublishService == "" {
1029 1042
 		if err := ep.Delete(); err != nil {
1030 1043
 			logrus.Errorf("deleting endpoint failed: %v", err)
1031 1044
 		}
1032 1045
 	}
1046
+
1033 1047
 }
1034 1048
 
1035 1049
 func disableAllActiveLinks(container *Container) {
... ...
@@ -18,7 +18,7 @@ clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://gith
18 18
 clone hg code.google.com/p/gosqlite 74691fb6f837
19 19
 
20 20
 #get libnetwork packages
21
-clone git github.com/docker/libnetwork 1aaf1047fd48345619a875184538a0eb6c6cfb2a
21
+clone git github.com/docker/libnetwork 82a1f5634904b57e619fd715ded6903727e00143
22 22
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
23 23
 clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
24 24
 clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
... ...
@@ -1480,10 +1480,10 @@ func (s *DockerSuite) TestRunResolvconfUpdate(c *check.C) {
1480 1480
 		c.Fatalf("Restarted container does not have updated resolv.conf; expected %q, got %q", tmpResolvConf, string(containerResolv))
1481 1481
 	}
1482 1482
 
1483
-	/* 	//make a change to resolv.conf (in this case replacing our tmp copy with orig copy)
1484
-	   	if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil {
1485
-	   		c.Fatal(err)
1486
-	   	} */
1483
+	/*	//make a change to resolv.conf (in this case replacing our tmp copy with orig copy)
1484
+		if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil {
1485
+			c.Fatal(err)
1486
+		} */
1487 1487
 	//2. test that a restarting container does not receive resolv.conf updates
1488 1488
 	//   if it modified the container copy of the starting point resolv.conf
1489 1489
 	cmd = exec.Command(dockerBinary, "run", "--name='second'", "busybox", "sh", "-c", "echo 'search mylittlepony.com' >>/etc/resolv.conf")
... ...
@@ -1793,7 +1793,7 @@ func (s *DockerSuite) TestRunCleanupCmdOnEntrypoint(c *check.C) {
1793 1793
 	if _, err := buildImage(name,
1794 1794
 		`FROM busybox
1795 1795
 		ENTRYPOINT ["echo"]
1796
-        CMD ["testingpoint"]`,
1796
+	CMD ["testingpoint"]`,
1797 1797
 		true); err != nil {
1798 1798
 		c.Fatal(err)
1799 1799
 	}
... ...
@@ -2820,6 +2820,22 @@ func (s *DockerSuite) TestRunNetHost(c *check.C) {
2820 2820
 	}
2821 2821
 }
2822 2822
 
2823
+func (s *DockerSuite) TestRunNetHostTwiceSameName(c *check.C) {
2824
+	testRequires(c, SameHostDaemon)
2825
+
2826
+	cmd := exec.Command(dockerBinary, "run", "--rm", "--name=thost", "--net=host", "busybox", "true")
2827
+	out2, _, err := runCommandWithOutput(cmd)
2828
+	if err != nil {
2829
+		c.Fatal(err, out2)
2830
+	}
2831
+
2832
+	cmd = exec.Command(dockerBinary, "run", "--rm", "--name=thost", "--net=host", "busybox", "true")
2833
+	out2, _, err = runCommandWithOutput(cmd)
2834
+	if err != nil {
2835
+		c.Fatal(err, out2)
2836
+	}
2837
+}
2838
+
2823 2839
 func (s *DockerSuite) TestRunNetContainerWhichHost(c *check.C) {
2824 2840
 	testRequires(c, SameHostDaemon)
2825 2841
 
... ...
@@ -68,6 +68,10 @@ func Build(path, IP, hostname, domainname string, extraContent []Record) error {
68 68
 
69 69
 // Add adds an arbitrary number of Records to an already existing /etc/hosts file
70 70
 func Add(path string, recs []Record) error {
71
+	if len(recs) == 0 {
72
+		return nil
73
+	}
74
+
71 75
 	f, err := os.Open(path)
72 76
 	if err != nil {
73 77
 		return err
... ...
@@ -91,6 +95,10 @@ func Add(path string, recs []Record) error {
91 91
 
92 92
 // Delete deletes an arbitrary number of Records already existing in /etc/hosts file
93 93
 func Delete(path string, recs []Record) error {
94
+	if len(recs) == 0 {
95
+		return nil
96
+	}
97
+
94 98
 	old, err := ioutil.ReadFile(path)
95 99
 	if err != nil {
96 100
 		return err
... ...
@@ -416,6 +416,11 @@ func (n *network) updateSvcRecord(ep *endpoint, isAdd bool) {
416 416
 	}
417 417
 	n.Unlock()
418 418
 
419
+	// If there are no records to add or delete then simply return here
420
+	if len(recs) == 0 {
421
+		return
422
+	}
423
+
419 424
 	var epList []*endpoint
420 425
 	n.WalkEndpoints(func(e Endpoint) bool {
421 426
 		cEp := e.(*endpoint)