- 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>
| ... | ... |
@@ -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) |