From b21702417ac1802db0b2e16c2ffa4e9985702a9e Mon Sep 17 00:00:00 2001 From: Zexi Li Date: Tue, 10 Oct 2023 19:39:18 +0800 Subject: [PATCH] fix(monitor): select host that isn't in source hosts as target --- pkg/monitor/controller/balancer/balancer.go | 25 ++++++++++++--------- pkg/monitor/controller/balancer/cpu.go | 23 +++++++++++++++++-- pkg/monitor/controller/balancer/mem.go | 2 +- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/pkg/monitor/controller/balancer/balancer.go b/pkg/monitor/controller/balancer/balancer.go index c42fb324b9..b99c849910 100644 --- a/pkg/monitor/controller/balancer/balancer.go +++ b/pkg/monitor/controller/balancer/balancer.go @@ -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)) diff --git a/pkg/monitor/controller/balancer/cpu.go b/pkg/monitor/controller/balancer/cpu.go index c1cfaf1d86..b9a2dc4389 100644 --- a/pkg/monitor/controller/balancer/cpu.go +++ b/pkg/monitor/controller/balancer/cpu.go @@ -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()) } diff --git a/pkg/monitor/controller/balancer/mem.go b/pkg/monitor/controller/balancer/mem.go index 379a2d247d..fc4a860ef0 100644 --- a/pkg/monitor/controller/balancer/mem.go +++ b/pkg/monitor/controller/balancer/mem.go @@ -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 }