| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- 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"
- )
- func setHostCurrent(host IHost, vals map[string]float64, key string) error {
- val, ok := vals[key]
- if !ok {
- return errors.Errorf("not found %q in vals %#v", key, vals)
- }
- host.SetCurrent(val)
- return nil
- }
- type cpuUsageActive struct{}
- func newCPUUsageActive() IMetricDriver {
- return &cpuUsageActive{}
- }
- func (c *cpuUsageActive) GetType() monitor.MigrationAlertMetricType {
- return monitor.MigrationAlertMetricTypeCPUUsageActive
- }
- func (c *cpuUsageActive) GetTsdbQuery() *TsdbQuery {
- return &TsdbQuery{
- Database: monitor.METRIC_DATABASE_TELE,
- Measurement: "cpu",
- Fields: []string{"usage_active"},
- }
- }
- func (c *cpuUsageActive) GetCandidate(obj jsonutils.JSONObject, host IHost, ds *tsdb.DataSource) (ICandidate, error) {
- return newCPUCandidate(obj, host.GetHostResource(), ds)
- }
- func (c *cpuUsageActive) SetHostCurrent(host IHost, vals map[string]float64) error {
- return setHostCurrent(host, vals, "usage_active")
- }
- func (c *cpuUsageActive) GetTarget(host jsonutils.JSONObject) (ITarget, error) {
- return newTargetCPUHost(host)
- }
- func (ma *cpuUsageActive) GetCondition(s *monitor.AlertSetting) (ICondition, error) {
- t, err := GetAlertSettingThreshold(s)
- if err != nil {
- return nil, errors.Wrap(err, "GetAlertSettingThreshold")
- }
- return newCPUCond(t), nil
- }
- // cpuCondition implements ICondition
- type cpuCondition struct {
- value float64
- }
- func newCPUCond(val float64) ICondition {
- return &cpuCondition{
- value: val,
- }
- }
- func (c *cpuCondition) GetThreshold() float64 {
- return c.value
- }
- func (c *cpuCondition) GetSourceThresholdDelta(threshold float64, host IHost) float64 {
- // cpu.usage_active
- return host.GetCurrent() - threshold
- }
- 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()
- 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 calculated score is 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())
- }
- // cpuCandidate implements ICandidate
- type cpuCandidate struct {
- *guestResource
- usageActive float64
- guestCPUCount int
- hostCPUCount int
- }
- func newCPUCandidate(gst jsonutils.JSONObject, host *HostResource, ds *tsdb.DataSource) (ICandidate, error) {
- res, err := newGuestResource(gst, host.GetName())
- if err != nil {
- return nil, errors.Wrap(err, "newGuestResource")
- }
- gstCPUCount, err := res.guest.Int("vcpu_count")
- if err != nil {
- return nil, errors.Wrap(err, "get vcpu_count")
- }
- // fetch metric from influxdb
- metrics, err := InfluxdbQuery(ds, "vm_id", []IResource{res}, &TsdbQuery{
- Database: monitor.METRIC_DATABASE_TELE,
- Measurement: "vm_cpu",
- Fields: []string{"usage_active"},
- })
- if err != nil {
- return nil, errors.Wrapf(err, "InfluxdbQuery guest %q(%q)", res.GetName(), res.GetId())
- }
- metric := metrics.Get(res.GetId())
- if metric == nil {
- return nil, errors.Errorf("not found resource %q metric from %#v", res.GetId(), metrics.indexes)
- }
- usage := metric.Values["usage_active"]
- return &cpuCandidate{
- guestResource: res,
- usageActive: usage,
- guestCPUCount: int(gstCPUCount),
- hostCPUCount: int(host.cpuCount),
- }, nil
- }
- func (c cpuCandidate) GetScore() float64 {
- return c.getTargetScore(c.hostCPUCount)
- }
- func (c cpuCandidate) getTargetScore(tCPUCnt int) float64 {
- score := c.usageActive * (float64(c.guestCPUCount) / float64(tCPUCnt))
- return score
- }
- type cpuHost struct {
- *HostResource
- usageActive float64
- }
- func newCPUHost(obj jsonutils.JSONObject) (IHost, error) {
- host, err := newHostResource(obj)
- if err != nil {
- return nil, errors.Wrap(err, "newHostResource")
- }
- return &cpuHost{
- HostResource: host,
- }, nil
- }
- func (h *cpuHost) GetCurrent() float64 {
- return h.usageActive
- }
- func (h *cpuHost) SetCurrent(val float64) IHost {
- h.usageActive = val
- return h
- }
- func (h *cpuHost) Compare(oh IHost) bool {
- return h.GetCurrent() < oh.GetCurrent()
- }
- type targetCPUHost struct {
- IHost
- }
- func newTargetCPUHost(obj jsonutils.JSONObject) (ITarget, error) {
- host, err := newCPUHost(obj)
- if err != nil {
- return nil, errors.Wrap(err, "newCPUHost")
- }
- ts := &targetCPUHost{
- IHost: host,
- }
- return ts, nil
- }
- func (ts *targetCPUHost) Selected(c ICandidate) ITarget {
- ts.SetCurrent(ts.GetCurrent() + c.GetScore())
- return ts
- }
- func (ts *targetCPUHost) GetCPUCount() int {
- return int(ts.IHost.(*cpuHost).cpuCount)
- }
|