mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-08-31 01:35:56 +08:00
dynamic schedule support resource type
This commit is contained in:
@@ -114,14 +114,18 @@ func init() {
|
||||
})
|
||||
|
||||
type DynamicSchedtagEvaluateOptions struct {
|
||||
ID string `help:"ID or name of the sched policy"`
|
||||
HOST string `help:"ID or name of the host"`
|
||||
SERVER string `help:"ID or name of the server"`
|
||||
ID string `help:"ID or name of the sched policy"`
|
||||
ResourceType string `help:"Standalone resource type" choices:"host|storage" default:"host"`
|
||||
VirtaulResourceType string `help:"Virtual resource type" choices:"server|disk" default:"server"`
|
||||
STANDALONERES string `help:"ID or name of the standalone resource, e.g. host, storage"`
|
||||
VIRTUALRES string `help:"ID or name of the virtual resource, e.g. server, disk"`
|
||||
}
|
||||
R(&DynamicSchedtagEvaluateOptions{}, "dynamic-schedtag-evaluate", "Evaluate dynamic schedtag condition", func(s *mcclient.ClientSession, args *DynamicSchedtagEvaluateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.HOST), "host")
|
||||
params.Add(jsonutils.NewString(args.SERVER), "server")
|
||||
params.Add(jsonutils.NewString(args.ResourceType), "resource_type")
|
||||
params.Add(jsonutils.NewString(args.VirtaulResourceType), "virtual_resource_type")
|
||||
params.Add(jsonutils.NewString(args.STANDALONERES), "object_id")
|
||||
params.Add(jsonutils.NewString(args.VIRTUALRES), "virtual_object_id")
|
||||
result, err := modules.Dynamicschedtags.PerformAction(s, args.ID, "evaluate", params)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -124,12 +124,14 @@ func init() {
|
||||
})
|
||||
|
||||
type SchedpoliciesEvaluateOptions struct {
|
||||
ID string `help:"ID or name of the sched policy"`
|
||||
SERVER string `help:"ID or name of the server"`
|
||||
ID string `help:"ID or name of the sched policy"`
|
||||
OBJECT string `help:"ID or name of the object"`
|
||||
ResourceType string `help:"Resource type of the object" default:"server" choices:"server|disk" short-token:"t"`
|
||||
}
|
||||
R(&SchedpoliciesEvaluateOptions{}, "sched-policy-evaluate", "Evaluate sched policy", func(s *mcclient.ClientSession, args *SchedpoliciesEvaluateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.SERVER), "server")
|
||||
params.Add(jsonutils.NewString(args.OBJECT), "object")
|
||||
params.Add(jsonutils.NewString(args.ResourceType), "resource_type")
|
||||
result, err := modules.Schedpolicies.PerformAction(s, args.ID, "evaluate", params)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -36,7 +36,7 @@ type NetworkConfig struct {
|
||||
StandbyPortCount int `json:"standby_port_count"`
|
||||
StandbyAddrCount int `json:"standby_addr_count"`
|
||||
|
||||
Project string `json:"project"`
|
||||
Project string `json:"project_id"`
|
||||
Ifname string `json:"ifname"`
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ type ServerConfigs struct {
|
||||
// ResourceType "shared|prepaid|dedicated"`
|
||||
ResourceType string `json:"resource_type"`
|
||||
InstanceType string `json:"instance_type"`
|
||||
Project string `json:"project"`
|
||||
Project string `json:"project_id"`
|
||||
Backup bool `json:"backup"`
|
||||
Count int `json:"count"`
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package scheduler
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
@@ -56,6 +58,13 @@ type ScheduleInput struct {
|
||||
ServerConfig
|
||||
}
|
||||
|
||||
func (input ScheduleInput) ToConditionInput() *jsonutils.JSONDict {
|
||||
ret := input.JSON(input)
|
||||
// old condition compatible
|
||||
ret.Add(jsonutils.NewString(input.Project), "owner_tenant_id")
|
||||
return ret
|
||||
}
|
||||
|
||||
type CandidateDisk struct {
|
||||
Index int `json:"index"`
|
||||
StorageId string `json:"storage_id"`
|
||||
|
||||
@@ -883,6 +883,8 @@ func doCreateItem(manager IModelManager, ctx context.Context, userCred mcclient.
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
// HACK: set data same as dataDict
|
||||
data.(*jsonutils.JSONDict).Update(dataDict)
|
||||
return model, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1702,3 +1702,8 @@ func (self *SDisk) IsDetachable() bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SDisk) GetDynamicConditionInput() *jsonutils.JSONDict {
|
||||
conf := self.ToDiskConfig()
|
||||
return conf.JSON(conf)
|
||||
}
|
||||
|
||||
@@ -3,9 +3,11 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
@@ -13,8 +15,20 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/util/conditionparser"
|
||||
)
|
||||
|
||||
type IDynamicResourceManager interface {
|
||||
db.IModelManager
|
||||
}
|
||||
|
||||
type IDynamicResource interface {
|
||||
db.IModel
|
||||
GetDynamicConditionInput() *jsonutils.JSONDict
|
||||
}
|
||||
|
||||
type SDynamicschedtagManager struct {
|
||||
db.SStandaloneResourceBaseManager
|
||||
|
||||
StandaloneResourcesManager map[string]IDynamicResourceManager
|
||||
VirtualResourcesManager map[string]IDynamicResourceManager
|
||||
}
|
||||
|
||||
var DynamicschedtagManager *SDynamicschedtagManager
|
||||
@@ -27,9 +41,39 @@ func init() {
|
||||
"dynamicschedtag",
|
||||
"dynamicschedtags",
|
||||
),
|
||||
StandaloneResourcesManager: make(map[string]IDynamicResourceManager),
|
||||
VirtualResourcesManager: make(map[string]IDynamicResourceManager),
|
||||
}
|
||||
}
|
||||
|
||||
func (man *SDynamicschedtagManager) bindDynamicResourceManager(
|
||||
store map[string]IDynamicResourceManager,
|
||||
ms ...IDynamicResourceManager) {
|
||||
for _, m := range ms {
|
||||
store[m.Keyword()] = m
|
||||
}
|
||||
}
|
||||
|
||||
func (man *SDynamicschedtagManager) BindStandaloneResourceManager(ms ...IDynamicResourceManager) {
|
||||
man.bindDynamicResourceManager(man.StandaloneResourcesManager, ms...)
|
||||
}
|
||||
|
||||
func (man *SDynamicschedtagManager) BindVirtualResourceManager(ms ...IDynamicResourceManager) {
|
||||
man.bindDynamicResourceManager(man.VirtualResourcesManager, ms...)
|
||||
}
|
||||
|
||||
func (man *SDynamicschedtagManager) InitializeData() error {
|
||||
man.BindStandaloneResourceManager(
|
||||
HostManager,
|
||||
StorageManager,
|
||||
)
|
||||
man.BindVirtualResourceManager(
|
||||
GuestManager,
|
||||
DiskManager,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
// dynamic schedtag is called before scan host candidates, dynamically adding additional schedtag to hosts
|
||||
// condition examples:
|
||||
// host.sys_load > 1.5 || host.mem_used_percent > 0.7 => "high_load"
|
||||
@@ -86,7 +130,8 @@ func validateDynamicSchedtagInputData(data *jsonutils.JSONDict, create bool) err
|
||||
return httperrors.NewGeneralError(err)
|
||||
}
|
||||
}
|
||||
data.Set("schedtag_id", jsonutils.NewString(schedObj.GetId()))
|
||||
schedtag := schedObj.(*SSchedtag)
|
||||
data.Set("schedtag_id", jsonutils.NewString(schedtag.GetId()))
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -126,6 +171,7 @@ func (self *SDynamicschedtag) getMoreColumns(extra *jsonutils.JSONDict) *jsonuti
|
||||
schedtag := self.getSchedtag()
|
||||
if schedtag != nil {
|
||||
extra.Add(jsonutils.NewString(schedtag.GetName()), "schedtag")
|
||||
extra.Add(jsonutils.NewString(schedtag.ResourceType), "resource_type")
|
||||
}
|
||||
return extra
|
||||
}
|
||||
@@ -143,17 +189,17 @@ func (self *SDynamicschedtag) GetExtraDetails(ctx context.Context, userCred mccl
|
||||
return self.getMoreColumns(extra), nil
|
||||
}
|
||||
|
||||
func (manager *SDynamicschedtagManager) GetAllEnabledDynamicSchedtags() []SDynamicschedtag {
|
||||
return manager.getAllEnabledDynamicSchedtags()
|
||||
}
|
||||
|
||||
func (manager *SDynamicschedtagManager) getAllEnabledDynamicSchedtags() []SDynamicschedtag {
|
||||
func (manager *SDynamicschedtagManager) GetEnabledDynamicSchedtagsByResource(resType string) []SDynamicschedtag {
|
||||
rules := make([]SDynamicschedtag, 0)
|
||||
|
||||
q := DynamicschedtagManager.Query().IsTrue("enabled")
|
||||
schedtags := SchedtagManager.Query().SubQuery()
|
||||
q = q.Join(schedtags, sqlchemy.AND(
|
||||
sqlchemy.Equals(q.Field("schedtag_id"), schedtags.Field("id")),
|
||||
sqlchemy.Equals(schedtags.Field("resource_type"), resType)))
|
||||
err := db.FetchModelObjects(manager, q, &rules)
|
||||
if err != nil {
|
||||
log.Errorf("getAllEnabledDynamicSchedtags fail %s", err)
|
||||
log.Errorf("GetEnabledDynamicSchedtagsByResource %s fail %s", resType, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -165,44 +211,46 @@ func (self *SDynamicschedtag) AllowPerformEvaluate(ctx context.Context, userCred
|
||||
}
|
||||
|
||||
func (self *SDynamicschedtag) PerformEvaluate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
serverStr := jsonutils.GetAnyString(data, []string{"server", "server_id", "guest", "guest_id"})
|
||||
serverObj, err := GuestManager.FetchByIdOrName(userCred, serverStr)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError("server %s not found", serverStr)
|
||||
} else {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
objectId := jsonutils.GetAnyString(data, []string{"object", "object_id"})
|
||||
resType := jsonutils.GetAnyString(data, []string{"resource_type"})
|
||||
virtObjId := jsonutils.GetAnyString(data, []string{"virtual_object", "virtual_object_id"})
|
||||
virtType := jsonutils.GetAnyString(data, []string{"virtual_resource_type"})
|
||||
|
||||
objectMan := DynamicschedtagManager.StandaloneResourcesManager[resType]
|
||||
if objectMan == nil {
|
||||
return nil, httperrors.NewResourceNotFoundError("Resource type %s not support", resType)
|
||||
}
|
||||
virtObjectMan := DynamicschedtagManager.VirtualResourcesManager[virtType]
|
||||
if virtObjectMan == nil {
|
||||
return nil, httperrors.NewResourceNotFoundError("Virtual resource type %s not support", virtType)
|
||||
}
|
||||
|
||||
server := serverObj.(*SGuest)
|
||||
srvDesc := server.getSchedDesc()
|
||||
|
||||
hostStr := jsonutils.GetAnyString(data, []string{"host", "host_id"})
|
||||
hostObj, err := HostManager.FetchByIdOrName(userCred, hostStr)
|
||||
object, err := FetchDynamicResourceObject(objectMan, userCred, objectId)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError("host %s not found", serverStr)
|
||||
} else {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
virtObject, err := FetchDynamicResourceObject(virtObjectMan, userCred, virtObjId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
host := hostObj.(*SHost)
|
||||
// TODO: to fill host scheduling information
|
||||
hostDesc := jsonutils.Marshal(host)
|
||||
// TODO: to fill standalone resource scheduling information
|
||||
standaloneDesc := object.GetDynamicConditionInput()
|
||||
virtDesc := virtObject.GetDynamicConditionInput()
|
||||
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(srvDesc.JSON(srvDesc), "server")
|
||||
params.Add(hostDesc, "host")
|
||||
params.Add(standaloneDesc, object.Keyword())
|
||||
params.Add(virtDesc, virtObject.Keyword())
|
||||
|
||||
log.V(10).Debugf("Dynamicschedtag evaluate input: %s", params.PrettyString())
|
||||
|
||||
meet, err := conditionparser.Eval(self.Condition, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := jsonutils.NewDict()
|
||||
result.Add(srvDesc.JSON(srvDesc), "server")
|
||||
result.Add(hostDesc, "host")
|
||||
result.Add(standaloneDesc, object.Keyword())
|
||||
result.Add(virtDesc, virtObject.Keyword())
|
||||
|
||||
if meet {
|
||||
result.Add(jsonutils.JSONTrue, "result")
|
||||
@@ -211,3 +259,19 @@ func (self *SDynamicschedtag) PerformEvaluate(ctx context.Context, userCred mccl
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func FetchDynamicResourceObject(man IDynamicResourceManager, userCred mcclient.TokenCredential, idOrName string) (IDynamicResource, error) {
|
||||
obj, err := man.FetchByIdOrName(userCred, idOrName)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError("%s %s not found", man.Keyword(), idOrName)
|
||||
} else {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
}
|
||||
res, ok := obj.(IDynamicResource)
|
||||
if !ok {
|
||||
return nil, httperrors.NewGeneralError(fmt.Errorf("%s %s not implement IDynamicResource", obj.Keyword(), obj.GetName()))
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@@ -3888,43 +3888,6 @@ func (self *SGuest) getDefaultStorageType() string {
|
||||
return STORAGE_LOCAL
|
||||
}
|
||||
|
||||
func (self *SGuest) getSchedDesc() *schedapi.ScheduleInput {
|
||||
desc := new(schedapi.ScheduleInput)
|
||||
|
||||
desc.Id = self.Id
|
||||
desc.Name = self.Name
|
||||
desc.Memory = self.VmemSize
|
||||
desc.Ncpu = int(self.VcpuCount)
|
||||
|
||||
gds := self.GetDisks()
|
||||
if gds != nil {
|
||||
for i := 0; i < len(gds); i += 1 {
|
||||
conf := new(api.DiskConfig)
|
||||
jsonutils.Marshal(gds[i].ToDiskInfo()).Unmarshal(conf)
|
||||
desc.Disks = append(desc.Disks, conf)
|
||||
}
|
||||
}
|
||||
|
||||
gns, _ := self.GetNetworks("")
|
||||
if gns != nil {
|
||||
for i := 0; i < len(gns); i += 1 {
|
||||
desc.Networks = append(desc.Networks, &api.NetworkConfig{
|
||||
Network: gns[i].NetworkId,
|
||||
Address: gns[i].IpAddr,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(self.HostId) > 0 && regutils.MatchUUID(self.HostId) {
|
||||
desc.HostId = self.HostId
|
||||
}
|
||||
|
||||
desc.Project = self.ProjectId
|
||||
desc.Hypervisor = self.GetHypervisor()
|
||||
|
||||
return desc
|
||||
}
|
||||
|
||||
func (self *SGuest) GetApptags() []string {
|
||||
tagsStr := self.GetMetadata("app_tags", nil)
|
||||
if len(tagsStr) > 0 {
|
||||
@@ -3936,13 +3899,15 @@ func (self *SGuest) GetApptags() []string {
|
||||
func (self *SGuest) ToSchedDesc() *schedapi.ScheduleInput {
|
||||
desc := new(schedapi.ScheduleInput)
|
||||
config := &schedapi.ServerConfig{
|
||||
Name: self.Name,
|
||||
Memory: self.VmemSize,
|
||||
Ncpu: int(self.VcpuCount),
|
||||
Name: self.Name,
|
||||
Memory: self.VmemSize,
|
||||
Ncpu: int(self.VcpuCount),
|
||||
ServerConfigs: new(api.ServerConfigs),
|
||||
}
|
||||
desc.Id = self.Id
|
||||
//self.FillGroupSchedDesc(desc)
|
||||
self.FillDiskSchedDesc(config)
|
||||
self.FillNetSchedDesc(config)
|
||||
self.FillDiskSchedDesc(config.ServerConfigs)
|
||||
self.FillNetSchedDesc(config.ServerConfigs)
|
||||
if len(self.HostId) > 0 && regutils.MatchUUID(self.HostId) {
|
||||
config.HostId = self.HostId
|
||||
}
|
||||
@@ -3970,7 +3935,7 @@ func (self *SGuest) ToSchedDesc() *schedapi.ScheduleInput {
|
||||
}
|
||||
}*/
|
||||
|
||||
func (self *SGuest) FillDiskSchedDesc(desc *schedapi.ServerConfig) {
|
||||
func (self *SGuest) FillDiskSchedDesc(desc *api.ServerConfigs) {
|
||||
guestDisks := make([]SGuestdisk, 0)
|
||||
err := GuestdiskManager.Query().Equals("guest_id", self.Id).All(&guestDisks)
|
||||
if err != nil {
|
||||
@@ -3982,13 +3947,16 @@ func (self *SGuest) FillDiskSchedDesc(desc *schedapi.ServerConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuest) FillNetSchedDesc(desc *schedapi.ServerConfig) {
|
||||
func (self *SGuest) FillNetSchedDesc(desc *api.ServerConfigs) {
|
||||
guestNetworks := make([]SGuestnetwork, 0)
|
||||
err := GuestnetworkManager.Query().Equals("guest_id", self.Id).All(&guestNetworks)
|
||||
if err != nil {
|
||||
log.Errorln("FillNetSchedDesc: %v", err)
|
||||
return
|
||||
}
|
||||
if desc.Networks == nil {
|
||||
desc.Networks = make([]*api.NetworkConfig, 0)
|
||||
}
|
||||
for i := 0; i < len(guestNetworks); i++ {
|
||||
desc.Networks = append(desc.Networks, guestNetworks[i].ToNetworkConfig())
|
||||
}
|
||||
@@ -4040,3 +4008,7 @@ func (guest *SGuest) GetDetailsTasks(ctx context.Context, userCred mcclient.Toke
|
||||
ret.Add(jsonutils.NewArray(objs...), "tasks")
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (guest *SGuest) GetDynamicConditionInput() *jsonutils.JSONDict {
|
||||
return guest.ToSchedDesc().ToConditionInput()
|
||||
}
|
||||
|
||||
@@ -3814,3 +3814,7 @@ func (host *SHost) PerformSetSchedtag(ctx context.Context, userCred mcclient.Tok
|
||||
host.ClearSchedDescCache()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (host *SHost) GetDynamicConditionInput() *jsonutils.JSONDict {
|
||||
return jsonutils.Marshal(host).(*jsonutils.JSONDict)
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ func InitDB() error {
|
||||
LoadbalancerBackendGroupManager,
|
||||
LoadbalancerBackendManager,
|
||||
SchedtagManager,
|
||||
DynamicschedtagManager,
|
||||
} {
|
||||
err := manager.InitializeData()
|
||||
if err != nil {
|
||||
|
||||
@@ -2,11 +2,11 @@ package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
schedapi "yunion.io/x/onecloud/pkg/apis/scheduler"
|
||||
@@ -113,6 +113,7 @@ func (self *SSchedpolicy) getMoreColumns(extra *jsonutils.JSONDict) *jsonutils.J
|
||||
schedtag := self.getSchedtag()
|
||||
if schedtag != nil {
|
||||
extra.Add(jsonutils.NewString(schedtag.GetName()), "schedtag")
|
||||
extra.Add(jsonutils.NewString(schedtag.ResourceType), "resource_type")
|
||||
}
|
||||
return extra
|
||||
}
|
||||
@@ -130,46 +131,58 @@ func (self *SSchedpolicy) GetExtraDetails(ctx context.Context, userCred mcclient
|
||||
return self.getMoreColumns(extra), nil
|
||||
}
|
||||
|
||||
func (manager *SSchedpolicyManager) getAllEnabledPolicies() []SSchedpolicy {
|
||||
func (manager *SSchedpolicyManager) getAllEnabledPoliciesByResource(resType string) []SSchedpolicy {
|
||||
policies := make([]SSchedpolicy, 0)
|
||||
|
||||
q := SchedpolicyManager.Query().IsTrue("enabled")
|
||||
schedtags := SchedtagManager.Query().SubQuery()
|
||||
q = q.Join(schedtags, sqlchemy.AND(
|
||||
sqlchemy.Equals(q.Field("schedtag_id"), schedtags.Field("id")),
|
||||
sqlchemy.Equals(schedtags.Field("resource_type"), resType)))
|
||||
err := db.FetchModelObjects(manager, q, &policies)
|
||||
if err != nil {
|
||||
log.Errorf("getAllEnabledPolicies fail %s", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return policies
|
||||
}
|
||||
|
||||
func (manager *SSchedpolicyManager) getHostEnabledPolicies() []SSchedpolicy {
|
||||
return manager.getAllEnabledPoliciesByResource(HostManager.KeywordPlural())
|
||||
}
|
||||
|
||||
func (manager *SSchedpolicyManager) getStorageEnabledPolicies() []SSchedpolicy {
|
||||
return manager.getAllEnabledPoliciesByResource(StorageManager.KeywordPlural())
|
||||
}
|
||||
|
||||
func (self *SSchedpolicy) AllowPerformEvaluate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsAdminAllowPerform(userCred, self, "evaluate")
|
||||
}
|
||||
|
||||
func (self *SSchedpolicy) PerformEvaluate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
serverStr := jsonutils.GetAnyString(data, []string{"server", "server_id", "guest", "guest_id"})
|
||||
serverObj, err := GuestManager.FetchByIdOrName(userCred, serverStr)
|
||||
objectId := jsonutils.GetAnyString(data, []string{"object", "object_id"})
|
||||
resType := jsonutils.GetAnyString(data, []string{"resource_type"})
|
||||
resMan := DynamicschedtagManager.VirtualResourcesManager[resType]
|
||||
if resMan == nil {
|
||||
return nil, httperrors.NewNotAcceptableError("ResourceType %q not support", resType)
|
||||
}
|
||||
obj, err := FetchDynamicResourceObject(resMan, userCred, objectId)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError("server %s not found", serverStr)
|
||||
} else {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
server := serverObj.(*SGuest)
|
||||
desc := server.getSchedDesc()
|
||||
desc := obj.GetDynamicConditionInput()
|
||||
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(desc.JSON(desc), "server")
|
||||
params.Add(desc, obj.Keyword())
|
||||
|
||||
log.V(10).Debugf("Schedpolicy evaluate input: %s", params.PrettyString())
|
||||
|
||||
meet, err := conditionparser.Eval(self.Condition, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := jsonutils.NewDict()
|
||||
result.Add(desc.JSON(desc), "server")
|
||||
result.Add(desc, obj.Keyword())
|
||||
if meet {
|
||||
result.Add(jsonutils.JSONTrue, "result")
|
||||
} else {
|
||||
@@ -178,45 +191,85 @@ func (self *SSchedpolicy) PerformEvaluate(ctx context.Context, userCred mcclient
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func ApplySchedPolicies(params *schedapi.ScheduleInput) *schedapi.ScheduleInput {
|
||||
policies := SchedpolicyManager.getAllEnabledPolicies()
|
||||
if policies == nil {
|
||||
log.Errorf("getAllEnabledPolicies fail")
|
||||
//return jsonutils.Marshal(params).(*jsonutils.JSONDict)
|
||||
return params
|
||||
func matchResourceSchedPolicy(
|
||||
policy SSchedpolicy,
|
||||
input *jsonutils.JSONDict,
|
||||
) bool {
|
||||
meet, err := conditionparser.Eval(policy.Condition, input)
|
||||
if err != nil {
|
||||
log.Errorf("Eval Condition %s error: %v", policy.Condition, err)
|
||||
return false
|
||||
}
|
||||
return meet
|
||||
}
|
||||
|
||||
func applyResourceSchedPolicy(
|
||||
policies []SSchedpolicy,
|
||||
oldTags []*api.SchedtagConfig,
|
||||
input *jsonutils.JSONDict,
|
||||
setTags func([]*api.SchedtagConfig),
|
||||
) {
|
||||
schedtags := make(map[string]string)
|
||||
|
||||
if len(params.ServerConfig.Schedtags) != 0 {
|
||||
for _, tag := range params.ServerConfig.Schedtags {
|
||||
schedtags[tag.Id] = tag.Strategy
|
||||
}
|
||||
log.Infof("original sched tag %#v", schedtags)
|
||||
for _, tag := range oldTags {
|
||||
schedtags[tag.Id] = tag.Strategy
|
||||
}
|
||||
|
||||
input := jsonutils.NewDict()
|
||||
input.Add(jsonutils.Marshal(params), "server")
|
||||
log.Infof("original schedtag %#v", schedtags)
|
||||
|
||||
for i := 0; i < len(policies); i += 1 {
|
||||
meet, err := conditionparser.Eval(policies[i].Condition, input)
|
||||
if err == nil && meet {
|
||||
st := policies[i].getSchedtag()
|
||||
if st != nil {
|
||||
schedtags[st.Name] = policies[i].Strategy
|
||||
}
|
||||
policy := policies[i]
|
||||
st := policy.getSchedtag()
|
||||
if matchResourceSchedPolicy(policy, input) {
|
||||
schedtags[st.Name] = policy.Strategy
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("updated sched tag %s", schedtags)
|
||||
|
||||
params.ServerConfig.Schedtags = make([]*api.SchedtagConfig, 0)
|
||||
newSchedtags := make([]*api.SchedtagConfig, 0)
|
||||
for name, strategy := range schedtags {
|
||||
params.ServerConfig.Schedtags = append(params.ServerConfig.Schedtags, &api.SchedtagConfig{
|
||||
newSchedtags = append(newSchedtags, &api.SchedtagConfig{
|
||||
Id: name,
|
||||
Strategy: strategy,
|
||||
})
|
||||
}
|
||||
|
||||
return params
|
||||
setTags(newSchedtags)
|
||||
}
|
||||
|
||||
func GetDynamicConditionInput(man IDynamicResourceManager, input *jsonutils.JSONDict) *jsonutils.JSONDict {
|
||||
ret := jsonutils.NewDict()
|
||||
ret.Add(input, man.Keyword())
|
||||
return ret
|
||||
}
|
||||
|
||||
func applyServerSchedtags(policies []SSchedpolicy, input *schedapi.ScheduleInput) {
|
||||
inputCond := GetDynamicConditionInput(GuestManager, input.ToConditionInput())
|
||||
setFunc := func(tags []*api.SchedtagConfig) {
|
||||
input.Schedtags = tags
|
||||
}
|
||||
applyResourceSchedPolicy(policies, input.Schedtags, inputCond, setFunc)
|
||||
}
|
||||
|
||||
func applyDiskSchedtags(policies []SSchedpolicy, input *api.DiskConfig) {
|
||||
inputCond := GetDynamicConditionInput(DiskManager, jsonutils.Marshal(input).(*jsonutils.JSONDict))
|
||||
setFunc := func(tags []*api.SchedtagConfig) {
|
||||
input.Schedtags = tags
|
||||
}
|
||||
applyResourceSchedPolicy(policies, input.Schedtags, inputCond, setFunc)
|
||||
}
|
||||
|
||||
func ApplySchedPolicies(input *schedapi.ScheduleInput) *schedapi.ScheduleInput {
|
||||
hostPolicies := SchedpolicyManager.getHostEnabledPolicies()
|
||||
storagePolicies := SchedpolicyManager.getStorageEnabledPolicies()
|
||||
|
||||
config := input.ServerConfigs
|
||||
|
||||
applyServerSchedtags(hostPolicies, input)
|
||||
for _, disk := range config.Disks {
|
||||
applyDiskSchedtags(storagePolicies, disk)
|
||||
}
|
||||
|
||||
input.ServerConfig.ServerConfigs = config
|
||||
|
||||
return input
|
||||
}
|
||||
|
||||
@@ -1151,3 +1151,7 @@ func (self *SStorage) IsPrepaidRecycleResource() bool {
|
||||
func (self *SStorage) GetSchedtags() []SSchedtag {
|
||||
return GetSchedtags(StorageschedtagManager, self.Id)
|
||||
}
|
||||
|
||||
func (self *SStorage) GetDynamicConditionInput() *jsonutils.JSONDict {
|
||||
return jsonutils.Marshal(self).(*jsonutils.JSONDict)
|
||||
}
|
||||
|
||||
@@ -6,8 +6,9 @@ var (
|
||||
|
||||
func init() {
|
||||
Dynamicschedtags = NewComputeManager("dynamicschedtag", "dynamicschedtags",
|
||||
[]string{"ID", "Name", "Description",
|
||||
"Condition", "Schedtag", "Schedtag_Id", "Enabled"},
|
||||
[]string{
|
||||
"ID", "Name", "Description", "Condition", "Schedtag",
|
||||
"Schedtag_Id", "Resource_Type", "Enabled"},
|
||||
[]string{})
|
||||
|
||||
registerComputeV2(&Dynamicschedtags)
|
||||
|
||||
@@ -6,8 +6,10 @@ var (
|
||||
|
||||
func init() {
|
||||
Schedpolicies = NewComputeManager("schedpolicy", "schedpolicies",
|
||||
[]string{"ID", "Name", "Description",
|
||||
"Condition", "Schedtag", "Schedtag_Id", "Strategy", "Enabled"},
|
||||
[]string{
|
||||
"ID", "Name", "Description", "Condition", "Schedtag",
|
||||
"Resource_Type", "Schedtag_Id", "Strategy", "Enabled",
|
||||
},
|
||||
[]string{})
|
||||
|
||||
registerComputeV2(&Schedpolicies)
|
||||
|
||||
@@ -178,7 +178,7 @@ type BaseListOptions struct {
|
||||
JointFilter []string `help:"Filters with joint table col; joint_tbl.related_key(origin_key).filter_col.filter_cond(filters)"`
|
||||
FilterAny *bool `help:"If true, match if any of the filters matches; otherwise, match if all of the filters match"`
|
||||
Admin *bool `help:"Is an admin call?"`
|
||||
Tenant string `help:"Tenant ID or Name"`
|
||||
Tenant string `help:"Tenant ID or Name" alias:"project"`
|
||||
User string `help:"User ID or Name"`
|
||||
System *bool `help:"Show system resource"`
|
||||
PendingDelete *bool `help:"Show only pending deleted resource"`
|
||||
|
||||
@@ -69,9 +69,9 @@ type schedtagCandidateW struct {
|
||||
func (w schedtagCandidateW) GetDynamicSchedDesc() *jsonutils.JSONDict {
|
||||
ret := jsonutils.NewDict()
|
||||
hostSchedDesc := w.GetSchedDesc()
|
||||
srvSchedDesc := jsonutils.Marshal(w.schedData)
|
||||
ret.Add(hostSchedDesc, "host")
|
||||
ret.Add(srvSchedDesc, "server")
|
||||
srvSchedDesc := w.schedData.ToConditionInput()
|
||||
ret.Add(hostSchedDesc, computemodels.HostManager.Keyword())
|
||||
ret.Add(srvSchedDesc, computemodels.GuestManager.Keyword())
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,12 @@ func (w schedtagStorageW) IndexKey() string {
|
||||
}
|
||||
|
||||
func (w schedtagStorageW) GetDynamicSchedDesc() *jsonutils.JSONDict {
|
||||
return nil
|
||||
ret := jsonutils.NewDict()
|
||||
storageSchedDesc := w.candidater.GetDynamicConditionInput()
|
||||
diskSchedDesc := w.disk.JSON(w.disk)
|
||||
ret.Add(storageSchedDesc, models.StorageManager.Keyword())
|
||||
ret.Add(diskSchedDesc, models.DiskManager.Keyword())
|
||||
return ret
|
||||
}
|
||||
|
||||
func (w schedtagStorageW) GetSchedtags() []models.SSchedtag {
|
||||
|
||||
@@ -187,11 +187,11 @@ func (c *SchedtagChecker) Contains(objectTags []models.SSchedtag, tags []compute
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (p *SchedtagChecker) getDynamicSchedtags(schedDesc *jsonutils.JSONDict) ([]models.SSchedtag, error) {
|
||||
func (p *SchedtagChecker) getDynamicSchedtags(resType string, schedDesc *jsonutils.JSONDict) ([]models.SSchedtag, error) {
|
||||
if schedDesc == nil {
|
||||
return []models.SSchedtag{}, nil
|
||||
}
|
||||
dynamicTags := models.DynamicschedtagManager.GetAllEnabledDynamicSchedtags()
|
||||
dynamicTags := models.DynamicschedtagManager.GetEnabledDynamicSchedtagsByResource(resType)
|
||||
|
||||
tags := []models.SSchedtag{}
|
||||
for _, tag := range dynamicTags {
|
||||
@@ -233,7 +233,7 @@ func (c *SchedtagChecker) mergeSchedtags(candiate ISchedtagCandidate, staticTags
|
||||
|
||||
func (c *SchedtagChecker) GetCandidateSchedtags(candidate ISchedtagCandidate) ([]models.SSchedtag, error) {
|
||||
staticTags := candidate.GetSchedtags()
|
||||
dynamicTags, err := c.getDynamicSchedtags(candidate.GetDynamicSchedDesc())
|
||||
dynamicTags, err := c.getDynamicSchedtags(candidate.ResourceType(), candidate.GetDynamicSchedDesc())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user