globalvpcs.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package models
  15. import (
  16. "context"
  17. "time"
  18. "yunion.io/x/cloudmux/pkg/cloudprovider"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/log"
  21. "yunion.io/x/pkg/errors"
  22. "yunion.io/x/pkg/tristate"
  23. "yunion.io/x/pkg/util/compare"
  24. "yunion.io/x/pkg/util/rbacscope"
  25. "yunion.io/x/sqlchemy"
  26. "yunion.io/x/onecloud/pkg/apis"
  27. api "yunion.io/x/onecloud/pkg/apis/compute"
  28. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  29. "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
  30. "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
  31. "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
  32. "yunion.io/x/onecloud/pkg/cloudcommon/validators"
  33. "yunion.io/x/onecloud/pkg/httperrors"
  34. "yunion.io/x/onecloud/pkg/mcclient"
  35. "yunion.io/x/onecloud/pkg/util/logclient"
  36. "yunion.io/x/onecloud/pkg/util/stringutils2"
  37. )
  38. // +onecloud:swagger-gen-model-singular=globalvpc
  39. // +onecloud:swagger-gen-model-plural=globalvpcs
  40. type SGlobalVpcManager struct {
  41. db.SEnabledStatusInfrasResourceBaseManager
  42. db.SExternalizedResourceBaseManager
  43. SManagedResourceBaseManager
  44. }
  45. var GlobalVpcManager *SGlobalVpcManager
  46. func init() {
  47. GlobalVpcManager = &SGlobalVpcManager{
  48. SEnabledStatusInfrasResourceBaseManager: db.NewEnabledStatusInfrasResourceBaseManager(
  49. SGlobalVpc{},
  50. "globalvpcs_tbl",
  51. "globalvpc",
  52. "globalvpcs",
  53. ),
  54. }
  55. GlobalVpcManager.SetVirtualObject(GlobalVpcManager)
  56. }
  57. type SGlobalVpc struct {
  58. db.SEnabledStatusInfrasResourceBase
  59. db.SExternalizedResourceBase
  60. SManagedResourceBase
  61. }
  62. func (self *SGlobalVpc) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
  63. vpcs, err := self.GetVpcs()
  64. if err != nil {
  65. return httperrors.NewInternalServerError("GetVpcs fail %s", err)
  66. }
  67. if len(vpcs) > 0 {
  68. return httperrors.NewNotEmptyError("global vpc has associate %d vpcs", len(vpcs))
  69. }
  70. return self.SEnabledStatusInfrasResourceBase.ValidateDeleteCondition(ctx, nil)
  71. }
  72. func (self *SGlobalVpc) GetVpcQuery() *sqlchemy.SQuery {
  73. return VpcManager.Query().Equals("globalvpc_id", self.Id)
  74. }
  75. func (self *SGlobalVpc) GetVpcs() ([]SVpc, error) {
  76. vpcs := []SVpc{}
  77. q := self.GetVpcQuery()
  78. err := db.FetchModelObjects(VpcManager, q, &vpcs)
  79. if err != nil {
  80. return nil, err
  81. }
  82. return vpcs, nil
  83. }
  84. func (self *SGlobalVpc) GetVpcCount() (int, error) {
  85. return self.GetVpcQuery().CountWithError()
  86. }
  87. func (manager *SGlobalVpcManager) FetchCustomizeColumns(
  88. ctx context.Context,
  89. userCred mcclient.TokenCredential,
  90. query jsonutils.JSONObject,
  91. objs []interface{},
  92. fields stringutils2.SSortedStrings,
  93. isList bool,
  94. ) []api.GlobalVpcDetails {
  95. rows := make([]api.GlobalVpcDetails, len(objs))
  96. stdRows := manager.SEnabledStatusInfrasResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  97. managerRows := manager.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  98. for i := range rows {
  99. rows[i] = api.GlobalVpcDetails{
  100. EnabledStatusInfrasResourceBaseDetails: stdRows[i],
  101. ManagedResourceInfo: managerRows[i],
  102. }
  103. gv := objs[i].(*SGlobalVpc)
  104. rows[i].VpcCount, _ = gv.GetVpcCount()
  105. }
  106. return rows
  107. }
  108. func (manager *SGlobalVpcManager) ValidateCreateData(
  109. ctx context.Context,
  110. userCred mcclient.TokenCredential,
  111. ownerId mcclient.IIdentityProvider,
  112. query jsonutils.JSONObject,
  113. input api.GlobalVpcCreateInput,
  114. ) (api.GlobalVpcCreateInput, error) {
  115. input.Status = apis.STATUS_CREATING
  116. var err error
  117. input.EnabledStatusInfrasResourceBaseCreateInput, err = manager.SEnabledStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusInfrasResourceBaseCreateInput)
  118. if err != nil {
  119. return input, errors.Wrap(err, "manager.SEnabledStatusInfrasResourceBaseManager.ValidateCreateData")
  120. }
  121. if len(input.CloudproviderId) == 0 {
  122. return input, httperrors.NewMissingParameterError("cloudprovider_id")
  123. }
  124. _, err = validators.ValidateModel(ctx, userCred, CloudproviderManager, &input.CloudproviderId)
  125. if err != nil {
  126. return input, err
  127. }
  128. input.ManagerId = input.CloudproviderId
  129. quota := &SDomainQuota{
  130. SBaseDomainQuotaKeys: quotas.SBaseDomainQuotaKeys{
  131. DomainId: ownerId.GetProjectDomainId(),
  132. },
  133. Globalvpc: 1,
  134. }
  135. err = quotas.CheckSetPendingQuota(ctx, userCred, quota)
  136. if err != nil {
  137. return input, errors.Wrap(err, "CheckSetPendingQuota")
  138. }
  139. return input, nil
  140. }
  141. func (self *SGlobalVpc) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
  142. self.SEnabledStatusInfrasResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
  143. quota := &SDomainQuota{
  144. SBaseDomainQuotaKeys: quotas.SBaseDomainQuotaKeys{
  145. DomainId: ownerId.GetProjectDomainId(),
  146. },
  147. Globalvpc: 1,
  148. }
  149. err := quotas.CancelPendingUsage(ctx, userCred, quota, quota, true)
  150. if err != nil {
  151. log.Errorf("CancelPendingUsage %s", err)
  152. }
  153. self.StartCreateTask(ctx, userCred, "")
  154. }
  155. func (self *SGlobalVpc) StartCreateTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  156. task, err := taskman.TaskManager.NewTask(ctx, "GlobalVpcCreateTask", self, userCred, nil, parentTaskId, "", nil)
  157. if err != nil {
  158. return errors.Wrapf(err, "NewTask")
  159. }
  160. return task.ScheduleRun(nil)
  161. }
  162. func (self *SGlobalVpc) ValidateUpdateData(
  163. ctx context.Context,
  164. userCred mcclient.TokenCredential,
  165. query jsonutils.JSONObject,
  166. input api.GlobalvpcUpdateInput,
  167. ) (api.GlobalvpcUpdateInput, error) {
  168. var err error
  169. input.EnabledStatusInfrasResourceBaseUpdateInput, err = self.SEnabledStatusInfrasResourceBase.ValidateUpdateData(ctx, userCred, query, input.EnabledStatusInfrasResourceBaseUpdateInput)
  170. if err != nil {
  171. return input, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.ValidateUpdateData")
  172. }
  173. return input, nil
  174. }
  175. // 全局VPC列表
  176. func (manager *SGlobalVpcManager) ListItemFilter(
  177. ctx context.Context,
  178. q *sqlchemy.SQuery,
  179. userCred mcclient.TokenCredential,
  180. query api.GlobalVpcListInput,
  181. ) (*sqlchemy.SQuery, error) {
  182. q, err := manager.SEnabledStatusInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, query.EnabledStatusInfrasResourceBaseListInput)
  183. if err != nil {
  184. return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.ListItemFilter")
  185. }
  186. q, err = manager.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
  187. if err != nil {
  188. return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
  189. }
  190. q, err = manager.SManagedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ManagedResourceListInput)
  191. if err != nil {
  192. return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemFilter")
  193. }
  194. return q, nil
  195. }
  196. func (manager *SGlobalVpcManager) OrderByExtraFields(
  197. ctx context.Context,
  198. q *sqlchemy.SQuery,
  199. userCred mcclient.TokenCredential,
  200. query api.GlobalVpcListInput,
  201. ) (*sqlchemy.SQuery, error) {
  202. q, err := manager.SEnabledStatusInfrasResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.EnabledStatusInfrasResourceBaseListInput)
  203. if err != nil {
  204. return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.OrderByExtraFields")
  205. }
  206. if db.NeedOrderQuery([]string{query.OrderByVpcCount}) {
  207. vpcQ := VpcManager.Query()
  208. vpcQ = vpcQ.AppendField(vpcQ.Field("globalvpc_id"), sqlchemy.COUNT("vpc_count"))
  209. vpcQ = vpcQ.GroupBy(vpcQ.Field("globalvpc_id"))
  210. vpcSQ := vpcQ.SubQuery()
  211. q = q.LeftJoin(vpcSQ, sqlchemy.Equals(vpcSQ.Field("globalvpc_id"), q.Field("id")))
  212. q = q.AppendField(q.QueryFields()...)
  213. q = q.AppendField(vpcSQ.Field("vpc_count"))
  214. q = db.OrderByFields(q, []string{query.OrderByVpcCount}, []sqlchemy.IQueryField{q.Field("vpc_count")})
  215. }
  216. return q, nil
  217. }
  218. func (manager *SGlobalVpcManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
  219. var err error
  220. q, err = manager.SEnabledStatusInfrasResourceBaseManager.QueryDistinctExtraField(q, field)
  221. if err == nil {
  222. return q, nil
  223. }
  224. return q, httperrors.ErrNotFound
  225. }
  226. func (self *SGlobalVpc) ValidateUpdateCondition(ctx context.Context) error {
  227. return self.SEnabledStatusInfrasResourceBase.ValidateUpdateCondition(ctx)
  228. }
  229. func (manager *SGlobalVpcManager) totalCount(scope rbacscope.TRbacScope, ownerId mcclient.IIdentityProvider) int {
  230. q := manager.Query()
  231. switch scope {
  232. case rbacscope.ScopeProject, rbacscope.ScopeDomain:
  233. q = q.Equals("domain_id", ownerId.GetProjectDomainId())
  234. }
  235. cnt, _ := q.CountWithError()
  236. return cnt
  237. }
  238. func (globalVpc *SGlobalVpc) GetUsages() []db.IUsage {
  239. if globalVpc.Deleted {
  240. return nil
  241. }
  242. usage := SDomainQuota{Globalvpc: 1}
  243. usage.SetKeys(quotas.SBaseDomainQuotaKeys{DomainId: globalVpc.DomainId})
  244. return []db.IUsage{
  245. &usage,
  246. }
  247. }
  248. func (globalVpc *SGlobalVpc) GetRequiredSharedDomainIds() []string {
  249. vpcs, _ := globalVpc.GetVpcs()
  250. if len(vpcs) == 0 {
  251. return globalVpc.SEnabledStatusInfrasResourceBase.GetRequiredSharedDomainIds()
  252. }
  253. requires := make([][]string, len(vpcs))
  254. for i := range vpcs {
  255. requires[i] = db.ISharableChangeOwnerCandidateDomainIds(&vpcs[i])
  256. }
  257. return db.ISharableMergeShareRequireDomainIds(requires...)
  258. }
  259. func (globalVpc *SGlobalVpc) GetChangeOwnerRequiredDomainIds() []string {
  260. requires := stringutils2.SSortedStrings{}
  261. vpcs, _ := globalVpc.GetVpcs()
  262. for i := range vpcs {
  263. requires = stringutils2.Append(requires, vpcs[i].DomainId)
  264. }
  265. return requires
  266. }
  267. func (self *SCloudprovider) GetGlobalVpcs() ([]SGlobalVpc, error) {
  268. q := GlobalVpcManager.Query().Equals("manager_id", self.Id)
  269. vpcs := []SGlobalVpc{}
  270. err := db.FetchModelObjects(GlobalVpcManager, q, &vpcs)
  271. if err != nil {
  272. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  273. }
  274. return vpcs, nil
  275. }
  276. func (self *SCloudprovider) SyncGlobalVpcs(ctx context.Context, userCred mcclient.TokenCredential, exts []cloudprovider.ICloudGlobalVpc, xor bool) ([]SGlobalVpc, []cloudprovider.ICloudGlobalVpc, compare.SyncResult) {
  277. lockman.LockRawObject(ctx, GlobalVpcManager.Keyword(), self.Id)
  278. defer lockman.ReleaseRawObject(ctx, GlobalVpcManager.Keyword(), self.Id)
  279. result := compare.SyncResult{}
  280. localVpcs := make([]SGlobalVpc, 0)
  281. remoteVpcs := make([]cloudprovider.ICloudGlobalVpc, 0)
  282. dbVpcs, err := self.GetGlobalVpcs()
  283. if err != nil {
  284. result.Error(err)
  285. return nil, nil, result
  286. }
  287. removed := make([]SGlobalVpc, 0)
  288. commondb := make([]SGlobalVpc, 0)
  289. commonext := make([]cloudprovider.ICloudGlobalVpc, 0)
  290. added := make([]cloudprovider.ICloudGlobalVpc, 0)
  291. err = compare.CompareSets(dbVpcs, exts, &removed, &commondb, &commonext, &added)
  292. if err != nil {
  293. result.Error(err)
  294. return nil, nil, result
  295. }
  296. for i := 0; i < len(removed); i += 1 {
  297. err = removed[i].syncRemoveGlobalVpc(ctx, userCred)
  298. if err != nil {
  299. result.DeleteError(err)
  300. continue
  301. }
  302. result.Delete()
  303. }
  304. for i := 0; i < len(commondb); i += 1 {
  305. err = commondb[i].SyncWithCloudGlobalVpc(ctx, userCred, commonext[i])
  306. if err != nil {
  307. result.UpdateError(err)
  308. continue
  309. }
  310. localVpcs = append(localVpcs, commondb[i])
  311. remoteVpcs = append(remoteVpcs, commonext[i])
  312. result.Update()
  313. }
  314. for i := 0; i < len(added); i += 1 {
  315. vpc, err := self.newFromCloudGlobalVpc(ctx, userCred, added[i])
  316. if err != nil {
  317. result.AddError(err)
  318. continue
  319. }
  320. localVpcs = append(localVpcs, *vpc)
  321. remoteVpcs = append(remoteVpcs, added[i])
  322. result.Add()
  323. }
  324. return localVpcs, remoteVpcs, result
  325. }
  326. func (self *SGlobalVpc) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
  327. return nil
  328. }
  329. func (self *SGlobalVpc) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
  330. return self.SEnabledStatusInfrasResourceBase.Delete(ctx, userCred)
  331. }
  332. func (self *SGlobalVpc) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
  333. return self.StartDeleteTask(ctx, userCred, "")
  334. }
  335. func (self *SGlobalVpc) StartDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  336. task, err := taskman.TaskManager.NewTask(ctx, "GlobalVpcDeleteTask", self, userCred, nil, parentTaskId, "", nil)
  337. if err != nil {
  338. return errors.Wrapf(err, "NewTask")
  339. }
  340. self.SetStatus(ctx, userCred, apis.STATUS_DELETING, "")
  341. return task.ScheduleRun(nil)
  342. }
  343. func (self *SGlobalVpc) GetICloudGlobalVpc(ctx context.Context) (cloudprovider.ICloudGlobalVpc, error) {
  344. if len(self.ExternalId) == 0 {
  345. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty external id")
  346. }
  347. provider, err := self.GetDriver(ctx)
  348. if err != nil {
  349. return nil, errors.Wrapf(err, "GetDriver")
  350. }
  351. return provider.GetICloudGlobalVpcById(self.ExternalId)
  352. }
  353. func (self *SGlobalVpc) syncRemoveGlobalVpc(ctx context.Context, userCred mcclient.TokenCredential) error {
  354. err := self.ValidateDeleteCondition(ctx, nil)
  355. if err != nil {
  356. self.SetStatus(ctx, userCred, apis.STATUS_UNKNOWN, "sync remove")
  357. return err
  358. }
  359. return self.RealDelete(ctx, userCred)
  360. }
  361. func (self *SGlobalVpc) SyncWithCloudGlobalVpc(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudGlobalVpc) error {
  362. _, err := db.Update(self, func() error {
  363. self.Status = ext.GetStatus()
  364. return nil
  365. })
  366. return err
  367. }
  368. func (self *SCloudprovider) newFromCloudGlobalVpc(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudGlobalVpc) (*SGlobalVpc, error) {
  369. gvpc := &SGlobalVpc{}
  370. gvpc.SetModelManager(GlobalVpcManager, gvpc)
  371. gvpc.Name = ext.GetName()
  372. gvpc.Status = ext.GetStatus()
  373. gvpc.ExternalId = ext.GetGlobalId()
  374. gvpc.ManagerId = self.Id
  375. gvpc.DomainId = self.DomainId
  376. gvpc.Enabled = tristate.True
  377. return gvpc, GlobalVpcManager.TableSpec().Insert(ctx, gvpc)
  378. }
  379. // 同步全局VPC状态
  380. func (self *SGlobalVpc) PerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.SyncstatusInput) (jsonutils.JSONObject, error) {
  381. var openTask = true
  382. count, err := taskman.TaskManager.QueryTasksOfObject(self, time.Now().Add(-3*time.Minute), &openTask).CountWithError()
  383. if err != nil {
  384. return nil, err
  385. }
  386. if count > 0 {
  387. return nil, httperrors.NewBadRequestError("Globalvpc has %d task active, can't sync status", count)
  388. }
  389. return nil, self.StartSyncstatusTask(ctx, userCred, "")
  390. }
  391. func (self *SGlobalVpc) StartSyncstatusTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  392. return StartResourceSyncStatusTask(ctx, userCred, self, "GlobalVpcSyncstatusTask", parentTaskId)
  393. }
  394. func (self *SGlobalVpc) GetSecgroups() ([]SSecurityGroup, error) {
  395. q := SecurityGroupManager.Query().Equals("globalvpc_id", self.Id)
  396. ret := []SSecurityGroup{}
  397. return ret, db.FetchModelObjects(SecurityGroupManager, q, &ret)
  398. }
  399. func (self *SGlobalVpc) SyncSecgroups(ctx context.Context, userCred mcclient.TokenCredential, exts []cloudprovider.ICloudSecurityGroup, xor bool) compare.SyncResult {
  400. lockman.LockRawObject(ctx, SecurityGroupManager.Keyword(), self.Id)
  401. defer lockman.ReleaseRawObject(ctx, SecurityGroupManager.Keyword(), self.Id)
  402. result := compare.SyncResult{}
  403. dbSecs, err := self.GetSecgroups()
  404. if err != nil {
  405. result.Error(err)
  406. return result
  407. }
  408. provider := self.GetCloudprovider()
  409. syncOwnerId := provider.GetOwnerId()
  410. removed := make([]SSecurityGroup, 0)
  411. commondb := make([]SSecurityGroup, 0)
  412. commonext := make([]cloudprovider.ICloudSecurityGroup, 0)
  413. added := make([]cloudprovider.ICloudSecurityGroup, 0)
  414. err = compare.CompareSets(dbSecs, exts, &removed, &commondb, &commonext, &added)
  415. if err != nil {
  416. result.Error(err)
  417. return result
  418. }
  419. for i := 0; i < len(removed); i += 1 {
  420. err = removed[i].RealDelete(ctx, userCred)
  421. if err != nil {
  422. result.DeleteError(err)
  423. continue
  424. }
  425. result.Delete()
  426. }
  427. for i := 0; i < len(commondb); i += 1 {
  428. if !xor {
  429. err = commondb[i].SyncWithCloudSecurityGroup(ctx, userCred, commonext[i], syncOwnerId, true)
  430. if err != nil {
  431. result.UpdateError(err)
  432. continue
  433. }
  434. }
  435. result.Update()
  436. }
  437. for i := 0; i < len(added); i += 1 {
  438. err := self.newFromCloudSecurityGroup(ctx, userCred, added[i], syncOwnerId)
  439. if err != nil {
  440. result.AddError(err)
  441. continue
  442. }
  443. result.Add()
  444. }
  445. return result
  446. }
  447. func (self *SGlobalVpc) newFromCloudSecurityGroup(
  448. ctx context.Context,
  449. userCred mcclient.TokenCredential,
  450. ext cloudprovider.ICloudSecurityGroup,
  451. syncOwnerId mcclient.IIdentityProvider,
  452. ) error {
  453. ret := &SSecurityGroup{}
  454. ret.SetModelManager(SecurityGroupManager, ret)
  455. ret.Name = ext.GetName()
  456. ret.Description = ext.GetDescription()
  457. ret.ExternalId = ext.GetGlobalId()
  458. ret.ManagerId = self.ManagerId
  459. ret.GlobalvpcId = self.Id
  460. ret.Status = api.SECGROUP_STATUS_READY
  461. err := SecurityGroupManager.TableSpec().Insert(ctx, ret)
  462. if err != nil {
  463. return errors.Wrapf(err, "Insert")
  464. }
  465. db.Update(ret, func() error {
  466. ret.CloudregionId = "-"
  467. return nil
  468. })
  469. syncVirtualResourceMetadata(ctx, userCred, ret, ext, false)
  470. if provider := self.GetCloudprovider(); provider != nil {
  471. SyncCloudProject(ctx, userCred, ret, syncOwnerId, ext, provider)
  472. }
  473. rules, err := ext.GetRules()
  474. if err != nil {
  475. return errors.Wrapf(err, "GetRules")
  476. }
  477. result := ret.SyncRules(ctx, userCred, rules)
  478. if result.IsError() {
  479. logclient.AddSimpleActionLog(ret, logclient.ACT_CLOUD_SYNC, result, userCred, false)
  480. }
  481. return nil
  482. }