func()

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}
}