Merge pull request #12682 from swordqiu/automated-cherry-pick-of-#12681-upstream-release-3.8

Automated cherry pick of #12681: fix: server-create-eip allocation prefer owner's eip network
This commit is contained in:
Zexi Li
2021-11-16 16:11:03 +08:00
committed by GitHub
2 changed files with 100 additions and 65 deletions
+95 -15
View File
@@ -18,6 +18,7 @@ import (
"context"
"database/sql"
"fmt"
"sort"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
@@ -1222,6 +1223,84 @@ func (self *SElasticip) getMoreDetails(out api.ElasticipDetails) api.ElasticipDe
return out
}
type SEipNetwork struct {
owner mcclient.IIdentityProvider
user mcclient.TokenCredential
freeCnt int
net *SNetwork
}
func NewEipNetwork(net *SNetwork, owner mcclient.IIdentityProvider, user mcclient.TokenCredential, freecnt int) SEipNetwork {
return SEipNetwork{
owner: owner,
user: user,
freeCnt: freecnt,
net: net,
}
}
func (en SEipNetwork) isOwnerProject() bool {
return en.owner.GetProjectId() == en.net.ProjectId
}
func (en SEipNetwork) isOwnerProjectDomain() bool {
return en.owner.GetProjectDomainId() == en.net.DomainId
}
func (en SEipNetwork) isUserProject() bool {
return en.user.GetProjectId() == en.net.ProjectId
}
func (en SEipNetwork) isUserProjectDomain() bool {
return en.user.GetProjectDomainId() == en.net.DomainId
}
func (en SEipNetwork) GetNetwork() *SNetwork {
return en.net
}
type SEipNetworks []SEipNetwork
func (a SEipNetworks) Len() int {
return len(a)
}
func (a SEipNetworks) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
func (a SEipNetworks) Less(i, j int) bool {
if a[i].isOwnerProject() && !a[j].isOwnerProject() {
return true
} else if !a[i].isOwnerProject() && a[j].isOwnerProject() {
return false
}
if a[i].isOwnerProjectDomain() && !a[j].isOwnerProjectDomain() {
return true
} else if !a[i].isOwnerProjectDomain() && a[j].isOwnerProjectDomain() {
return false
}
if a[i].isUserProject() && !a[j].isUserProject() {
return true
} else if !a[i].isUserProject() && a[j].isUserProject() {
return false
}
if a[i].isUserProjectDomain() && !a[j].isUserProjectDomain() {
return true
} else if !a[i].isUserProjectDomain() && a[j].isUserProjectDomain() {
return false
}
if a[i].freeCnt > a[j].freeCnt {
return true
} else if a[i].freeCnt < a[j].freeCnt {
return false
}
if a[i].net.Id < a[j].net.Id {
return true
}
return false
}
type NewEipForVMOnHostArgs struct {
Bandwidth int
BgpType string
@@ -1274,13 +1353,14 @@ func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCre
eip.Bandwidth = bw
eip.ChargeType = chargeType
eip.AutoDellocate = tristate.NewFromBool(autoDellocate)
ownerCred := userCred.(mcclient.IIdentityProvider)
if vm != nil {
eip.DomainId = vm.DomainId
eip.ProjectId = vm.ProjectId
} else {
eip.DomainId = userCred.GetProjectDomainId()
eip.ProjectId = userCred.GetProjectId()
ownerCred = vm.GetOwnerId()
} else if nat != nil {
ownerCred = nat.GetOwnerId()
}
eip.DomainId = ownerCred.GetProjectDomainId()
eip.ProjectId = ownerCred.GetProjectId()
eip.ProjectSrc = string(apis.OWNER_SOURCE_LOCAL)
if host != nil {
eip.ManagerId = host.ManagerId
@@ -1313,21 +1393,21 @@ func (manager *SElasticipManager) NewEipForVMOnHost(ctx context.Context, userCre
return nil, errors.Wrapf(err, "fetch eip networks usable in host %s(%s)",
host.Name, host.Id)
}
var net *SNetwork
eipNets := make([]SEipNetwork, 0)
for i := range nets {
net = &nets[i]
cnt, err := net.GetFreeAddressCount()
if err != nil {
continue
}
net := &nets[i]
cnt, _ := net.GetFreeAddressCount()
if cnt > 0 {
break
eipNets = append(eipNets, NewEipNetwork(net, ownerCred, userCred, cnt))
}
}
if net == nil {
return nil, errors.Error("no usable eip network")
if len(eipNets) == 0 {
return nil, httperrors.NewNotFoundError("no usable eip network")
}
eip.NetworkId = net.Id
// prefer networks with identical project, domain, more free address, Id
sort.Sort(SEipNetworks(eipNets))
log.Debugf("eipnets: %s", jsonutils.Marshal(eipNets))
eip.NetworkId = eipNets[0].GetNetwork().Id
}
var err = func() error {
+5 -50
View File
@@ -917,52 +917,6 @@ func (self *SKVMRegionDriver) ValidateEipChargeType(chargeType string) error {
return nil
}
type eipNetwork struct {
owner mcclient.TokenCredential
freeCnt int
net *models.SNetwork
}
func (en eipNetwork) isOwnerProject() bool {
return en.owner.GetProjectId() == en.net.ProjectId
}
func (en eipNetwork) isOwnerProjectDomain() bool {
return en.owner.GetProjectDomainId() == en.net.DomainId
}
type eipNetworks []eipNetwork
func (a eipNetworks) Len() int {
return len(a)
}
func (a eipNetworks) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
func (a eipNetworks) Less(i, j int) bool {
if a[i].isOwnerProject() && !a[j].isOwnerProject() {
return true
} else if !a[i].isOwnerProject() && a[j].isOwnerProject() {
return false
}
if a[i].isOwnerProjectDomain() && !a[j].isOwnerProjectDomain() {
return true
} else if !a[i].isOwnerProjectDomain() && a[j].isOwnerProjectDomain() {
return false
}
if a[i].freeCnt > a[j].freeCnt {
return true
} else if a[i].freeCnt < a[j].freeCnt {
return false
}
if a[i].net.Id < a[j].net.Id {
return true
}
return false
}
func (self *SKVMRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, input *api.SElasticipCreateInput) error {
if err := self.ValidateEipChargeType(input.ChargeType); err != nil {
return err
@@ -986,20 +940,21 @@ func (self *SKVMRegionDriver) ValidateCreateEipData(ctx context.Context, userCre
if err := db.FetchModelObjects(models.NetworkManager, q, &nets); err != nil {
return err
}
eipNets := make([]eipNetwork, 0)
eipNets := make([]models.SEipNetwork, 0)
for i := range nets {
net := &nets[i]
cnt, _ := net.GetFreeAddressCount()
if cnt > 0 {
eipNets = append(eipNets, eipNetwork{net: net, freeCnt: cnt, owner: userCred})
eipNets = append(eipNets, models.NewEipNetwork(net, userCred, userCred, cnt))
}
}
if len(eipNets) == 0 {
return httperrors.NewNotFoundError("no available eip network")
}
// prefer networks with identical project, domain, more free address, Id
sort.Sort(eipNetworks(eipNets))
network = eipNets[0].net
sort.Sort(models.SEipNetworks(eipNets))
log.Debugf("eipnets: %s", jsonutils.Marshal(eipNets))
network = eipNets[0].GetNetwork()
input.NetworkId = network.Id
}
if network.ServerType != api.NETWORK_TYPE_EIP {