mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #2058 from selansen/master
Allow user to specify default address pools for docker networks
This commit is contained in:
commit
f8a7f2e7be
10 changed files with 186 additions and 35 deletions
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/docker/libkv/store"
|
||||
"github.com/docker/libnetwork/cluster"
|
||||
"github.com/docker/libnetwork/datastore"
|
||||
"github.com/docker/libnetwork/ipamutils"
|
||||
"github.com/docker/libnetwork/netlabel"
|
||||
"github.com/docker/libnetwork/osl"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -40,6 +41,7 @@ type DaemonCfg struct {
|
|||
DriverCfg map[string]interface{}
|
||||
ClusterProvider cluster.Provider
|
||||
NetworkControlPlaneMTU int
|
||||
DefaultAddressPool []*ipamutils.NetworkToSplit
|
||||
}
|
||||
|
||||
// ClusterCfg represents cluster configuration
|
||||
|
@ -110,6 +112,13 @@ func OptionDefaultDriver(dd string) Option {
|
|||
}
|
||||
}
|
||||
|
||||
// OptionDefaultAddressPoolConfig function returns an option setter for default address pool
|
||||
func OptionDefaultAddressPoolConfig(addressPool []*ipamutils.NetworkToSplit) Option {
|
||||
return func(c *Config) {
|
||||
c.Daemon.DefaultAddressPool = addressPool
|
||||
}
|
||||
}
|
||||
|
||||
// OptionDriverConfig returns an option setter for driver configuration.
|
||||
func OptionDriverConfig(networkType string, config map[string]interface{}) Option {
|
||||
return func(c *Config) {
|
||||
|
|
|
@ -222,7 +222,7 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if err = initIPAMDrivers(drvRegistry, nil, c.getStore(datastore.GlobalScope)); err != nil {
|
||||
if err = initIPAMDrivers(drvRegistry, nil, c.getStore(datastore.GlobalScope), c.cfg.Daemon.DefaultAddressPool); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
ipamutils.InitNetworks()
|
||||
ipamutils.InitNetworks(nil)
|
||||
}
|
||||
|
||||
func TestEndpointMarshalling(t *testing.T) {
|
||||
|
|
|
@ -6,9 +6,11 @@ import (
|
|||
builtinIpam "github.com/docker/libnetwork/ipams/builtin"
|
||||
nullIpam "github.com/docker/libnetwork/ipams/null"
|
||||
remoteIpam "github.com/docker/libnetwork/ipams/remote"
|
||||
"github.com/docker/libnetwork/ipamutils"
|
||||
)
|
||||
|
||||
func initIPAMDrivers(r *drvregistry.DrvRegistry, lDs, gDs interface{}) error {
|
||||
func initIPAMDrivers(r *drvregistry.DrvRegistry, lDs, gDs interface{}, addressPool []*ipamutils.NetworkToSplit) error {
|
||||
builtinIpam.SetDefaultIPAddressPool(addressPool)
|
||||
for _, fn := range [](func(ipamapi.Callback, interface{}, interface{}) error){
|
||||
builtinIpam.Init,
|
||||
remoteIpam.Init,
|
||||
|
|
|
@ -51,7 +51,7 @@ func randomLocalStore() (datastore.DataStore, error) {
|
|||
}
|
||||
|
||||
func getAllocator() (*Allocator, error) {
|
||||
ipamutils.InitNetworks()
|
||||
ipamutils.InitNetworks(nil)
|
||||
ds, err := randomLocalStore()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -11,6 +11,11 @@ import (
|
|||
"github.com/docker/libnetwork/ipamutils"
|
||||
)
|
||||
|
||||
var (
|
||||
// defaultAddressPool Stores user configured subnet list
|
||||
defaultAddressPool []*ipamutils.NetworkToSplit
|
||||
)
|
||||
|
||||
// Init registers the built-in ipam service with libnetwork
|
||||
func Init(ic ipamapi.Callback, l, g interface{}) error {
|
||||
var (
|
||||
|
@ -30,7 +35,7 @@ func Init(ic ipamapi.Callback, l, g interface{}) error {
|
|||
}
|
||||
}
|
||||
|
||||
ipamutils.InitNetworks()
|
||||
ipamutils.InitNetworks(GetDefaultIPAddressPool())
|
||||
|
||||
a, err := ipam.NewAllocator(localDs, globalDs)
|
||||
if err != nil {
|
||||
|
@ -41,3 +46,13 @@ func Init(ic ipamapi.Callback, l, g interface{}) error {
|
|||
|
||||
return ic.RegisterIpamDriverWithCapabilities(ipamapi.DefaultIPAM, a, cps)
|
||||
}
|
||||
|
||||
// SetDefaultIPAddressPool stores default address pool.
|
||||
func SetDefaultIPAddressPool(addressPool []*ipamutils.NetworkToSplit) {
|
||||
defaultAddressPool = addressPool
|
||||
}
|
||||
|
||||
// GetDefaultIPAddressPool returns default address pool.
|
||||
func GetDefaultIPAddressPool() []*ipamutils.NetworkToSplit {
|
||||
return defaultAddressPool
|
||||
}
|
||||
|
|
|
@ -13,6 +13,11 @@ import (
|
|||
windowsipam "github.com/docker/libnetwork/ipams/windowsipam"
|
||||
)
|
||||
|
||||
var (
|
||||
// defaultAddressPool Stores user configured subnet list
|
||||
defaultAddressPool []*ipamutils.NetworkToSplit
|
||||
)
|
||||
|
||||
// InitDockerDefault registers the built-in ipam service with libnetwork
|
||||
func InitDockerDefault(ic ipamapi.Callback, l, g interface{}) error {
|
||||
var (
|
||||
|
@ -32,7 +37,7 @@ func InitDockerDefault(ic ipamapi.Callback, l, g interface{}) error {
|
|||
}
|
||||
}
|
||||
|
||||
ipamutils.InitNetworks()
|
||||
ipamutils.InitNetworks(nil)
|
||||
|
||||
a, err := ipam.NewAllocator(localDs, globalDs)
|
||||
if err != nil {
|
||||
|
@ -55,3 +60,13 @@ func Init(ic ipamapi.Callback, l, g interface{}) error {
|
|||
|
||||
return initFunc(ic, l, g)
|
||||
}
|
||||
|
||||
// SetDefaultIPAddressPool stores default address pool .
|
||||
func SetDefaultIPAddressPool(addressPool []*ipamutils.NetworkToSplit) {
|
||||
defaultAddressPool = addressPool
|
||||
}
|
||||
|
||||
// GetDefaultIPAddressPool returns default address pool .
|
||||
func GetDefaultIPAddressPool() []*ipamutils.NetworkToSplit {
|
||||
return defaultAddressPool
|
||||
}
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
package ipamutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -13,38 +16,81 @@ var (
|
|||
// PredefinedGranularNetworks contains a list of 64K IPv4 private networks with host size 8
|
||||
// (10.x.x.x/24) which do not overlap with the networks in `PredefinedBroadNetworks`
|
||||
PredefinedGranularNetworks []*net.IPNet
|
||||
initNetworksOnce sync.Once
|
||||
|
||||
initNetworksOnce sync.Once
|
||||
defaultBroadNetwork = []*NetworkToSplit{{"172.17.0.0/16", 16}, {"172.18.0.0/16", 16}, {"172.19.0.0/16", 16},
|
||||
{"172.20.0.0/14", 16}, {"172.24.0.0/14", 16}, {"172.28.0.0/14", 16},
|
||||
{"192.168.0.0/16", 20}}
|
||||
defaultGranularNetwork = []*NetworkToSplit{{"10.0.0.0/8", 24}}
|
||||
)
|
||||
|
||||
// InitNetworks initializes the pre-defined networks used by the built-in IP allocator
|
||||
func InitNetworks() {
|
||||
// NetworkToSplit represent a network that has to be split in chunks with mask length Size.
|
||||
// Each subnet in the set is derived from the Base pool. Base is to be passed
|
||||
// in CIDR format.
|
||||
// Example: a Base "10.10.0.0/16 with Size 24 will define the set of 256
|
||||
// 10.10.[0-255].0/24 address pools
|
||||
type NetworkToSplit struct {
|
||||
Base string `json:"base"`
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
// InitNetworks initializes the broad network pool and the granular network pool
|
||||
func InitNetworks(defaultAddressPool []*NetworkToSplit) {
|
||||
initNetworksOnce.Do(func() {
|
||||
PredefinedBroadNetworks = initBroadPredefinedNetworks()
|
||||
PredefinedGranularNetworks = initGranularPredefinedNetworks()
|
||||
// error ingnored should never fail
|
||||
PredefinedGranularNetworks, _ = splitNetworks(defaultGranularNetwork)
|
||||
if defaultAddressPool == nil {
|
||||
defaultAddressPool = defaultBroadNetwork
|
||||
}
|
||||
var err error
|
||||
if PredefinedBroadNetworks, err = splitNetworks(defaultAddressPool); err != nil {
|
||||
logrus.WithError(err).Error("InitAddressPools failed to initialize the default address pool")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func initBroadPredefinedNetworks() []*net.IPNet {
|
||||
pl := make([]*net.IPNet, 0, 31)
|
||||
mask := []byte{255, 255, 0, 0}
|
||||
for i := 17; i < 32; i++ {
|
||||
pl = append(pl, &net.IPNet{IP: []byte{172, byte(i), 0, 0}, Mask: mask})
|
||||
// splitNetworks takes a slice of networks, split them accordingly and returns them
|
||||
func splitNetworks(list []*NetworkToSplit) ([]*net.IPNet, error) {
|
||||
localPools := make([]*net.IPNet, 0, len(list))
|
||||
|
||||
for _, p := range list {
|
||||
_, b, err := net.ParseCIDR(p.Base)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid base pool %q: %v", p.Base, err)
|
||||
}
|
||||
ones, _ := b.Mask.Size()
|
||||
if p.Size <= 0 || p.Size < ones {
|
||||
return nil, fmt.Errorf("invalid pools size: %d", p.Size)
|
||||
}
|
||||
localPools = append(localPools, splitNetwork(p.Size, b)...)
|
||||
}
|
||||
mask20 := []byte{255, 255, 240, 0}
|
||||
for i := 0; i < 16; i++ {
|
||||
pl = append(pl, &net.IPNet{IP: []byte{192, 168, byte(i << 4), 0}, Mask: mask20})
|
||||
}
|
||||
return pl
|
||||
return localPools, nil
|
||||
}
|
||||
|
||||
func initGranularPredefinedNetworks() []*net.IPNet {
|
||||
pl := make([]*net.IPNet, 0, 256*256)
|
||||
mask := []byte{255, 255, 255, 0}
|
||||
for i := 0; i < 256; i++ {
|
||||
for j := 0; j < 256; j++ {
|
||||
pl = append(pl, &net.IPNet{IP: []byte{10, byte(i), byte(j), 0}, Mask: mask})
|
||||
}
|
||||
func splitNetwork(size int, base *net.IPNet) []*net.IPNet {
|
||||
one, bits := base.Mask.Size()
|
||||
mask := net.CIDRMask(size, bits)
|
||||
n := 1 << uint(size-one)
|
||||
s := uint(bits - size)
|
||||
list := make([]*net.IPNet, 0, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
ip := copyIP(base.IP)
|
||||
addIntToIP(ip, uint(i<<s))
|
||||
list = append(list, &net.IPNet{IP: ip, Mask: mask})
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func copyIP(from net.IP) net.IP {
|
||||
ip := make([]byte, len(from))
|
||||
copy(ip, from)
|
||||
return ip
|
||||
}
|
||||
|
||||
func addIntToIP(array net.IP, ordinal uint) {
|
||||
for i := len(array) - 1; i >= 0; i-- {
|
||||
array[i] |= (byte)(ordinal & 0xff)
|
||||
ordinal >>= 8
|
||||
}
|
||||
return pl
|
||||
}
|
||||
|
|
|
@ -1,16 +1,40 @@
|
|||
package ipamutils
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
_ "github.com/docker/libnetwork/testutils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func init() {
|
||||
InitNetworks()
|
||||
func initBroadPredefinedNetworks() []*net.IPNet {
|
||||
pl := make([]*net.IPNet, 0, 31)
|
||||
mask := []byte{255, 255, 0, 0}
|
||||
for i := 17; i < 32; i++ {
|
||||
pl = append(pl, &net.IPNet{IP: []byte{172, byte(i), 0, 0}, Mask: mask})
|
||||
}
|
||||
mask20 := []byte{255, 255, 240, 0}
|
||||
for i := 0; i < 16; i++ {
|
||||
pl = append(pl, &net.IPNet{IP: []byte{192, 168, byte(i << 4), 0}, Mask: mask20})
|
||||
}
|
||||
return pl
|
||||
}
|
||||
|
||||
func TestGranularPredefined(t *testing.T) {
|
||||
func initGranularPredefinedNetworks() []*net.IPNet {
|
||||
pl := make([]*net.IPNet, 0, 256*256)
|
||||
mask := []byte{255, 255, 255, 0}
|
||||
for i := 0; i < 256; i++ {
|
||||
for j := 0; j < 256; j++ {
|
||||
pl = append(pl, &net.IPNet{IP: []byte{10, byte(i), byte(j), 0}, Mask: mask})
|
||||
}
|
||||
}
|
||||
return pl
|
||||
}
|
||||
|
||||
func TestDefaultNetwork(t *testing.T) {
|
||||
InitNetworks(nil)
|
||||
for _, nw := range PredefinedGranularNetworks {
|
||||
if ones, bits := nw.Mask.Size(); bits != 32 || ones != 24 {
|
||||
t.Fatalf("Unexpected size for network in granular list: %v", nw)
|
||||
|
@ -23,4 +47,44 @@ func TestGranularPredefined(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
originalBroadNets := initBroadPredefinedNetworks()
|
||||
m := make(map[string]bool)
|
||||
for _, v := range originalBroadNets {
|
||||
m[v.String()] = true
|
||||
}
|
||||
for _, nw := range PredefinedBroadNetworks {
|
||||
_, ok := m[nw.String()]
|
||||
assert.True(t, ok)
|
||||
delete(m, nw.String())
|
||||
}
|
||||
|
||||
assert.Len(t, m, 0)
|
||||
|
||||
originalGranularNets := initGranularPredefinedNetworks()
|
||||
|
||||
m = make(map[string]bool)
|
||||
for _, v := range originalGranularNets {
|
||||
m[v.String()] = true
|
||||
}
|
||||
for _, nw := range PredefinedGranularNetworks {
|
||||
_, ok := m[nw.String()]
|
||||
assert.True(t, ok)
|
||||
delete(m, nw.String())
|
||||
}
|
||||
|
||||
assert.Len(t, m, 0)
|
||||
}
|
||||
|
||||
func TestInitAddressPools(t *testing.T) {
|
||||
initNetworksOnce = sync.Once{}
|
||||
InitNetworks([]*NetworkToSplit{{"172.80.0.0/16", 24}, {"172.90.0.0/16", 24}})
|
||||
|
||||
// Check for Random IPAddresses in PredefinedBroadNetworks ex: first , last and middle
|
||||
assert.Len(t, PredefinedBroadNetworks, 512, "Failed to find PredefinedBroadNetworks")
|
||||
assert.Equal(t, PredefinedBroadNetworks[0].String(), "172.80.0.0/24")
|
||||
assert.Equal(t, PredefinedBroadNetworks[127].String(), "172.80.127.0/24")
|
||||
assert.Equal(t, PredefinedBroadNetworks[255].String(), "172.80.255.0/24")
|
||||
assert.Equal(t, PredefinedBroadNetworks[256].String(), "172.90.0.0/24")
|
||||
assert.Equal(t, PredefinedBroadNetworks[383].String(), "172.90.127.0/24")
|
||||
assert.Equal(t, PredefinedBroadNetworks[511].String(), "172.90.255.0/24")
|
||||
}
|
||||
|
|
|
@ -212,7 +212,7 @@ func TestUtilGenerateRandomMAC(t *testing.T) {
|
|||
|
||||
func TestNetworkRequest(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
ipamutils.InitNetworks()
|
||||
ipamutils.InitNetworks(nil)
|
||||
|
||||
nw, err := FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
|
||||
if err != nil {
|
||||
|
@ -266,7 +266,7 @@ func TestNetworkRequest(t *testing.T) {
|
|||
|
||||
func TestElectInterfaceAddressMultipleAddresses(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
ipamutils.InitNetworks()
|
||||
ipamutils.InitNetworks(nil)
|
||||
|
||||
nws := []string{"172.101.202.254/16", "172.102.202.254/16"}
|
||||
createInterface(t, "test", nws...)
|
||||
|
@ -303,7 +303,7 @@ func TestElectInterfaceAddressMultipleAddresses(t *testing.T) {
|
|||
|
||||
func TestElectInterfaceAddress(t *testing.T) {
|
||||
defer testutils.SetupTestOSContext(t)()
|
||||
ipamutils.InitNetworks()
|
||||
ipamutils.InitNetworks(nil)
|
||||
|
||||
nws := "172.101.202.254/16"
|
||||
createInterface(t, "test", nws)
|
||||
|
|
Loading…
Reference in a new issue