Browse code

Vendor libnetwork v0.5.4

- Removed the isNodeAlive protection when user forces an endpoint delete

- Bridge driver supporting internal network option
- Backend implementation to support "force" option to network disconnect
- Fixing a regex in etchosts package to fix docker/docker#19080

Signed-off-by: Madhu Venugopal <madhu@docker.com>

Madhu Venugopal authored on 2016/01/13 04:33:16
Showing 11 changed files
... ...
@@ -26,7 +26,7 @@ clone git github.com/docker/engine-api v0.1.3
26 26
 clone git github.com/RackSec/srslog 6eb773f331e46fbba8eecb8e794e635e75fc04de
27 27
 
28 28
 #get libnetwork packages
29
-clone git github.com/docker/libnetwork c8ec4bd24e1e76feb4f79e3924c68cd2ce89938a
29
+clone git github.com/docker/libnetwork v0.5.4
30 30
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
31 31
 clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
32 32
 clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
33 33
new file mode 100644
... ...
@@ -0,0 +1,47 @@
0
+# Changelog
1
+
2
+## 0.5.4 (2016-01-12)
3
+- Removed the isNodeAlive protection when user forces an endpoint delete
4
+
5
+## 0.5.3 (2016-01-12)
6
+- Bridge driver supporting internal network option
7
+- Backend implementation to support "force" option to network disconnect
8
+- Fixing a regex in etchosts package to fix docker/docker#19080
9
+
10
+## 0.5.2 (2016-01-08)
11
+- Embedded DNS replacing /etc/hosts based Service Discovery
12
+- Container local alias and Network-scoped alias support
13
+- Backend support for internal network mode
14
+- Support for IPAM driver options
15
+- Fixes overlay veth cleanup issue : docker/docker#18814
16
+- fixes docker/docker#19139
17
+- disable IPv6 Duplicate Address Detection
18
+
19
+## 0.5.1 (2015-12-07)
20
+- Allowing user to assign IP Address for containers
21
+- Fixes docker/docker#18214
22
+- Fixes docker/docker#18380
23
+
24
+## 0.5.0 (2015-10-30)
25
+
26
+- Docker multi-host networking exiting experimental channel
27
+- Introduced IP Address Management and IPAM drivers
28
+- DEPRECATE service discovery from default bridge network
29
+- Introduced new network UX
30
+- Support for multiple networks in bridge driver
31
+- Local persistance with boltdb
32
+
33
+## 0.4.0 (2015-07-24)
34
+
35
+- Introduce experimental version of Overlay driver
36
+- Introduce experimental version of network plugins
37
+- Introduce experimental version of network & service UX
38
+- Introduced experimental /etc/hosts based service discovery
39
+- Integrated with libkv
40
+- Improving test coverage
41
+- Fixed a bunch of issues with osl namespace mgmt
42
+
43
+## 0.3.0 (2015-05-27)
44
+ 
45
+- Introduce CNM (Container Networking Model)
46
+- Replace docker networking with CNM & Bridge driver
... ...
@@ -216,6 +216,31 @@ func (c *controller) validateHostDiscoveryConfig() bool {
216 216
 	return true
217 217
 }
218 218
 
219
+func (c *controller) clusterHostID() string {
220
+	c.Lock()
221
+	defer c.Unlock()
222
+	if c.cfg == nil || c.cfg.Cluster.Address == "" {
223
+		return ""
224
+	}
225
+	addr := strings.Split(c.cfg.Cluster.Address, ":")
226
+	return addr[0]
227
+}
228
+
229
+func (c *controller) isNodeAlive(node string) bool {
230
+	if c.discovery == nil {
231
+		return false
232
+	}
233
+
234
+	nodes := c.discovery.Fetch()
235
+	for _, n := range nodes {
236
+		if n.String() == node {
237
+			return true
238
+		}
239
+	}
240
+
241
+	return false
242
+}
243
+
219 244
 func (c *controller) initDiscovery(watcher discovery.Watcher) error {
220 245
 	if c.cfg == nil {
221 246
 		return fmt.Errorf("discovery initialization requires a valid configuration")
... ...
@@ -87,7 +87,7 @@ func (sb *sandbox) clearDefaultGW() error {
87 87
 	if err := ep.sbLeave(sb); err != nil {
88 88
 		return fmt.Errorf("container %s: endpoint leaving GW Network failed: %v", sb.containerID, err)
89 89
 	}
90
-	if err := ep.Delete(); err != nil {
90
+	if err := ep.Delete(false); err != nil {
91 91
 		return fmt.Errorf("container %s: deleting endpoint on GW Network failed: %v", sb.containerID, err)
92 92
 	}
93 93
 	return nil
... ...
@@ -68,6 +68,7 @@ type networkConfiguration struct {
68 68
 	DefaultGatewayIPv6 net.IP
69 69
 	dbIndex            uint64
70 70
 	dbExists           bool
71
+	Internal           bool
71 72
 }
72 73
 
73 74
 // endpointConfiguration represents the user specified configuration for the sandbox endpoint
... ...
@@ -280,16 +281,25 @@ func (n *bridgeNetwork) getEndpoint(eid string) (*bridgeEndpoint, error) {
280 280
 // from each of the other networks
281 281
 func (n *bridgeNetwork) isolateNetwork(others []*bridgeNetwork, enable bool) error {
282 282
 	n.Lock()
283
-	thisIface := n.config.BridgeName
283
+	thisConfig := n.config
284 284
 	n.Unlock()
285 285
 
286
+	if thisConfig.Internal {
287
+		return nil
288
+	}
289
+
286 290
 	// Install the rules to isolate this networks against each of the other networks
287 291
 	for _, o := range others {
288 292
 		o.Lock()
289
-		otherIface := o.config.BridgeName
293
+		otherConfig := o.config
290 294
 		o.Unlock()
291
-		if thisIface != otherIface {
292
-			if err := setINC(thisIface, otherIface, enable); err != nil {
295
+
296
+		if otherConfig.Internal {
297
+			continue
298
+		}
299
+
300
+		if thisConfig.BridgeName != otherConfig.BridgeName {
301
+			if err := setINC(thisConfig.BridgeName, otherConfig.BridgeName, enable); err != nil {
293 302
 				return err
294 303
 			}
295 304
 		}
... ...
@@ -483,7 +493,7 @@ func parseNetworkOptions(id string, option options.Generic) (*networkConfigurati
483 483
 
484 484
 	if val, ok := option[netlabel.Internal]; ok {
485 485
 		if internal, ok := val.(bool); ok && internal {
486
-			return nil, &driverapi.ErrNotImplemented{}
486
+			config.Internal = true
487 487
 		}
488 488
 	}
489 489
 
... ...
@@ -82,38 +82,46 @@ func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInt
82 82
 		IP:   ipnet.IP.Mask(ipnet.Mask),
83 83
 		Mask: ipnet.Mask,
84 84
 	}
85
-	if err = setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil {
86
-		return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
87
-	}
88
-	n.registerIptCleanFunc(func() error {
89
-		return setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, false)
90
-	})
85
+	if config.Internal {
86
+		if err = setupInternalNetworkRules(config.BridgeName, maskedAddrv4, true); err != nil {
87
+			return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
88
+		}
89
+		n.registerIptCleanFunc(func() error {
90
+			return setupInternalNetworkRules(config.BridgeName, maskedAddrv4, false)
91
+		})
92
+	} else {
93
+		if err = setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil {
94
+			return fmt.Errorf("Failed to Setup IP tables: %s", err.Error())
95
+		}
96
+		n.registerIptCleanFunc(func() error {
97
+			return setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, false)
98
+		})
99
+		natChain, filterChain, _, err := n.getDriverChains()
100
+		if err != nil {
101
+			return fmt.Errorf("Failed to setup IP tables, cannot acquire chain info %s", err.Error())
102
+		}
91 103
 
92
-	natChain, filterChain, _, err := n.getDriverChains()
93
-	if err != nil {
94
-		return fmt.Errorf("Failed to setup IP tables, cannot acquire chain info %s", err.Error())
95
-	}
104
+		err = iptables.ProgramChain(natChain, config.BridgeName, hairpinMode, true)
105
+		if err != nil {
106
+			return fmt.Errorf("Failed to program NAT chain: %s", err.Error())
107
+		}
96 108
 
97
-	err = iptables.ProgramChain(natChain, config.BridgeName, hairpinMode, true)
98
-	if err != nil {
99
-		return fmt.Errorf("Failed to program NAT chain: %s", err.Error())
100
-	}
109
+		err = iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, true)
110
+		if err != nil {
111
+			return fmt.Errorf("Failed to program FILTER chain: %s", err.Error())
112
+		}
101 113
 
102
-	err = iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, true)
103
-	if err != nil {
104
-		return fmt.Errorf("Failed to program FILTER chain: %s", err.Error())
114
+		n.registerIptCleanFunc(func() error {
115
+			return iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, false)
116
+		})
117
+
118
+		n.portMapper.SetIptablesChain(filterChain, n.getNetworkBridgeName())
105 119
 	}
106 120
 
107 121
 	if err := ensureJumpRule("FORWARD", IsolationChain); err != nil {
108 122
 		return err
109 123
 	}
110 124
 
111
-	n.registerIptCleanFunc(func() error {
112
-		return iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, false)
113
-	})
114
-
115
-	n.portMapper.SetIptablesChain(filterChain, n.getNetworkBridgeName())
116
-
117 125
 	return nil
118 126
 }
119 127
 
... ...
@@ -312,12 +320,26 @@ func ensureJumpRule(fromChain, toChain string) error {
312 312
 
313 313
 func removeIPChains() {
314 314
 	for _, chainInfo := range []iptables.ChainInfo{
315
-		iptables.ChainInfo{Name: DockerChain, Table: iptables.Nat},
316
-		iptables.ChainInfo{Name: DockerChain, Table: iptables.Filter},
317
-		iptables.ChainInfo{Name: IsolationChain, Table: iptables.Filter},
315
+		{Name: DockerChain, Table: iptables.Nat},
316
+		{Name: DockerChain, Table: iptables.Filter},
317
+		{Name: IsolationChain, Table: iptables.Filter},
318 318
 	} {
319 319
 		if err := chainInfo.Remove(); err != nil {
320 320
 			logrus.Warnf("Failed to remove existing iptables entries in table %s chain %s : %v", chainInfo.Table, chainInfo.Name, err)
321 321
 		}
322 322
 	}
323 323
 }
324
+
325
+func setupInternalNetworkRules(bridgeIface string, addr net.Addr, insert bool) error {
326
+	var (
327
+		inDropRule  = iptRule{table: iptables.Filter, chain: IsolationChain, args: []string{"-i", bridgeIface, "!", "-d", addr.String(), "-j", "DROP"}}
328
+		outDropRule = iptRule{table: iptables.Filter, chain: IsolationChain, args: []string{"-o", bridgeIface, "!", "-s", addr.String(), "-j", "DROP"}}
329
+	)
330
+	if err := programChainRule(inDropRule, "DROP INCOMING", insert); err != nil {
331
+		return err
332
+	}
333
+	if err := programChainRule(outDropRule, "DROP OUTGOING", insert); err != nil {
334
+		return err
335
+	}
336
+	return nil
337
+}
... ...
@@ -41,7 +41,7 @@ type Endpoint interface {
41 41
 	DriverInfo() (map[string]interface{}, error)
42 42
 
43 43
 	// Delete and detaches this endpoint from the network.
44
-	Delete() error
44
+	Delete(force bool) error
45 45
 }
46 46
 
47 47
 // EndpointOption is a option setter function type used to pass varios options to Network
... ...
@@ -56,6 +56,7 @@ type endpoint struct {
56 56
 	iface             *endpointInterface
57 57
 	joinInfo          *endpointJoinInfo
58 58
 	sandboxID         string
59
+	locator           string
59 60
 	exposedPorts      []types.TransportPort
60 61
 	anonymous         bool
61 62
 	disableResolution bool
... ...
@@ -84,6 +85,7 @@ func (ep *endpoint) MarshalJSON() ([]byte, error) {
84 84
 		epMap["generic"] = ep.generic
85 85
 	}
86 86
 	epMap["sandbox"] = ep.sandboxID
87
+	epMap["locator"] = ep.locator
87 88
 	epMap["anonymous"] = ep.anonymous
88 89
 	epMap["disableResolution"] = ep.disableResolution
89 90
 	epMap["myAliases"] = ep.myAliases
... ...
@@ -167,6 +169,9 @@ func (ep *endpoint) UnmarshalJSON(b []byte) (err error) {
167 167
 	if v, ok := epMap["disableResolution"]; ok {
168 168
 		ep.disableResolution = v.(bool)
169 169
 	}
170
+	if l, ok := epMap["locator"]; ok {
171
+		ep.locator = l.(string)
172
+	}
170 173
 	ma, _ := json.Marshal(epMap["myAliases"])
171 174
 	var myAliases []string
172 175
 	json.Unmarshal(ma, &myAliases)
... ...
@@ -186,6 +191,7 @@ func (ep *endpoint) CopyTo(o datastore.KVObject) error {
186 186
 	dstEp.name = ep.name
187 187
 	dstEp.id = ep.id
188 188
 	dstEp.sandboxID = ep.sandboxID
189
+	dstEp.locator = ep.locator
189 190
 	dstEp.dbIndex = ep.dbIndex
190 191
 	dstEp.dbExists = ep.dbExists
191 192
 	dstEp.anonymous = ep.anonymous
... ...
@@ -600,7 +606,19 @@ func (ep *endpoint) sbLeave(sbox Sandbox, options ...EndpointOption) error {
600 600
 	return sb.clearDefaultGW()
601 601
 }
602 602
 
603
-func (ep *endpoint) Delete() error {
603
+func (n *network) validateForceDelete(locator string) error {
604
+	if n.Scope() == datastore.LocalScope {
605
+		return nil
606
+	}
607
+
608
+	if locator == "" {
609
+		return fmt.Errorf("invalid endpoint locator identifier")
610
+	}
611
+
612
+	return nil
613
+}
614
+
615
+func (ep *endpoint) Delete(force bool) error {
604 616
 	var err error
605 617
 	n, err := ep.getNetworkFromStore()
606 618
 	if err != nil {
... ...
@@ -615,18 +633,33 @@ func (ep *endpoint) Delete() error {
615 615
 	ep.Lock()
616 616
 	epid := ep.id
617 617
 	name := ep.name
618
-	sb, _ := n.getController().SandboxByID(ep.sandboxID)
619
-	if sb != nil {
620
-		ep.Unlock()
618
+	sbid := ep.sandboxID
619
+	locator := ep.locator
620
+	ep.Unlock()
621
+
622
+	if force {
623
+		if err = n.validateForceDelete(locator); err != nil {
624
+			return fmt.Errorf("unable to force delete endpoint %s: %v", name, err)
625
+		}
626
+	}
627
+
628
+	sb, _ := n.getController().SandboxByID(sbid)
629
+	if sb != nil && !force {
621 630
 		return &ActiveContainerError{name: name, id: epid}
622 631
 	}
623
-	ep.Unlock()
632
+
633
+	if sb != nil {
634
+		if e := ep.sbLeave(sb); e != nil {
635
+			log.Warnf("failed to leave sandbox for endpoint %s : %v", name, e)
636
+		}
637
+	}
624 638
 
625 639
 	if err = n.getController().deleteFromStore(ep); err != nil {
626 640
 		return err
627 641
 	}
642
+
628 643
 	defer func() {
629
-		if err != nil {
644
+		if err != nil && !force {
630 645
 			ep.dbExists = false
631 646
 			if e := n.getController().updateToStore(ep); e != nil {
632 647
 				log.Warnf("failed to recreate endpoint in store %s : %v", name, e)
... ...
@@ -634,11 +667,11 @@ func (ep *endpoint) Delete() error {
634 634
 		}
635 635
 	}()
636 636
 
637
-	if err = n.getEpCnt().DecEndpointCnt(); err != nil {
637
+	if err = n.getEpCnt().DecEndpointCnt(); err != nil && !force {
638 638
 		return err
639 639
 	}
640 640
 	defer func() {
641
-		if err != nil {
641
+		if err != nil && !force {
642 642
 			if e := n.getEpCnt().IncEndpointCnt(); e != nil {
643 643
 				log.Warnf("failed to update network %s : %v", n.name, e)
644 644
 			}
... ...
@@ -648,7 +681,7 @@ func (ep *endpoint) Delete() error {
648 648
 	// unwatch for service records
649 649
 	n.getController().unWatchSvcRecord(ep)
650 650
 
651
-	if err = ep.deleteEndpoint(); err != nil {
651
+	if err = ep.deleteEndpoint(); err != nil && !force {
652 652
 		return err
653 653
 	}
654 654
 
... ...
@@ -683,8 +716,8 @@ func (ep *endpoint) deleteEndpoint() error {
683 683
 }
684 684
 
685 685
 func (ep *endpoint) getSandbox() (*sandbox, bool) {
686
-	ep.Lock()
687 686
 	c := ep.network.getController()
687
+	ep.Lock()
688 688
 	sid := ep.sandboxID
689 689
 	ep.Unlock()
690 690
 
... ...
@@ -923,7 +956,7 @@ func (c *controller) cleanupLocalEndpoints() {
923 923
 		}
924 924
 
925 925
 		for _, ep := range epl {
926
-			if err := ep.Delete(); err != nil {
926
+			if err := ep.Delete(false); err != nil {
927 927
 				log.Warnf("Could not delete local endpoint %s during endpoint cleanup: %v", ep.name, err)
928 928
 			}
929 929
 		}
... ...
@@ -182,6 +182,6 @@ func Update(path, IP, hostname string) error {
182 182
 	if err != nil {
183 183
 		return err
184 184
 	}
185
-	var re = regexp.MustCompile(fmt.Sprintf("(\\S*)(\\t%s)", regexp.QuoteMeta(hostname)))
186
-	return ioutil.WriteFile(path, re.ReplaceAll(old, []byte(IP+"$2")), 0644)
185
+	var re = regexp.MustCompile(fmt.Sprintf("(\\S*)(\\t%s)(\\s|\\.)", regexp.QuoteMeta(hostname)))
186
+	return ioutil.WriteFile(path, re.ReplaceAll(old, []byte(IP+"$2"+"$3")), 0644)
187 187
 }
... ...
@@ -681,6 +681,7 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi
681 681
 	// Initialize ep.network with a possibly stale copy of n. We need this to get network from
682 682
 	// store. But once we get it from store we will have the most uptodate copy possible.
683 683
 	ep.network = n
684
+	ep.locator = n.getController().clusterHostID()
684 685
 	ep.network, err = ep.getNetworkFromStore()
685 686
 	if err != nil {
686 687
 		return nil, fmt.Errorf("failed to get network during CreateEndpoint: %v", err)
... ...
@@ -198,7 +198,7 @@ func (sb *sandbox) Delete() error {
198 198
 			log.Warnf("Failed detaching sandbox %s from endpoint %s: %v\n", sb.ID(), ep.ID(), err)
199 199
 		}
200 200
 
201
-		if err := ep.Delete(); err != nil {
201
+		if err := ep.Delete(false); err != nil {
202 202
 			log.Warnf("Failed deleting endpoint %s: %v\n", ep.ID(), err)
203 203
 		}
204 204
 	}
... ...
@@ -129,7 +129,9 @@ func (c *controller) getNetworksFromStore() ([]*network, error) {
129 129
 
130 130
 		for _, kvo := range kvol {
131 131
 			n := kvo.(*network)
132
+			n.Lock()
132 133
 			n.ctrlr = c
134
+			n.Unlock()
133 135
 
134 136
 			ec := &endpointCnt{n: n}
135 137
 			err = store.GetObject(datastore.Key(ec.Key()...), ec)