mirror of
				https://github.com/datarhei/core.git
				synced 2025-10-31 03:16:21 +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
 | |
| }
 | 
