mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-01 15:07:17 +08:00
feat(esxiagent): determine vs by bridge and network when creating vm
This commit is contained in:
@@ -3,8 +3,9 @@ package models
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
)
|
||||
|
||||
type wireIdChangeArgs struct {
|
||||
|
||||
@@ -137,24 +137,65 @@ func NewUSBController(key *int32) types.BaseVirtualDevice {
|
||||
return &device
|
||||
}
|
||||
|
||||
var getNetwork func(bridge, vlanId string) (IVMNetwork, error)
|
||||
|
||||
func NewVNICDev(host *SHost, mac, driver string, bridge string, vlanId int32, key, ctlKey, index int32) (types.BaseVirtualDevice, error) {
|
||||
desc := types.Description{Label: fmt.Sprintf("Network adapter %d", index+1), Summary: "VM Network"}
|
||||
|
||||
var inet IVMNetwork
|
||||
var err error
|
||||
if (vlanId == 0 || vlanId == 1) && len(bridge) > 0 {
|
||||
inet, err = host.findDVPGById(bridge)
|
||||
newGetNetwork := func(bridge string, vlanId int32) (IVMNetwork, error) {
|
||||
if len(bridge) == 0 {
|
||||
log.Warningf("empty bridge for host %s, vlanId %d, mac %s", host.GetGlobalId(), vlanId, mac)
|
||||
return nil, nil
|
||||
}
|
||||
vs, err := findVirtualSwitch(host, bridge)
|
||||
if err != nil {
|
||||
log.Errorf("fail to find dvportgroup by name %s: %s", bridge, err)
|
||||
return nil, errors.Wrapf(err, "findVirtualSwitch for host %s bridge %s", host.GetGlobalId(), bridge)
|
||||
}
|
||||
if vs == nil {
|
||||
log.Infof("can't find vs via host %s, bridge %s", host.GetId(), bridge)
|
||||
return nil, nil
|
||||
}
|
||||
network, err := vs.FindNetworkByVlanID(vlanId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "FindNetworkByVlanID for vlanId %q", vlanId)
|
||||
}
|
||||
return network, nil
|
||||
}
|
||||
|
||||
oldGetNework := func(bridge string, vlanId int32) (IVMNetwork, error) {
|
||||
var inet IVMNetwork
|
||||
var err error
|
||||
if (vlanId == 0 || vlanId == 1) && len(bridge) > 0 {
|
||||
inet, err = host.findDVPGById(bridge)
|
||||
if err != nil {
|
||||
log.Errorf("fail to find dvportgroup by name %s: %s", bridge, err)
|
||||
}
|
||||
}
|
||||
if inet == nil || reflect.ValueOf(inet).IsNil() {
|
||||
inet, err = host.FindNetworkByVlanID(vlanId)
|
||||
if err != nil {
|
||||
log.Errorf("fail to find network by vlanid %d: %s", vlanId, err)
|
||||
}
|
||||
}
|
||||
if inet == nil || reflect.ValueOf(inet).IsNil() {
|
||||
return nil, nil
|
||||
}
|
||||
return inet, nil
|
||||
}
|
||||
|
||||
inet, err := newGetNetwork(bridge, vlanId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if inet == nil {
|
||||
log.Infof("no find network via new method")
|
||||
inet, err = oldGetNework(bridge, vlanId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if inet == nil || reflect.ValueOf(inet).IsNil() {
|
||||
inet, err = host.FindNetworkByVlanID(vlanId)
|
||||
if err != nil {
|
||||
log.Errorf("fail to find network by vlanid %d: %s", vlanId, err)
|
||||
}
|
||||
}
|
||||
if inet == nil || reflect.ValueOf(inet).IsNil() {
|
||||
|
||||
if inet == nil {
|
||||
return nil, errors.Error(fmt.Sprintf("Brige %s VLAN %d not found", bridge, vlanId))
|
||||
}
|
||||
|
||||
@@ -165,14 +206,6 @@ func NewVNICDev(host *SHost, mac, driver string, bridge string, vlanId int32, ke
|
||||
var backing types.BaseVirtualDeviceBackingInfo
|
||||
switch inet.(type) {
|
||||
case *SDistributedVirtualPortgroup:
|
||||
// net := inet.(*SDistributedVirtualPortgroup)
|
||||
// port, err := net.FindPort()
|
||||
//if err != nil {
|
||||
// return nil, errors.Wrap(err, "net.FindPort")
|
||||
// }
|
||||
// if port == nil {
|
||||
// return nil, fmt.Errorf("no active port for dvportgroup %q", net.GetName())
|
||||
// }
|
||||
net := inet.(*SDistributedVirtualPortgroup)
|
||||
dvpg := net.getMODVPortgroup()
|
||||
uuid, err := net.GetDVSUuid()
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
// 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 (
|
||||
"regexp"
|
||||
|
||||
"github.com/vmware/govmomi/property"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
)
|
||||
|
||||
var DVS_PROPS = []string{"name"}
|
||||
|
||||
type IVirtualSwitch interface {
|
||||
FindNetworkByVlanID(vlanID int32) (IVMNetwork, error)
|
||||
}
|
||||
|
||||
type SVirtualSwitch struct {
|
||||
Host *SHost
|
||||
HostVirtualSwitch types.HostVirtualSwitch
|
||||
}
|
||||
|
||||
func (vs *SVirtualSwitch) FindNetworkByVlanID(vlanID int32) (IVMNetwork, error) {
|
||||
vsKey := vs.HostVirtualSwitch.Key
|
||||
pgs := vs.Host.getHostSystem().Config.Network.Portgroup
|
||||
var networkName string
|
||||
for i := range pgs {
|
||||
if pgs[i].Vswitch != vsKey {
|
||||
continue
|
||||
}
|
||||
if vlanEqual(pgs[i].Spec.VlanId, vlanID) {
|
||||
networkName = pgs[i].Spec.Name
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(networkName) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
networks, err := vs.Host.GetNetworks()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "can't get networks of host %q", vs.Host.GetGlobalId())
|
||||
}
|
||||
for i := range networks {
|
||||
if networks[i].GetName() == networkName {
|
||||
return networks[i], nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type SDistributedVirtualSwitch struct {
|
||||
Host *SHost
|
||||
DistributedVirtualSwitch mo.DistributedVirtualSwitch
|
||||
}
|
||||
|
||||
func (vs *SDistributedVirtualSwitch) FindNetworkByVlanID(vlanID int32) (IVMNetwork, error) {
|
||||
var modvpgs []mo.DistributedVirtualPortgroup
|
||||
filter := property.Filter{}
|
||||
filter["config.distributedVirtualSwitch"] = vs.DistributedVirtualSwitch.Self
|
||||
err := vs.Host.manager.scanMObjectsWithFilter(vs.Host.datacenter.object.Entity().Self, DVPORTGROUP_PROPS, &modvpgs, filter)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "can't fetch portgroup of DistributedVirtualSwitch %q", vs.DistributedVirtualSwitch.Name)
|
||||
}
|
||||
dvpgs := make([]*SDistributedVirtualPortgroup, 0, len(modvpgs))
|
||||
for i := range modvpgs {
|
||||
dvpgs = append(dvpgs, NewDistributedVirtualPortgroup(vs.Host.manager, &modvpgs[i], nil))
|
||||
}
|
||||
for i := range dvpgs {
|
||||
if vlanEqual(dvpgs[i].GetVlanId(), vlanID) {
|
||||
return dvpgs[i], nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func vlanEqual(v1, v2 int32) bool {
|
||||
if v1 <= 1 && v2 <= 1 {
|
||||
return true
|
||||
}
|
||||
return v1 == v2
|
||||
}
|
||||
|
||||
var (
|
||||
vsBridgeRegex = regexp.MustCompile(`^(host-\d+)/(.*)`)
|
||||
dvsBridgeRegex = regexp.MustCompile(`^dvs-\d+$`)
|
||||
)
|
||||
|
||||
// config.distributedVirtualSwitch
|
||||
|
||||
func findVirtualSwitch(host *SHost, bridge string) (IVirtualSwitch, error) {
|
||||
group := vsBridgeRegex.FindStringSubmatch(bridge)
|
||||
oHost := host.getHostSystem()
|
||||
if len(group) > 0 {
|
||||
// vswitch
|
||||
vsName := group[2]
|
||||
for _, vs := range oHost.Config.Network.Vswitch {
|
||||
if vs.Name != vsName {
|
||||
continue
|
||||
}
|
||||
return &SVirtualSwitch{
|
||||
Host: host,
|
||||
HostVirtualSwitch: vs,
|
||||
}, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// distributed vswitch
|
||||
if !dvsBridgeRegex.MatchString(bridge) {
|
||||
return nil, nil
|
||||
}
|
||||
objRef := types.ManagedObjectReference{
|
||||
Type: "VmwareDistributedVirtualSwitch",
|
||||
Value: bridge,
|
||||
}
|
||||
var dvs mo.DistributedVirtualSwitch
|
||||
err := host.manager.reference2Object(objRef, DVS_PROPS, &dvs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "can't fetch DistributedVirtualSwitch %q", objRef.String())
|
||||
}
|
||||
return &SDistributedVirtualSwitch{
|
||||
Host: host,
|
||||
DistributedVirtualSwitch: dvs,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user