func setupTestSchedulerLongBindingWithRetry(queuedPodStore *clientcache.FIFO, scache schedulercache.Cache, nodeLister algorithm.FakeNodeLister, predicateMap map[string]algorithm.FitPredicate, stop chan struct{}, bindingTime time.Duration) (*Scheduler, chan *v1.Binding) { algo := NewGenericScheduler( scache, predicateMap, algorithm.EmptyMetadataProducer, []algorithm.PriorityConfig{}, algorithm.EmptyMetadataProducer, []algorithm.SchedulerExtender{}) bindingChan := make(chan *v1.Binding, 2) cfg := &Config{ SchedulerCache: scache, NodeLister: nodeLister, Algorithm: algo, Binder: fakeBinder{func(b *v1.Binding) error { time.Sleep(bindingTime) bindingChan <- b return nil }}, NextPod: func() *v1.Pod { return clientcache.Pop(queuedPodStore).(*v1.Pod) }, Error: func(p *v1.Pod, err error) { queuedPodStore.AddIfNotPresent(p) }, Recorder: &record.FakeRecorder{}, PodConditionUpdater: fakePodConditionUpdater{}, StopEverything: stop, } return New(cfg), bindingChan }
func (factory *ConfigFactory) makeDefaultErrorFunc(backoff *podBackoff, podQueue *cache.FIFO) func(pod *v1.Pod, err error) { return func(pod *v1.Pod, err error) { if err == scheduler.ErrNoNodesAvailable { glog.V(4).Infof("Unable to schedule %v %v: no nodes are registered to the cluster; waiting", pod.Namespace, pod.Name) } else { glog.Errorf("Error scheduling %v %v: %v; retrying", pod.Namespace, pod.Name, err) } backoff.gc() // Retry asynchronously. // Note that this is extremely rudimentary and we need a more real error handling path. go func() { defer runtime.HandleCrash() podID := types.NamespacedName{ Namespace: pod.Namespace, Name: pod.Name, } entry := backoff.getEntry(podID) if !entry.TryWait(backoff.maxDuration) { glog.Warningf("Request for pod %v already in flight, abandoning", podID) return } // Get the pod again; it may have changed/been scheduled already. getBackoff := initialGetBackoff for { pod, err := factory.Client.Core().Pods(podID.Namespace).Get(podID.Name, metav1.GetOptions{}) if err == nil { if len(pod.Spec.NodeName) == 0 { podQueue.AddIfNotPresent(pod) } break } if errors.IsNotFound(err) { glog.Warningf("A pod %v no longer exists", podID) return } glog.Errorf("Error getting pod %v for retry: %v; retrying...", podID, err) if getBackoff = getBackoff * 2; getBackoff > maximalGetBackoff { getBackoff = maximalGetBackoff } time.Sleep(getBackoff) } }() } }
func (factory *ConfigFactory) makeDefaultErrorFunc(backoff *podBackoff, podQueue *cache.FIFO) func(pod *api.Pod, err error) { return func(pod *api.Pod, err error) { if err == scheduler.ErrNoNodesAvailable { glog.V(4).Infof("Unable to schedule %v %v: no nodes are registered to the cluster; waiting", pod.Namespace, pod.Name) } else { glog.Errorf("Error scheduling %v %v: %v; retrying", pod.Namespace, pod.Name, err) } backoff.gc() // Retry asynchronously. // Note that this is extremely rudimentary and we need a more real error handling path. go func() { defer runtime.HandleCrash() podID := types.NamespacedName{ Namespace: pod.Namespace, Name: pod.Name, } entry := backoff.getEntry(podID) if !entry.TryWait(backoff.maxDuration) { glog.Warningf("Request for pod %v already in flight, abandoning", podID) return } // Get the pod again; it may have changed/been scheduled already. pod = &api.Pod{} err := factory.Client.Get().Namespace(podID.Namespace).Resource("pods").Name(podID.Name).Do().Into(pod) if err != nil { if !errors.IsNotFound(err) { glog.Errorf("Error getting pod %v for retry: %v; abandoning", podID, err) } return } if pod.Spec.NodeName == "" { podQueue.AddIfNotPresent(pod) } }() } }