managedresource.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  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. "database/sql"
  18. "strings"
  19. "yunion.io/x/cloudmux/pkg/cloudprovider"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/log"
  22. "yunion.io/x/pkg/appctx"
  23. "yunion.io/x/pkg/errors"
  24. "yunion.io/x/pkg/util/rbacscope"
  25. "yunion.io/x/pkg/util/reflectutils"
  26. "yunion.io/x/pkg/utils"
  27. "yunion.io/x/sqlchemy"
  28. "yunion.io/x/onecloud/pkg/apis"
  29. api "yunion.io/x/onecloud/pkg/apis/compute"
  30. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  31. "yunion.io/x/onecloud/pkg/httperrors"
  32. "yunion.io/x/onecloud/pkg/mcclient"
  33. "yunion.io/x/onecloud/pkg/util/stringutils2"
  34. )
  35. type SManagedResourceBase struct {
  36. // 云订阅ID
  37. ManagerId string `width:"128" charset:"ascii" nullable:"true" list:"user" create:"optional"`
  38. }
  39. type SManagedResourceBaseManager struct {
  40. managerIdFieldName string
  41. }
  42. func (self *SManagedResourceBase) GetCloudproviderId() string {
  43. return self.ManagerId
  44. }
  45. func ValidateCloudproviderResourceInput(ctx context.Context, userCred mcclient.TokenCredential, query api.CloudproviderResourceInput) (*SCloudprovider, api.CloudproviderResourceInput, error) {
  46. managerObj, err := CloudproviderManager.FetchByIdOrName(ctx, userCred, query.CloudproviderId)
  47. if err != nil {
  48. if err == sql.ErrNoRows {
  49. return nil, query, errors.Wrapf(httperrors.ErrResourceNotFound, "%s %s", CloudproviderManager.Keyword(), query.CloudproviderId)
  50. } else {
  51. return nil, query, errors.Wrap(err, "CloudproviderManager.FetchByIdOrName")
  52. }
  53. }
  54. query.CloudproviderId = managerObj.GetId()
  55. return managerObj.(*SCloudprovider), query, nil
  56. }
  57. func (manager *SManagedResourceBaseManager) getManagerIdFileName() string {
  58. if len(manager.managerIdFieldName) > 0 {
  59. return manager.managerIdFieldName
  60. }
  61. return "manager_id"
  62. }
  63. func (self *SManagedResourceBase) GetCloudprovider() *SCloudprovider {
  64. if len(self.ManagerId) > 0 {
  65. return CloudproviderManager.FetchCloudproviderById(self.ManagerId)
  66. }
  67. return nil
  68. }
  69. func (self *SManagedResourceBase) GetCloudaccount() *SCloudaccount {
  70. cp := self.GetCloudprovider()
  71. if cp == nil {
  72. return nil
  73. }
  74. account, _ := cp.GetCloudaccount()
  75. return account
  76. }
  77. func (self *SManagedResourceBase) GetRegionDriver() (IRegionDriver, error) {
  78. cloudprovider := self.GetCloudprovider()
  79. provider := api.CLOUD_PROVIDER_ONECLOUD
  80. if cloudprovider != nil {
  81. provider = cloudprovider.Provider
  82. }
  83. driver := GetRegionDriver(provider)
  84. if driver == nil {
  85. return nil, errors.Wrapf(httperrors.ErrInvalidStatus, "failed to get %s region drivder", provider)
  86. }
  87. return driver, nil
  88. }
  89. func (self *SManagedResourceBase) GetProviderFactory() (cloudprovider.ICloudProviderFactory, error) {
  90. provider := self.GetCloudprovider()
  91. if provider == nil {
  92. if len(self.ManagerId) > 0 {
  93. return nil, cloudprovider.ErrInvalidProvider
  94. }
  95. return nil, errors.Wrap(httperrors.ErrInvalidStatus, "Resource is self managed")
  96. }
  97. return provider.GetProviderFactory()
  98. }
  99. func (self *SManagedResourceBase) GetDriver(ctx context.Context) (cloudprovider.ICloudProvider, error) {
  100. provider := self.GetCloudprovider()
  101. if provider == nil {
  102. if len(self.ManagerId) > 0 {
  103. return nil, cloudprovider.ErrInvalidProvider
  104. }
  105. return nil, errors.Wrap(httperrors.ErrInvalidStatus, "Resource is self managed")
  106. }
  107. return provider.GetProvider(ctx)
  108. }
  109. func (self *SManagedResourceBase) GetProviderName() string {
  110. account := self.GetCloudaccount()
  111. if account != nil {
  112. return account.Provider
  113. }
  114. return api.CLOUD_PROVIDER_ONECLOUD
  115. }
  116. func (self *SManagedResourceBase) GetBrand() string {
  117. account := self.GetCloudaccount()
  118. if account != nil {
  119. return account.Brand
  120. }
  121. return api.CLOUD_PROVIDER_ONECLOUD
  122. }
  123. func (self *SManagedResourceBase) IsManaged() bool {
  124. return len(self.ManagerId) > 0
  125. }
  126. func (self *SManagedResourceBase) CanShareToDomain(domainId string) bool {
  127. provider := self.GetCloudprovider()
  128. if provider == nil {
  129. return true
  130. }
  131. account, _ := provider.GetCloudaccount()
  132. if account == nil {
  133. // no cloud account, can share to any domain
  134. return true
  135. }
  136. switch account.ShareMode {
  137. case api.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN:
  138. if domainId == account.DomainId {
  139. return true
  140. } else {
  141. return false
  142. }
  143. case api.CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN:
  144. if domainId == provider.DomainId {
  145. return true
  146. } else {
  147. return false
  148. }
  149. case api.CLOUD_ACCOUNT_SHARE_MODE_SYSTEM:
  150. if account.PublicScope == string(rbacscope.ScopeSystem) {
  151. return true
  152. } else {
  153. // public_scope = domain
  154. if domainId == account.DomainId {
  155. return true
  156. }
  157. if utils.IsInStringArray(domainId, account.GetSharedDomains()) {
  158. return true
  159. }
  160. return false
  161. }
  162. default:
  163. return true
  164. }
  165. }
  166. func (manager *SManagedResourceBaseManager) FetchCustomizeColumns(
  167. ctx context.Context,
  168. userCred mcclient.TokenCredential,
  169. query jsonutils.JSONObject,
  170. objs []interface{},
  171. fields stringutils2.SSortedStrings,
  172. isList bool,
  173. ) []api.ManagedResourceInfo {
  174. rows := make([]api.ManagedResourceInfo, len(objs))
  175. managerIds := make([]string, len(objs))
  176. managerCnt := 0
  177. for i := range objs {
  178. rows[i] = api.ManagedResourceInfo{}
  179. rows[i].CloudEnv = api.CLOUD_ENV_ON_PREMISE
  180. rows[i].Provider = api.CLOUD_PROVIDER_ONECLOUD
  181. rows[i].Brand = api.CLOUD_PROVIDER_ONECLOUD
  182. var base *SManagedResourceBase
  183. err := reflectutils.FindAnonymouStructPointer(objs[i], &base)
  184. if err != nil {
  185. log.Errorf("Cannot find SCloudregionResourceBase in object %s", objs[i])
  186. continue
  187. }
  188. if base != nil && len(base.ManagerId) > 0 {
  189. managerIds[i] = base.ManagerId
  190. managerCnt += 1
  191. }
  192. }
  193. if managerCnt == 0 {
  194. return rows
  195. }
  196. managers := make(map[string]SCloudprovider)
  197. err := db.FetchStandaloneObjectsByIds(CloudproviderManager, managerIds, &managers)
  198. if err != nil {
  199. log.Errorf("FetchStandaloneObjectsByIds fail %s", err)
  200. return rows
  201. }
  202. accountIds := make([]string, len(objs))
  203. projectIds := make([]string, len(objs))
  204. for i := range rows {
  205. if _, ok := managers[managerIds[i]]; ok {
  206. manager := managers[managerIds[i]]
  207. rows[i].Manager = manager.Name
  208. rows[i].ManagerDomainId = manager.DomainId
  209. rows[i].ManagerProjectId = manager.ProjectId
  210. rows[i].AccountId = manager.CloudaccountId
  211. projectIds[i] = manager.ProjectId
  212. accountIds[i] = manager.CloudaccountId
  213. }
  214. }
  215. accounts := make(map[string]SCloudaccount)
  216. err = db.FetchStandaloneObjectsByIds(CloudaccountManager, accountIds, &accounts)
  217. if err != nil {
  218. log.Errorf("FetchStandaloneObjectsByIds for accounts fail %s", err)
  219. return nil
  220. }
  221. projects := db.DefaultProjectsFetcher(ctx, projectIds, false)
  222. for i := range rows {
  223. if account, ok := accounts[rows[i].AccountId]; ok {
  224. rows[i].Account = account.Name
  225. rows[i].AccountStatus = account.Status
  226. rows[i].AccountHealthStatus = account.HealthStatus
  227. rows[i].AccountReadOnly = account.ReadOnly
  228. rows[i].Brand = account.Brand
  229. rows[i].Provider = account.Provider
  230. rows[i].CloudEnv = account.GetCloudEnv()
  231. rows[i].Environment = account.GetEnvironment()
  232. }
  233. if project, ok := projects[rows[i].ManagerProjectId]; ok {
  234. rows[i].ManagerProject = project.Name
  235. rows[i].ManagerDomain = project.Domain
  236. rows[i].ManagerDomainId = project.DomainId
  237. }
  238. }
  239. return rows
  240. }
  241. func (manager *SManagedResourceBaseManager) ListItemFilter(
  242. ctx context.Context,
  243. q *sqlchemy.SQuery,
  244. userCred mcclient.TokenCredential,
  245. query api.ManagedResourceListInput,
  246. ) (*sqlchemy.SQuery, error) {
  247. return _managedResourceFilterByAccount(ctx, manager.getManagerIdFileName(), q, query, "", nil)
  248. }
  249. func (manager *SManagedResourceBaseManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
  250. switch field {
  251. case "manager":
  252. managerQuery := CloudproviderManager.Query("name", "id").SubQuery()
  253. q.AppendField(managerQuery.Field("name", field)).Distinct()
  254. q = q.Join(managerQuery, sqlchemy.Equals(q.Field(manager.getManagerIdFileName()), managerQuery.Field("id")))
  255. return q, nil
  256. case "account":
  257. accountQuery := CloudaccountManager.Query("name", "id").SubQuery()
  258. providers := CloudproviderManager.Query("id", "cloudaccount_id").SubQuery()
  259. q.AppendField(accountQuery.Field("name", field)).Distinct()
  260. q = q.Join(providers, sqlchemy.Equals(q.Field(manager.getManagerIdFileName()), providers.Field("id")))
  261. q = q.Join(accountQuery, sqlchemy.Equals(providers.Field("cloudaccount_id"), accountQuery.Field("id")))
  262. return q, nil
  263. case "provider", "brand":
  264. accountQuery := CloudaccountManager.Query(field, "id").Distinct().SubQuery()
  265. providers := CloudproviderManager.Query("id", "cloudaccount_id").SubQuery()
  266. q.AppendField(accountQuery.Field(field)).Distinct()
  267. q = q.Join(providers, sqlchemy.Equals(q.Field(manager.getManagerIdFileName()), providers.Field("id")))
  268. q = q.Join(accountQuery, sqlchemy.Equals(providers.Field("cloudaccount_id"), accountQuery.Field("id")))
  269. return q, nil
  270. }
  271. return q, httperrors.ErrNotFound
  272. }
  273. func (manager *SManagedResourceBaseManager) QueryDistinctExtraFields(q *sqlchemy.SQuery, resource string, fields []string) (*sqlchemy.SQuery, error) {
  274. switch resource {
  275. case CloudproviderManager.Keyword():
  276. cpQuery := CloudproviderManager.Query().SubQuery()
  277. for _, field := range fields {
  278. q = q.AppendField(cpQuery.Field(field))
  279. }
  280. q = q.Join(cpQuery, sqlchemy.Equals(q.Field("manager_id"), cpQuery.Field("id")))
  281. return q, nil
  282. }
  283. return q, httperrors.ErrNotFound
  284. }
  285. func (manager *SManagedResourceBaseManager) OrderByExtraFields(
  286. ctx context.Context,
  287. q *sqlchemy.SQuery,
  288. userCred mcclient.TokenCredential,
  289. query api.ManagedResourceListInput,
  290. ) (*sqlchemy.SQuery, error) {
  291. if !db.NeedOrderQuery(manager.GetOrderByFields(query)) {
  292. return q, nil
  293. }
  294. orderQ := CloudproviderManager.Query("id")
  295. subOrderQ := orderQ.SubQuery()
  296. orderQ, orders, fields := manager.GetOrderBySubQuery(orderQ, subOrderQ, orderQ.Field("id"), userCred, query, nil, nil)
  297. q = q.LeftJoin(subOrderQ, sqlchemy.Equals(q.Field(manager.getManagerIdFileName()), subOrderQ.Field("id")))
  298. q = db.OrderByFields(q, orders, fields)
  299. return q, nil
  300. }
  301. func (manager *SManagedResourceBaseManager) GetOrderBySubQuery(
  302. q *sqlchemy.SQuery,
  303. subq *sqlchemy.SSubQuery,
  304. subqField sqlchemy.IQueryField,
  305. userCred mcclient.TokenCredential,
  306. query api.ManagedResourceListInput,
  307. orders []string,
  308. fields []sqlchemy.IQueryField,
  309. ) (*sqlchemy.SQuery, []string, []sqlchemy.IQueryField) {
  310. if !db.NeedOrderQuery(manager.GetOrderByFields(query)) {
  311. return q, orders, fields
  312. }
  313. providers := CloudproviderManager.Query().SubQuery()
  314. accounts := CloudaccountManager.Query().SubQuery()
  315. q = q.LeftJoin(providers, sqlchemy.Equals(subqField, providers.Field("id")))
  316. q = q.LeftJoin(accounts, sqlchemy.Equals(providers.Field("cloudaccount_id"), accounts.Field("id")))
  317. q = q.AppendField(providers.Field("name").Label("manager"))
  318. q = q.AppendField(accounts.Field("name").Label("account"))
  319. q = q.AppendField(accounts.Field("provider"))
  320. q = q.AppendField(accounts.Field("brand"))
  321. orders = append(orders, query.OrderByManager, query.OrderByAccount, query.OrderByProvider, query.OrderByBrand)
  322. fields = append(fields, subq.Field("manager"), subq.Field("account"), subq.Field("provider"), subq.Field("brand"))
  323. return q, orders, fields
  324. }
  325. func (manager *SManagedResourceBaseManager) GetOrderByFields(query api.ManagedResourceListInput) []string {
  326. return []string{query.OrderByManager, query.OrderByAccount, query.OrderByProvider, query.OrderByBrand}
  327. }
  328. func (model *SManagedResourceBase) GetChangeOwnerCandidateDomainIds() []string {
  329. provider := model.GetCloudprovider()
  330. if provider == nil {
  331. return nil
  332. }
  333. account := model.GetCloudaccount()
  334. if account == nil {
  335. return nil
  336. }
  337. var candidateIds []string
  338. switch account.ShareMode {
  339. case api.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN:
  340. candidateIds = append(candidateIds, account.DomainId)
  341. case api.CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN:
  342. candidateIds = append(candidateIds, provider.DomainId)
  343. case api.CLOUD_ACCOUNT_SHARE_MODE_SYSTEM:
  344. if account.PublicScope != string(rbacscope.ScopeSystem) {
  345. candidateIds = account.GetSharedDomains()
  346. candidateIds = append(candidateIds, account.DomainId)
  347. }
  348. }
  349. return candidateIds
  350. }
  351. func (manager *SManagedResourceBaseManager) ListItemExportKeys(ctx context.Context,
  352. q *sqlchemy.SQuery,
  353. userCred mcclient.TokenCredential,
  354. keys stringutils2.SSortedStrings,
  355. ) (*sqlchemy.SQuery, error) {
  356. if keys.ContainsAny(manager.GetExportKeys()...) {
  357. cloudprovidersQ := CloudproviderManager.Query("id", "name", "cloudaccount_id").SubQuery()
  358. q = q.LeftJoin(cloudprovidersQ, sqlchemy.Equals(q.Field(manager.getManagerIdFileName()), cloudprovidersQ.Field("id")))
  359. if keys.Contains("manager") {
  360. q = q.AppendField(cloudprovidersQ.Field("name", "manager"))
  361. }
  362. if keys.Contains("account") || keys.Contains("provider") || keys.Contains("brand") {
  363. cloudaccountsQ := CloudaccountManager.Query("id", "name", "provider", "brand").SubQuery()
  364. q = q.LeftJoin(cloudaccountsQ, sqlchemy.Equals(cloudprovidersQ.Field("cloudaccount_id"), cloudaccountsQ.Field("id")))
  365. if keys.Contains("account") {
  366. q = q.AppendField(cloudaccountsQ.Field("name", "account"))
  367. }
  368. if keys.Contains("provider") {
  369. q = q.AppendField(cloudaccountsQ.Field("provider"))
  370. }
  371. if keys.Contains("brand") {
  372. q = q.AppendField(cloudaccountsQ.Field("provider"))
  373. }
  374. }
  375. }
  376. return q, nil
  377. }
  378. func (manager *SManagedResourceBaseManager) GetExportKeys() []string {
  379. return []string{"manager", "account", "provider", "brand"}
  380. }
  381. func _managedResourceFilterByDomain(managerIdFieldName string, q *sqlchemy.SQuery, query apis.DomainizedResourceListInput, filterField string, subqFunc func() *sqlchemy.SQuery) (*sqlchemy.SQuery, error) {
  382. domainStr := query.ProjectDomainId
  383. if len(domainStr) > 0 {
  384. domain, err := db.TenantCacheManager.FetchDomainByIdOrName(context.Background(), domainStr)
  385. if err != nil {
  386. if err == sql.ErrNoRows {
  387. return nil, httperrors.NewResourceNotFoundError2("domains", domainStr)
  388. }
  389. return nil, httperrors.NewGeneralError(err)
  390. }
  391. accounts := CloudaccountManager.Query("id")
  392. accounts = CloudaccountManager.filterByDomainId(accounts, domain.GetId())
  393. subq := CloudproviderManager.Query("id").In("cloudaccount_id", accounts.SubQuery())
  394. /*subq := providers.Query(providers.Field("id"))
  395. subq = subq.Join(accounts, sqlchemy.Equals(providers.Field("cloudaccount_id"), accounts.Field("id")))
  396. subq = subq.Filter(sqlchemy.OR(
  397. sqlchemy.AND(
  398. sqlchemy.Equals(providers.Field("domain_id"), domain.GetId()),
  399. sqlchemy.Equals(accounts.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN),
  400. ),
  401. sqlchemy.Equals(accounts.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_SYSTEM),
  402. sqlchemy.AND(
  403. sqlchemy.Equals(accounts.Field("domain_id"), domain.GetId()),
  404. sqlchemy.Equals(accounts.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN),
  405. ),
  406. ))*/
  407. if len(filterField) == 0 {
  408. q = q.Filter(sqlchemy.OR(
  409. sqlchemy.IsNullOrEmpty(q.Field(managerIdFieldName)),
  410. sqlchemy.In(q.Field(managerIdFieldName), subq.SubQuery()),
  411. ))
  412. } else {
  413. sq := subqFunc()
  414. sq = sq.Filter(sqlchemy.OR(sqlchemy.In(sq.Field(managerIdFieldName), subq.SubQuery()), sqlchemy.IsNullOrEmpty(sq.Field(managerIdFieldName))))
  415. q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery()))
  416. }
  417. }
  418. return q, nil
  419. }
  420. func splitProviders(providers []string) (bool, []string) {
  421. oneCloud := false
  422. others := make([]string, 0)
  423. for _, pro := range providers {
  424. if pro == api.CLOUD_PROVIDER_ONECLOUD {
  425. oneCloud = true
  426. } else {
  427. others = append(others, pro)
  428. }
  429. }
  430. return oneCloud, others
  431. }
  432. func _filterByProviderStrs(managerIdFieldName string, q *sqlchemy.SQuery, filterField string, subqFunc func() *sqlchemy.SQuery, fieldName string, providerStrs []string) *sqlchemy.SQuery {
  433. oneCloud, providers := splitProviders(providerStrs)
  434. sq := q
  435. if len(filterField) > 0 {
  436. sq = subqFunc()
  437. }
  438. filters := make([]sqlchemy.ICondition, 0)
  439. if len(providers) > 0 {
  440. account := CloudaccountManager.Query().SubQuery()
  441. providers := CloudproviderManager.Query().SubQuery()
  442. subq := providers.Query(providers.Field("id"))
  443. subq = subq.Join(account, sqlchemy.Equals(
  444. account.Field("id"), providers.Field("cloudaccount_id"),
  445. ))
  446. subq = subq.Filter(sqlchemy.In(account.Field(fieldName), providerStrs))
  447. filters = append(filters, sqlchemy.In(sq.Field(managerIdFieldName), subq.SubQuery()))
  448. }
  449. if oneCloud {
  450. filters = append(filters, sqlchemy.IsNullOrEmpty(sq.Field(managerIdFieldName)))
  451. }
  452. if len(filters) == 1 {
  453. sq = sq.Filter(filters[0])
  454. } else if len(filters) > 1 {
  455. sq = sq.Filter(sqlchemy.OR(filters...))
  456. }
  457. if len(filterField) == 0 {
  458. q = sq
  459. } else {
  460. q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery()))
  461. }
  462. return q
  463. }
  464. func managedResourceFilterByAccount(ctx context.Context, q *sqlchemy.SQuery, input api.ManagedResourceListInput, filterField string, subqFunc func() *sqlchemy.SQuery) (*sqlchemy.SQuery, error) {
  465. return _managedResourceFilterByAccount(ctx, "manager_id", q, input, filterField, subqFunc)
  466. }
  467. func _managedResourceFilterByAccount(ctx context.Context, managerIdFieldName string, q *sqlchemy.SQuery, input api.ManagedResourceListInput, filterField string, subqFunc func() *sqlchemy.SQuery) (*sqlchemy.SQuery, error) {
  468. cloudproviderStrs := input.CloudproviderId
  469. managerIds := []string{}
  470. for _, cloudproviderStr := range cloudproviderStrs {
  471. if len(cloudproviderStr) == 0 {
  472. continue
  473. }
  474. provider, err := CloudproviderManager.FetchByIdOrName(ctx, nil, cloudproviderStr)
  475. if err != nil {
  476. if err == sql.ErrNoRows {
  477. return nil, httperrors.NewResourceNotFoundError2(CloudproviderManager.Keyword(), cloudproviderStr)
  478. }
  479. return nil, httperrors.NewGeneralError(err)
  480. }
  481. if len(filterField) == 0 {
  482. managerIds = append(managerIds, provider.GetId())
  483. } else {
  484. sq := subqFunc()
  485. sq = sq.Filter(sqlchemy.Equals(sq.Field(managerIdFieldName), provider.GetId()))
  486. q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery()))
  487. }
  488. }
  489. if len(managerIds) > 0 {
  490. q = q.In(managerIdFieldName, managerIds)
  491. }
  492. cloudaccountArr := input.CloudaccountId
  493. if len(cloudaccountArr) > 0 {
  494. cpq := CloudaccountManager.Query().SubQuery()
  495. subcpq := cpq.Query(cpq.Field("id")).Filter(sqlchemy.OR(
  496. sqlchemy.In(cpq.Field("id"), stringutils2.RemoveUtf8Strings(cloudaccountArr)),
  497. sqlchemy.In(cpq.Field("name"), cloudaccountArr),
  498. )).SubQuery()
  499. subq := CloudproviderManager.Query("id").In("cloudaccount_id", subcpq).SubQuery()
  500. if len(filterField) == 0 {
  501. q = q.Filter(sqlchemy.In(q.Field(managerIdFieldName), subq))
  502. } else {
  503. sq := subqFunc()
  504. sq = sq.Filter(sqlchemy.In(sq.Field(managerIdFieldName), subq))
  505. q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery()))
  506. }
  507. }
  508. if len(input.Providers) > 0 {
  509. q = _filterByProviderStrs(managerIdFieldName, q, filterField, subqFunc, "provider", input.Providers)
  510. }
  511. if len(input.Brands) > 0 {
  512. q = _filterByProviderStrs(managerIdFieldName, q, filterField, subqFunc, "brand", input.Brands)
  513. }
  514. if input.IsManaged != nil {
  515. if *input.IsManaged {
  516. q = q.IsNotEmpty(managerIdFieldName)
  517. } else {
  518. q = q.IsNullOrEmpty(managerIdFieldName)
  519. }
  520. }
  521. q = _filterByCloudType(managerIdFieldName, q, input, filterField, subqFunc)
  522. q, err := _managedResourceFilterByDomain(managerIdFieldName, q, input.DomainizedResourceListInput, filterField, subqFunc)
  523. if err != nil {
  524. return nil, errors.Wrap(err, "managedResourceFilterByDomain")
  525. }
  526. return q, nil
  527. }
  528. func managedResourceFilterByZone(ctx context.Context, q *sqlchemy.SQuery, query api.ZonalFilterListInput, filterField string, subqFunc func() *sqlchemy.SQuery) (*sqlchemy.SQuery, error) {
  529. zoneList := query.ZoneList()
  530. if len(query.ZoneIds) >= 1 {
  531. zoneQ := ZoneManager.Query("id")
  532. zoneQ = zoneQ.Filter(sqlchemy.OR(
  533. sqlchemy.In(zoneQ.Field("id"), zoneList),
  534. sqlchemy.In(zoneQ.Field("name"), zoneList),
  535. ))
  536. if len(filterField) == 0 {
  537. q = q.Filter(sqlchemy.In(q.Field("zone_id"), zoneQ.SubQuery()))
  538. } else {
  539. sq := subqFunc()
  540. sq = sq.Filter(sqlchemy.In(sq.Field("zone_id"), zoneQ.SubQuery()))
  541. q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery()))
  542. }
  543. } else if len(query.ZoneId) > 0 {
  544. zoneObj, _, err := ValidateZoneResourceInput(ctx, nil, query.ZoneResourceInput)
  545. if err != nil {
  546. return nil, errors.Wrap(err, "ValidateZoneResourceInput")
  547. }
  548. if len(filterField) == 0 {
  549. q = q.Filter(sqlchemy.Equals(q.Field("zone_id"), zoneObj.GetId()))
  550. } else {
  551. sq := subqFunc()
  552. sq = sq.Filter(sqlchemy.Equals(sq.Field("zone_id"), zoneObj.GetId()))
  553. q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery()))
  554. }
  555. }
  556. return q, nil
  557. }
  558. func managedResourceFilterByRegion(ctx context.Context, q *sqlchemy.SQuery, query api.RegionalFilterListInput, filterField string, subqFunc func() *sqlchemy.SQuery) (*sqlchemy.SQuery, error) {
  559. regionIds := []string{}
  560. for _, region := range query.CloudregionId {
  561. if len(region) == 0 {
  562. continue
  563. }
  564. regionObj, err := ValidateCloudregionId(ctx, nil, region)
  565. if err != nil {
  566. return nil, errors.Wrap(err, "ValidateCloudregionResourceInput")
  567. }
  568. regionIds = append(regionIds, regionObj.GetId())
  569. }
  570. if len(filterField) == 0 {
  571. if len(regionIds) > 0 {
  572. q = q.In("cloudregion_id", regionIds)
  573. }
  574. } else {
  575. if len(regionIds) > 0 {
  576. sq := subqFunc()
  577. sq = sq.Filter(sqlchemy.In(sq.Field("cloudregion_id"), regionIds))
  578. q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery()))
  579. }
  580. }
  581. if len(query.City) > 0 {
  582. subq := CloudregionManager.Query("id").Equals("city", query.City).SubQuery()
  583. if len(filterField) == 0 {
  584. q = q.Filter(sqlchemy.In(q.Field("cloudregion_id"), subq))
  585. } else {
  586. sq := subqFunc()
  587. sq = sq.Filter(sqlchemy.In(sq.Field("cloudregion_id"), subq))
  588. q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery()))
  589. }
  590. }
  591. return q, nil
  592. }
  593. func _filterByCloudType(managerIdFieldName string, q *sqlchemy.SQuery, input api.ManagedResourceListInput, filterField string, subqFunc func() *sqlchemy.SQuery) *sqlchemy.SQuery {
  594. cloudEnvStr := input.CloudEnv
  595. switch cloudEnvStr {
  596. case api.CLOUD_ENV_PUBLIC_CLOUD:
  597. if len(filterField) == 0 {
  598. q = q.Filter(sqlchemy.In(q.Field(managerIdFieldName), CloudproviderManager.GetPublicProviderIdsQuery()))
  599. } else {
  600. sq := subqFunc()
  601. sq = sq.Filter(sqlchemy.In(sq.Field(managerIdFieldName), CloudproviderManager.GetPublicProviderIdsQuery()))
  602. q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery()))
  603. }
  604. case api.CLOUD_ENV_PRIVATE_CLOUD:
  605. if len(filterField) == 0 {
  606. q = q.Filter(sqlchemy.In(q.Field(managerIdFieldName), CloudproviderManager.GetPrivateProviderIdsQuery()))
  607. } else {
  608. sq := subqFunc()
  609. sq = sq.Filter(sqlchemy.In(sq.Field(managerIdFieldName), CloudproviderManager.GetPrivateProviderIdsQuery()))
  610. q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery()))
  611. }
  612. case api.CLOUD_ENV_ON_PREMISE:
  613. if len(filterField) == 0 {
  614. q = q.Filter(
  615. sqlchemy.OR(
  616. sqlchemy.In(q.Field(managerIdFieldName), CloudproviderManager.GetOnPremiseProviderIdsQuery()),
  617. sqlchemy.IsNullOrEmpty(q.Field(managerIdFieldName)),
  618. ),
  619. )
  620. } else {
  621. sq := subqFunc()
  622. sq = sq.Filter(
  623. sqlchemy.OR(
  624. sqlchemy.In(sq.Field(managerIdFieldName), CloudproviderManager.GetOnPremiseProviderIdsQuery()),
  625. sqlchemy.IsNullOrEmpty(sq.Field(managerIdFieldName)),
  626. ),
  627. )
  628. q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery()))
  629. }
  630. case api.CLOUD_ENV_PRIVATE_ON_PREMISE:
  631. if len(filterField) == 0 {
  632. q = q.Filter(
  633. sqlchemy.OR(
  634. sqlchemy.In(q.Field(managerIdFieldName), CloudproviderManager.GetPrivateOrOnPremiseProviderIdsQuery()),
  635. sqlchemy.IsNullOrEmpty(q.Field(managerIdFieldName)),
  636. ),
  637. )
  638. } else {
  639. sq := subqFunc()
  640. sq = sq.Filter(
  641. sqlchemy.OR(
  642. sqlchemy.In(sq.Field(managerIdFieldName), CloudproviderManager.GetPrivateOrOnPremiseProviderIdsQuery()),
  643. sqlchemy.IsNullOrEmpty(sq.Field(managerIdFieldName)),
  644. ),
  645. )
  646. q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery()))
  647. }
  648. }
  649. /*if input.IsManaged {
  650. if len(filterField) == 0 {
  651. q = q.Filter(sqlchemy.IsNotEmpty(q.Field(managerIdFieldName)))
  652. } else {
  653. sq := subqFunc()
  654. sq = sq.Filter(sqlchemy.IsNotEmpty(sq.Field(managerIdFieldName)))
  655. q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery()))
  656. }
  657. }*/
  658. return q
  659. }
  660. type SCloudProviderInfo struct {
  661. Provider string `json:",omitempty"`
  662. Brand string `json:",omitempty"`
  663. Account string `json:",omitempty"`
  664. AccountId string `json:",omitempty"`
  665. Manager string `json:",omitempty"`
  666. ManagerId string `json:",omitempty"`
  667. ManagerProject string `json:",omitempty"`
  668. ManagerProjectId string `json:",omitempty"`
  669. ManagerDomain string `json:",omitempty"`
  670. ManagerDomainId string `json:",omitempty"`
  671. Region string `json:",omitempty"`
  672. RegionId string `json:",omitempty"`
  673. CloudregionId string `json:",omitempty"`
  674. RegionExternalId string `json:",omitempty"`
  675. RegionExtId string `json:",omitempty"`
  676. Zone string `json:",omitempty"`
  677. ZoneId string `json:",omitempty"`
  678. ZoneExtId string `json:",omitempty"`
  679. CloudEnv string `json:",omitempty"`
  680. }
  681. var (
  682. providerInfoFields = []string{
  683. "provider",
  684. "brand",
  685. "account",
  686. "account_id",
  687. "manager",
  688. "manager_id",
  689. "manager_project",
  690. "manager_project_id",
  691. "region",
  692. "region_id",
  693. "region_external_id",
  694. "region_ext_id",
  695. "zone",
  696. "zone_id",
  697. "zone_ext_id",
  698. "cloud_env",
  699. }
  700. )
  701. func fetchExternalId(extId string) string {
  702. if len(extId) == 0 {
  703. return ""
  704. }
  705. pos := strings.LastIndexByte(extId, '/')
  706. if pos > 0 {
  707. return extId[pos+1:]
  708. } else {
  709. return extId
  710. }
  711. }
  712. func MakeCloudProviderInfo(region *SCloudregion, zone *SZone, provider *SCloudprovider) SCloudProviderInfo {
  713. info := SCloudProviderInfo{}
  714. if zone != nil {
  715. info.Zone = zone.GetName()
  716. info.ZoneId = zone.GetId()
  717. }
  718. if region != nil {
  719. info.Region = region.GetName()
  720. info.RegionId = region.GetId()
  721. info.CloudregionId = region.GetId()
  722. }
  723. if provider != nil {
  724. info.Manager = provider.GetName()
  725. info.ManagerId = provider.GetId()
  726. info.Provider = provider.Provider
  727. if len(provider.ProjectId) > 0 {
  728. info.ManagerProjectId = provider.ProjectId
  729. tc, err := db.TenantCacheManager.FetchTenantById(appctx.Background, provider.ProjectId)
  730. if err == nil {
  731. info.ManagerProject = tc.GetName()
  732. info.ManagerDomain = tc.Domain
  733. info.ManagerDomainId = tc.DomainId
  734. }
  735. }
  736. account, _ := provider.GetCloudaccount()
  737. if account != nil {
  738. info.Account = account.GetName()
  739. info.AccountId = account.GetId()
  740. info.Brand = account.Brand
  741. info.CloudEnv = account.GetCloudEnv()
  742. }
  743. if region != nil {
  744. info.RegionExternalId = region.ExternalId
  745. info.RegionExtId = fetchExternalId(region.ExternalId)
  746. if zone != nil {
  747. info.ZoneExtId = fetchExternalId(zone.ExternalId)
  748. }
  749. }
  750. } else {
  751. info.CloudEnv = api.CLOUD_ENV_ON_PREMISE
  752. info.Provider = api.CLOUD_PROVIDER_ONECLOUD
  753. info.Brand = api.CLOUD_PROVIDER_ONECLOUD
  754. }
  755. return info
  756. }
  757. func fetchByManagerId(manager db.IModelManager, providerId string, receiver interface{}) error {
  758. q := manager.Query().Equals("manager_id", providerId)
  759. return db.FetchModelObjects(manager, q, receiver)
  760. }
  761. func fetchByVpcManagerId(manager db.IModelManager, providerId string, receiver interface{}) error {
  762. vpc := VpcManager.Query().SubQuery()
  763. q := manager.Query()
  764. q = q.Join(vpc, sqlchemy.Equals(vpc.Field("id"), q.Field("vpc_id"))).Filter(sqlchemy.Equals(vpc.Field("manager_id"), providerId))
  765. return db.FetchModelObjects(manager, q, receiver)
  766. }
  767. func fetchByLbVpcManagerId(manager db.IModelManager, providerId string, receiver interface{}) error {
  768. vpc := VpcManager.Query().SubQuery()
  769. lb := LoadbalancerManager.Query().SubQuery()
  770. q := manager.Query()
  771. q = q.Join(lb, sqlchemy.Equals(lb.Field("id"), q.Field("loadbalancer_id"))).
  772. Join(vpc, sqlchemy.Equals(vpc.Field("id"), lb.Field("vpc_id"))).
  773. Filter(sqlchemy.Equals(vpc.Field("manager_id"), providerId))
  774. return db.FetchModelObjects(manager, q, receiver)
  775. }