Skip to content

Commit 6083ef6

Browse files
authored
feat(schd): returning list of preferred nodes for scheduling (#2)
The scheduler should return list of preferred nodes for scheduling. It is up to the user of this libary which can pick first node in the preferred list or can try on all the nodes in the order returned by the scheduler. This can solve the issue where csi controller is not able to create the volume on first node, it can pick the next one in the list. Use the requisite list if preferred is not provided Signed-off-by: Pawan <[email protected]>
1 parent a64be5d commit 6083ef6

File tree

1 file changed

+53
-22
lines changed

1 file changed

+53
-22
lines changed

pkg/scheduler/scheduler.go

+53-22
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,22 @@ limitations under the License.
1717
package scheduler
1818

1919
import (
20-
"math"
20+
"sort"
2121

2222
"github.com/container-storage-interface/spec/lib/go/csi"
2323
k8sapi "github.com/openebs/lib-csi/pkg/client/k8s"
2424
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2525
"k8s.io/klog"
2626
)
2727

28+
// key value struct for creating the filtered list
29+
type kv struct {
30+
Key string
31+
Value int64
32+
}
33+
2834
// getNodeList gets the nodelist which satisfies the topology info
29-
func getNodeList(topo *csi.TopologyRequirement) ([]string, error) {
35+
func getNodeList(topo []*csi.Topology) ([]string, error) {
3036

3137
var nodelist []string
3238

@@ -36,7 +42,7 @@ func getNodeList(topo *csi.TopologyRequirement) ([]string, error) {
3642
}
3743

3844
for _, node := range list.Items {
39-
for _, prf := range topo.Preferred {
45+
for _, prf := range topo {
4046
nodeFiltered := false
4147
for key, value := range prf.Segments {
4248
if node.Labels[key] != value {
@@ -54,45 +60,70 @@ func getNodeList(topo *csi.TopologyRequirement) ([]string, error) {
5460
return nodelist, nil
5561
}
5662

57-
// runScheduler goes through the node mapping
58-
// in the topology and picks the node which is less weighted
59-
func runScheduler(nodelist []string, nmap map[string]int64) string {
60-
var selected string
63+
// runScheduler goes through the node mapping in the topology
64+
// and creates the list of preferred nodes as per their weight
65+
func runScheduler(nodelist []string, nmap map[string]int64) []string {
66+
var preferred []string
67+
var fmap []kv
6168

62-
var weight int64 = math.MaxInt64
63-
64-
// schedule it on the node which has less weight
69+
// go though the filtered node and prepare the preferred list
6570
for _, node := range nodelist {
66-
if nmap[node] < weight {
67-
selected = node
68-
weight = nmap[node]
71+
if val, ok := nmap[node]; ok {
72+
// create the filtered node map
73+
fmap = append(fmap, kv{node, val})
74+
} else {
75+
// put the non occupied nodes in beginning of the list
76+
preferred = append(preferred, node)
6977
}
7078
}
71-
return selected
79+
80+
// sort the filtered node map
81+
sort.Slice(fmap, func(i, j int) bool {
82+
return fmap[i].Value < fmap[j].Value
83+
})
84+
85+
// put the occupied nodes in the sorted order at the end
86+
for _, kv := range fmap {
87+
preferred = append(preferred, kv.Key)
88+
}
89+
90+
return preferred
7291
}
7392

7493
// Scheduler schedules the PV as per topology constraints for
7594
// the given node weight.
76-
func Scheduler(req *csi.CreateVolumeRequest, nmap map[string]int64) string {
77-
topo := req.AccessibilityRequirements
78-
if topo == nil ||
79-
len(topo.Preferred) == 0 {
95+
func Scheduler(req *csi.CreateVolumeRequest, nmap map[string]int64) []string {
96+
var nodelist []string
97+
areq := req.AccessibilityRequirements
98+
99+
if areq == nil {
100+
klog.Errorf("scheduler: Accessibility Requirements not provided")
101+
return nodelist
102+
}
103+
104+
topo := areq.Preferred
105+
if len(topo) == 0 {
106+
// if preferred list is empty, use the requisite
107+
topo = areq.Requisite
108+
}
109+
110+
if len(topo) == 0 {
80111
klog.Errorf("scheduler: topology information not provided")
81-
return ""
112+
return nodelist
82113
}
83114

84115
nodelist, err := getNodeList(topo)
85116
if err != nil {
86117
klog.Errorf("scheduler: can not get the nodelist err : %v", err.Error())
87-
return ""
118+
return nodelist
88119
} else if len(nodelist) == 0 {
89120
klog.Errorf("scheduler: nodelist is empty")
90-
return ""
121+
return nodelist
91122
}
92123

93124
// if there is a single node, schedule it on that
94125
if len(nodelist) == 1 {
95-
return nodelist[0]
126+
return nodelist
96127
}
97128

98129
return runScheduler(nodelist, nmap)

0 commit comments

Comments
 (0)