mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-06-20 18:26:05 +08:00
scheduler: optimize forecast filter info
This commit is contained in:
@@ -72,16 +72,22 @@ func (p *DiskSchedtagPredicate) GetResources(c core.Candidater) []ISchedtagCandi
|
||||
return ret
|
||||
}
|
||||
|
||||
func (p *DiskSchedtagPredicate) IsResourceFitInput(u *core.Unit, c core.Candidater, res ISchedtagCandidateResource, input ISchedtagCustomer) error {
|
||||
func (p *DiskSchedtagPredicate) IsResourceFitInput(u *core.Unit, c core.Candidater, res ISchedtagCandidateResource, input ISchedtagCustomer) core.PredicateFailureReason {
|
||||
storage := res.(*api.CandidateStorage)
|
||||
if storage.Status == computeapi.STORAGE_OFFLINE || storage.Enabled.IsFalse() {
|
||||
return fmt.Errorf("Storage status is %s, enable is %v", storage.Status, storage.Enabled)
|
||||
return &FailReason{
|
||||
fmt.Sprintf("Storage status is %s, enable is %v", storage.Status, storage.Enabled),
|
||||
StorageEnable,
|
||||
}
|
||||
}
|
||||
|
||||
d := input.(*diskW)
|
||||
if d.Storage != "" {
|
||||
if storage.Id != d.Storage && storage.Name != d.Storage {
|
||||
return fmt.Errorf("Storage name %s != (%s:%s)", d.Storage, storage.Name, storage.Id)
|
||||
return &FailReason{
|
||||
fmt.Sprintf("Storage name %s != (%s:%s)", d.Storage, storage.Name, storage.Id),
|
||||
StorageMatch,
|
||||
}
|
||||
}
|
||||
}
|
||||
if c.Getter().ResourceType() == computeapi.HostResourceTypePrepaidRecycle {
|
||||
@@ -89,13 +95,19 @@ func (p *DiskSchedtagPredicate) IsResourceFitInput(u *core.Unit, c core.Candidat
|
||||
}
|
||||
if !(len(d.Backend) == 0 || d.Backend == computeapi.STORAGE_LOCAL) {
|
||||
if storage.StorageType != d.Backend {
|
||||
return fmt.Errorf("Storage %s backend %s != %s", storage.Name, storage.StorageType, d.Backend)
|
||||
return &FailReason{
|
||||
fmt.Sprintf("Storage %s backend %s != %s", storage.Name, storage.StorageType, d.Backend),
|
||||
StorageType,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
storageTypes := p.GetHypervisorDriver().GetStorageTypes()
|
||||
if len(storageTypes) != 0 && !utils.IsInStringArray(storage.StorageType, storageTypes) {
|
||||
return fmt.Errorf("Storage %s storage type %s not in %v", storage.Name, storage.StorageType, storageTypes)
|
||||
return &FailReason{
|
||||
fmt.Sprintf("Storage %s storage type %s not in %v", storage.Name, storage.StorageType, storageTypes),
|
||||
StorageType,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -94,3 +94,32 @@ func (ure *UnexceptedResourceError) Error() string {
|
||||
func (ure *UnexceptedResourceError) GetReason() string {
|
||||
return ure.Error()
|
||||
}
|
||||
|
||||
type FailReason struct {
|
||||
Reason string
|
||||
Type string
|
||||
}
|
||||
|
||||
func (r FailReason) GetReason() string {
|
||||
return r.Reason
|
||||
}
|
||||
|
||||
func (r FailReason) GetType() string {
|
||||
return r.Type
|
||||
}
|
||||
|
||||
const (
|
||||
NetworkPrivate = "network_private"
|
||||
NetworkPublic = "network_public"
|
||||
NetworkTypeMatch = "network_type"
|
||||
NetworkMatch = "network_match"
|
||||
NetworkWire = "network_wire"
|
||||
NetworkOwner = "network_owner"
|
||||
NetworkDomain = "network_domain"
|
||||
NetworkRange = "network_range"
|
||||
NetworkFreeCount = "network_free_count"
|
||||
|
||||
StorageEnable = "storage_status"
|
||||
StorageMatch = "storage_match"
|
||||
StorageType = "storage_type"
|
||||
)
|
||||
|
||||
@@ -75,42 +75,63 @@ func (p *NetworkSchedtagPredicate) GetResources(c core.Candidater) []ISchedtagCa
|
||||
return ret
|
||||
}
|
||||
|
||||
func (p *NetworkSchedtagPredicate) IsResourceFitInput(u *core.Unit, c core.Candidater, res ISchedtagCandidateResource, input ISchedtagCustomer) error {
|
||||
func (p *NetworkSchedtagPredicate) IsResourceFitInput(u *core.Unit, c core.Candidater, res ISchedtagCandidateResource, input ISchedtagCustomer) core.PredicateFailureReason {
|
||||
network := res.(*api.CandidateNetwork)
|
||||
net := input.(*netW)
|
||||
if net.Network != "" {
|
||||
if network.Id != net.Network && network.Name != net.Network {
|
||||
return fmt.Errorf("Network name %s != (%s:%s)", net.Network, network.Name, network.Id)
|
||||
return &FailReason{
|
||||
Reason: fmt.Sprintf("Network name %s != (%s:%s)", net.Network, network.Name, network.Id),
|
||||
Type: NetworkMatch,
|
||||
}
|
||||
}
|
||||
}
|
||||
if net.Wire != "" {
|
||||
if network.WireId != net.Wire {
|
||||
return fmt.Errorf("Wire %s != %s", net.Wire, network.WireId)
|
||||
return &FailReason{
|
||||
Reason: fmt.Sprintf("Wire %s != %s", net.Wire, network.WireId),
|
||||
Type: NetworkWire,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if net.Network == "" {
|
||||
netTypes := p.GetNetworkTypes(net.NetType)
|
||||
if !utils.IsInStringArray(network.ServerType, netTypes) {
|
||||
return fmt.Errorf("Network %s type %s not in %v", network.Name, network.ServerType, netTypes)
|
||||
return &FailReason{
|
||||
Reason: fmt.Sprintf("Network %s type %s not in %v", network.Name, network.ServerType, netTypes),
|
||||
Type: NetworkTypeMatch,
|
||||
}
|
||||
}
|
||||
schedData := u.SchedData()
|
||||
if net.Private {
|
||||
if network.IsPublic {
|
||||
return fmt.Errorf("Network %s is public", network.Name)
|
||||
return &FailReason{
|
||||
Reason: fmt.Sprintf("Network %s is public", network.Name),
|
||||
Type: NetworkPublic,
|
||||
}
|
||||
}
|
||||
if network.ProjectId != schedData.Project && !utils.IsInStringArray(schedData.Project, network.GetSharedProjects()) {
|
||||
return fmt.Errorf("Network project %s + %v not owner by %s", network.ProjectId, network.GetSharedProjects(), schedData.Project)
|
||||
return &FailReason{
|
||||
Reason: fmt.Sprintf("Network project %s + %v not owner by %s", network.ProjectId, network.GetSharedProjects(), schedData.Project),
|
||||
Type: NetworkOwner,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if !network.IsPublic {
|
||||
return fmt.Errorf("Network %s is private", network.Name)
|
||||
return &FailReason{
|
||||
fmt.Sprintf("Network %s is private", network.Name),
|
||||
NetworkPrivate,
|
||||
}
|
||||
}
|
||||
if rbacutils.TRbacScope(network.PublicScope) == rbacutils.ScopeDomain {
|
||||
netDomain := network.DomainId
|
||||
reqDomain := net.Domain
|
||||
if netDomain != reqDomain {
|
||||
return fmt.Errorf("Network domain scope %s not owner by %s", netDomain, reqDomain)
|
||||
return &FailReason{
|
||||
fmt.Sprintf("Network domain scope %s not owner by %s", netDomain, reqDomain),
|
||||
NetworkDomain,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,19 +140,31 @@ func (p *NetworkSchedtagPredicate) IsResourceFitInput(u *core.Unit, c core.Candi
|
||||
if len(net.Address) > 0 {
|
||||
ipAddr, err := netutils.NewIPV4Addr(net.Address)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Invalid ip address %s: %v", net.Address, err)
|
||||
return &FailReason{
|
||||
fmt.Sprintf("Invalid ip address %s: %v", net.Address, err),
|
||||
NetworkRange,
|
||||
}
|
||||
}
|
||||
if !network.GetIPRange().Contains(ipAddr) {
|
||||
return fmt.Errorf("Address %s not in range", net.Address)
|
||||
return &FailReason{
|
||||
fmt.Sprintf("Address %s not in range", net.Address),
|
||||
NetworkRange,
|
||||
}
|
||||
}
|
||||
}
|
||||
free, err := network.GetFreeAddressCount()
|
||||
if err != nil {
|
||||
return err
|
||||
return &FailReason{
|
||||
Reason: fmt.Sprintf("get free address count: %v", err),
|
||||
Type: NetworkFreeCount,
|
||||
}
|
||||
}
|
||||
req := u.SchedData().Count
|
||||
if free < req {
|
||||
return fmt.Errorf("Network %s no free IPs, free %d, require %d", network.Name, free, req)
|
||||
return &FailReason{
|
||||
Reason: fmt.Sprintf("Network %s no free IPs, free %d, require %d", network.Name, free, req),
|
||||
Type: NetworkFreeCount,
|
||||
}
|
||||
}
|
||||
h := NewPredicateHelper(p, u, c)
|
||||
h.SetCapacity(int64(free))
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
@@ -103,13 +101,34 @@ func (h *PredicateHelper) AppendPredicateFail(reason core.PredicateFailureReason
|
||||
h.predicateFails = append(h.predicateFails, reason)
|
||||
}
|
||||
|
||||
type predicateFailure struct {
|
||||
err core.PredicateFailureError
|
||||
eType string
|
||||
}
|
||||
|
||||
func (f predicateFailure) GetReason() string {
|
||||
return f.err.GetReason()
|
||||
}
|
||||
|
||||
func (f predicateFailure) GetType() string {
|
||||
return f.eType
|
||||
}
|
||||
|
||||
func (h *PredicateHelper) AppendPredicateFailMsg(reason string) {
|
||||
h.AppendPredicateFail(NewUnexceptedResourceError(reason))
|
||||
h.AppendPredicateFailMsgWithType(reason, h.predicate.Name())
|
||||
}
|
||||
|
||||
func (h *PredicateHelper) AppendPredicateFailMsgWithType(reason string, eType string) {
|
||||
err := NewUnexceptedResourceError(reason)
|
||||
h.AppendPredicateFail(&predicateFailure{err: err, eType: eType})
|
||||
}
|
||||
|
||||
func (h *PredicateHelper) AppendInsufficientResourceError(req, total, free int64) {
|
||||
h.AppendPredicateFail(
|
||||
NewInsufficientResourceError(h.Candidate.Getter().Name(), req, total, free))
|
||||
&predicateFailure{
|
||||
err: NewInsufficientResourceError(h.Candidate.Getter().Name(), req, total, free),
|
||||
eType: h.predicate.Name(),
|
||||
})
|
||||
}
|
||||
|
||||
// SetCapacity returns the current resource capacity calculated by a filter.
|
||||
@@ -137,6 +156,13 @@ func (h *PredicateHelper) Exclude(reason string) {
|
||||
h.AppendPredicateFailMsg(reason)
|
||||
}
|
||||
|
||||
func (h *PredicateHelper) ExcludeByErrors(errs []core.PredicateFailureReason) {
|
||||
h.SetCapacity(0)
|
||||
for _, err := range errs {
|
||||
h.AppendPredicateFail(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *PredicateHelper) Exclude2(predicateName string, current, expected interface{}) {
|
||||
h.Exclude(fmt.Sprintf("%s is '%v', expected '%v'", predicateName, current, expected))
|
||||
}
|
||||
@@ -204,7 +230,7 @@ type ISchedtagPredicateInstance interface {
|
||||
|
||||
GetInputs(u *core.Unit) []ISchedtagCustomer
|
||||
GetResources(c core.Candidater) []ISchedtagCandidateResource
|
||||
IsResourceFitInput(unit *core.Unit, c core.Candidater, res ISchedtagCandidateResource, input ISchedtagCustomer) error
|
||||
IsResourceFitInput(unit *core.Unit, c core.Candidater, res ISchedtagCandidateResource, input ISchedtagCustomer) core.PredicateFailureReason
|
||||
|
||||
DoSelect(c core.Candidater, input ISchedtagCustomer, res []ISchedtagCandidateResource) []ISchedtagCandidateResource
|
||||
AddSelectResult(index int, selectRes []ISchedtagCandidateResource, output *core.AllocatedResource)
|
||||
@@ -354,10 +380,10 @@ func (p *BaseSchedtagPredicate) Execute(
|
||||
h := NewPredicateHelper(sp, u, c)
|
||||
|
||||
inputRes := p.GetInputResourcesMap(c.IndexKey())
|
||||
filterErrs := make([]error, 0)
|
||||
filterErrs := make([]core.PredicateFailureReason, 0)
|
||||
for idx, input := range inputs {
|
||||
fitResources := make([]ISchedtagCandidateResource, 0)
|
||||
errs := make([]error, 0)
|
||||
errs := make([]core.PredicateFailureReason, 0)
|
||||
for _, res := range resources {
|
||||
if err := sp.IsResourceFitInput(u, c, res, input); err == nil {
|
||||
fitResources = append(fitResources, res)
|
||||
@@ -366,20 +392,19 @@ func (p *BaseSchedtagPredicate) Execute(
|
||||
}
|
||||
}
|
||||
if len(fitResources) == 0 {
|
||||
h.Exclude(fmt.Sprintf("Not found available resources for %s %s: %s", input.Keyword(), input.JSON(input), errors.NewAggregate(errs)))
|
||||
h.ExcludeByErrors(errs)
|
||||
break
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
filterErrs = append(filterErrs, errors.NewAggregate(errs))
|
||||
filterErrs = append(filterErrs, errs...)
|
||||
}
|
||||
|
||||
matchedResources, err := p.checkResources(input, fitResources, u, c)
|
||||
if err != nil {
|
||||
aggErr := errors.NewAggregate(filterErrs)
|
||||
errMsg := fmt.Sprintf("schedtag: %v", err.Error())
|
||||
if aggErr != nil {
|
||||
errMsg = fmt.Sprintf("%s; filter: %v", errMsg, aggErr.Error())
|
||||
if len(filterErrs) > 0 {
|
||||
h.ExcludeByErrors(filterErrs)
|
||||
}
|
||||
errMsg := fmt.Sprintf("schedtag: %v", err.Error())
|
||||
h.Exclude(errMsg)
|
||||
}
|
||||
inputRes[idx] = matchedResources
|
||||
|
||||
Reference in New Issue
Block a user