mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
feat(region): add wire level for preparing network
There are three wire level for vmware: vcenter, datacenter and cluster. According to different wire levels, the recommended network has a different structure.
This commit is contained in:
@@ -334,9 +334,16 @@ type CloudaccountPerformPublicInput struct {
|
||||
|
||||
type CloudaccountPerformPrepareNetsInput struct {
|
||||
CloudaccountCreateInput
|
||||
|
||||
// enum: vcenter,datacenter,cluster
|
||||
WireLevelForVmware string `json:"wire_level_for_vmware"`
|
||||
}
|
||||
|
||||
type CloudaccountPerformPrepareNetsOutput struct {
|
||||
CAWireNets []CAWireNet `json:"wire_networks"`
|
||||
}
|
||||
|
||||
type CAWireNet struct {
|
||||
SuggestedWire CAWireConf `json:"suggested_wire"`
|
||||
SuitableWire string `json:"suitable_wire,allowempty"`
|
||||
Hosts []CAHostNet `json:"hosts"`
|
||||
|
||||
@@ -61,6 +61,10 @@ const (
|
||||
|
||||
ZSTACK_BRAND_DSTACK = "DStack"
|
||||
ONECLOUD_BRAND_ONECLOUD = "OneCloud"
|
||||
|
||||
CLOUD_ACCOUNT_WIRE_LEVEL_VCENTER = "vcenter"
|
||||
CLOUD_ACCOUNT_WIRE_LEVEL_DATACENTER = "datacenter"
|
||||
CLOUD_ACCOUNT_WIRE_LEVEL_CLUSTER = "cluster"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
+333
-255
@@ -357,6 +357,74 @@ func (scm *SCloudaccountManager) AllowPerformPrepareNets(_ context.Context, user
|
||||
return db.IsAdminAllowPerform(userCred, scm, "prepare-nets")
|
||||
}
|
||||
|
||||
type sHostVMIp struct {
|
||||
hostIps map[string]string
|
||||
vms []esxi.SSimpleVM
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (scm *SCloudaccountManager) hostVMIPsPrepareNets(ctx context.Context, client *esxi.SESXiClient, input api.CloudaccountPerformPrepareNetsInput) ([]sHostVMIp, error) {
|
||||
caName := input.Name
|
||||
wireLevel := input.WireLevelForVmware
|
||||
ret := make([]sHostVMIp, 0)
|
||||
if len(wireLevel) == 0 {
|
||||
wireLevel = api.CLOUD_ACCOUNT_WIRE_LEVEL_VCENTER
|
||||
}
|
||||
switch wireLevel {
|
||||
case api.CLOUD_ACCOUNT_WIRE_LEVEL_VCENTER:
|
||||
hostIps, simpleVms, err := client.HostVmIPs(ctx)
|
||||
if err != nil {
|
||||
return ret, errors.Wrap(err, "unable to fetch ips of hosts and vms")
|
||||
}
|
||||
ret = append(ret, sHostVMIp{
|
||||
hostIps: hostIps,
|
||||
vms: simpleVms,
|
||||
prefix: caName,
|
||||
})
|
||||
case api.CLOUD_ACCOUNT_WIRE_LEVEL_DATACENTER:
|
||||
dcs, err := client.GetDatacenters()
|
||||
if err != nil {
|
||||
return ret, errors.Wrap(err, "GetDatacenters")
|
||||
}
|
||||
for _, dc := range dcs {
|
||||
hostIps, simpleVms, err := client.HostVmIPsInDc(ctx, dc)
|
||||
if err != nil {
|
||||
return ret, errors.Wrapf(err, "unable to fetch ips of hosts and vms for dc %q", dc.GetName())
|
||||
}
|
||||
ret = append(ret, sHostVMIp{
|
||||
hostIps: hostIps,
|
||||
vms: simpleVms,
|
||||
prefix: fmt.Sprintf("%s/%s", caName, dc.GetName()),
|
||||
})
|
||||
}
|
||||
case api.CLOUD_ACCOUNT_WIRE_LEVEL_CLUSTER:
|
||||
dcs, err := client.GetDatacenters()
|
||||
if err != nil {
|
||||
return ret, errors.Wrap(err, "GetDatacenters")
|
||||
}
|
||||
for _, dc := range dcs {
|
||||
clusters, err := dc.ListClusters()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to ListCluster for dc %q", dc.GetName())
|
||||
}
|
||||
for _, cluster := range clusters {
|
||||
hostIps, simpleVms, err := client.HostVmIPsInCluster(ctx, cluster)
|
||||
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())
|
||||
}
|
||||
ret = append(ret, sHostVMIp{
|
||||
hostIps: hostIps,
|
||||
vms: simpleVms,
|
||||
prefix: fmt.Sprintf("%s/%s/%s", caName, dc.GetName(), cluster.GetName()),
|
||||
})
|
||||
}
|
||||
}
|
||||
default:
|
||||
return nil, httperrors.NewInputParameterError("valid wire_level_for_vmware, accept vcenter, datacenter, cluster")
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Performpreparenets searches for suitable network facilities for physical and virtual machines under the cloud account or provides configuration recommendations for network facilities before importing a cloud account.
|
||||
func (scm *SCloudaccountManager) PerformPrepareNets(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.CloudaccountPerformPrepareNetsInput) (api.CloudaccountPerformPrepareNetsOutput, error) {
|
||||
var (
|
||||
@@ -438,9 +506,9 @@ func (scm *SCloudaccountManager) PerformPrepareNets(ctx context.Context, userCre
|
||||
}
|
||||
// hack
|
||||
client := iregion.(*esxi.SESXiClient)
|
||||
hostIps, simpleVms, err := client.HostVmIPs(ctx)
|
||||
hostVMIPs, err := scm.hostVMIPsPrepareNets(ctx, client, input)
|
||||
if err != nil {
|
||||
return output, errors.Wrap(err, "unable to fetch ips of hosts and vms")
|
||||
return output, err
|
||||
}
|
||||
// fetch networks
|
||||
networks := make([][]SNetwork, len(wires))
|
||||
@@ -451,198 +519,181 @@ func (scm *SCloudaccountManager) PerformPrepareNets(ctx context.Context, userCre
|
||||
}
|
||||
networks[i] = nets
|
||||
}
|
||||
output.CAWireNets = make([]api.CAWireNet, 0, len(hostVMIPs))
|
||||
for _, hv := range hostVMIPs {
|
||||
var (
|
||||
wireNet api.CAWireNet
|
||||
hostIps = hv.hostIps
|
||||
simpleVms = hv.vms
|
||||
prefix = hv.prefix
|
||||
)
|
||||
|
||||
// key of ipHosts is host's ip
|
||||
ipHosts := make(map[netutils.IPV4Addr]string, len(hostIps))
|
||||
for name, ip := range hostIps {
|
||||
addr, err := netutils.NewIPV4Addr(ip)
|
||||
if err != nil {
|
||||
return output, err
|
||||
}
|
||||
ipHosts[addr] = name
|
||||
}
|
||||
// Find suitable wire and the network containing the Host IP in suitable wire.
|
||||
var (
|
||||
tmpSocre int
|
||||
maxScore = len(ipHosts)
|
||||
suitableWire *SWire
|
||||
suitableNetworks map[netutils.IPV4Addr]*SNetwork
|
||||
)
|
||||
for i, nets := range networks {
|
||||
score := 0
|
||||
tmpSNs := make(map[netutils.IPV4Addr]*SNetwork)
|
||||
ipRanges := make([]netutils.IPV4AddrRange, len(nets))
|
||||
for i2 := range ipRanges {
|
||||
ipRanges[i2] = nets[i2].GetIPRange()
|
||||
}
|
||||
for ip := range ipHosts {
|
||||
for i := range ipRanges {
|
||||
if !ipRanges[i].Contains(ip) {
|
||||
continue
|
||||
}
|
||||
tmpSNs[ip] = &nets[i]
|
||||
score += 1
|
||||
break
|
||||
}
|
||||
}
|
||||
if score > tmpSocre {
|
||||
tmpSocre = score
|
||||
suitableWire = &wires[i]
|
||||
suitableNetworks = tmpSNs
|
||||
}
|
||||
if tmpSocre == maxScore {
|
||||
break
|
||||
}
|
||||
}
|
||||
if suitableWire != nil {
|
||||
output.SuitableWire = suitableWire.GetId()
|
||||
} else {
|
||||
output.SuggestedWire = api.CAWireConf{
|
||||
ZoneIds: zoneids,
|
||||
Name: input.Name + "-wire",
|
||||
Description: fmt.Sprintf("Auto created Wire for VMware account %q", input.Name),
|
||||
}
|
||||
}
|
||||
|
||||
// Give the suggested network configuration for the Host IP that does not have a corresponding suitable network.
|
||||
noNetHostIP := make([]netutils.IPV4Addr, 0, len(ipHosts))
|
||||
for ip, name := range ipHosts {
|
||||
rnet := api.CAHostNet{
|
||||
Name: name,
|
||||
IP: ip.String(),
|
||||
}
|
||||
if net, ok := suitableNetworks[ip]; ok {
|
||||
rnet.SuitableNetwork = net.GetId()
|
||||
} else {
|
||||
noNetHostIP = append(noNetHostIP, ip)
|
||||
}
|
||||
output.Hosts = append(output.Hosts, rnet)
|
||||
}
|
||||
|
||||
if len(noNetHostIP) > 0 {
|
||||
sConfs := scm.suggestHostNetworks(noNetHostIP)
|
||||
confs := make([]api.CANetConf, len(sConfs))
|
||||
for i := range confs {
|
||||
confs[i].CASimpleNetConf = sConfs[i]
|
||||
confs[i].Name = fmt.Sprintf("%s-host-network-%d", input.Name, i+1)
|
||||
}
|
||||
output.HostSuggestedNetworks = confs
|
||||
}
|
||||
|
||||
// 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, err = suitableWire.getNetworks(userCred, rbacutils.ScopeSystem)
|
||||
if err != nil {
|
||||
return output, err
|
||||
}
|
||||
}
|
||||
|
||||
type vm struct {
|
||||
FakeID int
|
||||
IP netutils.IPV4Addr
|
||||
Name string
|
||||
VlanID int32
|
||||
}
|
||||
vms := make([]vm, 0, len(simpleVms))
|
||||
var nip netutils.IPV4Addr
|
||||
guestMap := make(map[int]*api.CAGuestNet)
|
||||
for i := range simpleVms {
|
||||
id := i
|
||||
if len(simpleVms[i].IPVlans) == 0 {
|
||||
if _, ok := guestMap[id]; !ok {
|
||||
guestMap[id] = &api.CAGuestNet{
|
||||
Name: simpleVms[i].Name,
|
||||
IPNets: []api.CAIPNet{},
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, ipVlan := range simpleVms[i].IPVlans {
|
||||
nip, err = netutils.NewIPV4Addr(ipVlan.IP)
|
||||
// key of ipHosts is host's ip
|
||||
ipHosts := make(map[netutils.IPV4Addr]string, len(hostIps))
|
||||
for name, ip := range hostIps {
|
||||
addr, err := netutils.NewIPV4Addr(ip)
|
||||
if err != nil {
|
||||
return output, err
|
||||
}
|
||||
vms = append(vms, vm{
|
||||
FakeID: i,
|
||||
IP: nip,
|
||||
Name: simpleVms[i].Name,
|
||||
VlanID: ipVlan.VlanID,
|
||||
})
|
||||
ipHosts[addr] = name
|
||||
}
|
||||
}
|
||||
// sort vms via vm's ip
|
||||
sort.Slice(vms, func(i, j int) bool {
|
||||
return vms[i].IP < vms[j].IP
|
||||
})
|
||||
|
||||
type sExcludeNet struct {
|
||||
StartIp netutils.IPV4Addr
|
||||
EndIp netutils.IPV4Addr
|
||||
Id string
|
||||
}
|
||||
excludeNets := make([]sExcludeNet, 0, len(allNets)+len(output.HostSuggestedNetworks))
|
||||
for i := range allNets {
|
||||
startIp, _ := netutils.NewIPV4Addr(allNets[i].GuestIpStart)
|
||||
endIp, _ := netutils.NewIPV4Addr(allNets[i].GuestIpEnd)
|
||||
excludeNets = append(excludeNets, sExcludeNet{
|
||||
StartIp: startIp,
|
||||
EndIp: endIp,
|
||||
Id: allNets[i].GetId(),
|
||||
})
|
||||
}
|
||||
for i := range output.HostSuggestedNetworks {
|
||||
startIp, _ := netutils.NewIPV4Addr(output.HostSuggestedNetworks[i].GuestIpStart)
|
||||
endIp, _ := netutils.NewIPV4Addr(output.HostSuggestedNetworks[i].GuestIpEnd)
|
||||
excludeNets = append(excludeNets, sExcludeNet{
|
||||
StartIp: startIp,
|
||||
EndIp: endIp,
|
||||
})
|
||||
}
|
||||
// sort excludeNets via their GuestIpStart
|
||||
sort.Slice(excludeNets, func(i, j int) bool {
|
||||
return excludeNets[i].StartIp < excludeNets[j].StartIp
|
||||
})
|
||||
|
||||
svNets := make([]api.CASimpleNetConf, 0, 5)
|
||||
var vmi, neti int
|
||||
|
||||
Loop:
|
||||
for neti = 0; neti < len(excludeNets); {
|
||||
if vmi >= len(vms) {
|
||||
break
|
||||
// Find suitable wire and the network containing the Host IP in suitable wire.
|
||||
var (
|
||||
tmpSocre int
|
||||
maxScore = len(ipHosts)
|
||||
suitableWire *SWire
|
||||
suitableNetworks map[netutils.IPV4Addr]*SNetwork
|
||||
)
|
||||
for i, nets := range networks {
|
||||
score := 0
|
||||
tmpSNs := make(map[netutils.IPV4Addr]*SNetwork)
|
||||
ipRanges := make([]netutils.IPV4AddrRange, len(nets))
|
||||
for i2 := range ipRanges {
|
||||
ipRanges[i2] = nets[i2].GetIPRange()
|
||||
}
|
||||
for ip := range ipHosts {
|
||||
for i := range ipRanges {
|
||||
if !ipRanges[i].Contains(ip) {
|
||||
continue
|
||||
}
|
||||
tmpSNs[ip] = &nets[i]
|
||||
score += 1
|
||||
break
|
||||
}
|
||||
}
|
||||
if score > tmpSocre {
|
||||
tmpSocre = score
|
||||
suitableWire = &wires[i]
|
||||
suitableNetworks = tmpSNs
|
||||
}
|
||||
if tmpSocre == maxScore {
|
||||
break
|
||||
}
|
||||
}
|
||||
startIp := excludeNets[neti].StartIp
|
||||
endIp := excludeNets[neti].EndIp
|
||||
switch {
|
||||
case vms[vmi].IP > endIp:
|
||||
neti++
|
||||
case vms[vmi].IP >= startIp:
|
||||
for vms[vmi].IP <= endIp {
|
||||
id := vms[vmi].FakeID
|
||||
if suitableWire != nil {
|
||||
wireNet.SuitableWire = suitableWire.GetId()
|
||||
} else {
|
||||
wireNet.SuggestedWire = api.CAWireConf{
|
||||
ZoneIds: zoneids,
|
||||
Name: prefix + "-wire",
|
||||
Description: fmt.Sprintf("Auto created Wire for VMware account %q", input.Name),
|
||||
}
|
||||
}
|
||||
|
||||
// Give the suggested network configuration for the Host IP that does not have a corresponding suitable network.
|
||||
noNetHostIP := make([]netutils.IPV4Addr, 0, len(ipHosts))
|
||||
for ip, name := range ipHosts {
|
||||
rnet := api.CAHostNet{
|
||||
Name: name,
|
||||
IP: ip.String(),
|
||||
}
|
||||
if net, ok := suitableNetworks[ip]; ok {
|
||||
rnet.SuitableNetwork = net.GetId()
|
||||
} else {
|
||||
noNetHostIP = append(noNetHostIP, ip)
|
||||
}
|
||||
wireNet.Hosts = append(wireNet.Hosts, rnet)
|
||||
}
|
||||
|
||||
if len(noNetHostIP) > 0 {
|
||||
sConfs := scm.suggestHostNetworks(noNetHostIP)
|
||||
confs := make([]api.CANetConf, len(sConfs))
|
||||
for i := range confs {
|
||||
confs[i].CASimpleNetConf = sConfs[i]
|
||||
confs[i].Name = fmt.Sprintf("%s-host-network-%d", prefix, i+1)
|
||||
}
|
||||
wireNet.HostSuggestedNetworks = confs
|
||||
}
|
||||
|
||||
// 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, err = suitableWire.getNetworks(userCred, rbacutils.ScopeSystem)
|
||||
if err != nil {
|
||||
return output, err
|
||||
}
|
||||
}
|
||||
|
||||
type vm struct {
|
||||
FakeID int
|
||||
IP netutils.IPV4Addr
|
||||
Name string
|
||||
VlanID int32
|
||||
}
|
||||
vms := make([]vm, 0, len(simpleVms))
|
||||
var nip netutils.IPV4Addr
|
||||
guestMap := make(map[int]*api.CAGuestNet)
|
||||
for i := range simpleVms {
|
||||
id := i
|
||||
if len(simpleVms[i].IPVlans) == 0 {
|
||||
if _, ok := guestMap[id]; !ok {
|
||||
guestMap[id] = &api.CAGuestNet{
|
||||
Name: vms[vmi].Name,
|
||||
Name: simpleVms[i].Name,
|
||||
IPNets: []api.CAIPNet{},
|
||||
}
|
||||
}
|
||||
guestMap[id].IPNets = append(guestMap[id].IPNets, api.CAIPNet{
|
||||
IP: vms[vmi].IP.String(),
|
||||
SuitableNetwork: excludeNets[neti].Id,
|
||||
VlanID: vms[vmi].VlanID,
|
||||
})
|
||||
vmi += 1
|
||||
if vmi == len(vms) {
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
neti++
|
||||
default:
|
||||
for vms[vmi].IP < startIp {
|
||||
suggestStartIp := vms[vmi].IP
|
||||
suggestEndIp := vms[vmi].IP
|
||||
endLimitIp := suggestStartIp.NetAddr(24) + 255
|
||||
vlanId := vms[vmi].VlanID
|
||||
for {
|
||||
for _, ipVlan := range simpleVms[i].IPVlans {
|
||||
nip, err = netutils.NewIPV4Addr(ipVlan.IP)
|
||||
if err != nil {
|
||||
return output, err
|
||||
}
|
||||
vms = append(vms, vm{
|
||||
FakeID: i,
|
||||
IP: nip,
|
||||
Name: simpleVms[i].Name,
|
||||
VlanID: ipVlan.VlanID,
|
||||
})
|
||||
}
|
||||
}
|
||||
// sort vms via vm's ip
|
||||
sort.Slice(vms, func(i, j int) bool {
|
||||
return vms[i].IP < vms[j].IP
|
||||
})
|
||||
|
||||
type sExcludeNet struct {
|
||||
StartIp netutils.IPV4Addr
|
||||
EndIp netutils.IPV4Addr
|
||||
Id string
|
||||
}
|
||||
excludeNets := make([]sExcludeNet, 0, len(allNets)+len(wireNet.HostSuggestedNetworks))
|
||||
for i := range allNets {
|
||||
startIp, _ := netutils.NewIPV4Addr(allNets[i].GuestIpStart)
|
||||
endIp, _ := netutils.NewIPV4Addr(allNets[i].GuestIpEnd)
|
||||
excludeNets = append(excludeNets, sExcludeNet{
|
||||
StartIp: startIp,
|
||||
EndIp: endIp,
|
||||
Id: allNets[i].GetId(),
|
||||
})
|
||||
}
|
||||
for i := range wireNet.HostSuggestedNetworks {
|
||||
startIp, _ := netutils.NewIPV4Addr(wireNet.HostSuggestedNetworks[i].GuestIpStart)
|
||||
endIp, _ := netutils.NewIPV4Addr(wireNet.HostSuggestedNetworks[i].GuestIpEnd)
|
||||
excludeNets = append(excludeNets, sExcludeNet{
|
||||
StartIp: startIp,
|
||||
EndIp: endIp,
|
||||
})
|
||||
}
|
||||
// sort excludeNets via their GuestIpStart
|
||||
sort.Slice(excludeNets, func(i, j int) bool {
|
||||
return excludeNets[i].StartIp < excludeNets[j].StartIp
|
||||
})
|
||||
|
||||
svNets := make([]api.CASimpleNetConf, 0, 5)
|
||||
var vmi, neti int
|
||||
|
||||
Loop:
|
||||
for neti = 0; neti < len(excludeNets); {
|
||||
if vmi >= len(vms) {
|
||||
break
|
||||
}
|
||||
startIp := excludeNets[neti].StartIp
|
||||
endIp := excludeNets[neti].EndIp
|
||||
switch {
|
||||
case vms[vmi].IP > endIp:
|
||||
neti++
|
||||
case vms[vmi].IP >= startIp:
|
||||
for vms[vmi].IP <= endIp {
|
||||
id := vms[vmi].FakeID
|
||||
if _, ok := guestMap[id]; !ok {
|
||||
guestMap[id] = &api.CAGuestNet{
|
||||
@@ -651,92 +702,119 @@ Loop:
|
||||
}
|
||||
}
|
||||
guestMap[id].IPNets = append(guestMap[id].IPNets, api.CAIPNet{
|
||||
IP: vms[vmi].IP.String(),
|
||||
VlanID: vms[vmi].VlanID,
|
||||
IP: vms[vmi].IP.String(),
|
||||
SuitableNetwork: excludeNets[neti].Id,
|
||||
VlanID: vms[vmi].VlanID,
|
||||
})
|
||||
vmi++
|
||||
vmi += 1
|
||||
if vmi == len(vms) {
|
||||
break
|
||||
break Loop
|
||||
}
|
||||
if suggestEndIp == endLimitIp {
|
||||
break
|
||||
}
|
||||
if vms[vmi].IP > suggestEndIp+1 {
|
||||
break
|
||||
}
|
||||
if vms[vmi].IP >= startIp {
|
||||
break
|
||||
}
|
||||
if vms[vmi].VlanID != vlanId {
|
||||
break
|
||||
}
|
||||
suggestEndIp = vms[vmi].IP
|
||||
}
|
||||
svNets = append(svNets, api.CASimpleNetConf{
|
||||
GuestIpStart: suggestStartIp.String(),
|
||||
GuestIpEnd: suggestEndIp.String(),
|
||||
VlanID: vlanId,
|
||||
GuestIpMask: 24,
|
||||
GuestGateway: (suggestStartIp.NetAddr(24) + netutils.IPV4Addr(options.Options.DefaultNetworkGatewayAddressEsxi)).String(),
|
||||
neti++
|
||||
default:
|
||||
for vms[vmi].IP < startIp {
|
||||
suggestStartIp := vms[vmi].IP
|
||||
suggestEndIp := vms[vmi].IP
|
||||
endLimitIp := suggestStartIp.NetAddr(24) + 255
|
||||
vlanId := vms[vmi].VlanID
|
||||
for {
|
||||
id := vms[vmi].FakeID
|
||||
if _, ok := guestMap[id]; !ok {
|
||||
guestMap[id] = &api.CAGuestNet{
|
||||
Name: vms[vmi].Name,
|
||||
IPNets: []api.CAIPNet{},
|
||||
}
|
||||
}
|
||||
guestMap[id].IPNets = append(guestMap[id].IPNets, api.CAIPNet{
|
||||
IP: vms[vmi].IP.String(),
|
||||
VlanID: vms[vmi].VlanID,
|
||||
})
|
||||
vmi++
|
||||
if vmi == len(vms) {
|
||||
break
|
||||
}
|
||||
if suggestEndIp == endLimitIp {
|
||||
break
|
||||
}
|
||||
if vms[vmi].IP > suggestEndIp+1 {
|
||||
break
|
||||
}
|
||||
if vms[vmi].IP >= startIp {
|
||||
break
|
||||
}
|
||||
if vms[vmi].VlanID != vlanId {
|
||||
break
|
||||
}
|
||||
suggestEndIp = vms[vmi].IP
|
||||
}
|
||||
svNets = append(svNets, api.CASimpleNetConf{
|
||||
GuestIpStart: suggestStartIp.String(),
|
||||
GuestIpEnd: suggestEndIp.String(),
|
||||
VlanID: vlanId,
|
||||
GuestIpMask: 24,
|
||||
GuestGateway: (suggestStartIp.NetAddr(24) + netutils.IPV4Addr(options.Options.DefaultNetworkGatewayAddressEsxi)).String(),
|
||||
})
|
||||
if vmi == len(vms) {
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for vmi < len(vms) {
|
||||
suggestStartIp := vms[vmi].IP
|
||||
endLimitIp := suggestStartIp.NetAddr(24) + 255
|
||||
suggestEndIp := suggestStartIp
|
||||
vlanId := vms[vmi].VlanID
|
||||
for {
|
||||
id := vms[vmi].FakeID
|
||||
if _, ok := guestMap[id]; !ok {
|
||||
guestMap[id] = &api.CAGuestNet{
|
||||
Name: vms[vmi].Name,
|
||||
IPNets: []api.CAIPNet{},
|
||||
}
|
||||
}
|
||||
guestMap[id].IPNets = append(guestMap[id].IPNets, api.CAIPNet{
|
||||
IP: vms[vmi].IP.String(),
|
||||
})
|
||||
vmi++
|
||||
if vmi == len(vms) {
|
||||
break Loop
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for vmi < len(vms) {
|
||||
suggestStartIp := vms[vmi].IP
|
||||
endLimitIp := suggestStartIp.NetAddr(24) + 255
|
||||
suggestEndIp := suggestStartIp
|
||||
vlanId := vms[vmi].VlanID
|
||||
for {
|
||||
id := vms[vmi].FakeID
|
||||
if _, ok := guestMap[id]; !ok {
|
||||
guestMap[id] = &api.CAGuestNet{
|
||||
Name: vms[vmi].Name,
|
||||
IPNets: []api.CAIPNet{},
|
||||
if suggestEndIp == endLimitIp {
|
||||
break
|
||||
}
|
||||
if vms[vmi].IP > suggestEndIp+1 {
|
||||
break
|
||||
}
|
||||
if vms[vmi].VlanID != vlanId {
|
||||
break
|
||||
}
|
||||
suggestEndIp = vms[vmi].IP
|
||||
}
|
||||
guestMap[id].IPNets = append(guestMap[id].IPNets, api.CAIPNet{
|
||||
IP: vms[vmi].IP.String(),
|
||||
svNets = append(svNets, api.CASimpleNetConf{
|
||||
GuestIpStart: suggestStartIp.String(),
|
||||
GuestIpEnd: suggestEndIp.String(),
|
||||
VlanID: vlanId,
|
||||
GuestIpMask: 24,
|
||||
GuestGateway: (suggestStartIp.NetAddr(24) + netutils.IPV4Addr(options.Options.DefaultNetworkGatewayAddressEsxi)).String(),
|
||||
})
|
||||
vmi++
|
||||
if vmi == len(vms) {
|
||||
break
|
||||
}
|
||||
if suggestEndIp == endLimitIp {
|
||||
break
|
||||
}
|
||||
if vms[vmi].IP > suggestEndIp+1 {
|
||||
break
|
||||
}
|
||||
if vms[vmi].VlanID != vlanId {
|
||||
break
|
||||
}
|
||||
suggestEndIp = vms[vmi].IP
|
||||
}
|
||||
svNets = append(svNets, api.CASimpleNetConf{
|
||||
GuestIpStart: suggestStartIp.String(),
|
||||
GuestIpEnd: suggestEndIp.String(),
|
||||
VlanID: vlanId,
|
||||
GuestIpMask: 24,
|
||||
GuestGateway: (suggestStartIp.NetAddr(24) + netutils.IPV4Addr(options.Options.DefaultNetworkGatewayAddressEsxi)).String(),
|
||||
})
|
||||
}
|
||||
|
||||
for _, guest := range guestMap {
|
||||
output.Guests = append(output.Guests, *guest)
|
||||
}
|
||||
|
||||
if len(svNets) > 0 {
|
||||
confs := make([]api.CANetConf, len(svNets))
|
||||
for i := range confs {
|
||||
confs[i].CASimpleNetConf = svNets[i]
|
||||
confs[i].Name = fmt.Sprintf("%s-guest-network-%d", input.Name, i+1)
|
||||
for _, guest := range guestMap {
|
||||
wireNet.Guests = append(wireNet.Guests, *guest)
|
||||
}
|
||||
output.GuestSuggestedNetworks = confs
|
||||
|
||||
if len(svNets) > 0 {
|
||||
confs := make([]api.CANetConf, len(svNets))
|
||||
for i := range confs {
|
||||
confs[i].CASimpleNetConf = svNets[i]
|
||||
confs[i].Name = fmt.Sprintf("%s-guest-network-%d", prefix, i+1)
|
||||
}
|
||||
wireNet.GuestSuggestedNetworks = confs
|
||||
}
|
||||
output.CAWireNets = append(output.CAWireNets, wireNet)
|
||||
}
|
||||
return output, nil
|
||||
}
|
||||
|
||||
@@ -750,10 +750,12 @@ func (opts *SCtyunCloudAccountUpdateOptions) Params() (jsonutils.JSONObject, err
|
||||
}
|
||||
|
||||
type SVMwareCloudAccountPrepareNetsOptions struct {
|
||||
SVMwareCredentialWithEnvironment
|
||||
|
||||
Project string `help:"project for this account"`
|
||||
ProjectDomain string `help:"domain for this account"`
|
||||
WireLevel string `help:"wire level for this account" choices:"vcenter|datacenter|cluster" json:"wire_level_for_vmware"`
|
||||
NAME string `help:"name for this account"`
|
||||
SVMwareCredentialWithEnvironment
|
||||
}
|
||||
|
||||
func (opts *SVMwareCloudAccountPrepareNetsOptions) Params() (jsonutils.JSONObject, error) {
|
||||
|
||||
@@ -724,6 +724,69 @@ func (cli *SESXiClient) dvpgKeyVlanMap() (*sync.Map, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) HostVmIPsInDc(ctx context.Context, dc *SDatacenter) (map[string]string, []SSimpleVM, error) {
|
||||
var hosts []mo.HostSystem
|
||||
err := cli.scanMObjects(dc.object.Entity().Self, HOST_SYSTEM_PROPS, &hosts)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "scanMObjects")
|
||||
}
|
||||
return cli.hostVMIPs(ctx, hosts)
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) HostVmIPsInCluster(ctx context.Context, cluster *SCluster) (map[string]string, []SSimpleVM,
|
||||
error) {
|
||||
var hosts []mo.HostSystem
|
||||
err := cli.scanMObjects(cluster.object.Entity().Self, HOST_SYSTEM_PROPS, &hosts)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "scanMObjects")
|
||||
}
|
||||
return cli.hostVMIPs(ctx, hosts)
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) hostVMIPs(ctx context.Context, hosts []mo.HostSystem) (map[string]string, []SSimpleVM, error) {
|
||||
dvpgKeyVlanMap, err := cli.dvpgKeyVlanMap()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "unable to get dvpgKeyVlanMap")
|
||||
}
|
||||
group, ctx := errgroup.WithContext(ctx)
|
||||
collection := make([][]SSimpleVM, len(hosts))
|
||||
for i := range hosts {
|
||||
j := i
|
||||
group.Go(func() error {
|
||||
vmIps, err := cli.vmIPs(&hosts[j], dvpgKeyVlanMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
collection[j] = vmIps
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
hostIps := make(map[string]string, len(hosts))
|
||||
for i := range hosts {
|
||||
// find ip
|
||||
host := &SHost{SManagedObject: newManagedObject(cli, &hosts[i], nil)}
|
||||
ip := host.GetAccessIp()
|
||||
hostIps[host.GetName()] = ip
|
||||
}
|
||||
err = group.Wait()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// length
|
||||
length := 0
|
||||
for i := range collection {
|
||||
length += len(collection[i])
|
||||
}
|
||||
svms := make([]SSimpleVM, 0, length)
|
||||
for i := range collection {
|
||||
for j := range collection[i] {
|
||||
svms = append(svms, collection[i][j])
|
||||
}
|
||||
}
|
||||
return hostIps, svms, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) HostVmIPs(ctx context.Context) (map[string]string, []SSimpleVM, error) {
|
||||
dvpgKeyVlanMap, err := cli.dvpgKeyVlanMap()
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user