| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- // 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 models
- import (
- "context"
- "database/sql"
- "time"
- "yunion.io/x/jsonutils"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/sqlchemy"
- "yunion.io/x/onecloud/pkg/apis/monitor"
- "yunion.io/x/onecloud/pkg/cloudcommon/db"
- "yunion.io/x/onecloud/pkg/httperrors"
- "yunion.io/x/onecloud/pkg/mcclient"
- )
- var (
- migrationAlertMan *SMigrationAlertManager
- )
- func init() {
- migrationAlertMan = GetMigrationAlertManager()
- }
- func GetMigrationAlertManager() *SMigrationAlertManager {
- if migrationAlertMan != nil {
- return migrationAlertMan
- }
- migrationAlertMan = &SMigrationAlertManager{
- SAlertManager: *NewAlertManager(SMigrationAlert{}, "migrationalert", "migrationalerts"),
- }
- migrationAlertMan.SetVirtualObject(migrationAlertMan)
- return migrationAlertMan
- }
- // +onecloud:swagger-gen-model-singular=migrationalert
- // +onecloud:swagger-gen-model-plural=migrationalerts
- type SMigrationAlertManager struct {
- SAlertManager
- }
- type SMigrationAlert struct {
- SAlert
- MetricType string `create:"admin_required" list:"admin" get:"admin"`
- MigrateNotes jsonutils.JSONObject `nullable:"true" list:"admin" get:"admin" update:"admin" create:"admin_optional"`
- }
- type MigrateNoteGuest struct {
- Id string `json:"id"`
- Name string `json:"name"`
- HostId string `json:"host_id"`
- Host string `json:"host"`
- VCPUCount int `json:"vcpu_count"`
- VMemSize int `json:"vmem_size"`
- Score float64 `json:"score"`
- }
- type MigrateNoteTarget struct {
- Id string `json:"id"`
- Name string `json:"name"`
- Score float64 `json:"score"`
- }
- type MigrateNote struct {
- Guest *MigrateNoteGuest `json:"guest"`
- Target *MigrateNoteTarget `json:"target_host"`
- Error string `json:"error"`
- }
- func (m *SMigrationAlertManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query monitor.MigrationAlertListInput) (*sqlchemy.SQuery, error) {
- q, err := m.SAlertManager.ListItemFilter(ctx, q, userCred, query.AlertListInput)
- if err != nil {
- return nil, err
- }
- if len(query.MetricType) > 0 {
- q = q.Equals("metric_type", query.MetricType)
- }
- q = q.Equals("used_by", AlertNotificationUsedByMigrationAlert)
- return q, nil
- }
- func (m *SMigrationAlertManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input *monitor.MigrationAlertCreateInput) (*monitor.MigrationAlertCreateInput, error) {
- if input.Period == "" {
- input.Period = "5m"
- }
- if _, err := time.ParseDuration(input.Period); err != nil {
- return nil, httperrors.NewInputParameterError("Invalid period format: %s", input.Period)
- }
- if err := monitor.IsValidMigrationAlertMetricType(input.MetricType); err != nil {
- return nil, httperrors.NewInputParameterError("Invalid metric_type %v", err)
- }
- if input.MigrationSettings == nil {
- input.MigrationSettings = &monitor.MigrationAlertSettings{
- Source: new(monitor.MigrationAlertSettingsSource),
- Target: new(monitor.MigrationAlertSettingsTarget),
- }
- }
- if err := m.ValidateMigrationSettings(input.MigrationSettings); err != nil {
- return nil, errors.Wrap(err, "validate migration settings")
- }
- aInput := *(input.ToAlertCreateInput())
- aInput, err := AlertManager.ValidateCreateData(ctx, userCred, nil, query, aInput)
- if err != nil {
- return input, errors.Wrap(err, "AlertManager.ValidateCreateData")
- }
- input.AlertCreateInput = aInput
- return input, nil
- }
- func (m *SMigrationAlertManager) ValidateMigrationSettings(s *monitor.MigrationAlertSettings) error {
- if s.Source != nil {
- if err := m.ValidateMigrationSettingsSource(s.Source); err != nil {
- return errors.Wrap(err, "validate source")
- }
- }
- if s.Target != nil {
- if err := m.ValidateMigrationSettingsTarget(s.Target); err != nil {
- return errors.Wrap(err, "validate target")
- }
- }
- return nil
- }
- func (m *SMigrationAlertManager) GetResourceByIdOrName(rType string, id string) (jsonutils.JSONObject, error) {
- ok, objs := MonitorResourceManager.GetResourceObjByResType(rType)
- if !ok {
- return nil, errors.Errorf("Get by %q", rType)
- }
- for _, obj := range objs {
- name, _ := obj.GetString("name")
- if name == id {
- return obj, nil
- }
- objId, _ := obj.GetString("id")
- if objId == id {
- return obj, nil
- }
- }
- return nil, errors.Errorf("Not found resource %q by %q", rType, id)
- }
- func (m *SMigrationAlertManager) GetHostByIdOrName(id string) (jsonutils.JSONObject, error) {
- return m.GetResourceByIdOrName(monitor.METRIC_RES_TYPE_HOST, id)
- }
- func (m *SMigrationAlertManager) GetGuestByIdOrName(id string) (jsonutils.JSONObject, error) {
- return m.GetResourceByIdOrName(monitor.METRIC_RES_TYPE_GUEST, id)
- }
- func (m *SMigrationAlertManager) validateResource(vf func(idOrName string) (jsonutils.JSONObject, error), ids []string) ([]string, error) {
- nIds := make([]string, len(ids))
- for idx, idName := range ids {
- obj, err := vf(idName)
- if err != nil {
- return nil, errors.Wrapf(err, "find by %s", idName)
- }
- id, err := obj.GetString("id")
- if err != nil {
- return nil, errors.Wrap(err, "get id")
- }
- nIds[idx] = id
- }
- return nIds, nil
- }
- func (m *SMigrationAlertManager) ValidateMigrationSettingsSource(input *monitor.MigrationAlertSettingsSource) error {
- if len(input.HostIds) != 0 {
- hIds, err := m.validateResource(m.GetHostByIdOrName, input.HostIds)
- if err != nil {
- return errors.Wrap(err, "validate host")
- }
- input.HostIds = hIds
- }
- if len(input.GuestIds) != 0 {
- gIds, err := m.validateResource(m.GetGuestByIdOrName, input.GuestIds)
- if err != nil {
- return errors.Wrap(err, "validate guest")
- }
- input.GuestIds = gIds
- }
- return nil
- }
- func (m *SMigrationAlertManager) ValidateMigrationSettingsTarget(input *monitor.MigrationAlertSettingsTarget) error {
- if len(input.HostIds) != 0 {
- hIds, err := m.validateResource(m.GetHostByIdOrName, input.HostIds)
- if err != nil {
- return errors.Wrap(err, "validate host")
- }
- input.HostIds = hIds
- }
- return nil
- }
- func (alert *SMigrationAlert) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
- out := new(monitor.MigrationAlertCreateInput)
- if err := data.Unmarshal(out); err != nil {
- return errors.Wrap(err, "Unmarshal to MigrationAlertCreateInput")
- }
- fs := out.GetMetricDriver().GetQueryFields()
- alert.ResType = string(fs.ResourceType)
- alert.UsedBy = AlertNotificationUsedByMigrationAlert
- if err := alert.SAlert.CustomizeCreate(ctx, userCred, ownerId, query, data); err != nil {
- return errors.Wrap(err, "SAlert.CustomizeCreate")
- }
- return alert.CreateNotification(ctx, userCred)
- }
- func (m *SMigrationAlertManager) FetchAllMigrationAlerts() ([]SMigrationAlert, error) {
- objs := make([]SMigrationAlert, 0)
- q := m.Query()
- q = q.IsTrue("enabled")
- err := db.FetchModelObjects(m, q, &objs)
- if err != nil && err != sql.ErrNoRows {
- return nil, errors.Wrap(err, "db.FetchModelObjects")
- }
- return objs, nil
- }
- func (m *SMigrationAlertManager) GetInMigrationAlerts() ([]*SMigrationAlert, error) {
- alerts, err := m.FetchAllMigrationAlerts()
- if err != nil {
- return nil, errors.Wrap(err, "FetchAllMigrationAlerts")
- }
- objs := make([]*SMigrationAlert, 0)
- for _, a := range alerts {
- if ok, _, _ := a.IsInMigrationProcess(); ok {
- tmp := a
- objs = append(objs, &tmp)
- }
- }
- return objs, nil
- }
- func (alert *SMigrationAlert) GetMigrateNotes() (map[string]MigrateNote, error) {
- if alert.MigrateNotes == nil {
- return make(map[string]MigrateNote, 0), nil
- }
- objs := make(map[string]MigrateNote, 0)
- if err := alert.MigrateNotes.Unmarshal(&objs); err != nil {
- return nil, errors.Wrap(err, "Unmarshal")
- }
- return objs, nil
- }
- func (alert *SMigrationAlert) SetMigrateNote(ctx context.Context, ns *MigrateNote, isDelete bool) error {
- _, err := db.UpdateWithLock(ctx, alert, func() error {
- curNotes, err := alert.GetMigrateNotes()
- if err != nil {
- return errors.Wrap(err, "GetMigrateNotes")
- }
- if isDelete {
- delete(curNotes, ns.Guest.Id)
- } else {
- curNotes[ns.Guest.Id] = *ns
- }
- alert.MigrateNotes = jsonutils.Marshal(curNotes)
- return nil
- })
- return err
- }
- func (alert *SMigrationAlert) IsInMigrationProcess() (bool, map[string]MigrateNote, error) {
- notes, err := alert.GetMigrateNotes()
- if err != nil {
- return false, nil, errors.Wrap(err, "GetMigrateNotes")
- }
- if len(notes) == 0 {
- return false, nil, nil
- }
- return true, nil, nil
- }
- func (alert *SMigrationAlert) GetMigrationSettings() (*monitor.MigrationAlertSettings, error) {
- if alert.CustomizeConfig == nil {
- return nil, errors.Errorf("CustomizeConfig is nil")
- }
- out := new(monitor.MigrationAlertSettings)
- if err := alert.CustomizeConfig.Unmarshal(out); err != nil {
- return nil, err
- }
- return out, nil
- }
- func (alert *SMigrationAlert) CreateNotification(ctx context.Context, userCred mcclient.TokenCredential) error {
- if alert.Id == "" {
- alert.Id = db.DefaultUUIDGenerator()
- }
- noti, err := NotificationManager.CreateAutoMigrationNotification(ctx, userCred, alert)
- if err != nil {
- return errors.Wrap(err, "CreateAutoMigrationNotification")
- }
- if _, err := alert.AttachNotification(ctx, userCred, noti, monitor.AlertNotificationStateUnknown, ""); err != nil {
- return errors.Wrap(err, "alert.AttachNotification")
- }
- return nil
- }
- func (alert *SMigrationAlert) GetMetricType() monitor.MigrationAlertMetricType {
- return monitor.MigrationAlertMetricType(alert.MetricType)
- }
- func (alert *SMigrationAlert) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
- if err := alert.deleteNotifications(ctx, userCred, query, data); err != nil {
- return errors.Wrap(err, "delete related notification")
- }
- return alert.SAlert.CustomizeDelete(ctx, userCred, query, data)
- }
|