Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(schd): returning list of preferred nodes for scheduling #2

Merged
merged 3 commits into from
Feb 2, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

n_: the comments needs to change to reflect the change in the logic.

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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q_: is it required to maintain backward compatibility for this API so that any of the CSI drivers using this method can still work, after this is merged and if they are using the latest code from this repo (without changing their code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will work even after the merge because of the gomod.

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