infraresource.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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 db
  15. import (
  16. "context"
  17. "yunion.io/x/jsonutils"
  18. "yunion.io/x/pkg/errors"
  19. "yunion.io/x/pkg/util/rbacscope"
  20. "yunion.io/x/sqlchemy"
  21. "yunion.io/x/onecloud/pkg/apis"
  22. "yunion.io/x/onecloud/pkg/cloudcommon/consts"
  23. "yunion.io/x/onecloud/pkg/httperrors"
  24. "yunion.io/x/onecloud/pkg/mcclient"
  25. "yunion.io/x/onecloud/pkg/util/stringutils2"
  26. )
  27. type SInfrasResourceBaseManager struct {
  28. SDomainLevelResourceBaseManager
  29. SSharableBaseResourceManager
  30. }
  31. func NewInfrasResourceBaseManager(
  32. dt interface{},
  33. tableName string,
  34. keyword string,
  35. keywordPlural string,
  36. ) SInfrasResourceBaseManager {
  37. return SInfrasResourceBaseManager{
  38. SDomainLevelResourceBaseManager: NewDomainLevelResourceBaseManager(dt, tableName, keyword, keywordPlural),
  39. }
  40. }
  41. type SInfrasResourceBase struct {
  42. SDomainLevelResourceBase
  43. SSharableBaseResource `"is_public->create":"domain_optional" "public_scope->create":"domain_optional"`
  44. }
  45. func (manager *SInfrasResourceBaseManager) GetIInfrasModelManager() IInfrasModelManager {
  46. return manager.GetVirtualObject().(IInfrasModelManager)
  47. }
  48. func (manager *SInfrasResourceBaseManager) FilterByOwner(ctx context.Context, q *sqlchemy.SQuery, man FilterByOwnerProvider, userCred mcclient.TokenCredential, owner mcclient.IIdentityProvider, scope rbacscope.TRbacScope) *sqlchemy.SQuery {
  49. return SharableManagerFilterByOwner(ctx, manager.GetIInfrasModelManager(), q, userCred, owner, scope)
  50. }
  51. func (model *SInfrasResourceBase) IsSharable(reqUsrId mcclient.IIdentityProvider) bool {
  52. return SharableModelIsSharable(model.GetIInfrasModel(), reqUsrId)
  53. }
  54. func (model *SInfrasResourceBase) IsShared() bool {
  55. return SharableModelIsShared(model)
  56. }
  57. func (model *SInfrasResourceBase) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPublicDomainInput) (jsonutils.JSONObject, error) {
  58. err := SharablePerformPublic(model.GetIInfrasModel(), ctx, userCred, apis.PerformPublicProjectInput{PerformPublicDomainInput: input})
  59. if err != nil {
  60. return nil, errors.Wrap(err, "SharablePerformPublic")
  61. }
  62. return nil, nil
  63. }
  64. func (model *SInfrasResourceBase) PerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPrivateInput) (jsonutils.JSONObject, error) {
  65. err := SharablePerformPrivate(model.GetIInfrasModel(), ctx, userCred)
  66. if err != nil {
  67. return nil, errors.Wrap(err, "SharablePerformPrivate")
  68. }
  69. return nil, nil
  70. }
  71. func (model *SInfrasResourceBase) GetIInfrasModel() IInfrasModel {
  72. return model.GetVirtualObject().(IInfrasModel)
  73. }
  74. func (manager *SInfrasResourceBaseManager) ValidateCreateData(
  75. ctx context.Context,
  76. userCred mcclient.TokenCredential,
  77. ownerId mcclient.IIdentityProvider,
  78. query jsonutils.JSONObject,
  79. input apis.InfrasResourceBaseCreateInput,
  80. ) (apis.InfrasResourceBaseCreateInput, error) {
  81. var err error
  82. input.DomainLevelResourceCreateInput, err = manager.SDomainLevelResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.DomainLevelResourceCreateInput)
  83. if err != nil {
  84. return input, errors.Wrap(err, "manager.SDomainLevelResourceBaseManager.ValidateCreateData")
  85. }
  86. input.SharableResourceBaseCreateInput, err = SharableManagerValidateCreateData(manager.GetIInfrasModelManager(), ctx, userCred, ownerId, query, input.SharableResourceBaseCreateInput)
  87. if err != nil {
  88. return input, errors.Wrap(err, "SharableManagerValidateCreateData")
  89. }
  90. return input, nil
  91. }
  92. func (manager *SInfrasResourceBaseManager) ListItemFilter(
  93. ctx context.Context,
  94. q *sqlchemy.SQuery,
  95. userCred mcclient.TokenCredential,
  96. query apis.InfrasResourceBaseListInput,
  97. ) (*sqlchemy.SQuery, error) {
  98. q, err := manager.SDomainLevelResourceBaseManager.ListItemFilter(ctx, q, userCred, query.DomainLevelResourceListInput)
  99. if err != nil {
  100. return nil, errors.Wrap(err, "SDomainLevelResourceBaseManager.ListItemFilter")
  101. }
  102. q, err = manager.SSharableBaseResourceManager.ListItemFilter(ctx, q, userCred, query.SharableResourceBaseListInput)
  103. if err != nil {
  104. return nil, errors.Wrap(err, "SSharableBaseResourceManager.ListItemFilter")
  105. }
  106. return q, nil
  107. }
  108. func (manager *SInfrasResourceBaseManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
  109. q, err := manager.SDomainLevelResourceBaseManager.QueryDistinctExtraField(q, field)
  110. if err == nil {
  111. return q, nil
  112. }
  113. return q, httperrors.ErrNotFound
  114. }
  115. func (manager *SInfrasResourceBaseManager) OrderByExtraFields(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query apis.InfrasResourceBaseListInput) (*sqlchemy.SQuery, error) {
  116. q, err := manager.SDomainLevelResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.DomainLevelResourceListInput)
  117. if err != nil {
  118. return nil, errors.Wrap(err, "SDomainLevelResourceBaseManager.OrderByExtraFields")
  119. }
  120. return q, nil
  121. }
  122. func (manager *SInfrasResourceBaseManager) FetchCustomizeColumns(
  123. ctx context.Context,
  124. userCred mcclient.TokenCredential,
  125. query jsonutils.JSONObject,
  126. objs []interface{},
  127. fields stringutils2.SSortedStrings,
  128. isList bool,
  129. ) []apis.InfrasResourceBaseDetails {
  130. rows := make([]apis.InfrasResourceBaseDetails, len(objs))
  131. domainRows := manager.SDomainLevelResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  132. shareRows := manager.SSharableBaseResourceManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  133. for i := range rows {
  134. rows[i] = apis.InfrasResourceBaseDetails{
  135. DomainLevelResourceDetails: domainRows[i],
  136. SharableResourceBaseInfo: shareRows[i],
  137. }
  138. }
  139. return rows
  140. }
  141. func (model *SInfrasResourceBase) ValidateUpdateData(
  142. ctx context.Context,
  143. userCred mcclient.TokenCredential,
  144. query jsonutils.JSONObject,
  145. input apis.InfrasResourceBaseUpdateInput,
  146. ) (apis.InfrasResourceBaseUpdateInput, error) {
  147. var err error
  148. input.DomainLevelResourceBaseUpdateInput, err = model.SDomainLevelResourceBase.ValidateUpdateData(ctx, userCred, query, input.DomainLevelResourceBaseUpdateInput)
  149. if err != nil {
  150. return input, errors.Wrap(err, "SDomainLevelResourceBase.ValidateUpdateData")
  151. }
  152. return input, nil
  153. }
  154. func (model *SInfrasResourceBase) GetSharedDomains() []string {
  155. return SharableGetSharedProjects(model, SharedTargetDomain)
  156. }
  157. func (model *SInfrasResourceBase) PerformChangeOwner(
  158. ctx context.Context,
  159. userCred mcclient.TokenCredential,
  160. query jsonutils.JSONObject,
  161. input apis.PerformChangeDomainOwnerInput,
  162. ) (jsonutils.JSONObject, error) {
  163. if !consts.GetNonDefaultDomainProjects() {
  164. return nil, errors.Wrap(httperrors.ErrForbidden, "not allow to change owner of domain resource if non_default_domain_projects is turned off")
  165. }
  166. if model.IsShared() {
  167. return nil, errors.Wrap(httperrors.ErrInvalidStatus, "cannot change owner when shared!")
  168. }
  169. return model.SDomainLevelResourceBase.PerformChangeOwner(ctx, userCred, query, input)
  170. }
  171. func (model *SInfrasResourceBase) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
  172. // 避免domain_id为空导致异常
  173. defer SharableModelCustomizeCreate(model.GetIInfrasModel(), ctx, userCred, ownerId, query, data)
  174. return model.SDomainLevelResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
  175. }
  176. func (model *SInfrasResourceBase) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
  177. SharedResourceManager.CleanModelShares(ctx, userCred, model.GetIInfrasModel())
  178. return model.SDomainLevelResourceBase.Delete(ctx, userCred)
  179. }
  180. func (model *SInfrasResourceBase) GetSharedInfo() apis.SShareInfo {
  181. ret := apis.SShareInfo{}
  182. ret.IsPublic = model.IsPublic
  183. ret.PublicScope = rbacscope.String2ScopeDefault(model.PublicScope, rbacscope.ScopeNone)
  184. ret.SharedDomains = model.GetSharedDomains()
  185. ret.SharedProjects = nil
  186. // fix
  187. if len(ret.SharedDomains) > 0 {
  188. ret.PublicScope = rbacscope.ScopeDomain
  189. ret.SharedProjects = nil
  190. ret.IsPublic = true
  191. } else if !ret.IsPublic {
  192. ret.PublicScope = rbacscope.ScopeNone
  193. }
  194. return ret
  195. }
  196. func (model *SInfrasResourceBase) SaveSharedInfo(src apis.TOwnerSource, ctx context.Context, userCred mcclient.TokenCredential, si apis.SShareInfo) {
  197. diff, _ := Update(model, func() error {
  198. model.PublicSrc = string(src)
  199. model.IsPublic = si.IsPublic
  200. model.PublicScope = string(si.PublicScope)
  201. return nil
  202. })
  203. if len(diff) > 0 {
  204. OpsLog.LogEvent(model, ACT_SYNC_SHARE, diff, userCred)
  205. }
  206. SharedResourceManager.shareToTarget(ctx, userCred, model.GetIInfrasModel(), SharedTargetProject, nil, nil, nil)
  207. SharedResourceManager.shareToTarget(ctx, userCred, model.GetIInfrasModel(), SharedTargetDomain, si.SharedDomains, nil, nil)
  208. }
  209. func (model *SInfrasResourceBase) SyncShareState(ctx context.Context, userCred mcclient.TokenCredential, shareInfo apis.SAccountShareInfo) {
  210. if !consts.GetNonDefaultDomainProjects() {
  211. if model.PublicSrc != string(apis.OWNER_SOURCE_LOCAL) {
  212. model.SaveSharedInfo(apis.OWNER_SOURCE_CLOUD, ctx, userCred, apis.SShareInfo{
  213. IsPublic: true,
  214. PublicScope: rbacscope.ScopeSystem,
  215. })
  216. }
  217. return
  218. }
  219. si := shareInfo.GetDomainShareInfo()
  220. if model.PublicSrc != string(apis.OWNER_SOURCE_LOCAL) {
  221. model.SaveSharedInfo(apis.OWNER_SOURCE_CLOUD, ctx, userCred, si)
  222. } else {
  223. localSi := model.GetSharedInfo()
  224. if localSi.IsViolate(si) {
  225. newSi := localSi.Intersect(si)
  226. newSi.FixDomainShare()
  227. // reset to cloud base public_src
  228. model.SaveSharedInfo(apis.OWNER_SOURCE_CLOUD, ctx, userCred, newSi)
  229. }
  230. }
  231. }
  232. func (model *SInfrasResourceBase) GetSharableTargetDomainIds() []string {
  233. return model.GetIInfrasModel().GetChangeOwnerCandidateDomainIds()
  234. }
  235. func (model *SInfrasResourceBase) GetRequiredSharedDomainIds() []string {
  236. return []string{model.DomainId}
  237. }
  238. /*func (model *SInfrasResourceBase) ValidateDeleteCondition(ctx context.Context) error {
  239. if model.IsShared() {
  240. return httperrors.NewForbiddenError("%s %s is shared", model.Keyword(), model.Name)
  241. }
  242. return model.SDomainLevelResourceBase.ValidateDeleteCondition(ctx)
  243. }*/