func (na *NetworkAllocator) allocatePools(n *api.Network) (map[string]string, error) { ipam, dName, err := na.resolveIPAM(n) if err != nil { return nil, err } // We don't support user defined address spaces yet so just // retrive default address space names for the driver. _, asName, err := na.drvRegistry.IPAMDefaultAddressSpaces(dName) if err != nil { return nil, err } pools := make(map[string]string) if n.Spec.IPAM == nil { n.Spec.IPAM = &api.IPAMOptions{} } ipamConfigs := make([]*api.IPAMConfig, len(n.Spec.IPAM.Configs)) copy(ipamConfigs, n.Spec.IPAM.Configs) // If there is non-nil IPAM state always prefer those subnet // configs over Spec configs. if n.IPAM != nil { ipamConfigs = n.IPAM.Configs } // Append an empty slot for subnet allocation if there are no // IPAM configs from either spec or state. if len(ipamConfigs) == 0 { ipamConfigs = append(ipamConfigs, &api.IPAMConfig{Family: api.IPAMConfig_IPV4}) } // Update the runtime IPAM configurations with initial state n.IPAM = &api.IPAMOptions{ Driver: &api.Driver{Name: dName}, Configs: ipamConfigs, } for i, ic := range ipamConfigs { poolID, poolIP, _, err := ipam.RequestPool(asName, ic.Subnet, ic.Range, nil, false) if err != nil { // Rollback by releasing all the resources allocated so far. releasePools(ipam, ipamConfigs[:i], pools) return nil, err } pools[poolIP.String()] = poolID gwIP, _, err := ipam.RequestAddress(poolID, net.ParseIP(ic.Gateway), nil) if err != nil { // Rollback by releasing all the resources allocated so far. releasePools(ipam, ipamConfigs[:i], pools) return nil, err } if ic.Subnet == "" { ic.Subnet = poolIP.String() } if ic.Gateway == "" { ic.Gateway = gwIP.IP.String() } } return pools, nil }