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 util.HandleCrash() podID := pod.Name podNamespace := pod.Namespace backoff.wait(podID) // Get the pod again; it may have changed/been scheduled already. pod = &api.Pod{} err := factory.Client.Get().Namespace(podNamespace).Resource("pods").Name(podID).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.Add(pod) } }() } }
// queuedPodStore: pods queued before processing. // cache: scheduler cache that might contain assumed pods. func setupTestSchedulerWithOnePodOnNode(t *testing.T, queuedPodStore *clientcache.FIFO, scache schedulercache.Cache, nodeLister algorithm.FakeNodeLister, predicateMap map[string]algorithm.FitPredicate, pod *api.Pod, node *api.Node) (*Scheduler, chan *api.Binding, chan error) { scheduler, bindingChan, errChan := setupTestScheduler(queuedPodStore, scache, nodeLister, predicateMap) queuedPodStore.Add(pod) // queuedPodStore: [foo:8080] // cache: [] scheduler.scheduleOne() // queuedPodStore: [] // cache: [(assumed)foo:8080] select { case b := <-bindingChan: expectBinding := &api.Binding{ ObjectMeta: api.ObjectMeta{Name: pod.Name}, Target: api.ObjectReference{Kind: "Node", Name: node.Name}, } if !reflect.DeepEqual(expectBinding, b) { t.Errorf("binding want=%v, get=%v", expectBinding, b) } case <-time.After(wait.ForeverTestTimeout): t.Fatalf("timeout after %v", wait.ForeverTestTimeout) } return scheduler, bindingChan, errChan }
// queuedPodStore: pods queued before processing. // cache: scheduler cache that might contain assumed pods. func setupTestSchedulerWithOnePod(t *testing.T, queuedPodStore *clientcache.FIFO, scache schedulercache.Cache, pod *api.Pod) (*Scheduler, chan *api.Binding, chan error) { // Create the scheduler config algo := NewGenericScheduler( scache, map[string]algorithm.FitPredicate{"PodFitsHostPorts": predicates.PodFitsHostPorts}, []algorithm.PriorityConfig{}, []algorithm.SchedulerExtender{}) bindingChan := make(chan *api.Binding, 1) errChan := make(chan error, 1) cfg := &Config{ SchedulerCache: scache, NodeLister: algorithm.FakeNodeLister( []*api.Node{{ObjectMeta: api.ObjectMeta{Name: "machine1"}}}, ), Algorithm: algo, Binder: fakeBinder{func(b *api.Binding) error { bindingChan <- b return nil }}, NextPod: func() *api.Pod { return clientcache.Pop(queuedPodStore).(*api.Pod) }, Error: func(p *api.Pod, err error) { errChan <- err }, Recorder: &record.FakeRecorder{}, PodConditionUpdater: fakePodConditionUpdater{}, } scheduler := New(cfg) queuedPodStore.Add(pod) // queuedPodStore: [foo:8080] // cache: [] scheduler.scheduleOne() // queuedPodStore: [] // cache: [(assumed)foo:8080] select { case b := <-bindingChan: expectBinding := &api.Binding{ ObjectMeta: api.ObjectMeta{Name: "pod.Name"}, Target: api.ObjectReference{Kind: "Node", Name: "machine1"}, } if !reflect.DeepEqual(expectBinding, b) { t.Errorf("binding want=%v, get=%v", expectBinding, b) } case <-time.After(wait.ForeverTestTimeout): t.Fatalf("timeout after %v", wait.ForeverTestTimeout) } return scheduler, bindingChan, errChan }