| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- // 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"
- merrors "yunion.io/x/onecloud/pkg/monitor/errors"
- "yunion.io/x/onecloud/pkg/monitor/notifydrivers"
- )
- var (
- NotificationManager *SNotificationManager
- )
- func init() {
- NotificationManager = NewNotificationManager()
- }
- // +onecloud:swagger-gen-model-singular=alert_notification
- // +onecloud:swagger-gen-model-plural=alert_notifications
- type SNotificationManager struct {
- db.SVirtualResourceBaseManager
- }
- func NewNotificationManager() *SNotificationManager {
- man := &SNotificationManager{
- SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
- SNotification{},
- "notifications_tbl",
- "alert_notification",
- "alert_notifications",
- ),
- }
- man.SetAlias("notification", "notifications")
- man.SetVirtualObject(man)
- return man
- }
- type SNotification struct {
- db.SVirtualResourceBase
- Type string `nullable:"false" list:"user" create:"required"`
- IsDefault bool `nullable:"false" default:"false" list:"user" create:"optional" update:"user"`
- SendReminder bool `nullable:"false" default:"false" list:"user" create:"optional" update:"user"`
- DisableResolveMessage bool `nullable:"false" default:"false" list:"user" create:"optional" update:"user"`
- // unit is second
- Frequency int64 `nullable:"false" default:"0" list:"user" create:"optional" update:"user"`
- Settings jsonutils.JSONObject `nullable:"false" list:"user" create:"required" update:"user"`
- LastSendNotification time.Time `list:"user" create:"optional" update:"user"`
- }
- func (man *SNotificationManager) GetPlugin(typ string) (*notifydrivers.NotifierPlugin, error) {
- drv, err := notifydrivers.GetPlugin(typ)
- if err != nil {
- if errors.Cause(err) == notifydrivers.ErrUnsupportedNotificationType {
- return nil, httperrors.NewInputParameterError("unsupported notification type %s", typ)
- } else {
- return nil, err
- }
- }
- return drv, nil
- }
- func (man *SNotificationManager) GetNotification(id string) (*SNotification, error) {
- obj, err := man.FetchById(id)
- if err != nil {
- if errors.Cause(err) == sql.ErrNoRows {
- return nil, nil
- }
- return nil, err
- }
- return obj.(*SNotification), nil
- }
- func (man *SNotificationManager) GetNotifications(ids []string) ([]SNotification, error) {
- objs := make([]SNotification, 0)
- notis := man.Query().SubQuery()
- q := notis.Query().Filter(sqlchemy.In(notis.Field("id"), ids))
- if err := db.FetchModelObjects(man, q, &objs); err != nil {
- if err == sql.ErrNoRows {
- return nil, nil
- }
- return nil, err
- }
- return objs, nil
- }
- func (man *SNotificationManager) GetNotificationsWithDefault(ids []string) ([]SNotification, error) {
- objs := make([]SNotification, 0)
- notis := man.Query().SubQuery()
- q := notis.Query().Filter(sqlchemy.In(notis.Field("id"), ids))
- //sqlchemy.OR(
- // sqlchemy.IsTrue(notis.Field("is_default")),
- // sqlchemy.In(notis.Field("id"), ids)))
- if err := db.FetchModelObjects(man, q, &objs); err != nil {
- if err == sql.ErrNoRows {
- return nil, nil
- }
- return nil, err
- }
- return objs, nil
- }
- func (man *SNotificationManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, _ jsonutils.JSONObject, input monitor.NotificationCreateInput) (monitor.NotificationCreateInput, error) {
- if input.Type == "" {
- return input, merrors.NewArgIsEmptyErr("type")
- }
- if input.SendReminder == nil {
- sendReminder := true
- input.SendReminder = &sendReminder
- }
- if input.DisableResolveMessage == nil {
- dr := false
- input.DisableResolveMessage = &dr
- }
- plug, err := man.GetPlugin(input.Type)
- if err != nil {
- return input, err
- }
- return plug.ValidateCreateData(userCred, input)
- }
- func (man *SNotificationManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery,
- userCred mcclient.TokenCredential, input monitor.NotificationListInput) (*sqlchemy.SQuery, error) {
- q, err := man.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, input.VirtualResourceListInput)
- if err != nil {
- return nil, err
- }
- if len(input.Type) > 0 {
- q = q.Equals("type", input.Type)
- }
- return q, err
- }
- func (man *SNotificationManager) CreateOneCloudNotification(ctx context.Context, userCred mcclient.TokenCredential, alertName string, settings *monitor.NotificationSettingOneCloud, silentPeriod string) (*SNotification, error) {
- newName, err := db.GenerateName(ctx, man, userCred, alertName)
- if err != nil {
- return nil, errors.Wrapf(err, "generate name: %s", alertName)
- }
- input := &monitor.NotificationCreateInput{
- Name: newName,
- Type: monitor.AlertNotificationTypeOneCloud,
- Settings: jsonutils.Marshal(settings),
- }
- if silentPeriod != "" {
- duration, _ := time.ParseDuration(silentPeriod)
- input.Frequency = duration / time.Second
- }
- return man.createNotification(ctx, userCred, input)
- }
- func (man *SNotificationManager) CreateAutoMigrationNotification(ctx context.Context, userCred mcclient.TokenCredential, alert *SMigrationAlert) (*SNotification, error) {
- alertName := alert.GetName()
- newName, err := db.GenerateName(ctx, man, userCred, alertName)
- if err != nil {
- return nil, errors.Wrapf(err, "generate name: %s", alertName)
- }
- settings := monitor.NotificationSettingAutoMigration{
- AlertId: alert.GetId(),
- }
- input := &monitor.NotificationCreateInput{
- Name: newName,
- Type: monitor.AlertNotificationTypeAutoMigration,
- Settings: jsonutils.Marshal(settings),
- }
- return man.createNotification(ctx, userCred, input)
- }
- func (man *SNotificationManager) createNotification(ctx context.Context, userCred mcclient.TokenCredential, input *monitor.NotificationCreateInput) (*SNotification, error) {
- obj, err := db.DoCreate(man, ctx, userCred, nil, input.JSON(input), userCred)
- if err != nil {
- return nil, errors.Wrapf(err, "create notification input: %s", input.JSON(input))
- }
- return obj.(*SNotification), nil
- }
- func (n *SNotification) AttachToAlert(
- ctx context.Context,
- userCred mcclient.TokenCredential,
- alertId string) (*SAlertnotification, error) {
- alert, err := AlertManager.GetAlert(alertId)
- if err != nil {
- return nil, err
- }
- return alert.AttachNotification(ctx, userCred, n, monitor.AlertNotificationStateUnknown, "")
- }
- func (n *SNotification) GetAlertNotificationCount() (int, error) {
- alertNotis := AlertNotificationManager.Query()
- return alertNotis.Equals("notification_id", n.Id).CountWithError()
- }
- func (n *SNotification) IsAttached() (bool, error) {
- cnt, err := n.GetAlertNotificationCount()
- if err != nil {
- return false, err
- }
- return cnt > 0, nil
- }
- func (n *SNotification) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
- cnt, err := n.GetAlertNotificationCount()
- if err != nil {
- return err
- }
- if cnt > 0 {
- return httperrors.NewNotEmptyError("Alert notification used by %d alert", cnt)
- }
- return n.SVirtualResourceBase.ValidateDeleteCondition(ctx, nil)
- }
- func (n *SNotification) ShouldSendNotification() bool {
- if n.Frequency == 0 {
- return true
- }
- // 如果从未发送过通知(LastSendNotification 为零值),允许第一次发送
- if n.LastSendNotification.IsZero() {
- return true
- }
- if int64(time.Since(n.LastSendNotification)/time.Second)+int64(60) >= n.Frequency {
- return true
- }
- return false
- }
- func (n *SNotification) UpdateSendTime() error {
- _, err := db.Update(n, func() error {
- n.LastSendNotification = time.Now()
- return nil
- })
- return err
- }
|