Skip to content

Commit

Permalink
feat(schd): returning list of preferred nodes for scheduling (#2)
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
pawanpraka1 authored Feb 2, 2021
1 parent a64be5d commit 6083ef6
Showing 1 changed file with 53 additions and 22 deletions.
75 changes: 53 additions & 22 deletions pkg/scheduler/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,22 @@ limitations under the License.
package scheduler

import (
"math"
"sort"

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

// key value struct for creating the filtered list
type kv struct {
Key string
Value int64
}

// getNodeList gets the nodelist which satisfies the topology info
func getNodeList(topo *csi.TopologyRequirement) ([]string, error) {
func getNodeList(topo []*csi.Topology) ([]string, error) {

var nodelist []string

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

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

// runScheduler goes through the node mapping
// in the topology and picks the node which is less weighted
func runScheduler(nodelist []string, nmap map[string]int64) string {
var selected string
// runScheduler goes through the node mapping in the topology
// and creates the list of preferred nodes as per their weight
func runScheduler(nodelist []string, nmap map[string]int64) []string {
var preferred []string
var fmap []kv

var weight int64 = math.MaxInt64

// schedule it on the node which has less weight
// go though the filtered node and prepare the preferred list
for _, node := range nodelist {
if nmap[node] < weight {
selected = node
weight = nmap[node]
if val, ok := nmap[node]; ok {
// create the filtered node map
fmap = append(fmap, kv{node, val})
} else {
// put the non occupied nodes in beginning of the list
preferred = append(preferred, node)
}
}
return selected

// sort the filtered node map
sort.Slice(fmap, func(i, j int) bool {
return fmap[i].Value < fmap[j].Value
})

// put the occupied nodes in the sorted order at the end
for _, kv := range fmap {
preferred = append(preferred, kv.Key)
}

return preferred
}

// Scheduler schedules the PV as per topology constraints for
// the given node weight.
func Scheduler(req *csi.CreateVolumeRequest, nmap map[string]int64) string {
topo := req.AccessibilityRequirements
if topo == nil ||
len(topo.Preferred) == 0 {
func Scheduler(req *csi.CreateVolumeRequest, nmap map[string]int64) []string {
var nodelist []string
areq := req.AccessibilityRequirements

if areq == nil {
klog.Errorf("scheduler: Accessibility Requirements not provided")
return nodelist
}

topo := areq.Preferred
if len(topo) == 0 {
// if preferred list is empty, use the requisite
topo = areq.Requisite
}

if len(topo) == 0 {
klog.Errorf("scheduler: topology information not provided")
return ""
return nodelist
}

nodelist, err := getNodeList(topo)
if err != nil {
klog.Errorf("scheduler: can not get the nodelist err : %v", err.Error())
return ""
return nodelist
} else if len(nodelist) == 0 {
klog.Errorf("scheduler: nodelist is empty")
return ""
return nodelist
}

// if there is a single node, schedule it on that
if len(nodelist) == 1 {
return nodelist[0]
return nodelist
}

return runScheduler(nodelist, nmap)
Expand Down

0 comments on commit 6083ef6

Please sign in to comment.