func (ep *endpoint) assignAddress() error { var ( ipam ipamapi.Ipam err error ) n := ep.getNetwork() if n.Type() == "host" || n.Type() == "null" || n.Type() == "bridge" { return nil } ipam, err = n.getController().getIpamDriver(n.ipamType) if err != nil { return err } for _, d := range n.getIPInfo() { var addr *net.IPNet addr, _, err = ipam.RequestAddress(d.PoolID, nil, nil) if err == nil { ep.Lock() ep.iface.addr = addr ep.iface.poolID = d.PoolID ep.Unlock() return nil } if err != ipamapi.ErrNoAvailableIPs { return err } } return fmt.Errorf("no available ip addresses on this network address pools: %s (%s)", n.Name(), n.ID()) }
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() switch ipVer { 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) } ipInfo := n.getIPInfo(ipVer) // ipv6 address is not mandatory if len(ipInfo) == 0 && ipVer == 6 { 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 { if progAdd != nil && !d.Pool.Contains(progAdd) { continue } addr, _, err := ipam.RequestAddress(d.PoolID, progAdd, ep.ipamOptions) if err == nil { ep.Lock() *address = addr *poolID = d.PoolID ep.Unlock() return nil } if err != ipamapi.ErrNoAvailableIPs || progAdd != nil { return err } } if progAdd != nil { return types.BadRequestErrorf("Invalid address %s: It does not belong to any of this network's subnets", prefAdd) } return fmt.Errorf("no available IPv%d addresses on this network's address pools: %s (%s)", ipVer, n.Name(), n.ID()) }
func (ep *endpoint) assignAddressVersion(ipVer int, ipam ipamapi.Ipam) error { var ( poolID *string address **net.IPNet ) n := ep.getNetwork() switch ipVer { case 4: poolID = &ep.iface.v4PoolID address = &ep.iface.addr case 6: poolID = &ep.iface.v6PoolID address = &ep.iface.addrv6 default: return types.InternalErrorf("incorrect ip version number passed: %d", ipVer) } ipInfo := n.getIPInfo(ipVer) // ipv6 address is not mandatory if len(ipInfo) == 0 && ipVer == 6 { return nil } for _, d := range ipInfo { var prefIP net.IP if *address != nil { prefIP = (*address).IP } addr, _, err := ipam.RequestAddress(d.PoolID, prefIP, nil) if err == nil { ep.Lock() *address = addr *poolID = d.PoolID ep.Unlock() return nil } if err != ipamapi.ErrNoAvailableIPs { return err } } return fmt.Errorf("no available IPv%d addresses on this network's address pools: %s (%s)", ipVer, n.Name(), n.ID()) }
func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error { var ( cfgList *[]*IpamConf infoList *[]*IpamInfo err error ) switch ipVer { case 4: cfgList = &n.ipamV4Config infoList = &n.ipamV4Info case 6: cfgList = &n.ipamV6Config infoList = &n.ipamV6Info default: return types.InternalErrorf("incorrect ip version passed to ipam allocate: %d", ipVer) } if len(*cfgList) == 0 { if ipVer == 6 { return nil } *cfgList = []*IpamConf{{}} } *infoList = make([]*IpamInfo, len(*cfgList)) log.Debugf("Allocating IPv%d pools for network %s (%s)", ipVer, n.Name(), n.ID()) for i, cfg := range *cfgList { if err = cfg.Validate(); err != nil { return err } d := &IpamInfo{} (*infoList)[i] = d d.AddressSpace = n.addrSpace d.PoolID, d.Pool, d.Meta, err = n.requestPoolHelper(ipam, n.addrSpace, cfg.PreferredPool, cfg.SubPool, n.ipamOptions, ipVer == 6) if err != nil { return err } defer func() { if err != nil { if err := ipam.ReleasePool(d.PoolID); err != nil { log.Warnf("Failed to release address pool %s after failure to create network %s (%s)", d.PoolID, n.Name(), n.ID()) } } }() if gws, ok := d.Meta[netlabel.Gateway]; ok { if d.Gateway, err = types.ParseCIDR(gws); err != nil { return types.BadRequestErrorf("failed to parse gateway address (%v) returned by ipam driver: %v", gws, err) } } // If user requested a specific gateway, libnetwork will allocate it // irrespective of whether ipam driver returned a gateway already. // If none of the above is true, libnetwork will allocate one. if cfg.Gateway != "" || d.Gateway == nil { var gatewayOpts = map[string]string{ ipamapi.RequestAddressType: netlabel.Gateway, } if d.Gateway, _, err = ipam.RequestAddress(d.PoolID, net.ParseIP(cfg.Gateway), gatewayOpts); err != nil { return types.InternalErrorf("failed to allocate gateway (%v): %v", cfg.Gateway, err) } } // 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 { var ip net.IP d.IPAMData.AuxAddresses = make(map[string]*net.IPNet, len(cfg.AuxAddresses)) for k, v := range cfg.AuxAddresses { if ip = net.ParseIP(v); ip == nil { return types.BadRequestErrorf("non parsable secondary ip address (%s:%s) passed for network %s", k, v, n.Name()) } if !d.Pool.Contains(ip) { return 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 types.InternalErrorf("failed to allocate secondary ip address (%s:%s): %v", k, v, err) } } } } return nil }