topic.go 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139
  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"`
  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_CLOUDPHONE,
  474. )
  475. t.addAction(
  476. api.ActionStart,
  477. api.ActionStop,
  478. api.ActionRestart,
  479. api.ActionReset,
  480. api.ActionAttach,
  481. api.ActionDetach,
  482. api.ActionCreate,
  483. api.ActionSyncStatus,
  484. api.ActionRebuildRoot,
  485. api.ActionChangeConfig,
  486. api.ActionCreateBackupServer,
  487. api.ActionDelBackupServer,
  488. api.ActionMigrate,
  489. )
  490. case DefaultResourceOperationSuccessed:
  491. t.addResources(
  492. api.TOPIC_RESOURCE_SERVER,
  493. api.TOPIC_RESOURCE_CLOUDPHONE,
  494. api.TOPIC_RESOURCE_DISK,
  495. )
  496. t.addAction(
  497. api.ActionStart,
  498. api.ActionStop,
  499. api.ActionRestart,
  500. api.ActionReset,
  501. api.ActionCreateBackupServer,
  502. )
  503. case DefaultResourceSync:
  504. t.addResources(
  505. api.TOPIC_RESOURCE_SERVER,
  506. api.TOPIC_RESOURCE_DISK,
  507. api.TOPIC_RESOURCE_DBINSTANCE,
  508. api.TOPIC_RESOURCE_ELASTICCACHE,
  509. api.TOPIC_RESOURCE_LOADBALANCER,
  510. api.TOPIC_RESOURCE_EIP,
  511. api.TOPIC_RESOURCE_VPC,
  512. api.TOPIC_RESOURCE_NETWORK,
  513. api.TOPIC_RESOURCE_LOADBALANCERCERTIFICATE,
  514. api.TOPIC_RESOURCE_DNSZONE,
  515. api.TOPIC_RESOURCE_NATGATEWAY,
  516. api.TOPIC_RESOURCE_BUCKET,
  517. api.TOPIC_RESOURCE_FILESYSTEM,
  518. api.TOPIC_RESOURCE_WEBAPP,
  519. api.TOPIC_RESOURCE_CDNDOMAIN,
  520. api.TOPIC_RESOURCE_WAF,
  521. api.TOPIC_RESOURCE_KAFKA,
  522. api.TOPIC_RESOURCE_ELASTICSEARCH,
  523. api.TOPIC_RESOURCE_MONGODB,
  524. api.TOPIC_RESOURCE_DNSRECORDSET,
  525. api.TOPIC_RESOURCE_LOADBALANCERLISTENER,
  526. api.TOPIC_RESOURCE_LOADBALANCERBACKEDNGROUP,
  527. )
  528. t.addAction(
  529. api.ActionSyncCreate,
  530. api.ActionSyncUpdate,
  531. api.ActionSyncDelete,
  532. )
  533. case DefaultSystemExceptionEvent:
  534. t.addResources(
  535. api.TOPIC_RESOURCE_HOST,
  536. api.TOPIC_RESOURCE_TASK,
  537. )
  538. t.addAction(
  539. api.ActionSystemPanic,
  540. api.ActionSystemException,
  541. api.ActionOffline,
  542. api.ActionHostDown,
  543. api.ActionHostDownAutoMigrate,
  544. )
  545. case DefaultChecksumTestFailed:
  546. t.addResources(
  547. api.TOPIC_RESOURCE_DB_TABLE_RECORD,
  548. api.TOPIC_RESOURCE_VM_INTEGRITY_CHECK,
  549. api.TOPIC_RESOURCE_CLOUDPODS_COMPONENT,
  550. api.TOPIC_RESOURCE_SNAPSHOT,
  551. api.TOPIC_RESOURCE_IMAGE,
  552. )
  553. t.addAction(
  554. api.ActionChecksumTest,
  555. )
  556. case DefaultUserLock:
  557. t.addResources(
  558. api.TOPIC_RESOURCE_USER,
  559. )
  560. t.addAction(
  561. api.ActionLock,
  562. )
  563. case DefaultActionLogExceedCount:
  564. t.addResources(
  565. api.TOPIC_RESOURCE_ACTION_LOG,
  566. )
  567. t.addAction(
  568. api.ActionExceedCount,
  569. )
  570. case DefaultSyncAccountStatus:
  571. t.addResources(
  572. api.TOPIC_RESOURCE_ACCOUNT_STATUS,
  573. )
  574. t.addAction(
  575. api.ActionSyncAccountStatus,
  576. )
  577. case DefaultNetOutOfSync:
  578. t.addResources(
  579. api.TOPIC_RESOURCE_NET,
  580. )
  581. t.addAction(
  582. api.ActionNetOutOfSync,
  583. )
  584. case DefaultMysqlOutOfSync:
  585. t.addResources(
  586. api.TOPIC_RESOURCE_DBINSTANCE,
  587. )
  588. t.addAction(
  589. api.ActionMysqlOutOfSync,
  590. )
  591. case DefaultServiceAbnormal:
  592. t.addResources(
  593. api.TOPIC_RESOURCE_SERVICE,
  594. )
  595. t.addAction(
  596. api.ActionServiceAbnormal,
  597. )
  598. case DefaultServerPanicked:
  599. t.addResources(
  600. api.TOPIC_RESOURCE_SERVER,
  601. )
  602. t.addAction(
  603. api.ActionServerPanicked,
  604. )
  605. case DefaultPasswordExpire:
  606. t.addResources(
  607. api.TOPIC_RESOURCE_USER,
  608. )
  609. t.addAction(
  610. api.ActionPasswordExpireSoon,
  611. )
  612. case DefaultResourceRelease:
  613. t.addResources(
  614. api.TOPIC_RESOURCE_SERVER,
  615. api.TOPIC_RESOURCE_DISK,
  616. api.TOPIC_RESOURCE_EIP,
  617. api.TOPIC_RESOURCE_LOADBALANCER,
  618. api.TOPIC_RESOURCE_DBINSTANCE,
  619. api.TOPIC_RESOURCE_ELASTICCACHE,
  620. )
  621. t.addAction(api.ActionExpiredRelease)
  622. case DefaultAttachOrDetach:
  623. t.addResources(
  624. api.TOPIC_RESOURCE_HOST,
  625. api.TOPIC_RESOURCE_CLOUDPHONE,
  626. )
  627. t.addAction(
  628. api.ActionAttach,
  629. api.ActionDetach,
  630. )
  631. case DefaultIsolatedDeviceChanged:
  632. t.addResources(
  633. api.TOPIC_RESOURCE_HOST,
  634. )
  635. t.addAction(
  636. api.ActionIsolatedDeviceCreate,
  637. api.ActionIsolatedDeviceUpdate,
  638. api.ActionIsolatedDeviceDelete,
  639. )
  640. case DefaultStatusChanged:
  641. t.addResources(
  642. api.TOPIC_RESOURCE_SERVER,
  643. api.TOPIC_RESOURCE_HOST,
  644. )
  645. t.addAction(
  646. api.ActionStatusChanged,
  647. )
  648. }
  649. }
  650. func (sm *STopicManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, input api.TopicListInput) (*sqlchemy.SQuery, error) {
  651. q, err := sm.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, input.StandaloneResourceListInput)
  652. if err != nil {
  653. return nil, errors.Wrap(err, "SStandaloneResourceBaseManager.ListItemFilter")
  654. }
  655. q, err = sm.SEnabledResourceBaseManager.ListItemFilter(ctx, q, userCred, input.EnabledResourceBaseListInput)
  656. if err != nil {
  657. return nil, errors.Wrap(err, "SEnabledResourceBaseManager.ListItemFilter")
  658. }
  659. return q, nil
  660. }
  661. func (sm *STopicManager) FetchCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, objs []interface{}, fields stringutils2.SSortedStrings, isList bool) []api.TopicDetails {
  662. sRows := sm.SStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  663. rows := make([]api.TopicDetails, len(objs))
  664. topicIds := make([]string, len(objs))
  665. for i := range rows {
  666. rows[i].StandaloneResourceDetails = sRows[i]
  667. ss := objs[i].(*STopic)
  668. topicIds[i] = ss.Id
  669. }
  670. resources, resourceMap := []STopicResource{}, map[string][]string{}
  671. err := TopicResourceManager.Query().In("topic_id", topicIds).All(&resources)
  672. if err != nil {
  673. log.Errorf("query resources error: %v", err)
  674. return rows
  675. }
  676. for _, r := range resources {
  677. _, ok := resourceMap[r.TopicId]
  678. if !ok {
  679. resourceMap[r.TopicId] = []string{}
  680. }
  681. resourceMap[r.TopicId] = append(resourceMap[r.TopicId], r.ResourceId)
  682. }
  683. actions, actionMap := []STopicAction{}, map[string][]string{}
  684. err = TopicActionManager.Query().In("topic_id", topicIds).All(&actions)
  685. if err != nil {
  686. log.Errorf("query actions error: %v", err)
  687. return rows
  688. }
  689. for _, a := range actions {
  690. _, ok := actionMap[a.TopicId]
  691. if !ok {
  692. actionMap[a.TopicId] = []string{}
  693. }
  694. actionMap[a.TopicId] = append(actionMap[a.TopicId], a.ActionId)
  695. }
  696. for i := range rows {
  697. rows[i].Resources, _ = resourceMap[topicIds[i]]
  698. rows[i].Actions, _ = actionMap[topicIds[i]]
  699. }
  700. return rows
  701. }
  702. func (sm *STopicManager) ValidateCreateData(
  703. ctx context.Context,
  704. userCred mcclient.TokenCredential,
  705. ownerId mcclient.IIdentityProvider,
  706. query jsonutils.JSONObject,
  707. input *api.STopicCreateInput,
  708. ) (*api.STopicCreateInput, error) {
  709. var err error
  710. input.EnabledStatusStandaloneResourceCreateInput, err = sm.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusStandaloneResourceCreateInput)
  711. if err != nil {
  712. return nil, err
  713. }
  714. if !utils.IsInStringArray(input.Type, []string{
  715. api.TOPIC_TYPE_RESOURCE,
  716. api.TOPIC_TYPE_AUTOMATED_PROCESS,
  717. api.TOPIC_TYPE_SECURITY,
  718. }) {
  719. return nil, httperrors.NewInputParameterError("invalid type %s", input.Type)
  720. }
  721. input.Status = apis.STATUS_AVAILABLE
  722. return input, nil
  723. }
  724. func (tp *STopic) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
  725. tp.SEnabledStatusStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
  726. input := &api.STopicCreateInput{}
  727. data.Unmarshal(input)
  728. for _, resource := range input.Resources {
  729. r := &STopicResource{
  730. ResourceId: resource,
  731. TopicId: tp.Id,
  732. }
  733. r.SetModelManager(TopicResourceManager, r)
  734. TopicResourceManager.TableSpec().Insert(ctx, r)
  735. }
  736. for _, action := range input.Actions {
  737. a := &STopicAction{
  738. ActionId: action,
  739. TopicId: tp.Id,
  740. }
  741. a.SetModelManager(TopicActionManager, a)
  742. TopicActionManager.TableSpec().Insert(ctx, a)
  743. }
  744. }
  745. func (ss *STopic) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.TopicUpdateInput) (*api.TopicUpdateInput, error) {
  746. var err error
  747. input.EnabledStatusStandaloneResourceBaseUpdateInput, err = ss.SEnabledStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, input.EnabledStatusStandaloneResourceBaseUpdateInput)
  748. if err != nil {
  749. return nil, err
  750. }
  751. return input, nil
  752. }
  753. func (tp *STopic) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
  754. tp.SEnabledStatusStandaloneResourceBase.PostUpdate(ctx, userCred, query, data)
  755. input := api.TopicUpdateInput{}
  756. jsonutils.Update(&input, data)
  757. if len(input.Resources) > 0 {
  758. tp.cleanResources()
  759. for _, res := range input.Resources {
  760. r := &STopicResource{
  761. ResourceId: res,
  762. TopicId: tp.Id,
  763. }
  764. r.SetModelManager(TopicResourceManager, r)
  765. TopicResourceManager.TableSpec().Insert(ctx, r)
  766. }
  767. }
  768. if len(input.Actions) > 0 {
  769. tp.cleanActions()
  770. for _, action := range input.Actions {
  771. a := &STopicAction{
  772. ActionId: action,
  773. TopicId: tp.Id,
  774. }
  775. a.SetModelManager(TopicActionManager, a)
  776. TopicActionManager.TableSpec().Insert(ctx, a)
  777. }
  778. }
  779. }
  780. func (ss *STopic) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
  781. return ss.SEnabledStatusStandaloneResourceBase.ValidateDeleteCondition(ctx, info)
  782. }
  783. func (tp *STopic) cleanResources() error {
  784. _, err := sqlchemy.GetDB().Exec(
  785. fmt.Sprintf(
  786. "delete from %s where topic_id = ?",
  787. TopicResourceManager.TableSpec().Name(),
  788. ), tp.Id,
  789. )
  790. return err
  791. }
  792. func (tp *STopic) cleanActions() error {
  793. _, err := sqlchemy.GetDB().Exec(
  794. fmt.Sprintf(
  795. "delete from %s where topic_id = ?",
  796. TopicActionManager.TableSpec().Name(),
  797. ), tp.Id,
  798. )
  799. return err
  800. }
  801. func (tp *STopic) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
  802. err := tp.cleanResources()
  803. if err != nil {
  804. return errors.Wrapf(err, "cleanResources")
  805. }
  806. err = tp.cleanActions()
  807. if err != nil {
  808. return errors.Wrapf(err, "cleanActions")
  809. }
  810. return tp.SEnabledStatusStandaloneResourceBase.Delete(ctx, userCred)
  811. }
  812. func (s *STopic) addResources(resources ...string) {
  813. for i := range resources {
  814. if TopicResourceManager.Query().Equals("topic_id", s.Id).Equals("resource_id", resources[i]).Count() == 0 {
  815. TopicResourceManager.TableSpec().InsertOrUpdate(context.Background(), &STopicResource{
  816. ResourceId: resources[i],
  817. TopicId: s.Id,
  818. })
  819. }
  820. }
  821. }
  822. func (s *STopic) addAction(actions ...api.SAction) {
  823. for i := range actions {
  824. if TopicActionManager.Query().Equals("topic_id", s.Id).Equals("action_id", actions[i]).Count() == 0 {
  825. TopicActionManager.TableSpec().InsertOrUpdate(context.Background(), &STopicAction{
  826. ActionId: string(actions[i]),
  827. TopicId: s.Id,
  828. })
  829. }
  830. }
  831. }
  832. func (s *STopic) GetResources() ([]STopicResource, error) {
  833. ret := []STopicResource{}
  834. q := TopicResourceManager.Query().Equals("topic_id", s.Id)
  835. err := db.FetchModelObjects(TopicResourceManager, q, &ret)
  836. if err != nil {
  837. return nil, err
  838. }
  839. return ret, nil
  840. }
  841. func (s *STopic) GetActions() ([]STopicAction, error) {
  842. ret := []STopicAction{}
  843. q := TopicActionManager.Query().Equals("topic_id", s.Id)
  844. err := db.FetchModelObjects(TopicActionManager, q, &ret)
  845. if err != nil {
  846. return nil, err
  847. }
  848. return ret, nil
  849. }
  850. func (sm *STopicManager) GetTopicByEvent(resourceType string, action api.SAction, isFailed api.SResult) (*STopic, error) {
  851. topics, err := sm.GetTopicsByEvent(resourceType, action, isFailed)
  852. if err != nil {
  853. return nil, errors.Wrapf(err, "GetTopicsByEvent")
  854. }
  855. if len(topics) == 0 {
  856. return nil, httperrors.NewResourceNotFoundError("no available topic found by %s %s", action, resourceType)
  857. }
  858. // free memory in time
  859. if len(topics) > 1 {
  860. return nil, httperrors.NewResourceNotFoundError("duplicates %d topics found by %s %s", len(topics), action, resourceType)
  861. }
  862. return &topics[0], nil
  863. }
  864. func (sm *STopicManager) GetTopicsByEvent(resourceType string, action api.SAction, isFailed api.SResult) ([]STopic, error) {
  865. q := sm.Query()
  866. q = q.Equals("results", isFailed).IsTrue("enabled")
  867. actionQ := TopicActionManager.Query("topic_id").Equals("action_id", action).SubQuery()
  868. q = q.In("id", actionQ)
  869. resourceQ := TopicResourceManager.Query("topic_id").Equals("resource_id", resourceType).SubQuery()
  870. q = q.In("id", resourceQ)
  871. var topics []STopic
  872. err := db.FetchModelObjects(sm, q, &topics)
  873. if err != nil {
  874. return nil, errors.Wrap(err, "unable to FetchModelObjects")
  875. }
  876. return topics, err
  877. }
  878. func (manager *STopicManager) TopicByEvent(eventStr string) (*STopic, error) {
  879. event, err := parseEvent(eventStr)
  880. if err != nil {
  881. return nil, errors.Wrapf(err, "unable to parse event %q", event)
  882. }
  883. q := manager.Query().Equals("results", event.Result() == api.ResultSucceed)
  884. actionQ := TopicActionManager.Query("topic_id").Equals("action_id", event.Action()).SubQuery()
  885. q = q.In("id", actionQ)
  886. resourceQ := TopicResourceManager.Query("topic_id").Equals("resource_id", event.ResourceType()).SubQuery()
  887. q = q.In("id", resourceQ)
  888. var topics []STopic
  889. err = db.FetchModelObjects(manager, q, &topics)
  890. if err != nil {
  891. return nil, errors.Wrap(err, "unable to FetchModelObjects")
  892. }
  893. for i := range topics {
  894. if topics[i].Enabled.IsFalse() {
  895. return nil, errors.Wrapf(errors.ErrInvalidStatus, "topic %s disabled", eventStr)
  896. }
  897. return &topics[i], nil
  898. }
  899. return nil, errors.Wrapf(errors.ErrNotFound, "topic %s", eventStr)
  900. }
  901. func (t *STopic) PreCheckPerformAction(
  902. ctx context.Context, userCred mcclient.TokenCredential,
  903. action string, query jsonutils.JSONObject, data jsonutils.JSONObject,
  904. ) error {
  905. if err := t.SStandaloneResourceBase.PreCheckPerformAction(ctx, userCred, action, query, data); err != nil {
  906. return err
  907. }
  908. if action == "enable" || action == "disable" {
  909. if !db.IsAdminAllowPerform(ctx, userCred, t, action) {
  910. return httperrors.NewForbiddenError("only allow admin to perform enable operations")
  911. }
  912. }
  913. return nil
  914. }
  915. func init() {
  916. converter = &sConverter{
  917. resource2Value: &sync.Map{},
  918. value2Resource: &sync.Map{},
  919. action2Value: &sync.Map{},
  920. value2Action: &sync.Map{},
  921. }
  922. converter.registerResource(
  923. map[string]int{
  924. notify.TOPIC_RESOURCE_SERVER: 0,
  925. notify.TOPIC_RESOURCE_SCALINGGROUP: 1,
  926. notify.TOPIC_RESOURCE_SCALINGPOLICY: 2,
  927. notify.TOPIC_RESOURCE_IMAGE: 3,
  928. notify.TOPIC_RESOURCE_DISK: 4,
  929. notify.TOPIC_RESOURCE_SNAPSHOT: 5,
  930. notify.TOPIC_RESOURCE_INSTANCESNAPSHOT: 6,
  931. notify.TOPIC_RESOURCE_SNAPSHOTPOLICY: 7,
  932. notify.TOPIC_RESOURCE_NETWORK: 8,
  933. notify.TOPIC_RESOURCE_EIP: 9,
  934. notify.TOPIC_RESOURCE_SECGROUP: 10,
  935. notify.TOPIC_RESOURCE_LOADBALANCER: 11,
  936. notify.TOPIC_RESOURCE_LOADBALANCERACL: 12,
  937. notify.TOPIC_RESOURCE_LOADBALANCERCERTIFICATE: 13,
  938. notify.TOPIC_RESOURCE_BUCKET: 14,
  939. notify.TOPIC_RESOURCE_DBINSTANCE: 15,
  940. notify.TOPIC_RESOURCE_ELASTICCACHE: 16,
  941. notify.TOPIC_RESOURCE_SCHEDULEDTASK: 17,
  942. notify.TOPIC_RESOURCE_BAREMETAL: 18,
  943. notify.TOPIC_RESOURCE_VPC: 19,
  944. notify.TOPIC_RESOURCE_DNSZONE: 20,
  945. notify.TOPIC_RESOURCE_NATGATEWAY: 21,
  946. notify.TOPIC_RESOURCE_WEBAPP: 22,
  947. notify.TOPIC_RESOURCE_CDNDOMAIN: 23,
  948. notify.TOPIC_RESOURCE_FILESYSTEM: 24,
  949. notify.TOPIC_RESOURCE_WAF: 25,
  950. notify.TOPIC_RESOURCE_KAFKA: 26,
  951. notify.TOPIC_RESOURCE_ELASTICSEARCH: 27,
  952. notify.TOPIC_RESOURCE_MONGODB: 28,
  953. notify.TOPIC_RESOURCE_DNSRECORDSET: 29,
  954. notify.TOPIC_RESOURCE_LOADBALANCERLISTENER: 30,
  955. notify.TOPIC_RESOURCE_LOADBALANCERBACKEDNGROUP: 31,
  956. notify.TOPIC_RESOURCE_HOST: 32,
  957. notify.TOPIC_RESOURCE_TASK: 33,
  958. notify.TOPIC_RESOURCE_CLOUDPODS_COMPONENT: 34,
  959. notify.TOPIC_RESOURCE_DB_TABLE_RECORD: 35,
  960. notify.TOPIC_RESOURCE_USER: 36,
  961. notify.TOPIC_RESOURCE_ACTION_LOG: 37,
  962. notify.TOPIC_RESOURCE_ACCOUNT_STATUS: 38,
  963. notify.TOPIC_RESOURCE_NET: 39,
  964. notify.TOPIC_RESOURCE_SERVICE: 40,
  965. notify.TOPIC_RESOURCE_VM_INTEGRITY_CHECK: 41,
  966. notify.TOPIC_RESOURCE_PROJECT: 42,
  967. },
  968. )
  969. converter.registerAction(
  970. map[notify.SAction]int{
  971. notify.ActionCreate: 0,
  972. notify.ActionDelete: 1,
  973. notify.ActionPendingDelete: 2,
  974. notify.ActionUpdate: 3,
  975. notify.ActionRebuildRoot: 4,
  976. notify.ActionResetPassword: 5,
  977. notify.ActionChangeConfig: 6,
  978. notify.ActionExpiredRelease: 7,
  979. notify.ActionExecute: 8,
  980. notify.ActionChangeIpaddr: 9,
  981. notify.ActionSyncStatus: 10,
  982. notify.ActionCleanData: 11,
  983. notify.ActionMigrate: 12,
  984. notify.ActionCreateBackupServer: 13,
  985. notify.ActionDelBackupServer: 14,
  986. notify.ActionSyncCreate: 15,
  987. notify.ActionSyncUpdate: 16,
  988. notify.ActionSyncDelete: 17,
  989. notify.ActionOffline: 18,
  990. notify.ActionSystemPanic: 19,
  991. notify.ActionSystemException: 20,
  992. notify.ActionChecksumTest: 21,
  993. notify.ActionLock: 22,
  994. notify.ActionExceedCount: 23,
  995. notify.ActionSyncAccountStatus: 24,
  996. notify.ActionPasswordExpireSoon: 25,
  997. notify.ActionNetOutOfSync: 26,
  998. notify.ActionMysqlOutOfSync: 27,
  999. notify.ActionServiceAbnormal: 28,
  1000. notify.ActionServerPanicked: 29,
  1001. notify.ActionAttach: 30,
  1002. notify.ActionDetach: 31,
  1003. notify.ActionIsolatedDeviceCreate: 32,
  1004. notify.ActionIsolatedDeviceUpdate: 33,
  1005. notify.ActionIsolatedDeviceDelete: 34,
  1006. notify.ActionStatusChanged: 35,
  1007. },
  1008. )
  1009. }
  1010. var converter *sConverter
  1011. type sConverter struct {
  1012. resource2Value *sync.Map
  1013. value2Resource *sync.Map
  1014. action2Value *sync.Map
  1015. value2Action *sync.Map
  1016. }
  1017. type sResourceValue struct {
  1018. resource string
  1019. value int
  1020. }
  1021. type sActionValue struct {
  1022. action string
  1023. value int
  1024. }
  1025. func (rc *sConverter) registerResource(resourceValues map[string]int) {
  1026. for resource, value := range resourceValues {
  1027. if v, ok := rc.resource2Value.Load(resource); ok && v.(int) != value {
  1028. log.Fatalf("resource '%s' has been mapped to value '%d', and it is not allowed to map to another value '%d'", resource, v, value)
  1029. }
  1030. if r, ok := rc.value2Resource.Load(value); ok && r.(string) != resource {
  1031. log.Fatalf("value '%d' has been mapped to resource '%s', and it is not allowed to map to another resource '%s'", value, r, resource)
  1032. }
  1033. rc.resource2Value.Store(resource, value)
  1034. rc.value2Resource.Store(value, resource)
  1035. }
  1036. }
  1037. func (rc *sConverter) registerAction(actionValues map[notify.SAction]int) {
  1038. for action, value := range actionValues {
  1039. if v, ok := rc.action2Value.Load(action); ok && v.(int) != value {
  1040. log.Fatalf("action '%s' has been mapped to value '%d', and it is not allowed to map to another value '%d'", action, v, value)
  1041. }
  1042. if a, ok := rc.value2Action.Load(value); ok && a.(notify.SAction) != action {
  1043. log.Fatalf("value '%d' has been mapped to action '%s', and it is not allowed to map to another action '%s'", value, a, action)
  1044. }
  1045. rc.action2Value.Store(action, value)
  1046. rc.value2Action.Store(value, action)
  1047. }
  1048. }
  1049. func (rc *sConverter) resourceValue(resource string) int {
  1050. v, ok := rc.resource2Value.Load(resource)
  1051. if !ok {
  1052. return -1
  1053. }
  1054. return v.(int)
  1055. }
  1056. func (rc *sConverter) resource(resourceValue int) string {
  1057. r, ok := rc.value2Resource.Load(resourceValue)
  1058. if !ok {
  1059. return ""
  1060. }
  1061. return r.(string)
  1062. }
  1063. func (rc *sConverter) actionValue(action notify.SAction) int {
  1064. v, ok := rc.action2Value.Load(action)
  1065. if !ok {
  1066. return -1
  1067. }
  1068. return v.(int)
  1069. }
  1070. func (rc *sConverter) action(actionValue int) notify.SAction {
  1071. a, ok := rc.value2Action.Load(actionValue)
  1072. if !ok {
  1073. return notify.SAction("")
  1074. }
  1075. return a.(notify.SAction)
  1076. }
  1077. func (self *STopic) GetEnabledSubscribers(domainId, projectId string) ([]SSubscriber, error) {
  1078. q := SubscriberManager.Query().Equals("topic_id", self.Id).IsTrue("enabled")
  1079. q = q.Filter(sqlchemy.OR(
  1080. sqlchemy.AND(
  1081. sqlchemy.Equals(q.Field("resource_scope"), api.SUBSCRIBER_SCOPE_PROJECT),
  1082. sqlchemy.Equals(q.Field("resource_attribution_id"), projectId),
  1083. ),
  1084. sqlchemy.AND(
  1085. sqlchemy.Equals(q.Field("resource_scope"), api.SUBSCRIBER_SCOPE_DOMAIN),
  1086. sqlchemy.Equals(q.Field("resource_attribution_id"), domainId),
  1087. ),
  1088. sqlchemy.Equals(q.Field("resource_scope"), api.SUBSCRIBER_SCOPE_SYSTEM),
  1089. ))
  1090. ret := []SSubscriber{}
  1091. err := db.FetchModelObjects(SubscriberManager, q, &ret)
  1092. return ret, err
  1093. }