- 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>
This commit is contained in:
Madhu Venugopal 2016-01-12 11:33:16 -08:00
Родитель 45211af702
Коммит 537089481f
11 изменённых файлов: 188 добавлений и 48 удалений

Просмотреть файл

@ -26,7 +26,7 @@ clone git github.com/docker/engine-api v0.1.3
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

47
vendor/src/github.com/docker/libnetwork/CHANGELOG.md поставляемый Normal file
Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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
}
}

Просмотреть файл

@ -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
}

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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