From b9a239bd65536923511bc730aee47f9a77e7954f Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Sat, 11 Apr 2020 06:02:15 +0800 Subject: [PATCH] fix: sync sharing state --- pkg/cloudcommon/db/domain.go | 2 +- pkg/cloudcommon/db/domainresource.go | 3 +- pkg/cloudcommon/db/fetch.go | 4 +- pkg/cloudcommon/db/infraresource.go | 9 ++- pkg/cloudcommon/db/managed.go | 3 +- pkg/cloudcommon/db/opslog.go | 2 +- pkg/cloudcommon/db/project.go | 5 +- pkg/cloudcommon/db/scoperesource.go | 4 +- pkg/cloudcommon/db/sharablebase.go | 23 +++--- pkg/cloudcommon/db/sharablevirtual.go | 9 ++- pkg/cloudcommon/db/sharedresource.go | 7 +- pkg/cloudcommon/db/tenantcache.go | 10 +++ pkg/compute/models/managedresource.go | 2 +- pkg/image/models/images.go | 3 + pkg/keystone/models/credentials.go | 2 +- pkg/keystone/models/identitybase.go | 23 +++--- pkg/keystone/models/identityquota.go | 2 +- pkg/keystone/models/policies.go | 2 +- pkg/keystone/models/roles.go | 4 +- pkg/keystone/service/override.go | 107 ++++++++++++++++++++++++++ pkg/keystone/service/service.go | 9 +-- 21 files changed, 182 insertions(+), 53 deletions(-) create mode 100644 pkg/keystone/service/override.go diff --git a/pkg/cloudcommon/db/domain.go b/pkg/cloudcommon/db/domain.go index c43efeb4f1..e86c3e6c90 100644 --- a/pkg/cloudcommon/db/domain.go +++ b/pkg/cloudcommon/db/domain.go @@ -146,7 +146,7 @@ func (manager *SDomainizedResourceBaseManager) FetchCustomizeColumns( domainIds = stringutils2.Append(domainIds, base.DomainId) } } - domains := FetchProjects(domainIds, true) + domains := DefaultProjectsFetcher(ctx, domainIds, true) if domains != nil { for i := range objs { var base *SDomainizedResourceBase diff --git a/pkg/cloudcommon/db/domainresource.go b/pkg/cloudcommon/db/domainresource.go index 2717d815c8..e4ffc69fd6 100644 --- a/pkg/cloudcommon/db/domainresource.go +++ b/pkg/cloudcommon/db/domainresource.go @@ -17,11 +17,10 @@ package db import ( "context" - "yunion.io/x/pkg/utils" - "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/pkg/errors" + "yunion.io/x/pkg/utils" "yunion.io/x/sqlchemy" "yunion.io/x/onecloud/pkg/apis" diff --git a/pkg/cloudcommon/db/fetch.go b/pkg/cloudcommon/db/fetch.go index d3291f30bd..1b3b251d7a 100644 --- a/pkg/cloudcommon/db/fetch.go +++ b/pkg/cloudcommon/db/fetch.go @@ -246,7 +246,7 @@ func FetchProjectInfo(ctx context.Context, data jsonutils.JSONObject) (mcclient. tenantId, key := jsonutils.GetAnyString2(data, []string{"project", "project_id", "tenant", "tenant_id"}) if len(tenantId) > 0 { data.(*jsonutils.JSONDict).Remove(key) - t, err := TenantCacheManager.FetchTenantByIdOrName(ctx, tenantId) + t, err := DefaultProjectFetcher(ctx, tenantId) if err != nil { if err == sql.ErrNoRows { return nil, httperrors.NewResourceNotFoundError2("project", tenantId) @@ -271,7 +271,7 @@ func FetchDomainInfo(ctx context.Context, data jsonutils.JSONObject) (mcclient.I domainId, key := jsonutils.GetAnyString2(data, []string{"domain_id", "project_domain", "project_domain_id"}) if len(domainId) > 0 { data.(*jsonutils.JSONDict).Remove(key) - domain, err := TenantCacheManager.FetchDomainByIdOrName(ctx, domainId) + domain, err := DefaultDomainFetcher(ctx, domainId) if err != nil { if err == sql.ErrNoRows { return nil, httperrors.NewResourceNotFoundError2("domain", domainId) diff --git a/pkg/cloudcommon/db/infraresource.go b/pkg/cloudcommon/db/infraresource.go index ee46add44a..25602f0f27 100644 --- a/pkg/cloudcommon/db/infraresource.go +++ b/pkg/cloudcommon/db/infraresource.go @@ -214,19 +214,26 @@ func (model *SInfrasResourceBase) Delete(ctx context.Context, userCred mcclient. } func (model *SInfrasResourceBase) SyncShareState(ctx context.Context, userCred mcclient.TokenCredential, shareInfo apis.SAccountShareInfo) { - if model.PublicScope != string(apis.OWNER_SOURCE_LOCAL) { + if model.PublicSrc != string(apis.OWNER_SOURCE_LOCAL) { diff, _ := Update(model, func() error { + model.PublicSrc = string(apis.OWNER_SOURCE_CLOUD) switch shareInfo.ShareMode { case compute.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN: model.IsPublic = false model.PublicScope = string(rbacutils.ScopeNone) + SharedResourceManager.shareToTarget(ctx, userCred, model.GetIInfrasModel(), SharedTargetProject, nil, nil, nil) + SharedResourceManager.shareToTarget(ctx, userCred, model.GetIInfrasModel(), SharedTargetDomain, nil, nil, nil) case compute.CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN: model.IsPublic = false model.PublicScope = string(rbacutils.ScopeNone) + SharedResourceManager.shareToTarget(ctx, userCred, model.GetIInfrasModel(), SharedTargetProject, nil, nil, nil) + SharedResourceManager.shareToTarget(ctx, userCred, model.GetIInfrasModel(), SharedTargetDomain, nil, nil, nil) case compute.CLOUD_ACCOUNT_SHARE_MODE_SYSTEM: if shareInfo.IsPublic && shareInfo.PublicScope == rbacutils.ScopeSystem { model.IsPublic = true model.PublicScope = string(rbacutils.ScopeSystem) + SharedResourceManager.shareToTarget(ctx, userCred, model.GetIInfrasModel(), SharedTargetProject, nil, nil, nil) + SharedResourceManager.shareToTarget(ctx, userCred, model.GetIInfrasModel(), SharedTargetDomain, nil, nil, nil) } else if len(shareInfo.SharedDomains) > 0 { model.IsPublic = true model.PublicScope = string(rbacutils.ScopeDomain) diff --git a/pkg/cloudcommon/db/managed.go b/pkg/cloudcommon/db/managed.go index 5c29d1f648..7abcd2ccbd 100644 --- a/pkg/cloudcommon/db/managed.go +++ b/pkg/cloudcommon/db/managed.go @@ -15,8 +15,9 @@ package db import ( - "yunion.io/x/onecloud/pkg/apis" "yunion.io/x/pkg/errors" + + "yunion.io/x/onecloud/pkg/apis" ) type IOwnerResourceBaseModel interface { diff --git a/pkg/cloudcommon/db/opslog.go b/pkg/cloudcommon/db/opslog.go index d97af6666f..139f25fa87 100644 --- a/pkg/cloudcommon/db/opslog.go +++ b/pkg/cloudcommon/db/opslog.go @@ -480,7 +480,7 @@ func (manager *SOpsLogManager) ListItemFilter( projStrs := jsonutils.GetQueryStringArray(query, "project") if len(projStrs) > 0 { for i := range projStrs { - projObj, err := TenantCacheManager.FetchTenantByIdOrName(ctx, projStrs[i]) + projObj, err := DefaultProjectFetcher(ctx, projStrs[i]) if err != nil { if err == sql.ErrNoRows { return nil, httperrors.NewResourceNotFoundError2("project", projStrs[i]) diff --git a/pkg/cloudcommon/db/project.go b/pkg/cloudcommon/db/project.go index f846757274..77091ef3fb 100644 --- a/pkg/cloudcommon/db/project.go +++ b/pkg/cloudcommon/db/project.go @@ -143,7 +143,7 @@ func (manager *SProjectizedResourceBaseManager) FetchCustomizeColumns( projectIds = stringutils2.Append(projectIds, base.ProjectId) } } - projects := FetchProjects(projectIds, false) + projects := DefaultProjectsFetcher(ctx, projectIds, false) if projects != nil { for i := range objs { var base *SProjectizedResourceBase @@ -164,7 +164,7 @@ func (manager *SProjectizedResourceBaseManager) FetchCustomizeColumns( return ret } -func FetchProjects(projectIds []string, isDomain bool) map[string]STenant { +func fetchProjects(ctx context.Context, projectIds []string, isDomain bool) map[string]STenant { deadline := time.Now().UTC().Add(-consts.GetTenantCacheExpireSeconds()) q := TenantCacheManager.Query().In("id", projectIds).GT("last_check", deadline) if isDomain { @@ -181,7 +181,6 @@ func FetchProjects(projectIds []string, isDomain bool) map[string]STenant { for i := range projects { ret[projects[i].Id] = projects[i] } - ctx := context.Background() for _, pid := range projectIds { if _, ok := ret[pid]; !ok { // not found diff --git a/pkg/cloudcommon/db/scoperesource.go b/pkg/cloudcommon/db/scoperesource.go index 2ddf6fb44d..50b36fe4b6 100644 --- a/pkg/cloudcommon/db/scoperesource.go +++ b/pkg/cloudcommon/db/scoperesource.go @@ -151,7 +151,7 @@ func (m *SScopedResourceBaseManager) PerformSetScope( domainId := jsonutils.GetAnyString(data, []string{"domain_id", "domain", "project_domain_id", "project_domain"}) projectId := jsonutils.GetAnyString(data, []string{"project_id", "project"}) if projectId != "" { - project, err := TenantCacheManager.FetchTenantByIdOrName(ctx, projectId) + project, err := DefaultProjectFetcher(ctx, projectId) if err != nil { return nil, err } @@ -159,7 +159,7 @@ func (m *SScopedResourceBaseManager) PerformSetScope( domainId = project.GetDomainId() } if domainId != "" { - domain, err := TenantCacheManager.FetchDomainByIdOrName(ctx, domainId) + domain, err := DefaultDomainFetcher(ctx, domainId) if err != nil { return nil, err } diff --git a/pkg/cloudcommon/db/sharablebase.go b/pkg/cloudcommon/db/sharablebase.go index a384d114ae..40857df433 100644 --- a/pkg/cloudcommon/db/sharablebase.go +++ b/pkg/cloudcommon/db/sharablebase.go @@ -101,20 +101,14 @@ func (manager *SSharableBaseResourceManager) FetchCustomizeColumns( } } - tenantMap := make(map[string]STenant) - domainMap := make(map[string]STenant) + var tenantMap map[string]STenant + var domainMap map[string]STenant if len(targetTenantIds) > 0 { - err = FetchQueryObjectsByIds(TenantCacheManager.GetTenantQuery(), "id", targetTenantIds, &tenantMap) - if err != nil { - log.Errorf("FetchQueryObjectsByIds for tenant_cache fail %s", err) - } + tenantMap = DefaultProjectsFetcher(ctx, targetTenantIds, false) } if len(targetDomainIds) > 0 { - err = FetchQueryObjectsByIds(TenantCacheManager.GetDomainQuery(), "id", targetDomainIds, &domainMap) - if err != nil { - log.Errorf("FetchQueryObjectsByIds for tenant_cache fail %s", err) - } + domainMap = DefaultProjectsFetcher(ctx, targetDomainIds, true) } for i := range rows { @@ -160,6 +154,10 @@ func SharableManagerFilterByOwner(manager IStandaloneModelManager, q *sqlchemy.S subq = subq.Equals("resource_type", manager.Keyword()) subq = subq.Equals("target_project_id", ownerProjectId) subq = subq.Equals("target_type", SharedTargetProject) + subq2 := SharedResourceManager.Query("resource_id") + subq2 = subq2.Equals("resource_type", manager.Keyword()) + subq2 = subq2.Equals("target_project_id", owner.GetProjectDomainId()) + subq2 = subq2.Equals("target_type", SharedTargetDomain) q = q.Filter(sqlchemy.OR( sqlchemy.Equals(q.Field("tenant_id"), ownerProjectId), sqlchemy.AND( @@ -169,7 +167,10 @@ func SharableManagerFilterByOwner(manager IStandaloneModelManager, q *sqlchemy.S sqlchemy.AND( sqlchemy.IsTrue(q.Field("is_public")), sqlchemy.Equals(q.Field("public_scope"), rbacutils.ScopeDomain), - sqlchemy.Equals(q.Field("domain_id"), owner.GetProjectDomainId()), + sqlchemy.OR( + sqlchemy.Equals(q.Field("domain_id"), owner.GetProjectDomainId()), + sqlchemy.In(q.Field("id"), subq2.SubQuery()), + ), ), sqlchemy.In(q.Field("id"), subq.SubQuery()), )) diff --git a/pkg/cloudcommon/db/sharablevirtual.go b/pkg/cloudcommon/db/sharablevirtual.go index c71eef43b7..337c51d0dd 100644 --- a/pkg/cloudcommon/db/sharablevirtual.go +++ b/pkg/cloudcommon/db/sharablevirtual.go @@ -207,19 +207,26 @@ func (model *SSharableVirtualResourceBase) Delete(ctx context.Context, userCred } func (model *SSharableVirtualResourceBase) SyncShareState(ctx context.Context, userCred mcclient.TokenCredential, shareInfo apis.SAccountShareInfo) { - if model.PublicScope != string(apis.OWNER_SOURCE_LOCAL) { + if model.PublicSrc != string(apis.OWNER_SOURCE_LOCAL) { diff, _ := Update(model, func() error { + model.PublicSrc = string(apis.OWNER_SOURCE_CLOUD) switch shareInfo.ShareMode { case compute.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN: model.IsPublic = true model.PublicScope = string(rbacutils.ScopeDomain) + SharedResourceManager.shareToTarget(ctx, userCred, model.GetISharableVirtualModel(), SharedTargetProject, nil, nil, nil) + SharedResourceManager.shareToTarget(ctx, userCred, model.GetISharableVirtualModel(), SharedTargetDomain, nil, nil, nil) case compute.CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN: model.IsPublic = true model.PublicScope = string(rbacutils.ScopeDomain) + SharedResourceManager.shareToTarget(ctx, userCred, model.GetISharableVirtualModel(), SharedTargetProject, nil, nil, nil) + SharedResourceManager.shareToTarget(ctx, userCred, model.GetISharableVirtualModel(), SharedTargetDomain, nil, nil, nil) case compute.CLOUD_ACCOUNT_SHARE_MODE_SYSTEM: model.IsPublic = true if shareInfo.IsPublic && shareInfo.PublicScope == rbacutils.ScopeSystem { model.PublicScope = string(rbacutils.ScopeSystem) + SharedResourceManager.shareToTarget(ctx, userCred, model.GetISharableVirtualModel(), SharedTargetProject, nil, nil, nil) + SharedResourceManager.shareToTarget(ctx, userCred, model.GetISharableVirtualModel(), SharedTargetDomain, nil, nil, nil) } else { model.PublicScope = string(rbacutils.ScopeDomain) SharedResourceManager.shareToTarget(ctx, userCred, model.GetISharableVirtualModel(), SharedTargetProject, nil, nil, nil) diff --git a/pkg/cloudcommon/db/sharedresource.go b/pkg/cloudcommon/db/sharedresource.go index ff1ce86132..44241085aa 100644 --- a/pkg/cloudcommon/db/sharedresource.go +++ b/pkg/cloudcommon/db/sharedresource.go @@ -18,9 +18,8 @@ import ( "context" "database/sql" - "yunion.io/x/pkg/utils" - "yunion.io/x/pkg/errors" + "yunion.io/x/pkg/utils" "yunion.io/x/onecloud/pkg/cloudcommon/consts" "yunion.io/x/onecloud/pkg/cloudcommon/policy" @@ -146,7 +145,7 @@ func (manager *SSharedResourceManager) shareToTarget( for i := 0; i < len(targetIds); i++ { switch targetType { case SharedTargetProject: - tenant, err := TenantCacheManager.FetchTenantByIdOrName(ctx, targetIds[i]) + tenant, err := DefaultProjectFetcher(ctx, targetIds[i]) if err != nil { return nil, errors.Wrapf(err, "fetch tenant %s error", targetIds[i]) } @@ -158,7 +157,7 @@ func (manager *SSharedResourceManager) shareToTarget( } newIds = stringutils2.Append(newIds, tenant.GetId()) case SharedTargetDomain: - domain, err := TenantCacheManager.FetchDomainByIdOrName(ctx, targetIds[i]) + domain, err := DefaultDomainFetcher(ctx, targetIds[i]) if err != nil { return nil, errors.Wrapf(err, "fetch domain %s error", targetIds[i]) } diff --git a/pkg/cloudcommon/db/tenantcache.go b/pkg/cloudcommon/db/tenantcache.go index e7cbb2490a..14227af52d 100644 --- a/pkg/cloudcommon/db/tenantcache.go +++ b/pkg/cloudcommon/db/tenantcache.go @@ -37,6 +37,12 @@ import ( "yunion.io/x/onecloud/pkg/util/stringutils2" ) +var ( + DefaultProjectFetcher func(ctx context.Context, id string) (*STenant, error) + DefaultDomainFetcher func(ctx context.Context, id string) (*STenant, error) + DefaultProjectsFetcher func(ctx context.Context, idList []string, isDomain bool) map[string]STenant +) + type STenantCacheManager struct { SKeystoneCacheObjectManager } @@ -64,6 +70,10 @@ func init() { // log.Debugf("Initialize tenant cache manager %s %s", TenantCacheManager.KeywordPlural(), TenantCacheManager) TenantCacheManager.SetVirtualObject(TenantCacheManager) + + DefaultProjectFetcher = TenantCacheManager.FetchTenantByIdOrName + DefaultDomainFetcher = TenantCacheManager.FetchDomainByIdOrName + DefaultProjectsFetcher = fetchProjects } func RegistUserCredCacheUpdater() { diff --git a/pkg/compute/models/managedresource.go b/pkg/compute/models/managedresource.go index c97ddc211f..bfbaa0be71 100644 --- a/pkg/compute/models/managedresource.go +++ b/pkg/compute/models/managedresource.go @@ -245,7 +245,7 @@ func (manager *SManagedResourceBaseManager) FetchCustomizeColumns( return nil } - projects := db.FetchProjects(projectIds, false) + projects := db.DefaultProjectsFetcher(ctx, projectIds, false) for i := range rows { if account, ok := accounts[rows[i].AccountId]; ok { diff --git a/pkg/image/models/images.go b/pkg/image/models/images.go index f7b2beff1e..2d4f969be2 100644 --- a/pkg/image/models/images.go +++ b/pkg/image/models/images.go @@ -1354,6 +1354,9 @@ func (self *SImage) PerformMarkStandard( query jsonutils.JSONObject, data jsonutils.JSONObject, ) (jsonutils.JSONObject, error) { + if self.IsGuestImage.IsTrue() { + return nil, errors.Wrap(httperrors.ErrForbidden, "cannot mark standard to a guest image") + } isStandard := jsonutils.QueryBoolean(data, "is_standard", false) if !self.IsStandard.IsTrue() && isStandard { input := apis.PerformPublicInput{ diff --git a/pkg/keystone/models/credentials.go b/pkg/keystone/models/credentials.go index f524dd7a2b..b3b011e081 100644 --- a/pkg/keystone/models/credentials.go +++ b/pkg/keystone/models/credentials.go @@ -261,7 +261,7 @@ func (self *SCredential) GetOwnerId() mcclient.IIdentityProvider { func (manager *SCredentialManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) { userStr, key := jsonutils.GetAnyString2(data, []string{"user", "user_id"}) if len(userStr) > 0 { - domainOwner, err := fetchDomainInfo(data) + domainOwner, err := db.FetchDomainInfo(ctx, data) if err != nil { return nil, err } diff --git a/pkg/keystone/models/identitybase.go b/pkg/keystone/models/identitybase.go index ac7c2c6928..6e87a3d417 100644 --- a/pkg/keystone/models/identitybase.go +++ b/pkg/keystone/models/identitybase.go @@ -16,16 +16,13 @@ package models import ( "context" - "database/sql" "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/pkg/errors" "yunion.io/x/pkg/tristate" - "yunion.io/x/pkg/util/reflectutils" "yunion.io/x/sqlchemy" - "yunion.io/x/onecloud/pkg/apis" api "yunion.io/x/onecloud/pkg/apis/identity" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/httperrors" @@ -223,7 +220,7 @@ func (manager *SEnabledIdentityBaseResourceManager) QueryDistinctExtraField(q *s return q, httperrors.ErrNotFound } -func fetchDomainInfo(data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) { +/*func fetchDomainInfo(data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) { domainId, key := jsonutils.GetAnyString2(data, []string{"domain_id", "project_domain", "project_domain_id"}) if len(domainId) > 0 { data.(*jsonutils.JSONDict).Remove(key) @@ -243,7 +240,7 @@ func fetchDomainInfo(data jsonutils.JSONObject) (mcclient.IIdentityProvider, err func (manager *SIdentityBaseResourceManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) { return fetchDomainInfo(data) -} +}*/ func (manager *SIdentityBaseResourceManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.IdentityBaseResourceCreateInput) (api.IdentityBaseResourceCreateInput, error) { domain, _ := DomainManager.FetchDomainById(ownerId.GetProjectDomainId()) @@ -319,21 +316,22 @@ func (manager *SIdentityBaseResourceManager) FetchCustomizeColumns( rows := make([]api.IdentityBaseResourceDetails, len(objs)) stdRows := manager.SStandaloneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList) + domainRows := manager.SDomainizedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList) - domainIds := stringutils2.SSortedStrings{} + // domainIds := stringutils2.SSortedStrings{} for i := range rows { rows[i] = api.IdentityBaseResourceDetails{ StandaloneResourceDetails: stdRows[i], - DomainizedResourceInfo: apis.DomainizedResourceInfo{}, + DomainizedResourceInfo: domainRows[i], } - var base *SIdentityBaseResource + /*var base *SIdentityBaseResource reflectutils.FindAnonymouStructPointer(objs[i], &base) if base != nil && len(base.DomainId) > 0 && base.DomainId != api.KeystoneDomainRoot { domainIds = stringutils2.Append(domainIds, base.DomainId) - } + }*/ } - if len(fields) == 0 || fields.Contains("project_domain") { + /*if len(fields) == 0 || fields.Contains("project_domain") { domains := fetchDomain(domainIds) if domains != nil { for i := range rows { @@ -346,7 +344,7 @@ func (manager *SIdentityBaseResourceManager) FetchCustomizeColumns( } } } - } + }*/ return rows } @@ -380,6 +378,7 @@ func (manager *SEnabledIdentityBaseResourceManager) FetchCustomizeColumns( return rows } +/* func fetchDomain(domainIds []string) map[string]SDomain { q := DomainManager.Query().In("id", domainIds) domains := make([]SDomain, 0) @@ -392,7 +391,7 @@ func fetchDomain(domainIds []string) map[string]SDomain { ret[domains[i].Id] = domains[i] } return ret -} +}*/ func (model *SIdentityBaseResource) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error { model.DomainId = ownerId.GetProjectDomainId() diff --git a/pkg/keystone/models/identityquota.go b/pkg/keystone/models/identityquota.go index cfa5c589e0..999bd8f095 100644 --- a/pkg/keystone/models/identityquota.go +++ b/pkg/keystone/models/identityquota.go @@ -277,7 +277,7 @@ func (manager *SQuotaManager) FetchIdNames(ctx context.Context, idMap map[string } func (manager *SQuotaManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) { - return fetchDomainInfo(data) + return db.FetchDomainInfo(ctx, data) } /////////////////////////////////////////////////// diff --git a/pkg/keystone/models/policies.go b/pkg/keystone/models/policies.go index a6f745980e..a30273c37c 100644 --- a/pkg/keystone/models/policies.go +++ b/pkg/keystone/models/policies.go @@ -66,7 +66,7 @@ func init() { type SPolicy struct { SEnabledIdentityBaseResource - db.SSharableBaseResource + db.SSharableBaseResource `"is_public=>create":"domain_optional" "public_scope=>create":"domain_optional"` Type string `width:"255" charset:"utf8" nullable:"false" list:"user" create:"domain_required" update:"domain"` Blob jsonutils.JSONObject `nullable:"false" list:"user" create:"domain_required" update:"domain"` diff --git a/pkg/keystone/models/roles.go b/pkg/keystone/models/roles.go index af51750cf3..33d5ad1f43 100644 --- a/pkg/keystone/models/roles.go +++ b/pkg/keystone/models/roles.go @@ -67,8 +67,8 @@ func init() { */ type SRole struct { - SIdentityBaseResource `"name->update":""` - db.SSharableBaseResource + SIdentityBaseResource `"name->update":""` + db.SSharableBaseResource `"is_public=>create":"domain_optional" "public_scope=>create":"domain_optional"` } func (manager *SRoleManager) GetContextManagers() [][]db.IModelManager { diff --git a/pkg/keystone/service/override.go b/pkg/keystone/service/override.go new file mode 100644 index 0000000000..d931cf75a4 --- /dev/null +++ b/pkg/keystone/service/override.go @@ -0,0 +1,107 @@ +// Copyright 2019 Yunion +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package service + +import ( + "context" + "database/sql" + + "github.com/golang-plus/uuid" + + "yunion.io/x/log" + "yunion.io/x/pkg/errors" + + api "yunion.io/x/onecloud/pkg/apis/identity" + "yunion.io/x/onecloud/pkg/cloudcommon/db" + "yunion.io/x/onecloud/pkg/httperrors" + "yunion.io/x/onecloud/pkg/keystone/models" +) + +func keystoneUUIDGenerator() string { + id, _ := uuid.NewV4() + return id.Format(uuid.StyleWithoutDash) +} + +func keystoneProjectFetcher(ctx context.Context, idstr string) (*db.STenant, error) { + tenantObj, err := models.ProjectManager.FetchByIdOrName(nil, idstr) + if err != nil { + if errors.Cause(err) == sql.ErrNoRows { + return nil, errors.Wrapf(httperrors.ErrResourceNotFound, "tenant %s", idstr) + } else { + return nil, errors.Wrap(err, "models.ProjectManager.FetchByIdOrName") + } + } + ret := project2Tenant(tenantObj.(*models.SProject)) + return &ret, nil +} + +func keystoneDomainFetcher(ctx context.Context, idstr string) (*db.STenant, error) { + domainObj, err := models.DomainManager.FetchByIdOrName(nil, idstr) + if err != nil { + if errors.Cause(err) == sql.ErrNoRows { + return nil, errors.Wrapf(httperrors.ErrResourceNotFound, "domain %s", idstr) + } else { + return nil, errors.Wrap(err, "models.DomainManager.FetchByIdOrName") + } + } + ret := domain2Tenant(domainObj.(*models.SDomain)) + return &ret, nil +} + +func project2Tenant(tenant *models.SProject) db.STenant { + ret := db.STenant{} + ret.Id = tenant.Id + ret.Name = tenant.Name + ret.DomainId = tenant.DomainId + ret.Domain = tenant.GetDomain().Name + return ret +} + +func domain2Tenant(domain *models.SDomain) db.STenant { + ret := db.STenant{} + ret.Id = domain.Id + ret.Name = domain.Name + ret.DomainId = api.KeystoneDomainRoot + ret.Domain = api.KeystoneDomainRoot + return ret +} + +func keystoneProjectsFetcher(ctx context.Context, idList []string, isDomain bool) map[string]db.STenant { + if isDomain { + domains := make(map[string]models.SDomain) + err := db.FetchStandaloneObjectsByIds(models.DomainManager, idList, &domains) + if err != nil { + log.Errorf("FetchStandaloneObjectsByIds for domain fail %s", err) + return nil + } + ret := make(map[string]db.STenant) + for id, domain := range domains { + ret[id] = domain2Tenant(&domain) + } + return ret + } else { + projects := make(map[string]models.SProject) + err := db.FetchStandaloneObjectsByIds(models.ProjectManager, idList, &projects) + if err != nil { + log.Errorf("FetchStandaloneObjectsByIds for project fail %s", err) + return nil + } + ret := make(map[string]db.STenant) + for id, project := range projects { + ret[id] = project2Tenant(&project) + } + return ret + } +} diff --git a/pkg/keystone/service/service.go b/pkg/keystone/service/service.go index e2c315cddd..874e4709b5 100644 --- a/pkg/keystone/service/service.go +++ b/pkg/keystone/service/service.go @@ -19,7 +19,6 @@ import ( "time" _ "github.com/go-sql-driver/mysql" - "github.com/golang-plus/uuid" api "yunion.io/x/onecloud/pkg/apis/identity" "yunion.io/x/onecloud/pkg/cloudcommon" @@ -41,14 +40,12 @@ import ( "yunion.io/x/onecloud/pkg/util/logclient" ) -func keystoneUUIDGenerator() string { - id, _ := uuid.NewV4() - return id.Format(uuid.StyleWithoutDash) -} - func StartService() { auth.DefaultTokenVerifier = tokens.FernetTokenVerifier db.DefaultUUIDGenerator = keystoneUUIDGenerator + db.DefaultProjectFetcher = keystoneProjectFetcher + db.DefaultDomainFetcher = keystoneDomainFetcher + db.DefaultProjectsFetcher = keystoneProjectsFetcher policy.DefaultPolicyFetcher = localPolicyFetcher logclient.DefaultSessionGenerator = models.GetDefaultClientSession cronman.DefaultAdminSessionGenerator = models.GetDefaultAdminCred