diff --git a/pkg/apis/scheduler/api.go b/pkg/apis/scheduler/api.go index 984a557e3f..d4dd46b5c3 100644 --- a/pkg/apis/scheduler/api.go +++ b/pkg/apis/scheduler/api.go @@ -53,8 +53,10 @@ type ServerConfig struct { GuestStatus string `json:"guest_status"` Cdrom string `json:"cdrom"` + // owner project id Project string `json:"project_id"` - Domain string `json:"domain_id"` + // owner domain id + Domain string `json:"domain_id"` // Deprecated Metadata map[string]string `json:"__meta__"` diff --git a/pkg/compute/tasks/schedule.go b/pkg/compute/tasks/schedule.go index 0325e5b9d5..cd3111b0f2 100644 --- a/pkg/compute/tasks/schedule.go +++ b/pkg/compute/tasks/schedule.go @@ -129,7 +129,7 @@ func doScheduleObjects( params := jsonutils.Marshal(schedInput).(*jsonutils.JSONDict) task.SetStage("OnScheduleComplete", params) - s := auth.GetAdminSession(ctx, options.Options.Region, "") + s := auth.GetSession(ctx, task.GetUserCred(), options.Options.Region, "") output, err := modules.SchedManager.DoSchedule(s, schedInput, len(objs)) if err != nil { onSchedulerRequestFail(ctx, task, objs, jsonutils.Marshal(err)) diff --git a/pkg/scheduler/algorithm/predicates/domain_predicate.go b/pkg/scheduler/algorithm/predicates/domain_predicate.go index d53087967b..adbba01063 100644 --- a/pkg/scheduler/algorithm/predicates/domain_predicate.go +++ b/pkg/scheduler/algorithm/predicates/domain_predicate.go @@ -17,6 +17,7 @@ package predicates import ( "yunion.io/x/pkg/utils" + "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/scheduler/core" "yunion.io/x/onecloud/pkg/util/rbacutils" ) @@ -39,6 +40,7 @@ func (p *DomainPredicate) Execute(u *core.Unit, c core.Candidater) (bool, []core if getter.DomainId() == u.SchedInfo.Domain { } else if getter.IsPublic() && getter.PublicScope() == string(rbacutils.ScopeSystem) { } else if getter.IsPublic() && getter.PublicScope() == string(rbacutils.ScopeDomain) && utils.IsInStringArray(u.SchedInfo.Domain, getter.SharedDomains()) { + } else if db.IsAdminAllowGet(u.SchedInfo.UserCred, getter) { } else { h.Exclude("domain_ownership") } diff --git a/pkg/scheduler/algorithm/predicates/network_predicate.go b/pkg/scheduler/algorithm/predicates/network_predicate.go index 2ff422d46d..887348cc5c 100644 --- a/pkg/scheduler/algorithm/predicates/network_predicate.go +++ b/pkg/scheduler/algorithm/predicates/network_predicate.go @@ -21,6 +21,7 @@ import ( "yunion.io/x/pkg/utils" computeapi "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/compute/models" "yunion.io/x/onecloud/pkg/scheduler/algorithm/plugin" "yunion.io/x/onecloud/pkg/scheduler/api" @@ -150,6 +151,10 @@ func IsNetworkAvailable( // project-wide share } else if n.ProjectId == data.Project { // owner + } else if db.IsAdminAllowGet(data.UserCred, n) { + // system admin, can do anything + } else if db.IsDomainAllowGet(data.UserCred, n) && data.UserCred.GetProjectDomainId() == n.DomainId { + // domain admin, can do anything with domain network } else { return FailReason{ Reason: fmt.Sprintf("Network %s not accessible", n.Name), diff --git a/pkg/scheduler/api/sched.go b/pkg/scheduler/api/sched.go index 4cd515d473..8c06d224c6 100644 --- a/pkg/scheduler/api/sched.go +++ b/pkg/scheduler/api/sched.go @@ -18,13 +18,18 @@ import ( "net/http" //"yunion.io/x/jsonutils" "yunion.io/x/log" + "yunion.io/x/pkg/errors" computeapi "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/apis/identity" api "yunion.io/x/onecloud/pkg/apis/scheduler" "yunion.io/x/onecloud/pkg/appsrv" "yunion.io/x/onecloud/pkg/cloudcommon/cmdline" "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/compute/models" + "yunion.io/x/onecloud/pkg/httperrors" + "yunion.io/x/onecloud/pkg/mcclient" + "yunion.io/x/onecloud/pkg/mcclient/auth" o "yunion.io/x/onecloud/pkg/scheduler/options" ) @@ -43,9 +48,28 @@ type SchedInfo struct { Raw string InstanceGroupsDetail map[string]*models.SGroup + + UserCred mcclient.TokenCredential +} + +func fetchAuthToken(req *http.Request) (mcclient.TokenCredential, error) { + tokenStr := req.Header.Get(identity.AUTH_TOKEN_HEADER) + if tokenStr == "" { + return nil, errors.Wrap(httperrors.ErrInvalidCredential, "missing token header") + } + token, err := auth.Verify(req.Context(), tokenStr) + if err != nil { + return nil, errors.Wrap(err, "Verify") + } + return token, nil } func FetchSchedInfo(req *http.Request) (*SchedInfo, error) { + token, err := fetchAuthToken(req) + if err != nil { + return nil, errors.Wrap(err, "fetchAuthToken") + } + body, err := appsrv.FetchJSON(req) if err != nil { return nil, err @@ -59,6 +83,7 @@ func FetchSchedInfo(req *http.Request) (*SchedInfo, error) { input = models.ApplySchedPolicies(input) data := NewSchedInfo(input) + data.UserCred = token domainId := data.Domain for _, net := range data.Networks { diff --git a/pkg/scheduler/cache/candidate/base.go b/pkg/scheduler/cache/candidate/base.go index bad028d718..5619f87b4f 100644 --- a/pkg/scheduler/cache/candidate/base.go +++ b/pkg/scheduler/cache/candidate/base.go @@ -98,6 +98,10 @@ func (b baseHostGetter) IsPublic() bool { return account.ShareMode == computeapi.CLOUD_ACCOUNT_SHARE_MODE_SYSTEM*/ } +func (b baseHostGetter) KeywordPlural() string { + return b.h.KeywordPlural() +} + func (b baseHostGetter) DomainId() string { return b.h.DomainId } diff --git a/pkg/scheduler/core/types.go b/pkg/scheduler/core/types.go index 71e71d76f1..841e081cc1 100644 --- a/pkg/scheduler/core/types.go +++ b/pkg/scheduler/core/types.go @@ -21,6 +21,7 @@ import ( computeapi "yunion.io/x/onecloud/pkg/apis/compute" schedapi "yunion.io/x/onecloud/pkg/apis/scheduler" + "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/types" "yunion.io/x/onecloud/pkg/compute/baremetal" computemodels "yunion.io/x/onecloud/pkg/compute/models" @@ -112,6 +113,8 @@ type CandidatePropertyGetter interface { GetIsolatedDevice(devID string) *IsolatedDeviceDesc UnusedGpuDevices() []*IsolatedDeviceDesc GetIsolatedDevices() []*IsolatedDeviceDesc + + db.IResource } // Candidater replace host Candidate resource info