diff --git a/pkg/scheduler/cache/candidate/baremetals.go b/pkg/scheduler/cache/candidate/baremetals.go index d4da4ca317..b547315654 100644 --- a/pkg/scheduler/cache/candidate/baremetals.go +++ b/pkg/scheduler/cache/candidate/baremetals.go @@ -192,18 +192,18 @@ func (bb *BaremetalBuilder) Do(ids []string) ([]interface{}, error) { if err != nil { return nil, err } - - descs, err := bb.build() + netGetter := newNetworkGetter() + descs, err := bb.build(netGetter) if err != nil { return nil, err } return descs, nil } -func (bb *BaremetalBuilder) build() ([]interface{}, error) { +func (bb *BaremetalBuilder) build(netGetter *networkGetter) ([]interface{}, error) { schedDescs := []interface{}{} for _, bm := range bb.baremetals { - desc, err := bb.buildOne(&bm) + desc, err := bb.buildOne(&bm, netGetter) if err != nil { log.Errorf("BaremetalBuilder error: %v", err) continue @@ -213,8 +213,8 @@ func (bb *BaremetalBuilder) build() ([]interface{}, error) { return schedDescs, nil } -func (bb *BaremetalBuilder) buildOne(hostObj *computemodels.SHost) (interface{}, error) { - baseDesc, err := newBaseHostDesc(bb.baseBuilder, hostObj) +func (bb *BaremetalBuilder) buildOne(hostObj *computemodels.SHost, netGetter *networkGetter) (interface{}, error) { + baseDesc, err := newBaseHostDesc(bb.baseBuilder, hostObj, netGetter) if err != nil { return nil, err } diff --git a/pkg/scheduler/cache/candidate/base.go b/pkg/scheduler/cache/candidate/base.go index e9b108c0d9..f3cb0e50da 100644 --- a/pkg/scheduler/cache/candidate/base.go +++ b/pkg/scheduler/cache/candidate/base.go @@ -17,6 +17,7 @@ package candidate import ( "fmt" "strings" + "sync" "yunion.io/x/jsonutils" "yunion.io/x/log" @@ -326,7 +327,33 @@ func reviseResourceType(resType string) string { return resType } -func newBaseHostDesc(b *baseBuilder, host *computemodels.SHost) (*BaseHostDesc, error) { +type networkGetter struct { + netFreeMap *sync.Map +} + +func newNetworkGetter() *networkGetter { + return &networkGetter{ + netFreeMap: new(sync.Map), + } +} + +func (g *networkGetter) GetFreePort(host *computemodels.SHost, n *computemodels.SNetwork) (int, error) { + if host.IsEmulated { + // not calculate emulated host's network free address + return -1, nil + } + if val, ok := g.netFreeMap.Load(n.GetId()); ok { + return val.(int), nil + } + freePort, err := n.GetFreeAddressCount() + if err != nil { + return -1, errors.Wrapf(err, "GetFreeAddressCount for network %s(%s)", n.GetName(), n.GetId()) + } + g.netFreeMap.Store(n.GetId(), freePort) + return freePort, nil +} + +func newBaseHostDesc(b *baseBuilder, host *computemodels.SHost, netGetter *networkGetter) (*BaseHostDesc, error) { host.ResourceType = reviseResourceType(host.ResourceType) desc := &BaseHostDesc{ SHost: host, @@ -336,17 +363,17 @@ func newBaseHostDesc(b *baseBuilder, host *computemodels.SHost) (*BaseHostDesc, return nil, fmt.Errorf("Fill cloudprovider info error: %v", err) } - if err := desc.fillNetworks(host); err != nil { + if err := desc.fillNetworks(host, netGetter); err != nil { return nil, fmt.Errorf("Fill networks error: %v", err) } // only onecloud host should fill onecloud vpc networks if host.HostType == computeapi.HOST_TYPE_HYPERVISOR { - if err := desc.fillOnecloudVpcNetworks(); err != nil { + if err := desc.fillOnecloudVpcNetworks(netGetter); err != nil { return nil, fmt.Errorf("Fill onecloud vpc networks error: %v", err) } } if host.HostType == computeapi.HOST_TYPE_CLOUDPODS { - if err := desc.fillCloudpodsVpcNetworks(); err != nil { + if err := desc.fillCloudpodsVpcNetworks(netGetter); err != nil { return nil, fmt.Errorf("Fill cloudpods vpc networks error: %v", err) } } @@ -430,7 +457,10 @@ func (b *BaseHostDesc) GetFreePort(netId string) int { if selNet == nil { return 0 } - // freeCount, _ := selNet.GetFreeAddressCount() + if b.IsEmulated { + freeCount, _ := selNet.GetFreeAddressCount() + return freeCount + } return selNet.FreePort } @@ -583,7 +613,7 @@ func (b *BaseHostDesc) fillSharedDomains() error { return nil } -func (b *BaseHostDesc) fillNetworks(host *computemodels.SHost) error { +func (b *BaseHostDesc) fillNetworks(host *computemodels.SHost, netGetter *networkGetter) error { hostId := host.Id hostwires := computemodels.HostwireManager.Query().SubQuery() sq := hostwires.Query(sqlchemy.DISTINCT("wire_id", hostwires.Field("wire_id"))).Equals("host_id", hostId) @@ -597,9 +627,9 @@ func (b *BaseHostDesc) fillNetworks(host *computemodels.SHost) error { } b.Networks = make([]*api.CandidateNetwork, len(nets)) for idx, n := range nets { - freePort, err := n.GetFreeAddressCount() + freePort, err := netGetter.GetFreePort(host, &n) if err != nil { - return errors.Wrapf(err, "GetFreeAddressCount for network %s(%s)", n.GetName(), n.GetId()) + return errors.Wrapf(err, "GetFreePort for network %s(%s)", n.GetName(), n.GetId()) } b.Networks[idx] = &api.CandidateNetwork{ SNetwork: &nets[idx], @@ -628,7 +658,7 @@ func (b *BaseHostDesc) fillNetworks(host *computemodels.SHost) error { return nil } -func (b *BaseHostDesc) fillCloudpodsVpcNetworks() error { +func (b *BaseHostDesc) fillCloudpodsVpcNetworks(netGetter *networkGetter) error { nets := computemodels.NetworkManager.Query() wires := computemodels.WireManager.Query().SubQuery() vpcs := computemodels.VpcManager.Query().SubQuery() @@ -659,7 +689,7 @@ func (b *BaseHostDesc) fillCloudpodsVpcNetworks() error { row := &rows[i] net := &row.SNetwork net.SetModelManager(computemodels.NetworkManager, net) - freePort, err := net.GetFreeAddressCount() + freePort, err := netGetter.GetFreePort(b.SHost, net) if err != nil { return errors.Wrapf(err, "GetFreeAddressCount for network %s(%s)", net.GetName(), net.GetId()) } @@ -674,7 +704,7 @@ func (b *BaseHostDesc) fillCloudpodsVpcNetworks() error { return nil } -func (b *BaseHostDesc) fillOnecloudVpcNetworks() error { +func (b *BaseHostDesc) fillOnecloudVpcNetworks(netGetter *networkGetter) error { nets := computemodels.NetworkManager.Query() wires := computemodels.WireManager.Query().SubQuery() vpcs := computemodels.VpcManager.Query().SubQuery() @@ -705,7 +735,7 @@ func (b *BaseHostDesc) fillOnecloudVpcNetworks() error { row := &rows[i] net := &row.SNetwork net.SetModelManager(computemodels.NetworkManager, net) - freePort, err := net.GetFreeAddressCount() + freePort, err := netGetter.GetFreePort(b.SHost, net) if err != nil { return errors.Wrapf(err, "GetFreeAddressCount for network %s(%s)", net.GetName(), net.GetId()) } diff --git a/pkg/scheduler/cache/candidate/hosts.go b/pkg/scheduler/cache/candidate/hosts.go index 61cf19184d..41f6a96bf8 100644 --- a/pkg/scheduler/cache/candidate/hosts.go +++ b/pkg/scheduler/cache/candidate/hosts.go @@ -759,14 +759,15 @@ func (b *HostBuilder) Do(ids []string) ([]interface{}, error) { if err != nil { return nil, err } - descs, err := b.build() + netGetter := newNetworkGetter() + descs, err := b.build(netGetter) if err != nil { return nil, err } return descs, nil } -func (b *HostBuilder) build() ([]interface{}, error) { +func (b *HostBuilder) build(netGetter *networkGetter) ([]interface{}, error) { schedDescs := make([]interface{}, len(b.hosts)) errs := []error{} var descResultLock gosync.Mutex @@ -774,11 +775,11 @@ func (b *HostBuilder) build() ([]interface{}, error) { buildOne := func(i int) { if i >= len(b.hosts) { - log.Errorf("invalid host index[%d] in b.hosts:%v\n", i, b.hosts) + log.Errorf("invalid host index[%d] in b.hosts: %v", i, b.hosts) return } host := b.hosts[i] - desc, err := b.buildOne(&host) + desc, err := b.buildOne(&host, netGetter) if err != nil { descResultLock.Lock() errs = append(errs, err) @@ -801,8 +802,8 @@ func (b *HostBuilder) build() ([]interface{}, error) { return schedDescs, nil } -func (b *HostBuilder) buildOne(host *computemodels.SHost) (interface{}, error) { - baseDesc, err := newBaseHostDesc(b.baseBuilder, host) +func (b *HostBuilder) buildOne(host *computemodels.SHost, netGetter *networkGetter) (interface{}, error) { + baseDesc, err := newBaseHostDesc(b.baseBuilder, host, netGetter) if err != nil { return nil, err }