diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go index 7ac05d771c..870adfe7e8 100644 --- a/daemon/container_operations_unix.go +++ b/daemon/container_operations_unix.go @@ -792,7 +792,7 @@ func (daemon *Daemon) connectToNetwork(container *container.Container, idOrName } defer func() { if err != nil { - if e := ep.Delete(); e != nil { + if e := ep.Delete(false); e != nil { logrus.Warnf("Could not rollback container connection to network %s", idOrName) } } @@ -894,7 +894,7 @@ func disconnectFromNetwork(container *container.Container, n libnetwork.Network) return fmt.Errorf("container %s failed to leave network %s: %v", container.ID, n.Name(), err) } - if err := ep.Delete(); err != nil { + if err := ep.Delete(false); err != nil { return fmt.Errorf("endpoint delete failed for container %s on network %s: %v", container.ID, n.Name(), err) } diff --git a/hack/vendor.sh b/hack/vendor.sh index d6f04dea3e..9e94cfc596 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -26,7 +26,7 @@ clone git github.com/docker/engine-api v0.2.1 clone git github.com/RackSec/srslog 6eb773f331e46fbba8eecb8e794e635e75fc04de #get libnetwork packages -clone git github.com/docker/libnetwork c8ec4bd24e1e76feb4f79e3924c68cd2ce89938a +clone git github.com/docker/libnetwork v0.5.4 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4 diff --git a/vendor/src/github.com/docker/libnetwork/CHANGELOG.md b/vendor/src/github.com/docker/libnetwork/CHANGELOG.md new file mode 100644 index 0000000000..dc21f351f3 --- /dev/null +++ b/vendor/src/github.com/docker/libnetwork/CHANGELOG.md @@ -0,0 +1,47 @@ +# Changelog + +## 0.5.4 (2016-01-12) +- Removed the isNodeAlive protection when user forces an endpoint delete + +## 0.5.3 (2016-01-12) +- 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 + +## 0.5.2 (2016-01-08) +- Embedded DNS replacing /etc/hosts based Service Discovery +- Container local alias and Network-scoped alias support +- Backend support for internal network mode +- Support for IPAM driver options +- Fixes overlay veth cleanup issue : docker/docker#18814 +- fixes docker/docker#19139 +- disable IPv6 Duplicate Address Detection + +## 0.5.1 (2015-12-07) +- Allowing user to assign IP Address for containers +- Fixes docker/docker#18214 +- Fixes docker/docker#18380 + +## 0.5.0 (2015-10-30) + +- Docker multi-host networking exiting experimental channel +- Introduced IP Address Management and IPAM drivers +- DEPRECATE service discovery from default bridge network +- Introduced new network UX +- Support for multiple networks in bridge driver +- Local persistance with boltdb + +## 0.4.0 (2015-07-24) + +- Introduce experimental version of Overlay driver +- Introduce experimental version of network plugins +- Introduce experimental version of network & service UX +- Introduced experimental /etc/hosts based service discovery +- Integrated with libkv +- Improving test coverage +- Fixed a bunch of issues with osl namespace mgmt + +## 0.3.0 (2015-05-27) + +- Introduce CNM (Container Networking Model) +- Replace docker networking with CNM & Bridge driver diff --git a/vendor/src/github.com/docker/libnetwork/controller.go b/vendor/src/github.com/docker/libnetwork/controller.go index 1cd200f48f..7efc409356 100644 --- a/vendor/src/github.com/docker/libnetwork/controller.go +++ b/vendor/src/github.com/docker/libnetwork/controller.go @@ -216,6 +216,31 @@ func (c *controller) validateHostDiscoveryConfig() bool { return true } +func (c *controller) clusterHostID() string { + c.Lock() + defer c.Unlock() + if c.cfg == nil || c.cfg.Cluster.Address == "" { + return "" + } + addr := strings.Split(c.cfg.Cluster.Address, ":") + return addr[0] +} + +func (c *controller) isNodeAlive(node string) bool { + if c.discovery == nil { + return false + } + + nodes := c.discovery.Fetch() + for _, n := range nodes { + if n.String() == node { + return true + } + } + + return false +} + func (c *controller) initDiscovery(watcher discovery.Watcher) error { if c.cfg == nil { return fmt.Errorf("discovery initialization requires a valid configuration") diff --git a/vendor/src/github.com/docker/libnetwork/default_gateway.go b/vendor/src/github.com/docker/libnetwork/default_gateway.go index d9277ba577..bfd7b725d3 100644 --- a/vendor/src/github.com/docker/libnetwork/default_gateway.go +++ b/vendor/src/github.com/docker/libnetwork/default_gateway.go @@ -87,7 +87,7 @@ func (sb *sandbox) clearDefaultGW() error { if err := ep.sbLeave(sb); err != nil { return fmt.Errorf("container %s: endpoint leaving GW Network failed: %v", sb.containerID, err) } - if err := ep.Delete(); err != nil { + if err := ep.Delete(false); err != nil { return fmt.Errorf("container %s: deleting endpoint on GW Network failed: %v", sb.containerID, err) } return nil diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go index dbe3a3e919..7b2bdebd20 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go @@ -68,6 +68,7 @@ type networkConfiguration struct { DefaultGatewayIPv6 net.IP dbIndex uint64 dbExists bool + Internal bool } // endpointConfiguration represents the user specified configuration for the sandbox endpoint @@ -280,16 +281,25 @@ func (n *bridgeNetwork) getEndpoint(eid string) (*bridgeEndpoint, error) { // from each of the other networks func (n *bridgeNetwork) isolateNetwork(others []*bridgeNetwork, enable bool) error { n.Lock() - thisIface := n.config.BridgeName + thisConfig := n.config n.Unlock() + if thisConfig.Internal { + return nil + } + // Install the rules to isolate this networks against each of the other networks for _, o := range others { o.Lock() - otherIface := o.config.BridgeName + otherConfig := o.config o.Unlock() - if thisIface != otherIface { - if err := setINC(thisIface, otherIface, enable); err != nil { + + if otherConfig.Internal { + continue + } + + if thisConfig.BridgeName != otherConfig.BridgeName { + if err := setINC(thisConfig.BridgeName, otherConfig.BridgeName, enable); err != nil { return err } } @@ -483,7 +493,7 @@ func parseNetworkOptions(id string, option options.Generic) (*networkConfigurati if val, ok := option[netlabel.Internal]; ok { if internal, ok := val.(bool); ok && internal { - return nil, &driverapi.ErrNotImplemented{} + config.Internal = true } } diff --git a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go b/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go index 60329c8f43..1d523d6c2c 100644 --- a/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go +++ b/vendor/src/github.com/docker/libnetwork/drivers/bridge/setup_ip_tables.go @@ -82,38 +82,46 @@ func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInt IP: ipnet.IP.Mask(ipnet.Mask), Mask: ipnet.Mask, } - if err = setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil { - return fmt.Errorf("Failed to Setup IP tables: %s", err.Error()) - } - n.registerIptCleanFunc(func() error { - return setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, false) - }) + if config.Internal { + if err = setupInternalNetworkRules(config.BridgeName, maskedAddrv4, true); err != nil { + return fmt.Errorf("Failed to Setup IP tables: %s", err.Error()) + } + n.registerIptCleanFunc(func() error { + return setupInternalNetworkRules(config.BridgeName, maskedAddrv4, false) + }) + } else { + if err = setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, true); err != nil { + return fmt.Errorf("Failed to Setup IP tables: %s", err.Error()) + } + n.registerIptCleanFunc(func() error { + return setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, false) + }) + natChain, filterChain, _, err := n.getDriverChains() + if err != nil { + return fmt.Errorf("Failed to setup IP tables, cannot acquire chain info %s", err.Error()) + } - natChain, filterChain, _, err := n.getDriverChains() - if err != nil { - return fmt.Errorf("Failed to setup IP tables, cannot acquire chain info %s", err.Error()) - } + err = iptables.ProgramChain(natChain, config.BridgeName, hairpinMode, true) + if err != nil { + return fmt.Errorf("Failed to program NAT chain: %s", err.Error()) + } - err = iptables.ProgramChain(natChain, config.BridgeName, hairpinMode, true) - if err != nil { - return fmt.Errorf("Failed to program NAT chain: %s", err.Error()) - } + err = iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, true) + if err != nil { + return fmt.Errorf("Failed to program FILTER chain: %s", err.Error()) + } - err = iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, true) - if err != nil { - return fmt.Errorf("Failed to program FILTER chain: %s", err.Error()) + n.registerIptCleanFunc(func() error { + return iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, false) + }) + + n.portMapper.SetIptablesChain(filterChain, n.getNetworkBridgeName()) } if err := ensureJumpRule("FORWARD", IsolationChain); err != nil { return err } - n.registerIptCleanFunc(func() error { - return iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, false) - }) - - n.portMapper.SetIptablesChain(filterChain, n.getNetworkBridgeName()) - return nil } @@ -312,12 +320,26 @@ func ensureJumpRule(fromChain, toChain string) error { func removeIPChains() { for _, chainInfo := range []iptables.ChainInfo{ - iptables.ChainInfo{Name: DockerChain, Table: iptables.Nat}, - iptables.ChainInfo{Name: DockerChain, Table: iptables.Filter}, - iptables.ChainInfo{Name: IsolationChain, Table: iptables.Filter}, + {Name: DockerChain, Table: iptables.Nat}, + {Name: DockerChain, Table: iptables.Filter}, + {Name: IsolationChain, Table: iptables.Filter}, } { if err := chainInfo.Remove(); err != nil { logrus.Warnf("Failed to remove existing iptables entries in table %s chain %s : %v", chainInfo.Table, chainInfo.Name, err) } } } + +func setupInternalNetworkRules(bridgeIface string, addr net.Addr, insert bool) error { + var ( + inDropRule = iptRule{table: iptables.Filter, chain: IsolationChain, args: []string{"-i", bridgeIface, "!", "-d", addr.String(), "-j", "DROP"}} + outDropRule = iptRule{table: iptables.Filter, chain: IsolationChain, args: []string{"-o", bridgeIface, "!", "-s", addr.String(), "-j", "DROP"}} + ) + if err := programChainRule(inDropRule, "DROP INCOMING", insert); err != nil { + return err + } + if err := programChainRule(outDropRule, "DROP OUTGOING", insert); err != nil { + return err + } + return nil +} diff --git a/vendor/src/github.com/docker/libnetwork/endpoint.go b/vendor/src/github.com/docker/libnetwork/endpoint.go index de08c4210f..88312e9c15 100644 --- a/vendor/src/github.com/docker/libnetwork/endpoint.go +++ b/vendor/src/github.com/docker/libnetwork/endpoint.go @@ -41,7 +41,7 @@ type Endpoint interface { DriverInfo() (map[string]interface{}, error) // Delete and detaches this endpoint from the network. - Delete() error + Delete(force bool) error } // EndpointOption is a option setter function type used to pass varios options to Network @@ -56,6 +56,7 @@ type endpoint struct { iface *endpointInterface joinInfo *endpointJoinInfo sandboxID string + locator string exposedPorts []types.TransportPort anonymous bool disableResolution bool @@ -84,6 +85,7 @@ func (ep *endpoint) MarshalJSON() ([]byte, error) { epMap["generic"] = ep.generic } epMap["sandbox"] = ep.sandboxID + epMap["locator"] = ep.locator epMap["anonymous"] = ep.anonymous epMap["disableResolution"] = ep.disableResolution epMap["myAliases"] = ep.myAliases @@ -167,6 +169,9 @@ func (ep *endpoint) UnmarshalJSON(b []byte) (err error) { if v, ok := epMap["disableResolution"]; ok { ep.disableResolution = v.(bool) } + if l, ok := epMap["locator"]; ok { + ep.locator = l.(string) + } ma, _ := json.Marshal(epMap["myAliases"]) var myAliases []string json.Unmarshal(ma, &myAliases) @@ -186,6 +191,7 @@ func (ep *endpoint) CopyTo(o datastore.KVObject) error { dstEp.name = ep.name dstEp.id = ep.id dstEp.sandboxID = ep.sandboxID + dstEp.locator = ep.locator dstEp.dbIndex = ep.dbIndex dstEp.dbExists = ep.dbExists dstEp.anonymous = ep.anonymous @@ -600,7 +606,19 @@ func (ep *endpoint) sbLeave(sbox Sandbox, options ...EndpointOption) error { return sb.clearDefaultGW() } -func (ep *endpoint) Delete() error { +func (n *network) validateForceDelete(locator string) error { + if n.Scope() == datastore.LocalScope { + return nil + } + + if locator == "" { + return fmt.Errorf("invalid endpoint locator identifier") + } + + return nil +} + +func (ep *endpoint) Delete(force bool) error { var err error n, err := ep.getNetworkFromStore() if err != nil { @@ -615,18 +633,33 @@ func (ep *endpoint) Delete() error { ep.Lock() epid := ep.id name := ep.name - sb, _ := n.getController().SandboxByID(ep.sandboxID) - if sb != nil { - ep.Unlock() + sbid := ep.sandboxID + locator := ep.locator + ep.Unlock() + + if force { + if err = n.validateForceDelete(locator); err != nil { + return fmt.Errorf("unable to force delete endpoint %s: %v", name, err) + } + } + + sb, _ := n.getController().SandboxByID(sbid) + if sb != nil && !force { return &ActiveContainerError{name: name, id: epid} } - ep.Unlock() + + if sb != nil { + if e := ep.sbLeave(sb); e != nil { + log.Warnf("failed to leave sandbox for endpoint %s : %v", name, e) + } + } if err = n.getController().deleteFromStore(ep); err != nil { return err } + defer func() { - if err != nil { + if err != nil && !force { ep.dbExists = false if e := n.getController().updateToStore(ep); e != nil { log.Warnf("failed to recreate endpoint in store %s : %v", name, e) @@ -634,11 +667,11 @@ func (ep *endpoint) Delete() error { } }() - if err = n.getEpCnt().DecEndpointCnt(); err != nil { + if err = n.getEpCnt().DecEndpointCnt(); err != nil && !force { return err } defer func() { - if err != nil { + if err != nil && !force { if e := n.getEpCnt().IncEndpointCnt(); e != nil { log.Warnf("failed to update network %s : %v", n.name, e) } @@ -648,7 +681,7 @@ func (ep *endpoint) Delete() error { // unwatch for service records n.getController().unWatchSvcRecord(ep) - if err = ep.deleteEndpoint(); err != nil { + if err = ep.deleteEndpoint(); err != nil && !force { return err } @@ -683,8 +716,8 @@ func (ep *endpoint) deleteEndpoint() error { } func (ep *endpoint) getSandbox() (*sandbox, bool) { - ep.Lock() c := ep.network.getController() + ep.Lock() sid := ep.sandboxID ep.Unlock() @@ -923,7 +956,7 @@ func (c *controller) cleanupLocalEndpoints() { } for _, ep := range epl { - if err := ep.Delete(); err != nil { + if err := ep.Delete(false); err != nil { log.Warnf("Could not delete local endpoint %s during endpoint cleanup: %v", ep.name, err) } } diff --git a/vendor/src/github.com/docker/libnetwork/etchosts/etchosts.go b/vendor/src/github.com/docker/libnetwork/etchosts/etchosts.go index 256a89dfa8..5f68372b90 100644 --- a/vendor/src/github.com/docker/libnetwork/etchosts/etchosts.go +++ b/vendor/src/github.com/docker/libnetwork/etchosts/etchosts.go @@ -182,6 +182,6 @@ func Update(path, IP, hostname string) error { if err != nil { return err } - var re = regexp.MustCompile(fmt.Sprintf("(\\S*)(\\t%s)", regexp.QuoteMeta(hostname))) - return ioutil.WriteFile(path, re.ReplaceAll(old, []byte(IP+"$2")), 0644) + var re = regexp.MustCompile(fmt.Sprintf("(\\S*)(\\t%s)(\\s|\\.)", regexp.QuoteMeta(hostname))) + return ioutil.WriteFile(path, re.ReplaceAll(old, []byte(IP+"$2"+"$3")), 0644) } diff --git a/vendor/src/github.com/docker/libnetwork/network.go b/vendor/src/github.com/docker/libnetwork/network.go index 2fe49062f0..e582767c18 100644 --- a/vendor/src/github.com/docker/libnetwork/network.go +++ b/vendor/src/github.com/docker/libnetwork/network.go @@ -681,6 +681,7 @@ func (n *network) CreateEndpoint(name string, options ...EndpointOption) (Endpoi // Initialize ep.network with a possibly stale copy of n. We need this to get network from // store. But once we get it from store we will have the most uptodate copy possible. ep.network = n + ep.locator = n.getController().clusterHostID() ep.network, err = ep.getNetworkFromStore() if err != nil { return nil, fmt.Errorf("failed to get network during CreateEndpoint: %v", err) diff --git a/vendor/src/github.com/docker/libnetwork/sandbox.go b/vendor/src/github.com/docker/libnetwork/sandbox.go index 2f69897d12..8977cf349f 100644 --- a/vendor/src/github.com/docker/libnetwork/sandbox.go +++ b/vendor/src/github.com/docker/libnetwork/sandbox.go @@ -198,7 +198,7 @@ func (sb *sandbox) Delete() error { log.Warnf("Failed detaching sandbox %s from endpoint %s: %v\n", sb.ID(), ep.ID(), err) } - if err := ep.Delete(); err != nil { + if err := ep.Delete(false); err != nil { log.Warnf("Failed deleting endpoint %s: %v\n", ep.ID(), err) } } diff --git a/vendor/src/github.com/docker/libnetwork/store.go b/vendor/src/github.com/docker/libnetwork/store.go index a7682e5af6..be3e8ae638 100644 --- a/vendor/src/github.com/docker/libnetwork/store.go +++ b/vendor/src/github.com/docker/libnetwork/store.go @@ -129,7 +129,9 @@ func (c *controller) getNetworksFromStore() ([]*network, error) { for _, kvo := range kvol { n := kvo.(*network) + n.Lock() n.ctrlr = c + n.Unlock() ec := &endpointCnt{n: n} err = store.GetObject(datastore.Key(ec.Key()...), ec)