in controllers/util/solr_update_util.go [551:616]
func EvictReplicasForPodIfNecessary(ctx context.Context, solrCloud *solr.SolrCloud, pod *corev1.Pod, podHasReplicas bool, evictionReason string, logger logr.Logger) (err error, canDeletePod bool, requestInProgress bool) {
logger = logger.WithValues("evictionReason", evictionReason)
// If the Cloud has 1 or zero pods, and this is the "-0" pod, then delete the data since we can't move it anywhere else
// Otherwise, move the replicas to other pods
if (solrCloud.Spec.Replicas == nil || *solrCloud.Spec.Replicas < 2) && strings.HasSuffix(pod.Name, "-0") {
queryParams := url.Values{}
queryParams.Add("action", "DELETENODE")
queryParams.Add("node", SolrNodeName(solrCloud, pod.Name))
// TODO: Figure out a way to do this, since DeleteNode will not delete the last replica of every type...
canDeletePod = true
} else {
requestId := "move-replicas-" + pod.Name
// First check to see if the Async Replace request has started
if asyncState, message, asyncErr := solr_api.CheckAsyncRequest(ctx, solrCloud, requestId); asyncErr != nil {
err = asyncErr
logger.Error(err, "Error occurred while checking the status of the ReplaceNode task. Will try again.", "requestId", requestId)
} else if asyncState == "notfound" {
if podHasReplicas {
// Submit new Replace Node request
replaceResponse := &solr_api.SolrAsyncResponse{}
queryParams := url.Values{}
queryParams.Add("action", "REPLACENODE")
queryParams.Add("parallel", "true")
queryParams.Add("sourceNode", SolrNodeName(solrCloud, pod.Name))
queryParams.Add("waitForFinalState", "true")
queryParams.Add("async", requestId)
err = solr_api.CallCollectionsApi(ctx, solrCloud, queryParams, replaceResponse)
if _, apiErr := solr_api.CheckForCollectionsApiError("REPLACENODE", replaceResponse.ResponseHeader, replaceResponse.Error); apiErr != nil {
err = apiErr
}
if err == nil {
logger.Info("Migrating all replicas off of pod before deletion.", "requestId", requestId, "pod", pod.Name)
requestInProgress = true
} else {
logger.Error(err, "Could not migrate all replicas off of pod before deletion. Will try again.")
}
} else {
canDeletePod = true
}
} else {
logger.Info("Found async status", "requestId", requestId, "state", asyncState)
// Only continue to delete the pod if the ReplaceNode request is complete and successful
if asyncState == "completed" {
canDeletePod = true
logger.Info("Migration of all replicas off of pod before deletion complete. Pod can now be deleted.", "pod", pod.Name)
} else if asyncState == "failed" {
logger.Info("Migration of all replicas off of pod before deletion failed. Will try again.", "pod", pod.Name, "message", message)
} else {
requestInProgress = true
}
// Delete the async request Id if the async request is successful or failed.
// If the request failed, this will cause a retry since the next reconcile won't find the async requestId in Solr.
if asyncState == "completed" || asyncState == "failed" {
if _, err = solr_api.DeleteAsyncRequest(ctx, solrCloud, requestId); err != nil {
logger.Error(err, "Could not delete Async request status.", "requestId", requestId)
canDeletePod = false
requestInProgress = true
}
}
}
}
return err, canDeletePod, requestInProgress
}