fix(monitor): select host that isn't in source hosts as target

This commit is contained in:
Zexi Li
2023-10-10 19:39:18 +08:00
parent 83d02d2bf0
commit b21702417a
3 changed files with 36 additions and 14 deletions

View File

@@ -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))

View File

@@ -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())
}

View File

@@ -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
}