Fix issue for `--fixed-cidr` when bridge has multiple addresses
| ... | ... |
@@ -41,6 +41,7 @@ import ( |
| 41 | 41 |
rsystem "github.com/opencontainers/runc/libcontainer/system" |
| 42 | 42 |
"github.com/opencontainers/runc/libcontainer/user" |
| 43 | 43 |
specs "github.com/opencontainers/runtime-spec/specs-go" |
| 44 |
+ "github.com/pkg/errors" |
|
| 44 | 45 |
"github.com/vishvananda/netlink" |
| 45 | 46 |
) |
| 46 | 47 |
|
| ... | ... |
@@ -710,13 +711,30 @@ func initBridgeDriver(controller libnetwork.NetworkController, config *Config) e |
| 710 | 710 |
|
| 711 | 711 |
ipamV4Conf = &libnetwork.IpamConf{AuxAddresses: make(map[string]string)}
|
| 712 | 712 |
|
| 713 |
- nw, nw6List, err := netutils.ElectInterfaceAddresses(bridgeName) |
|
| 714 |
- if err == nil {
|
|
| 715 |
- ipamV4Conf.PreferredPool = lntypes.GetIPNetCanonical(nw).String() |
|
| 716 |
- hip, _ := lntypes.GetHostPartIP(nw.IP, nw.Mask) |
|
| 717 |
- if hip.IsGlobalUnicast() {
|
|
| 718 |
- ipamV4Conf.Gateway = nw.IP.String() |
|
| 713 |
+ nwList, nw6List, err := netutils.ElectInterfaceAddresses(bridgeName) |
|
| 714 |
+ if err != nil {
|
|
| 715 |
+ return errors.Wrap(err, "list bridge addresses failed") |
|
| 716 |
+ } |
|
| 717 |
+ |
|
| 718 |
+ nw := nwList[0] |
|
| 719 |
+ if len(nwList) > 1 && config.bridgeConfig.FixedCIDR != "" {
|
|
| 720 |
+ _, fCIDR, err := net.ParseCIDR(config.bridgeConfig.FixedCIDR) |
|
| 721 |
+ if err != nil {
|
|
| 722 |
+ return errors.Wrap(err, "parse CIDR failed") |
|
| 719 | 723 |
} |
| 724 |
+ // Iterate through in case there are multiple addresses for the bridge |
|
| 725 |
+ for _, entry := range nwList {
|
|
| 726 |
+ if fCIDR.Contains(entry.IP) {
|
|
| 727 |
+ nw = entry |
|
| 728 |
+ break |
|
| 729 |
+ } |
|
| 730 |
+ } |
|
| 731 |
+ } |
|
| 732 |
+ |
|
| 733 |
+ ipamV4Conf.PreferredPool = lntypes.GetIPNetCanonical(nw).String() |
|
| 734 |
+ hip, _ := lntypes.GetHostPartIP(nw.IP, nw.Mask) |
|
| 735 |
+ if hip.IsGlobalUnicast() {
|
|
| 736 |
+ ipamV4Conf.Gateway = nw.IP.String() |
|
| 720 | 737 |
} |
| 721 | 738 |
|
| 722 | 739 |
if config.bridgeConfig.IP != "" {
|
| ... | ... |
@@ -70,7 +70,7 @@ clone git github.com/RackSec/srslog 365bf33cd9acc21ae1c355209865f17228ca534e |
| 70 | 70 |
clone git github.com/imdario/mergo 0.2.1 |
| 71 | 71 |
|
| 72 | 72 |
#get libnetwork packages |
| 73 |
-clone git github.com/docker/libnetwork 9fbb4ecbb45af655c4ac3c2f3a849b2294cb447a |
|
| 73 |
+clone git github.com/docker/libnetwork f4338b6f1085ccfe5972e655cca8a1d15d73439d |
|
| 74 | 74 |
clone git github.com/docker/go-events 18b43f1bc85d9cdd42c05a6cd2d444c7a200a894 |
| 75 | 75 |
clone git github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 |
| 76 | 76 |
clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec |
| ... | ... |
@@ -1062,9 +1062,14 @@ func SandboxKeyWalker(out *Sandbox, key string) SandboxWalker {
|
| 1062 | 1062 |
} |
| 1063 | 1063 |
|
| 1064 | 1064 |
func (c *controller) loadDriver(networkType string) error {
|
| 1065 |
- // Plugins pkg performs lazy loading of plugins that acts as remote drivers. |
|
| 1066 |
- // As per the design, this Get call will result in remote driver discovery if there is a corresponding plugin available. |
|
| 1067 |
- _, err := plugins.Get(networkType, driverapi.NetworkPluginEndpointType) |
|
| 1065 |
+ var err error |
|
| 1066 |
+ |
|
| 1067 |
+ if pg := c.GetPluginGetter(); pg != nil {
|
|
| 1068 |
+ _, err = pg.Get(networkType, driverapi.NetworkPluginEndpointType, plugingetter.LOOKUP) |
|
| 1069 |
+ } else {
|
|
| 1070 |
+ _, err = plugins.Get(networkType, driverapi.NetworkPluginEndpointType) |
|
| 1071 |
+ } |
|
| 1072 |
+ |
|
| 1068 | 1073 |
if err != nil {
|
| 1069 | 1074 |
if err == plugins.ErrNotFound {
|
| 1070 | 1075 |
return types.NotFoundErrorf(err.Error()) |
| ... | ... |
@@ -1076,7 +1081,15 @@ func (c *controller) loadDriver(networkType string) error {
|
| 1076 | 1076 |
} |
| 1077 | 1077 |
|
| 1078 | 1078 |
func (c *controller) loadIPAMDriver(name string) error {
|
| 1079 |
- if _, err := c.GetPluginGetter().Get(name, ipamapi.PluginEndpointType, plugingetter.LOOKUP); err != nil {
|
|
| 1079 |
+ var err error |
|
| 1080 |
+ |
|
| 1081 |
+ if pg := c.GetPluginGetter(); pg != nil {
|
|
| 1082 |
+ _, err = pg.Get(name, ipamapi.PluginEndpointType, plugingetter.LOOKUP) |
|
| 1083 |
+ } else {
|
|
| 1084 |
+ _, err = plugins.Get(name, ipamapi.PluginEndpointType) |
|
| 1085 |
+ } |
|
| 1086 |
+ |
|
| 1087 |
+ if err != nil {
|
|
| 1080 | 1088 |
if err == plugins.ErrNotFound {
|
| 1081 | 1089 |
return types.NotFoundErrorf(err.Error()) |
| 1082 | 1090 |
} |
| ... | ... |
@@ -779,6 +779,20 @@ func (d *driver) DeleteNetwork(nid string) error {
|
| 779 | 779 |
config := n.config |
| 780 | 780 |
n.Unlock() |
| 781 | 781 |
|
| 782 |
+ // delele endpoints belong to this network |
|
| 783 |
+ for _, ep := range n.endpoints {
|
|
| 784 |
+ if err := n.releasePorts(ep); err != nil {
|
|
| 785 |
+ logrus.Warn(err) |
|
| 786 |
+ } |
|
| 787 |
+ if link, err := d.nlh.LinkByName(ep.srcName); err == nil {
|
|
| 788 |
+ d.nlh.LinkDel(link) |
|
| 789 |
+ } |
|
| 790 |
+ |
|
| 791 |
+ if err := d.storeDelete(ep); err != nil {
|
|
| 792 |
+ logrus.Warnf("Failed to remove bridge endpoint %s from store: %v", ep.id[0:7], err)
|
|
| 793 |
+ } |
|
| 794 |
+ } |
|
| 795 |
+ |
|
| 782 | 796 |
d.Lock() |
| 783 | 797 |
delete(d.networks, nid) |
| 784 | 798 |
d.Unlock() |
| ... | ... |
@@ -52,23 +52,22 @@ func (i *bridgeInterface) exists() bool {
|
| 52 | 52 |
return i.Link != nil |
| 53 | 53 |
} |
| 54 | 54 |
|
| 55 |
-// addresses returns a single IPv4 address and all IPv6 addresses for the |
|
| 56 |
-// bridge interface. |
|
| 57 |
-func (i *bridgeInterface) addresses() (netlink.Addr, []netlink.Addr, error) {
|
|
| 55 |
+// addresses returns all IPv4 addresses and all IPv6 addresses for the bridge interface. |
|
| 56 |
+func (i *bridgeInterface) addresses() ([]netlink.Addr, []netlink.Addr, error) {
|
|
| 58 | 57 |
v4addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V4) |
| 59 | 58 |
if err != nil {
|
| 60 |
- return netlink.Addr{}, nil, fmt.Errorf("Failed to retrieve V4 addresses: %v", err)
|
|
| 59 |
+ return nil, nil, fmt.Errorf("Failed to retrieve V4 addresses: %v", err)
|
|
| 61 | 60 |
} |
| 62 | 61 |
|
| 63 | 62 |
v6addr, err := i.nlh.AddrList(i.Link, netlink.FAMILY_V6) |
| 64 | 63 |
if err != nil {
|
| 65 |
- return netlink.Addr{}, nil, fmt.Errorf("Failed to retrieve V6 addresses: %v", err)
|
|
| 64 |
+ return nil, nil, fmt.Errorf("Failed to retrieve V6 addresses: %v", err)
|
|
| 66 | 65 |
} |
| 67 | 66 |
|
| 68 | 67 |
if len(v4addr) == 0 {
|
| 69 |
- return netlink.Addr{}, v6addr, nil
|
|
| 68 |
+ return nil, v6addr, nil |
|
| 70 | 69 |
} |
| 71 |
- return v4addr[0], v6addr, nil |
|
| 70 |
+ return v4addr, v6addr, nil |
|
| 72 | 71 |
} |
| 73 | 72 |
|
| 74 | 73 |
func (i *bridgeInterface) programIPv6Address() error {
|
| ... | ... |
@@ -3,6 +3,7 @@ package bridge |
| 3 | 3 |
import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"io/ioutil" |
| 6 |
+ "net" |
|
| 6 | 7 |
"path/filepath" |
| 7 | 8 |
|
| 8 | 9 |
log "github.com/Sirupsen/logrus" |
| ... | ... |
@@ -10,12 +11,28 @@ import ( |
| 10 | 10 |
"github.com/vishvananda/netlink" |
| 11 | 11 |
) |
| 12 | 12 |
|
| 13 |
+func selectIPv4Address(addresses []netlink.Addr, selector *net.IPNet) (netlink.Addr, error) {
|
|
| 14 |
+ if len(addresses) == 0 {
|
|
| 15 |
+ return netlink.Addr{}, fmt.Errorf("unable to select an address as the address pool is empty")
|
|
| 16 |
+ } |
|
| 17 |
+ if selector != nil {
|
|
| 18 |
+ for _, addr := range addresses {
|
|
| 19 |
+ if selector.Contains(addr.IP) {
|
|
| 20 |
+ return addr, nil |
|
| 21 |
+ } |
|
| 22 |
+ } |
|
| 23 |
+ } |
|
| 24 |
+ return addresses[0], nil |
|
| 25 |
+} |
|
| 26 |
+ |
|
| 13 | 27 |
func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error {
|
| 14 |
- addrv4, _, err := i.addresses() |
|
| 28 |
+ addrv4List, _, err := i.addresses() |
|
| 15 | 29 |
if err != nil {
|
| 16 | 30 |
return fmt.Errorf("failed to retrieve bridge interface addresses: %v", err)
|
| 17 | 31 |
} |
| 18 | 32 |
|
| 33 |
+ addrv4, _ := selectIPv4Address(addrv4List, config.AddressIPv4) |
|
| 34 |
+ |
|
| 19 | 35 |
if !types.CompareIPNet(addrv4.IPNet, config.AddressIPv4) {
|
| 20 | 36 |
if addrv4.IPNet != nil {
|
| 21 | 37 |
if err := i.nlh.AddrDel(i.Link, &addrv4); err != nil {
|
| ... | ... |
@@ -11,12 +11,14 @@ import ( |
| 11 | 11 |
) |
| 12 | 12 |
|
| 13 | 13 |
func setupVerifyAndReconcile(config *networkConfiguration, i *bridgeInterface) error {
|
| 14 |
- // Fetch a single IPv4 and a slice of IPv6 addresses from the bridge. |
|
| 15 |
- addrv4, addrsv6, err := i.addresses() |
|
| 14 |
+ // Fetch a slice of IPv4 addresses and a slice of IPv6 addresses from the bridge. |
|
| 15 |
+ addrsv4, addrsv6, err := i.addresses() |
|
| 16 | 16 |
if err != nil {
|
| 17 | 17 |
return fmt.Errorf("Failed to verify ip addresses: %v", err)
|
| 18 | 18 |
} |
| 19 | 19 |
|
| 20 |
+ addrv4, _ := selectIPv4Address(addrsv4, config.AddressIPv4) |
|
| 21 |
+ |
|
| 20 | 22 |
// Verify that the bridge does have an IPv4 address. |
| 21 | 23 |
if addrv4.IPNet == nil {
|
| 22 | 24 |
return &ErrNoIPAddr{}
|
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
"github.com/docker/docker/pkg/stringid" |
| 9 | 9 |
"github.com/docker/libnetwork/driverapi" |
| 10 | 10 |
"github.com/docker/libnetwork/netlabel" |
| 11 |
+ "github.com/docker/libnetwork/ns" |
|
| 11 | 12 |
"github.com/docker/libnetwork/options" |
| 12 | 13 |
"github.com/docker/libnetwork/osl" |
| 13 | 14 |
"github.com/docker/libnetwork/types" |
| ... | ... |
@@ -147,6 +148,15 @@ func (d *driver) DeleteNetwork(nid string) error {
|
| 147 | 147 |
} |
| 148 | 148 |
} |
| 149 | 149 |
} |
| 150 |
+ for _, ep := range n.endpoints {
|
|
| 151 |
+ if link, err := ns.NlHandle().LinkByName(ep.srcName); err == nil {
|
|
| 152 |
+ ns.NlHandle().LinkDel(link) |
|
| 153 |
+ } |
|
| 154 |
+ |
|
| 155 |
+ if err := d.storeDelete(ep); err != nil {
|
|
| 156 |
+ logrus.Warnf("Failed to remove ipvlan endpoint %s from store: %v", ep.id[0:7], err)
|
|
| 157 |
+ } |
|
| 158 |
+ } |
|
| 150 | 159 |
// delete the *network |
| 151 | 160 |
d.deleteNetwork(nid) |
| 152 | 161 |
// delete the network record from persistent cache |
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
"github.com/docker/docker/pkg/stringid" |
| 9 | 9 |
"github.com/docker/libnetwork/driverapi" |
| 10 | 10 |
"github.com/docker/libnetwork/netlabel" |
| 11 |
+ "github.com/docker/libnetwork/ns" |
|
| 11 | 12 |
"github.com/docker/libnetwork/options" |
| 12 | 13 |
"github.com/docker/libnetwork/osl" |
| 13 | 14 |
"github.com/docker/libnetwork/types" |
| ... | ... |
@@ -151,6 +152,15 @@ func (d *driver) DeleteNetwork(nid string) error {
|
| 151 | 151 |
} |
| 152 | 152 |
} |
| 153 | 153 |
} |
| 154 |
+ for _, ep := range n.endpoints {
|
|
| 155 |
+ if link, err := ns.NlHandle().LinkByName(ep.srcName); err == nil {
|
|
| 156 |
+ ns.NlHandle().LinkDel(link) |
|
| 157 |
+ } |
|
| 158 |
+ |
|
| 159 |
+ if err := d.storeDelete(ep); err != nil {
|
|
| 160 |
+ logrus.Warnf("Failed to remove macvlan endpoint %s from store: %v", ep.id[0:7], err)
|
|
| 161 |
+ } |
|
| 162 |
+ } |
|
| 154 | 163 |
// delete the *network |
| 155 | 164 |
d.deleteNetwork(nid) |
| 156 | 165 |
// delete the network record from persistent cache |
| ... | ... |
@@ -182,6 +182,18 @@ func (d *driver) DeleteNetwork(nid string) error {
|
| 182 | 182 |
return fmt.Errorf("could not find network with id %s", nid)
|
| 183 | 183 |
} |
| 184 | 184 |
|
| 185 |
+ for _, ep := range n.endpoints {
|
|
| 186 |
+ if ep.ifName != "" {
|
|
| 187 |
+ if link, err := ns.NlHandle().LinkByName(ep.ifName); err != nil {
|
|
| 188 |
+ ns.NlHandle().LinkDel(link) |
|
| 189 |
+ } |
|
| 190 |
+ } |
|
| 191 |
+ |
|
| 192 |
+ if err := d.deleteEndpointFromStore(ep); err != nil {
|
|
| 193 |
+ logrus.Warnf("Failed to delete overlay endpoint %s from local store: %v", ep.id[0:7], err)
|
|
| 194 |
+ } |
|
| 195 |
+ |
|
| 196 |
+ } |
|
| 185 | 197 |
d.deleteNetwork(nid) |
| 186 | 198 |
|
| 187 | 199 |
vnis, err := n.releaseVxlanID() |
| ... | ... |
@@ -513,14 +513,22 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) error {
|
| 513 | 513 |
if moveExtConn {
|
| 514 | 514 |
if extEp != nil {
|
| 515 | 515 |
log.Debugf("Revoking external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
|
| 516 |
- if err = d.RevokeExternalConnectivity(extEp.network.ID(), extEp.ID()); err != nil {
|
|
| 516 |
+ extN, err := extEp.getNetworkFromStore() |
|
| 517 |
+ if err != nil {
|
|
| 518 |
+ return fmt.Errorf("failed to get network from store during join: %v", err)
|
|
| 519 |
+ } |
|
| 520 |
+ extD, err := extN.driver(true) |
|
| 521 |
+ if err != nil {
|
|
| 522 |
+ return fmt.Errorf("failed to join endpoint: %v", err)
|
|
| 523 |
+ } |
|
| 524 |
+ if err = extD.RevokeExternalConnectivity(extEp.network.ID(), extEp.ID()); err != nil {
|
|
| 517 | 525 |
return types.InternalErrorf( |
| 518 | 526 |
"driver failed revoking external connectivity on endpoint %s (%s): %v", |
| 519 | 527 |
extEp.Name(), extEp.ID(), err) |
| 520 | 528 |
} |
| 521 | 529 |
defer func() {
|
| 522 | 530 |
if err != nil {
|
| 523 |
- if e := d.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); e != nil {
|
|
| 531 |
+ if e := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); e != nil {
|
|
| 524 | 532 |
log.Warnf("Failed to roll-back external connectivity on endpoint %s (%s): %v",
|
| 525 | 533 |
extEp.Name(), extEp.ID(), e) |
| 526 | 534 |
} |
| ... | ... |
@@ -699,7 +707,15 @@ func (ep *endpoint) sbLeave(sb *sandbox, force bool, options ...EndpointOption) |
| 699 | 699 |
extEp = sb.getGatewayEndpoint() |
| 700 | 700 |
if moveExtConn && extEp != nil {
|
| 701 | 701 |
log.Debugf("Programming external connectivity on endpoint %s (%s)", extEp.Name(), extEp.ID())
|
| 702 |
- if err := d.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); err != nil {
|
|
| 702 |
+ extN, err := extEp.getNetworkFromStore() |
|
| 703 |
+ if err != nil {
|
|
| 704 |
+ return fmt.Errorf("failed to get network from store during leave: %v", err)
|
|
| 705 |
+ } |
|
| 706 |
+ extD, err := extN.driver(true) |
|
| 707 |
+ if err != nil {
|
|
| 708 |
+ return fmt.Errorf("failed to leave endpoint: %v", err)
|
|
| 709 |
+ } |
|
| 710 |
+ if err := extD.ProgramExternalConnectivity(extEp.network.ID(), extEp.ID(), sb.Labels()); err != nil {
|
|
| 703 | 711 |
log.Warnf("driver failed programming external connectivity on endpoint %s: (%s) %v",
|
| 704 | 712 |
extEp.Name(), extEp.ID(), err) |
| 705 | 713 |
} |
| ... | ... |
@@ -199,12 +199,22 @@ func (a *Allocator) GetDefaultAddressSpaces() (string, string, error) {
|
| 199 | 199 |
// RequestPool returns an address pool along with its unique id. |
| 200 | 200 |
func (a *Allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
|
| 201 | 201 |
log.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6)
|
| 202 |
-retry: |
|
| 203 |
- k, nw, ipr, pdf, err := a.parsePoolRequest(addressSpace, pool, subPool, v6) |
|
| 202 |
+ |
|
| 203 |
+ k, nw, ipr, err := a.parsePoolRequest(addressSpace, pool, subPool, v6) |
|
| 204 | 204 |
if err != nil {
|
| 205 | 205 |
return "", nil, nil, types.InternalErrorf("failed to parse pool request for address space %q pool %q subpool %q: %v", addressSpace, pool, subPool, err)
|
| 206 | 206 |
} |
| 207 | 207 |
|
| 208 |
+ pdf := k == nil |
|
| 209 |
+ |
|
| 210 |
+retry: |
|
| 211 |
+ if pdf {
|
|
| 212 |
+ if nw, err = a.getPredefinedPool(addressSpace, v6); err != nil {
|
|
| 213 |
+ return "", nil, nil, err |
|
| 214 |
+ } |
|
| 215 |
+ k = &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String()}
|
|
| 216 |
+ } |
|
| 217 |
+ |
|
| 208 | 218 |
if err := a.refresh(addressSpace); err != nil {
|
| 209 | 219 |
return "", nil, nil, err |
| 210 | 220 |
} |
| ... | ... |
@@ -279,39 +289,36 @@ func (a *Allocator) getAddrSpace(as string) (*addrSpace, error) {
|
| 279 | 279 |
return aSpace, nil |
| 280 | 280 |
} |
| 281 | 281 |
|
| 282 |
-func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool) (*SubnetKey, *net.IPNet, *AddressRange, bool, error) {
|
|
| 282 |
+func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool) (*SubnetKey, *net.IPNet, *AddressRange, error) {
|
|
| 283 | 283 |
var ( |
| 284 | 284 |
nw *net.IPNet |
| 285 | 285 |
ipr *AddressRange |
| 286 | 286 |
err error |
| 287 |
- pdf = false |
|
| 288 | 287 |
) |
| 289 | 288 |
|
| 290 | 289 |
if addressSpace == "" {
|
| 291 |
- return nil, nil, nil, false, ipamapi.ErrInvalidAddressSpace |
|
| 290 |
+ return nil, nil, nil, ipamapi.ErrInvalidAddressSpace |
|
| 292 | 291 |
} |
| 293 | 292 |
|
| 294 | 293 |
if pool == "" && subPool != "" {
|
| 295 |
- return nil, nil, nil, false, ipamapi.ErrInvalidSubPool |
|
| 294 |
+ return nil, nil, nil, ipamapi.ErrInvalidSubPool |
|
| 296 | 295 |
} |
| 297 | 296 |
|
| 298 |
- if pool != "" {
|
|
| 299 |
- if _, nw, err = net.ParseCIDR(pool); err != nil {
|
|
| 300 |
- return nil, nil, nil, false, ipamapi.ErrInvalidPool |
|
| 301 |
- } |
|
| 302 |
- if subPool != "" {
|
|
| 303 |
- if ipr, err = getAddressRange(subPool, nw); err != nil {
|
|
| 304 |
- return nil, nil, nil, false, err |
|
| 305 |
- } |
|
| 306 |
- } |
|
| 307 |
- } else {
|
|
| 308 |
- if nw, err = a.getPredefinedPool(addressSpace, v6); err != nil {
|
|
| 309 |
- return nil, nil, nil, false, err |
|
| 297 |
+ if pool == "" {
|
|
| 298 |
+ return nil, nil, nil, nil |
|
| 299 |
+ } |
|
| 300 |
+ |
|
| 301 |
+ if _, nw, err = net.ParseCIDR(pool); err != nil {
|
|
| 302 |
+ return nil, nil, nil, ipamapi.ErrInvalidPool |
|
| 303 |
+ } |
|
| 304 |
+ |
|
| 305 |
+ if subPool != "" {
|
|
| 306 |
+ if ipr, err = getAddressRange(subPool, nw); err != nil {
|
|
| 307 |
+ return nil, nil, nil, err |
|
| 310 | 308 |
} |
| 311 |
- pdf = true |
|
| 312 | 309 |
} |
| 313 | 310 |
|
| 314 |
- return &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String(), ChildSubnet: subPool}, nw, ipr, pdf, nil
|
|
| 311 |
+ return &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String(), ChildSubnet: subPool}, nw, ipr, nil
|
|
| 315 | 312 |
} |
| 316 | 313 |
|
| 317 | 314 |
func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error {
|
| ... | ... |
@@ -406,7 +413,7 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error) |
| 406 | 406 |
} |
| 407 | 407 |
} |
| 408 | 408 |
|
| 409 |
- return nil, types.NotFoundErrorf("could not find an available predefined network")
|
|
| 409 |
+ return nil, types.NotFoundErrorf("could not find an available non-overlapping address pool among the defaults to auto assign to the network")
|
|
| 410 | 410 |
} |
| 411 | 411 |
|
| 412 | 412 |
// RequestAddress returns an address from the specified pool ID |
| ... | ... |
@@ -7,10 +7,12 @@ import ( |
| 7 | 7 |
) |
| 8 | 8 |
|
| 9 | 9 |
// ElectInterfaceAddresses looks for an interface on the OS with the specified name |
| 10 |
-// and returns its IPv4 and IPv6 addresses in CIDR form. If the interface does not exist, |
|
| 11 |
-// it chooses from a predifined list the first IPv4 address which does not conflict |
|
| 12 |
-// with other interfaces on the system. |
|
| 13 |
-func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
|
|
| 10 |
+// and returns returns all its IPv4 and IPv6 addresses in CIDR notation. |
|
| 11 |
+// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned. |
|
| 12 |
+// If the interface does not exist, it chooses from a predefined |
|
| 13 |
+// list the first IPv4 address which does not conflict with other |
|
| 14 |
+// interfaces on the system. |
|
| 15 |
+func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
|
|
| 14 | 16 |
return nil, nil, types.NotImplementedErrorf("not supported on freebsd")
|
| 15 | 17 |
} |
| 16 | 18 |
|
| ... | ... |
@@ -62,15 +62,15 @@ func GenerateIfaceName(nlh *netlink.Handle, prefix string, len int) (string, err |
| 62 | 62 |
} |
| 63 | 63 |
|
| 64 | 64 |
// ElectInterfaceAddresses looks for an interface on the OS with the |
| 65 |
-// specified name and returns its IPv4 and IPv6 addresses in CIDR |
|
| 66 |
-// form. If the interface does not exist, it chooses from a predefined |
|
| 65 |
+// specified name and returns returns all its IPv4 and IPv6 addresses in CIDR notation. |
|
| 66 |
+// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned. |
|
| 67 |
+// If the interface does not exist, it chooses from a predefined |
|
| 67 | 68 |
// list the first IPv4 address which does not conflict with other |
| 68 | 69 |
// interfaces on the system. |
| 69 |
-func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
|
|
| 70 |
+func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
|
|
| 70 | 71 |
var ( |
| 71 |
- v4Net *net.IPNet |
|
| 72 |
+ v4Nets []*net.IPNet |
|
| 72 | 73 |
v6Nets []*net.IPNet |
| 73 |
- err error |
|
| 74 | 74 |
) |
| 75 | 75 |
|
| 76 | 76 |
defer osl.InitOSContext()() |
| ... | ... |
@@ -85,23 +85,24 @@ func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
|
| 85 | 85 |
if err != nil {
|
| 86 | 86 |
return nil, nil, err |
| 87 | 87 |
} |
| 88 |
- if len(v4addr) > 0 {
|
|
| 89 |
- v4Net = v4addr[0].IPNet |
|
| 88 |
+ for _, nlAddr := range v4addr {
|
|
| 89 |
+ v4Nets = append(v4Nets, nlAddr.IPNet) |
|
| 90 | 90 |
} |
| 91 | 91 |
for _, nlAddr := range v6addr {
|
| 92 | 92 |
v6Nets = append(v6Nets, nlAddr.IPNet) |
| 93 | 93 |
} |
| 94 | 94 |
} |
| 95 | 95 |
|
| 96 |
- if link == nil || v4Net == nil {
|
|
| 96 |
+ if link == nil || len(v4Nets) == 0 {
|
|
| 97 | 97 |
// Choose from predefined broad networks |
| 98 |
- v4Net, err = FindAvailableNetwork(ipamutils.PredefinedBroadNetworks) |
|
| 98 |
+ v4Net, err := FindAvailableNetwork(ipamutils.PredefinedBroadNetworks) |
|
| 99 | 99 |
if err != nil {
|
| 100 | 100 |
return nil, nil, err |
| 101 | 101 |
} |
| 102 |
+ v4Nets = append(v4Nets, v4Net) |
|
| 102 | 103 |
} |
| 103 | 104 |
|
| 104 |
- return v4Net, v6Nets, nil |
|
| 105 |
+ return v4Nets, v6Nets, nil |
|
| 105 | 106 |
} |
| 106 | 107 |
|
| 107 | 108 |
// FindAvailableNetwork returns a network from the passed list which does not |
| ... | ... |
@@ -22,10 +22,12 @@ func CheckRouteOverlaps(toCheck *net.IPNet) error {
|
| 22 | 22 |
} |
| 23 | 23 |
|
| 24 | 24 |
// ElectInterfaceAddresses looks for an interface on the OS with the specified name |
| 25 |
-// and returns its IPv4 and IPv6 addresses in CIDR form. If the interface does not exist, |
|
| 26 |
-// it chooses from a predifined list the first IPv4 address which does not conflict |
|
| 27 |
-// with other interfaces on the system. |
|
| 28 |
-func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
|
|
| 25 |
+// and returns returns all its IPv4 and IPv6 addresses in CIDR notation. |
|
| 26 |
+// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned. |
|
| 27 |
+// If the interface does not exist, it chooses from a predefined |
|
| 28 |
+// list the first IPv4 address which does not conflict with other |
|
| 29 |
+// interfaces on the system. |
|
| 30 |
+func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
|
|
| 29 | 31 |
var ( |
| 30 | 32 |
v4Net *net.IPNet |
| 31 | 33 |
) |
| ... | ... |
@@ -63,7 +65,7 @@ func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
|
| 63 | 63 |
return nil, nil, err |
| 64 | 64 |
} |
| 65 | 65 |
} |
| 66 |
- return v4Net, nil, nil |
|
| 66 |
+ return []*net.IPNet{v4Net}, nil, nil
|
|
| 67 | 67 |
} |
| 68 | 68 |
|
| 69 | 69 |
// FindAvailableNetwork returns a network from the passed list which does not |
| ... | ... |
@@ -7,10 +7,12 @@ import ( |
| 7 | 7 |
) |
| 8 | 8 |
|
| 9 | 9 |
// ElectInterfaceAddresses looks for an interface on the OS with the specified name |
| 10 |
-// and returns its IPv4 and IPv6 addresses in CIDR form. If the interface does not exist, |
|
| 11 |
-// it chooses from a predifined list the first IPv4 address which does not conflict |
|
| 12 |
-// with other interfaces on the system. |
|
| 13 |
-func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
|
|
| 10 |
+// and returns returns all its IPv4 and IPv6 addresses in CIDR notation. |
|
| 11 |
+// If a failure in retrieving the addresses or no IPv4 address is found, an error is returned. |
|
| 12 |
+// If the interface does not exist, it chooses from a predefined |
|
| 13 |
+// list the first IPv4 address which does not conflict with other |
|
| 14 |
+// interfaces on the system. |
|
| 15 |
+func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
|
|
| 14 | 16 |
return nil, nil, types.NotImplementedErrorf("not supported on windows")
|
| 15 | 17 |
} |
| 16 | 18 |
|
| ... | ... |
@@ -16,9 +16,11 @@ import ( |
| 16 | 16 |
) |
| 17 | 17 |
|
| 18 | 18 |
const ( |
| 19 |
- reapInterval = 60 * time.Second |
|
| 20 |
- reapPeriod = 5 * time.Second |
|
| 21 |
- retryInterval = 1 * time.Second |
|
| 19 |
+ reapInterval = 60 * time.Second |
|
| 20 |
+ reapPeriod = 5 * time.Second |
|
| 21 |
+ retryInterval = 1 * time.Second |
|
| 22 |
+ nodeReapInterval = 24 * time.Hour |
|
| 23 |
+ nodeReapPeriod = 2 * time.Hour |
|
| 22 | 24 |
) |
| 23 | 25 |
|
| 24 | 26 |
type logWriter struct{}
|
| ... | ... |
@@ -147,6 +149,7 @@ func (nDB *NetworkDB) clusterInit() error {
|
| 147 | 147 |
{config.GossipInterval, nDB.gossip},
|
| 148 | 148 |
{config.PushPullInterval, nDB.bulkSyncTables},
|
| 149 | 149 |
{retryInterval, nDB.reconnectNode},
|
| 150 |
+ {nodeReapPeriod, nDB.reapDeadNode},
|
|
| 150 | 151 |
} {
|
| 151 | 152 |
t := time.NewTicker(trigger.interval) |
| 152 | 153 |
go nDB.triggerFunc(trigger.interval, t.C, nDB.stopCh, trigger.fn) |
| ... | ... |
@@ -234,6 +237,19 @@ func (nDB *NetworkDB) triggerFunc(stagger time.Duration, C <-chan time.Time, sto |
| 234 | 234 |
} |
| 235 | 235 |
} |
| 236 | 236 |
|
| 237 |
+func (nDB *NetworkDB) reapDeadNode() {
|
|
| 238 |
+ nDB.Lock() |
|
| 239 |
+ defer nDB.Unlock() |
|
| 240 |
+ for id, n := range nDB.failedNodes {
|
|
| 241 |
+ if n.reapTime > 0 {
|
|
| 242 |
+ n.reapTime -= reapPeriod |
|
| 243 |
+ continue |
|
| 244 |
+ } |
|
| 245 |
+ logrus.Debugf("Removing failed node %v from gossip cluster", n.Name)
|
|
| 246 |
+ delete(nDB.failedNodes, id) |
|
| 247 |
+ } |
|
| 248 |
+} |
|
| 249 |
+ |
|
| 237 | 250 |
func (nDB *NetworkDB) reconnectNode() {
|
| 238 | 251 |
nDB.RLock() |
| 239 | 252 |
if len(nDB.failedNodes) == 0 {
|