topic.go 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166
  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. "fmt"
  18. "strings"
  19. "sync"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/log"
  22. "yunion.io/x/pkg/errors"
  23. "yunion.io/x/pkg/gotypes"
  24. "yunion.io/x/pkg/tristate"
  25. "yunion.io/x/pkg/util/sets"
  26. "yunion.io/x/pkg/utils"
  27. "yunion.io/x/sqlchemy"
  28. "yunion.io/x/onecloud/pkg/apis"
  29. "yunion.io/x/onecloud/pkg/apis/notify"
  30. api "yunion.io/x/onecloud/pkg/apis/notify"
  31. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  32. "yunion.io/x/onecloud/pkg/httperrors"
  33. "yunion.io/x/onecloud/pkg/mcclient"
  34. "yunion.io/x/onecloud/pkg/mcclient/auth"
  35. "yunion.io/x/onecloud/pkg/util/stringutils2"
  36. )
  37. func parseEvent(es string) (api.SNotifyEvent, error) {
  38. es = strings.ToLower(es)
  39. ess := strings.Split(es, api.DelimiterInEvent)
  40. if len(ess) != 2 && len(ess) != 3 {
  41. return api.SNotifyEvent{}, fmt.Errorf("invalid event string %q", es)
  42. }
  43. event := api.Event.WithResourceType(ess[0]).WithAction(api.SAction(ess[1]))
  44. if len(ess) == 3 {
  45. event = event.WithResult(api.SResult(ess[2]))
  46. }
  47. return event, nil
  48. }
  49. type STopicManager struct {
  50. db.SEnabledStatusStandaloneResourceBaseManager
  51. }
  52. var TopicManager *STopicManager
  53. func init() {
  54. TopicManager = &STopicManager{
  55. SEnabledStatusStandaloneResourceBaseManager: db.NewEnabledStatusStandaloneResourceBaseManager(
  56. STopic{},
  57. "topic_tbl",
  58. "topic",
  59. "topics",
  60. ),
  61. }
  62. TopicManager.SetVirtualObject(TopicManager)
  63. }
  64. // 消息订阅
  65. type STopic struct {
  66. db.SEnabledStatusStandaloneResourceBase
  67. Type string `width:"20" nullable:"false" create:"required" update:"user" list:"user"`
  68. Results tristate.TriState `default:"true" create:"optional" get:"user" list:"user"`
  69. TitleCn string `length:"medium" nullable:"true" charset:"utf8" list:"user" update:"user" create:"optional"`
  70. TitleEn string `length:"medium" nullable:"true" charset:"utf8" list:"user" update:"user" create:"optional"`
  71. ContentCn string `length:"medium" nullable:"true" charset:"utf8" list:"user" update:"user" create:"optional"`
  72. ContentEn string `length:"medium" nullable:"true" charset:"utf8" list:"user" update:"user" create:"optional"`
  73. GroupKeys *api.STopicGroupKeys `nullable:"true" list:"user" update:"user" create:"optional"`
  74. AdvanceDays []int `nullable:"true" charset:"utf8" list:"user" update:"user" create:"optional"`
  75. WebconsoleDisable tristate.TriState `default:"false" list:"user" update:"user" create:"optional"`
  76. }
  77. const (
  78. DefaultResourceCreateDelete = "resource create or delete"
  79. DefaultResourceChangeConfig = "resource change config"
  80. DefaultResourceUpdate = "resource update"
  81. DefaultResourceReleaseDue1Day = "resource release due 1 day"
  82. DefaultResourceReleaseDue3Day = "resource release due 3 day"
  83. DefaultResourceReleaseDue30Day = "resource release due 30 day"
  84. DefaultResourceRelease = "resource release"
  85. DefaultScheduledTaskExecute = "scheduled task execute"
  86. DefaultScalingPolicyExecute = "scaling policy execute"
  87. DefaultSnapshotPolicyExecute = "snapshot policy execute"
  88. DefaultResourceOperationFailed = "resource operation failed"
  89. DefaultResourceOperationSuccessed = "resource operation successed"
  90. DefaultResourceSync = "resource sync"
  91. DefaultSystemExceptionEvent = "system exception event"
  92. DefaultChecksumTestFailed = "checksum test failed"
  93. DefaultUserLock = "user lock"
  94. DefaultActionLogExceedCount = "action log exceed count"
  95. DefaultSyncAccountStatus = "cloud account sync status"
  96. DefaultPasswordExpireDue1Day = "password expire due 1 day"
  97. DefaultPasswordExpireDue7Day = "password expire due 7 day"
  98. DefaultPasswordExpire = "password expire"
  99. DefaultNetOutOfSync = "net out of sync"
  100. DefaultMysqlOutOfSync = "mysql out of sync"
  101. DefaultServiceAbnormal = "service abnormal"
  102. DefaultServerPanicked = "server panicked"
  103. DefaultAttachOrDetach = "resource attach or detach"
  104. DefaultIsolatedDeviceChanged = "isolated device changed"
  105. DefaultStatusChanged = "resource status changed"
  106. )
  107. func (sm *STopicManager) InitializeData() error {
  108. initSNames := sets.NewString(
  109. DefaultResourceCreateDelete,
  110. DefaultResourceChangeConfig,
  111. DefaultResourceUpdate,
  112. DefaultScheduledTaskExecute,
  113. DefaultScalingPolicyExecute,
  114. DefaultSnapshotPolicyExecute,
  115. DefaultResourceOperationFailed,
  116. DefaultResourceSync,
  117. DefaultSystemExceptionEvent,
  118. DefaultChecksumTestFailed,
  119. DefaultUserLock,
  120. DefaultActionLogExceedCount,
  121. DefaultSyncAccountStatus,
  122. DefaultNetOutOfSync,
  123. DefaultMysqlOutOfSync,
  124. DefaultServiceAbnormal,
  125. DefaultServerPanicked,
  126. DefaultPasswordExpire,
  127. DefaultResourceRelease,
  128. DefaultResourceOperationSuccessed,
  129. DefaultAttachOrDetach,
  130. DefaultIsolatedDeviceChanged,
  131. DefaultStatusChanged,
  132. )
  133. q := sm.Query()
  134. topics := make([]STopic, 0, initSNames.Len())
  135. err := db.FetchModelObjects(sm, q, &topics)
  136. if err != nil {
  137. return errors.Wrap(err, "unable to FetchModelObjects")
  138. }
  139. nameTopicMap := make(map[string]*STopic, len(topics))
  140. for i := range topics {
  141. t := &topics[i]
  142. initSNames.Delete(t.Name)
  143. nameTopicMap[t.Name] = t
  144. }
  145. for _, name := range initSNames.UnsortedList() {
  146. nameTopicMap[name] = nil
  147. }
  148. ctx := context.Background()
  149. for name, topic := range nameTopicMap {
  150. isNew := false
  151. t := new(STopic)
  152. if topic == nil {
  153. t.Id = db.DefaultUUIDGenerator()
  154. isNew = true
  155. } else {
  156. t.Id = topic.Id
  157. }
  158. t.Name = name
  159. t.Enabled = tristate.True
  160. switch name {
  161. case DefaultResourceCreateDelete:
  162. t.Type = api.TOPIC_TYPE_RESOURCE
  163. t.Results = tristate.True
  164. t.ContentCn = api.COMMON_CONTENT_CN
  165. t.ContentEn = api.COMMON_CONTENT_EN
  166. t.TitleCn = api.COMMON_TITLE_CN
  167. t.TitleEn = api.COMMON_TITLE_EN
  168. case DefaultResourceChangeConfig:
  169. t.Type = api.TOPIC_TYPE_RESOURCE
  170. t.Results = tristate.True
  171. t.ContentCn = api.COMMON_CONTENT_CN
  172. t.ContentEn = api.COMMON_CONTENT_EN
  173. t.TitleCn = api.COMMON_TITLE_CN
  174. t.TitleEn = api.COMMON_TITLE_EN
  175. case DefaultResourceUpdate:
  176. t.Type = api.TOPIC_TYPE_RESOURCE
  177. t.Results = tristate.True
  178. t.ContentCn = api.UPDATE_CONTENT_CN
  179. t.ContentEn = api.UPDATE_CONTENT_EN
  180. t.TitleCn = api.UPDATE_TITLE_CN
  181. t.TitleEn = api.UPDATE_TITLE_EN
  182. case DefaultScheduledTaskExecute:
  183. t.Type = api.TOPIC_TYPE_AUTOMATED_PROCESS
  184. t.Results = tristate.True
  185. t.ContentCn = api.SCHEDULEDTASK_EXECUTE_CONTENT_CN
  186. t.ContentEn = api.SCHEDULEDTASK_EXECUTE_CONTENT_EN
  187. t.TitleCn = api.SCHEDULEDTASK_EXECUTE_TITLE_CN
  188. t.TitleEn = api.SCHEDULEDTASK_EXECUTE_TITLE_EN
  189. case DefaultScalingPolicyExecute:
  190. t.Type = api.TOPIC_TYPE_AUTOMATED_PROCESS
  191. t.Results = tristate.True
  192. t.ContentCn = api.SCALINGPOLICY_EXECUTE_CONTENT_CN
  193. t.ContentEn = api.SCALINGPOLICY_EXECUTE_CONTENT_EN
  194. t.TitleCn = api.SCALINGPOLICY_EXECUTE_TITLE_CN
  195. t.TitleEn = api.SCALINGPOLICY_EXECUTE_TITLE_EN
  196. case DefaultSnapshotPolicyExecute:
  197. t.Type = api.TOPIC_TYPE_AUTOMATED_PROCESS
  198. t.Results = tristate.True
  199. t.ContentCn = api.SNAPSHOTPOLICY_EXECUTE_CONTENT_CN
  200. t.ContentEn = api.SNAPSHOTPOLICY_EXECUTE_CONTENT_EN
  201. t.TitleCn = api.SNAPSHOTPOLICY_EXECUTE_TITLE_CN
  202. t.TitleEn = api.SNAPSHOTPOLICY_EXECUTE_TITLE_EN
  203. case DefaultResourceOperationFailed:
  204. t.Type = api.TOPIC_TYPE_RESOURCE
  205. t.Results = tristate.False
  206. case DefaultResourceOperationSuccessed:
  207. t.Results = tristate.True
  208. t.Type = api.TOPIC_TYPE_RESOURCE
  209. case DefaultResourceSync:
  210. t.Type = api.TOPIC_TYPE_RESOURCE
  211. t.WebconsoleDisable = tristate.True
  212. t.Results = tristate.True
  213. t.ContentCn = api.COMMON_CONTENT_CN
  214. t.ContentEn = api.COMMON_CONTENT_EN
  215. t.TitleCn = api.COMMON_TITLE_CN
  216. t.TitleEn = api.COMMON_TITLE_EN
  217. groupKeys := []string{"action_display"}
  218. t.GroupKeys = (*api.STopicGroupKeys)(&groupKeys)
  219. case DefaultSystemExceptionEvent:
  220. t.Type = api.TOPIC_TYPE_RESOURCE
  221. t.Results = tristate.False
  222. t.ContentCn = api.EXCEPTION_CONTENT_CN
  223. t.ContentEn = api.EXCEPTION_CONTENT_EN
  224. t.TitleCn = api.EXCEPTION_TITLE_CN
  225. t.TitleEn = api.EXCEPTION_TITLE_EN
  226. case DefaultChecksumTestFailed:
  227. t.Type = api.TOPIC_TYPE_SECURITY
  228. t.Results = tristate.False
  229. t.ContentCn = api.CHECKSUM_TEST_FAILED_CONTENT_CN
  230. t.ContentEn = api.CHECKSUM_TEST_FAILED_CONTENT_EN
  231. t.TitleCn = api.CHECKSUM_TEST_FAILED_TITLE_CN
  232. t.TitleEn = api.CHECKSUM_TEST_FAILED_TITLE_EN
  233. case DefaultUserLock:
  234. t.Type = api.TOPIC_TYPE_SECURITY
  235. t.Results = tristate.True
  236. t.ContentCn = api.USER_LOCK_CONTENT_CN
  237. t.ContentEn = api.USER_LOCK_CONTENT_EN
  238. t.TitleCn = api.USER_LOCK_TITLE_CN
  239. t.TitleEn = api.USER_LOCK_TITLE_EN
  240. case DefaultActionLogExceedCount:
  241. t.Type = api.TOPIC_TYPE_RESOURCE
  242. t.Results = tristate.True
  243. t.ContentCn = api.ACTION_LOG_EXCEED_COUNT_CONTENT_CN
  244. t.ContentEn = api.ACTION_LOG_EXCEED_COUNT_CONTENT_EN
  245. t.TitleCn = api.ACTION_LOG_EXCEED_COUNT_TITLE_CN
  246. t.TitleEn = api.ACTION_LOG_EXCEED_COUNT_TITLE_EN
  247. case DefaultSyncAccountStatus:
  248. t.Type = api.TOPIC_TYPE_AUTOMATED_PROCESS
  249. t.Results = tristate.True
  250. t.ContentCn = api.SYNC_ACCOUNT_STATUS_CONTENT_CN
  251. t.ContentEn = api.SYNC_ACCOUNT_STATUS_CONTENT_EN
  252. t.TitleCn = api.SYNC_ACCOUNT_STATUS_TITLE_CN
  253. t.TitleEn = api.SYNC_ACCOUNT_STATUS_TITLE_EN
  254. groupKeys := []string{"name"}
  255. t.GroupKeys = (*api.STopicGroupKeys)(&groupKeys)
  256. case DefaultNetOutOfSync:
  257. t.Type = api.TOPIC_TYPE_AUTOMATED_PROCESS
  258. t.Results = tristate.True
  259. t.ContentCn = api.NET_OUT_OF_SYNC_CONTENT_CN
  260. t.ContentEn = api.NET_OUT_OF_SYNC_CONTENT_EN
  261. t.TitleCn = api.NET_OUT_OF_SYNC_TITLE_CN
  262. t.TitleEn = api.NET_OUT_OF_SYNC_TITLE_EN
  263. groupKeys := []string{"service_name"}
  264. t.GroupKeys = (*api.STopicGroupKeys)(&groupKeys)
  265. case DefaultMysqlOutOfSync:
  266. t.Type = api.TOPIC_TYPE_AUTOMATED_PROCESS
  267. t.Results = tristate.True
  268. t.ContentCn = api.MYSQL_OUT_OF_SYNC_CONTENT_CN
  269. t.ContentEn = api.MYSQL_OUT_OF_SYNC_CONTENT_EN
  270. t.TitleCn = api.MYSQL_OUT_OF_SYNC_TITLE_CN
  271. t.TitleEn = api.MYSQL_OUT_OF_SYNC_TITLE_EN
  272. groupKeys := []string{"ip"}
  273. t.GroupKeys = (*api.STopicGroupKeys)(&groupKeys)
  274. case DefaultServiceAbnormal:
  275. t.Results = tristate.True
  276. t.Type = api.TOPIC_TYPE_AUTOMATED_PROCESS
  277. t.ContentCn = api.SERVICE_ABNORMAL_CONTENT_CN
  278. t.ContentEn = api.SERVICE_ABNORMAL_CONTENT_EN
  279. t.TitleCn = api.SERVICE_ABNORMAL_TITLE_CN
  280. t.TitleEn = api.SERVICE_ABNORMAL_TITLE_EN
  281. groupKeys := []string{"service_name"}
  282. t.GroupKeys = (*api.STopicGroupKeys)(&groupKeys)
  283. case DefaultServerPanicked:
  284. t.Results = tristate.False
  285. t.Type = api.TOPIC_TYPE_RESOURCE
  286. t.ContentCn = api.SERVER_PANICKED_CONTENT_CN
  287. t.ContentEn = api.SERVER_PANICKED_CONTENT_EN
  288. t.TitleCn = api.SERVER_PANICKED_TITLE_CN
  289. t.TitleEn = api.SERVER_PANICKED_TITLE_EN
  290. groupKeys := []string{"name"}
  291. t.GroupKeys = (*api.STopicGroupKeys)(&groupKeys)
  292. case DefaultPasswordExpire:
  293. t.AdvanceDays = []int{1, 7}
  294. t.Type = api.TOPIC_TYPE_SECURITY
  295. t.Results = tristate.True
  296. t.ContentCn = api.PWD_EXPIRE_SOON_CONTENT_CN
  297. t.ContentEn = api.PWD_EXPIRE_SOON_CONTENT_EN
  298. t.TitleCn = api.PWD_EXPIRE_SOON_TITLE_CN
  299. t.TitleEn = api.PWD_EXPIRE_SOON_TITLE_EN
  300. case DefaultResourceRelease:
  301. t.Type = api.TOPIC_TYPE_RESOURCE
  302. t.AdvanceDays = []int{1, 7, 30}
  303. t.Results = tristate.True
  304. t.ContentCn = api.EXPIRED_RELEASE_CONTENT_CN
  305. t.ContentEn = api.EXPIRED_RELEASE_CONTENT_EN
  306. t.TitleCn = api.EXPIRED_RELEASE_TITLE_CN
  307. t.TitleEn = api.EXPIRED_RELEASE_TITLE_EN
  308. case DefaultAttachOrDetach:
  309. t.Type = api.TOPIC_TYPE_RESOURCE
  310. t.Results = tristate.True
  311. case DefaultIsolatedDeviceChanged:
  312. t.Type = api.TOPIC_TYPE_RESOURCE
  313. t.Results = tristate.True
  314. case DefaultStatusChanged:
  315. t.Type = api.TOPIC_TYPE_RESOURCE
  316. t.Results = tristate.True
  317. t.ContentCn = api.STATUS_CHANGED_CONTENT_CN
  318. t.ContentEn = api.STATUS_CHANGED_CONTENT_EN
  319. t.TitleCn = api.STATUS_CHANGED_TITLE_CN
  320. t.TitleEn = api.STATUS_CHANGED_TITLE_EN
  321. }
  322. if topic == nil {
  323. err := sm.TableSpec().Insert(ctx, t)
  324. if err != nil {
  325. return errors.Wrapf(err, "unable to insert %s", name)
  326. }
  327. } else {
  328. if t.Name == DefaultResourceReleaseDue3Day || t.Name == DefaultResourceReleaseDue30Day || t.Name == DefaultResourceReleaseDue1Day {
  329. err = topic.Delete(ctx, auth.AdminCredential())
  330. if err != nil {
  331. log.Errorf("delete %s err %s", topic.Name, err.Error())
  332. }
  333. continue
  334. }
  335. if t.Name == DefaultPasswordExpireDue7Day || t.Name == DefaultPasswordExpireDue1Day {
  336. err = topic.Delete(ctx, auth.AdminCredential())
  337. if err != nil {
  338. log.Errorf("delete %s err %s", topic.Name, err.Error())
  339. }
  340. continue
  341. }
  342. _, err := db.Update(topic, func() error {
  343. topic.Name = t.Name
  344. // topic.Resources = t.Resources
  345. // topic.Actions = t.Actions
  346. topic.Type = t.Type
  347. topic.Results = t.Results
  348. topic.WebconsoleDisable = t.WebconsoleDisable
  349. topic.GroupKeys = t.GroupKeys
  350. if len(topic.AdvanceDays) == 0 {
  351. topic.AdvanceDays = t.AdvanceDays
  352. }
  353. if len(topic.ContentCn) == 0 || topic.Name == DefaultPasswordExpire || topic.Name == DefaultResourceRelease {
  354. if len(t.ContentCn) == 0 {
  355. t.ContentCn = api.COMMON_CONTENT_CN
  356. }
  357. topic.ContentCn = t.ContentCn
  358. }
  359. if len(topic.ContentEn) == 0 || topic.Name == DefaultPasswordExpire || topic.Name == DefaultResourceRelease {
  360. if len(t.ContentEn) == 0 {
  361. t.ContentEn = api.COMMON_CONTENT_EN
  362. }
  363. topic.ContentEn = t.ContentEn
  364. }
  365. if len(topic.TitleCn) == 0 || topic.Name == DefaultPasswordExpire || topic.Name == DefaultResourceRelease {
  366. if len(t.TitleCn) == 0 {
  367. t.TitleCn = api.COMMON_TITLE_CN
  368. }
  369. topic.TitleCn = t.TitleCn
  370. }
  371. if len(topic.TitleEn) == 0 || topic.Name == DefaultPasswordExpire || topic.Name == DefaultResourceRelease {
  372. if len(t.TitleEn) == 0 {
  373. t.TitleEn = api.COMMON_TITLE_EN
  374. }
  375. topic.TitleEn = t.TitleEn
  376. }
  377. return nil
  378. })
  379. if err != nil {
  380. return errors.Wrapf(err, "unable to update topic %s", topic.Name)
  381. }
  382. }
  383. acnt, rcnt := 0, 0
  384. if !gotypes.IsNil(topic) {
  385. acnt = TopicActionManager.Query().Equals("topic_id", topic.Id).Count()
  386. rcnt = TopicResourceManager.Query().Equals("topic_id", topic.Id).Count()
  387. }
  388. if isNew || acnt == 0 || rcnt == 0 {
  389. initTopicElement(name, t)
  390. }
  391. }
  392. return nil
  393. }
  394. // 新建关联关系
  395. func initTopicElement(name string, t *STopic) {
  396. switch name {
  397. case DefaultResourceCreateDelete:
  398. t.addResources(
  399. api.TOPIC_RESOURCE_HOST,
  400. api.TOPIC_RESOURCE_SERVER,
  401. api.TOPIC_RESOURCE_SCALINGGROUP,
  402. api.TOPIC_RESOURCE_IMAGE,
  403. api.TOPIC_RESOURCE_DISK,
  404. api.TOPIC_RESOURCE_SNAPSHOT,
  405. api.TOPIC_RESOURCE_INSTANCESNAPSHOT,
  406. api.TOPIC_RESOURCE_SNAPSHOTPOLICY,
  407. api.TOPIC_RESOURCE_NETWORK,
  408. api.TOPIC_RESOURCE_EIP,
  409. api.TOPIC_RESOURCE_LOADBALANCER,
  410. api.TOPIC_RESOURCE_LOADBALANCERACL,
  411. api.TOPIC_RESOURCE_LOADBALANCERCERTIFICATE,
  412. api.TOPIC_RESOURCE_BUCKET,
  413. api.TOPIC_RESOURCE_DBINSTANCE,
  414. api.TOPIC_RESOURCE_ELASTICCACHE,
  415. api.TOPIC_RESOURCE_BAREMETAL,
  416. api.TOPIC_RESOURCE_SECGROUP,
  417. api.TOPIC_RESOURCE_FILESYSTEM,
  418. api.TOPIC_RESOURCE_NATGATEWAY,
  419. api.TOPIC_RESOURCE_VPC,
  420. api.TOPIC_RESOURCE_CDNDOMAIN,
  421. api.TOPIC_RESOURCE_WAF,
  422. api.TOPIC_RESOURCE_KAFKA,
  423. api.TOPIC_RESOURCE_ELASTICSEARCH,
  424. api.TOPIC_RESOURCE_MONGODB,
  425. api.TOPIC_RESOURCE_DNSZONE,
  426. api.TOPIC_RESOURCE_DNSRECORDSET,
  427. api.TOPIC_RESOURCE_LOADBALANCERLISTENER,
  428. api.TOPIC_RESOURCE_LOADBALANCERBACKEDNGROUP,
  429. api.TOPIC_RESOURCE_PROJECT,
  430. )
  431. t.addAction(
  432. api.ActionCreate,
  433. api.ActionDelete,
  434. api.ActionPendingDelete,
  435. )
  436. case DefaultResourceChangeConfig:
  437. t.addResources(
  438. api.TOPIC_RESOURCE_HOST,
  439. api.TOPIC_RESOURCE_SERVER,
  440. api.TOPIC_RESOURCE_DBINSTANCE,
  441. api.TOPIC_RESOURCE_ELASTICCACHE,
  442. )
  443. t.addAction(api.ActionChangeConfig)
  444. case DefaultResourceUpdate:
  445. t.addResources(
  446. api.TOPIC_RESOURCE_SERVER,
  447. api.TOPIC_RESOURCE_DBINSTANCE,
  448. api.TOPIC_RESOURCE_ELASTICCACHE,
  449. api.TOPIC_RESOURCE_USER,
  450. api.TOPIC_RESOURCE_HOST,
  451. api.TOPIC_RESOURCE_PROJECT,
  452. )
  453. t.addAction(api.ActionUpdate)
  454. t.addAction(api.ActionRebuildRoot)
  455. t.addAction(api.ActionResetPassword)
  456. t.addAction(api.ActionChangeIpaddr)
  457. case DefaultScheduledTaskExecute:
  458. t.addResources(api.TOPIC_RESOURCE_SCHEDULEDTASK)
  459. t.addAction(api.ActionExecute)
  460. case DefaultScalingPolicyExecute:
  461. t.addResources(api.TOPIC_RESOURCE_SCALINGPOLICY)
  462. t.addAction(api.ActionExecute)
  463. case DefaultSnapshotPolicyExecute:
  464. t.addResources(api.TOPIC_RESOURCE_SNAPSHOTPOLICY)
  465. t.addAction(api.ActionExecute)
  466. case DefaultResourceOperationFailed:
  467. t.addResources(
  468. api.TOPIC_RESOURCE_SERVER,
  469. api.TOPIC_RESOURCE_EIP,
  470. api.TOPIC_RESOURCE_LOADBALANCER,
  471. api.TOPIC_RESOURCE_DBINSTANCE,
  472. api.TOPIC_RESOURCE_ELASTICCACHE,
  473. api.TOPIC_RESOURCE_DISK,
  474. api.TOPIC_RESOURCE_CLOUDPHONE,
  475. )
  476. t.addAction(
  477. api.ActionStart,
  478. api.ActionStop,
  479. api.ActionRestart,
  480. api.ActionReset,
  481. api.ActionAttach,
  482. api.ActionDetach,
  483. api.ActionCreate,
  484. api.ActionSyncStatus,
  485. api.ActionRebuildRoot,
  486. api.ActionChangeConfig,
  487. api.ActionCreateBackupServer,
  488. api.ActionDelBackupServer,
  489. api.ActionMigrate,
  490. )
  491. case DefaultResourceOperationSuccessed:
  492. t.addResources(
  493. api.TOPIC_RESOURCE_SERVER,
  494. api.TOPIC_RESOURCE_CLOUDPHONE,
  495. api.TOPIC_RESOURCE_DISK,
  496. )
  497. t.addAction(
  498. api.ActionStart,
  499. api.ActionStop,
  500. api.ActionRestart,
  501. api.ActionReset,
  502. api.ActionCreateBackupServer,
  503. )
  504. case DefaultResourceSync:
  505. t.addResources(
  506. api.TOPIC_RESOURCE_SERVER,
  507. api.TOPIC_RESOURCE_DISK,
  508. api.TOPIC_RESOURCE_DBINSTANCE,
  509. api.TOPIC_RESOURCE_ELASTICCACHE,
  510. api.TOPIC_RESOURCE_LOADBALANCER,
  511. api.TOPIC_RESOURCE_EIP,
  512. api.TOPIC_RESOURCE_VPC,
  513. api.TOPIC_RESOURCE_NETWORK,
  514. api.TOPIC_RESOURCE_LOADBALANCERCERTIFICATE,
  515. api.TOPIC_RESOURCE_DNSZONE,
  516. api.TOPIC_RESOURCE_NATGATEWAY,
  517. api.TOPIC_RESOURCE_BUCKET,
  518. api.TOPIC_RESOURCE_FILESYSTEM,
  519. api.TOPIC_RESOURCE_WEBAPP,
  520. api.TOPIC_RESOURCE_CDNDOMAIN,
  521. api.TOPIC_RESOURCE_WAF,
  522. api.TOPIC_RESOURCE_KAFKA,
  523. api.TOPIC_RESOURCE_ELASTICSEARCH,
  524. api.TOPIC_RESOURCE_MONGODB,
  525. api.TOPIC_RESOURCE_DNSRECORDSET,
  526. api.TOPIC_RESOURCE_LOADBALANCERLISTENER,
  527. api.TOPIC_RESOURCE_LOADBALANCERBACKEDNGROUP,
  528. )
  529. t.addAction(
  530. api.ActionSyncCreate,
  531. api.ActionSyncUpdate,
  532. api.ActionSyncDelete,
  533. )
  534. case DefaultSystemExceptionEvent:
  535. t.addResources(
  536. api.TOPIC_RESOURCE_HOST,
  537. api.TOPIC_RESOURCE_TASK,
  538. )
  539. t.addAction(
  540. api.ActionSystemPanic,
  541. api.ActionSystemException,
  542. api.ActionOffline,
  543. api.ActionHostDown,
  544. api.ActionHostDownAutoMigrate,
  545. )
  546. case DefaultChecksumTestFailed:
  547. t.addResources(
  548. api.TOPIC_RESOURCE_DB_TABLE_RECORD,
  549. api.TOPIC_RESOURCE_VM_INTEGRITY_CHECK,
  550. api.TOPIC_RESOURCE_CLOUDPODS_COMPONENT,
  551. api.TOPIC_RESOURCE_SNAPSHOT,
  552. api.TOPIC_RESOURCE_IMAGE,
  553. )
  554. t.addAction(
  555. api.ActionChecksumTest,
  556. )
  557. case DefaultUserLock:
  558. t.addResources(
  559. api.TOPIC_RESOURCE_USER,
  560. )
  561. t.addAction(
  562. api.ActionLock,
  563. )
  564. case DefaultActionLogExceedCount:
  565. t.addResources(
  566. api.TOPIC_RESOURCE_ACTION_LOG,
  567. )
  568. t.addAction(
  569. api.ActionExceedCount,
  570. )
  571. case DefaultSyncAccountStatus:
  572. t.addResources(
  573. api.TOPIC_RESOURCE_ACCOUNT_STATUS,
  574. )
  575. t.addAction(
  576. api.ActionSyncAccountStatus,
  577. )
  578. case DefaultNetOutOfSync:
  579. t.addResources(
  580. api.TOPIC_RESOURCE_NET,
  581. )
  582. t.addAction(
  583. api.ActionNetOutOfSync,
  584. )
  585. case DefaultMysqlOutOfSync:
  586. t.addResources(
  587. api.TOPIC_RESOURCE_DBINSTANCE,
  588. )
  589. t.addAction(
  590. api.ActionMysqlOutOfSync,
  591. )
  592. case DefaultServiceAbnormal:
  593. t.addResources(
  594. api.TOPIC_RESOURCE_SERVICE,
  595. )
  596. t.addAction(
  597. api.ActionServiceAbnormal,
  598. )
  599. case DefaultServerPanicked:
  600. t.addResources(
  601. api.TOPIC_RESOURCE_SERVER,
  602. )
  603. t.addAction(
  604. api.ActionServerPanicked,
  605. )
  606. case DefaultPasswordExpire:
  607. t.addResources(
  608. api.TOPIC_RESOURCE_USER,
  609. )
  610. t.addAction(
  611. api.ActionPasswordExpireSoon,
  612. )
  613. case DefaultResourceRelease:
  614. t.addResources(
  615. api.TOPIC_RESOURCE_SERVER,
  616. api.TOPIC_RESOURCE_DISK,
  617. api.TOPIC_RESOURCE_EIP,
  618. api.TOPIC_RESOURCE_LOADBALANCER,
  619. api.TOPIC_RESOURCE_DBINSTANCE,
  620. api.TOPIC_RESOURCE_ELASTICCACHE,
  621. )
  622. t.addAction(api.ActionExpiredRelease)
  623. case DefaultAttachOrDetach:
  624. t.addResources(
  625. api.TOPIC_RESOURCE_HOST,
  626. api.TOPIC_RESOURCE_CLOUDPHONE,
  627. )
  628. t.addAction(
  629. api.ActionAttach,
  630. api.ActionDetach,
  631. )
  632. case DefaultIsolatedDeviceChanged:
  633. t.addResources(
  634. api.TOPIC_RESOURCE_HOST,
  635. )
  636. t.addAction(
  637. api.ActionIsolatedDeviceCreate,
  638. api.ActionIsolatedDeviceUpdate,
  639. api.ActionIsolatedDeviceDelete,
  640. )
  641. case DefaultStatusChanged:
  642. t.addResources(
  643. api.TOPIC_RESOURCE_SERVER,
  644. api.TOPIC_RESOURCE_HOST,
  645. )
  646. t.addAction(
  647. api.ActionStatusChanged,
  648. )
  649. }
  650. }
  651. func (sm *STopicManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, input api.TopicListInput) (*sqlchemy.SQuery, error) {
  652. q, err := sm.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, input.StandaloneResourceListInput)
  653. if err != nil {
  654. return nil, errors.Wrap(err, "SStandaloneResourceBaseManager.ListItemFilter")
  655. }
  656. q, err = sm.SEnabledResourceBaseManager.ListItemFilter(ctx, q, userCred, input.EnabledResourceBaseListInput)
  657. if err != nil {
  658. return nil, errors.Wrap(err, "SEnabledResourceBaseManager.ListItemFilter")
  659. }
  660. return q, nil
  661. }
  662. func (sm *STopicManager) FetchCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, objs []interface{}, fields stringutils2.SSortedStrings, isList bool) []api.TopicDetails {
  663. sRows := sm.SStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  664. rows := make([]api.TopicDetails, len(objs))
  665. topicIds := make([]string, len(objs))
  666. for i := range rows {
  667. rows[i].StandaloneResourceDetails = sRows[i]
  668. ss := objs[i].(*STopic)
  669. topicIds[i] = ss.Id
  670. }
  671. resources, resourceMap := []STopicResource{}, map[string][]string{}
  672. err := TopicResourceManager.Query().In("topic_id", topicIds).All(&resources)
  673. if err != nil {
  674. log.Errorf("query resources error: %v", err)
  675. return rows
  676. }
  677. for _, r := range resources {
  678. _, ok := resourceMap[r.TopicId]
  679. if !ok {
  680. resourceMap[r.TopicId] = []string{}
  681. }
  682. resourceMap[r.TopicId] = append(resourceMap[r.TopicId], r.ResourceId)
  683. }
  684. actions, actionMap := []STopicAction{}, map[string][]string{}
  685. err = TopicActionManager.Query().In("topic_id", topicIds).All(&actions)
  686. if err != nil {
  687. log.Errorf("query actions error: %v", err)
  688. return rows
  689. }
  690. for _, a := range actions {
  691. _, ok := actionMap[a.TopicId]
  692. if !ok {
  693. actionMap[a.TopicId] = []string{}
  694. }
  695. actionMap[a.TopicId] = append(actionMap[a.TopicId], a.ActionId)
  696. }
  697. for i := range rows {
  698. rows[i].Resources, _ = resourceMap[topicIds[i]]
  699. rows[i].Actions, _ = actionMap[topicIds[i]]
  700. }
  701. return rows
  702. }
  703. func (sm *STopicManager) ValidateCreateData(
  704. ctx context.Context,
  705. userCred mcclient.TokenCredential,
  706. ownerId mcclient.IIdentityProvider,
  707. query jsonutils.JSONObject,
  708. input *api.STopicCreateInput,
  709. ) (*api.STopicCreateInput, error) {
  710. var err error
  711. input.EnabledStatusStandaloneResourceCreateInput, err = sm.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusStandaloneResourceCreateInput)
  712. if err != nil {
  713. return nil, err
  714. }
  715. if !utils.IsInStringArray(input.Type, []string{
  716. api.TOPIC_TYPE_RESOURCE,
  717. api.TOPIC_TYPE_AUTOMATED_PROCESS,
  718. api.TOPIC_TYPE_SECURITY,
  719. }) {
  720. return nil, httperrors.NewInputParameterError("invalid type %s", input.Type)
  721. }
  722. input.Status = apis.STATUS_AVAILABLE
  723. return input, nil
  724. }
  725. func (tp *STopic) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
  726. tp.SEnabledStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
  727. input := &api.STopicCreateInput{}
  728. data.Unmarshal(input)
  729. for _, resource := range input.Resources {
  730. r := &STopicResource{
  731. ResourceId: resource,
  732. TopicId: tp.Id,
  733. }
  734. r.SetModelManager(TopicResourceManager, r)
  735. TopicResourceManager.TableSpec().Insert(ctx, r)
  736. }
  737. for _, action := range input.Actions {
  738. a := &STopicAction{
  739. ActionId: action,
  740. TopicId: tp.Id,
  741. }
  742. a.SetModelManager(TopicActionManager, a)
  743. TopicActionManager.TableSpec().Insert(ctx, a)
  744. }
  745. }
  746. func (ss *STopic) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.TopicUpdateInput) (*api.TopicUpdateInput, error) {
  747. var err error
  748. input.EnabledStatusStandaloneResourceBaseUpdateInput, err = ss.SEnabledStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input.EnabledStatusStandaloneResourceBaseUpdateInput)
  749. if err != nil {
  750. return nil, err
  751. }
  752. return input, nil
  753. }
  754. func (tp *STopic) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
  755. tp.SEnabledStatusStandaloneResourceBase.PostUpdate(ctx, userCred, query, data)
  756. input := api.TopicUpdateInput{}
  757. jsonutils.Update(&input, data)
  758. if len(input.Resources) > 0 {
  759. tp.cleanResources()
  760. for _, res := range input.Resources {
  761. r := &STopicResource{
  762. ResourceId: res,
  763. TopicId: tp.Id,
  764. }
  765. r.SetModelManager(TopicResourceManager, r)
  766. TopicResourceManager.TableSpec().Insert(ctx, r)
  767. }
  768. }
  769. if len(input.Actions) > 0 {
  770. tp.cleanActions()
  771. for _, action := range input.Actions {
  772. a := &STopicAction{
  773. ActionId: action,
  774. TopicId: tp.Id,
  775. }
  776. a.SetModelManager(TopicActionManager, a)
  777. TopicActionManager.TableSpec().Insert(ctx, a)
  778. }
  779. }
  780. }
  781. func (ss *STopic) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
  782. return ss.SEnabledStatusStandaloneResourceBase.ValidateDeleteCondition(ctx, info)
  783. }
  784. func (tp *STopic) cleanResources() error {
  785. _, err := sqlchemy.GetDB().Exec(
  786. fmt.Sprintf(
  787. "delete from %s where topic_id = ?",
  788. TopicResourceManager.TableSpec().Name(),
  789. ), tp.Id,
  790. )
  791. return err
  792. }
  793. func (tp *STopic) cleanActions() error {
  794. _, err := sqlchemy.GetDB().Exec(
  795. fmt.Sprintf(
  796. "delete from %s where topic_id = ?",
  797. TopicActionManager.TableSpec().Name(),
  798. ), tp.Id,
  799. )
  800. return err
  801. }
  802. func (tp *STopic) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
  803. err := tp.cleanResources()
  804. if err != nil {
  805. return errors.Wrapf(err, "cleanResources")
  806. }
  807. err = tp.cleanActions()
  808. if err != nil {
  809. return errors.Wrapf(err, "cleanActions")
  810. }
  811. return tp.SEnabledStatusStandaloneResourceBase.Delete(ctx, userCred)
  812. }
  813. func (s *STopic) addResources(resources ...string) {
  814. for i := range resources {
  815. if TopicResourceManager.Query().Equals("topic_id", s.Id).Equals("resource_id", resources[i]).Count() == 0 {
  816. TopicResourceManager.TableSpec().InsertOrUpdate(context.Background(), &STopicResource{
  817. ResourceId: resources[i],
  818. TopicId: s.Id,
  819. })
  820. }
  821. }
  822. }
  823. func (s *STopic) addAction(actions ...api.SAction) {
  824. for i := range actions {
  825. if TopicActionManager.Query().Equals("topic_id", s.Id).Equals("action_id", actions[i]).Count() == 0 {
  826. TopicActionManager.TableSpec().InsertOrUpdate(context.Background(), &STopicAction{
  827. ActionId: string(actions[i]),
  828. TopicId: s.Id,
  829. })
  830. }
  831. }
  832. }
  833. func (s *STopic) GetResources() ([]STopicResource, error) {
  834. ret := []STopicResource{}
  835. q := TopicResourceManager.Query().Equals("topic_id", s.Id)
  836. err := db.FetchModelObjects(TopicResourceManager, q, &ret)
  837. if err != nil {
  838. return nil, err
  839. }
  840. return ret, nil
  841. }
  842. func (s *STopic) GetActions() ([]STopicAction, error) {
  843. ret := []STopicAction{}
  844. q := TopicActionManager.Query().Equals("topic_id", s.Id)
  845. err := db.FetchModelObjects(TopicActionManager, q, &ret)
  846. if err != nil {
  847. return nil, err
  848. }
  849. return ret, nil
  850. }
  851. func (sm *STopicManager) GetTopicByEvent(resourceType string, action api.SAction, isFailed api.SResult) (*STopic, error) {
  852. topics, err := sm.GetTopicsByEvent(resourceType, action, isFailed)
  853. if err != nil {
  854. return nil, errors.Wrapf(err, "GetTopicsByEvent")
  855. }
  856. if len(topics) == 0 {
  857. return nil, httperrors.NewResourceNotFoundError("no available topic found by %s %s", action, resourceType)
  858. }
  859. // free memory in time
  860. if len(topics) > 1 {
  861. return nil, httperrors.NewResourceNotFoundError("duplicates %d topics found by %s %s", len(topics), action, resourceType)
  862. }
  863. return &topics[0], nil
  864. }
  865. func (sm *STopicManager) GetTopicsByEvent(resourceType string, action api.SAction, isFailed api.SResult) ([]STopic, error) {
  866. q := sm.Query()
  867. q = q.Equals("results", isFailed).IsTrue("enabled")
  868. actionQ := TopicActionManager.Query("topic_id").Equals("action_id", action).SubQuery()
  869. q = q.In("id", actionQ)
  870. resourceQ := TopicResourceManager.Query("topic_id").Equals("resource_id", resourceType).SubQuery()
  871. q = q.In("id", resourceQ)
  872. var topics []STopic
  873. err := db.FetchModelObjects(sm, q, &topics)
  874. if err != nil {
  875. return nil, errors.Wrap(err, "unable to FetchModelObjects")
  876. }
  877. return topics, err
  878. }
  879. func (manager *STopicManager) TopicByEvent(eventStr string) (*STopic, error) {
  880. event, err := parseEvent(eventStr)
  881. if err != nil {
  882. return nil, errors.Wrapf(err, "unable to parse event %q", event)
  883. }
  884. q := manager.Query().Equals("results", event.Result() == api.ResultSucceed)
  885. actionQ := TopicActionManager.Query("topic_id").Equals("action_id", event.Action()).SubQuery()
  886. q = q.In("id", actionQ)
  887. resourceQ := TopicResourceManager.Query("topic_id").Equals("resource_id", event.ResourceType()).SubQuery()
  888. q = q.In("id", resourceQ)
  889. var topics []STopic
  890. err = db.FetchModelObjects(manager, q, &topics)
  891. if err != nil {
  892. return nil, errors.Wrap(err, "unable to FetchModelObjects")
  893. }
  894. for i := range topics {
  895. if topics[i].Enabled.IsFalse() {
  896. return nil, errors.Wrapf(errors.ErrInvalidStatus, "topic %s disabled", eventStr)
  897. }
  898. return &topics[i], nil
  899. }
  900. return nil, errors.Wrapf(errors.ErrNotFound, "topic %s", eventStr)
  901. }
  902. func (t *STopic) PreCheckPerformAction(
  903. ctx context.Context, userCred mcclient.TokenCredential,
  904. action string, query jsonutils.JSONObject, data jsonutils.JSONObject,
  905. ) error {
  906. if err := t.SStandaloneResourceBase.PreCheckPerformAction(ctx, userCred, action, query, data); err != nil {
  907. return err
  908. }
  909. if action == "enable" || action == "disable" {
  910. if !db.IsAdminAllowPerform(ctx, userCred, t, action) {
  911. return httperrors.NewForbiddenError("only allow admin to perform enable operations")
  912. }
  913. }
  914. return nil
  915. }
  916. func (t *STopic) PerformAddActions(
  917. ctx context.Context, userCred mcclient.TokenCredential,
  918. query jsonutils.JSONObject, data api.TopicAddActionInput,
  919. ) (jsonutils.JSONObject, error) {
  920. for _, action := range data.Actions {
  921. if len(action) == 0 {
  922. continue
  923. }
  924. t.addAction(notify.SAction(action))
  925. }
  926. return nil, nil
  927. }
  928. func (t *STopic) PerformAddResources(
  929. ctx context.Context, userCred mcclient.TokenCredential,
  930. query jsonutils.JSONObject, data api.TopicAddResourcesInput,
  931. ) (jsonutils.JSONObject, error) {
  932. for _, resource := range data.Resources {
  933. if len(resource) == 0 {
  934. continue
  935. }
  936. t.addResources(resource)
  937. }
  938. return nil, nil
  939. }
  940. func init() {
  941. converter = &sConverter{
  942. resource2Value: &sync.Map{},
  943. value2Resource: &sync.Map{},
  944. action2Value: &sync.Map{},
  945. value2Action: &sync.Map{},
  946. }
  947. converter.registerResource(
  948. map[string]int{
  949. notify.TOPIC_RESOURCE_SERVER: 0,
  950. notify.TOPIC_RESOURCE_SCALINGGROUP: 1,
  951. notify.TOPIC_RESOURCE_SCALINGPOLICY: 2,
  952. notify.TOPIC_RESOURCE_IMAGE: 3,
  953. notify.TOPIC_RESOURCE_DISK: 4,
  954. notify.TOPIC_RESOURCE_SNAPSHOT: 5,
  955. notify.TOPIC_RESOURCE_INSTANCESNAPSHOT: 6,
  956. notify.TOPIC_RESOURCE_SNAPSHOTPOLICY: 7,
  957. notify.TOPIC_RESOURCE_NETWORK: 8,
  958. notify.TOPIC_RESOURCE_EIP: 9,
  959. notify.TOPIC_RESOURCE_SECGROUP: 10,
  960. notify.TOPIC_RESOURCE_LOADBALANCER: 11,
  961. notify.TOPIC_RESOURCE_LOADBALANCERACL: 12,
  962. notify.TOPIC_RESOURCE_LOADBALANCERCERTIFICATE: 13,
  963. notify.TOPIC_RESOURCE_BUCKET: 14,
  964. notify.TOPIC_RESOURCE_DBINSTANCE: 15,
  965. notify.TOPIC_RESOURCE_ELASTICCACHE: 16,
  966. notify.TOPIC_RESOURCE_SCHEDULEDTASK: 17,
  967. notify.TOPIC_RESOURCE_BAREMETAL: 18,
  968. notify.TOPIC_RESOURCE_VPC: 19,
  969. notify.TOPIC_RESOURCE_DNSZONE: 20,
  970. notify.TOPIC_RESOURCE_NATGATEWAY: 21,
  971. notify.TOPIC_RESOURCE_WEBAPP: 22,
  972. notify.TOPIC_RESOURCE_CDNDOMAIN: 23,
  973. notify.TOPIC_RESOURCE_FILESYSTEM: 24,
  974. notify.TOPIC_RESOURCE_WAF: 25,
  975. notify.TOPIC_RESOURCE_KAFKA: 26,
  976. notify.TOPIC_RESOURCE_ELASTICSEARCH: 27,
  977. notify.TOPIC_RESOURCE_MONGODB: 28,
  978. notify.TOPIC_RESOURCE_DNSRECORDSET: 29,
  979. notify.TOPIC_RESOURCE_LOADBALANCERLISTENER: 30,
  980. notify.TOPIC_RESOURCE_LOADBALANCERBACKEDNGROUP: 31,
  981. notify.TOPIC_RESOURCE_HOST: 32,
  982. notify.TOPIC_RESOURCE_TASK: 33,
  983. notify.TOPIC_RESOURCE_CLOUDPODS_COMPONENT: 34,
  984. notify.TOPIC_RESOURCE_DB_TABLE_RECORD: 35,
  985. notify.TOPIC_RESOURCE_USER: 36,
  986. notify.TOPIC_RESOURCE_ACTION_LOG: 37,
  987. notify.TOPIC_RESOURCE_ACCOUNT_STATUS: 38,
  988. notify.TOPIC_RESOURCE_NET: 39,
  989. notify.TOPIC_RESOURCE_SERVICE: 40,
  990. notify.TOPIC_RESOURCE_VM_INTEGRITY_CHECK: 41,
  991. notify.TOPIC_RESOURCE_PROJECT: 42,
  992. },
  993. )
  994. converter.registerAction(
  995. map[notify.SAction]int{
  996. notify.ActionCreate: 0,
  997. notify.ActionDelete: 1,
  998. notify.ActionPendingDelete: 2,
  999. notify.ActionUpdate: 3,
  1000. notify.ActionRebuildRoot: 4,
  1001. notify.ActionResetPassword: 5,
  1002. notify.ActionChangeConfig: 6,
  1003. notify.ActionExpiredRelease: 7,
  1004. notify.ActionExecute: 8,
  1005. notify.ActionChangeIpaddr: 9,
  1006. notify.ActionSyncStatus: 10,
  1007. notify.ActionCleanData: 11,
  1008. notify.ActionMigrate: 12,
  1009. notify.ActionCreateBackupServer: 13,
  1010. notify.ActionDelBackupServer: 14,
  1011. notify.ActionSyncCreate: 15,
  1012. notify.ActionSyncUpdate: 16,
  1013. notify.ActionSyncDelete: 17,
  1014. notify.ActionOffline: 18,
  1015. notify.ActionSystemPanic: 19,
  1016. notify.ActionSystemException: 20,
  1017. notify.ActionChecksumTest: 21,
  1018. notify.ActionLock: 22,
  1019. notify.ActionExceedCount: 23,
  1020. notify.ActionSyncAccountStatus: 24,
  1021. notify.ActionPasswordExpireSoon: 25,
  1022. notify.ActionNetOutOfSync: 26,
  1023. notify.ActionMysqlOutOfSync: 27,
  1024. notify.ActionServiceAbnormal: 28,
  1025. notify.ActionServerPanicked: 29,
  1026. notify.ActionAttach: 30,
  1027. notify.ActionDetach: 31,
  1028. notify.ActionIsolatedDeviceCreate: 32,
  1029. notify.ActionIsolatedDeviceUpdate: 33,
  1030. notify.ActionIsolatedDeviceDelete: 34,
  1031. notify.ActionStatusChanged: 35,
  1032. },
  1033. )
  1034. }
  1035. var converter *sConverter
  1036. type sConverter struct {
  1037. resource2Value *sync.Map
  1038. value2Resource *sync.Map
  1039. action2Value *sync.Map
  1040. value2Action *sync.Map
  1041. }
  1042. type sResourceValue struct {
  1043. resource string
  1044. value int
  1045. }
  1046. type sActionValue struct {
  1047. action string
  1048. value int
  1049. }
  1050. func (rc *sConverter) registerResource(resourceValues map[string]int) {
  1051. for resource, value := range resourceValues {
  1052. if v, ok := rc.resource2Value.Load(resource); ok && v.(int) != value {
  1053. log.Fatalf("resource '%s' has been mapped to value '%d', and it is not allowed to map to another value '%d'", resource, v, value)
  1054. }
  1055. if r, ok := rc.value2Resource.Load(value); ok && r.(string) != resource {
  1056. log.Fatalf("value '%d' has been mapped to resource '%s', and it is not allowed to map to another resource '%s'", value, r, resource)
  1057. }
  1058. rc.resource2Value.Store(resource, value)
  1059. rc.value2Resource.Store(value, resource)
  1060. }
  1061. }
  1062. func (rc *sConverter) registerAction(actionValues map[notify.SAction]int) {
  1063. for action, value := range actionValues {
  1064. if v, ok := rc.action2Value.Load(action); ok && v.(int) != value {
  1065. log.Fatalf("action '%s' has been mapped to value '%d', and it is not allowed to map to another value '%d'", action, v, value)
  1066. }
  1067. if a, ok := rc.value2Action.Load(value); ok && a.(notify.SAction) != action {
  1068. log.Fatalf("value '%d' has been mapped to action '%s', and it is not allowed to map to another action '%s'", value, a, action)
  1069. }
  1070. rc.action2Value.Store(action, value)
  1071. rc.value2Action.Store(value, action)
  1072. }
  1073. }
  1074. func (rc *sConverter) resourceValue(resource string) int {
  1075. v, ok := rc.resource2Value.Load(resource)
  1076. if !ok {
  1077. return -1
  1078. }
  1079. return v.(int)
  1080. }
  1081. func (rc *sConverter) resource(resourceValue int) string {
  1082. r, ok := rc.value2Resource.Load(resourceValue)
  1083. if !ok {
  1084. return ""
  1085. }
  1086. return r.(string)
  1087. }
  1088. func (rc *sConverter) actionValue(action notify.SAction) int {
  1089. v, ok := rc.action2Value.Load(action)
  1090. if !ok {
  1091. return -1
  1092. }
  1093. return v.(int)
  1094. }
  1095. func (rc *sConverter) action(actionValue int) notify.SAction {
  1096. a, ok := rc.value2Action.Load(actionValue)
  1097. if !ok {
  1098. return notify.SAction("")
  1099. }
  1100. return a.(notify.SAction)
  1101. }
  1102. func (self *STopic) GetEnabledSubscribers(domainId, projectId string) ([]SSubscriber, error) {
  1103. q := SubscriberManager.Query().Equals("topic_id", self.Id).IsTrue("enabled")
  1104. q = q.Filter(sqlchemy.OR(
  1105. sqlchemy.AND(
  1106. sqlchemy.Equals(q.Field("resource_scope"), api.SUBSCRIBER_SCOPE_PROJECT),
  1107. sqlchemy.Equals(q.Field("resource_attribution_id"), projectId),
  1108. ),
  1109. sqlchemy.AND(
  1110. sqlchemy.Equals(q.Field("resource_scope"), api.SUBSCRIBER_SCOPE_DOMAIN),
  1111. sqlchemy.Equals(q.Field("resource_attribution_id"), domainId),
  1112. ),
  1113. sqlchemy.Equals(q.Field("resource_scope"), api.SUBSCRIBER_SCOPE_SYSTEM),
  1114. ))
  1115. ret := []SSubscriber{}
  1116. err := db.FetchModelObjects(SubscriberManager, q, &ret)
  1117. return ret, err
  1118. }