mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-06-08 23:45:40 +08:00
fix(monitor): select host that isn't in source hosts as target
This commit is contained in:
@@ -92,7 +92,7 @@ type ICondition interface {
|
||||
GetThreshold() float64
|
||||
// GetSourceThresholdDelta must > 0
|
||||
GetSourceThresholdDelta(threshold float64, srcHost IHost) float64
|
||||
IsFitTarget(t ITarget, c ICandidate) error
|
||||
IsFitTarget(settings *monitor.MigrationAlertSettings, t ITarget, c ICandidate) error
|
||||
}
|
||||
|
||||
type Rules struct {
|
||||
@@ -439,15 +439,13 @@ func findResult(rules *Rules) (*result, error) {
|
||||
// return nil, errors.Wrap(err, "find source candidates to migrate")
|
||||
// }
|
||||
|
||||
// all guests of source host to migrate
|
||||
guests := rules.Source.Candidates
|
||||
|
||||
// TODO
|
||||
// 将找到的 guests 进行配对,调用 scheduler-forecast 接口判断能否迁移到宿主机
|
||||
// 如果不能迁就提出这些 guests,重新 findCandidates
|
||||
|
||||
// 将找到的虚拟机分配到对应的宿主机,形成 1-1 配对
|
||||
return pairMigratResult(guests, rules.Target, rules.Condtion, rules.ResultMustPair)
|
||||
settings, _ := rules.GetAlert().GetMigrationSettings()
|
||||
return pairMigratResult(settings, rules.Source, rules.Target, rules.Condtion, rules.ResultMustPair)
|
||||
}
|
||||
|
||||
type IResource interface {
|
||||
@@ -541,13 +539,13 @@ func findCandidates(src *SourceRule, cond ICondition) ([]ICandidate, error) {
|
||||
return findFitCandidates(cds, delta)
|
||||
}
|
||||
|
||||
func findFitTarget(c ICandidate, targets iTargets, cond ICondition) (ITarget, error) {
|
||||
func findFitTarget(settings *monitor.MigrationAlertSettings, c ICandidate, tr *TargetRule, targets iTargets, cond ICondition) (ITarget, error) {
|
||||
// sort targets
|
||||
sort.Sort(targets)
|
||||
var errs []error
|
||||
for i := range targets {
|
||||
target := targets[i]
|
||||
if err := cond.IsFitTarget(target, c); err == nil {
|
||||
if err := cond.IsFitTarget(settings, target, c); err == nil {
|
||||
return target, nil
|
||||
} else {
|
||||
errs = append(errs, err)
|
||||
@@ -556,12 +554,17 @@ func findFitTarget(c ICandidate, targets iTargets, cond ICondition) (ITarget, er
|
||||
return nil, errors.NewAggregate(errs)
|
||||
}
|
||||
|
||||
func pairMigratResult(gsts []ICandidate, target *TargetRule, cond ICondition, mustPair bool) (*result, error) {
|
||||
func pairMigratResult(
|
||||
settings *monitor.MigrationAlertSettings,
|
||||
src *SourceRule, target *TargetRule, cond ICondition, mustPair bool) (*result, error) {
|
||||
// all guests of source host to migrate
|
||||
gsts := src.Candidates
|
||||
|
||||
pairs := make([]*resultPair, 0)
|
||||
hosts := target.Items
|
||||
errs := []error{}
|
||||
for _, gst := range gsts {
|
||||
host, err := findFitTarget(gst, hosts, cond)
|
||||
host, err := findFitTarget(settings, gst, target, hosts, cond)
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, "not found target for guest %s on %s", gst.GetName(), gst.GetHostName())
|
||||
if mustPair {
|
||||
@@ -579,11 +582,11 @@ func pairMigratResult(gsts []ICandidate, target *TargetRule, cond ICondition, mu
|
||||
}
|
||||
if len(gsts) != len(pairs) {
|
||||
if mustPair {
|
||||
return nil, errors.Wrapf(errors.NewAggregate(errs), "Paired: %d candidates != %d hosts", len(gsts), len(pairs))
|
||||
return nil, errors.Errorf("%v: Paired: %d candidates != %d hosts", errors.NewAggregate(errs), len(gsts), len(pairs))
|
||||
}
|
||||
}
|
||||
if len(pairs) == 0 {
|
||||
return nil, errors.Wrapf(errors.NewAggregate(errs), "Not found any pairs, mustPair is %v", mustPair)
|
||||
return nil, errors.Errorf("%v: Not found any pairs, mustPair is %v", errors.NewAggregate(errs), mustPair)
|
||||
}
|
||||
if !mustPair && len(errs) != 0 {
|
||||
log.Warningf("some guest not paired: %v", errors.NewAggregate(errs))
|
||||
|
||||
@@ -16,7 +16,9 @@ package balancer
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/sets"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/monitor"
|
||||
"yunion.io/x/onecloud/pkg/monitor/tsdb"
|
||||
@@ -89,11 +91,28 @@ func (c *cpuCondition) GetSourceThresholdDelta(threshold float64, host IHost) fl
|
||||
return host.GetCurrent() - threshold
|
||||
}
|
||||
|
||||
func (m *cpuCondition) IsFitTarget(t ITarget, c ICandidate) error {
|
||||
func (m *cpuCondition) IsFitTarget(settings *monitor.MigrationAlertSettings, t ITarget, c ICandidate) error {
|
||||
src := settings.Source
|
||||
srcHostIds := []string{}
|
||||
if src != nil {
|
||||
srcHostIds = src.HostIds
|
||||
}
|
||||
tCPUCnt := t.(*targetCPUHost).GetCPUCount()
|
||||
if t.GetCurrent()+c.(*cpuCandidate).getTargetScore(tCPUCnt) < m.GetThreshold() {
|
||||
tScore := t.GetCurrent() + c.(*cpuCandidate).getTargetScore(tCPUCnt)
|
||||
ltThreshold := tScore < m.GetThreshold()
|
||||
if ltThreshold {
|
||||
return nil
|
||||
}
|
||||
|
||||
MAX_THRESHOLD := 95.0
|
||||
// only when srcHostIds isn't empty
|
||||
if len(srcHostIds) != 0 {
|
||||
if !ltThreshold && !sets.NewString(srcHostIds...).Has(t.GetId()) && tScore < MAX_THRESHOLD {
|
||||
// if target host is not in source specified hosts and calculate score less than MAX_THRESHOLD
|
||||
log.Infof("let host:%s:current(%f) + guest:%s:score(%f) < MAX_THRESHOLD(%f) to fit target, because it's not in source specified hosts", t.GetName(), t.GetCurrent(), c.GetName(), c.GetScore(), MAX_THRESHOLD)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.Errorf("host:%s:current(%f) + guest:%s:score(%f) >= threshold(%f)", t.GetName(), t.GetCurrent(), c.GetName(), c.GetScore(), m.GetThreshold())
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ func (m *memCondition) GetSourceThresholdDelta(threshold float64, host IHost) fl
|
||||
return threshold - host.GetCurrent()
|
||||
}
|
||||
|
||||
func (m *memCondition) IsFitTarget(t ITarget, c ICandidate) error {
|
||||
func (m *memCondition) IsFitTarget(settings *monitor.MigrationAlertSettings, t ITarget, c ICandidate) error {
|
||||
if t.GetCurrent()-c.GetScore() > m.GetThreshold() {
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user