// networkReleaseAddress release the ip address func networkReleaseAddress(nwCfg *mastercfg.CfgNetworkState, ipAddress string) error { isIPv6 := netutils.IsIPv6(ipAddress) if isIPv6 { hostID, err := netutils.GetIPv6HostID(nwCfg.SubnetIP, nwCfg.SubnetLen, ipAddress) if err != nil { log.Errorf("error getting host id from hostIP %s Subnet %s/%d. Error: %s", ipAddress, nwCfg.SubnetIP, nwCfg.SubnetLen, err) return err } // networkReleaseAddress is called from multiple places // Make sure we decrement the EpCount only if the IPAddress // was not already freed earlier if _, found := nwCfg.IPv6AllocMap[hostID]; found { nwCfg.EpAddrCount-- } delete(nwCfg.IPv6AllocMap, hostID) } else { ipAddrValue, err := netutils.GetIPNumber(nwCfg.SubnetIP, nwCfg.SubnetLen, 32, ipAddress) if err != nil { log.Errorf("error getting host id from hostIP %s Subnet %s/%d. Error: %s", ipAddress, nwCfg.SubnetIP, nwCfg.SubnetLen, err) return err } // networkReleaseAddress is called from multiple places // Make sure we decrement the EpCount only if the IPAddress // was not already freed earlier if nwCfg.IPAllocMap.Test(ipAddrValue) { nwCfg.EpAddrCount-- } nwCfg.IPAllocMap.Clear(ipAddrValue) } err := nwCfg.Write() if err != nil { log.Errorf("error writing nw config. Error: %s", err) return err } return nil }
// AllocAddressHandler allocates addresses func AllocAddressHandler(w http.ResponseWriter, r *http.Request, vars map[string]string) (interface{}, error) { var allocReq AddressAllocRequest // Get object from the request err := json.NewDecoder(r.Body).Decode(&allocReq) if err != nil { log.Errorf("Error decoding AllocAddressHandler. Err %v", err) return nil, err } log.Infof("Received AddressAllocRequest: %+v", allocReq) // Take a global lock for address allocation addrMutex.Lock() defer addrMutex.Unlock() // Get hold of the state driver stateDriver, err := utils.GetStateDriver() if err != nil { return nil, err } isIPv6 := netutils.IsIPv6(allocReq.AddressPool) networkID := "" // Determine the network id to use if allocReq.NetworkID != "" { networkID = allocReq.NetworkID } else { // find the network from address pool subnetIP := strings.Split(allocReq.AddressPool, "/")[0] subnetLen := strings.Split(allocReq.AddressPool, "/")[1] tenant := "" if strings.Contains(subnetLen, ":") { tenant = strings.Split(subnetLen, ":")[1] subnetLen = strings.Split(subnetLen, ":")[0] } // find the network from networkID readNet := &mastercfg.CfgNetworkState{} readNet.StateDriver = stateDriver netList, err := readNet.ReadAll() if err != nil { if !strings.Contains(err.Error(), "Key not found") { log.Errorf("error reading keys during host create. Error: %s", err) return nil, err } } for _, ncfg := range netList { nw := ncfg.(*mastercfg.CfgNetworkState) if isIPv6 && nw.IPv6Subnet == subnetIP && fmt.Sprintf("%d", nw.IPv6SubnetLen) == subnetLen { if tenant == "" || nw.Tenant == tenant { networkID = nw.ID } } else if nw.SubnetIP == subnetIP && fmt.Sprintf("%d", nw.SubnetLen) == subnetLen { if tenant == "" || nw.Tenant == tenant { networkID = nw.ID } } } } if networkID == "" { log.Errorf("Could not find the network for: %s", allocReq.NetworkID) return nil, errors.New("Network not found") } // find the network from network id nwCfg := &mastercfg.CfgNetworkState{} nwCfg.StateDriver = stateDriver err = nwCfg.Read(networkID) if err != nil { log.Errorf("network %s is not operational", allocReq.NetworkID) return nil, err } // Alloc addresses addr, err := networkAllocAddress(nwCfg, allocReq.PreferredIPv4Address, netutils.IsIPv6(allocReq.AddressPool)) if err != nil { log.Errorf("Failed to allocate address. Err: %v", err) return nil, err } var subnetLen uint if isIPv6 { subnetLen = nwCfg.IPv6SubnetLen } else { subnetLen = nwCfg.SubnetLen } // Build the response aresp := AddressAllocResponse{ NetworkID: allocReq.NetworkID, IPv4Address: addr + "/" + fmt.Sprintf("%d", subnetLen), } return aresp, nil }