in pkg/pool/pool.go [415:528]
func (p *pool) ReconcilePool() *worker.WarmPoolJob {
p.lock.Lock()
defer p.lock.Unlock()
// Total created resources includes all the resources for the instance that are not yet deleted
numWarmResources := numResourcesFromMap(p.warmResources)
totalCreatedResources := numWarmResources + len(p.usedResources) + len(p.coolDownQueue) +
p.pendingCreate + p.pendingDelete
log := p.log.WithValues("resync", p.reSyncRequired, "warm", numWarmResources, "used",
len(p.usedResources), "pending create", p.pendingCreate, "pending delete", p.pendingDelete,
"cool down queue", len(p.coolDownQueue), "total resources", totalCreatedResources, "capacity", p.capacity)
if p.reSyncRequired {
// If Pending operations are present then we can't re-sync as the upstream
// and pool could change during re-sync
if p.pendingCreate != 0 || p.pendingDelete != 0 {
p.log.Info("cannot re-sync as there are pending add/delete request")
return &worker.WarmPoolJob{
Operations: worker.OperationReconcileNotRequired,
}
}
p.log.Info("submitting request re-sync the pool")
return worker.NewWarmPoolReSyncJob(p.nodeName)
}
if len(p.usedResources)+p.pendingCreate+p.pendingDelete+len(p.coolDownQueue) == p.capacity {
log.V(1).Info("cannot reconcile, at max capacity")
return &worker.WarmPoolJob{Operations: worker.OperationReconcileNotRequired}
}
// Consider pending create as well so we don't create multiple subsequent create request
// deviation represents the difference between the desired number of resources and the current state
// A negative deviation means IP resources need to be deleted to reach the desired state
// A positive deviation means IP resources need to be created to reach the desired state
var deviation int
if p.isPDPool {
deviation = p.getPDDeviation()
} else {
deviation = p.calculateSecondaryIPDeviation()
}
// Need to create more resources for warm pool
if deviation > p.warmPoolConfig.MaxDeviation {
// The maximum number of resources that can be created
canCreateUpto := p.capacity - totalCreatedResources
if canCreateUpto == 0 {
return &worker.WarmPoolJob{Operations: worker.OperationReconcileNotRequired}
}
// Need to add to warm pool
if deviation > canCreateUpto {
log.V(1).Info("can only create limited resources", "can create", canCreateUpto,
"requested", deviation, "desired", deviation)
deviation = canCreateUpto
}
// Increment the pending to the size of deviation, once we get async response on creation success we can decrement
// pending
p.pendingCreate += deviation
log.Info("created job to add resources to warm pool", "pendingCreate", p.pendingCreate,
"requested count", deviation)
if p.isPDPool {
return worker.NewWarmPoolCreateJob(p.nodeName, deviation/NumIPv4AddrPerPrefix)
}
return worker.NewWarmPoolCreateJob(p.nodeName, deviation)
} else if -deviation > p.warmPoolConfig.MaxDeviation {
// Need to delete from warm pool
deviation = -deviation
var resourceToDelete []string
numToDelete := deviation
if numToDelete > 0 {
var freeResourceGroups []string
if p.isPDPool {
// for prefix IP pool, each resource group is a /28 IPv4 prefix, which contains 16 IPv4 addresses
freeResourceGroups = findFreeGroup(p.warmResources, NumIPv4AddrPerPrefix)
} else {
// for secondary IP pool, each resource group only contains 1 IPv4 address
freeResourceGroups = findFreeGroup(p.warmResources, 1)
}
if len(freeResourceGroups) > 0 {
// Remove resources to be deleted from the warm pool
for _, groupID := range freeResourceGroups {
if numToDelete <= 0 {
break
}
log.Info("removing free resource group from warm pool", "group id", groupID,
"# resources deleted", len(p.warmResources[groupID]))
resourceToDelete = append(resourceToDelete, groupID)
numToDelete -= len(p.warmResources[groupID])
// Increment pending to the number of resource being deleted, once successfully deleted the count can be decremented
p.pendingDelete += len(p.warmResources[groupID])
delete(p.warmResources, groupID)
}
} else {
log.Info("no warm resources to delete", "deviation", deviation, "numToDelete", numToDelete)
}
}
if len(resourceToDelete) > 0 {
// Submit the job to delete resources
log.Info("created job to delete resources from warm pool", "pendingDelete", p.pendingDelete,
"resources to delete", resourceToDelete)
return worker.NewWarmPoolDeleteJob(p.nodeName, resourceToDelete)
}
}
log.V(1).Info("no need for reconciliation")
return &worker.WarmPoolJob{Operations: worker.OperationReconcileNotRequired}
}