1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Avoid persisting ipam data if it can be reconstructed

- Also restore older behavior where overlap check is not run
  when preferred pool is specified. Got broken by recent changes

Signed-off-by: Alessandro Boch <aboch@docker.com>
This commit is contained in:
Alessandro Boch 2016-04-18 15:11:36 -07:00
parent 0de68331ab
commit 651f6ea0fa
7 changed files with 69 additions and 5 deletions

View file

@ -200,6 +200,8 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
c.cleanupLocalEndpoints()
c.networkCleanup()
c.reservePools()
if err := c.startExternalKeyListener(); err != nil {
return nil, err
}
@ -546,6 +548,52 @@ func (c *controller) NewNetwork(networkType, name string, id string, options ...
return network, nil
}
func (c *controller) reservePools() {
networks, err := c.getNetworksForScope(datastore.LocalScope)
if err != nil {
log.Warnf("Could not retrieve networks from local store during ipam allocation for existing networks: %v", err)
return
}
for _, n := range networks {
if !doReplayPoolReserve(n) {
continue
}
// Construct pseudo configs for the auto IP case
autoIPv4 := (len(n.ipamV4Config) == 0 || (len(n.ipamV4Config) == 1 && n.ipamV4Config[0].PreferredPool == "")) && len(n.ipamV4Info) > 0
autoIPv6 := (len(n.ipamV6Config) == 0 || (len(n.ipamV6Config) == 1 && n.ipamV6Config[0].PreferredPool == "")) && len(n.ipamV6Info) > 0
if autoIPv4 {
n.ipamV4Config = []*IpamConf{{PreferredPool: n.ipamV4Info[0].Pool.String()}}
}
if n.enableIPv6 && autoIPv6 {
n.ipamV6Config = []*IpamConf{{PreferredPool: n.ipamV6Info[0].Pool.String()}}
}
// Account current network gateways
for i, c := range n.ipamV4Config {
if c.Gateway == "" && n.ipamV4Info[i].Gateway != nil {
c.Gateway = n.ipamV4Info[i].Gateway.IP.String()
}
}
for i, c := range n.ipamV6Config {
if c.Gateway == "" && n.ipamV6Info[i].Gateway != nil {
c.Gateway = n.ipamV6Info[i].Gateway.IP.String()
}
}
if err := n.ipamAllocate(); err != nil {
log.Warnf("Failed to allocate ipam pool(s) for network %q (%s): %v", n.Name(), n.ID(), err)
}
}
}
func doReplayPoolReserve(n *network) bool {
_, caps, err := n.getController().getIPAMDriver(n.ipamType)
if err != nil {
log.Warnf("Failed to retrieve ipam driver for network %q (%s): %v", n.Name(), n.ID(), err)
return false
}
return caps.RequiresRequestReplay
}
func (c *controller) addNetwork(n *network) error {
d, err := n.driver(true)
if err != nil {

View file

@ -249,6 +249,7 @@ During registration, the remote driver will receive a POST message to the URL `/
{
"RequiresMACAddress": bool
"RequiresRequestReplay": bool
}
@ -263,6 +264,10 @@ As of now libnetwork accepts the following capabilities:
It is a boolean value which tells libnetwork whether the ipam driver needs to know the interface MAC address in order to properly process the `RequestAddress()` call.
If true, on `CreateEndpoint()` request, libnetwork will generate a random MAC address for the endpoint (if an explicit MAC address was not already provided by the user) and pass it to `RequestAddress()` when requesting the IP address inside the options map. The key will be the `netlabel.MacAddress` constant: `"com.docker.network.endpoint.macaddress"`.
### RequiresRequestReplay
It is a boolean value which tells libnetwork whether the ipam driver needs to receive the replay of the `RequestPool()` and `RequestAddress()` requests on daemon reload. When libnetwork controller is initializing, it retrieves from local store the list of current local scope networks and, if this capability flag is set, it allows the IPAM driver to reconstruct the database of pools by replaying the `RequestPool()` requests for each pool and the `RequestAddress()` for each network gateway owned by the local networks. This can be useful to ipam drivers which decide not to persist the pools allocated to local scope networks.
## Appendix

View file

@ -163,7 +163,7 @@ func (r *DrvRegistry) initIPAMs(lDs, gDs interface{}) error {
remoteIpam.Init,
nullIpam.Init,
} {
if err := fn(r, lDs, gDs); err != nil {
if err := fn(r, nil, gDs); err != nil {
return err
}
}

View file

@ -80,5 +80,10 @@ type Ipam interface {
// Capability represents the requirements and capabilities of the IPAM driver
type Capability struct {
// Whether on address request, libnetwork must
// specify the endpoint MAC address
RequiresMACAddress bool
// Whether of daemon start, libnetwork must replay the pool
// request and the address request for current local networks
RequiresRequestReplay bool
}

View file

@ -37,5 +37,7 @@ func Init(ic ipamapi.Callback, l, g interface{}) error {
return err
}
return ic.RegisterIpamDriver(ipamapi.DefaultIPAM, a)
cps := &ipamapi.Capability{RequiresRequestReplay: true}
return ic.RegisterIpamDriverWithCapabilities(ipamapi.DefaultIPAM, a, cps)
}

View file

@ -23,11 +23,15 @@ func (r *Response) GetError() string {
type GetCapabilityResponse struct {
Response
RequiresMACAddress bool
RequiresRequestReplay bool
}
// ToCapability converts the capability response into the internal ipam driver capaility structure
func (capRes GetCapabilityResponse) ToCapability() *ipamapi.Capability {
return &ipamapi.Capability{RequiresMACAddress: capRes.RequiresMACAddress}
return &ipamapi.Capability{
RequiresMACAddress: capRes.RequiresMACAddress,
RequiresRequestReplay: capRes.RequiresRequestReplay,
}
}
// GetAddressSpacesResponse is the response to the ``get default address spaces`` request message

View file

@ -86,7 +86,7 @@ func TestGetCapabilities(t *testing.T) {
t.Fatal(err)
}
if !caps.RequiresMACAddress {
if !caps.RequiresMACAddress || caps.RequiresRequestReplay {
t.Fatalf("Unexpected capability: %v", caps)
}
}