mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-21 14:19:49 +08:00
fix(region): check the global network situation when expanding the network
This commit is contained in:
@@ -359,7 +359,8 @@ func (scm *SCloudaccountManager) AllowPerformPrepareNets(_ context.Context, user
|
||||
|
||||
type sNetworkInfo struct {
|
||||
esxi.SNetworkInfo
|
||||
prefix string
|
||||
prefix string
|
||||
fakeVsId string
|
||||
}
|
||||
|
||||
func (scm *SCloudaccountManager) hostVMIPsPrepareNets(ctx context.Context, client *esxi.SESXiClient,
|
||||
@@ -376,9 +377,11 @@ func (scm *SCloudaccountManager) hostVMIPsPrepareNets(ctx context.Context, clien
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to fetch ips of hosts and vms")
|
||||
}
|
||||
nInfo.IPPool.FillVsId(caName)
|
||||
ret = append(ret, sNetworkInfo{
|
||||
SNetworkInfo: nInfo,
|
||||
prefix: caName,
|
||||
fakeVsId: caName,
|
||||
})
|
||||
case api.CLOUD_ACCOUNT_WIRE_LEVEL_DATACENTER:
|
||||
dcs, err := client.GetDatacenters()
|
||||
@@ -390,9 +393,12 @@ func (scm *SCloudaccountManager) hostVMIPsPrepareNets(ctx context.Context, clien
|
||||
if err != nil {
|
||||
return ret, errors.Wrapf(err, "unable to fetch ips of hosts and vms for dc %q", dc.GetName())
|
||||
}
|
||||
prefix := fmt.Sprintf("%s/%s", caName, dc.GetName())
|
||||
nInfo.IPPool.FillVsId(prefix)
|
||||
ret = append(ret, sNetworkInfo{
|
||||
SNetworkInfo: nInfo,
|
||||
prefix: fmt.Sprintf("%s/%s", caName, dc.GetName()),
|
||||
prefix: prefix,
|
||||
fakeVsId: prefix,
|
||||
})
|
||||
}
|
||||
case api.CLOUD_ACCOUNT_WIRE_LEVEL_CLUSTER:
|
||||
@@ -410,9 +416,12 @@ func (scm *SCloudaccountManager) hostVMIPsPrepareNets(ctx context.Context, clien
|
||||
if err != nil {
|
||||
return ret, errors.Wrapf(err, "unable to fetch ips of hosts and vms for dc %q cluster %q", dc.GetName(), cluster.GetName())
|
||||
}
|
||||
prefix := fmt.Sprintf("%s/%s/%s", caName, dc.GetName(), cluster.GetName())
|
||||
nInfo.IPPool.FillVsId(prefix)
|
||||
ret = append(ret, sNetworkInfo{
|
||||
SNetworkInfo: nInfo,
|
||||
prefix: fmt.Sprintf("%s/%s/%s", caName, dc.GetName(), cluster.GetName()),
|
||||
prefix: prefix,
|
||||
fakeVsId: prefix,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -555,6 +564,33 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
wires = params.Wires
|
||||
networks = params.Networks
|
||||
)
|
||||
// build global existedNetMap and IPPool
|
||||
netNum := 0
|
||||
for i := range networks {
|
||||
netNum += len(networks[i])
|
||||
}
|
||||
existedNets := newIPPool(netNum)
|
||||
for _, nets := range networks {
|
||||
for i := range nets {
|
||||
startIp, _ := netutils.NewIPV4Addr(nets[i].GuestIpStart)
|
||||
endIp, _ := netutils.NewIPV4Addr(nets[i].GuestIpEnd)
|
||||
existedNets.Insert(startIp, sSimpleNet{
|
||||
Diff: endIp - startIp,
|
||||
Vlan: int32(nets[i].VlanId),
|
||||
Id: nets[i].Id,
|
||||
WireId: nets[i].WireId,
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
ipPoolLen := 0
|
||||
for i := range nInfos {
|
||||
ipPoolLen += nInfos[i].IPPool.Len()
|
||||
}
|
||||
ipPool := esxi.NewIPPool(ipPoolLen)
|
||||
for i := range nInfos {
|
||||
ipPool.Merge(&nInfos[i].IPPool)
|
||||
}
|
||||
output.CAWireNets = make([]api.CAWireNet, 0, len(nInfos))
|
||||
for _, ni := range nInfos {
|
||||
var (
|
||||
@@ -569,11 +605,10 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
}
|
||||
// Find suitable wire and the network containing the Host IP in suitable wire.
|
||||
var (
|
||||
tmpSocre int
|
||||
maxScore = len(ipHosts)
|
||||
suitableWire *SWire
|
||||
suitableWireIndex = -1
|
||||
suitableNetworks map[netutils.IPV4Addr]*SNetwork
|
||||
tmpSocre int
|
||||
maxScore = len(ipHosts)
|
||||
suitableWire *SWire
|
||||
suitableNetworks map[netutils.IPV4Addr]*SNetwork
|
||||
)
|
||||
for i, nets := range networks {
|
||||
score := 0
|
||||
@@ -595,7 +630,6 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
if score > tmpSocre {
|
||||
tmpSocre = score
|
||||
suitableWire = &wires[i]
|
||||
suitableWireIndex = i
|
||||
suitableNetworks = tmpSNs
|
||||
}
|
||||
if tmpSocre == maxScore {
|
||||
@@ -638,30 +672,12 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
}
|
||||
|
||||
// Find the suitable network containing the VM IP, and if not, give the corresponding suggested network configuration in this project.
|
||||
var allNets []SNetwork
|
||||
if suitableWire != nil {
|
||||
allNets = networks[suitableWireIndex]
|
||||
}
|
||||
type simpleNet struct {
|
||||
Id string
|
||||
Vlan int32
|
||||
}
|
||||
existedNetMap := make(map[netutils.IPV4Addr]simpleNet, len(allNets))
|
||||
for i := range allNets {
|
||||
ipStart, _ := netutils.NewIPV4Addr(allNets[i].GuestIpStart)
|
||||
ipEnd, _ := netutils.NewIPV4Addr(allNets[i].GuestIpEnd)
|
||||
for ip := ipStart; ip <= ipEnd; ip++ {
|
||||
existedNetMap[ip] = simpleNet{Id: allNets[i].Id, Vlan: int32(allNets[i].VlanId)}
|
||||
}
|
||||
}
|
||||
|
||||
for i := range wireNet.HostSuggestedNetworks {
|
||||
ipStart, _ := netutils.NewIPV4Addr(wireNet.HostSuggestedNetworks[i].GuestIpStart)
|
||||
ipEnd, _ := netutils.NewIPV4Addr(wireNet.HostSuggestedNetworks[i].GuestIpEnd)
|
||||
existedNetMap[ipStart] = simpleNet{}
|
||||
if ipEnd != ipStart {
|
||||
existedNetMap[ipEnd] = simpleNet{}
|
||||
}
|
||||
existedNets.Insert(ipStart, sSimpleNet{
|
||||
Diff: ipEnd - ipStart,
|
||||
})
|
||||
}
|
||||
|
||||
guests := make([]api.CAGuestNet, len(ni.VMs))
|
||||
@@ -669,7 +685,7 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
guests[i].Name = ni.VMs[i].Name
|
||||
for _, ipvlan := range ni.VMs[i].IPVlans {
|
||||
var suitableNetId string
|
||||
sn, ok := existedNetMap[ipvlan.IP]
|
||||
sn, ok := existedNets.Get(ipvlan.IP)
|
||||
if ok {
|
||||
suitableNetId = sn.Id
|
||||
}
|
||||
@@ -685,7 +701,7 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
for vlan, ips := range ni.VlanIps {
|
||||
for i := 0; i < len(ips); i++ {
|
||||
ip := ips[i]
|
||||
if _, ok := existedNetMap[ip]; ok {
|
||||
if _, ok := existedNets.Get(ip); ok {
|
||||
continue
|
||||
}
|
||||
net := ip.NetAddr(24)
|
||||
@@ -694,20 +710,20 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
// find startip
|
||||
startIp := ip - 1
|
||||
for ; startIp >= netLimitLow; startIp-- {
|
||||
if _, ok := existedNetMap[startIp]; ok {
|
||||
if _, ok := existedNets.Get(startIp); ok {
|
||||
break
|
||||
}
|
||||
if _, ok := ni.IPPool.Get(startIp); ok {
|
||||
if _, ok := ipPool.Get(startIp); ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
endIp := ip + 1
|
||||
for ; endIp <= netLimitUp; endIp++ {
|
||||
if _, ok := existedNetMap[endIp]; ok {
|
||||
if _, ok := existedNets.Get(endIp); ok {
|
||||
break
|
||||
}
|
||||
if proc, ok := ni.IPPool.Get(endIp); ok {
|
||||
if proc.VlanId == vlan {
|
||||
if proc, ok := ipPool.Get(endIp); ok {
|
||||
if proc.VlanId == vlan && proc.VSId == ni.fakeVsId {
|
||||
// find one in ips
|
||||
i++
|
||||
continue
|
||||
@@ -729,8 +745,9 @@ func (scm *SCloudaccountManager) parseAndSuggest(params sParseAndSuggest) api.Cl
|
||||
},
|
||||
})
|
||||
// Avoid assigning already assigned ip subnet
|
||||
existedNetMap[startIp+1] = simpleNet{}
|
||||
existedNetMap[endIp-1] = simpleNet{}
|
||||
existedNets.Insert(startIp+1, sSimpleNet{
|
||||
Diff: endIp - startIp - 2,
|
||||
})
|
||||
}
|
||||
}
|
||||
output.CAWireNets = append(output.CAWireNets, wireNet)
|
||||
@@ -824,6 +841,64 @@ func (manager *SCloudaccountManager) suggestHostNetworks(ips []netutils.IPV4Addr
|
||||
return ret
|
||||
}
|
||||
|
||||
type sIPPool struct {
|
||||
netranges []netutils.IPV4Addr
|
||||
simpleNetMap map[netutils.IPV4Addr]sSimpleNet
|
||||
}
|
||||
|
||||
func newIPPool(length ...int) *sIPPool {
|
||||
initLen := 0
|
||||
if len(length) > 0 {
|
||||
initLen = length[0]
|
||||
}
|
||||
return &sIPPool{
|
||||
netranges: make([]netutils.IPV4Addr, 0, initLen),
|
||||
simpleNetMap: make(map[netutils.IPV4Addr]sSimpleNet, initLen),
|
||||
}
|
||||
}
|
||||
|
||||
type sSimpleNet struct {
|
||||
Diff netutils.IPV4Addr
|
||||
Id string
|
||||
Vlan int32
|
||||
WireId string
|
||||
}
|
||||
|
||||
func (pl *sIPPool) Insert(startIp netutils.IPV4Addr, sNet sSimpleNet) {
|
||||
// TODO:check
|
||||
index := pl.getIndex(startIp)
|
||||
pl.netranges = append(pl.netranges, 0)
|
||||
pl.netranges = append(pl.netranges[:index+1], pl.netranges[index:len(pl.netranges)-1]...)
|
||||
pl.netranges[index] = startIp
|
||||
pl.simpleNetMap[startIp] = sNet
|
||||
}
|
||||
|
||||
func (pl *sIPPool) getIndex(ip netutils.IPV4Addr) int {
|
||||
index := sort.Search(len(pl.netranges), func(n int) bool {
|
||||
return pl.netranges[n] >= ip
|
||||
})
|
||||
return index
|
||||
}
|
||||
|
||||
func (pl *sIPPool) Get(ip netutils.IPV4Addr) (sSimpleNet, bool) {
|
||||
index := pl.getIndex(ip)
|
||||
if index > len(pl.netranges) || index < 0 {
|
||||
return sSimpleNet{}, false
|
||||
}
|
||||
if index < len(pl.netranges) && pl.netranges[index] == ip {
|
||||
return pl.simpleNetMap[ip], true
|
||||
}
|
||||
if index == 0 {
|
||||
return sSimpleNet{}, false
|
||||
}
|
||||
startIp := pl.netranges[index-1]
|
||||
simpleNet := pl.simpleNetMap[startIp]
|
||||
if ip-startIp <= simpleNet.Diff {
|
||||
return simpleNet, true
|
||||
}
|
||||
return sSimpleNet{}, false
|
||||
}
|
||||
|
||||
// The suggestVMNetworks give the suggest config of network that contain the IP in 'ips' and does not intersect with the network segment described in 'excludes'.
|
||||
// The suggested network mask is 24 and the gateway is x.x.x.1.
|
||||
// The suggests network is the largest network segment that meets the above conditions.
|
||||
|
||||
@@ -395,6 +395,15 @@ func (p *SIPPool) Has(ip netutils.IPV4Addr) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
func (p *SIPPool) FillVsId(vsId string) {
|
||||
for k, v := range p.p {
|
||||
p.p[k] = SIPProc{
|
||||
VlanId: v.VlanId,
|
||||
VSId: vsId,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *SIPPool) Get(ip netutils.IPV4Addr) (SIPProc, bool) {
|
||||
r, ok := p.p[ip]
|
||||
return r, ok
|
||||
|
||||
Reference in New Issue
Block a user