Vendoring libnetwork
- 49c24217054e269aad3dbfd81ee32780b104dd84 Signed-off-by: Alessandro Boch <aboch@docker.com>
This commit is contained in:
parent
3a8d694e01
commit
19b063e740
8 changed files with 172 additions and 96 deletions
|
@ -25,7 +25,7 @@ clone git github.com/docker/go-connections v0.1.2
|
|||
clone git github.com/docker/engine-api v0.1.3
|
||||
|
||||
#get libnetwork packages
|
||||
clone git github.com/docker/libnetwork 9f0563ea8f430d8828553aac97161cbff4056436
|
||||
clone git github.com/docker/libnetwork 49c24217054e269aad3dbfd81ee32780b104dd84
|
||||
clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
|
||||
clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
|
||||
clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
|
||||
|
|
|
@ -15,6 +15,11 @@ There are many networking solutions available to suit a broad range of use-cases
|
|||
|
||||
|
||||
```go
|
||||
func main() {
|
||||
if reexec.Init() {
|
||||
return
|
||||
}
|
||||
|
||||
// Select and configure the network driver
|
||||
networkType := "bridge"
|
||||
|
||||
|
@ -24,14 +29,14 @@ There are many networking solutions available to suit a broad range of use-cases
|
|||
genericOption[netlabel.GenericData] = driverOptions
|
||||
controller, err := libnetwork.New(config.OptionDriverConfig(networkType, genericOption))
|
||||
if err != nil {
|
||||
return
|
||||
log.Fatalf("libnetwork.New: %s", err)
|
||||
}
|
||||
|
||||
// Create a network for containers to join.
|
||||
// NewNetwork accepts Variadic optional arguments that libnetwork and Drivers can use.
|
||||
network, err := controller.NewNetwork(networkType, "network1")
|
||||
if err != nil {
|
||||
return
|
||||
log.Fatalf("controller.NewNetwork: %s", err)
|
||||
}
|
||||
|
||||
// For each new container: allocate IP and interfaces. The returned network
|
||||
|
@ -40,7 +45,7 @@ There are many networking solutions available to suit a broad range of use-cases
|
|||
// from the returned endpoint.
|
||||
ep, err := network.CreateEndpoint("Endpoint1")
|
||||
if err != nil {
|
||||
return
|
||||
log.Fatalf("network.CreateEndpoint: %s", err)
|
||||
}
|
||||
|
||||
// Create the sandbox for the container.
|
||||
|
@ -48,22 +53,29 @@ There are many networking solutions available to suit a broad range of use-cases
|
|||
sbx, err := controller.NewSandbox("container1",
|
||||
libnetwork.OptionHostname("test"),
|
||||
libnetwork.OptionDomainname("docker.io"))
|
||||
if err != nil {
|
||||
log.Fatalf("controller.NewSandbox: %s", err)
|
||||
}
|
||||
|
||||
// A sandbox can join the endpoint via the join api.
|
||||
err = ep.Join(sbx)
|
||||
if err != nil {
|
||||
return
|
||||
log.Fatalf("ep.Join: %s", err)
|
||||
}
|
||||
|
||||
// libnetwork client can check the endpoint's operational data via the Info() API
|
||||
epInfo, err := ep.DriverInfo()
|
||||
mapData, ok := epInfo[netlabel.PortMap]
|
||||
if ok {
|
||||
portMapping, ok := mapData.([]types.PortBinding)
|
||||
if ok {
|
||||
fmt.Printf("Current port mapping for endpoint %s: %v", ep.Name(), portMapping)
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalf("ep.DriverInfo: %s", err)
|
||||
}
|
||||
|
||||
macAddress, ok := epInfo[netlabel.MacAddress]
|
||||
if !ok {
|
||||
log.Fatalf("failed to get mac address from endpoint info")
|
||||
}
|
||||
|
||||
fmt.Printf("Joined endpoint %s (%s) to sandbox %s (%s)\n", ep.Name(), macAddress, sbx.ContainerID(), sbx.Key())
|
||||
}
|
||||
```
|
||||
|
||||
## Future
|
||||
|
|
|
@ -106,12 +106,13 @@ type bridgeNetwork struct {
|
|||
}
|
||||
|
||||
type driver struct {
|
||||
config *configuration
|
||||
network *bridgeNetwork
|
||||
natChain *iptables.ChainInfo
|
||||
filterChain *iptables.ChainInfo
|
||||
networks map[string]*bridgeNetwork
|
||||
store datastore.DataStore
|
||||
config *configuration
|
||||
network *bridgeNetwork
|
||||
natChain *iptables.ChainInfo
|
||||
filterChain *iptables.ChainInfo
|
||||
isolationChain *iptables.ChainInfo
|
||||
networks map[string]*bridgeNetwork
|
||||
store datastore.DataStore
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
|
@ -244,15 +245,15 @@ func (n *bridgeNetwork) registerIptCleanFunc(clean iptableCleanFunc) {
|
|||
n.iptCleanFuncs = append(n.iptCleanFuncs, clean)
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) getDriverChains() (*iptables.ChainInfo, *iptables.ChainInfo, error) {
|
||||
func (n *bridgeNetwork) getDriverChains() (*iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, error) {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
if n.driver == nil {
|
||||
return nil, nil, types.BadRequestErrorf("no driver found")
|
||||
return nil, nil, nil, types.BadRequestErrorf("no driver found")
|
||||
}
|
||||
|
||||
return n.driver.natChain, n.driver.filterChain, nil
|
||||
return n.driver.natChain, n.driver.filterChain, n.driver.isolationChain, nil
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) getNetworkBridgeName() string {
|
||||
|
@ -282,26 +283,16 @@ 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()
|
||||
thisV4 := n.bridge.bridgeIPv4
|
||||
thisV6 := getV6Network(n.config, n.bridge)
|
||||
thisIface := n.config.BridgeName
|
||||
n.Unlock()
|
||||
|
||||
// Install the rules to isolate this networks against each of the other networks
|
||||
for _, o := range others {
|
||||
o.Lock()
|
||||
otherV4 := o.bridge.bridgeIPv4
|
||||
otherV6 := getV6Network(o.config, o.bridge)
|
||||
otherIface := o.config.BridgeName
|
||||
o.Unlock()
|
||||
|
||||
if !types.CompareIPNet(thisV4, otherV4) {
|
||||
// It's ok to pass a.b.c.d/x, iptables will ignore the host subnet bits
|
||||
if err := setINC(thisV4.String(), otherV4.String(), enable); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if thisV6 != nil && otherV6 != nil && !types.CompareIPNet(thisV6, otherV6) {
|
||||
if err := setINC(thisV6.String(), otherV6.String(), enable); err != nil {
|
||||
if thisIface != otherIface {
|
||||
if err := setINC(thisIface, otherIface, enable); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -347,9 +338,11 @@ func (c *networkConfiguration) conflictsWithNetworks(id string, others []*bridge
|
|||
|
||||
func (d *driver) configure(option map[string]interface{}) error {
|
||||
var (
|
||||
config *configuration
|
||||
err error
|
||||
natChain, filterChain *iptables.ChainInfo
|
||||
config *configuration
|
||||
err error
|
||||
natChain *iptables.ChainInfo
|
||||
filterChain *iptables.ChainInfo
|
||||
isolationChain *iptables.ChainInfo
|
||||
)
|
||||
|
||||
genericData, ok := option[netlabel.GenericData]
|
||||
|
@ -378,7 +371,7 @@ func (d *driver) configure(option map[string]interface{}) error {
|
|||
}
|
||||
|
||||
if config.EnableIPTables {
|
||||
natChain, filterChain, err = setupIPChains(config)
|
||||
natChain, filterChain, isolationChain, err = setupIPChains(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -387,6 +380,7 @@ func (d *driver) configure(option map[string]interface{}) error {
|
|||
d.Lock()
|
||||
d.natChain = natChain
|
||||
d.filterChain = filterChain
|
||||
d.isolationChain = isolationChain
|
||||
d.config = config
|
||||
d.Unlock()
|
||||
|
||||
|
|
|
@ -11,35 +11,52 @@ import (
|
|||
|
||||
// DockerChain: DOCKER iptable chain name
|
||||
const (
|
||||
DockerChain = "DOCKER"
|
||||
DockerChain = "DOCKER"
|
||||
IsolationChain = "DOCKER-ISOLATION"
|
||||
)
|
||||
|
||||
func setupIPChains(config *configuration) (*iptables.ChainInfo, *iptables.ChainInfo, error) {
|
||||
func setupIPChains(config *configuration) (*iptables.ChainInfo, *iptables.ChainInfo, *iptables.ChainInfo, error) {
|
||||
// Sanity check.
|
||||
if config.EnableIPTables == false {
|
||||
return nil, nil, fmt.Errorf("Cannot create new chains, EnableIPTable is disabled")
|
||||
return nil, nil, nil, fmt.Errorf("cannot create new chains, EnableIPTable is disabled")
|
||||
}
|
||||
|
||||
hairpinMode := !config.EnableUserlandProxy
|
||||
|
||||
natChain, err := iptables.NewChain(DockerChain, iptables.Nat, hairpinMode)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Failed to create NAT chain: %s", err.Error())
|
||||
return nil, nil, nil, fmt.Errorf("failed to create NAT chain: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if err := iptables.RemoveExistingChain(DockerChain, iptables.Nat); err != nil {
|
||||
logrus.Warnf("Failed on removing iptables NAT chain on cleanup: %v", err)
|
||||
logrus.Warnf("failed on removing iptables NAT chain on cleanup: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
filterChain, err := iptables.NewChain(DockerChain, iptables.Filter, hairpinMode)
|
||||
filterChain, err := iptables.NewChain(DockerChain, iptables.Filter, false)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Failed to create FILTER chain: %s", err.Error())
|
||||
return nil, nil, nil, fmt.Errorf("failed to create FILTER chain: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if err := iptables.RemoveExistingChain(DockerChain, iptables.Filter); err != nil {
|
||||
logrus.Warnf("failed on removing iptables FILTER chain on cleanup: %v", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
isolationChain, err := iptables.NewChain(IsolationChain, iptables.Filter, false)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("failed to create FILTER isolation chain: %v", err)
|
||||
}
|
||||
|
||||
return natChain, filterChain, nil
|
||||
if err := addReturnRule(IsolationChain); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return natChain, filterChain, isolationChain, nil
|
||||
}
|
||||
|
||||
func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInterface) error {
|
||||
|
@ -72,7 +89,7 @@ func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInt
|
|||
return setupIPTablesInternal(config.BridgeName, maskedAddrv4, config.EnableICC, config.EnableIPMasquerade, hairpinMode, false)
|
||||
})
|
||||
|
||||
natChain, filterChain, err := n.getDriverChains()
|
||||
natChain, filterChain, _, err := n.getDriverChains()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to setup IP tables, cannot acquire chain info %s", err.Error())
|
||||
}
|
||||
|
@ -86,6 +103,11 @@ func (n *bridgeNetwork) setupIPTables(config *networkConfiguration, i *bridgeInt
|
|||
if err != nil {
|
||||
return fmt.Errorf("Failed to program FILTER chain: %s", err.Error())
|
||||
}
|
||||
|
||||
if err := ensureJumpRule("FORWARD", IsolationChain); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n.registerIptCleanFunc(func() error {
|
||||
return iptables.ProgramChain(filterChain, config.BridgeName, hairpinMode, false)
|
||||
})
|
||||
|
@ -166,10 +188,8 @@ func programChainRule(rule iptRule, ruleDescr string, insert bool) error {
|
|||
}
|
||||
|
||||
if condition {
|
||||
if output, err := iptables.Raw(append(prefix, rule.args...)...); err != nil {
|
||||
if err := iptables.RawCombinedOutput(append(prefix, rule.args...)...); err != nil {
|
||||
return fmt.Errorf("Unable to %s %s rule: %s", operation, ruleDescr, err.Error())
|
||||
} else if len(output) != 0 {
|
||||
return &iptables.ChainError{Chain: rule.chain, Output: output}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,20 +210,16 @@ func setIcc(bridgeIface string, iccEnable, insert bool) error {
|
|||
iptables.Raw(append([]string{"-D", chain}, acceptArgs...)...)
|
||||
|
||||
if !iptables.Exists(table, chain, dropArgs...) {
|
||||
if output, err := iptables.Raw(append([]string{"-A", chain}, dropArgs...)...); err != nil {
|
||||
if err := iptables.RawCombinedOutput(append([]string{"-A", chain}, dropArgs...)...); err != nil {
|
||||
return fmt.Errorf("Unable to prevent intercontainer communication: %s", err.Error())
|
||||
} else if len(output) != 0 {
|
||||
return fmt.Errorf("Error disabling intercontainer communication: %s", output)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iptables.Raw(append([]string{"-D", chain}, dropArgs...)...)
|
||||
|
||||
if !iptables.Exists(table, chain, acceptArgs...) {
|
||||
if output, err := iptables.Raw(append([]string{"-I", chain}, acceptArgs...)...); err != nil {
|
||||
if err := iptables.RawCombinedOutput(append([]string{"-I", chain}, acceptArgs...)...); err != nil {
|
||||
return fmt.Errorf("Unable to allow intercontainer communication: %s", err.Error())
|
||||
} else if len(output) != 0 {
|
||||
return fmt.Errorf("Error enabling intercontainer communication: %s", output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -224,11 +240,11 @@ func setIcc(bridgeIface string, iccEnable, insert bool) error {
|
|||
}
|
||||
|
||||
// Control Inter Network Communication. Install/remove only if it is not/is present.
|
||||
func setINC(network1, network2 string, enable bool) error {
|
||||
func setINC(iface1, iface2 string, enable bool) error {
|
||||
var (
|
||||
table = iptables.Filter
|
||||
chain = "FORWARD"
|
||||
args = [2][]string{{"-s", network1, "-d", network2, "-j", "DROP"}, {"-s", network2, "-d", network1, "-j", "DROP"}}
|
||||
chain = IsolationChain
|
||||
args = [2][]string{{"-i", iface1, "-o", iface2, "-j", "DROP"}, {"-i", iface2, "-o", iface1, "-j", "DROP"}}
|
||||
)
|
||||
|
||||
if enable {
|
||||
|
@ -236,10 +252,8 @@ func setINC(network1, network2 string, enable bool) error {
|
|||
if iptables.Exists(table, chain, args[i]...) {
|
||||
continue
|
||||
}
|
||||
if output, err := iptables.Raw(append([]string{"-I", chain}, args[i]...)...); err != nil {
|
||||
return fmt.Errorf("unable to add inter-network communication rule: %s", err.Error())
|
||||
} else if len(output) != 0 {
|
||||
return fmt.Errorf("error adding inter-network communication rule: %s", string(output))
|
||||
if err := iptables.RawCombinedOutput(append([]string{"-I", chain}, args[i]...)...); err != nil {
|
||||
return fmt.Errorf("unable to add inter-network communication rule: %v", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -247,13 +261,51 @@ func setINC(network1, network2 string, enable bool) error {
|
|||
if !iptables.Exists(table, chain, args[i]...) {
|
||||
continue
|
||||
}
|
||||
if output, err := iptables.Raw(append([]string{"-D", chain}, args[i]...)...); err != nil {
|
||||
return fmt.Errorf("unable to remove inter-network communication rule: %s", err.Error())
|
||||
} else if len(output) != 0 {
|
||||
return fmt.Errorf("error removing inter-network communication rule: %s", string(output))
|
||||
if err := iptables.RawCombinedOutput(append([]string{"-D", chain}, args[i]...)...); err != nil {
|
||||
return fmt.Errorf("unable to remove inter-network communication rule: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addReturnRule(chain string) error {
|
||||
var (
|
||||
table = iptables.Filter
|
||||
args = []string{"-j", "RETURN"}
|
||||
)
|
||||
|
||||
if iptables.Exists(table, chain, args...) {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := iptables.RawCombinedOutput(append([]string{"-I", chain}, args...)...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to add return rule in %s chain: %s", chain, err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Ensure the jump rule is on top
|
||||
func ensureJumpRule(fromChain, toChain string) error {
|
||||
var (
|
||||
table = iptables.Filter
|
||||
args = []string{"-j", toChain}
|
||||
)
|
||||
|
||||
if iptables.Exists(table, fromChain, args...) {
|
||||
err := iptables.RawCombinedOutput(append([]string{"-D", fromChain}, args...)...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to remove jump to %s rule in %s chain: %s", toChain, fromChain, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
err := iptables.RawCombinedOutput(append([]string{"-I", fromChain}, args...)...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to insert jump to %s rule in %s chain: %s", toChain, fromChain, err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -12,16 +12,6 @@ const globalChain = "DOCKER-OVERLAY"
|
|||
|
||||
var filterOnce sync.Once
|
||||
|
||||
func rawIPTables(args ...string) error {
|
||||
if output, err := iptables.Raw(args...); err != nil {
|
||||
return fmt.Errorf("unable to add overlay filter: %v", err)
|
||||
} else if len(output) != 0 {
|
||||
return fmt.Errorf("unable to add overlay filter: %s", string(output))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func chainExists(cname string) bool {
|
||||
if _, err := iptables.Raw("-L", cname); err != nil {
|
||||
return false
|
||||
|
@ -31,12 +21,14 @@ func chainExists(cname string) bool {
|
|||
}
|
||||
|
||||
func setupGlobalChain() {
|
||||
if err := rawIPTables("-N", globalChain); err != nil {
|
||||
logrus.Debugf("could not create global overlay chain: %v", err)
|
||||
if err := iptables.RawCombinedOutput("-N", globalChain); err != nil {
|
||||
logrus.Errorf("could not create global overlay chain: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := rawIPTables("-A", globalChain, "-j", "RETURN"); err != nil {
|
||||
logrus.Debugf("could not install default return chain in the overlay global chain: %v", err)
|
||||
if err := iptables.RawCombinedOutput("-A", globalChain, "-j", "RETURN"); err != nil {
|
||||
logrus.Errorf("could not install default return chain in the overlay global chain: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,21 +41,21 @@ func setNetworkChain(cname string, remove bool) error {
|
|||
opt := "-N"
|
||||
// In case of remove, make sure to flush the rules in the chain
|
||||
if remove && exists {
|
||||
if err := rawIPTables("-F", cname); err != nil {
|
||||
if err := iptables.RawCombinedOutput("-F", cname); err != nil {
|
||||
return fmt.Errorf("failed to flush overlay network chain %s rules: %v", cname, err)
|
||||
}
|
||||
opt = "-X"
|
||||
}
|
||||
|
||||
if (!remove && !exists) || (remove && exists) {
|
||||
if err := rawIPTables(opt, cname); err != nil {
|
||||
if err := iptables.RawCombinedOutput(opt, cname); err != nil {
|
||||
return fmt.Errorf("failed network chain operation %q for chain %s: %v", opt, cname, err)
|
||||
}
|
||||
}
|
||||
|
||||
if !remove {
|
||||
if !iptables.Exists(iptables.Filter, cname, "-j", "DROP") {
|
||||
if err := rawIPTables("-A", cname, "-j", "DROP"); err != nil {
|
||||
if err := iptables.RawCombinedOutput("-A", cname, "-j", "DROP"); err != nil {
|
||||
return fmt.Errorf("failed adding default drop rule to overlay network chain %s: %v", cname, err)
|
||||
}
|
||||
}
|
||||
|
@ -91,12 +83,12 @@ func setFilters(cname, brName string, remove bool) error {
|
|||
for _, chain := range []string{"OUTPUT", "FORWARD"} {
|
||||
exists := iptables.Exists(iptables.Filter, chain, "-j", globalChain)
|
||||
if exists {
|
||||
if err := rawIPTables("-D", chain, "-j", globalChain); err != nil {
|
||||
if err := iptables.RawCombinedOutput("-D", chain, "-j", globalChain); err != nil {
|
||||
return fmt.Errorf("failed to delete overlay hook in chain %s while moving the hook: %v", chain, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := rawIPTables("-I", chain, "-j", globalChain); err != nil {
|
||||
if err := iptables.RawCombinedOutput("-I", chain, "-j", globalChain); err != nil {
|
||||
return fmt.Errorf("failed to insert overlay hook in chain %s: %v", chain, err)
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +97,7 @@ func setFilters(cname, brName string, remove bool) error {
|
|||
// Insert/Delete the rule to jump to per-bridge chain
|
||||
exists := iptables.Exists(iptables.Filter, globalChain, "-o", brName, "-j", cname)
|
||||
if (!remove && !exists) || (remove && exists) {
|
||||
if err := rawIPTables(opt, globalChain, "-o", brName, "-j", cname); err != nil {
|
||||
if err := iptables.RawCombinedOutput(opt, globalChain, "-o", brName, "-j", cname); err != nil {
|
||||
return fmt.Errorf("failed to add per-bridge filter rule for bridge %s, network chain %s: %v", brName, cname, err)
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +107,7 @@ func setFilters(cname, brName string, remove bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if err := rawIPTables(opt, cname, "-i", brName, "-j", "ACCEPT"); err != nil {
|
||||
if err := iptables.RawCombinedOutput(opt, cname, "-i", brName, "-j", "ACCEPT"); err != nil {
|
||||
return fmt.Errorf("failed to add overlay filter rile for network chain %s, bridge %s: %v", cname, brName, err)
|
||||
}
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ type endpoint struct {
|
|||
generic map[string]interface{}
|
||||
joinLeaveDone chan struct{}
|
||||
prefAddress net.IP
|
||||
prefAddressV6 net.IP
|
||||
ipamOptions map[string]string
|
||||
dbIndex uint64
|
||||
dbExists bool
|
||||
|
@ -688,9 +689,10 @@ func EndpointOptionGeneric(generic map[string]interface{}) EndpointOption {
|
|||
}
|
||||
|
||||
// CreateOptionIpam function returns an option setter for the ipam configuration for this endpoint
|
||||
func CreateOptionIpam(prefAddress net.IP, ipamOptions map[string]string) EndpointOption {
|
||||
func CreateOptionIpam(ipV4, ipV6 net.IP, ipamOptions map[string]string) EndpointOption {
|
||||
return func(ep *endpoint) {
|
||||
ep.prefAddress = prefAddress
|
||||
ep.prefAddress = ipV4
|
||||
ep.prefAddressV6 = ipV6
|
||||
ep.ipamOptions = ipamOptions
|
||||
}
|
||||
}
|
||||
|
@ -775,6 +777,8 @@ func (ep *endpoint) assignAddressVersion(ipVer int, ipam ipamapi.Ipam) error {
|
|||
var (
|
||||
poolID *string
|
||||
address **net.IPNet
|
||||
prefAdd net.IP
|
||||
progAdd net.IP
|
||||
)
|
||||
|
||||
n := ep.getNetwork()
|
||||
|
@ -782,9 +786,11 @@ func (ep *endpoint) assignAddressVersion(ipVer int, ipam ipamapi.Ipam) error {
|
|||
case 4:
|
||||
poolID = &ep.iface.v4PoolID
|
||||
address = &ep.iface.addr
|
||||
prefAdd = ep.prefAddress
|
||||
case 6:
|
||||
poolID = &ep.iface.v6PoolID
|
||||
address = &ep.iface.addrv6
|
||||
prefAdd = ep.prefAddressV6
|
||||
default:
|
||||
return types.InternalErrorf("incorrect ip version number passed: %d", ipVer)
|
||||
}
|
||||
|
@ -796,12 +802,19 @@ func (ep *endpoint) assignAddressVersion(ipVer int, ipam ipamapi.Ipam) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// The address to program may be chosen by the user or by the network driver in one specific
|
||||
// case to support backward compatibility with `docker daemon --fixed-cidrv6` use case
|
||||
if prefAdd != nil {
|
||||
progAdd = prefAdd
|
||||
} else if *address != nil {
|
||||
progAdd = (*address).IP
|
||||
}
|
||||
|
||||
for _, d := range ipInfo {
|
||||
var prefIP net.IP
|
||||
if *address != nil {
|
||||
prefIP = (*address).IP
|
||||
if progAdd != nil && !d.Pool.Contains(progAdd) {
|
||||
continue
|
||||
}
|
||||
addr, _, err := ipam.RequestAddress(d.PoolID, prefIP, ep.ipamOptions)
|
||||
addr, _, err := ipam.RequestAddress(d.PoolID, progAdd, ep.ipamOptions)
|
||||
if err == nil {
|
||||
ep.Lock()
|
||||
*address = addr
|
||||
|
@ -809,10 +822,13 @@ func (ep *endpoint) assignAddressVersion(ipVer int, ipam ipamapi.Ipam) error {
|
|||
ep.Unlock()
|
||||
return nil
|
||||
}
|
||||
if err != ipamapi.ErrNoAvailableIPs {
|
||||
if err != ipamapi.ErrNoAvailableIPs || progAdd != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if progAdd != nil {
|
||||
return types.BadRequestErrorf("Invalid preferred address %s: It does not belong to any of this network's subnets")
|
||||
}
|
||||
return fmt.Errorf("no available IPv%d addresses on this network's address pools: %s (%s)", ipVer, n.Name(), n.ID())
|
||||
}
|
||||
|
||||
|
|
|
@ -312,6 +312,7 @@ func Exists(table Table, chain string, rule ...string) bool {
|
|||
// parse "iptables -S" for the rule (this checks rules in a specific chain
|
||||
// in a specific table)
|
||||
ruleString := strings.Join(rule, " ")
|
||||
ruleString = chain + " " + ruleString
|
||||
existingRules, _ := exec.Command(iptablesPath, "-t", string(table), "-S", chain).Output()
|
||||
|
||||
return strings.Contains(string(existingRules), ruleString)
|
||||
|
@ -351,3 +352,12 @@ func Raw(args ...string) ([]byte, error) {
|
|||
|
||||
return output, err
|
||||
}
|
||||
|
||||
// RawCombinedOutput inernally calls the Raw function and returns a non nil
|
||||
// error if Raw returned a non nil error or a non empty output
|
||||
func RawCombinedOutput(args ...string) error {
|
||||
if output, err := Raw(args...); err != nil || len(output) != 0 {
|
||||
return fmt.Errorf("%s (%v)", string(output), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
)
|
||||
|
||||
// IPLocalhost is a regex patter for localhost IP address range.
|
||||
const IPLocalhost = `((127\.([0-9]{1,3}\.){2}[0-9]{1,3})|(::1))`
|
||||
const IPLocalhost = `((127\.([0-9]{1,3}\.){2}[0-9]{1,3})|(::1)$)`
|
||||
|
||||
var localhostIPRegexp = regexp.MustCompile(IPLocalhost)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue