Browse code

Fix when connecting/disconnecting to/from default gw network

- Restoring original behavior where on disconnect
from overlay network (only connected network), it also
disconnects from default gw network.
- On sandbox delete, the leave and delete of each
endpoint is performed, regardless of whether the endpoint
is the gw network endpoint. This endpoint is already
automatically removed in endpoint.sbLeave()
- Also do not let internal network dictate container does
not need external connectivity. Before this fix, if a container
was connected to an overlay and an internal network, it may not
get attached to the default gw network.

Signed-off-by: Alessandro Boch <aboch@docker.com>

Alessandro Boch authored on 2016/04/07 01:11:45
Showing 4 changed files
... ...
@@ -65,20 +65,13 @@ func (sb *sandbox) setupDefaultGW() error {
65 65
 	return nil
66 66
 }
67 67
 
68
-// If present, removes the endpoint connecting the sandbox to the default gw network.
69
-// Unless it is the endpoint designated to provide the external connectivity.
70
-// If the sandbox is being deleted, removes the endpoint unconditionally.
68
+// If present, detach and remove the endpoint connecting the sandbox to the default gw network.
71 69
 func (sb *sandbox) clearDefaultGW() error {
72 70
 	var ep *endpoint
73 71
 
74 72
 	if ep = sb.getEndpointInGWNetwork(); ep == nil {
75 73
 		return nil
76 74
 	}
77
-
78
-	if ep == sb.getGatewayEndpoint() && !sb.inDelete {
79
-		return nil
80
-	}
81
-
82 75
 	if err := ep.sbLeave(sb, false); err != nil {
83 76
 		return fmt.Errorf("container %s: endpoint leaving GW Network failed: %v", sb.containerID, err)
84 77
 	}
... ...
@@ -88,21 +81,26 @@ func (sb *sandbox) clearDefaultGW() error {
88 88
 	return nil
89 89
 }
90 90
 
91
+// Evaluate whether the sandbox requires a default gateway based
92
+// on the endpoints to which it is connected. It does not account
93
+// for the default gateway network endpoint.
94
+
91 95
 func (sb *sandbox) needDefaultGW() bool {
92 96
 	var needGW bool
93 97
 
94 98
 	for _, ep := range sb.getConnectedEndpoints() {
95 99
 		if ep.endpointInGWNetwork() {
96
-			return false
100
+			continue
97 101
 		}
98 102
 		if ep.getNetwork().Type() == "null" || ep.getNetwork().Type() == "host" {
99 103
 			continue
100 104
 		}
101 105
 		if ep.getNetwork().Internal() {
102
-			return false
106
+			continue
103 107
 		}
104
-		if ep.joinInfo.disableGatewayService {
105
-			return false
108
+		// During stale sandbox cleanup, joinInfo may be nil
109
+		if ep.joinInfo != nil && ep.joinInfo.disableGatewayService {
110
+			continue
106 111
 		}
107 112
 		// TODO v6 needs to be handled.
108 113
 		if len(ep.Gateway()) > 0 {
... ...
@@ -115,6 +113,7 @@ func (sb *sandbox) needDefaultGW() bool {
115 115
 		}
116 116
 		needGW = true
117 117
 	}
118
+
118 119
 	return needGW
119 120
 }
120 121
 
... ...
@@ -446,7 +446,7 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
446 446
 		return err
447 447
 	}
448 448
 
449
-	if sb.needDefaultGW() {
449
+	if sb.needDefaultGW() && sb.getEndpointInGWNetwork() == nil {
450 450
 		return sb.setupDefaultGW()
451 451
 	}
452 452
 
... ...
@@ -479,7 +479,14 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
479 479
 		}
480 480
 	}
481 481
 
482
-	return sb.clearDefaultGW()
482
+	if !sb.needDefaultGW() {
483
+		if err := sb.clearDefaultGW(); err != nil {
484
+			log.Warnf("Failure while disconnecting sandbox %s (%s) from gateway network: %v",
485
+				sb.ID(), sb.ContainerID(), err)
486
+		}
487
+	}
488
+
489
+	return nil
483 490
 }
484 491
 
485 492
 func (ep *endpoint) rename(name string) error {
... ...
@@ -622,10 +629,7 @@ func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption)
622 622
 	}
623 623
 
624 624
 	sb.deleteHostsEntries(n.getSvcRecords(ep))
625
-	if !sb.inDelete && sb.needDefaultGW() {
626
-		if sb.getEPwithoutGateway() == nil {
627
-			return fmt.Errorf("endpoint without GW expected, but not found")
628
-		}
625
+	if !sb.inDelete && sb.needDefaultGW() && sb.getEndpointInGWNetwork() == nil {
629 626
 		return sb.setupDefaultGW()
630 627
 	}
631 628
 
... ...
@@ -639,7 +643,14 @@ func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption)
639 639
 		}
640 640
 	}
641 641
 
642
-	return sb.clearDefaultGW()
642
+	if !sb.needDefaultGW() {
643
+		if err := sb.clearDefaultGW(); err != nil {
644
+			log.Warnf("Failure while disconnecting sandbox %s (%s) from gateway network: %v",
645
+				sb.ID(), sb.ContainerID(), err)
646
+		}
647
+	}
648
+
649
+	return nil
643 650
 }
644 651
 
645 652
 func (n *network) validateForceDelete(locator string) error {
... ...
@@ -197,6 +197,10 @@ func (sb *sandbox) delete(force bool) error {
197 197
 	// Detach from all endpoints
198 198
 	retain := false
199 199
 	for _, ep := range sb.getConnectedEndpoints() {
200
+		// gw network endpoint detach and removal are automatic
201
+		if ep.endpointInGWNetwork() {
202
+			continue
203
+		}
200 204
 		// Retain the sanbdox if we can't obtain the network from store.
201 205
 		if _, err := c.getNetworkFromStore(ep.getNetwork().ID()); err != nil {
202 206
 			retain = true
... ...
@@ -345,10 +345,6 @@ function test_overlay() {
345 345
             # Disconnect from overlay network
346 346
             net_disconnect ${start} container_${start} multihost
347 347
 
348
-            # Make sure external connectivity works
349
-            runc $(dnet_container_name ${start} $dnet_suffix) $(get_sbox_id ${start} container_${start}) \
350
-                "ping -c 1 www.google.com"
351
-
352 348
             # Connect to overlay network again
353 349
             net_connect ${start} container_${start} multihost
354 350