mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge branch 'release/2.4.0' of ssh://git.yunion.io/~quxuan/onecloud into release/2.4.0
This commit is contained in:
+35
-123
@@ -1,64 +1,16 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
type DNSRecordOptions struct {
|
||||
A []string `help:"DNS A record" metavar:"A_RECORD" positional:"false"`
|
||||
AAAA []string `help:"DNS AAAA record" metavar:"AAAA_RECORD" positional:"false"`
|
||||
CNAME string `help:"DNS CNAME record" metavar:"CNAME_RECORD" positional:"false"`
|
||||
PTR string `help:"DNS PTR record" metavar:"PTR_RECORD" positional:"false"`
|
||||
|
||||
SRVHost string `help:"(deprecated) DNS SRV record, server of service" metavar:"SRV_RECORD_HOST" positional:"false"`
|
||||
SRVPort int64 `help:"(deprecated) DNS SRV record, port of service" metavar:"SRV_RECORD_PORT" positional:"false"`
|
||||
SRV []string `help:"DNS SRV record, in the format of host:port:weight:priority" metavar:"SRV_RECORD" positional:"false"`
|
||||
}
|
||||
|
||||
func parseDNSRecords(args *DNSRecordOptions, params *jsonutils.JSONDict) {
|
||||
if len(args.A) > 0 || len(args.AAAA) > 0 {
|
||||
for i, a := range args.A {
|
||||
params.Add(jsonutils.NewString(a), fmt.Sprintf("A.%d", i))
|
||||
}
|
||||
for i, a := range args.AAAA {
|
||||
params.Add(jsonutils.NewString(a), fmt.Sprintf("AAAA.%d", i))
|
||||
}
|
||||
} else if len(args.CNAME) > 0 {
|
||||
params.Add(jsonutils.NewString(args.CNAME), "CNAME")
|
||||
} else if len(args.SRV) > 0 || (len(args.SRVHost) > 0 && args.SRVPort > 0) {
|
||||
for i, s := range args.SRV {
|
||||
params.Set(fmt.Sprintf("SRV.%d", i), jsonutils.NewString(s))
|
||||
}
|
||||
// Keep using the original argument passing method in case a
|
||||
// newer climc is used against old service
|
||||
if len(args.SRVHost) > 0 && args.SRVPort > 0 {
|
||||
params.Set("SRV_host", jsonutils.NewString(args.SRVHost))
|
||||
params.Set("SRV_port", jsonutils.NewInt(args.SRVPort))
|
||||
}
|
||||
} else if len(args.PTR) > 0 {
|
||||
params.Add(jsonutils.NewString(args.PTR), "PTR")
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
type DNSListOptions struct {
|
||||
options.BaseListOptions
|
||||
}
|
||||
R(&DNSListOptions{}, "dns-list", "List dns records", func(s *mcclient.ClientSession, suboptions *DNSListOptions) error {
|
||||
var params *jsonutils.JSONDict
|
||||
{
|
||||
var err error
|
||||
params, err = suboptions.BaseListOptions.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
R(&options.DNSListOptions{}, "dns-list", "List dns records", func(s *mcclient.ClientSession, opts *options.DNSListOptions) error {
|
||||
params, err := options.ListStructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.DNSRecords.List(s, params)
|
||||
if err != nil {
|
||||
@@ -68,24 +20,10 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type DNSCreateOptions struct {
|
||||
NAME string `help:"DNS name to create"`
|
||||
TTL int64 `help:"TTL in seconds" positional:"false"`
|
||||
Desc string `help:"Description" metavar:"DESCRIPTION"`
|
||||
DNSRecordOptions
|
||||
}
|
||||
R(&DNSCreateOptions{}, "dns-create", "Create dns record", func(s *mcclient.ClientSession, args *DNSCreateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
parseDNSRecords(&args.DNSRecordOptions, params)
|
||||
if params.Size() == 0 {
|
||||
return fmt.Errorf("No records to create")
|
||||
}
|
||||
params.Add(jsonutils.NewString(args.NAME), "name")
|
||||
if args.TTL > 0 {
|
||||
params.Add(jsonutils.NewInt(args.TTL), "ttl")
|
||||
}
|
||||
if len(args.Desc) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Desc), "description")
|
||||
R(&options.DNSCreateOptions{}, "dns-create", "Create dns record", func(s *mcclient.ClientSession, opts *options.DNSCreateOptions) error {
|
||||
params, err := opts.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rec, e := modules.DNSRecords.Create(s, params)
|
||||
if e != nil {
|
||||
@@ -95,11 +33,8 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type DNSShowOptions struct {
|
||||
ID string `help:"ID of DNS record to show"`
|
||||
}
|
||||
R(&DNSShowOptions{}, "dns-show", "Show details of a dns records", func(s *mcclient.ClientSession, args *DNSShowOptions) error {
|
||||
dns, e := modules.DNSRecords.Get(s, args.ID, nil)
|
||||
R(&options.DNSGetOptions{}, "dns-show", "Show details of a dns records", func(s *mcclient.ClientSession, opts *options.DNSGetOptions) error {
|
||||
dns, e := modules.DNSRecords.Get(s, opts.ID, nil)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
@@ -107,29 +42,12 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type DNSUpdateOptions struct {
|
||||
ID string `help:"ID of DNS record to update"`
|
||||
Name string `help:"Domain name"`
|
||||
TTL int64 `help:"TTL in seconds" positional:"false"`
|
||||
Desc string `help:"Description"`
|
||||
DNSRecordOptions
|
||||
}
|
||||
R(&DNSUpdateOptions{}, "dns-update", "Update details of a dns records", func(s *mcclient.ClientSession, args *DNSUpdateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
if len(args.Name) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Name), "name")
|
||||
R(&options.DNSUpdateOptions{}, "dns-update", "Update details of a dns records", func(s *mcclient.ClientSession, opts *options.DNSUpdateOptions) error {
|
||||
params, err := opts.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(args.Desc) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Desc), "description")
|
||||
}
|
||||
if args.TTL > 0 {
|
||||
params.Add(jsonutils.NewInt(args.TTL), "ttl")
|
||||
}
|
||||
parseDNSRecords(&args.DNSRecordOptions, params)
|
||||
if params.Size() == 0 {
|
||||
return InvalidUpdateError()
|
||||
}
|
||||
dns, e := modules.DNSRecords.Update(s, args.ID, params)
|
||||
dns, e := modules.DNSRecords.Update(s, opts.ID, params)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
@@ -137,8 +55,8 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&DNSShowOptions{}, "dns-delete", "Delete a dns record", func(s *mcclient.ClientSession, args *DNSShowOptions) error {
|
||||
dns, e := modules.DNSRecords.Delete(s, args.ID, nil)
|
||||
R(&options.DNSGetOptions{}, "dns-delete", "Delete a dns record", func(s *mcclient.ClientSession, opts *options.DNSGetOptions) error {
|
||||
dns, e := modules.DNSRecords.Delete(s, opts.ID, nil)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
@@ -146,8 +64,8 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&DNSShowOptions{}, "dns-public", "Make a dns record publicly available", func(s *mcclient.ClientSession, args *DNSShowOptions) error {
|
||||
dns, e := modules.DNSRecords.PerformAction(s, args.ID, "public", nil)
|
||||
R(&options.DNSGetOptions{}, "dns-public", "Make a dns record publicly available", func(s *mcclient.ClientSession, opts *options.DNSGetOptions) error {
|
||||
dns, e := modules.DNSRecords.PerformAction(s, opts.ID, "public", nil)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
@@ -155,8 +73,8 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&DNSShowOptions{}, "dns-private", "Make a dns record private", func(s *mcclient.ClientSession, args *DNSShowOptions) error {
|
||||
dns, e := modules.DNSRecords.PerformAction(s, args.ID, "private", nil)
|
||||
R(&options.DNSGetOptions{}, "dns-private", "Make a dns record private", func(s *mcclient.ClientSession, opts *options.DNSGetOptions) error {
|
||||
dns, e := modules.DNSRecords.PerformAction(s, opts.ID, "private", nil)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
@@ -164,8 +82,8 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&DNSShowOptions{}, "dns-enable", "Enable dns record", func(s *mcclient.ClientSession, args *DNSShowOptions) error {
|
||||
dns, e := modules.DNSRecords.PerformAction(s, args.ID, "enable", nil)
|
||||
R(&options.DNSGetOptions{}, "dns-enable", "Enable dns record", func(s *mcclient.ClientSession, opts *options.DNSGetOptions) error {
|
||||
dns, e := modules.DNSRecords.PerformAction(s, opts.ID, "enable", nil)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
@@ -173,8 +91,8 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&DNSShowOptions{}, "dns-disable", "Disable dns record", func(s *mcclient.ClientSession, args *DNSShowOptions) error {
|
||||
dns, e := modules.DNSRecords.PerformAction(s, args.ID, "disable", nil)
|
||||
R(&options.DNSGetOptions{}, "dns-disable", "Disable dns record", func(s *mcclient.ClientSession, opts *options.DNSGetOptions) error {
|
||||
dns, e := modules.DNSRecords.PerformAction(s, opts.ID, "disable", nil)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
@@ -182,17 +100,12 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type DNSUpdateRecordsOptions struct {
|
||||
ID string `help:"ID of dns record to modify"`
|
||||
DNSRecordOptions
|
||||
}
|
||||
R(&DNSUpdateRecordsOptions{}, "dns-add-records", "Add DNS records to a name", func(s *mcclient.ClientSession, args *DNSUpdateRecordsOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
parseDNSRecords(&args.DNSRecordOptions, params)
|
||||
if params.Size() == 0 {
|
||||
return fmt.Errorf("Nothing to add")
|
||||
R(&options.DNSUpdateRecordsOptions{}, "dns-add-records", "Add DNS records to a name", func(s *mcclient.ClientSession, opts *options.DNSUpdateRecordsOptions) error {
|
||||
params, err := opts.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dns, e := modules.DNSRecords.PerformAction(s, args.ID, "add-records", params)
|
||||
dns, e := modules.DNSRecords.PerformAction(s, opts.ID, "add-records", params)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
@@ -200,13 +113,12 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&DNSUpdateRecordsOptions{}, "dns-remove-records", "Remove DNS records from a name", func(s *mcclient.ClientSession, args *DNSUpdateRecordsOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
parseDNSRecords(&args.DNSRecordOptions, params)
|
||||
if params.Size() == 0 {
|
||||
return fmt.Errorf("Nothing to remove")
|
||||
R(&options.DNSUpdateRecordsOptions{}, "dns-remove-records", "Remove DNS records from a name", func(s *mcclient.ClientSession, opts *options.DNSUpdateRecordsOptions) error {
|
||||
params, err := opts.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dns, e := modules.DNSRecords.PerformAction(s, args.ID, "remove-records", params)
|
||||
dns, e := modules.DNSRecords.PerformAction(s, opts.ID, "remove-records", params)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -111,6 +111,18 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type SchedpoliciesShowOptions struct {
|
||||
ID string `help:"ID or name of the sched policy"`
|
||||
}
|
||||
R(&SchedpoliciesShowOptions{}, "sched-policy-show", "show details of a sched policy", func(s *mcclient.ClientSession, args *SchedpoliciesShowOptions) error {
|
||||
result, err := modules.Schedpolicies.Get(s, args.ID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type SchedpoliciesEvaluateOptions struct {
|
||||
ID string `help:"ID or name of the sched policy"`
|
||||
SERVER string `help:"ID or name of the server"`
|
||||
|
||||
@@ -57,12 +57,16 @@ func (dispatcher *DBModelDispatcher) ContextKeywordPlural() []string {
|
||||
}
|
||||
|
||||
func (dispatcher *DBModelDispatcher) Filter(f appsrv.FilterHandler) appsrv.FilterHandler {
|
||||
return auth.Authenticate(f)
|
||||
if consts.IsRbacEnabled() {
|
||||
return auth.AuthenticateWithDelayDecision(f, true)
|
||||
} else {
|
||||
return auth.Authenticate(f)
|
||||
}
|
||||
}
|
||||
|
||||
func fetchUserCredential(ctx context.Context) mcclient.TokenCredential {
|
||||
token := auth.FetchUserCredential(ctx)
|
||||
if token == nil {
|
||||
if token == nil && !consts.IsRbacEnabled() {
|
||||
log.Fatalf("user token credential not found?")
|
||||
}
|
||||
return token
|
||||
@@ -479,14 +483,14 @@ func listItems(manager IModelManager, ctx context.Context, userCred mcclient.Tok
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
retConut := len(retList)
|
||||
retCount := len(retList)
|
||||
|
||||
// apply customizeFilters
|
||||
retList, err = customizeFilters.DoApply(retList)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
if len(retList) != retConut {
|
||||
if len(retList) != retCount {
|
||||
totalCnt = int64(len(retList))
|
||||
}
|
||||
paginate := false
|
||||
@@ -500,7 +504,7 @@ func listItems(manager IModelManager, ctx context.Context, userCred mcclient.Tok
|
||||
func calculateListResult(data []jsonutils.JSONObject, total, limit, offset int64, paginate bool) *modules.ListResult {
|
||||
if paginate {
|
||||
// do offset first
|
||||
if offset != 0 {
|
||||
if offset > 0 {
|
||||
if total > offset {
|
||||
data = data[offset:]
|
||||
} else {
|
||||
@@ -508,11 +512,13 @@ func calculateListResult(data []jsonutils.JSONObject, total, limit, offset int64
|
||||
}
|
||||
}
|
||||
// do limit
|
||||
if total > limit {
|
||||
if limit > 0 && total > limit {
|
||||
data = data[:limit]
|
||||
}
|
||||
}
|
||||
|
||||
retResult := modules.ListResult{Data: data, Total: int(total), Limit: int(limit), Offset: int(offset)}
|
||||
|
||||
return &retResult
|
||||
}
|
||||
|
||||
@@ -725,7 +731,7 @@ func fetchOwnerProjectId(ctx context.Context, manager IModelManager, userCred mc
|
||||
if consts.IsRbacEnabled() {
|
||||
result := policy.PolicyManager.Allow(true, userCred,
|
||||
consts.GetServiceType(), policy.PolicyDelegation, "")
|
||||
if result == rbacutils.Allow {
|
||||
if result == rbacutils.AdminAllow {
|
||||
isAllow = true
|
||||
}
|
||||
} else {
|
||||
@@ -957,6 +963,34 @@ func (dispatcher *DBModelDispatcher) BatchCreate(ctx context.Context, query json
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func managerPerformCheckCreateData(
|
||||
manager IModelManager,
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
action string,
|
||||
ownerProjId string,
|
||||
query jsonutils.JSONObject,
|
||||
data jsonutils.JSONObject,
|
||||
) (jsonutils.JSONObject, error) {
|
||||
body, err := data.(*jsonutils.JSONDict).Get(manager.Keyword())
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
bodyDict := body.(*jsonutils.JSONDict)
|
||||
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = isClassActionRbacAllowed(manager, userCred, ownerProjId, policy.PolicyActionPerform, action)
|
||||
} else {
|
||||
isAllow = manager.AllowPerformCheckCreateData(ctx, userCred, query, data)
|
||||
}
|
||||
if !isAllow {
|
||||
return nil, httperrors.NewForbiddenError("not allow to perform %s", action)
|
||||
}
|
||||
|
||||
return manager.ValidateCreateData(ctx, userCred, ownerProjId, query, bodyDict)
|
||||
}
|
||||
|
||||
func (dispatcher *DBModelDispatcher) PerformClassAction(ctx context.Context, action string, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
userCred := fetchUserCredential(ctx)
|
||||
|
||||
@@ -969,25 +1003,8 @@ func (dispatcher *DBModelDispatcher) PerformClassAction(ctx context.Context, act
|
||||
defer lockman.ReleaseClass(ctx, dispatcher.modelManager, ownerProjId)
|
||||
|
||||
if action == "check-create-data" {
|
||||
manager := dispatcher.modelManager
|
||||
|
||||
body, err := data.(*jsonutils.JSONDict).Get(manager.Keyword())
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
data := body.(*jsonutils.JSONDict)
|
||||
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = isClassActionRbacAllowed(manager, userCred, ownerProjId, policy.PolicyActionPerform, action)
|
||||
} else {
|
||||
isAllow = manager.AllowPerformCheckCreateData(ctx, userCred, query, data)
|
||||
}
|
||||
if !isAllow {
|
||||
return nil, httperrors.NewForbiddenError("not allow to perform %s", action)
|
||||
}
|
||||
|
||||
return manager.ValidateCreateData(ctx, userCred, ownerProjId, query, data)
|
||||
return managerPerformCheckCreateData(dispatcher.modelManager,
|
||||
ctx, userCred, action, ownerProjId, query, data)
|
||||
}
|
||||
|
||||
managerValue := reflect.ValueOf(dispatcher.modelManager)
|
||||
@@ -1022,8 +1039,8 @@ func objectPerformAction(dispatcher *DBModelDispatcher, model IModel, modelValue
|
||||
|
||||
isGeneral := false
|
||||
funcName := fmt.Sprintf("Perform%s", utils.Kebab2Camel(action, "-"))
|
||||
|
||||
funcValue := modelValue.MethodByName(funcName)
|
||||
|
||||
if !funcValue.IsValid() || funcValue.IsNil() {
|
||||
funcValue = modelValue.MethodByName(generalFuncName)
|
||||
if !funcValue.IsValid() || funcValue.IsNil() {
|
||||
@@ -1057,7 +1074,12 @@ func objectPerformAction(dispatcher *DBModelDispatcher, model IModel, modelValue
|
||||
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = isObjectRbacAllowed(dispatcher.modelManager, model, userCred, policy.PolicyActionPerform, action)
|
||||
if model == nil {
|
||||
ownerProjId, _ := fetchOwnerProjectId(ctx, dispatcher.modelManager, userCred, data)
|
||||
isAllow = isClassActionRbacAllowed(dispatcher.modelManager, userCred, ownerProjId, policy.PolicyActionPerform, action)
|
||||
} else {
|
||||
isAllow = isObjectRbacAllowed(dispatcher.modelManager, model, userCred, policy.PolicyActionPerform, action)
|
||||
}
|
||||
} else {
|
||||
allowFuncName := "Allow" + funcName
|
||||
allowFuncValue := modelValue.MethodByName(allowFuncName)
|
||||
|
||||
@@ -91,7 +91,7 @@ func getQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Request
|
||||
if consts.IsRbacEnabled() {
|
||||
result := policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
|
||||
policy.PolicyDelegation, policy.PolicyActionGet)
|
||||
isAllow = result == rbacutils.Allow
|
||||
isAllow = result == rbacutils.AdminAllow
|
||||
} else {
|
||||
isAllow = userCred.IsSystemAdmin()
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func getQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Request
|
||||
}
|
||||
if consts.IsRbacEnabled() {
|
||||
if policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
|
||||
"quotas", policy.PolicyActionGet) != rbacutils.Allow {
|
||||
"quotas", policy.PolicyActionGet) != rbacutils.AdminAllow {
|
||||
httperrors.ForbiddenError(w, "not allow to query quota")
|
||||
return
|
||||
}
|
||||
@@ -138,7 +138,7 @@ func setQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Request
|
||||
var isAllow bool
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
|
||||
"quotas", policy.PolicyActionUpdate) == rbacutils.Allow
|
||||
"quotas", policy.PolicyActionUpdate) == rbacutils.AdminAllow
|
||||
} else {
|
||||
isAllow = userCred.IsSystemAdmin()
|
||||
}
|
||||
@@ -201,7 +201,7 @@ func checkQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Reque
|
||||
isAllow := false
|
||||
if consts.IsRbacEnabled() {
|
||||
isAllow = policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
|
||||
policy.PolicyDelegation, policy.PolicyActionGet) == rbacutils.Allow
|
||||
policy.PolicyDelegation, policy.PolicyActionGet) == rbacutils.AdminAllow
|
||||
} else {
|
||||
isAllow = userCred.IsSystemAdmin()
|
||||
}
|
||||
@@ -211,7 +211,7 @@ func checkQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Reque
|
||||
}
|
||||
if consts.IsRbacEnabled() {
|
||||
if policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
|
||||
"quotas", policy.PolicyActionGet) != rbacutils.Allow {
|
||||
"quotas", policy.PolicyActionGet) != rbacutils.AdminAllow {
|
||||
httperrors.ForbiddenError(w, "not allow to query quota")
|
||||
return
|
||||
}
|
||||
|
||||
+33
-12
@@ -28,14 +28,22 @@ func isListRbacAllowedInternal(manager IModelManager, resource string, userCred
|
||||
}
|
||||
result := policy.PolicyManager.Allow(false, userCred, consts.GetServiceType(),
|
||||
resource, policy.PolicyActionList)
|
||||
log.Debugf("allow list for non-admin %s %v ownerId: %s", result, requireAdmin, ownerId)
|
||||
if (result == rbacutils.OwnerAllow && !requireAdmin) || (result == rbacutils.Allow && requireAdmin) {
|
||||
|
||||
switch {
|
||||
case result == rbacutils.GuestAllow:
|
||||
return true
|
||||
case result == rbacutils.UserAllow && userCred != nil && userCred.IsValid():
|
||||
return true
|
||||
case result == rbacutils.OwnerAllow && !requireAdmin:
|
||||
return true
|
||||
case result == rbacutils.AdminAllow && requireAdmin:
|
||||
return true
|
||||
}
|
||||
|
||||
result = policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
|
||||
resource, policy.PolicyActionList)
|
||||
log.Debugf("allow list for admin %s %v ownerId: %s", result, requireAdmin, ownerId)
|
||||
return result == rbacutils.Allow
|
||||
|
||||
return result == rbacutils.AdminAllow
|
||||
}
|
||||
|
||||
func isJointListRbacAllowed(manager IJointModelManager, userCred mcclient.TokenCredential, isAdminMode bool) bool {
|
||||
@@ -54,16 +62,23 @@ func isClassActionRbacAllowed(manager IModelManager, userCred mcclient.TokenCred
|
||||
} else {
|
||||
requireAdmin = true
|
||||
}
|
||||
// if !requireAdmin {
|
||||
|
||||
result := policy.PolicyManager.Allow(false, userCred, consts.GetServiceType(),
|
||||
manager.KeywordPlural(), action, extra...)
|
||||
if result == rbacutils.Allow || (!requireAdmin && result == rbacutils.OwnerAllow) {
|
||||
switch {
|
||||
case result == rbacutils.GuestAllow:
|
||||
return true
|
||||
case result == rbacutils.UserAllow && userCred != nil && userCred.IsValid():
|
||||
return true
|
||||
case result == rbacutils.OwnerAllow && !requireAdmin:
|
||||
return true
|
||||
case result == rbacutils.AdminAllow && requireAdmin:
|
||||
return true
|
||||
}
|
||||
// }
|
||||
|
||||
result = policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
|
||||
manager.KeywordPlural(), action, extra...)
|
||||
return result == rbacutils.Allow
|
||||
return result == rbacutils.AdminAllow
|
||||
}
|
||||
|
||||
func isObjectRbacAllowed(manager IModelManager, model IModel, userCred mcclient.TokenCredential, action string, extra ...string) bool {
|
||||
@@ -85,16 +100,22 @@ func isObjectRbacAllowed(manager IModelManager, model IModel, userCred mcclient.
|
||||
requireAdmin = true
|
||||
}
|
||||
|
||||
//if !requireAdmin {
|
||||
result := policy.PolicyManager.Allow(false, userCred, consts.GetServiceType(),
|
||||
manager.KeywordPlural(), action, extra...)
|
||||
if result == rbacutils.Allow || (!requireAdmin && result == rbacutils.OwnerAllow && isOwner) {
|
||||
switch {
|
||||
case result == rbacutils.GuestAllow:
|
||||
return true
|
||||
case result == rbacutils.UserAllow && userCred != nil && userCred.IsValid():
|
||||
return true
|
||||
case result == rbacutils.OwnerAllow && isOwner && !requireAdmin:
|
||||
return true
|
||||
case result == rbacutils.AdminAllow && (requireAdmin || isOwner):
|
||||
return true
|
||||
}
|
||||
//}
|
||||
|
||||
result = policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
|
||||
manager.KeywordPlural(), action, extra...)
|
||||
return result == rbacutils.Allow
|
||||
return result == rbacutils.AdminAllow
|
||||
}
|
||||
|
||||
func isJointObjectRbacAllowed(manager IJointModelManager, item IJointModel, userCred mcclient.TokenCredential, action string, extra ...string) bool {
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
type SSharableVirtualResourceBase struct {
|
||||
SVirtualResourceBase
|
||||
|
||||
IsPublic bool `default:"false" nullable:"false" list:"user"`
|
||||
IsPublic bool `default:"false" nullable:"false" create:"admin_optional" list:"user"`
|
||||
}
|
||||
|
||||
type SSharableVirtualResourceBaseManager struct {
|
||||
|
||||
@@ -89,10 +89,6 @@ func (manager *STaskManager) FilterByName(q *sqlchemy.SQuery, name string) *sqlc
|
||||
return q
|
||||
}
|
||||
|
||||
func (manager *STaskManager) FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery {
|
||||
return q
|
||||
}
|
||||
|
||||
func (manager *STaskManager) AllowPerformAction(ctx context.Context, userCred mcclient.TokenCredential, action string, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return true
|
||||
}
|
||||
@@ -105,6 +101,19 @@ func (manager *STaskManager) PerformAction(ctx context.Context, userCred mcclien
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (manager *STaskManager) GetOwnerId(userCred mcclient.IIdentityProvider) string {
|
||||
return userCred.GetProjectId()
|
||||
}
|
||||
|
||||
func (self *STask) GetOwnerProjectId() string {
|
||||
return self.UserCred.GetProjectId()
|
||||
}
|
||||
|
||||
func (manager *STaskManager) FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery {
|
||||
q = q.Contains("user_cred", owner)
|
||||
return q
|
||||
}
|
||||
|
||||
func (self *STask) AllowGetDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return userCred.IsSystemAdmin() || userCred.GetProjectId() == self.UserCred.GetProjectId()
|
||||
}
|
||||
@@ -414,7 +423,7 @@ func execITask(taskValue reflect.Value, task *STask, odata jsonutils.JSONObject,
|
||||
return
|
||||
}
|
||||
|
||||
log.Debugf("Call %s %s: %s with %s", task.TaskName, stageName, funcValue, params)
|
||||
log.Debugf("Call %s %s", task.TaskName, stageName)
|
||||
funcValue.Call(params)
|
||||
|
||||
// call save request context
|
||||
|
||||
@@ -40,7 +40,7 @@ type Options struct {
|
||||
SslCertfile string `help:"ssl certification file"`
|
||||
SslKeyfile string `help:"ssl certification key file"`
|
||||
|
||||
EnableRbac bool `help:"Switch on Role-based Access Control" default:"false"`
|
||||
EnableRbac bool `help:"Switch on Role-based Access Control" default:"true"`
|
||||
RbacDebug bool `help:"turn on rbac debug log" default:"false"`
|
||||
RbacPolicySyncPeriodSeconds int `help:"policy sync interval in seconds, default 15 minutes" default:"900"`
|
||||
RbacPolicySyncFailedRetrySeconds int `help:"seconds to wait after a failed sync, default 30 seconds" default:"30"`
|
||||
|
||||
@@ -30,8 +30,37 @@ const (
|
||||
var (
|
||||
PolicyManager *SPolicyManager
|
||||
|
||||
PolicyFailedRetryInterval = 15 * time.Second
|
||||
PolicyRefreshInterval = 15 * time.Minute
|
||||
defaultRules = []rbacutils.SRbacRule{
|
||||
{
|
||||
Resource: "tasks",
|
||||
Action: PolicyActionPerform,
|
||||
Result: rbacutils.UserAllow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "zones",
|
||||
Action: PolicyActionList,
|
||||
Result: rbacutils.UserAllow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "zones",
|
||||
Action: PolicyActionGet,
|
||||
Result: rbacutils.UserAllow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "cloudregions",
|
||||
Action: PolicyActionList,
|
||||
Result: rbacutils.UserAllow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "cloudregions",
|
||||
Action: PolicyActionGet,
|
||||
Result: rbacutils.UserAllow,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -41,7 +70,11 @@ func init() {
|
||||
type SPolicyManager struct {
|
||||
policies map[string]rbacutils.SRbacPolicy
|
||||
adminPolicies map[string]rbacutils.SRbacPolicy
|
||||
defaultPolicy *rbacutils.SRbacPolicy
|
||||
lastSync time.Time
|
||||
|
||||
failedRetryInterval time.Duration
|
||||
refreshInterval time.Duration
|
||||
}
|
||||
|
||||
func parseJsonPolicy(obj jsonutils.JSONObject) (string, rbacutils.SRbacPolicy, error) {
|
||||
@@ -114,8 +147,13 @@ func fetchPolicies() (map[string]rbacutils.SRbacPolicy, map[string]rbacutils.SRb
|
||||
|
||||
func (manager *SPolicyManager) start(refreshInterval time.Duration, retryInterval time.Duration) {
|
||||
log.Infof("PolicyManager start to fetch policies ...")
|
||||
PolicyRefreshInterval = refreshInterval
|
||||
PolicyFailedRetryInterval = retryInterval
|
||||
manager.refreshInterval = refreshInterval
|
||||
manager.failedRetryInterval = retryInterval
|
||||
if len(defaultRules) > 0 {
|
||||
manager.defaultPolicy = &rbacutils.SRbacPolicy{
|
||||
Rules: rbacutils.CompactRules(defaultRules),
|
||||
}
|
||||
}
|
||||
manager.sync()
|
||||
}
|
||||
|
||||
@@ -124,13 +162,14 @@ func (manager *SPolicyManager) sync() {
|
||||
policies, adminPolicies, err := fetchPolicies()
|
||||
if err != nil {
|
||||
log.Errorf("sync policy fail %s", err)
|
||||
time.AfterFunc(PolicyFailedRetryInterval, manager.sync)
|
||||
time.AfterFunc(manager.failedRetryInterval, manager.sync)
|
||||
return
|
||||
}
|
||||
manager.policies = policies
|
||||
manager.adminPolicies = adminPolicies
|
||||
|
||||
manager.lastSync = time.Now()
|
||||
time.AfterFunc(PolicyRefreshInterval, manager.sync)
|
||||
time.AfterFunc(manager.refreshInterval, manager.sync)
|
||||
}
|
||||
|
||||
func (manager *SPolicyManager) Allow(isAdmin bool, userCred mcclient.TokenCredential, service string, resource string, action string, extra ...string) rbacutils.TRbacResult {
|
||||
@@ -148,7 +187,13 @@ func (manager *SPolicyManager) Allow(isAdmin bool, userCred mcclient.TokenCreden
|
||||
currentPriv := rbacutils.Deny
|
||||
for _, p := range policies {
|
||||
result := p.Allow(userCredJson, service, resource, action, extra...)
|
||||
if result.IsHigherPrivilege(currentPriv) {
|
||||
if currentPriv.StricterThan(result) {
|
||||
currentPriv = result
|
||||
}
|
||||
}
|
||||
if manager.defaultPolicy != nil {
|
||||
result := manager.defaultPolicy.Allow(userCredJson, service, resource, action, extra...)
|
||||
if currentPriv.StricterThan(result) {
|
||||
currentPriv = result
|
||||
}
|
||||
}
|
||||
@@ -165,8 +210,10 @@ func (manager *SPolicyManager) explainPolicy(userCred mcclient.TokenCredential,
|
||||
}
|
||||
isAdmin, _ := policySeq[0].Bool()
|
||||
if !consts.IsRbacEnabled() {
|
||||
if !isAdmin || (isAdmin && userCred.IsSystemAdmin()) {
|
||||
return rbacutils.Allow, nil
|
||||
if !isAdmin {
|
||||
return rbacutils.OwnerAllow, nil
|
||||
} else if isAdmin && userCred.IsSystemAdmin() {
|
||||
return rbacutils.AdminAllow, nil
|
||||
} else {
|
||||
return rbacutils.Deny, httperrors.NewForbiddenError("operation not allowed")
|
||||
}
|
||||
@@ -210,6 +257,10 @@ func (manager *SPolicyManager) ExplainRpc(userCred mcclient.TokenCredential, par
|
||||
}
|
||||
|
||||
func (manager *SPolicyManager) IsAdminCapable(userCred mcclient.TokenCredential) bool {
|
||||
if !consts.IsRbacEnabled() && userCred.IsSystemAdmin() {
|
||||
return true
|
||||
}
|
||||
|
||||
userCredJson := userCred.ToJson()
|
||||
for _, p := range manager.adminPolicies {
|
||||
match, _ := conditionparser.Eval(p.Condition, userCredJson)
|
||||
|
||||
@@ -251,12 +251,10 @@ type ICloudDisk interface {
|
||||
|
||||
type ICloudSnapshot interface {
|
||||
ICloudResource
|
||||
GetManagerId() string
|
||||
GetSize() int32
|
||||
GetDiskId() string
|
||||
GetDiskType() string
|
||||
Delete() error
|
||||
GetRegionId() string
|
||||
}
|
||||
|
||||
type ICloudVpc interface {
|
||||
|
||||
@@ -504,30 +504,3 @@ func (self *SAliyunGuestDriver) OnGuestDeployTaskDataReceived(ctx context.Contex
|
||||
func (self *SAliyunGuestDriver) AllowReconfigGuest() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SAliyunGuestDriver) RequestDiskSnapshot(ctx context.Context, guest *models.SGuest, task taskman.ITask, snapshotId, diskId string) error {
|
||||
iDisk, _ := models.DiskManager.FetchById(diskId)
|
||||
disk := iDisk.(*models.SDisk)
|
||||
providerDisk, err := disk.GetIDisk()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
iSnapshot, _ := models.SnapshotManager.FetchById(snapshotId)
|
||||
snapshot := iSnapshot.(*models.SSnapshot)
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
cloudSnapshot, err := providerDisk.CreateISnapshot(snapshot.Name, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := jsonutils.NewDict()
|
||||
res.Set("snapshot_id", jsonutils.NewString(cloudSnapshot.GetId()))
|
||||
res.Set("manager_id", jsonutils.NewString(cloudSnapshot.GetManagerId()))
|
||||
cloudRegion, err := models.CloudregionManager.FetchByExternalId("Aliyun/" + cloudSnapshot.GetRegionId())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Cloud region not found? %s", err)
|
||||
}
|
||||
res.Set("cloudregion_id", jsonutils.NewString(cloudRegion.GetId()))
|
||||
return res, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/util/ansible"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
@@ -158,7 +160,7 @@ func (self *SAwsGuestDriver) RequestDeployGuestOnHost(ctx context.Context, guest
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := fetchIVMinfo(desc, iVM, guest.Id, DEFAULT_USER, passwd, action)
|
||||
data := fetchIVMinfo(desc, iVM, guest.Id, ansible.PUBLIC_CLOUD_ANSIBLE_USER, passwd, action)
|
||||
return data, nil
|
||||
})
|
||||
case "rebuild":
|
||||
@@ -210,7 +212,7 @@ func (self *SAwsGuestDriver) RequestDeployGuestOnHost(ctx context.Context, guest
|
||||
}
|
||||
}
|
||||
|
||||
data := fetchIVMinfo(desc, iVM, guest.Id, DEFAULT_USER, passwd, action)
|
||||
data := fetchIVMinfo(desc, iVM, guest.Id, ansible.PUBLIC_CLOUD_ANSIBLE_USER, passwd, action)
|
||||
|
||||
return data, nil
|
||||
})
|
||||
@@ -288,29 +290,6 @@ func (self *SAwsGuestDriver) OnGuestDeployTaskDataReceived(ctx context.Context,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) RequestDiskSnapshot(ctx context.Context, guest *models.SGuest, task taskman.ITask, snapshotId, diskId string) error {
|
||||
iDisk, _ := models.DiskManager.FetchById(diskId)
|
||||
disk := iDisk.(*models.SDisk)
|
||||
providerDisk, err := disk.GetIDisk()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
iSnapshot, _ := models.SnapshotManager.FetchById(snapshotId)
|
||||
snapshot := iSnapshot.(*models.SSnapshot)
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
cloudSnapshot, err := providerDisk.CreateISnapshot(snapshot.Name, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := jsonutils.NewDict()
|
||||
res.Set("snapshot_id", jsonutils.NewString(cloudSnapshot.GetId()))
|
||||
res.Set("manager_id", jsonutils.NewString(cloudSnapshot.GetManagerId()))
|
||||
res.Set("cloudregion_id", jsonutils.NewString(cloudSnapshot.GetRegionId()))
|
||||
return res, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
driver := SAwsGuestDriver{}
|
||||
models.RegisterGuestDriver(&driver)
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/ansible"
|
||||
"yunion.io/x/onecloud/pkg/util/seclib2"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
@@ -22,10 +23,6 @@ type SAzureGuestDriver struct {
|
||||
SManagedVirtualizedGuestDriver
|
||||
}
|
||||
|
||||
const (
|
||||
DEFAULT_USER = "yunion"
|
||||
)
|
||||
|
||||
func init() {
|
||||
driver := SAzureGuestDriver{}
|
||||
models.RegisterGuestDriver(&driver)
|
||||
@@ -169,7 +166,7 @@ func (self *SAzureGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gue
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := fetchIVMinfo(desc, iVM, guest.Id, DEFAULT_USER, passwd, action)
|
||||
data := fetchIVMinfo(desc, iVM, guest.Id, ansible.PUBLIC_CLOUD_ANSIBLE_USER, passwd, action)
|
||||
return data, nil
|
||||
}
|
||||
})
|
||||
@@ -192,7 +189,7 @@ func (self *SAzureGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gue
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := fetchIVMinfo(desc, iVM, guest.Id, DEFAULT_USER, passwd, action)
|
||||
data := fetchIVMinfo(desc, iVM, guest.Id, ansible.PUBLIC_CLOUD_ANSIBLE_USER, passwd, action)
|
||||
return data, nil
|
||||
})
|
||||
} else if action == "rebuild" {
|
||||
@@ -209,7 +206,7 @@ func (self *SAzureGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gue
|
||||
}
|
||||
|
||||
log.Debugf("VMrebuildRoot %s, and status is ready", iVM.GetGlobalId())
|
||||
data := fetchIVMinfo(desc, iVM, guest.Id, DEFAULT_USER, passwd, action)
|
||||
data := fetchIVMinfo(desc, iVM, guest.Id, ansible.PUBLIC_CLOUD_ANSIBLE_USER, passwd, action)
|
||||
|
||||
return data, nil
|
||||
})
|
||||
|
||||
@@ -49,29 +49,29 @@ func (self *SKVMGuestDriver) DoGuestCreateDisksTask(ctx context.Context, guest *
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) RequestDiskSnapshot(ctx context.Context, guest *models.SGuest, task taskman.ITask, snapshotId, diskId string) error {
|
||||
url := fmt.Sprintf("/servers/%s/snapshot", guest.Id)
|
||||
host := guest.GetHost()
|
||||
url := fmt.Sprintf("%s/servers/%s/snapshot", host.ManagerUri, guest.Id)
|
||||
body := jsonutils.NewDict()
|
||||
body.Set("disk_id", jsonutils.NewString(diskId))
|
||||
body.Set("snapshot_id", jsonutils.NewString(snapshotId))
|
||||
header := self.getTaskRequestHeader(task)
|
||||
host := guest.GetHost()
|
||||
_, err := host.Request(task.GetUserCred(), "POST", url, header, body)
|
||||
_, _, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, body, false)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) RequestDeleteSnapshot(ctx context.Context, guest *models.SGuest, task taskman.ITask, params *jsonutils.JSONDict) error {
|
||||
url := fmt.Sprintf("/servers/%s/delete-snapshot", guest.Id)
|
||||
header := self.getTaskRequestHeader(task)
|
||||
host := guest.GetHost()
|
||||
_, err := host.Request(task.GetUserCred(), "POST", url, header, params)
|
||||
url := fmt.Sprintf("%s/servers/%s/delete-snapshot", host.ManagerUri, guest.Id)
|
||||
header := self.getTaskRequestHeader(task)
|
||||
_, _, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, params, false)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) RequestReloadDiskSnapshot(ctx context.Context, guest *models.SGuest, task taskman.ITask, params *jsonutils.JSONDict) error {
|
||||
url := fmt.Sprintf("/servers/%s/reload-disk-snapshot", guest.Id)
|
||||
header := self.getTaskRequestHeader(task)
|
||||
host := guest.GetHost()
|
||||
_, err := host.Request(task.GetUserCred(), "POST", url, header, params)
|
||||
url := fmt.Sprintf("%s/servers/%s/reload-disk-snapshot", host.ManagerUri, guest.Id)
|
||||
header := self.getTaskRequestHeader(task)
|
||||
_, _, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, params, false)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -294,9 +294,9 @@ func (self *SKVMGuestDriver) RequestSyncConfigOnHost(ctx context.Context, guest
|
||||
if fw_only, _ := task.GetParams().Bool("fw_only"); fw_only {
|
||||
body.Add(jsonutils.JSONTrue, "fw_only")
|
||||
}
|
||||
url := fmt.Sprintf("/servers/%s/sync", guest.Id)
|
||||
url := fmt.Sprintf("%s/servers/%s/sync", host.ManagerUri, guest.Id)
|
||||
header := self.getTaskRequestHeader(task)
|
||||
_, err := host.Request(task.GetUserCred(), "POST", url, header, body)
|
||||
_, _, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, header, body, false)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -351,3 +351,24 @@ func (self *SManagedVirtualizedGuestDriver) RequestSyncConfigOnHost(ctx context.
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) RequestDiskSnapshot(ctx context.Context, guest *models.SGuest, task taskman.ITask, snapshotId, diskId string) error {
|
||||
iDisk, _ := models.DiskManager.FetchById(diskId)
|
||||
disk := iDisk.(*models.SDisk)
|
||||
providerDisk, err := disk.GetIDisk()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
iSnapshot, _ := models.SnapshotManager.FetchById(snapshotId)
|
||||
snapshot := iSnapshot.(*models.SSnapshot)
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
cloudSnapshot, err := providerDisk.CreateISnapshot(snapshot.Name, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := jsonutils.NewDict()
|
||||
res.Set("snapshot_id", jsonutils.NewString(cloudSnapshot.GetId()))
|
||||
return res, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -345,30 +345,3 @@ func (self *SQcloudGuestDriver) OnGuestDeployTaskDataReceived(ctx context.Contex
|
||||
func (self *SQcloudGuestDriver) AllowReconfigGuest() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SQcloudGuestDriver) RequestDiskSnapshot(ctx context.Context, guest *models.SGuest, task taskman.ITask, snapshotId, diskId string) error {
|
||||
iDisk, _ := models.DiskManager.FetchById(diskId)
|
||||
disk := iDisk.(*models.SDisk)
|
||||
providerDisk, err := disk.GetIDisk()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
iSnapshot, _ := models.SnapshotManager.FetchById(snapshotId)
|
||||
snapshot := iSnapshot.(*models.SSnapshot)
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
cloudSnapshot, err := providerDisk.CreateISnapshot(snapshot.Name, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := jsonutils.NewDict()
|
||||
res.Set("snapshot_id", jsonutils.NewString(cloudSnapshot.GetId()))
|
||||
res.Set("manager_id", jsonutils.NewString(cloudSnapshot.GetManagerId()))
|
||||
cloudRegion, err := models.CloudregionManager.FetchByExternalId("Aliyun/" + cloudSnapshot.GetRegionId())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Cloud region not found? %s", err)
|
||||
}
|
||||
res.Set("cloudregion_id", jsonutils.NewString(cloudRegion.GetId()))
|
||||
return res, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ func (manager *SCloudaccountManager) ValidateCreateData(ctx context.Context, use
|
||||
if err == cloudprovider.ErrNoSuchProvder {
|
||||
return nil, httperrors.NewResourceNotFoundError("no such provider %s", provider)
|
||||
}
|
||||
return nil, httperrors.NewInvalidCredentialError("invalid cloud account info")
|
||||
return nil, httperrors.NewInputParameterError("invalid cloud account info")
|
||||
}
|
||||
|
||||
return manager.SEnabledStatusStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data)
|
||||
@@ -386,6 +386,7 @@ func (self *SCloudaccount) ImportSubAccount(ctx context.Context, userCred mcclie
|
||||
newCloudprovider.CloudaccountId = self.Id
|
||||
newCloudprovider.Provider = self.Provider
|
||||
newCloudprovider.Enabled = true
|
||||
newCloudprovider.Status = CLOUD_PROVIDER_CONNECTED
|
||||
newCloudprovider.Name = subAccount.Name
|
||||
if !autoCreateProject {
|
||||
newCloudprovider.ProjectId = auth.AdminCredential().GetProjectId()
|
||||
|
||||
@@ -1101,6 +1101,7 @@ type DiskInfo struct {
|
||||
MediumType string
|
||||
Driver string
|
||||
Cache string
|
||||
DiskType string
|
||||
}
|
||||
|
||||
func (self *SDisk) ToDiskInfo() DiskInfo {
|
||||
@@ -1110,6 +1111,7 @@ func (self *SDisk) ToDiskInfo() DiskInfo {
|
||||
MountPoint: self.GetMountPoint(),
|
||||
Format: self.DiskFormat,
|
||||
Size: int64(self.DiskSize),
|
||||
DiskType: self.DiskType,
|
||||
}
|
||||
storage := self.GetStorage()
|
||||
if storage == nil {
|
||||
|
||||
@@ -3915,6 +3915,7 @@ func (self *SGuest) GetSpec(checkStatus bool) *jsonutils.JSONDict {
|
||||
diskSpec.Set("size", jsonutils.NewInt(info.Size))
|
||||
diskSpec.Set("backend", jsonutils.NewString(info.Backend))
|
||||
diskSpec.Set("medium_type", jsonutils.NewString(info.MediumType))
|
||||
diskSpec.Set("disk_type", jsonutils.NewString(info.DiskType))
|
||||
diskSpecs.Add(diskSpec)
|
||||
}
|
||||
spec.Set("disk", diskSpecs)
|
||||
|
||||
@@ -958,7 +958,7 @@ func (manager *SHostManager) getHostsByZone(zone *SZone, provider *SCloudprovide
|
||||
return hosts, nil
|
||||
}
|
||||
|
||||
func (manager *SHostManager) SyncHosts(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, zone *SZone, hosts []cloudprovider.ICloudHost) ([]SHost, []cloudprovider.ICloudHost, compare.SyncResult) {
|
||||
func (manager *SHostManager) SyncHosts(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, zone *SZone, hosts []cloudprovider.ICloudHost, projectSync bool) ([]SHost, []cloudprovider.ICloudHost, compare.SyncResult) {
|
||||
localHosts := make([]SHost, 0)
|
||||
remoteHosts := make([]cloudprovider.ICloudHost, 0)
|
||||
syncResult := compare.SyncResult{}
|
||||
@@ -1002,7 +1002,7 @@ func (manager *SHostManager) SyncHosts(ctx context.Context, userCred mcclient.To
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(commondb); i += 1 {
|
||||
err = commondb[i].syncWithCloudHost(commonext[i])
|
||||
err = commondb[i].syncWithCloudHost(commonext[i], projectSync)
|
||||
if err != nil {
|
||||
syncResult.UpdateError(err)
|
||||
} else {
|
||||
@@ -1025,7 +1025,7 @@ func (manager *SHostManager) SyncHosts(ctx context.Context, userCred mcclient.To
|
||||
return localHosts, remoteHosts, syncResult
|
||||
}
|
||||
|
||||
func (self *SHost) syncWithCloudHost(extHost cloudprovider.ICloudHost) error {
|
||||
func (self *SHost) syncWithCloudHost(extHost cloudprovider.ICloudHost, projectSync bool) error {
|
||||
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
|
||||
self.Name = extHost.GetName()
|
||||
self.Status = extHost.GetStatus()
|
||||
@@ -1052,6 +1052,13 @@ func (self *SHost) syncWithCloudHost(extHost cloudprovider.ICloudHost) error {
|
||||
if err != nil {
|
||||
log.Errorf("syncWithCloudZone error %s", err)
|
||||
}
|
||||
|
||||
if projectSync {
|
||||
if err := HostManager.ClearSchedDescCache(self.Id); err != nil {
|
||||
log.Errorf("ClearSchedDescCache for host %s error %v", self.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1089,6 +1096,11 @@ func (manager *SHostManager) newFromCloudHost(extHost cloudprovider.ICloudHost,
|
||||
log.Errorf("newFromCloudHost fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := manager.ClearSchedDescCache(host.Id); err != nil {
|
||||
log.Errorf("ClearSchedDescCache for host %s error %v", host.Name, err)
|
||||
}
|
||||
|
||||
return &host, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ type SLoadbalancerListenerRule struct {
|
||||
|
||||
func loadbalancerListenerRuleCheckUniqueness(ctx context.Context, lbls *SLoadbalancerListener, domain, path string) error {
|
||||
q := LoadbalancerListenerRuleManager.Query().
|
||||
IsFalse("pending_deleted").
|
||||
Equals("listener_id", lbls.Id).
|
||||
Equals("domain", domain).
|
||||
Equals("path", path)
|
||||
|
||||
@@ -104,6 +104,7 @@ type SLoadbalancerListener struct {
|
||||
|
||||
func (man *SLoadbalancerListenerManager) checkListenerUniqueness(ctx context.Context, lb *SLoadbalancer, listenerType string, listenerPort int64) error {
|
||||
q := man.Query().
|
||||
IsFalse("pending_deleted").
|
||||
Equals("loadbalancer_id", lb.Id).
|
||||
Equals("listener_port", listenerPort)
|
||||
switch listenerType {
|
||||
@@ -260,16 +261,8 @@ func (man *SLoadbalancerListenerManager) ValidateCreateData(ctx context.Context,
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
if aclStatusV.Value == LB_BOOL_ON {
|
||||
acl := aclV.Model.(*SLoadbalancerAcl)
|
||||
if acl == nil {
|
||||
return nil, fmt.Errorf("missing acl")
|
||||
}
|
||||
if len(aclTypeV.Value) == 0 {
|
||||
return nil, fmt.Errorf("missing acl_type")
|
||||
}
|
||||
}
|
||||
if err := man.validateAcl(aclStatusV, aclTypeV, aclV, data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return man.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data)
|
||||
}
|
||||
@@ -287,6 +280,20 @@ func (man *SLoadbalancerListenerManager) checkTypeV(listenerType string) validat
|
||||
return nil
|
||||
}
|
||||
|
||||
func (man *SLoadbalancerListenerManager) validateAcl(aclStatusV *validators.ValidatorStringChoices, aclTypeV *validators.ValidatorStringChoices, aclV *validators.ValidatorModelIdOrName, data *jsonutils.JSONDict) error {
|
||||
if aclStatusV.Value == LB_BOOL_ON {
|
||||
if aclV.Model == nil {
|
||||
return httperrors.NewInputParameterError("missing acl")
|
||||
}
|
||||
if len(aclTypeV.Value) == 0 {
|
||||
return httperrors.NewInputParameterError("missing acl_type")
|
||||
}
|
||||
} else {
|
||||
data.Set("acl_id", jsonutils.NewString(""))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (lblis *SLoadbalancerListener) AllowPerformStatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return lblis.IsOwner(userCred) || userCred.IsSystemAdmin()
|
||||
}
|
||||
@@ -295,7 +302,11 @@ func (lblis *SLoadbalancerListener) ValidateUpdateData(ctx context.Context, user
|
||||
ownerProjId := lblis.GetOwnerProjectId()
|
||||
backendGroupV := validators.NewModelIdOrNameValidator("backend_group", "loadbalancerbackendgroup", ownerProjId)
|
||||
aclStatusV := validators.NewStringChoicesValidator("acl_status", LB_BOOL_VALUES)
|
||||
aclStatusV.Default(lblis.AclStatus)
|
||||
aclTypeV := validators.NewStringChoicesValidator("acl_type", LB_ACL_TYPES)
|
||||
if LB_ACL_TYPES.Has(lblis.AclType) {
|
||||
aclTypeV.Default(lblis.AclType)
|
||||
}
|
||||
aclV := validators.NewModelIdOrNameValidator("acl", "loadbalanceracl", ownerProjId)
|
||||
certV := validators.NewModelIdOrNameValidator("certificate", "loadbalancercertificate", ownerProjId)
|
||||
tlsCipherPolicyV := validators.NewStringChoicesValidator("tls_cipher_policy", LB_TLS_CIPHER_POLICIES).Default(LB_TLS_CIPHER_POLICY_1_2)
|
||||
@@ -344,6 +355,9 @@ func (lblis *SLoadbalancerListener) ValidateUpdateData(ctx context.Context, user
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := LoadbalancerListenerManager.validateAcl(aclStatusV, aclTypeV, aclV, data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{
|
||||
if backendGroup, ok := backendGroupV.Model.(*SLoadbalancerBackendGroup); ok && backendGroup.LoadbalancerId != lblis.LoadbalancerId {
|
||||
return nil, httperrors.NewInputParameterError("backend group %s(%s) belongs to loadbalancer %s instead of %s",
|
||||
|
||||
@@ -145,7 +145,12 @@ func (self *SNetwork) ValidateDeleteCondition(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetTotalNicCount() int {
|
||||
return self.GetGuestnicsCount() + self.GetGroupNicsCount() + self.GetBaremetalNicsCount() + self.GetReservedNicsCount()
|
||||
total := self.GetGuestnicsCount() +
|
||||
self.GetGroupNicsCount() +
|
||||
self.GetBaremetalNicsCount() +
|
||||
self.GetReservedNicsCount() +
|
||||
self.GetLoadbalancerIpsCount()
|
||||
return total
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetGuestnicsCount() int {
|
||||
@@ -164,6 +169,10 @@ func (self *SNetwork) GetReservedNicsCount() int {
|
||||
return ReservedipManager.Query().Equals("network_id", self.Id).Count()
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetLoadbalancerIpsCount() int {
|
||||
return LoadbalancernetworkManager.Query().Equals("network_id", self.Id).Count()
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetUsedAddresses() map[string]bool {
|
||||
used := make(map[string]bool)
|
||||
|
||||
@@ -818,6 +827,7 @@ func (self *SNetwork) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSOND
|
||||
extra.Add(jsonutils.JSONFalse, "exit")
|
||||
}
|
||||
extra.Add(jsonutils.NewInt(int64(self.getIPRange().AddressCount())), "ports")
|
||||
extra.Add(jsonutils.NewInt(int64(self.GetTotalNicCount())), "ports_used")
|
||||
extra.Add(jsonutils.NewInt(int64(self.GetGuestnicsCount())), "vnics")
|
||||
extra.Add(jsonutils.NewInt(int64(self.GetBaremetalNicsCount())), "bm_vnics")
|
||||
extra.Add(jsonutils.NewInt(int64(self.GetGroupNicsCount())), "group_vnics")
|
||||
|
||||
@@ -300,6 +300,7 @@ func (self *SSnapshotManager) CreateSnapshot(ctx context.Context, userCred mccli
|
||||
return nil, err
|
||||
}
|
||||
disk := iDisk.(*SDisk)
|
||||
storage := disk.GetStorage()
|
||||
snapshot := &SSnapshot{}
|
||||
snapshot.SetModelManager(self)
|
||||
snapshot.ProjectId = userCred.GetProjectId()
|
||||
@@ -311,6 +312,8 @@ func (self *SSnapshotManager) CreateSnapshot(ctx context.Context, userCred mccli
|
||||
snapshot.DiskType = disk.DiskType
|
||||
snapshot.Location = location
|
||||
snapshot.CreatedBy = createdBy
|
||||
snapshot.ManagerId = storage.ManagerId
|
||||
snapshot.CloudregionId = storage.getZone().GetRegion().GetId()
|
||||
snapshot.Name = name
|
||||
snapshot.Status = SNAPSHOT_CREATING
|
||||
err = SnapshotManager.TableSpec().Insert(snapshot)
|
||||
@@ -467,13 +470,15 @@ func totalSnapshotCount(projectId string) int {
|
||||
}
|
||||
|
||||
// Only sync snapshot status
|
||||
func (self *SSnapshot) SyncWithCloudSnapshot(userCred mcclient.TokenCredential, ext cloudprovider.ICloudSnapshot, projectId string, projectSync bool) error {
|
||||
func (self *SSnapshot) SyncWithCloudSnapshot(userCred mcclient.TokenCredential, ext cloudprovider.ICloudSnapshot, projectId string, projectSync bool, region *SCloudregion) error {
|
||||
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
|
||||
self.Name = ext.GetName()
|
||||
self.Status = ext.GetStatus()
|
||||
self.DiskType = ext.GetDiskType()
|
||||
if projectSync && len(projectId) > 0 {
|
||||
self.ProjectId = projectId
|
||||
}
|
||||
self.CloudregionId = region.Id
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -482,7 +487,7 @@ func (self *SSnapshot) SyncWithCloudSnapshot(userCred mcclient.TokenCredential,
|
||||
return err
|
||||
}
|
||||
|
||||
func (manager *SSnapshotManager) newFromCloudSnapshot(userCred mcclient.TokenCredential, extSnapshot cloudprovider.ICloudSnapshot, region *SCloudregion, projectId string) (*SSnapshot, error) {
|
||||
func (manager *SSnapshotManager) newFromCloudSnapshot(userCred mcclient.TokenCredential, extSnapshot cloudprovider.ICloudSnapshot, region *SCloudregion, projectId string, provider *SCloudprovider) (*SSnapshot, error) {
|
||||
snapshot := SSnapshot{}
|
||||
snapshot.SetModelManager(manager)
|
||||
|
||||
@@ -500,7 +505,7 @@ func (manager *SSnapshotManager) newFromCloudSnapshot(userCred mcclient.TokenCre
|
||||
|
||||
snapshot.DiskType = extSnapshot.GetDiskType()
|
||||
snapshot.Size = int(extSnapshot.GetSize()) * 1024
|
||||
snapshot.ManagerId = extSnapshot.GetManagerId()
|
||||
snapshot.ManagerId = provider.Id
|
||||
snapshot.CloudregionId = region.Id
|
||||
|
||||
snapshot.ProjectId = userCred.GetProjectId()
|
||||
@@ -555,7 +560,7 @@ func (manager *SSnapshotManager) SyncSnapshots(ctx context.Context, userCred mcc
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(commondb); i += 1 {
|
||||
err = commondb[i].SyncWithCloudSnapshot(userCred, commonext[i], projectId, projectSync)
|
||||
err = commondb[i].SyncWithCloudSnapshot(userCred, commonext[i], projectId, projectSync, region)
|
||||
if err != nil {
|
||||
syncResult.UpdateError(err)
|
||||
} else {
|
||||
@@ -563,7 +568,7 @@ func (manager *SSnapshotManager) SyncSnapshots(ctx context.Context, userCred mcc
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(added); i += 1 {
|
||||
_, err := manager.newFromCloudSnapshot(userCred, added[i], region, projectId)
|
||||
_, err := manager.newFromCloudSnapshot(userCred, added[i], region, projectId, provider)
|
||||
if err != nil {
|
||||
syncResult.AddError(err)
|
||||
} else {
|
||||
|
||||
@@ -37,7 +37,7 @@ func AttachUsageQuery(
|
||||
case "vcenter":
|
||||
q = q.Filter(sqlchemy.Equals(hosts.Field("manager_id"), rangeObjId))
|
||||
case "schedtag":
|
||||
aggHosts := SchedtagManager.Query().SubQuery()
|
||||
aggHosts := HostschedtagManager.Query().SubQuery()
|
||||
q = q.Join(aggHosts, sqlchemy.AND(
|
||||
sqlchemy.Equals(hosts.Field("id"), aggHosts.Field("host_id")),
|
||||
sqlchemy.IsFalse(aggHosts.Field("deleted")))).
|
||||
|
||||
@@ -353,10 +353,6 @@ func (manager *SVpcManager) ValidateCreateData(ctx context.Context, userCred mcc
|
||||
return nil, httperrors.NewInputParameterError("Invalid cloudregion_id")
|
||||
}
|
||||
if region.isManaged() {
|
||||
if region.GetVpcCount() >= MAX_VPC_PER_REGION {
|
||||
return nil, httperrors.NewNotAcceptableError("Too many vpcs per region")
|
||||
}
|
||||
|
||||
managerStr, _ := data.GetString("manager_id")
|
||||
if len(managerStr) == 0 {
|
||||
managerStr, _ = data.GetString("manager")
|
||||
|
||||
@@ -343,7 +343,7 @@ func syncZoneHosts(ctx context.Context, provider *models.SCloudprovider, task *C
|
||||
logSyncFailed(provider, task, msg)
|
||||
return
|
||||
}
|
||||
localHosts, remoteHosts, result := models.HostManager.SyncHosts(ctx, task.UserCred, provider, localZone, hosts)
|
||||
localHosts, remoteHosts, result := models.HostManager.SyncHosts(ctx, task.UserCred, provider, localZone, hosts, syncRange.ProjectSync)
|
||||
msg := result.Result()
|
||||
notes := fmt.Sprintf("SyncHosts for zone %s result: %s", localZone.Name, msg)
|
||||
log.Infof(notes)
|
||||
|
||||
@@ -52,32 +52,25 @@ func (self *GuestDiskSnapshotTask) DoDiskSnapshot(ctx context.Context, guest *mo
|
||||
|
||||
func (self *GuestDiskSnapshotTask) OnDiskSnapshotComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
res := data.(*jsonutils.JSONDict)
|
||||
snapshotId, _ := self.Params.GetString("snapshot_id")
|
||||
iSnapshot, _ := models.SnapshotManager.FetchById(snapshotId)
|
||||
snapshot := iSnapshot.(*models.SSnapshot)
|
||||
if guest.Hypervisor == models.HYPERVISOR_KVM {
|
||||
location, err := res.GetString("location")
|
||||
if err != nil {
|
||||
log.Infof("OnDiskSnapshotComplete called with data no location")
|
||||
return
|
||||
}
|
||||
snapshotId, _ := self.Params.GetString("snapshot_id")
|
||||
iSnapshot, _ := models.SnapshotManager.FetchById(snapshotId)
|
||||
snapshot := iSnapshot.(*models.SSnapshot)
|
||||
models.SnapshotManager.TableSpec().Update(snapshot, func() error {
|
||||
snapshot.Location = location
|
||||
snapshot.Status = models.SNAPSHOT_READY
|
||||
return nil
|
||||
})
|
||||
} else {
|
||||
snapshotId, _ := self.Params.GetString("snapshot_id")
|
||||
iSnapshot, _ := models.SnapshotManager.FetchById(snapshotId)
|
||||
snapshot := iSnapshot.(*models.SSnapshot)
|
||||
extSnapshotId, _ := data.GetString("snapshot_id")
|
||||
cloudregionId, _ := data.GetString("cloudregion_id")
|
||||
managerId, _ := data.GetString("manager_id")
|
||||
models.SnapshotManager.TableSpec().Update(snapshot, func() error {
|
||||
snapshot.CloudregionId = cloudregionId
|
||||
snapshot.ExternalId = extSnapshotId
|
||||
snapshot.Status = models.SNAPSHOT_READY
|
||||
snapshot.ManagerId = managerId
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -48,8 +48,9 @@ func (self *GuestStartTask) startStart(ctx context.Context, guest *models.SGuest
|
||||
self.onStartGuestFailed(ctx, guest, err)
|
||||
} else {
|
||||
if result != nil && jsonutils.QueryBoolean(result, "is_running", false) {
|
||||
guest.SetStatus(self.UserCred, models.VM_RUNNING, "start")
|
||||
self.taskComplete(ctx, guest)
|
||||
self.OnStartComplete(ctx, guest, nil)
|
||||
// guest.SetStatus(self.UserCred, models.VM_RUNNING, "start")
|
||||
// self.taskComplete(ctx, guest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ func ReportGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandalo
|
||||
|
||||
if consts.IsRbacEnabled() {
|
||||
if policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
|
||||
"usages", policy.PolicyActionGet) == rbacutils.Allow {
|
||||
"usages", policy.PolicyActionGet) == rbacutils.AdminAllow {
|
||||
isAdmin = true
|
||||
}
|
||||
} else {
|
||||
|
||||
+9
-76
@@ -7,7 +7,6 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/coredns/coredns/plugin"
|
||||
@@ -26,7 +25,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
ylog "yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
@@ -35,7 +33,6 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
kubeserver "yunion.io/x/onecloud/pkg/mcclient/modules/k8s"
|
||||
"yunion.io/x/onecloud/pkg/util/k8s"
|
||||
)
|
||||
|
||||
@@ -74,14 +71,11 @@ type SRegionDNS struct {
|
||||
AdminUser string
|
||||
AdminPassword string
|
||||
Region string
|
||||
k8sConfigLock *sync.RWMutex
|
||||
k8sConfig string
|
||||
K8sManager *k8s.SKubeClusterManager
|
||||
}
|
||||
|
||||
func New() *SRegionDNS {
|
||||
r := &SRegionDNS{
|
||||
k8sConfigLock: new(sync.RWMutex),
|
||||
}
|
||||
r := &SRegionDNS{}
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -106,6 +100,12 @@ func (r *SRegionDNS) initDB(c *caddy.Controller) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *SRegionDNS) initK8s() {
|
||||
r.initAuth()
|
||||
r.K8sManager = k8s.NewKubeClusterManager(r.Region, 30*time.Second)
|
||||
r.K8sManager.Start()
|
||||
}
|
||||
|
||||
func (r *SRegionDNS) getAdminSession() *mcclient.ClientSession {
|
||||
return auth.GetAdminSession(r.Region, "")
|
||||
}
|
||||
@@ -115,68 +115,6 @@ func (r *SRegionDNS) initAuth() {
|
||||
auth.Init(authInfo, false, true, "", "")
|
||||
}
|
||||
|
||||
func (r *SRegionDNS) getKubeClusterConfig() (string, error) {
|
||||
session := r.getAdminSession()
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.JSONTrue, "directly")
|
||||
ret, err := kubeserver.Clusters.PerformAction(session, "default", "generate-kubeconfig", params)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ret.GetString("kubeconfig")
|
||||
}
|
||||
|
||||
func (r *SRegionDNS) getK8sConfig() string {
|
||||
r.k8sConfigLock.RLock()
|
||||
defer r.k8sConfigLock.RUnlock()
|
||||
return r.k8sConfig
|
||||
}
|
||||
|
||||
func (r *SRegionDNS) setK8sConfig(conf string) {
|
||||
r.k8sConfigLock.Lock()
|
||||
defer r.k8sConfigLock.Unlock()
|
||||
r.k8sConfig = conf
|
||||
}
|
||||
|
||||
func (r *SRegionDNS) isK8sHealthy() bool {
|
||||
if r.getK8sConfig() == "" {
|
||||
return false
|
||||
}
|
||||
cli, err := r.getK8sClient()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
_, err = cli.Discovery().ServerVersion()
|
||||
if err != nil {
|
||||
ylog.Errorf("Discovery k8s version: %v", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *SRegionDNS) startRefreshKubeConfig() {
|
||||
r.initAuth()
|
||||
r.refreshKubeConfig()
|
||||
tick := time.Tick(30 * time.Second)
|
||||
for {
|
||||
select {
|
||||
case <-tick:
|
||||
r.refreshKubeConfig()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *SRegionDNS) refreshKubeConfig() {
|
||||
if r.isK8sHealthy() {
|
||||
return
|
||||
}
|
||||
kubeConfig, err := r.getKubeClusterConfig()
|
||||
if err != nil {
|
||||
ylog.Errorf("Get default k8s config from kube server error: %v", err)
|
||||
}
|
||||
r.setK8sConfig(kubeConfig)
|
||||
}
|
||||
|
||||
func (r *SRegionDNS) ServeDNS(ctx context.Context, w dns.ResponseWriter, rmsg *dns.Msg) (int, error) {
|
||||
var (
|
||||
records []dns.RR
|
||||
@@ -341,12 +279,7 @@ func getK8sServiceBackends(cli *kubernetes.Clientset, req *recordRequest) ([]str
|
||||
}
|
||||
|
||||
func (r *SRegionDNS) getK8sClient() (*kubernetes.Clientset, error) {
|
||||
cli, err := k8s.NewClientByContent([]byte(r.getK8sConfig()), nil)
|
||||
if err != nil {
|
||||
ylog.Warningf("Init kubernetes client error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return cli, nil
|
||||
return r.K8sManager.GetK8sClient()
|
||||
}
|
||||
|
||||
func getK8sServicePods(cli *kubernetes.Clientset, namespace, name string) ([]v1.Pod, error) {
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ func setup(c *caddy.Controller) error {
|
||||
return plugin.Error(PluginName, err)
|
||||
}
|
||||
|
||||
go rDNS.startRefreshKubeConfig()
|
||||
go rDNS.initK8s()
|
||||
|
||||
dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
|
||||
rDNS.Next = next
|
||||
|
||||
@@ -17,25 +17,38 @@ const (
|
||||
)
|
||||
|
||||
func Authenticate(f appsrv.FilterHandler) appsrv.FilterHandler {
|
||||
return AuthenticateWithDelayDecision(f, false)
|
||||
}
|
||||
|
||||
func AuthenticateWithDelayDecision(f appsrv.FilterHandler, delayDecision bool) appsrv.FilterHandler {
|
||||
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
||||
tokenStr := r.Header.Get(mcclient.AUTH_TOKEN)
|
||||
if len(tokenStr) == 0 {
|
||||
httperrors.UnauthorizedError(w, "Unauthorized")
|
||||
return
|
||||
log.Errorf("no auth_token found!")
|
||||
if !delayDecision {
|
||||
httperrors.UnauthorizedError(w, "Unauthorized")
|
||||
return
|
||||
}
|
||||
}
|
||||
token, err := Verify(tokenStr)
|
||||
if err != nil {
|
||||
log.Errorf("Verify token failed: %s", err)
|
||||
httperrors.UnauthorizedError(w, "InvalidToken")
|
||||
return
|
||||
if !delayDecision {
|
||||
httperrors.UnauthorizedError(w, "InvalidToken")
|
||||
return
|
||||
}
|
||||
}
|
||||
ctx = context.WithValue(ctx, AUTH_TOKEN, token)
|
||||
if token != nil {
|
||||
ctx = context.WithValue(ctx, AUTH_TOKEN, token)
|
||||
}
|
||||
|
||||
if taskId := r.Header.Get(mcclient.TASK_ID); taskId != "" {
|
||||
ctx = context.WithValue(ctx, appctx.APP_CONTEXT_KEY_TASK_ID, taskId)
|
||||
}
|
||||
if taskNotifyUrl := r.Header.Get(mcclient.TASK_NOTIFY_URL); taskNotifyUrl != "" {
|
||||
ctx = context.WithValue(ctx, appctx.APP_CONTEXT_KEY_TASK_NOTIFY_URL, taskNotifyUrl)
|
||||
}
|
||||
|
||||
f(ctx, w, r)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
)
|
||||
|
||||
type DNSRecordOptions struct {
|
||||
A []string `help:"DNS A record" metavar:"A_RECORD" positional:"false"`
|
||||
AAAA []string `help:"DNS AAAA record" metavar:"AAAA_RECORD" positional:"false"`
|
||||
CNAME string `help:"DNS CNAME record" metavar:"CNAME_RECORD" positional:"false"`
|
||||
PTR string `help:"DNS PTR record" metavar:"PTR_RECORD" positional:"false"`
|
||||
|
||||
SRVHost string `help:"(deprecated) DNS SRV record, server of service" metavar:"SRV_RECORD_HOST" positional:"false"`
|
||||
SRVPort int64 `help:"(deprecated) DNS SRV record, port of service" metavar:"SRV_RECORD_PORT" positional:"false"`
|
||||
SRV []string `help:"DNS SRV record, in the format of host:port:weight:priority" metavar:"SRV_RECORD" positional:"false"`
|
||||
}
|
||||
|
||||
func parseDNSRecords(opts *DNSRecordOptions, params *jsonutils.JSONDict) {
|
||||
if len(opts.A) > 0 || len(opts.AAAA) > 0 {
|
||||
for i, a := range opts.A {
|
||||
params.Add(jsonutils.NewString(a), fmt.Sprintf("A.%d", i))
|
||||
}
|
||||
for i, a := range opts.AAAA {
|
||||
params.Add(jsonutils.NewString(a), fmt.Sprintf("AAAA.%d", i))
|
||||
}
|
||||
} else if len(opts.CNAME) > 0 {
|
||||
params.Add(jsonutils.NewString(opts.CNAME), "CNAME")
|
||||
} else if len(opts.SRV) > 0 || (len(opts.SRVHost) > 0 && opts.SRVPort > 0) {
|
||||
for i, s := range opts.SRV {
|
||||
params.Set(fmt.Sprintf("SRV.%d", i), jsonutils.NewString(s))
|
||||
}
|
||||
// Keep using the original argument passing method in case a
|
||||
// newer climc is used against old service
|
||||
if len(opts.SRVHost) > 0 && opts.SRVPort > 0 {
|
||||
params.Set("SRV_host", jsonutils.NewString(opts.SRVHost))
|
||||
params.Set("SRV_port", jsonutils.NewInt(opts.SRVPort))
|
||||
}
|
||||
} else if len(opts.PTR) > 0 {
|
||||
params.Add(jsonutils.NewString(opts.PTR), "PTR")
|
||||
}
|
||||
}
|
||||
|
||||
type DNSCreateOptions struct {
|
||||
NAME string `help:"DNS name to create"`
|
||||
TTL int64 `help:"TTL in seconds" positional:"false"`
|
||||
Desc string `help:"Description" json:"description"`
|
||||
IsPublic *bool `help:"Make the newly created record public to all"`
|
||||
|
||||
DNSRecordOptions
|
||||
}
|
||||
|
||||
func (opts *DNSCreateOptions) Params() (*jsonutils.JSONDict, error) {
|
||||
params, err := StructToParams(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parseDNSRecords(&opts.DNSRecordOptions, params)
|
||||
return params, nil
|
||||
}
|
||||
|
||||
type DNSUpdateOptions struct {
|
||||
ID string `help:"ID of DNS record to update" json:"-"`
|
||||
Name string `help:"Domain name"`
|
||||
TTL int64 `help:"TTL in seconds" positional:"false"`
|
||||
Desc string `help:"Description" json:"description"`
|
||||
|
||||
DNSRecordOptions
|
||||
}
|
||||
|
||||
func (opts *DNSUpdateOptions) Params() (*jsonutils.JSONDict, error) {
|
||||
params, err := StructToParams(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parseDNSRecords(&opts.DNSRecordOptions, params)
|
||||
return params, nil
|
||||
}
|
||||
|
||||
type DNSUpdateRecordsOptions struct {
|
||||
ID string `help:"ID of dns record to modify" json:"-"`
|
||||
|
||||
DNSRecordOptions
|
||||
}
|
||||
|
||||
func (opts *DNSUpdateRecordsOptions) Params() (*jsonutils.JSONDict, error) {
|
||||
params := jsonutils.NewDict()
|
||||
parseDNSRecords(&opts.DNSRecordOptions, params)
|
||||
if params.Size() == 0 {
|
||||
return nil, fmt.Errorf("Nothing to add")
|
||||
}
|
||||
return params, nil
|
||||
}
|
||||
|
||||
type DNSListOptions struct {
|
||||
BaseListOptions
|
||||
|
||||
IsPublic string `choices:"0|1"`
|
||||
}
|
||||
|
||||
type DNSGetOptions struct {
|
||||
ID string `help:"ID of DNS record to show" json:"-"`
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/scheduler/algorithm/predicates/guest"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/cache/candidate"
|
||||
@@ -19,11 +20,11 @@ func (p *HostStatusPredicate) Name() string {
|
||||
return "host_status"
|
||||
}
|
||||
|
||||
func (p *HostStatusPredicate) PreExecute(pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) bool {
|
||||
func (p *HostStatusPredicate) PreExecute(cli *kubernetes.Clientset, pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *HostStatusPredicate) Execute(pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) (bool, error) {
|
||||
func (p *HostStatusPredicate) Execute(cli *kubernetes.Clientset, pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) (bool, error) {
|
||||
if host.Status != guest.ExpectedStatus {
|
||||
return false, fmt.Errorf("Host status is %s", host.Status)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/scheduler/cache/candidate"
|
||||
)
|
||||
@@ -16,14 +17,15 @@ func init() {
|
||||
PredicatesManager.Register(
|
||||
&HostStatusPredicate{},
|
||||
&NetworkPredicate{},
|
||||
&LocalVolumePredicate{},
|
||||
)
|
||||
}
|
||||
|
||||
type IPredicate interface {
|
||||
Name() string
|
||||
Clone() IPredicate
|
||||
PreExecute(pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) bool
|
||||
Execute(pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) (bool, error)
|
||||
PreExecute(cli *kubernetes.Clientset, pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) bool
|
||||
Execute(cli *kubernetes.Clientset, pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) (bool, error)
|
||||
}
|
||||
|
||||
type SPredicatesManager struct {
|
||||
@@ -58,13 +60,18 @@ func (man *SPredicatesManager) Has(newPre IPredicate) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (man *SPredicatesManager) DoFilter(pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) (bool, error) {
|
||||
func (man *SPredicatesManager) DoFilter(
|
||||
k8sCli *kubernetes.Clientset,
|
||||
pod *v1.Pod,
|
||||
node *v1.Node,
|
||||
host *candidate.HostDesc,
|
||||
) (bool, error) {
|
||||
for _, pre := range man.predicates {
|
||||
tmpPre := pre.Clone()
|
||||
if !tmpPre.PreExecute(pod, node, host) {
|
||||
if !tmpPre.PreExecute(k8sCli, pod, node, host) {
|
||||
continue
|
||||
}
|
||||
fit, err := tmpPre.Execute(pod, node, host)
|
||||
fit, err := tmpPre.Execute(k8sCli, pod, node, host)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"yunion.io/x/pkg/util/errors"
|
||||
|
||||
@@ -30,7 +31,7 @@ func (p *NetworkPredicate) Name() string {
|
||||
return "network"
|
||||
}
|
||||
|
||||
func (p *NetworkPredicate) PreExecute(pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) bool {
|
||||
func (p *NetworkPredicate) PreExecute(cli *kubernetes.Clientset, pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) bool {
|
||||
net, netCont := pod.Annotations[YUNION_CNI_NETWORK_ANNOTATION]
|
||||
ipAddr, ipCont := pod.Annotations[YUNION_CNI_IPADDR_ANNOTATION]
|
||||
p.network = net
|
||||
@@ -38,7 +39,7 @@ func (p *NetworkPredicate) PreExecute(pod *v1.Pod, node *v1.Node, host *candidat
|
||||
return netCont || ipCont
|
||||
}
|
||||
|
||||
func (p *NetworkPredicate) Execute(pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) (bool, error) {
|
||||
func (p *NetworkPredicate) Execute(cli *kubernetes.Clientset, pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) (bool, error) {
|
||||
hostNets := host.Networks
|
||||
if p.network != "" {
|
||||
err := p.checkByNetworks(hostNets)
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package k8s
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/scheduler/cache/candidate"
|
||||
)
|
||||
|
||||
const (
|
||||
YUNION_CSI_STORAGECLASS = "csi-yunion"
|
||||
)
|
||||
|
||||
type LocalVolumePredicate struct {
|
||||
pvcs []*v1.PersistentVolumeClaim
|
||||
}
|
||||
|
||||
func (p *LocalVolumePredicate) Clone() IPredicate {
|
||||
return &LocalVolumePredicate{}
|
||||
}
|
||||
|
||||
func (p *LocalVolumePredicate) Name() string {
|
||||
return "local-volume"
|
||||
}
|
||||
|
||||
func (p *LocalVolumePredicate) PreExecute(cli *kubernetes.Clientset, pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) bool {
|
||||
if cli == nil {
|
||||
log.Errorf("k8s client is nil, not execute %s filter", p.Name())
|
||||
return false
|
||||
}
|
||||
pvcs := make([]*v1.PersistentVolumeClaim, 0)
|
||||
if pod.Spec.Volumes != nil && len(pod.Spec.Volumes) > 0 {
|
||||
for _, v := range pod.Spec.Volumes {
|
||||
if v.PersistentVolumeClaim == nil {
|
||||
continue
|
||||
}
|
||||
pvcName := v.PersistentVolumeClaim.ClaimName
|
||||
pvc, err := cli.CoreV1().PersistentVolumeClaims(pod.Namespace).Get(pvcName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
log.Warningf("Not found pvc %s for pod %s/%s", pvcName, pod.Namespace, pod.Name)
|
||||
return false
|
||||
}
|
||||
// pvc's StorageClassName must "csi-yunion"
|
||||
if pvc.Spec.StorageClassName != nil && *(pvc.Spec.StorageClassName) != YUNION_CSI_STORAGECLASS {
|
||||
continue
|
||||
}
|
||||
pvcs = append(pvcs, pvc)
|
||||
}
|
||||
}
|
||||
p.pvcs = pvcs
|
||||
return len(pvcs) != 0
|
||||
}
|
||||
|
||||
func (p *LocalVolumePredicate) getPvcRequestSize(pvc *v1.PersistentVolumeClaim) int64 {
|
||||
req := pvc.Spec.Resources.Requests[v1.ResourceStorage]
|
||||
return req.Value()
|
||||
}
|
||||
|
||||
func (p *LocalVolumePredicate) Execute(cli *kubernetes.Clientset, pod *v1.Pod, node *v1.Node, host *candidate.HostDesc) (bool, error) {
|
||||
var reqSize int64
|
||||
for _, pvc := range p.pvcs {
|
||||
pvName := pvc.Spec.VolumeName
|
||||
if pvName != "" {
|
||||
pv, _ := cli.CoreV1().PersistentVolumes().Get(pvName, metav1.GetOptions{})
|
||||
if pv != nil {
|
||||
// PersistentVolume already exists
|
||||
log.V(10).Debugf("PV %s already exists", pv)
|
||||
continue
|
||||
}
|
||||
}
|
||||
reqSize += p.getPvcRequestSize(pvc)
|
||||
}
|
||||
reqSizeMB := reqSize / 1024 / 1024
|
||||
return p.canHostStorageCreateVol(host, reqSizeMB)
|
||||
}
|
||||
|
||||
func (p *LocalVolumePredicate) canHostStorageCreateVol(host *candidate.HostDesc, reqSize int64) (bool, error) {
|
||||
freeSize := host.GetFreeStorageSizeOfType("local", false)
|
||||
log.Debugf("[host %s] PVC request %dMB, free %dMB", host.Name, reqSize, freeSize)
|
||||
if freeSize > reqSize {
|
||||
return true, nil
|
||||
}
|
||||
return false, fmt.Errorf("Out of local storage for volume: %d/%d (request/free)MB", reqSize, freeSize)
|
||||
}
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"k8s.io/api/core/v1"
|
||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api/v1"
|
||||
|
||||
"yunion.io/x/log"
|
||||
|
||||
k8spredicates "yunion.io/x/onecloud/pkg/scheduler/algorithm/predicates/k8s"
|
||||
schedman "yunion.io/x/onecloud/pkg/scheduler/manager"
|
||||
)
|
||||
@@ -70,7 +72,11 @@ func doK8sPredicates(pod *v1.Pod, node *v1.Node) (bool, error) {
|
||||
if len(hosts) == 0 {
|
||||
return false, fmt.Errorf("Not found candidate host %s", node.Name)
|
||||
}
|
||||
return k8spredicates.PredicatesManager.DoFilter(pod, node, hosts[0])
|
||||
k8sCli, err := schedman.GetK8sClient()
|
||||
if err != nil {
|
||||
log.Warningf("Get k8s client error: %v, some predicates will not execute", err)
|
||||
}
|
||||
return k8spredicates.PredicatesManager.DoFilter(k8sCli, pod, node, hosts[0])
|
||||
}
|
||||
|
||||
func k8sPrioritizeHandler(c *gin.Context) {
|
||||
|
||||
@@ -6,13 +6,18 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
o "yunion.io/x/onecloud/cmd/scheduler/options"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/api"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/cache/candidate"
|
||||
candidatecache "yunion.io/x/onecloud/pkg/scheduler/cache/candidate"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/core"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/data_manager"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/onecloud/pkg/util/k8s"
|
||||
)
|
||||
|
||||
const defaultIgnorePool = true
|
||||
@@ -29,6 +34,7 @@ type SchedulerManager struct {
|
||||
CandidateManager *data_manager.CandidateManager
|
||||
//ReservedPoolManager *data_manager.ReservedPoolManager
|
||||
//NetworkManager *data_manager.NetworkManager
|
||||
KubeClusterManager *k8s.SKubeClusterManager
|
||||
}
|
||||
|
||||
func NewSchedulerManager(stopCh <-chan struct{}) *SchedulerManager {
|
||||
@@ -41,10 +47,19 @@ func NewSchedulerManager(stopCh <-chan struct{}) *SchedulerManager {
|
||||
sm.TaskManager = NewTaskManager(stopCh)
|
||||
//sm.ReservedPoolManager = data_manager.NewReservedPoolManager(stopCh)
|
||||
//sm.NetworkManager = data_manager.NewNetworkManager(sm.DataManager, sm.ReservedPoolManager)
|
||||
sm.KubeClusterManager = k8s.NewKubeClusterManager(o.GetOptions().Region, 30*time.Second)
|
||||
|
||||
return sm
|
||||
}
|
||||
|
||||
func GetScheduleManager() *SchedulerManager {
|
||||
return schedManager
|
||||
}
|
||||
|
||||
func GetK8sClient() (*kubernetes.Clientset, error) {
|
||||
return GetScheduleManager().KubeClusterManager.GetK8sClient()
|
||||
}
|
||||
|
||||
func InitAndStart(stopCh <-chan struct{}) {
|
||||
if schedManager != nil {
|
||||
log.Warningf("Global scheduler already init.")
|
||||
@@ -65,6 +80,7 @@ func (sm *SchedulerManager) start() {
|
||||
sm.CandidateManager.Run,
|
||||
//sm.ReservedPoolManager.Run,
|
||||
//sm.NetworkManager.Run,
|
||||
sm.KubeClusterManager.Start,
|
||||
}
|
||||
for _, f := range startFuncs {
|
||||
go f()
|
||||
|
||||
@@ -51,14 +51,6 @@ func (self *SSnapshot) GetStatus() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetManagerId() string {
|
||||
return self.region.client.providerId
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetRegionId() string {
|
||||
return self.region.GetId()
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetSize() int32 {
|
||||
return self.SourceDiskSize
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package ansible
|
||||
|
||||
const (
|
||||
PUBLIC_CLOUD_ANSIBLE_USER = "yunionroot"
|
||||
PUBLIC_CLOUD_ANSIBLE_USER = "cloudroot"
|
||||
)
|
||||
|
||||
+116
-29
@@ -106,8 +106,10 @@ func (self *SAzureClient) getDefaultClient() (*autorest.Client, error) {
|
||||
return nil, err
|
||||
}
|
||||
client.Authorizer = authorizer
|
||||
// client.RequestInspector = LogRequest()
|
||||
// client.ResponseInspector = LogResponse()
|
||||
if DEBUG {
|
||||
client.RequestInspector = LogRequest()
|
||||
client.ResponseInspector = LogResponse()
|
||||
}
|
||||
return &client, nil
|
||||
}
|
||||
|
||||
@@ -116,7 +118,7 @@ func (self *SAzureClient) jsonRequest(method, url string, body string) (jsonutil
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return jsonRequest(cli, method, self.domain, url, body)
|
||||
return jsonRequest(cli, method, self.domain, url, self.subscriptionId, body)
|
||||
}
|
||||
|
||||
func (self *SAzureClient) Get(resourceId string, params []string, retVal interface{}) error {
|
||||
@@ -131,7 +133,7 @@ func (self *SAzureClient) Get(resourceId string, params []string, retVal interfa
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
body, err := jsonRequest(cli, "GET", self.domain, path, "")
|
||||
body, err := jsonRequest(cli, "GET", self.domain, path, self.subscriptionId, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -151,7 +153,7 @@ func (self *SAzureClient) ListVmSizes(location string) (jsonutils.JSONObject, er
|
||||
return nil, fmt.Errorf("need subscription id")
|
||||
}
|
||||
url := fmt.Sprintf("/subscriptions/%s/providers/Microsoft.Compute/locations/%s/vmSizes", self.subscriptionId, location)
|
||||
return jsonRequest(cli, "GET", self.domain, url, "")
|
||||
return jsonRequest(cli, "GET", self.domain, url, self.subscriptionId, "")
|
||||
}
|
||||
|
||||
func (self *SAzureClient) ListClassicDisks() (jsonutils.JSONObject, error) {
|
||||
@@ -163,7 +165,7 @@ func (self *SAzureClient) ListClassicDisks() (jsonutils.JSONObject, error) {
|
||||
return nil, fmt.Errorf("need subscription id")
|
||||
}
|
||||
url := fmt.Sprintf("/subscriptions/%s/services/disks", self.subscriptionId)
|
||||
return jsonRequest(cli, "GET", self.domain, url, "")
|
||||
return jsonRequest(cli, "GET", self.domain, url, self.subscriptionId, "")
|
||||
}
|
||||
|
||||
func (self *SAzureClient) ListAll(resourceType string, retVal interface{}) error {
|
||||
@@ -178,7 +180,7 @@ func (self *SAzureClient) ListAll(resourceType string, retVal interface{}) error
|
||||
if len(resourceType) > 0 {
|
||||
url += fmt.Sprintf("/providers/%s", resourceType)
|
||||
}
|
||||
body, err := jsonRequest(cli, "GET", self.domain, url, "")
|
||||
body, err := jsonRequest(cli, "GET", self.domain, url, self.subscriptionId, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -193,7 +195,7 @@ func (self *SAzureClient) ListSubscriptions() (jsonutils.JSONObject, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return jsonRequest(cli, "GET", self.domain, "/subscriptions", "")
|
||||
return jsonRequest(cli, "GET", self.domain, "/subscriptions", self.subscriptionId, "")
|
||||
}
|
||||
|
||||
func (self *SAzureClient) List(golbalResource string, retVal interface{}) error {
|
||||
@@ -208,7 +210,7 @@ func (self *SAzureClient) List(golbalResource string, retVal interface{}) error
|
||||
if len(self.subscriptionId) > 0 && len(golbalResource) > 0 {
|
||||
url += fmt.Sprintf("/%s", golbalResource)
|
||||
}
|
||||
body, err := jsonRequest(cli, "GET", self.domain, url, "")
|
||||
body, err := jsonRequest(cli, "GET", self.domain, url, self.subscriptionId, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -224,7 +226,7 @@ func (self *SAzureClient) ListByTypeWithResourceGroup(resourceGroupName string,
|
||||
return fmt.Errorf("Missing subscription Info")
|
||||
}
|
||||
url := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/%s", self.subscriptionId, resourceGroupName, Type)
|
||||
body, err := jsonRequest(cli, "GET", self.domain, url, "")
|
||||
body, err := jsonRequest(cli, "GET", self.domain, url, self.subscriptionId, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -236,7 +238,7 @@ func (self *SAzureClient) Delete(resourceId string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = jsonRequest(cli, "DELETE", self.domain, resourceId, "")
|
||||
_, err = jsonRequest(cli, "DELETE", self.domain, resourceId, self.subscriptionId, "")
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -246,7 +248,7 @@ func (self *SAzureClient) PerformAction(resourceId string, action string, body s
|
||||
return nil, err
|
||||
}
|
||||
url := fmt.Sprintf("%s/%s", resourceId, action)
|
||||
return jsonRequest(cli, "POST", self.domain, url, body)
|
||||
return jsonRequest(cli, "POST", self.domain, url, self.subscriptionId, body)
|
||||
}
|
||||
|
||||
func (self *SAzureClient) fetchResourceGroup(cli *autorest.Client, location string) error {
|
||||
@@ -261,7 +263,7 @@ func (self *SAzureClient) fetchResourceGroup(cli *autorest.Client, location stri
|
||||
if len(self.ressourceGroups) == 0 {
|
||||
//Create Default resourceGroup
|
||||
_url := fmt.Sprintf("/subscriptions/%s/resourcegroups/Default", self.subscriptionId)
|
||||
body, err := jsonRequest(cli, "PUT", self.domain, _url, fmt.Sprintf(`{"name": "Default", "location": "%s"}`, location))
|
||||
body, err := jsonRequest(cli, "PUT", self.domain, _url, self.subscriptionId, fmt.Sprintf(`{"name": "Default", "location": "%s"}`, location))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -280,13 +282,25 @@ func (self *SAzureClient) checkParams(body jsonutils.JSONObject, params []string
|
||||
for i := 0; i < len(params); i++ {
|
||||
data, err := body.GetString(params[i])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Missing %s params")
|
||||
return nil, fmt.Errorf("Missing %s params", params[i])
|
||||
}
|
||||
result[params[i]] = data
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type AzureErrorDetail struct {
|
||||
Code string `json:"code,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Target string `json:"target,omitempty"`
|
||||
}
|
||||
|
||||
type AzureError struct {
|
||||
Code string `json:"code,omitempty"`
|
||||
Details []AzureErrorDetail `json:"details,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
func (self *SAzureClient) Create(body jsonutils.JSONObject, retVal interface{}) error {
|
||||
cli, err := self.getDefaultClient()
|
||||
if err != nil {
|
||||
@@ -307,11 +321,14 @@ func (self *SAzureClient) Create(body jsonutils.JSONObject, retVal interface{})
|
||||
return fmt.Errorf("Create Default resourceGroup error?")
|
||||
}
|
||||
url := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/%s/%s", self.subscriptionId, self.ressourceGroups[0].Name, params["type"], params["name"])
|
||||
result, err := jsonRequest(cli, "PUT", self.domain, url, body.String())
|
||||
result, err := jsonRequest(cli, "PUT", self.domain, url, self.subscriptionId, body.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return result.Unmarshal(retVal)
|
||||
if retVal != nil {
|
||||
return result.Unmarshal(retVal)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAzureClient) CheckNameAvailability(Type string, body string) (jsonutils.JSONObject, error) {
|
||||
@@ -323,7 +340,7 @@ func (self *SAzureClient) CheckNameAvailability(Type string, body string) (jsonu
|
||||
return nil, fmt.Errorf("Missing subscription ID")
|
||||
}
|
||||
url := fmt.Sprintf("/subscriptions/%s/providers/%s/checkNameAvailability", self.subscriptionId, Type)
|
||||
return jsonRequest(cli, "POST", self.domain, url, body)
|
||||
return jsonRequest(cli, "POST", self.domain, url, self.subscriptionId, body)
|
||||
}
|
||||
|
||||
func (self *SAzureClient) Update(body jsonutils.JSONObject, retVal interface{}) error {
|
||||
@@ -332,7 +349,7 @@ func (self *SAzureClient) Update(body jsonutils.JSONObject, retVal interface{})
|
||||
return err
|
||||
}
|
||||
url, err := body.GetString("id")
|
||||
result, err := jsonRequest(cli, "PUT", self.domain, url, body.String())
|
||||
result, err := jsonRequest(cli, "PUT", self.domain, url, self.subscriptionId, body.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -342,8 +359,86 @@ func (self *SAzureClient) Update(body jsonutils.JSONObject, retVal interface{})
|
||||
return nil
|
||||
}
|
||||
|
||||
func jsonRequest(client *autorest.Client, method, domain, baseUrl string, body string) (jsonutils.JSONObject, error) {
|
||||
return _jsonRequest(client, method, domain, baseUrl, body)
|
||||
func waitRegisterComplete(client *autorest.Client, domain, subscriptionId string, serviceType string) error {
|
||||
for i := 1; i < 10; i++ {
|
||||
result, err := _jsonRequest(client, "GET", domain, fmt.Sprintf("/subscriptions/%s/providers", subscriptionId), "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
value, err := result.GetArray("value")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, v := range value {
|
||||
namespace, _ := v.GetString("namespace")
|
||||
if namespace == serviceType {
|
||||
state, _ := v.GetString("registrationState")
|
||||
if state == "Registered" {
|
||||
return nil
|
||||
}
|
||||
log.Debugf("service %s state %s waite %d second ...", serviceType, state, i*10)
|
||||
}
|
||||
}
|
||||
time.Sleep(time.Second * time.Duration(i*10))
|
||||
}
|
||||
return fmt.Errorf("wait service %s register timeout", serviceType)
|
||||
}
|
||||
|
||||
func registerService(client *autorest.Client, domain, subscriptionId string, serviceType string) error {
|
||||
registryUrl := fmt.Sprintf("/subscriptions/%s/providers/%s/register", subscriptionId, serviceType)
|
||||
result, err := _jsonRequest(client, "POST", domain, registryUrl, "")
|
||||
if err != nil || result.Contains("error") {
|
||||
return fmt.Errorf("failed to register %s service", serviceType)
|
||||
}
|
||||
if state, _ := result.GetString("registrationState"); state == "Registered" {
|
||||
return nil
|
||||
}
|
||||
return waitRegisterComplete(client, domain, subscriptionId, serviceType)
|
||||
}
|
||||
|
||||
func recoverFromError(client *autorest.Client, domain, subscriptionId string, azureErr AzureError) bool {
|
||||
switch azureErr.Code {
|
||||
case "SubscriptionNotRegistered":
|
||||
services := []string{"Microsoft.Network"}
|
||||
for _, service := range services {
|
||||
if err := registerService(client, domain, subscriptionId, service); err != nil {
|
||||
log.Errorf("register %s error: %v", service, err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case "MissingSubscriptionRegistration":
|
||||
for _, detail := range azureErr.Details {
|
||||
log.Errorf("The subscription is not registered to use namespace '%s', try register it", detail.Target)
|
||||
if err := registerService(client, domain, subscriptionId, detail.Target); err != nil {
|
||||
log.Errorf("register %s error: %v", detail.Target, err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func jsonRequest(client *autorest.Client, method, domain, baseUrl string, subscriptionId string, body string) (jsonutils.JSONObject, error) {
|
||||
result, err := _jsonRequest(client, method, domain, baseUrl, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if result.Contains("error") {
|
||||
azureError := AzureError{}
|
||||
if err := result.Unmarshal(&azureError, "error"); err != nil {
|
||||
return nil, fmt.Errorf(result.String())
|
||||
}
|
||||
if recoverFromError(client, domain, subscriptionId, azureError) {
|
||||
return _jsonRequest(client, method, domain, baseUrl, body)
|
||||
}
|
||||
log.Errorf("Azure %s request: %s \nbody: %s error: %v", method, baseUrl, body, result.String())
|
||||
return nil, fmt.Errorf(result.String())
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func waitForComplatetion(client *autorest.Client, req *http.Request, resp *http.Response, timeout time.Duration) (jsonutils.JSONObject, error) {
|
||||
@@ -470,15 +565,7 @@ func _jsonRequest(client *autorest.Client, method, domain, baseURL, body string)
|
||||
return nil, err
|
||||
}
|
||||
_data := strings.Replace(string(data), "\r", "", -1)
|
||||
result, err = jsonutils.Parse([]byte(_data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if result.Contains("error") {
|
||||
log.Errorf("Azure %s request: %s \nbody: %s error: %v", req.Method, req.URL.String(), body, result.String())
|
||||
return nil, fmt.Errorf(result.String())
|
||||
}
|
||||
return result, nil
|
||||
return jsonutils.Parse([]byte(_data))
|
||||
}
|
||||
|
||||
func (self *SAzureClient) UpdateAccount(tenantId, secret, envName string) error {
|
||||
|
||||
@@ -13,10 +13,6 @@ type SClassicHost struct {
|
||||
zone *SZone
|
||||
}
|
||||
|
||||
const (
|
||||
DEFAULT_USER = "yunion"
|
||||
)
|
||||
|
||||
func (self *SClassicHost) GetMetadata() *jsonutils.JSONDict {
|
||||
return nil
|
||||
}
|
||||
@@ -26,7 +22,7 @@ func (self *SClassicHost) GetId() string {
|
||||
}
|
||||
|
||||
func (self *SClassicHost) GetName() string {
|
||||
return fmt.Sprintf("%s-classic", self.zone.region.client.subscriptionId)
|
||||
return fmt.Sprintf("%s/%s-classic", self.zone.region.GetGlobalId(), self.zone.region.client.subscriptionId)
|
||||
}
|
||||
|
||||
func (self *SClassicHost) GetGlobalId() string {
|
||||
@@ -73,7 +69,7 @@ func (self *SClassicHost) GetMemSizeMB() int {
|
||||
return 0
|
||||
}
|
||||
func (self *SClassicHost) GetEnabled() bool {
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SClassicHost) GetHostStatus() string {
|
||||
|
||||
@@ -9,6 +9,10 @@ import (
|
||||
"github.com/Azure/go-autorest/autorest"
|
||||
)
|
||||
|
||||
const (
|
||||
DEBUG = false
|
||||
)
|
||||
|
||||
func LogRequest() autorest.PrepareDecorator {
|
||||
return func(p autorest.Preparer) autorest.Preparer {
|
||||
return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) {
|
||||
|
||||
+43
-13
@@ -8,6 +8,7 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/ansible"
|
||||
)
|
||||
|
||||
type SHost struct {
|
||||
@@ -23,7 +24,7 @@ func (self *SHost) GetId() string {
|
||||
}
|
||||
|
||||
func (self *SHost) GetName() string {
|
||||
return fmt.Sprintf("%s", self.zone.region.client.subscriptionId)
|
||||
return fmt.Sprintf("%s/%s", self.zone.region.GetGlobalId(), self.zone.region.client.subscriptionId)
|
||||
}
|
||||
|
||||
func (self *SHost) GetGlobalId() string {
|
||||
@@ -42,18 +43,47 @@ func (self *SHost) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SHost) CreateVM(name string, imgId string, sysDiskSize int, cpu int, memMB int, networkId string, ipAddr string, desc string, passwd string, storageType string, diskSizes []int, publicKey string, secgroupId string, userData string) (cloudprovider.ICloudVM, error) {
|
||||
nicId := ""
|
||||
if net := self.zone.getNetworkById(networkId); net == nil {
|
||||
return nil, fmt.Errorf("invalid network ID %s", networkId)
|
||||
} else if nic, err := self.zone.region.CreateNetworkInterface(fmt.Sprintf("%s-ipconfig", name), ipAddr, net.GetId(), secgroupId); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
nicId = nic.ID
|
||||
}
|
||||
vmId, err := self._createVM(name, imgId, int32(sysDiskSize), cpu, memMB, nicId, ipAddr, desc, passwd, storageType, diskSizes, publicKey, userData)
|
||||
func (self *SHost) searchNetorkInterface(IPAddr string, networkId string, secgroupId string) (*SInstanceNic, error) {
|
||||
interfaces, err := self.zone.region.GetNetworkInterfaces()
|
||||
if err != nil {
|
||||
self.zone.region.DeleteNetworkInterface(nicId)
|
||||
return nil, err
|
||||
}
|
||||
for i, nic := range interfaces {
|
||||
for _, ipConf := range nic.Properties.IPConfigurations {
|
||||
if ipConf.Properties.PrivateIPAddress == IPAddr && networkId == ipConf.Properties.Subnet.ID && ipConf.Properties.PrivateIPAllocationMethod == "Static" {
|
||||
if nic.Properties.NetworkSecurityGroup == nil || nic.Properties.NetworkSecurityGroup.ID != secgroupId {
|
||||
nic.Properties.NetworkSecurityGroup = &SSecurityGroup{ID: secgroupId}
|
||||
if err := self.zone.region.client.Update(jsonutils.Marshal(nic), nil); err != nil {
|
||||
log.Errorf("assign secgroup %s for nic %s failed %d")
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &interfaces[i], nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SHost) CreateVM(name string, imgId string, sysDiskSize int, cpu int, memMB int, networkId string, ipAddr string, desc string, passwd string, storageType string, diskSizes []int, publicKey string, secgroupId string, userData string) (cloudprovider.ICloudVM, error) {
|
||||
net := self.zone.getNetworkById(networkId)
|
||||
if net == nil {
|
||||
return nil, fmt.Errorf("invalid network ID %s", networkId)
|
||||
}
|
||||
nic, err := self.searchNetorkInterface(ipAddr, net.GetId(), secgroupId)
|
||||
if err != nil {
|
||||
if err == cloudprovider.ErrNotFound {
|
||||
nic, err = self.zone.region.CreateNetworkInterface(fmt.Sprintf("%s-ipconfig", name), ipAddr, net.GetId(), secgroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
vmId, err := self._createVM(name, imgId, int32(sysDiskSize), cpu, memMB, nic.ID, ipAddr, desc, passwd, storageType, diskSizes, publicKey, userData)
|
||||
if err != nil {
|
||||
self.zone.region.DeleteNetworkInterface(nic.ID)
|
||||
return nil, err
|
||||
}
|
||||
if vm, err := self.zone.region.GetInstance(vmId); err != nil {
|
||||
@@ -89,7 +119,7 @@ func (self *SHost) _createVM(name string, imgId string, sysDiskSize int32, cpu i
|
||||
},
|
||||
OsProfile: OsProfile{
|
||||
ComputerName: name,
|
||||
AdminUsername: DEFAULT_USER,
|
||||
AdminUsername: ansible.PUBLIC_CLOUD_ANSIBLE_USER,
|
||||
AdminPassword: passwd,
|
||||
CustomData: userData,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package azure
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type SServices struct {
|
||||
Value []SService `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
type SService struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
RegistrationState string `json:"registrationState,omitempty"`
|
||||
ResourceTypes []ResourceType `json:"resourceTypes,omitempty"`
|
||||
}
|
||||
|
||||
type ResourceType struct {
|
||||
ApiVersions []string `json:"apiVersions,omitempty"`
|
||||
Capabilities string `json:"capabilities,omitempty"`
|
||||
Locations []string `json:"locations,omitempty"`
|
||||
ResourceType string `json:"locations,omitempty"`
|
||||
}
|
||||
|
||||
func (self *SRegion) ListServices() ([]SService, error) {
|
||||
services := []SService{}
|
||||
return services, self.client.List("providers", &services)
|
||||
}
|
||||
|
||||
func (self *SRegion) SerciceShow(serviceType string) (*SService, error) {
|
||||
service := SService{}
|
||||
return &service, self.client.Get("providers/"+serviceType, []string{}, &service)
|
||||
}
|
||||
|
||||
func (self *SRegion) serviceOperation(resourceType, operation string) error {
|
||||
services, err := self.ListServices()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, service := range services {
|
||||
if service.Namespace == resourceType {
|
||||
_, err := self.client.jsonRequest("POST", fmt.Sprintf("%s/%s", service.ID, operation), "")
|
||||
return err
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("failed to find namespace: %s", resourceType)
|
||||
}
|
||||
|
||||
func (self *SRegion) ServiceRegister(resourceType string) error {
|
||||
return self.serviceOperation(resourceType, "register")
|
||||
}
|
||||
|
||||
func (self *SRegion) ServiceUnRegister(resourceType string) error {
|
||||
return self.serviceOperation(resourceType, "unregister")
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/azure"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type ServiceListOptions struct {
|
||||
}
|
||||
shellutils.R(&ServiceListOptions{}, "service-list", "List providers", func(cli *azure.SRegion, args *ServiceListOptions) error {
|
||||
services, err := cli.ListServices()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(services, len(services), 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type ServiceOptions struct {
|
||||
NAME string `help:"Name for service register"`
|
||||
}
|
||||
|
||||
shellutils.R(&ServiceOptions{}, "service-register", "Register service", func(cli *azure.SRegion, args *ServiceOptions) error {
|
||||
return cli.ServiceRegister(args.NAME)
|
||||
})
|
||||
|
||||
shellutils.R(&ServiceOptions{}, "service-unregister", "Unregister service", func(cli *azure.SRegion, args *ServiceOptions) error {
|
||||
return cli.ServiceUnRegister(args.NAME)
|
||||
})
|
||||
|
||||
shellutils.R(&ServiceOptions{}, "service-show", "Show service detail", func(cli *azure.SRegion, args *ServiceOptions) error {
|
||||
service, err := cli.SerciceShow(args.NAME)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(service)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
@@ -32,4 +32,23 @@ func init() {
|
||||
printObject(vpc)
|
||||
return nil
|
||||
})
|
||||
|
||||
shellutils.R(&VpcOptions{}, "vpc-delete", "Delete vpc", func(cli *azure.SRegion, args *VpcOptions) error {
|
||||
return cli.DeleteVpc(args.ID)
|
||||
})
|
||||
|
||||
type VpcCreateOptions struct {
|
||||
NAME string `help:"vpc Name"`
|
||||
CIDR string `help:"vpc cidr"`
|
||||
Desc string `help:"vpc description"`
|
||||
}
|
||||
|
||||
shellutils.R(&VpcCreateOptions{}, "vpc-create", "Create vpc", func(cli *azure.SRegion, args *VpcCreateOptions) error {
|
||||
vpc, err := cli.CreateIVpc(args.NAME, args.Desc, args.CIDR)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(vpc)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
+21
-10
@@ -22,8 +22,9 @@ type SSnapshot struct {
|
||||
Name string
|
||||
Location string
|
||||
ManagedBy string
|
||||
Sku SnapshotSku
|
||||
Sku *SnapshotSku
|
||||
Properties DiskProperties
|
||||
Type string
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetId() string {
|
||||
@@ -57,7 +58,23 @@ func (self *SSnapshot) IsEmulated() bool {
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateSnapshot(diskId, snapName, desc string) (*SSnapshot, error) {
|
||||
snapshot := SSnapshot{}
|
||||
disk, err := self.GetDisk(diskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
snapshot := SSnapshot{
|
||||
region: self,
|
||||
Name: snapName,
|
||||
Location: self.Name,
|
||||
Properties: DiskProperties{
|
||||
CreationData: CreationData{
|
||||
CreateOption: "Copy",
|
||||
SourceResourceID: diskId,
|
||||
},
|
||||
DiskSizeGB: disk.Properties.DiskSizeGB,
|
||||
},
|
||||
Type: "Microsoft.Compute/snapshots",
|
||||
}
|
||||
return &snapshot, self.client.Create(jsonutils.Marshal(snapshot), &snapshot)
|
||||
}
|
||||
|
||||
@@ -137,9 +154,11 @@ func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
|
||||
classicSnapshots = append(classicSnapshots, _classicSnapshots...)
|
||||
isnapshots := make([]cloudprovider.ICloudSnapshot, len(snapshots)+len(classicSnapshots))
|
||||
for i := 0; i < len(snapshots); i++ {
|
||||
snapshots[i].region = self
|
||||
isnapshots[i] = &snapshots[i]
|
||||
}
|
||||
for i := 0; i < len(classicSnapshots); i++ {
|
||||
classicSnapshots[i].region = self
|
||||
isnapshots[len(snapshots)+i] = &classicSnapshots[i]
|
||||
}
|
||||
return isnapshots, nil
|
||||
@@ -149,14 +168,6 @@ func (self *SSnapshot) GetDiskId() string {
|
||||
return self.Properties.CreationData.SourceResourceID
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetManagerId() string {
|
||||
return self.region.client.providerId
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetRegionId() string {
|
||||
return self.region.GetId()
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetDiskType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -77,7 +77,11 @@ func (self *SVpc) GetCidrBlock() string {
|
||||
}
|
||||
|
||||
func (self *SVpc) Delete() error {
|
||||
return self.region.client.Delete(self.ID)
|
||||
return self.region.DeleteVpc(self.ID)
|
||||
}
|
||||
|
||||
func (self *SRegion) DeleteVpc(vpcId string) error {
|
||||
return self.client.Delete(vpcId)
|
||||
}
|
||||
|
||||
func (self *SVpc) getSecurityGroups() ([]SSecurityGroup, error) {
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
package k8s
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
kubeserver "yunion.io/x/onecloud/pkg/mcclient/modules/k8s"
|
||||
)
|
||||
|
||||
type SKubeClusterManager struct {
|
||||
k8sConfigLock *sync.RWMutex
|
||||
k8sConfig string
|
||||
interval time.Duration
|
||||
region string
|
||||
}
|
||||
|
||||
func NewKubeClusterManager(region string, interval time.Duration) *SKubeClusterManager {
|
||||
return &SKubeClusterManager{
|
||||
k8sConfigLock: new(sync.RWMutex),
|
||||
interval: interval,
|
||||
region: region,
|
||||
}
|
||||
}
|
||||
|
||||
func (man *SKubeClusterManager) GetK8sConfig() string {
|
||||
man.k8sConfigLock.RLock()
|
||||
defer man.k8sConfigLock.RUnlock()
|
||||
return man.k8sConfig
|
||||
}
|
||||
|
||||
func (man *SKubeClusterManager) GetK8sClient() (*kubernetes.Clientset, error) {
|
||||
cli, err := NewClientByContent([]byte(man.GetK8sConfig()), nil)
|
||||
if err != nil {
|
||||
log.Warningf("Init kubernetes client error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
func (man *SKubeClusterManager) Start() {
|
||||
go man.startRefreshKubeConfig()
|
||||
}
|
||||
|
||||
func (man *SKubeClusterManager) setK8sConfig(conf string) {
|
||||
man.k8sConfigLock.Lock()
|
||||
defer man.k8sConfigLock.Unlock()
|
||||
man.k8sConfig = conf
|
||||
}
|
||||
|
||||
func (man *SKubeClusterManager) isK8sHealthy() bool {
|
||||
if man.GetK8sConfig() == "" {
|
||||
return false
|
||||
}
|
||||
cli, err := man.GetK8sClient()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
_, err = cli.Discovery().ServerVersion()
|
||||
if err != nil {
|
||||
log.Errorf("Discovery k8s version: %v", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (man *SKubeClusterManager) startRefreshKubeConfig() {
|
||||
man.refreshKubeConfig()
|
||||
tick := time.Tick(man.interval)
|
||||
for {
|
||||
select {
|
||||
case <-tick:
|
||||
man.refreshKubeConfig()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (man *SKubeClusterManager) refreshKubeConfig() {
|
||||
if man.isK8sHealthy() {
|
||||
return
|
||||
}
|
||||
kubeConfig, err := man.getKubeClusterConfig()
|
||||
if err != nil {
|
||||
log.Errorf("Get default k8s config from kube server error: %v", err)
|
||||
}
|
||||
man.setK8sConfig(kubeConfig)
|
||||
}
|
||||
|
||||
func (man *SKubeClusterManager) getKubeClusterConfig() (string, error) {
|
||||
session := auth.GetAdminSession(man.region, "v1")
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.JSONTrue, "directly")
|
||||
ret, err := kubeserver.Clusters.PerformAction(session, "default", "generate-kubeconfig", params)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ret.GetString("kubeconfig")
|
||||
}
|
||||
+33
-23
@@ -13,29 +13,29 @@ type TRbacResult string
|
||||
const (
|
||||
WILD_MATCH = "*"
|
||||
|
||||
Allow = TRbacResult("allow")
|
||||
AdminAllow = TRbacResult("allow")
|
||||
OwnerAllow = TRbacResult("owner")
|
||||
UserAllow = TRbacResult("user")
|
||||
GuestAllow = TRbacResult("guest")
|
||||
Deny = TRbacResult("deny")
|
||||
)
|
||||
|
||||
func (result TRbacResult) IsHigherPrivilege(r2 TRbacResult) bool {
|
||||
switch result {
|
||||
case Allow:
|
||||
if r2 == Allow {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
case OwnerAllow:
|
||||
if r2 == Deny {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case Deny:
|
||||
return false
|
||||
var (
|
||||
strictness = map[TRbacResult]int{
|
||||
Deny: 0,
|
||||
AdminAllow: 1,
|
||||
OwnerAllow: 2,
|
||||
UserAllow: 3,
|
||||
GuestAllow: 4,
|
||||
}
|
||||
return false
|
||||
)
|
||||
|
||||
func (r TRbacResult) Strictness() int {
|
||||
return strictness[r]
|
||||
}
|
||||
|
||||
func (r1 TRbacResult) StricterThan(r2 TRbacResult) bool {
|
||||
return r1.Strictness() < r2.Strictness()
|
||||
}
|
||||
|
||||
type SRbacPolicy struct {
|
||||
@@ -79,6 +79,10 @@ func (rule *SRbacRule) contains(rule2 *SRbacRule) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (rule *SRbacRule) stricterThan(r2 *SRbacRule) bool {
|
||||
return rule.Result.StricterThan(r2.Result)
|
||||
}
|
||||
|
||||
func (rule *SRbacRule) match(service string, resource string, action string, extra ...string) (bool, int, int) {
|
||||
matched := 0
|
||||
weight := 0
|
||||
@@ -144,7 +148,9 @@ func (policy *SRbacPolicy) GetMatchRule(service string, resource string, action
|
||||
var matchRule *SRbacRule
|
||||
for i := 0; i < len(policy.Rules); i += 1 {
|
||||
match, matchCnt, weight := policy.Rules[i].match(service, resource, action, extra...)
|
||||
if match && (maxMatchCnt < matchCnt || (maxMatchCnt == matchCnt && minWeight > weight)) {
|
||||
if match && (maxMatchCnt < matchCnt ||
|
||||
(maxMatchCnt == matchCnt && minWeight > weight) ||
|
||||
(maxMatchCnt == matchCnt && minWeight == weight && matchRule.stricterThan(&policy.Rules[i]))) {
|
||||
maxMatchCnt = matchCnt
|
||||
minWeight = weight
|
||||
matchRule = &policy.Rules[i]
|
||||
@@ -153,7 +159,7 @@ func (policy *SRbacPolicy) GetMatchRule(service string, resource string, action
|
||||
return matchRule
|
||||
}
|
||||
|
||||
func compactRules(rules []SRbacRule) []SRbacRule {
|
||||
func CompactRules(rules []SRbacRule) []SRbacRule {
|
||||
output := make([]SRbacRule, 1)
|
||||
output[0] = rules[0]
|
||||
for i := 1; i < len(rules); i += 1 {
|
||||
@@ -190,7 +196,7 @@ func (policy *SRbacPolicy) Decode(policyJson jsonutils.JSONObject) error {
|
||||
return err
|
||||
}
|
||||
|
||||
policy.Rules = compactRules(rules)
|
||||
policy.Rules = CompactRules(rules)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -208,10 +214,14 @@ func decode(rules jsonutils.JSONObject, decodeRule SRbacRule, level int) ([]SRba
|
||||
ruleJsonStr := rules.(*jsonutils.JSONString)
|
||||
ruleStr, _ := ruleJsonStr.GetString()
|
||||
switch ruleStr {
|
||||
case string(Allow):
|
||||
decodeRule.Result = Allow
|
||||
case string(AdminAllow):
|
||||
decodeRule.Result = AdminAllow
|
||||
case string(OwnerAllow):
|
||||
decodeRule.Result = OwnerAllow
|
||||
case string(UserAllow):
|
||||
decodeRule.Result = UserAllow
|
||||
case string(GuestAllow):
|
||||
decodeRule.Result = GuestAllow
|
||||
case string(Deny):
|
||||
decodeRule.Result = Deny
|
||||
default:
|
||||
|
||||
@@ -31,7 +31,7 @@ type SSHtoolSol struct {
|
||||
func getCommand(ctx context.Context, userCred mcclient.TokenCredential, ip string) (string, *BaseCommand, error) {
|
||||
cmd := NewBaseCommand(o.Options.SshToolPath)
|
||||
s := auth.GetAdminSession(o.Options.Region, "v2")
|
||||
key, err := modules.Sshkeypairs.GetById(s, userCred.GetProjectId(), jsonutils.NewDict())
|
||||
key, err := modules.Sshkeypairs.GetById(s, userCred.GetProjectId(), jsonutils.Marshal(map[string]bool{"admin": true}))
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func NewSSHtoolSolCommand(ctx context.Context, userCred mcclient.TokenCredential
|
||||
func (c *SSHtoolSol) GetCommand() *exec.Cmd {
|
||||
if c.BaseCommand != nil {
|
||||
cmd := c.BaseCommand.GetCommand()
|
||||
cmd.Env = append(cmd.Env, "TERM=screen-256color")
|
||||
cmd.Env = append(cmd.Env, "TERM=xterm-256color")
|
||||
return cmd
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -99,7 +99,7 @@ func initSocketHandler(so socketio.Socket, p *session.Pty) {
|
||||
log.Infof("exec: %s", p.Command)
|
||||
args := strings.Split(p.Command, " ")
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
cmd.Env = append(cmd.Env, "TERM=screen-256color")
|
||||
cmd.Env = append(cmd.Env, "TERM=xterm-256color")
|
||||
if _pty, err := pty.Start(cmd); err != nil {
|
||||
so.Emit(OUTPUT_EVENT, err.Error()+"\r\n")
|
||||
log.Errorf("exec error: %v", err)
|
||||
|
||||
Reference in New Issue
Block a user