|
@@ -12,6 +12,7 @@ import (
|
|
"github.com/docker/libnetwork/datastore"
|
|
"github.com/docker/libnetwork/datastore"
|
|
"github.com/docker/libnetwork/driverapi"
|
|
"github.com/docker/libnetwork/driverapi"
|
|
"github.com/docker/libnetwork/etchosts"
|
|
"github.com/docker/libnetwork/etchosts"
|
|
|
|
+ "github.com/docker/libnetwork/ipamapi"
|
|
"github.com/docker/libnetwork/netlabel"
|
|
"github.com/docker/libnetwork/netlabel"
|
|
"github.com/docker/libnetwork/options"
|
|
"github.com/docker/libnetwork/options"
|
|
"github.com/docker/libnetwork/types"
|
|
"github.com/docker/libnetwork/types"
|
|
@@ -58,12 +59,20 @@ type svcMap map[string]net.IP
|
|
|
|
|
|
// IpamConf contains all the ipam related configurations for a network
|
|
// IpamConf contains all the ipam related configurations for a network
|
|
type IpamConf struct {
|
|
type IpamConf struct {
|
|
|
|
+ // The master address pool for containers and network iterfaces
|
|
PreferredPool string
|
|
PreferredPool string
|
|
- SubPool string
|
|
|
|
- Options map[string]string // IPAM input options
|
|
|
|
- IsV6 bool
|
|
|
|
- Gateway string
|
|
|
|
- AuxAddresses map[string]string
|
|
|
|
|
|
+ // A subset of the master pool. If specified,
|
|
|
|
+ // this becomes the container pool
|
|
|
|
+ SubPool string
|
|
|
|
+ // Input options for IPAM Driver (optional)
|
|
|
|
+ Options map[string]string // IPAM input options
|
|
|
|
+ // IPv6 flag, Needed when no preferred pool is specified
|
|
|
|
+ IsV6 bool
|
|
|
|
+ // Preferred Network Gateway address (optional)
|
|
|
|
+ Gateway string
|
|
|
|
+ // Auxiliary addresses for network driver. Must be within the master pool.
|
|
|
|
+ // libnetwork will reserve them if they fall into the container pool
|
|
|
|
+ AuxAddresses map[string]string
|
|
}
|
|
}
|
|
|
|
|
|
// Validate checks whether the configuration is valid
|
|
// Validate checks whether the configuration is valid
|
|
@@ -845,15 +854,28 @@ func (n *network) ipamAllocate() ([]func(), error) {
|
|
log.Warnf("Failed to release gw address %s after failure to create network %s (%s)", d.Gateway, n.Name(), n.ID())
|
|
log.Warnf("Failed to release gw address %s after failure to create network %s (%s)", d.Gateway, n.Name(), n.ID())
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
+ // Auxiliary addresses must be part of the master address pool
|
|
|
|
+ // If they fall into the container addressable pool, libnetwork will reserve them
|
|
if cfg.AuxAddresses != nil {
|
|
if cfg.AuxAddresses != nil {
|
|
var ip net.IP
|
|
var ip net.IP
|
|
d.IPAMData.AuxAddresses = make(map[string]*net.IPNet, len(cfg.AuxAddresses))
|
|
d.IPAMData.AuxAddresses = make(map[string]*net.IPNet, len(cfg.AuxAddresses))
|
|
for k, v := range cfg.AuxAddresses {
|
|
for k, v := range cfg.AuxAddresses {
|
|
if ip = net.ParseIP(v); ip == nil {
|
|
if ip = net.ParseIP(v); ip == nil {
|
|
- return nil, types.BadRequestErrorf("non parsable secondary ip address %s (%s) passed for network %s", k, v, n.Name())
|
|
|
|
|
|
+ return nil, types.BadRequestErrorf("non parsable secondary ip address (%s:%s) passed for network %s", k, v, n.Name())
|
|
}
|
|
}
|
|
- if d.IPAMData.AuxAddresses[k], _, err = ipam.RequestAddress(d.PoolID, ip, nil); err != nil {
|
|
|
|
- return nil, types.InternalErrorf("failed to allocate secondary ip address %s(%s): %v", k, v, err)
|
|
|
|
|
|
+ if !d.Pool.Contains(ip) {
|
|
|
|
+ return cnl, types.ForbiddenErrorf("auxilairy address: (%s:%s) must belong to the master pool: %s", k, v, d.Pool)
|
|
|
|
+ }
|
|
|
|
+ // Attempt reservation in the container addressable pool, silent the error if address does not belong to that pool
|
|
|
|
+ if d.IPAMData.AuxAddresses[k], _, err = ipam.RequestAddress(d.PoolID, ip, nil); err != nil && err != ipamapi.ErrIPOutOfRange {
|
|
|
|
+ return nil, types.InternalErrorf("failed to allocate secondary ip address (%s:%s): %v", k, v, err)
|
|
|
|
+ }
|
|
|
|
+ if err == nil {
|
|
|
|
+ cnl = append(cnl, func() {
|
|
|
|
+ if err := ipam.ReleaseAddress(d.PoolID, ip); err != nil {
|
|
|
|
+ log.Warnf("Failed to release secondary ip address %s(%s) after failure to create network %s (%s)", k, v, ip, n.Name(), n.ID())
|
|
|
|
+ }
|
|
|
|
+ })
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -880,8 +902,10 @@ func (n *network) ipamRelease() {
|
|
}
|
|
}
|
|
if d.IPAMData.AuxAddresses != nil {
|
|
if d.IPAMData.AuxAddresses != nil {
|
|
for k, nw := range d.IPAMData.AuxAddresses {
|
|
for k, nw := range d.IPAMData.AuxAddresses {
|
|
- if err := ipam.ReleaseAddress(d.PoolID, nw.IP); err != nil {
|
|
|
|
- log.Warnf("Failed to release secondary ip address %s (%v) on delete of network %s (%s): %v", k, nw.IP, n.Name(), n.ID(), err)
|
|
|
|
|
|
+ if d.Pool.Contains(nw.IP) {
|
|
|
|
+ if err := ipam.ReleaseAddress(d.PoolID, nw.IP); err != nil && err != ipamapi.ErrIPOutOfRange {
|
|
|
|
+ log.Warnf("Failed to release secondary ip address %s (%v) on delete of network %s (%s): %v", k, nw.IP, n.Name(), n.ID(), err)
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|