meteralert.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package models
  15. import (
  16. "context"
  17. "time"
  18. "yunion.io/x/jsonutils"
  19. "yunion.io/x/log"
  20. "yunion.io/x/pkg/errors"
  21. "yunion.io/x/sqlchemy"
  22. "yunion.io/x/onecloud/pkg/apis/monitor"
  23. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  24. "yunion.io/x/onecloud/pkg/httperrors"
  25. "yunion.io/x/onecloud/pkg/mcclient"
  26. "yunion.io/x/onecloud/pkg/mcclient/auth"
  27. "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
  28. merrors "yunion.io/x/onecloud/pkg/monitor/errors"
  29. "yunion.io/x/onecloud/pkg/monitor/options"
  30. "yunion.io/x/onecloud/pkg/util/stringutils2"
  31. )
  32. const (
  33. MeterAlertMetadataType = "type"
  34. MeterAlertMetadataProjectId = "project_id"
  35. MeterAlertMetadataAccountId = "account_id"
  36. MeterAlertMetadataProvider = "provider"
  37. )
  38. var MeterAlertManager *SMeterAlertManager
  39. func init() {
  40. MeterAlertManager = NewMeterAlertManager()
  41. }
  42. type IMeterAlertDriver interface {
  43. GetType() string
  44. GetName() string
  45. GetFor() time.Duration
  46. ToAlertCreateInput(input monitor.MeterAlertCreateInput, allAccountIds []string, level string) monitor.AlertCreateInput
  47. }
  48. // +onecloud:swagger-gen-ignore
  49. type SMeterAlertManager struct {
  50. SV1AlertManager
  51. drivers map[string]IMeterAlertDriver
  52. }
  53. func NewMeterAlertManager() *SMeterAlertManager {
  54. man := &SMeterAlertManager{
  55. SV1AlertManager: SV1AlertManager{
  56. SAlertManager: *NewAlertManager(SMeterAlert{}, "meteralert", "meteralerts"),
  57. },
  58. }
  59. man.SetVirtualObject(man)
  60. man.registerDriver(man.newDailyFeeDriver())
  61. man.registerDriver(man.newMonthFeeDriver())
  62. return man
  63. }
  64. // +onecloud:swagger-gen-ignore
  65. type SMeterAlert struct {
  66. SV1Alert
  67. }
  68. func (man *SMeterAlertManager) newDailyFeeDriver() IMeterAlertDriver {
  69. return new(sMeterDailyFee)
  70. }
  71. func (man *SMeterAlertManager) newMonthFeeDriver() IMeterAlertDriver {
  72. return new(sMeterMonthFee)
  73. }
  74. func (man *SMeterAlertManager) registerDriver(drv IMeterAlertDriver) {
  75. if man.drivers == nil {
  76. man.drivers = make(map[string]IMeterAlertDriver, 0)
  77. }
  78. man.drivers[drv.GetType()] = drv
  79. }
  80. func (man *SMeterAlertManager) GetDriver(typ string) IMeterAlertDriver {
  81. return man.drivers[typ]
  82. }
  83. func (man *SMeterAlertManager) genName(ctx context.Context, ownerId mcclient.IIdentityProvider, hint string) (string, error) {
  84. return db.GenerateName(ctx, man, ownerId, hint)
  85. }
  86. func (man *SMeterAlertManager) getAllBillAccounts(ctx context.Context) ([]jsonutils.JSONObject, error) {
  87. s := auth.GetAdminSession(ctx, options.Options.Region)
  88. results := make([]jsonutils.JSONObject, 0)
  89. for {
  90. q := jsonutils.NewDict()
  91. q.Add(jsonutils.NewString("system"), "scope")
  92. q.Add(jsonutils.NewInt(int64(len(results))), "offset")
  93. q.Add(jsonutils.NewInt(20), "limit")
  94. ret, err := compute.Cloudaccounts.List(s, q)
  95. if err != nil {
  96. return nil, err
  97. }
  98. if len(ret.Data) == 0 {
  99. break
  100. }
  101. results = append(results, ret.Data...)
  102. if ret.Total <= len(results) {
  103. break
  104. }
  105. }
  106. return results, nil
  107. }
  108. func (man *SMeterAlertManager) getAllBillAccountIds(ctx context.Context) ([]string, error) {
  109. objs, err := man.getAllBillAccounts(ctx)
  110. if err != nil {
  111. return nil, err
  112. }
  113. ids := make([]string, len(objs))
  114. for idx, obj := range objs {
  115. id, err := obj.GetString("id")
  116. if err != nil {
  117. return nil, err
  118. }
  119. ids[idx] = id
  120. }
  121. return ids, nil
  122. }
  123. func (man *SMeterAlertManager) ValidateCreateData(
  124. ctx context.Context, userCred mcclient.TokenCredential,
  125. ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject,
  126. data monitor.MeterAlertCreateInput) (*monitor.MeterAlertCreateInput, error) {
  127. if data.Period == "" {
  128. // default 30 minutes
  129. data.Period = "30m"
  130. }
  131. if data.Window == "" {
  132. // default 5 minutes
  133. data.Window = "5m"
  134. }
  135. if _, err := time.ParseDuration(data.Period); err != nil {
  136. return nil, httperrors.NewInputParameterError("Invalid period format: %s", data.Period)
  137. }
  138. drv := man.GetDriver(data.Type)
  139. if drv == nil {
  140. return nil, httperrors.NewInputParameterError("not support type %q", data.Type)
  141. }
  142. name, err := man.genName(ctx, ownerId, drv.GetName())
  143. if err != nil {
  144. return nil, err
  145. }
  146. allAccountIds := []string{}
  147. if data.AccountId == "" {
  148. allAccountIds, err = man.getAllBillAccountIds(ctx)
  149. if err != nil {
  150. return nil, err
  151. }
  152. }
  153. if data.Recipients == "" {
  154. return nil, merrors.NewArgIsEmptyErr("recipients")
  155. }
  156. alertInput := drv.ToAlertCreateInput(data, allAccountIds, data.Level)
  157. alertInput, err = AlertManager.ValidateCreateData(ctx, userCred, ownerId, query, alertInput)
  158. if err != nil {
  159. return nil, err
  160. }
  161. data.AlertCreateInput = alertInput
  162. data.Name = name
  163. return &data, nil
  164. }
  165. type sMeterDailyFee struct{}
  166. func (_ *sMeterDailyFee) GetType() string {
  167. return monitor.MeterAlertTypeDailyResFee
  168. }
  169. func (_ *sMeterDailyFee) GetName() string {
  170. return "日消费"
  171. }
  172. func (_ *sMeterDailyFee) GetFor() time.Duration {
  173. return 12 * time.Hour
  174. }
  175. func (f *sMeterDailyFee) ToAlertCreateInput(
  176. input monitor.MeterAlertCreateInput,
  177. allAccountIds []string,
  178. level string,
  179. ) monitor.AlertCreateInput {
  180. freq, _ := time.ParseDuration(input.Window)
  181. customizeConfig := monitor.MeterCustomizeConfig{
  182. Name: f.GetName(),
  183. }
  184. ret := monitor.AlertCreateInput{
  185. Name: f.GetName(),
  186. Level: level,
  187. Frequency: int64(freq / time.Second),
  188. CustomizeConfig: jsonutils.Marshal(customizeConfig),
  189. Settings: GetMeterAlertSetting(input,
  190. "account_daily_resfee",
  191. "meter_db", allAccountIds, "sumDate"),
  192. }
  193. return ret
  194. }
  195. type sMeterMonthFee struct{}
  196. func (_ *sMeterMonthFee) GetType() string {
  197. return monitor.MeterAlertTypeMonthResFee
  198. }
  199. func (_ *sMeterMonthFee) GetName() string {
  200. return "月消费"
  201. }
  202. func (_ *sMeterMonthFee) GetFor() time.Duration {
  203. return 24 * time.Hour
  204. }
  205. func (f *sMeterMonthFee) ToAlertCreateInput(
  206. input monitor.MeterAlertCreateInput,
  207. allAccountIds []string,
  208. level string,
  209. ) monitor.AlertCreateInput {
  210. freq, _ := time.ParseDuration(input.Window)
  211. customizeConfig := monitor.MeterCustomizeConfig{
  212. Name: f.GetName(),
  213. }
  214. ret := monitor.AlertCreateInput{
  215. Name: f.GetName(),
  216. Level: level,
  217. Frequency: int64(freq / time.Second),
  218. CustomizeConfig: jsonutils.Marshal(customizeConfig),
  219. Settings: GetMeterAlertSetting(input,
  220. "account_month_resfee",
  221. "meter_db", allAccountIds, "sumMonth"),
  222. }
  223. return ret
  224. }
  225. func GetMeterAlertSetting(
  226. input monitor.MeterAlertCreateInput,
  227. measurement string,
  228. db string,
  229. accountIds []string,
  230. groupByStr string,
  231. ) monitor.AlertSetting {
  232. q, reducer, eval := GetMeterAlertQuery(input, measurement, db, accountIds, groupByStr)
  233. return monitor.AlertSetting{
  234. Conditions: []monitor.AlertCondition{
  235. {
  236. Type: "query",
  237. Operator: "and",
  238. Query: monitor.AlertQuery{
  239. Model: q,
  240. From: input.Period,
  241. To: "now",
  242. },
  243. Reducer: reducer,
  244. Evaluator: eval,
  245. },
  246. },
  247. }
  248. }
  249. func GetMeterAlertQuery(
  250. input monitor.MeterAlertCreateInput,
  251. measurement string,
  252. db string,
  253. allAccountIds []string,
  254. groupByStr string,
  255. ) (
  256. monitor.MetricQuery,
  257. monitor.Condition,
  258. monitor.Condition) {
  259. var (
  260. evaluator, reducer monitor.Condition
  261. alertType, field string
  262. filters []monitor.MetricQueryTag
  263. )
  264. groupBy := []monitor.MetricQueryPart{}
  265. evaluator = monitor.GetNodeAlertEvaluator(input.Comparator, input.Threshold)
  266. if input.AccountId == "" {
  267. reducer = monitor.Condition{Type: "sum"}
  268. alertType = "overview"
  269. field = "sum"
  270. for _, aId := range allAccountIds {
  271. filters = append(filters, monitor.MetricQueryTag{
  272. Key: "accountId",
  273. Value: aId,
  274. Condition: "or",
  275. })
  276. }
  277. } else {
  278. reducer = monitor.Condition{Type: "avg"}
  279. alertType = "account"
  280. field = input.Type
  281. groupBy = append(groupBy, monitor.MetricQueryPart{
  282. Type: "field",
  283. Params: []string{field},
  284. })
  285. filters = append(filters, monitor.MetricQueryTag{
  286. Key: "accountId",
  287. Value: input.AccountId,
  288. Condition: "and",
  289. })
  290. filters = append(filters, monitor.MetricQueryTag{
  291. Key: "provider",
  292. Value: input.Provider,
  293. })
  294. }
  295. log.Debugf("meteralert alertType: %s", alertType)
  296. if input.ProjectId != "" {
  297. filters = append(filters, monitor.MetricQueryTag{
  298. Key: "projectId",
  299. Value: input.ProjectId,
  300. })
  301. }
  302. groupBy = append(groupBy, monitor.MetricQueryPart{
  303. Type: "field",
  304. Params: []string{groupByStr},
  305. })
  306. sels := make([]monitor.MetricQuerySelect, 0)
  307. sels = append(sels, monitor.NewMetricQuerySelect(
  308. monitor.MetricQueryPart{
  309. Type: "field",
  310. Params: []string{input.Type},
  311. }))
  312. q := monitor.MetricQuery{
  313. Selects: sels,
  314. Tags: filters,
  315. GroupBy: groupBy,
  316. Measurement: measurement,
  317. Database: db,
  318. }
  319. return q, reducer, evaluator
  320. }
  321. func (man *SMeterAlertManager) GetAlert(id string) (*SMeterAlert, error) {
  322. obj, err := man.FetchById(id)
  323. if err != nil {
  324. return nil, err
  325. }
  326. return obj.(*SMeterAlert), nil
  327. }
  328. func (man *SMeterAlertManager) ListItemFilter(
  329. ctx context.Context,
  330. q *sqlchemy.SQuery,
  331. userCred mcclient.TokenCredential,
  332. query monitor.MeterAlertListInput,
  333. ) (*sqlchemy.SQuery, error) {
  334. q, err := man.SV1AlertManager.ListItemFilter(ctx, q, userCred, query.V1AlertListInput)
  335. if err != nil {
  336. return nil, errors.Wrap(err, "SV1AlertManager.ListItemFilter")
  337. }
  338. q.Equals("used_by", AlertNotificationUsedByMeterAlert)
  339. return q, nil
  340. }
  341. func (man *SMeterAlertManager) OrderByExtraFields(
  342. ctx context.Context,
  343. q *sqlchemy.SQuery,
  344. userCred mcclient.TokenCredential,
  345. query monitor.MeterAlertListInput,
  346. ) (*sqlchemy.SQuery, error) {
  347. var err error
  348. q, err = man.SV1AlertManager.OrderByExtraFields(ctx, q, userCred, query.V1AlertListInput)
  349. if err != nil {
  350. return nil, errors.Wrap(err, "SV1AlertManager.OrderByExtraFields")
  351. }
  352. return q, nil
  353. }
  354. func (man *SMeterAlertManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
  355. var err error
  356. q, err = man.SV1AlertManager.QueryDistinctExtraField(q, field)
  357. if err == nil {
  358. return q, nil
  359. }
  360. return q, httperrors.ErrNotFound
  361. }
  362. func (man *SMeterAlertManager) CustomizeFilterList(
  363. ctx context.Context, q *sqlchemy.SQuery,
  364. userCred mcclient.TokenCredential, query jsonutils.JSONObject) (
  365. *db.CustomizeListFilters, error) {
  366. filters, err := man.SV1AlertManager.CustomizeFilterList(ctx, q, userCred, query)
  367. if err != nil {
  368. return nil, err
  369. }
  370. input := new(monitor.MeterAlertListInput)
  371. if err := query.Unmarshal(input); err != nil {
  372. return nil, err
  373. }
  374. wrapF := func(f func(obj *SMeterAlert) (bool, error)) func(object jsonutils.JSONObject) (bool, error) {
  375. return func(data jsonutils.JSONObject) (bool, error) {
  376. id, err := data.GetString("id")
  377. if err != nil {
  378. return false, err
  379. }
  380. obj, err := man.GetAlert(id)
  381. if err != nil {
  382. return false, err
  383. }
  384. return f(obj)
  385. }
  386. }
  387. if input.Type != "" {
  388. filters.Append(wrapF(func(obj *SMeterAlert) (bool, error) {
  389. return obj.getType() == input.Type, nil
  390. }))
  391. }
  392. if input.AccountId != "" {
  393. filters.Append(wrapF(func(obj *SMeterAlert) (bool, error) {
  394. return obj.getAccountId() == input.AccountId, nil
  395. }))
  396. }
  397. if input.Provider != "" {
  398. filters.Append(wrapF(func(obj *SMeterAlert) (bool, error) {
  399. return obj.getProvider() == input.Provider, nil
  400. }))
  401. }
  402. if input.ProjectId != "" {
  403. filters.Append(wrapF(func(obj *SMeterAlert) (bool, error) {
  404. return obj.getProjectId() == input.ProjectId, nil
  405. }))
  406. }
  407. return filters, nil
  408. }
  409. func (alert *SMeterAlert) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
  410. if err := alert.SAlert.CustomizeCreate(ctx, userCred, ownerId, query, data); err != nil {
  411. return err
  412. }
  413. input := new(monitor.MeterAlertCreateInput)
  414. if err := data.Unmarshal(input); err != nil {
  415. return err
  416. }
  417. return alert.SV1Alert.CustomizeCreate(ctx, userCred, input.Type, input.Channel, input.Recipients, AlertNotificationUsedByMeterAlert)
  418. }
  419. func (alert *SMeterAlert) setType(ctx context.Context, userCred mcclient.TokenCredential, t string) error {
  420. return alert.SetMetadata(ctx, MeterAlertMetadataType, t, userCred)
  421. }
  422. func (alert *SMeterAlert) getType() string {
  423. return alert.GetMetadata(context.Background(), MeterAlertMetadataType, nil)
  424. }
  425. func (alert *SMeterAlert) setProjectId(ctx context.Context, userCred mcclient.TokenCredential, id string) error {
  426. return alert.SetMetadata(ctx, MeterAlertMetadataProjectId, id, userCred)
  427. }
  428. func (alert *SMeterAlert) getProjectId() string {
  429. return alert.GetMetadata(context.Background(), MeterAlertMetadataProjectId, nil)
  430. }
  431. func (alert *SMeterAlert) setAccountId(ctx context.Context, userCred mcclient.TokenCredential, id string) error {
  432. return alert.SetMetadata(ctx, MeterAlertMetadataAccountId, id, userCred)
  433. }
  434. func (alert *SMeterAlert) getAccountId() string {
  435. return alert.GetMetadata(context.Background(), MeterAlertMetadataAccountId, nil)
  436. }
  437. func (alert *SMeterAlert) setProvider(ctx context.Context, userCred mcclient.TokenCredential, p string) error {
  438. return alert.SetMetadata(ctx, MeterAlertMetadataProvider, p, userCred)
  439. }
  440. func (alert *SMeterAlert) getProvider() string {
  441. return alert.GetMetadata(context.Background(), MeterAlertMetadataProvider, nil)
  442. }
  443. func (alert *SMeterAlert) PostCreate(ctx context.Context,
  444. userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider,
  445. query jsonutils.JSONObject, data jsonutils.JSONObject) {
  446. alert.SStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
  447. input := new(monitor.MeterAlertCreateInput)
  448. if err := data.Unmarshal(input); err != nil {
  449. log.Errorf("post create unmarshal input: %v", err)
  450. return
  451. }
  452. if input.Type != "" {
  453. if err := alert.setType(ctx, userCred, input.Type); err != nil {
  454. log.Errorf("set type: %v", err)
  455. }
  456. }
  457. if input.Provider != "" {
  458. if err := alert.setProvider(ctx, userCred, input.Provider); err != nil {
  459. log.Errorf("set proider: %v", err)
  460. }
  461. }
  462. if input.AccountId != "" {
  463. if err := alert.setAccountId(ctx, userCred, input.AccountId); err != nil {
  464. log.Errorf("set account_id: %v", err)
  465. }
  466. }
  467. if input.ProjectId != "" {
  468. if err := alert.setProjectId(ctx, userCred, input.ProjectId); err != nil {
  469. log.Errorf("set project_id: %v", err)
  470. }
  471. }
  472. forTime := MeterAlertManager.GetDriver(alert.getType()).GetFor()
  473. if err := alert.SetFor(forTime); err != nil {
  474. log.Errorf("set for error: %v", err)
  475. }
  476. }
  477. func (man *SMeterAlertManager) FetchCustomizeColumns(
  478. ctx context.Context,
  479. userCred mcclient.TokenCredential,
  480. query jsonutils.JSONObject,
  481. objs []interface{},
  482. fields stringutils2.SSortedStrings,
  483. isList bool,
  484. ) []monitor.MeterAlertDetails {
  485. rows := make([]monitor.MeterAlertDetails, len(objs))
  486. v1Rows := man.SV1AlertManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  487. for i := range rows {
  488. rows[i] = monitor.MeterAlertDetails{
  489. AlertV1Details: v1Rows[i],
  490. }
  491. rows[i], _ = objs[i].(*SMeterAlert).getMoreDetails(rows[i])
  492. }
  493. return rows
  494. }
  495. func (alert *SMeterAlert) getExtraDetails(
  496. ctx context.Context,
  497. userCred mcclient.TokenCredential,
  498. query jsonutils.JSONObject,
  499. isList bool,
  500. ) (monitor.MeterAlertDetails, error) {
  501. ret := MeterAlertManager.FetchCustomizeColumns(ctx, userCred, query, []interface{}{alert}, nil, isList)
  502. if len(ret) == 0 {
  503. return monitor.MeterAlertDetails{}, errors.Error("empty meter alert details")
  504. }
  505. return ret[0], nil
  506. }
  507. func (alert *SMeterAlert) getMoreDetails(out monitor.MeterAlertDetails) (monitor.MeterAlertDetails, error) {
  508. var err error
  509. out.AlertV1Details, err = alert.SV1Alert.getMoreDetails(out.AlertV1Details, AlertNotificationUsedByMeterAlert)
  510. if err != nil {
  511. return out, errors.Wrap(err, "SV1Alert.getMoreDetails")
  512. }
  513. out.Type = alert.getType()
  514. out.ProjectId = alert.getProjectId()
  515. out.Provider = alert.getProvider()
  516. out.AccountId = alert.getAccountId()
  517. return out, nil
  518. }
  519. func (alert *SMeterAlert) ValidateUpdateData(
  520. ctx context.Context,
  521. userCred mcclient.TokenCredential,
  522. query jsonutils.JSONObject,
  523. input monitor.MeterAlertUpdateInput,
  524. ) (monitor.MeterAlertUpdateInput, error) {
  525. // ret := new(monitor.AlertUpdateInput)
  526. details, err := alert.getExtraDetails(ctx, userCred, query, false)
  527. if err != nil {
  528. return input, err
  529. }
  530. if input.Threshold != nil && *input.Threshold != details.Threshold {
  531. details.Threshold = *input.Threshold
  532. }
  533. if input.Comparator != nil && *input.Comparator != details.Comparator {
  534. details.Comparator = *input.Comparator
  535. }
  536. // hack: update notification here
  537. if err := alert.UpdateNotification(AlertNotificationUsedByMeterAlert, input.Channel, input.Recipients); err != nil {
  538. return input, errors.Wrap(err, "update notification")
  539. }
  540. allAccountIds := []string{}
  541. if details.AccountId == "" {
  542. allAccountIds, err = MeterAlertManager.getAllBillAccountIds(ctx)
  543. if err != nil {
  544. return input, err
  545. }
  546. }
  547. tmpS := alert.getUpdateSetting(details, allAccountIds)
  548. input.Settings = &tmpS
  549. input.V1AlertUpdateInput, err = alert.SV1Alert.ValidateUpdateData(ctx, userCred, query, input.V1AlertUpdateInput)
  550. if err != nil {
  551. return input, errors.Wrap(err, "SV1Alert.ValidateUpdateData")
  552. }
  553. return input, nil
  554. }
  555. func (alert *SMeterAlert) getUpdateSetting(details monitor.MeterAlertDetails, accountIds []string) monitor.AlertSetting {
  556. drv := MeterAlertManager.GetDriver(alert.getType())
  557. input := monitor.MeterAlertCreateInput{
  558. ResourceAlertV1CreateInput: monitor.ResourceAlertV1CreateInput{
  559. Period: details.Period,
  560. Window: details.Window,
  561. Comparator: details.Comparator,
  562. Threshold: details.Threshold,
  563. Channel: details.Channel,
  564. Recipients: details.Recipients,
  565. },
  566. Type: details.Type,
  567. Provider: details.Provider,
  568. ProjectId: details.ProjectId,
  569. AccountId: details.AccountId,
  570. }
  571. input.Level = details.Level
  572. out := drv.ToAlertCreateInput(input, accountIds, details.Level)
  573. return out.Settings
  574. }
  575. func (alert *SMeterAlert) PostUpdate(
  576. ctx context.Context, userCred mcclient.TokenCredential,
  577. query jsonutils.JSONObject, data jsonutils.JSONObject) {
  578. alert.SV1Alert.PostUpdate(ctx, userCred, query, data)
  579. }
  580. func (alert *SMeterAlert) CustomizeDelete(
  581. ctx context.Context, userCred mcclient.TokenCredential,
  582. query jsonutils.JSONObject, data jsonutils.JSONObject) error {
  583. return alert.SV1Alert.CustomizeDelete(ctx, userCred, query, data)
  584. }