mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
feat(esxi): fetch vmware network configuration info
1. vswitch and distributed vswitch info 2. ip, vlanId and vswitch of host and vm
This commit is contained in:
@@ -19,7 +19,6 @@ import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -33,13 +32,10 @@ import (
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -688,265 +684,3 @@ func (cli *SESXiClient) MoveDisk(ctx context.Context, src, dst string, isForce b
|
||||
}
|
||||
return task.Wait(ctx)
|
||||
}
|
||||
|
||||
var (
|
||||
SIMPLE_HOST_PROPS = []string{"name", "config.network", "vm"}
|
||||
SIMPLE_VM_PROPS = []string{"name", "guest.net", "config.template", "config.hardware.device"}
|
||||
SIMPLE_DVPG_PROPS = []string{"key", "config.defaultPortConfig", "config.distributedVirtualSwitch"}
|
||||
SIMPLE_NETWORK_PROPS = []string{"name"}
|
||||
)
|
||||
|
||||
type SIPVlan struct {
|
||||
IP netutils.IPV4Addr
|
||||
VlanId int32
|
||||
}
|
||||
|
||||
type SSimpleVM struct {
|
||||
Name string
|
||||
IPVlans []SIPVlan
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) scanAllDvPortgroups() ([]*SDistributedVirtualPortgroup, error) {
|
||||
var modvpgs []mo.DistributedVirtualPortgroup
|
||||
err := cli.scanAllMObjects(SIMPLE_DVPG_PROPS, &modvpgs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "scanAllMObjects")
|
||||
}
|
||||
dvpgs := make([]*SDistributedVirtualPortgroup, 0, len(modvpgs))
|
||||
for i := range modvpgs {
|
||||
dvpgs = append(dvpgs, NewDistributedVirtualPortgroup(cli, &modvpgs[i], nil))
|
||||
}
|
||||
return dvpgs, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) scanAllNetworks() ([]mo.Network, error) {
|
||||
var monets []mo.Network
|
||||
err := cli.scanAllMObjects(SIMPLE_NETWORK_PROPS, &monets)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "scanAllMObjects")
|
||||
}
|
||||
return monets, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) networkName(refV string) (string, error) {
|
||||
if cli.networkQueryMap == nil {
|
||||
nets, err := cli.scanAllNetworks()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cli.networkQueryMap = &sync.Map{}
|
||||
for i := range nets {
|
||||
cli.networkQueryMap.Store(nets[i].Reference().Value, nets[i].Name)
|
||||
}
|
||||
}
|
||||
iter, ok := cli.networkQueryMap.Load(refV)
|
||||
if !ok {
|
||||
return "", nil
|
||||
}
|
||||
return iter.(string), nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) HostVmIPsInDc(ctx context.Context, dc *SDatacenter) (SNetworkInfo, error) {
|
||||
var hosts []mo.HostSystem
|
||||
err := cli.scanMObjects(dc.object.Entity().Self, HOST_SYSTEM_PROPS, &hosts)
|
||||
if err != nil {
|
||||
return SNetworkInfo{}, errors.Wrap(err, "scanMObjects")
|
||||
}
|
||||
return cli.hostVMIPs(ctx, hosts)
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) HostVmIPsInCluster(ctx context.Context, cluster *SCluster) (SNetworkInfo, error) {
|
||||
var hosts []mo.HostSystem
|
||||
err := cli.scanMObjects(cluster.object.Entity().Self, HOST_SYSTEM_PROPS, &hosts)
|
||||
if err != nil {
|
||||
return SNetworkInfo{}, errors.Wrap(err, "scanMObjects")
|
||||
}
|
||||
return cli.hostVMIPs(ctx, hosts)
|
||||
}
|
||||
|
||||
type SNetworkInfo struct {
|
||||
HostIps map[string]netutils.IPV4Addr
|
||||
VMs []SSimpleVM
|
||||
VlanIps map[int32][]netutils.IPV4Addr
|
||||
IPPool SIPPool
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) hostVMIPs(ctx context.Context, hosts []mo.HostSystem) (SNetworkInfo, error) {
|
||||
ret := SNetworkInfo{}
|
||||
dvpgMap, err := cli.getDVPGMap()
|
||||
if err != nil {
|
||||
return ret, errors.Wrap(err, "unable to get dvpgKeyVlanMap")
|
||||
}
|
||||
group, ctx := errgroup.WithContext(ctx)
|
||||
collection := make([]SNetworkInfo, len(hosts))
|
||||
for i := range hosts {
|
||||
j := i
|
||||
group.Go(func() error {
|
||||
nInfo, err := cli.vmIPs(&hosts[j], dvpgMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
collection[j] = nInfo
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
hostIps := make(map[string]netutils.IPV4Addr, len(hosts))
|
||||
for i := range hosts {
|
||||
// find ip
|
||||
host := &SHost{SManagedObject: newManagedObject(cli, &hosts[i], nil)}
|
||||
ipStr := host.GetAccessIp()
|
||||
ip, err := netutils.NewIPV4Addr(ipStr)
|
||||
if err != nil {
|
||||
return ret, errors.Wrapf(err, "invalid host ip %q", ipStr)
|
||||
}
|
||||
hostIps[host.GetName()] = ip
|
||||
}
|
||||
err = group.Wait()
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
// length
|
||||
if len(collection) == 0 {
|
||||
ret.HostIps = hostIps
|
||||
return ret, nil
|
||||
}
|
||||
ni := cli.mergeNetworInfo(collection)
|
||||
ni.HostIps = hostIps
|
||||
return ni, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) mergeNetworInfo(nInfos []SNetworkInfo) SNetworkInfo {
|
||||
var vmsLen, vlanIpLen, ipPoolLen int
|
||||
for i := range nInfos {
|
||||
vmsLen += len(nInfos[i].VMs)
|
||||
vlanIpLen += len(nInfos[i].VlanIps)
|
||||
ipPoolLen += nInfos[i].IPPool.Len()
|
||||
}
|
||||
ret := SNetworkInfo{
|
||||
VMs: make([]SSimpleVM, 0, vmsLen),
|
||||
VlanIps: make(map[int32][]netutils.IPV4Addr, vlanIpLen),
|
||||
IPPool: NewIPPool(ipPoolLen),
|
||||
}
|
||||
for i := range nInfos {
|
||||
ret.VMs = append(ret.VMs, nInfos[i].VMs...)
|
||||
for vlan, ips := range nInfos[i].VlanIps {
|
||||
ret.VlanIps[vlan] = append(ret.VlanIps[vlan], ips...)
|
||||
}
|
||||
ret.IPPool.Merge(&nInfos[i].IPPool)
|
||||
}
|
||||
for _, ips := range ret.VlanIps {
|
||||
sort.Slice(ips, func(i, j int) bool {
|
||||
return ips[i] < ips[j]
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) HostVmIPs(ctx context.Context) (SNetworkInfo, error) {
|
||||
var hosts []mo.HostSystem
|
||||
err := cli.scanAllMObjects(SIMPLE_HOST_PROPS, &hosts)
|
||||
if err != nil {
|
||||
return SNetworkInfo{}, errors.Wrap(err, "scanAllMObjects")
|
||||
}
|
||||
return cli.hostVMIPs(ctx, hosts)
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) macVlanMap(mohost *mo.HostSystem, movm *mo.VirtualMachine, dvpgMap sVPGMap) map[string]int32 {
|
||||
vpgMap := cli.getVPGMap(mohost)
|
||||
ret := make(map[string]int32, 2)
|
||||
for _, device := range movm.Config.Hardware.Device {
|
||||
bcard, ok := device.(types.BaseVirtualEthernetCard)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
card := bcard.GetVirtualEthernetCard()
|
||||
mac := card.MacAddress
|
||||
switch bk := card.Backing.(type) {
|
||||
case *types.VirtualEthernetCardDistributedVirtualPortBackingInfo:
|
||||
key := bk.Port.PortgroupKey
|
||||
proc, ok := dvpgMap.Get(key)
|
||||
if !ok {
|
||||
log.Errorf("dvpg %s not found in key-vlanid map", key)
|
||||
ret[mac] = 0
|
||||
continue
|
||||
}
|
||||
ret[mac] = proc.vlanId
|
||||
case *types.VirtualEthernetCardNetworkBackingInfo:
|
||||
netName, err := cli.networkName(bk.Network.Value)
|
||||
if err != nil {
|
||||
log.Errorf("get getNetworkName of %q: %v", bk.Network.Value, err)
|
||||
ret[mac] = 0
|
||||
continue
|
||||
}
|
||||
key := fmt.Sprintf("%s-%s", mohost.Reference().Value, netName)
|
||||
proc, ok := vpgMap.Get(key)
|
||||
if !ok {
|
||||
log.Errorf("vpg %s not found in key-vlanid map", key)
|
||||
ret[mac] = 0
|
||||
continue
|
||||
}
|
||||
ret[mac] = proc.vlanId
|
||||
default:
|
||||
ret[mac] = 0
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) vmIPs(host *mo.HostSystem, vpgMap sVPGMap) (SNetworkInfo, error) {
|
||||
nInfo := SNetworkInfo{
|
||||
VMs: make([]SSimpleVM, 0, len(host.Vm)),
|
||||
VlanIps: make(map[int32][]netutils.IPV4Addr),
|
||||
IPPool: NewIPPool(),
|
||||
}
|
||||
if len(host.Vm) == 0 {
|
||||
return nInfo, nil
|
||||
}
|
||||
var vms []mo.VirtualMachine
|
||||
err := cli.references2Objects(host.Vm, SIMPLE_VM_PROPS, &vms)
|
||||
if err != nil {
|
||||
return nInfo, errors.Wrap(err, "references2Objects")
|
||||
}
|
||||
for i := range vms {
|
||||
vm := vms[i]
|
||||
if vm.Config == nil || vm.Config.Template {
|
||||
continue
|
||||
}
|
||||
if vm.Guest == nil {
|
||||
continue
|
||||
}
|
||||
macVlanMap := cli.macVlanMap(host, &vm, vpgMap)
|
||||
guestIps := make([]SIPVlan, 0)
|
||||
for _, net := range vm.Guest.Net {
|
||||
if len(net.Network) == 0 {
|
||||
continue
|
||||
}
|
||||
mac := net.MacAddress
|
||||
for _, ip := range net.IpAddress {
|
||||
if !regutils.MatchIP4Addr(ip) {
|
||||
continue
|
||||
}
|
||||
if !vmIPV4Filter.Contains(ip) {
|
||||
continue
|
||||
}
|
||||
ipaddr, _ := netutils.NewIPV4Addr(ip)
|
||||
if netutils.IsLinkLocal(ipaddr) {
|
||||
continue
|
||||
}
|
||||
vlan := macVlanMap[mac]
|
||||
guestIps = append(guestIps, SIPVlan{
|
||||
IP: ipaddr,
|
||||
VlanId: vlan,
|
||||
})
|
||||
nInfo.VlanIps[vlan] = append(nInfo.VlanIps[vlan], ipaddr)
|
||||
nInfo.IPPool.Insert(ipaddr, SIPProc{
|
||||
VlanId: vlan,
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
nInfo.VMs = append(nInfo.VMs, SSimpleVM{vm.Name, guestIps})
|
||||
}
|
||||
return nInfo, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
// 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
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package esxi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
)
|
||||
|
||||
func (cli *SESXiClient) HostVmIPsInDc(ctx context.Context, dc *SDatacenter) (SNetworkInfo, error) {
|
||||
var hosts []mo.HostSystem
|
||||
err := cli.scanMObjects(dc.object.Entity().Self, HOST_SYSTEM_PROPS, &hosts)
|
||||
if err != nil {
|
||||
return SNetworkInfo{}, errors.Wrap(err, "scanMObjects")
|
||||
}
|
||||
return cli.hostVMIPs(ctx, hosts)
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) HostVmIPsInCluster(ctx context.Context, cluster *SCluster) (SNetworkInfo, error) {
|
||||
var hosts []mo.HostSystem
|
||||
err := cli.scanMObjects(cluster.object.Entity().Self, HOST_SYSTEM_PROPS, &hosts)
|
||||
if err != nil {
|
||||
return SNetworkInfo{}, errors.Wrap(err, "scanMObjects")
|
||||
}
|
||||
return cli.hostVMIPs(ctx, hosts)
|
||||
}
|
||||
|
||||
type SNetworkInfo struct {
|
||||
SNetworkInfoBase
|
||||
|
||||
HostIps map[string]netutils.IPV4Addr
|
||||
VlanIps map[int32][]netutils.IPV4Addr
|
||||
}
|
||||
|
||||
func (s *SNetworkInfo) Insert(proc SIPProc, ip netutils.IPV4Addr) {
|
||||
s.SNetworkInfoBase.Insert(proc, ip)
|
||||
s.VlanIps[proc.VlanId] = append(s.VlanIps[proc.VlanId], ip)
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) hostVMIPs(ctx context.Context, hosts []mo.HostSystem) (SNetworkInfo, error) {
|
||||
ret := SNetworkInfo{}
|
||||
dvpgMap, err := cli.getDVPGMap()
|
||||
if err != nil {
|
||||
return ret, errors.Wrap(err, "unable to get dvpgKeyVlanMap")
|
||||
}
|
||||
group, ctx := errgroup.WithContext(ctx)
|
||||
collection := make([]*SNetworkInfo, len(hosts))
|
||||
for i := range hosts {
|
||||
j := i
|
||||
group.Go(func() error {
|
||||
nInfo, err := cli.vmIPs(&hosts[j], dvpgMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
collection[j] = nInfo.(*SNetworkInfo)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
hostIps := make(map[string]netutils.IPV4Addr, len(hosts))
|
||||
for i := range hosts {
|
||||
// find ip
|
||||
host := &SHost{SManagedObject: newManagedObject(cli, &hosts[i], nil)}
|
||||
ipStr := host.GetAccessIp()
|
||||
ip, err := netutils.NewIPV4Addr(ipStr)
|
||||
if err != nil {
|
||||
return ret, errors.Wrapf(err, "invalid host ip %q", ipStr)
|
||||
}
|
||||
hostIps[host.GetName()] = ip
|
||||
}
|
||||
err = group.Wait()
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
// length
|
||||
if len(collection) == 0 {
|
||||
ret.HostIps = hostIps
|
||||
return ret, nil
|
||||
}
|
||||
ni := cli.mergeNetworInfo(collection)
|
||||
ni.HostIps = hostIps
|
||||
return ni, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) mergeNetworInfo(nInfos []*SNetworkInfo) SNetworkInfo {
|
||||
var vmsLen, vlanIpLen, ipPoolLen int
|
||||
for i := range nInfos {
|
||||
vmsLen += len(nInfos[i].VMs)
|
||||
vlanIpLen += len(nInfos[i].VlanIps)
|
||||
ipPoolLen += nInfos[i].IPPool.Len()
|
||||
}
|
||||
ret := SNetworkInfo{
|
||||
SNetworkInfoBase: SNetworkInfoBase{
|
||||
IPPool: NewIPPool(ipPoolLen),
|
||||
VMs: make([]SSimpleVM, 0, vmsLen),
|
||||
},
|
||||
VlanIps: make(map[int32][]netutils.IPV4Addr, vlanIpLen),
|
||||
}
|
||||
for i := range nInfos {
|
||||
ret.VMs = append(ret.VMs, nInfos[i].VMs...)
|
||||
for vlan, ips := range nInfos[i].VlanIps {
|
||||
ret.VlanIps[vlan] = append(ret.VlanIps[vlan], ips...)
|
||||
}
|
||||
ret.IPPool.Merge(&nInfos[i].IPPool)
|
||||
}
|
||||
for _, ips := range ret.VlanIps {
|
||||
sort.Slice(ips, func(i, j int) bool {
|
||||
return ips[i] < ips[j]
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) HostVmIPs(ctx context.Context) (SNetworkInfo, error) {
|
||||
var hosts []mo.HostSystem
|
||||
err := cli.scanAllMObjects(SIMPLE_HOST_PROPS, &hosts)
|
||||
if err != nil {
|
||||
return SNetworkInfo{}, errors.Wrap(err, "scanAllMObjects")
|
||||
}
|
||||
return cli.hostVMIPs(ctx, hosts)
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) vmIPs(host *mo.HostSystem, vpgMap sVPGMap) (INetworkInfo, error) {
|
||||
nInfo := NewNetworkInfo(false, len(host.Vm))
|
||||
if len(host.Vm) == 0 {
|
||||
return nInfo, nil
|
||||
}
|
||||
var vms []mo.VirtualMachine
|
||||
err := cli.references2Objects(host.Vm, SIMPLE_VM_PROPS, &vms)
|
||||
if err != nil {
|
||||
return nInfo, errors.Wrap(err, "references2Objects")
|
||||
}
|
||||
for i := range vms {
|
||||
vm := vms[i]
|
||||
if vm.Config == nil || vm.Config.Template {
|
||||
continue
|
||||
}
|
||||
if vm.Guest == nil {
|
||||
continue
|
||||
}
|
||||
macVlanMap, err := cli.macVlanMap(host, &vm, vpgMap)
|
||||
if err != nil {
|
||||
return nInfo, errors.Wrap(err, "macVlanMap")
|
||||
}
|
||||
guestIps := make([]SIPVlan, 0)
|
||||
for _, net := range vm.Guest.Net {
|
||||
if len(net.Network) == 0 {
|
||||
continue
|
||||
}
|
||||
mac := net.MacAddress
|
||||
for _, ip := range net.IpAddress {
|
||||
if !regutils.MatchIP4Addr(ip) {
|
||||
continue
|
||||
}
|
||||
if !vmIPV4Filter.Contains(ip) {
|
||||
continue
|
||||
}
|
||||
ipaddr, _ := netutils.NewIPV4Addr(ip)
|
||||
if netutils.IsLinkLocal(ipaddr) {
|
||||
continue
|
||||
}
|
||||
proc := macVlanMap[mac]
|
||||
guestIps = append(guestIps, SIPVlan{
|
||||
IP: ipaddr,
|
||||
VlanId: proc.VlanId,
|
||||
})
|
||||
nInfo.Insert(proc, ipaddr)
|
||||
break
|
||||
}
|
||||
}
|
||||
nInfo.AppendVMs(vm.Name, guestIps)
|
||||
}
|
||||
return nInfo, nil
|
||||
}
|
||||
@@ -0,0 +1,671 @@
|
||||
// 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
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package esxi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
)
|
||||
|
||||
var (
|
||||
SIMPLE_HOST_PROPS = []string{"name", "config.network", "vm"}
|
||||
SIMPLE_VM_PROPS = []string{"name", "guest.net", "config.template", "config.hardware.device"}
|
||||
SIMPLE_DVPG_PROPS = []string{"key", "config.defaultPortConfig", "config.distributedVirtualSwitch"}
|
||||
SIMPLE_DVS_PROPS = []string{"name", "config"}
|
||||
SIMPLE_NETWORK_PROPS = []string{"name"}
|
||||
)
|
||||
|
||||
type SIPVlan struct {
|
||||
IP netutils.IPV4Addr
|
||||
VlanId int32
|
||||
}
|
||||
|
||||
type SSimpleVM struct {
|
||||
Name string
|
||||
IPVlans []SIPVlan
|
||||
}
|
||||
|
||||
type SSimpleHostDev struct {
|
||||
Name string
|
||||
Id string
|
||||
Mac string
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) scanAllDvPortgroups() ([]*SDistributedVirtualPortgroup, error) {
|
||||
var modvpgs []mo.DistributedVirtualPortgroup
|
||||
err := cli.scanAllMObjects(SIMPLE_DVPG_PROPS, &modvpgs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "scanAllMObjects")
|
||||
}
|
||||
dvpgs := make([]*SDistributedVirtualPortgroup, 0, len(modvpgs))
|
||||
for i := range modvpgs {
|
||||
dvpgs = append(dvpgs, NewDistributedVirtualPortgroup(cli, &modvpgs[i], nil))
|
||||
}
|
||||
return dvpgs, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) scanAllNetworks() ([]mo.Network, error) {
|
||||
var monets []mo.Network
|
||||
err := cli.scanAllMObjects(SIMPLE_NETWORK_PROPS, &monets)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "scanAllMObjects")
|
||||
}
|
||||
return monets, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) networkName(refV string) (string, error) {
|
||||
if cli.networkQueryMap == nil {
|
||||
nets, err := cli.scanAllNetworks()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cli.networkQueryMap = &sync.Map{}
|
||||
for i := range nets {
|
||||
cli.networkQueryMap.Store(nets[i].Reference().Value, nets[i].Name)
|
||||
}
|
||||
}
|
||||
iter, ok := cli.networkQueryMap.Load(refV)
|
||||
if !ok {
|
||||
return "", nil
|
||||
}
|
||||
return iter.(string), nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) hostVMIPsPro(ctx context.Context, hosts []mo.HostSystem) (SNetworkInfoPro, error) {
|
||||
ret := SNetworkInfoPro{
|
||||
SNetworkInfoBase: SNetworkInfoBase{
|
||||
VMs: []SSimpleVM{},
|
||||
IPPool: SIPPool{},
|
||||
},
|
||||
HostIps: make(map[string][]netutils.IPV4Addr),
|
||||
}
|
||||
vsMap, err := cli.getVirtualSwitchs(hosts)
|
||||
if err != nil {
|
||||
return ret, errors.Wrap(err, "unable to getVirtualSwitchs")
|
||||
}
|
||||
ret.VsMap = vsMap
|
||||
dvpgMap, err := cli.getDVPGMap()
|
||||
if err != nil {
|
||||
return ret, errors.Wrap(err, "unable to get dvpgKeyVlanMap")
|
||||
}
|
||||
group, ctx := errgroup.WithContext(ctx)
|
||||
collection := make([]*SNetworkInfoPro, len(hosts))
|
||||
for i := range hosts {
|
||||
j := i
|
||||
group.Go(func() error {
|
||||
nInfo, err := cli.vmIPsPro(&hosts[j], dvpgMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
collection[j] = nInfo.(*SNetworkInfoPro)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
err = group.Wait()
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
cli.mergeNetworInfoPro(&ret, collection)
|
||||
vsList := vsMap.List()
|
||||
for i := range vsList {
|
||||
vs := vsList[i]
|
||||
for hName, ips := range vs.HostIps {
|
||||
sort.Slice(ips, func(i, j int) bool {
|
||||
return ips[i] < ips[j]
|
||||
})
|
||||
for _, ip := range ips {
|
||||
ret.IPPool.Insert(ip, SIPProc{
|
||||
VlanId: 0,
|
||||
VSId: vs.Id,
|
||||
IsHost: true,
|
||||
})
|
||||
}
|
||||
ret.HostIps[hName] = append(ret.HostIps[hName], ips...)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) mergeNetworInfoPro(ret *SNetworkInfoPro, nInfos []*SNetworkInfoPro) {
|
||||
log.Infof("nInfos before mergeNetworInfoPro: %s", jsonutils.Marshal(nInfos))
|
||||
var vmsLen, ipPoolLen int
|
||||
for i := range nInfos {
|
||||
vmsLen += len(nInfos[i].VMs)
|
||||
ipPoolLen += nInfos[i].IPPool.Len()
|
||||
}
|
||||
ret.VMs = make([]SSimpleVM, 0, vmsLen)
|
||||
ret.IPPool = NewIPPool(ipPoolLen)
|
||||
for i := range nInfos {
|
||||
ret.VMs = append(ret.VMs, nInfos[i].VMs...)
|
||||
ret.IPPool.Merge(&nInfos[i].IPPool)
|
||||
ret.VsMap.Merge(&nInfos[i].VsMap)
|
||||
}
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) HostVmIPsPro(ctx context.Context) (SNetworkInfoPro, error) {
|
||||
var hosts []mo.HostSystem
|
||||
err := cli.scanAllMObjects(SIMPLE_HOST_PROPS, &hosts)
|
||||
if err != nil {
|
||||
return SNetworkInfoPro{}, errors.Wrap(err, "scanAllMObjects")
|
||||
}
|
||||
return cli.hostVMIPsPro(ctx, hosts)
|
||||
}
|
||||
|
||||
func vpgMapKey(prefix, key string) string {
|
||||
if len(prefix) == 0 {
|
||||
return key
|
||||
}
|
||||
return fmt.Sprintf("%s-%s", prefix, key)
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) macVlanMap(mohost *mo.HostSystem, movm *mo.VirtualMachine, dvpgMap sVPGMap) (map[string]SIPProc, error) {
|
||||
vpgMap := cli.getVPGMap(mohost)
|
||||
ret := make(map[string]SIPProc, 2)
|
||||
for _, device := range movm.Config.Hardware.Device {
|
||||
bcard, ok := device.(types.BaseVirtualEthernetCard)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
card := bcard.GetVirtualEthernetCard()
|
||||
mac := card.MacAddress
|
||||
switch bk := card.Backing.(type) {
|
||||
case *types.VirtualEthernetCardDistributedVirtualPortBackingInfo:
|
||||
key := vpgMapKey("", bk.Port.PortgroupKey)
|
||||
proc, ok := dvpgMap.Get(key)
|
||||
if !ok {
|
||||
log.Errorf("dvpg %s not found in key-vlanid map", key)
|
||||
continue
|
||||
}
|
||||
ret[mac] = proc
|
||||
case *types.VirtualEthernetCardNetworkBackingInfo:
|
||||
netName, err := cli.networkName(bk.Network.Value)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "cli.networkName of %q", bk.Network.Value)
|
||||
}
|
||||
key := vpgMapKey(mohost.Reference().Value, netName)
|
||||
proc, ok := vpgMap.Get(key)
|
||||
if !ok {
|
||||
log.Errorf("vpg %s not found in key-vlanid map", key)
|
||||
continue
|
||||
}
|
||||
ret[mac] = proc
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
type SNetworkInfoPro struct {
|
||||
SNetworkInfoBase
|
||||
|
||||
HostIps map[string][]netutils.IPV4Addr
|
||||
VsMap SVirtualSwitchMap
|
||||
}
|
||||
|
||||
func (s *SNetworkInfoPro) Insert(proc SIPProc, ip netutils.IPV4Addr) {
|
||||
s.SNetworkInfoBase.Insert(proc, ip)
|
||||
s.VsMap.AddVlanIp(proc.VSId, proc.VlanId, ip)
|
||||
}
|
||||
|
||||
type SNetworkInfoBase struct {
|
||||
VMs []SSimpleVM
|
||||
IPPool SIPPool
|
||||
}
|
||||
|
||||
func (s *SNetworkInfoBase) Insert(proc SIPProc, ip netutils.IPV4Addr) {
|
||||
s.IPPool.Insert(ip, proc)
|
||||
}
|
||||
|
||||
func (s *SNetworkInfoBase) AppendVMs(name string, IpVlans []SIPVlan) {
|
||||
s.VMs = append(s.VMs, SSimpleVM{name, IpVlans})
|
||||
}
|
||||
|
||||
type INetworkInfo interface {
|
||||
Insert(SIPProc, netutils.IPV4Addr)
|
||||
AppendVMs(name string, IpVlans []SIPVlan)
|
||||
}
|
||||
|
||||
func NewNetworkInfo(dvs bool, size int) INetworkInfo {
|
||||
base := SNetworkInfoBase{
|
||||
VMs: make([]SSimpleVM, 0, size),
|
||||
IPPool: NewIPPool(int(size)),
|
||||
}
|
||||
if dvs {
|
||||
return &SNetworkInfoPro{
|
||||
SNetworkInfoBase: base,
|
||||
VsMap: NewVirtualSwitchMap(),
|
||||
}
|
||||
}
|
||||
return &SNetworkInfo{
|
||||
SNetworkInfoBase: base,
|
||||
HostIps: make(map[string]netutils.IPV4Addr),
|
||||
VlanIps: make(map[int32][]netutils.IPV4Addr),
|
||||
}
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) vmIPsPro(host *mo.HostSystem, vpgMap sVPGMap) (INetworkInfo, error) {
|
||||
nInfo := NewNetworkInfo(true, len(host.Vm))
|
||||
if len(host.Vm) == 0 {
|
||||
return nInfo, nil
|
||||
}
|
||||
var vms []mo.VirtualMachine
|
||||
err := cli.references2Objects(host.Vm, SIMPLE_VM_PROPS, &vms)
|
||||
if err != nil {
|
||||
return nInfo, errors.Wrap(err, "references2Objects")
|
||||
}
|
||||
for i := range vms {
|
||||
vm := vms[i]
|
||||
if vm.Config == nil || vm.Config.Template {
|
||||
continue
|
||||
}
|
||||
if vm.Guest == nil {
|
||||
continue
|
||||
}
|
||||
macVlanMap, err := cli.macVlanMap(host, &vm, vpgMap)
|
||||
if err != nil {
|
||||
return nInfo, err
|
||||
}
|
||||
guestIps := make([]SIPVlan, 0)
|
||||
for _, net := range vm.Guest.Net {
|
||||
if len(net.Network) == 0 {
|
||||
continue
|
||||
}
|
||||
mac := net.MacAddress
|
||||
for _, ip := range net.IpAddress {
|
||||
if !regutils.MatchIP4Addr(ip) {
|
||||
continue
|
||||
}
|
||||
if !vmIPV4Filter.Contains(ip) {
|
||||
continue
|
||||
}
|
||||
ipaddr, _ := netutils.NewIPV4Addr(ip)
|
||||
if netutils.IsLinkLocal(ipaddr) {
|
||||
continue
|
||||
}
|
||||
proc := macVlanMap[mac]
|
||||
guestIps = append(guestIps, SIPVlan{
|
||||
IP: ipaddr,
|
||||
VlanId: proc.VlanId,
|
||||
})
|
||||
nInfo.Insert(proc, ipaddr)
|
||||
break
|
||||
}
|
||||
}
|
||||
nInfo.AppendVMs(vm.Name, guestIps)
|
||||
}
|
||||
return nInfo, nil
|
||||
}
|
||||
|
||||
type SVirtualSwitchSpec struct {
|
||||
Name string
|
||||
Id string
|
||||
Distributed bool
|
||||
Hosts []SSimpleHostDev
|
||||
HostIps map[string][]netutils.IPV4Addr
|
||||
Vlans map[int32][]netutils.IPV4Addr
|
||||
}
|
||||
|
||||
func NewVirtualSwitch() *SVirtualSwitchSpec {
|
||||
return &SVirtualSwitchSpec{
|
||||
HostIps: make(map[string][]netutils.IPV4Addr),
|
||||
Vlans: make(map[int32][]netutils.IPV4Addr),
|
||||
}
|
||||
}
|
||||
|
||||
func (vs *SVirtualSwitchSpec) Merge(vsc *SVirtualSwitchSpec) {
|
||||
for vlan, ips := range vsc.Vlans {
|
||||
vs.Vlans[vlan] = insert(vs.Vlans[vlan], ips)
|
||||
}
|
||||
}
|
||||
|
||||
func insert(base []netutils.IPV4Addr, add []netutils.IPV4Addr) []netutils.IPV4Addr {
|
||||
for _, ip := range add {
|
||||
index := sort.Search(len(base), func(n int) bool {
|
||||
return base[n] > ip
|
||||
})
|
||||
base = append(base, 0)
|
||||
base = append(base[:index+1], base[index:len(base)-1]...)
|
||||
base[index] = ip
|
||||
}
|
||||
return base
|
||||
}
|
||||
|
||||
type SVirtualSwitchMap struct {
|
||||
vsList []SVirtualSwitchSpec
|
||||
vsMap map[string]*SVirtualSwitchSpec
|
||||
}
|
||||
|
||||
func NewVirtualSwitchMap(length ...int) SVirtualSwitchMap {
|
||||
initLen := 0
|
||||
if len(length) > 0 {
|
||||
initLen = length[0]
|
||||
}
|
||||
return SVirtualSwitchMap{
|
||||
vsList: make([]SVirtualSwitchSpec, 0, initLen),
|
||||
vsMap: make(map[string]*SVirtualSwitchSpec, initLen),
|
||||
}
|
||||
}
|
||||
|
||||
func (vsm *SVirtualSwitchMap) Insert(id string, vs SVirtualSwitchSpec) {
|
||||
ovs, ok := vsm.vsMap[id]
|
||||
if ok {
|
||||
ovs.Merge(&vs)
|
||||
return
|
||||
}
|
||||
vsm.vsList = append(vsm.vsList, vs)
|
||||
vsm.vsMap[id] = &vsm.vsList[len(vsm.vsList)-1]
|
||||
}
|
||||
|
||||
func (vms *SVirtualSwitchMap) Merge(ovsm *SVirtualSwitchMap) {
|
||||
for i := range ovsm.vsList {
|
||||
vs := ovsm.vsList[i]
|
||||
vms.Insert(vs.Id, vs)
|
||||
}
|
||||
}
|
||||
|
||||
func (vsm *SVirtualSwitchMap) AddVlanIp(id string, vlanId int32, ip netutils.IPV4Addr) bool {
|
||||
vs, ok := vsm.vsMap[id]
|
||||
if !ok {
|
||||
vs = NewVirtualSwitch()
|
||||
vs.Id = id
|
||||
vsm.Insert(id, *vs)
|
||||
vs = vsm.vsMap[id]
|
||||
}
|
||||
vs.Vlans[vlanId] = append(vs.Vlans[vlanId], ip)
|
||||
return true
|
||||
}
|
||||
|
||||
func (vsm *SVirtualSwitchMap) List() []SVirtualSwitchSpec {
|
||||
return vsm.vsList
|
||||
}
|
||||
|
||||
func findIp(hs *mo.HostSystem, nic string) netutils.IPV4Addr {
|
||||
for i := range hs.Config.Network.Pnic {
|
||||
pnic := hs.Config.Network.Pnic[i]
|
||||
if pnic.Device != nic {
|
||||
continue
|
||||
}
|
||||
ip := pnic.Spec.Ip.IpAddress
|
||||
if len(ip) == 0 {
|
||||
return netutils.IPV4Addr(0)
|
||||
}
|
||||
if !regutils.MatchIP4Addr(ip) {
|
||||
return netutils.IPV4Addr(0)
|
||||
}
|
||||
ipaddr, _ := netutils.NewIPV4Addr(ip)
|
||||
if netutils.IsLinkLocal(ipaddr) {
|
||||
return netutils.IPV4Addr(0)
|
||||
}
|
||||
return ipaddr
|
||||
}
|
||||
return netutils.IPV4Addr(0)
|
||||
}
|
||||
|
||||
func getNicDevice(vs *types.HostVirtualSwitch) []string {
|
||||
bridge := vs.Spec.Bridge
|
||||
switch b := bridge.(type) {
|
||||
case *types.HostVirtualSwitchAutoBridge:
|
||||
return b.ExcludedNicDevice
|
||||
case *types.HostVirtualSwitchBondBridge:
|
||||
return b.NicDevice
|
||||
case *types.HostVirtualSwitchSimpleBridge:
|
||||
return []string{b.NicDevice}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) getVirtualSwitchs(hss []mo.HostSystem) (SVirtualSwitchMap, error) {
|
||||
nic2Ip := make(map[string]netutils.IPV4Addr, len(hss))
|
||||
nic2Mac := make(map[string]string, len(hss))
|
||||
for j := range hss {
|
||||
hs := hss[j]
|
||||
macToIp := make(map[string]string, len(hs.Config.Network.Vnic))
|
||||
for i := range hs.Config.Network.Vnic {
|
||||
vnic := hs.Config.Network.Vnic[i]
|
||||
if len(vnic.Spec.Ip.IpAddress) == 0 {
|
||||
continue
|
||||
}
|
||||
macToIp[vnic.Spec.Mac] = vnic.Spec.Ip.IpAddress
|
||||
}
|
||||
for i := range hs.Config.Network.ConsoleVnic {
|
||||
vnic := hs.Config.Network.Vnic[i]
|
||||
if len(vnic.Spec.Ip.IpAddress) == 0 {
|
||||
continue
|
||||
}
|
||||
macToIp[vnic.Spec.Mac] = vnic.Spec.Ip.IpAddress
|
||||
}
|
||||
for i := range hs.Config.Network.Pnic {
|
||||
pnic := hs.Config.Network.Pnic[i]
|
||||
ip := pnic.Spec.Ip.IpAddress
|
||||
nicKey := fmt.Sprintf("%s-%s", hs.Self.Value, pnic.Device)
|
||||
nic2Mac[nicKey] = pnic.Mac
|
||||
if len(ip) == 0 {
|
||||
ip = macToIp[pnic.Mac]
|
||||
}
|
||||
if len(ip) == 0 {
|
||||
log.Warningf("host %s pnic %s has no ipaddress", hs.Name, pnic.Device)
|
||||
continue
|
||||
}
|
||||
if !regutils.MatchIP4Addr(ip) {
|
||||
log.Warningf("host %s pnic %s ipaddress %q is not IPV4Addr", hs.Name, pnic.Device, ip)
|
||||
continue
|
||||
}
|
||||
ipaddr, _ := netutils.NewIPV4Addr(ip)
|
||||
if netutils.IsLinkLocal(ipaddr) {
|
||||
log.Warningf("host %s pnic %s ipaddress %q is link local addr", hs.Name, pnic.Device, ip)
|
||||
continue
|
||||
}
|
||||
nic2Ip[nicKey] = ipaddr
|
||||
}
|
||||
}
|
||||
value2name := make(map[string]string, len(hss))
|
||||
for i := range hss {
|
||||
value2name[hss[i].Self.Value] = hss[i].Name
|
||||
}
|
||||
// dvs
|
||||
var dvss []mo.DistributedVirtualSwitch
|
||||
err := cli.scanAllMObjects(SIMPLE_DVS_PROPS, &dvss)
|
||||
if err != nil {
|
||||
return SVirtualSwitchMap{}, err
|
||||
}
|
||||
ret := NewVirtualSwitchMap(len(dvss) + len(hss))
|
||||
for i := range dvss {
|
||||
dvs := dvss[i]
|
||||
vsId := dvs.Self.Value
|
||||
vsName := fmt.Sprintf("%s", dvs.Name)
|
||||
hosts := dvs.Config.GetDVSConfigInfo().Host
|
||||
vs := SVirtualSwitchSpec{
|
||||
Name: vsName,
|
||||
Id: vsId,
|
||||
Distributed: true,
|
||||
HostIps: make(map[string][]netutils.IPV4Addr, len(hosts)),
|
||||
Vlans: make(map[int32][]netutils.IPV4Addr),
|
||||
}
|
||||
for _, host := range hosts {
|
||||
hostName := value2name[host.Config.Host.Value]
|
||||
vs.HostIps[hostName] = []netutils.IPV4Addr{}
|
||||
hostDev := SSimpleHostDev{
|
||||
Id: host.Config.Host.Value,
|
||||
Name: hostName,
|
||||
}
|
||||
switch back := host.Config.Backing.(type) {
|
||||
case *types.DistributedVirtualSwitchHostMemberPnicBacking:
|
||||
for i := range back.PnicSpec {
|
||||
nicDevice := back.PnicSpec[i].PnicDevice
|
||||
nicKey := fmt.Sprintf("%s-%s", host.Config.Host.Value, nicDevice)
|
||||
hostDev.Mac = nic2Mac[nicKey]
|
||||
ip, ok := nic2Ip[nicKey]
|
||||
if ok {
|
||||
vs.HostIps[hostName] = append(vs.HostIps[hostName], ip)
|
||||
}
|
||||
}
|
||||
case *types.DistributedVirtualSwitchHostMemberBacking:
|
||||
}
|
||||
vs.Hosts = append(vs.Hosts, hostDev)
|
||||
}
|
||||
ret.Insert(vsId, vs)
|
||||
}
|
||||
// vs
|
||||
for i := range hss {
|
||||
hs := hss[i]
|
||||
if hs.Config.Network == nil {
|
||||
continue
|
||||
}
|
||||
for i := range hs.Config.Network.Vswitch {
|
||||
ivs := hs.Config.Network.Vswitch[i]
|
||||
vsId := fmt.Sprintf("%s/%s", hs.Self.Value, ivs.Name)
|
||||
vsName := fmt.Sprintf("%s/%s", hs.Name, ivs.Name)
|
||||
vs := SVirtualSwitchSpec{
|
||||
Name: vsName,
|
||||
Id: vsId,
|
||||
Distributed: false,
|
||||
HostIps: make(map[string][]netutils.IPV4Addr),
|
||||
Vlans: make(map[int32][]netutils.IPV4Addr),
|
||||
}
|
||||
hostDev := SSimpleHostDev{
|
||||
Id: hs.Self.Value,
|
||||
Name: hs.Name,
|
||||
}
|
||||
for _, nic := range getNicDevice(&ivs) {
|
||||
nicKey := fmt.Sprintf("%s-%s", hs.Self.Value, nic)
|
||||
log.Infof("nic: %s, nicKey: %s", nic, nicKey)
|
||||
hostDev.Mac = nic2Mac[nicKey]
|
||||
ip, ok := nic2Ip[nicKey]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
vs.HostIps[hs.Name] = append(vs.HostIps[hs.Name], ip)
|
||||
}
|
||||
vs.Hosts = append(vs.Hosts, hostDev)
|
||||
ret.Insert(vsId, vs)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) getVPGMap(mohost *mo.HostSystem) sVPGMap {
|
||||
sm := newVPGMap()
|
||||
if mohost.Config.Network == nil {
|
||||
return sm
|
||||
}
|
||||
for i := range mohost.Config.Network.Portgroup {
|
||||
ipg := mohost.Config.Network.Portgroup[i]
|
||||
key := vpgMapKey(mohost.Reference().Value, ipg.Spec.Name)
|
||||
vlan := ipg.Spec.VlanId
|
||||
vsId := fmt.Sprintf("%s/%s", mohost.Reference().Value, ipg.Spec.VswitchName)
|
||||
sm.Insert(key, SIPProc{
|
||||
VlanId: vlan,
|
||||
VSId: vsId,
|
||||
})
|
||||
}
|
||||
return sm
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) getDVPGMap() (sVPGMap, error) {
|
||||
sm := newVPGMap()
|
||||
dvpgs, err := cli.scanAllDvPortgroups()
|
||||
if err != nil {
|
||||
return sm, err
|
||||
}
|
||||
for i := range dvpgs {
|
||||
modvpg := dvpgs[i].getMODVPortgroup()
|
||||
key := vpgMapKey("", modvpg.Key)
|
||||
vlanid := dvpgs[i].GetVlanId()
|
||||
vsId := modvpg.Config.DistributedVirtualSwitch.Value
|
||||
sm.Insert(key, SIPProc{
|
||||
VlanId: vlanid,
|
||||
VSId: vsId,
|
||||
})
|
||||
}
|
||||
return sm, nil
|
||||
}
|
||||
|
||||
func newVPGMap() sVPGMap {
|
||||
return sVPGMap{m: &sync.Map{}}
|
||||
}
|
||||
|
||||
type sVPGMap struct {
|
||||
m *sync.Map
|
||||
}
|
||||
|
||||
func (vm *sVPGMap) Insert(key string, proc SIPProc) {
|
||||
vm.m.Store(key, proc)
|
||||
}
|
||||
|
||||
func (vm *sVPGMap) Get(key string) (SIPProc, bool) {
|
||||
v, ok := vm.m.Load(key)
|
||||
if !ok {
|
||||
return SIPProc{}, ok
|
||||
}
|
||||
r := v.(SIPProc)
|
||||
return r, ok
|
||||
}
|
||||
|
||||
type SIPProc struct {
|
||||
VSId string
|
||||
VlanId int32
|
||||
IsHost bool
|
||||
}
|
||||
|
||||
type SIPPool struct {
|
||||
p map[netutils.IPV4Addr]SIPProc
|
||||
}
|
||||
|
||||
func NewIPPool(size ...int) SIPPool {
|
||||
if len(size) > 0 {
|
||||
return SIPPool{p: make(map[netutils.IPV4Addr]SIPProc, size[0])}
|
||||
}
|
||||
return SIPPool{p: make(map[netutils.IPV4Addr]SIPProc)}
|
||||
}
|
||||
|
||||
func (p *SIPPool) Has(ip netutils.IPV4Addr) bool {
|
||||
_, ok := p.p[ip]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (p *SIPPool) Get(ip netutils.IPV4Addr) (SIPProc, bool) {
|
||||
r, ok := p.p[ip]
|
||||
return r, ok
|
||||
}
|
||||
|
||||
func (p *SIPPool) Insert(ip netutils.IPV4Addr, proc SIPProc) {
|
||||
p.p[ip] = proc
|
||||
}
|
||||
|
||||
func (p *SIPPool) Merge(op *SIPPool) {
|
||||
for ip, proc := range op.p {
|
||||
if p.Has(ip) {
|
||||
continue
|
||||
}
|
||||
p.Insert(ip, proc)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *SIPPool) Len() int {
|
||||
return len(p.p)
|
||||
}
|
||||
@@ -15,15 +15,11 @@
|
||||
package esxi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
)
|
||||
|
||||
type IVMNetwork interface {
|
||||
@@ -265,163 +261,3 @@ func (net *SDistributedVirtualPortgroup) AddHostToDVS(host *SHost) (err error) {
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type SVirtualSwitch struct {
|
||||
Name string
|
||||
Id string
|
||||
Distributed bool
|
||||
Hosts []string
|
||||
Vlans map[int32]SVirtualLan
|
||||
}
|
||||
|
||||
type SVirtualLan struct {
|
||||
Vlan int32
|
||||
Ips []netutils.IPV4Addr
|
||||
}
|
||||
|
||||
func (h *SHost) getVirtualSwitchs() []SVirtualSwitch {
|
||||
hs := h.getHostSystem()
|
||||
if hs.Config.Network == nil {
|
||||
return nil
|
||||
}
|
||||
vss := make([]SVirtualSwitch, 0, len(hs.Config.Network.Vswitch))
|
||||
vsMap := make(map[string]*SVirtualSwitch)
|
||||
for i := range hs.Config.Network.Vswitch {
|
||||
ivs := hs.Config.Network.Vswitch[i]
|
||||
vsId := fmt.Sprintf("%s-%s", h.GetId(), ivs.Name)
|
||||
vsName := ivs.Name
|
||||
vs := SVirtualSwitch{
|
||||
Name: vsName,
|
||||
Id: vsId,
|
||||
Distributed: false,
|
||||
}
|
||||
vss = append(vss, vs)
|
||||
vsMap[ivs.Name] = &vss[len(vss)-1]
|
||||
}
|
||||
for i := range hs.Config.Network.Portgroup {
|
||||
ipg := hs.Config.Network.Portgroup[i]
|
||||
vlan, vsName := ipg.Spec.VlanId, ipg.Spec.VswitchName
|
||||
ivs := vsMap[vsName]
|
||||
ivs.Vlans[vlan] = SVirtualLan{
|
||||
Vlan: vlan,
|
||||
}
|
||||
}
|
||||
return vss
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) getVPGMap(mohost *mo.HostSystem) sVPGMap {
|
||||
sm := newVPGMap()
|
||||
if mohost.Config.Network == nil {
|
||||
return sm
|
||||
}
|
||||
for i := range mohost.Config.Network.Portgroup {
|
||||
ipg := mohost.Config.Network.Portgroup[i]
|
||||
key := fmt.Sprintf("%s-%s", mohost.Reference().Value, ipg.Spec.Name)
|
||||
vlan := ipg.Spec.VlanId
|
||||
sm.Insert(key, sVPGProc{
|
||||
vlanId: vlan,
|
||||
})
|
||||
// TODO: fill VSId
|
||||
}
|
||||
return sm
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) getDVPGMap() (sVPGMap, error) {
|
||||
sm := newVPGMap()
|
||||
dvpgs, err := cli.scanAllDvPortgroups()
|
||||
if err != nil {
|
||||
return sm, err
|
||||
}
|
||||
for i := range dvpgs {
|
||||
key := dvpgs[i].getMODVPortgroup().Key
|
||||
vlanid := dvpgs[i].GetVlanId()
|
||||
sm.Insert(key, sVPGProc{
|
||||
vlanId: vlanid,
|
||||
})
|
||||
// TODO: fill VSId
|
||||
}
|
||||
return sm, nil
|
||||
}
|
||||
|
||||
func (cli *SESXiClient) getVirtualSwitchs() []SVirtualSwitch {
|
||||
// TODO
|
||||
return nil
|
||||
}
|
||||
|
||||
func newVPGMap() sVPGMap {
|
||||
return sVPGMap{m: &sync.Map{}}
|
||||
}
|
||||
|
||||
type sVPGMap struct {
|
||||
m *sync.Map
|
||||
}
|
||||
|
||||
func (vm *sVPGMap) Insert(key string, proc sVPGProc) {
|
||||
vm.m.Store(key, proc)
|
||||
}
|
||||
|
||||
func (vm *sVPGMap) Get(key string) (sVPGProc, bool) {
|
||||
v, ok := vm.m.Load(key)
|
||||
if !ok {
|
||||
return sVPGProc{}, ok
|
||||
}
|
||||
r := v.(sVPGProc)
|
||||
return r, ok
|
||||
}
|
||||
|
||||
type sVPGProc struct {
|
||||
vlanId int32
|
||||
dvId string
|
||||
}
|
||||
|
||||
type SIPProc struct {
|
||||
VSId string
|
||||
VlanId int32
|
||||
}
|
||||
|
||||
type SIPPool struct {
|
||||
p map[netutils.IPV4Addr]SIPProc
|
||||
}
|
||||
|
||||
func NewIPPool(length ...int) SIPPool {
|
||||
if len(length) > 0 {
|
||||
return SIPPool{p: make(map[netutils.IPV4Addr]SIPProc, length[0])}
|
||||
}
|
||||
return SIPPool{p: make(map[netutils.IPV4Addr]SIPProc)}
|
||||
}
|
||||
|
||||
func (p *SIPPool) Has(ip netutils.IPV4Addr) bool {
|
||||
_, ok := p.p[ip]
|
||||
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
|
||||
}
|
||||
|
||||
func (p *SIPPool) Insert(ip netutils.IPV4Addr, proc SIPProc) {
|
||||
p.p[ip] = proc
|
||||
}
|
||||
|
||||
func (p *SIPPool) Merge(op *SIPPool) {
|
||||
for ip, proc := range op.p {
|
||||
if p.Has(ip) {
|
||||
continue
|
||||
}
|
||||
p.Insert(ip, proc)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *SIPPool) Len() int {
|
||||
return len(p.p)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user