fix network ip allocation in HA

This commit is contained in:
abhishek9686
2025-02-27 16:26:15 +04:00
parent 2f0d289813
commit ce6ec25253
4 changed files with 161 additions and 36 deletions

View File

@@ -458,7 +458,9 @@ func deleteNetwork(w http.ResponseWriter, r *http.Request) {
go logic.DeleteNetworkRoles(network)
go logic.DeleteDefaultNetworkPolicies(models.NetworkID(network))
//delete network from allocated ip map
if servercfg.CacheEnabled() {
go logic.RemoveNetworkFromAllocatedIpMap(network)
}
logger.Log(1, r.Header.Get("user"), "deleted network", network)
w.WriteHeader(http.StatusOK)
@@ -534,7 +536,7 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
logic.CreateDefaultNetworkRolesAndGroups(models.NetworkID(network.NetID))
logic.CreateDefaultAclNetworkPolicies(models.NetworkID(network.NetID))
logic.CreateDefaultTags(models.NetworkID(network.NetID))
//add new network to allocated ip map
go logic.AddNetworkToAllocatedIpMap(network.NetID)
go func() {

View File

@@ -105,14 +105,14 @@ func DeleteExtClient(network string, clientid string) error {
if err != nil {
return err
}
//recycle ip address
if servercfg.CacheEnabled() {
// recycle ip address
if extClient.Address != "" {
RemoveIpFromAllocatedIpMap(network, extClient.Address)
}
if extClient.Address6 != "" {
RemoveIpFromAllocatedIpMap(network, extClient.Address6)
}
if servercfg.CacheEnabled() {
deleteExtClientFromCache(key)
}
return nil
@@ -342,7 +342,6 @@ func SaveExtClient(extclient *models.ExtClient) error {
}
if servercfg.CacheEnabled() {
storeExtClientInCache(key, *extclient)
}
if _, ok := allocatedIpMap[extclient.Network]; ok {
if extclient.Address != "" {
AddIpToAllocatedIpMap(extclient.Network, net.ParseIP(extclient.Address))
@@ -351,6 +350,8 @@ func SaveExtClient(extclient *models.ExtClient) error {
AddIpToAllocatedIpMap(extclient.Network, net.ParseIP(extclient.Address6))
}
}
}
return SetNetworkNodesLastModified(extclient.Network)
}

View File

@@ -30,6 +30,9 @@ var (
// SetAllocatedIpMap - set allocated ip map for networks
func SetAllocatedIpMap() error {
if !servercfg.CacheEnabled() {
return nil
}
logger.Log(0, "start setting up allocated ip map")
if allocatedIpMap == nil {
allocatedIpMap = map[string]map[string]net.IP{}
@@ -84,16 +87,25 @@ func SetAllocatedIpMap() error {
// ClearAllocatedIpMap - set allocatedIpMap to nil
func ClearAllocatedIpMap() {
if !servercfg.CacheEnabled() {
return
}
allocatedIpMap = nil
}
func AddIpToAllocatedIpMap(networkName string, ip net.IP) {
if !servercfg.CacheEnabled() {
return
}
networkCacheMutex.Lock()
allocatedIpMap[networkName][ip.String()] = ip
networkCacheMutex.Unlock()
}
func RemoveIpFromAllocatedIpMap(networkName string, ip string) {
if !servercfg.CacheEnabled() {
return
}
networkCacheMutex.Lock()
delete(allocatedIpMap[networkName], ip)
networkCacheMutex.Unlock()
@@ -101,6 +113,10 @@ func RemoveIpFromAllocatedIpMap(networkName string, ip string) {
// AddNetworkToAllocatedIpMap - add network to allocated ip map when network is added
func AddNetworkToAllocatedIpMap(networkName string) {
//add new network to allocated ip map
if !servercfg.CacheEnabled() {
return
}
networkCacheMutex.Lock()
allocatedIpMap[networkName] = map[string]net.IP{}
networkCacheMutex.Unlock()
@@ -108,6 +124,9 @@ func AddNetworkToAllocatedIpMap(networkName string) {
// RemoveNetworkFromAllocatedIpMap - remove network from allocated ip map when network is deleted
func RemoveNetworkFromAllocatedIpMap(networkName string) {
if !servercfg.CacheEnabled() {
return
}
networkCacheMutex.Lock()
delete(allocatedIpMap, networkName)
networkCacheMutex.Unlock()
@@ -326,7 +345,7 @@ func GetNetworkSettings(networkname string) (models.Network, error) {
}
// UniqueAddress - get a unique ipv4 address
func UniqueAddress(networkName string, reverse bool) (net.IP, error) {
func UniqueAddressCache(networkName string, reverse bool) (net.IP, error) {
add := net.IP{}
var network models.Network
network, err := GetParentNetwork(networkName)
@@ -368,6 +387,49 @@ func UniqueAddress(networkName string, reverse bool) (net.IP, error) {
return add, errors.New("ERROR: No unique addresses available. Check network subnet")
}
// UniqueAddress - get a unique ipv4 address
func UniqueAddressDB(networkName string, reverse bool) (net.IP, error) {
add := net.IP{}
var network models.Network
network, err := GetParentNetwork(networkName)
if err != nil {
logger.Log(0, "UniqueAddressServer encountered an error")
return add, err
}
if network.IsIPv4 == "no" {
return add, fmt.Errorf("IPv4 not active on network " + networkName)
}
//ensure AddressRange is valid
if _, _, err := net.ParseCIDR(network.AddressRange); err != nil {
logger.Log(0, "UniqueAddress encountered an error")
return add, err
}
net4 := iplib.Net4FromStr(network.AddressRange)
newAddrs := net4.FirstAddress()
if reverse {
newAddrs = net4.LastAddress()
}
for {
if IsIPUnique(networkName, newAddrs.String(), database.NODES_TABLE_NAME, false) &&
IsIPUnique(networkName, newAddrs.String(), database.EXT_CLIENT_TABLE_NAME, false) {
return newAddrs, nil
}
if reverse {
newAddrs, err = net4.PreviousIP(newAddrs)
} else {
newAddrs, err = net4.NextIP(newAddrs)
}
if err != nil {
break
}
}
return add, errors.New("ERROR: No unique addresses available. Check network subnet")
}
// IsIPUnique - checks if an IP is unique
func IsIPUnique(network string, ip string, tableName string, isIpv6 bool) bool {
@@ -411,9 +473,67 @@ func IsIPUnique(network string, ip string, tableName string, isIpv6 bool) bool {
return isunique
}
func UniqueAddress(networkName string, reverse bool) (net.IP, error) {
if servercfg.CacheEnabled() {
return UniqueAddressCache(networkName, reverse)
}
return UniqueAddressDB(networkName, reverse)
}
// UniqueAddress6 - see if ipv6 address is unique
func UniqueAddress6(networkName string, reverse bool) (net.IP, error) {
if servercfg.CacheEnabled() {
return UniqueAddress6Cache(networkName, reverse)
}
return UniqueAddress6DB(networkName, reverse)
}
// UniqueAddress6DB - see if ipv6 address is unique
func UniqueAddress6DB(networkName string, reverse bool) (net.IP, error) {
add := net.IP{}
var network models.Network
network, err := GetParentNetwork(networkName)
if err != nil {
fmt.Println("Network Not Found")
return add, err
}
if network.IsIPv6 == "no" {
return add, fmt.Errorf("IPv6 not active on network " + networkName)
}
//ensure AddressRange is valid
if _, _, err := net.ParseCIDR(network.AddressRange6); err != nil {
return add, err
}
net6 := iplib.Net6FromStr(network.AddressRange6)
newAddrs, err := net6.NextIP(net6.FirstAddress())
if reverse {
newAddrs, err = net6.PreviousIP(net6.LastAddress())
}
if err != nil {
return add, err
}
for {
if IsIPUnique(networkName, newAddrs.String(), database.NODES_TABLE_NAME, true) &&
IsIPUnique(networkName, newAddrs.String(), database.EXT_CLIENT_TABLE_NAME, true) {
return newAddrs, nil
}
if reverse {
newAddrs, err = net6.PreviousIP(newAddrs)
} else {
newAddrs, err = net6.NextIP(newAddrs)
}
if err != nil {
break
}
}
return add, errors.New("ERROR: No unique IPv6 addresses available. Check network subnet")
}
// UniqueAddress6Cache - see if ipv6 address is unique using cache
func UniqueAddress6Cache(networkName string, reverse bool) (net.IP, error) {
add := net.IP{}
var network models.Network
network, err := GetParentNetwork(networkName)

View File

@@ -364,12 +364,15 @@ func DeleteNodeByID(node *models.Node) error {
logger.Log(1, "unable to remove metrics from DB for node", node.ID.String(), err.Error())
}
//recycle ip address
if servercfg.CacheEnabled() {
if node.Address.IP != nil {
RemoveIpFromAllocatedIpMap(node.Network, node.Address.IP.String())
}
if node.Address6.IP != nil {
RemoveIpFromAllocatedIpMap(node.Network, node.Address6.IP.String())
}
}
return nil
}
@@ -694,7 +697,6 @@ func createNode(node *models.Node) error {
if servercfg.CacheEnabled() {
storeNodeInCache(*node)
storeNodeInNetworkCache(*node, node.Network)
}
if _, ok := allocatedIpMap[node.Network]; ok {
if node.Address.IP != nil {
AddIpToAllocatedIpMap(node.Network, node.Address.IP)
@@ -703,6 +705,8 @@ func createNode(node *models.Node) error {
AddIpToAllocatedIpMap(node.Network, node.Address6.IP)
}
}
}
_, err = nodeacls.CreateNodeACL(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID.String()), defaultACLVal)
if err != nil {
logger.Log(1, "failed to create node ACL for node,", node.ID.String(), "err:", err.Error())
@@ -748,16 +752,14 @@ func ValidateParams(nodeid, netid string) (models.Node, error) {
func ValidateNodeIp(currentNode *models.Node, newNode *models.ApiNode) error {
if currentNode.Address.IP != nil && currentNode.Address.String() != newNode.Address {
newIp, _, _ := net.ParseCIDR(newNode.Address)
ipAllocated := allocatedIpMap[currentNode.Network]
if _, ok := ipAllocated[newIp.String()]; ok {
if !IsIPUnique(newNode.Network, newNode.Address, database.NODES_TABLE_NAME, false) ||
!IsIPUnique(newNode.Network, newNode.Address, database.EXT_CLIENT_TABLE_NAME, false) {
return errors.New("ip specified is already allocated: " + newNode.Address)
}
}
if currentNode.Address6.IP != nil && currentNode.Address6.String() != newNode.Address6 {
newIp, _, _ := net.ParseCIDR(newNode.Address6)
ipAllocated := allocatedIpMap[currentNode.Network]
if _, ok := ipAllocated[newIp.String()]; ok {
if !IsIPUnique(newNode.Network, newNode.Address6, database.NODES_TABLE_NAME, false) ||
!IsIPUnique(newNode.Network, newNode.Address6, database.EXT_CLIENT_TABLE_NAME, false) {
return errors.New("ip specified is already allocated: " + newNode.Address6)
}
}