modelarts_pools.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  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. "time"
  19. "yunion.io/x/cloudmux/pkg/cloudprovider"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/pkg/errors"
  22. "yunion.io/x/pkg/util/compare"
  23. "yunion.io/x/pkg/util/netutils"
  24. "yunion.io/x/pkg/utils"
  25. "yunion.io/x/sqlchemy"
  26. billing_api "yunion.io/x/onecloud/pkg/apis/billing"
  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/taskman"
  31. "yunion.io/x/onecloud/pkg/cloudcommon/validators"
  32. "yunion.io/x/onecloud/pkg/compute/options"
  33. "yunion.io/x/onecloud/pkg/httperrors"
  34. "yunion.io/x/onecloud/pkg/mcclient"
  35. "yunion.io/x/onecloud/pkg/util/stringutils2"
  36. )
  37. type SModelartsPoolManager struct {
  38. // 由于资源是用户资源,因此定义为Virtual资源
  39. db.SVirtualResourceBaseManager
  40. db.SExternalizedResourceBaseManager
  41. SDeletePreventableResourceBaseManager
  42. SCloudregionResourceBaseManager
  43. SManagedResourceBaseManager
  44. }
  45. var ModelartsPoolManager *SModelartsPoolManager
  46. func init() {
  47. ModelartsPoolManager = &SModelartsPoolManager{
  48. SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
  49. SModelartsPool{},
  50. "modelarts_pools_tbl",
  51. "modelarts_pool",
  52. "modelarts_pools",
  53. ),
  54. }
  55. ModelartsPoolManager.SetVirtualObject(ModelartsPoolManager)
  56. }
  57. type SModelartsPool struct {
  58. db.SVirtualResourceBase
  59. db.SExternalizedResourceBase
  60. SManagedResourceBase
  61. SBillingResourceBase
  62. SCloudregionResourceBase
  63. SDeletePreventableResourceBase
  64. InstanceType string `width:"72" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"`
  65. NodeCount int `list:"user" create:"required"`
  66. WorkType string `width:"72" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"`
  67. // CPU 架构 x86|xarm
  68. CpuArch string `width:"16" charset:"ascii" nullable:"true" list:"user" create:"admin_optional" update:"admin"`
  69. Cidr string `width:"32" charset:"ascii" nullable:"true" list:"user" create:"admin_optional"`
  70. }
  71. func (manager *SModelartsPoolManager) GetContextManagers() [][]db.IModelManager {
  72. return [][]db.IModelManager{{CloudregionManager}}
  73. }
  74. // Pool实例列表
  75. func (man *SModelartsPoolManager) ListItemFilter(
  76. ctx context.Context,
  77. q *sqlchemy.SQuery,
  78. userCred mcclient.TokenCredential,
  79. query api.ModelartsPoolListInput,
  80. ) (*sqlchemy.SQuery, error) {
  81. var err error
  82. q, err = man.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query.VirtualResourceListInput)
  83. if err != nil {
  84. return nil, errors.Wrap(err, "SVirtualResourceBaseManager.ListItemFilter")
  85. }
  86. q, err = man.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
  87. if err != nil {
  88. return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
  89. }
  90. q, err = man.SDeletePreventableResourceBaseManager.ListItemFilter(ctx, q, userCred, query.DeletePreventableResourceBaseListInput)
  91. if err != nil {
  92. return nil, errors.Wrap(err, "SDeletePreventableResourceBaseManager.ListItemFilter")
  93. }
  94. q, err = man.SManagedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ManagedResourceListInput)
  95. if err != nil {
  96. return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemFilter")
  97. }
  98. q, err = man.SCloudregionResourceBaseManager.ListItemFilter(ctx, q, userCred, query.RegionalFilterListInput)
  99. if err != nil {
  100. return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.ListItemFilter")
  101. }
  102. return q, nil
  103. }
  104. func (man *SModelartsPoolManager) OrderByExtraFields(
  105. ctx context.Context,
  106. q *sqlchemy.SQuery,
  107. userCred mcclient.TokenCredential,
  108. query api.ModelartsPoolListInput,
  109. ) (*sqlchemy.SQuery, error) {
  110. q, err := man.SVirtualResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.VirtualResourceListInput)
  111. if err != nil {
  112. return nil, errors.Wrap(err, "SVirtualResourceBaseManager.OrderByExtraFields")
  113. }
  114. q, err = man.SCloudregionResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.RegionalFilterListInput)
  115. if err != nil {
  116. return nil, errors.Wrap(err, "SCloudregionResourceBaseManager.OrderByExtraFields")
  117. }
  118. q, err = man.SManagedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ManagedResourceListInput)
  119. if err != nil {
  120. return nil, errors.Wrap(err, "SManagedResourceBaseManager.OrderByExtraFields")
  121. }
  122. return q, nil
  123. }
  124. func (man *SModelartsPoolManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
  125. q, err := man.SVirtualResourceBaseManager.QueryDistinctExtraField(q, field)
  126. if err == nil {
  127. return q, nil
  128. }
  129. q, err = man.SCloudregionResourceBaseManager.QueryDistinctExtraField(q, field)
  130. if err == nil {
  131. return q, nil
  132. }
  133. q, err = man.SManagedResourceBaseManager.QueryDistinctExtraField(q, field)
  134. if err == nil {
  135. return q, nil
  136. }
  137. return q, httperrors.ErrNotFound
  138. }
  139. func (manager *SModelartsPoolManager) QueryDistinctExtraFields(q *sqlchemy.SQuery, resource string, fields []string) (*sqlchemy.SQuery, error) {
  140. var err error
  141. q, err = manager.SManagedResourceBaseManager.QueryDistinctExtraFields(q, resource, fields)
  142. if err == nil {
  143. return q, nil
  144. }
  145. return q, httperrors.ErrNotFound
  146. }
  147. func (man *SModelartsPoolManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.ModelartsPoolCreateInput) (api.ModelartsPoolCreateInput, error) {
  148. var err error
  149. if input.NodeCount <= 0 {
  150. input.NodeCount = 1
  151. }
  152. if input.NodeCount > 200 {
  153. return input, errors.Wrap(errors.ErrNotSupported, "node count must between 1 and 200")
  154. }
  155. _, err = netutils.NewIPV4Prefix(input.Cidr)
  156. if err != nil {
  157. return input, httperrors.NewInputParameterError("invalid cidr: %s", input.Cidr)
  158. }
  159. _, err = validators.ValidateModel(ctx, userCred, CloudproviderManager, &input.CloudproviderId)
  160. if err != nil {
  161. return input, err
  162. }
  163. input.ManagerId = input.CloudproviderId
  164. _, err = validators.ValidateModel(ctx, userCred, CloudregionManager, &input.CloudregionId)
  165. if err != nil {
  166. return input, err
  167. }
  168. input.VirtualResourceCreateInput, err = man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput)
  169. if err != nil {
  170. return input, err
  171. }
  172. return input, nil
  173. }
  174. func (manager *SModelartsPoolManager) FetchCustomizeColumns(
  175. ctx context.Context,
  176. userCred mcclient.TokenCredential,
  177. query jsonutils.JSONObject,
  178. objs []interface{},
  179. fields stringutils2.SSortedStrings,
  180. isList bool,
  181. ) []api.ModelartsPoolDetails {
  182. rows := make([]api.ModelartsPoolDetails, len(objs))
  183. virtRows := manager.SVirtualResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  184. manRows := manager.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  185. regRows := manager.SCloudregionResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  186. for i := range rows {
  187. rows[i] = api.ModelartsPoolDetails{
  188. VirtualResourceDetails: virtRows[i],
  189. ManagedResourceInfo: manRows[i],
  190. CloudregionResourceInfo: regRows[i],
  191. }
  192. }
  193. return rows
  194. }
  195. func (manager *SModelartsPoolManager) ListItemExportKeys(ctx context.Context,
  196. q *sqlchemy.SQuery,
  197. userCred mcclient.TokenCredential,
  198. keys stringutils2.SSortedStrings,
  199. ) (*sqlchemy.SQuery, error) {
  200. var err error
  201. q, err = manager.SVirtualResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  202. if err != nil {
  203. return nil, errors.Wrap(err, "SVirtualResourceBaseManager.ListItemExportKeys")
  204. }
  205. if keys.ContainsAny(manager.SManagedResourceBaseManager.GetExportKeys()...) {
  206. q, err = manager.SManagedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  207. if err != nil {
  208. return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemExportKeys")
  209. }
  210. }
  211. return q, nil
  212. }
  213. func (self *SCloudregion) GetPools(managerId string) ([]SModelartsPool, error) {
  214. q := ModelartsPoolManager.Query().Equals("cloudregion_id", self.Id)
  215. if len(managerId) > 0 {
  216. q = q.Equals("manager_id", managerId)
  217. }
  218. ret := []SModelartsPool{}
  219. err := db.FetchModelObjects(ModelartsPoolManager, q, &ret)
  220. if err != nil {
  221. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  222. }
  223. return ret, nil
  224. }
  225. func (self *SCloudregion) SyncModelartsPools(
  226. ctx context.Context,
  227. userCred mcclient.TokenCredential,
  228. provider *SCloudprovider,
  229. exts []cloudprovider.ICloudModelartsPool,
  230. xor bool,
  231. ) compare.SyncResult {
  232. // 加锁防止重入
  233. lockman.LockRawObject(ctx, ModelartsPoolManager.KeywordPlural(), fmt.Sprintf("%s-%s", provider.Id, self.Id))
  234. defer lockman.ReleaseRawObject(ctx, ModelartsPoolManager.KeywordPlural(), fmt.Sprintf("%s-%s", provider.Id, self.Id))
  235. result := compare.SyncResult{}
  236. dbPools, err := self.GetPools(provider.Id)
  237. if err != nil {
  238. result.Error(err)
  239. return result
  240. }
  241. removed := make([]SModelartsPool, 0)
  242. commondb := make([]SModelartsPool, 0)
  243. commonext := make([]cloudprovider.ICloudModelartsPool, 0)
  244. added := make([]cloudprovider.ICloudModelartsPool, 0)
  245. // 本地和云上资源列表进行比对
  246. err = compare.CompareSets(dbPools, exts, &removed, &commondb, &commonext, &added)
  247. if err != nil {
  248. result.Error(err)
  249. return result
  250. }
  251. // 删除云上没有的资源
  252. for i := 0; i < len(removed); i++ {
  253. err := removed[i].syncRemoveCloudModelartsPool(ctx, userCred)
  254. if err != nil {
  255. result.DeleteError(err)
  256. continue
  257. }
  258. result.Delete()
  259. }
  260. if !xor {
  261. // 和云上资源属性进行同步
  262. for i := 0; i < len(commondb); i++ {
  263. err := commondb[i].SyncWithCloudModelartsPool(ctx, userCred, commonext[i])
  264. if err != nil {
  265. result.UpdateError(err)
  266. continue
  267. }
  268. result.Update()
  269. }
  270. }
  271. // 创建本地没有的云上资源
  272. for i := 0; i < len(added); i++ {
  273. _, err := self.newFromCloudModelartsPool(ctx, userCred, provider, added[i])
  274. if err != nil {
  275. result.AddError(err)
  276. continue
  277. }
  278. result.Add()
  279. }
  280. return result
  281. }
  282. // 判断资源是否可以删除
  283. func (self *SModelartsPool) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
  284. if self.DisableDelete.IsTrue() {
  285. return httperrors.NewInvalidStatusError("ModelartsPool is locked, cannot delete")
  286. }
  287. if utils.IsInStringArray(self.Status, []string{api.MODELARTS_POOL_STATUS_CREATING, api.MODELARTS_POOL_STATUS_DELETING}) {
  288. return httperrors.NewInvalidStatusError("ModelartsPool status cannot support delete")
  289. }
  290. return self.SStatusStandaloneResourceBase.ValidateDeleteCondition(ctx, nil)
  291. }
  292. func (self *SModelartsPool) syncRemoveCloudModelartsPool(ctx context.Context, userCred mcclient.TokenCredential) error {
  293. return self.RealDelete(ctx, userCred)
  294. }
  295. func (self *SModelartsPool) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
  296. self.SVirtualResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
  297. self.StartCreateTask(ctx, userCred, "")
  298. }
  299. func (self *SModelartsPool) StartCreateTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  300. var err = func() error {
  301. params := jsonutils.NewDict()
  302. task, err := taskman.TaskManager.NewTask(ctx, "ModelartsPoolCreateTask", self, userCred, params, parentTaskId, "", nil)
  303. if err != nil {
  304. return errors.Wrapf(err, "NewTask")
  305. }
  306. return task.ScheduleRun(nil)
  307. }()
  308. if err != nil {
  309. self.SetStatus(ctx, userCred, api.MODELARTS_POOL_STATUS_ERROR, err.Error())
  310. return err
  311. }
  312. self.SetStatus(ctx, userCred, api.MODELARTS_POOL_STATUS_CREATING, "")
  313. return nil
  314. }
  315. func (modelarts *SModelartsPool) PerformSyncstatus(
  316. ctx context.Context,
  317. userCred mcclient.TokenCredential,
  318. query jsonutils.JSONObject,
  319. input api.ModelartsPoolSyncstatusInput,
  320. ) (jsonutils.JSONObject, error) {
  321. var openTask = true
  322. count, err := taskman.TaskManager.QueryTasksOfObject(modelarts, time.Now().Add(-3*time.Minute), &openTask).CountWithError()
  323. if err != nil {
  324. return nil, err
  325. }
  326. if count > 0 {
  327. return nil, httperrors.NewBadRequestError("ModelartsPool has %d task active, can't sync status", count)
  328. }
  329. return nil, StartResourceSyncStatusTask(ctx, userCred, modelarts, "ModelartsPoolSyncstatusTask", "")
  330. }
  331. func (self *SModelartsPool) StartSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  332. return StartResourceSyncStatusTask(ctx, userCred, self, "ModelartsPoolSyncstatusTask", parentTaskId)
  333. }
  334. func (self *SModelartsPool) GetCloudproviderId() string {
  335. return self.ManagerId
  336. }
  337. func (self *SModelartsPool) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
  338. return nil
  339. }
  340. func (self *SModelartsPool) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
  341. return self.SVirtualResourceBase.Delete(ctx, userCred)
  342. }
  343. // 进入删除任务
  344. func (self *SModelartsPool) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
  345. return self.StartDeleteTask(ctx, userCred, "")
  346. }
  347. func (self *SModelartsPool) StartDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  348. task, err := taskman.TaskManager.NewTask(ctx, "ModelartsPoolDeleteTask", self, userCred, nil, parentTaskId, "", nil)
  349. if err != nil {
  350. return err
  351. }
  352. self.SetStatus(ctx, userCred, api.MODELARTS_POOL_STATUS_DELETING, "")
  353. task.ScheduleRun(nil)
  354. return nil
  355. }
  356. func (self *SModelartsPool) PerformChangeConfig(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ModelartsPoolChangeConfigInput) (jsonutils.JSONObject, error) {
  357. if input.NodeCount == self.NodeCount {
  358. return nil, nil
  359. }
  360. return nil, self.StartChangeConfigTask(ctx, userCred, input)
  361. }
  362. func (self *SModelartsPool) StartChangeConfigTask(ctx context.Context, userCred mcclient.TokenCredential, input api.ModelartsPoolChangeConfigInput) error {
  363. params := jsonutils.Marshal(input).(*jsonutils.JSONDict)
  364. task, err := taskman.TaskManager.NewTask(ctx, "ModelartsPoolChangeConfigTask", self, userCred, params, "", "", nil)
  365. if err != nil {
  366. return err
  367. }
  368. self.SetStatus(ctx, userCred, api.MODELARTS_POOL_STATUS_CHANGE_CONFIG, "")
  369. return task.ScheduleRun(nil)
  370. }
  371. func (self *SModelartsPool) GetIRegion() (cloudprovider.ICloudRegion, error) {
  372. provider, err := self.GetDriver(context.Background())
  373. if err != nil {
  374. return nil, errors.Wrap(err, "self.GetDriver")
  375. }
  376. region, err := self.GetRegion()
  377. if err != nil {
  378. return nil, errors.Wrapf(err, "GetRegion")
  379. }
  380. iRegion, err := provider.GetIRegionById(region.ExternalId)
  381. if err != nil {
  382. return nil, errors.Wrapf(err, "provider.GetIRegionById")
  383. }
  384. return iRegion, nil
  385. }
  386. // 获取云上对应的资源
  387. func (self *SModelartsPool) GetIModelartsPool() (cloudprovider.ICloudModelartsPool, error) {
  388. if len(self.ExternalId) == 0 {
  389. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty externalId")
  390. }
  391. iRegion, err := self.GetIRegion()
  392. if err != nil {
  393. return nil, errors.Wrap(err, "self.GetDriver")
  394. }
  395. return iRegion.GetIModelartsPoolById(self.ExternalId)
  396. }
  397. // 同步资源属性
  398. func (self *SModelartsPool) SyncWithCloudModelartsPool(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudModelartsPool) error {
  399. instanceName := ext.GetInstanceType()
  400. sku := SModelartsPoolSku{}
  401. err := ModelartsPoolSkuManager.Query().Equals("name", instanceName).First(&sku)
  402. if err != nil {
  403. return errors.Wrapf(err, "get modelartsPoolSku")
  404. }
  405. diff, err := db.UpdateWithLock(ctx, self, func() error {
  406. if options.Options.EnableSyncName {
  407. newName, _ := db.GenerateAlterName(self, ext.GetName())
  408. if len(newName) > 0 {
  409. self.Name = newName
  410. }
  411. }
  412. self.Status = ext.GetStatus()
  413. self.BillingType = billing_api.TBillingType(ext.GetBillingType())
  414. self.InstanceType = instanceName
  415. self.WorkType = ext.GetWorkType()
  416. self.CpuArch = sku.CpuArch
  417. self.NodeCount = ext.GetNodeCount()
  418. return nil
  419. })
  420. if err != nil {
  421. return errors.Wrapf(err, "db.Update")
  422. }
  423. if account := self.GetCloudaccount(); account != nil {
  424. syncVirtualResourceMetadata(ctx, userCred, self, ext, account.ReadOnly)
  425. }
  426. if provider := self.GetCloudprovider(); provider != nil {
  427. SyncCloudProject(ctx, userCred, self, provider.GetOwnerId(), ext, provider)
  428. }
  429. db.OpsLog.LogSyncUpdate(self, diff, userCred)
  430. return nil
  431. }
  432. func (self *SCloudregion) newFromCloudModelartsPool(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, ext cloudprovider.ICloudModelartsPool) (*SModelartsPool, error) {
  433. pool := SModelartsPool{}
  434. pool.SetModelManager(ModelartsPoolManager, &pool)
  435. pool.ExternalId = ext.GetGlobalId()
  436. pool.CloudregionId = self.Id
  437. pool.ManagerId = provider.Id
  438. pool.IsEmulated = ext.IsEmulated()
  439. pool.Status = ext.GetStatus()
  440. pool.WorkType = ext.GetWorkType()
  441. pool.InstanceType = ext.GetInstanceType()
  442. pool.NodeCount = ext.GetNodeCount()
  443. if createdAt := ext.GetCreatedAt(); !createdAt.IsZero() {
  444. pool.CreatedAt = createdAt
  445. }
  446. sku := SModelartsPoolSku{}
  447. err := ModelartsPoolSkuManager.Query().Equals("Name", pool.InstanceType).First(&sku)
  448. if err != nil {
  449. return nil, errors.Wrapf(err, "ModelartsPoolSkuManager get cpuArch")
  450. }
  451. pool.CpuArch = sku.CpuArch
  452. pool.BillingType = billing_api.TBillingType(ext.GetBillingType())
  453. pool.ExpiredAt = time.Time{}
  454. pool.AutoRenew = false
  455. if pool.BillingType == billing_api.BILLING_TYPE_PREPAID {
  456. pool.ExpiredAt = ext.GetExpiredAt()
  457. pool.AutoRenew = ext.IsAutoRenew()
  458. }
  459. err = func() error {
  460. // 这里加锁是为了防止名称重复
  461. lockman.LockRawObject(ctx, ModelartsPoolManager.Keyword(), "name")
  462. defer lockman.ReleaseRawObject(ctx, ModelartsPoolManager.Keyword(), "name")
  463. pool.Name, err = db.GenerateName(ctx, ModelartsPoolManager, provider.GetOwnerId(), ext.GetName())
  464. if err != nil {
  465. return errors.Wrapf(err, "db.GenerateName")
  466. }
  467. return ModelartsPoolManager.TableSpec().Insert(ctx, &pool)
  468. }()
  469. if err != nil {
  470. return nil, errors.Wrapf(err, "newFromCloudModelartsPool.Insert")
  471. }
  472. // 同步标签
  473. syncVirtualResourceMetadata(ctx, userCred, &pool, ext, false)
  474. // 同步项目归属
  475. SyncCloudProject(ctx, userCred, &pool, provider.GetOwnerId(), ext, provider)
  476. db.OpsLog.LogEvent(&pool, db.ACT_CREATE, pool.GetShortDesc(ctx), userCred)
  477. return &pool, nil
  478. }