mirror of
https://github.com/datarhei/core.git
synced 2025-10-05 16:07:07 +08:00
124 lines
2.8 KiB
Go
124 lines
2.8 KiB
Go
package cluster
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"github.com/datarhei/core/v16/cluster/node"
|
|
)
|
|
|
|
type resourcePlanner struct {
|
|
nodes map[string]node.Resources
|
|
blocked map[string]struct{}
|
|
}
|
|
|
|
func NewResourcePlanner(nodes map[string]node.About) *resourcePlanner {
|
|
r := &resourcePlanner{
|
|
nodes: map[string]node.Resources{},
|
|
blocked: map[string]struct{}{},
|
|
}
|
|
|
|
for nodeid, about := range nodes {
|
|
r.nodes[nodeid] = about.Resources
|
|
if about.State != "online" {
|
|
r.blocked[nodeid] = struct{}{}
|
|
}
|
|
}
|
|
|
|
return r
|
|
}
|
|
|
|
func (r *resourcePlanner) Throttling(nodeid string, throttling bool) {
|
|
res, hasNode := r.nodes[nodeid]
|
|
if !hasNode {
|
|
return
|
|
}
|
|
|
|
res.IsThrottling = throttling
|
|
|
|
r.nodes[nodeid] = res
|
|
}
|
|
|
|
// HasNodeEnough returns whether a node has enough resources available for the
|
|
// requested cpu and memory consumption.
|
|
func (r *resourcePlanner) HasNodeEnough(nodeid string, cpu float64, mem uint64) bool {
|
|
res, hasNode := r.nodes[nodeid]
|
|
if !hasNode {
|
|
return false
|
|
}
|
|
|
|
if _, hasNode := r.blocked[nodeid]; hasNode {
|
|
return false
|
|
}
|
|
|
|
if res.Error == nil && res.CPU+cpu < res.CPULimit && res.Mem+mem < res.MemLimit && !res.IsThrottling {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// FindBestNodes returns an array of nodeids that can fit the requested cpu and memory requirements. If no
|
|
// such node is available, an empty array is returned. The array is sorted by the most suitable node first.
|
|
func (r *resourcePlanner) FindBestNodes(cpu float64, mem uint64) []string {
|
|
nodes := []string{}
|
|
|
|
for id := range r.nodes {
|
|
if r.HasNodeEnough(id, cpu, mem) {
|
|
nodes = append(nodes, id)
|
|
}
|
|
}
|
|
|
|
sort.SliceStable(nodes, func(i, j int) bool {
|
|
nodeA, nodeB := nodes[i], nodes[j]
|
|
|
|
if r.nodes[nodeA].CPU != r.nodes[nodeB].CPU {
|
|
return r.nodes[nodeA].CPU < r.nodes[nodeB].CPU
|
|
}
|
|
|
|
return r.nodes[nodeA].Mem <= r.nodes[nodeB].Mem
|
|
})
|
|
|
|
return nodes
|
|
}
|
|
|
|
// Add adds the resources of the node according to the cpu and memory utilization.
|
|
func (r *resourcePlanner) Add(nodeid string, cpu float64, mem uint64) {
|
|
res, hasRes := r.nodes[nodeid]
|
|
if !hasRes {
|
|
return
|
|
}
|
|
|
|
res.CPU += cpu
|
|
res.Mem += mem
|
|
r.nodes[nodeid] = res
|
|
}
|
|
|
|
// Remove subtracts the resources from the node according to the cpu and memory utilization.
|
|
func (r *resourcePlanner) Remove(nodeid string, cpu float64, mem uint64) {
|
|
res, hasRes := r.nodes[nodeid]
|
|
if !hasRes {
|
|
return
|
|
}
|
|
|
|
res.CPU -= cpu
|
|
if res.CPU < 0 {
|
|
res.CPU = 0
|
|
}
|
|
if mem >= res.Mem {
|
|
res.Mem = 0
|
|
} else {
|
|
res.Mem -= mem
|
|
}
|
|
r.nodes[nodeid] = res
|
|
}
|
|
|
|
// Move adjusts the resources from the target and source node according to the cpu and memory utilization.
|
|
func (r *resourcePlanner) Move(target, source string, cpu float64, mem uint64) {
|
|
r.Add(target, cpu, mem)
|
|
r.Remove(source, cpu, mem)
|
|
}
|
|
|
|
func (r *resourcePlanner) Map() map[string]node.Resources {
|
|
return r.nodes
|
|
}
|