Skip to content

Commit 7c8b2e6

Browse files
committed
Fix NSX-T LogicalSwitchUUID to DPVG lookup
A supported but very, very rare NSX-T configuration is for the same LogicalSwitchUUID to be shared between multiple DPVGs in a Datacenter. To support this, shortly before WCP 1.0 release, a change was made in WCP and then ported over here that used a "all the hosts in the CCR" check to determine which DVPG is the correct one to use. Ever since, this check in WCP and here have been peculiar and the details as to why mostly lost. This is all host check strict in the sense that it will fail if a host is in MM or otherwise disconnected. Fortunately, within a CCR, the LogicalSwitchUUID to DVPG mapping is unique, so use that to simplify the lookup logic. The possibility of multiple DVPGs for each CCR will be a pain when we start to do network placement. Remove the NSX-T OpaqueNetwork support since that was only used pre-1.0 and never in a shipped release.
1 parent 439c8f6 commit 7c8b2e6

File tree

2 files changed

+34
-90
lines changed

2 files changed

+34
-90
lines changed

pkg/vmprovider/providers/vsphere/network/network_provider.go

Lines changed: 33 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/pkg/errors"
2020
"github.com/vmware/govmomi/find"
2121
"github.com/vmware/govmomi/object"
22+
"github.com/vmware/govmomi/property"
2223
"github.com/vmware/govmomi/vim25"
2324
"github.com/vmware/govmomi/vim25/mo"
2425
vimtypes "github.com/vmware/govmomi/vim25/types"
@@ -367,7 +368,7 @@ func (np *netOpNetworkProvider) getNetworkRef(ctx goctx.Context, networkType, ne
367368
case VdsNetworkType:
368369
return np.networkForPortGroupID(networkID)
369370
case NsxtNetworkType:
370-
return searchNsxtNetworkReference(ctx, np.finder, np.cluster, networkID)
371+
return searchNsxtNetworkReference(ctx, np.cluster, networkID)
371372
default:
372373
return nil, fmt.Errorf("unsupported NetOP network type %s", networkType)
373374
}
@@ -603,7 +604,7 @@ func (np *nsxtNetworkProvider) createEthernetCard(
603604
return nil, err
604605
}
605606

606-
networkRef, err := searchNsxtNetworkReference(vmCtx, np.finder, np.cluster, vnetIf.Status.ProviderStatus.NsxLogicalSwitchID)
607+
networkRef, err := searchNsxtNetworkReference(vmCtx, np.cluster, vnetIf.Status.ProviderStatus.NsxLogicalSwitchID)
607608
if err != nil {
608609
// Log message used by VMC LINT. Refer to before making changes
609610
vmCtx.Logger.Error(err, "Failed to search for nsx-t network associated with vnetIf", "vnetIf", vnetIf)
@@ -727,108 +728,51 @@ func (np *nsxtNetworkProvider) getNetplanEthernet(vnetIf *ncpv1alpha1.VirtualNet
727728
return eth
728729
}
729730

730-
// matchOpaqueNetwork takes the network ID, returns whether the opaque network matches the networkID.
731-
func matchOpaqueNetwork(ctx goctx.Context, network object.NetworkReference, networkID string) bool {
732-
obj, ok := network.(*object.OpaqueNetwork)
733-
if !ok {
734-
return false
735-
}
736-
737-
var opaqueNet mo.OpaqueNetwork
738-
if err := obj.Properties(ctx, obj.Reference(), []string{"summary"}, &opaqueNet); err != nil {
739-
return false
740-
}
741-
742-
summary, _ := opaqueNet.Summary.(*vimtypes.OpaqueNetworkSummary)
743-
return summary.OpaqueNetworkId == networkID
744-
}
745-
746-
// matchDistributedPortGroup takes the network ID, returns whether the distributed port group matches the networkID.
747-
func matchDistributedPortGroup(
731+
// searchNsxtNetworkReference takes in nsx-t logical switch UUID and returns the reference of the network.
732+
func searchNsxtNetworkReference(
748733
ctx goctx.Context,
749-
network object.NetworkReference,
750-
networkID string,
751-
hostMoIDs []vimtypes.ManagedObjectReference) bool {
734+
ccr *object.ClusterComputeResource,
735+
networkID string) (object.NetworkReference, error) {
752736

753-
obj, ok := network.(*object.DistributedVirtualPortgroup)
754-
if !ok {
755-
return false
756-
}
757-
758-
var configInfo []vimtypes.ObjectContent
759-
err := obj.Properties(ctx, obj.Reference(), []string{"config.logicalSwitchUuid", "host"}, &configInfo)
760-
if err != nil {
761-
return false
737+
var obj mo.ClusterComputeResource
738+
if err := ccr.Properties(ctx, ccr.Reference(), []string{"network"}, &obj); err != nil {
739+
return nil, err
762740
}
763741

764-
if len(configInfo) > 0 {
765-
// Check "logicalSwitchUuid" property
766-
lsIDMatch := false
767-
for _, dynamicProperty := range configInfo[0].PropSet {
768-
if dynamicProperty.Name == "config.logicalSwitchUuid" && dynamicProperty.Val == networkID {
769-
lsIDMatch = true
770-
break
771-
}
772-
}
773-
774-
// logicalSwitchUuid did not match
775-
if !lsIDMatch {
776-
return false
777-
}
778-
779-
foundAllHosts := false
780-
for _, dynamicProperty := range configInfo[0].PropSet {
781-
// In the case of a single NSX Overlay Transport Zone for all the clusters and DVS's,
782-
// multiple DVPGs(associated with different DVS's) will have the same "logicalSwitchUuid".
783-
// So matching "logicalSwitchUuid" is necessary condition, but not sufficient.
784-
// Checking if the DPVG has all the hosts in the cluster, along with the above would be sufficient
785-
if dynamicProperty.Name == "host" {
786-
if hosts, ok := dynamicProperty.Val.(vimtypes.ArrayOfManagedObjectReference); ok {
787-
foundAllHosts = true
788-
dvsHostSet := make(map[string]bool, len(hosts.ManagedObjectReference))
789-
for _, dvsHost := range hosts.ManagedObjectReference {
790-
dvsHostSet[dvsHost.Value] = true
791-
}
792-
793-
for _, hostMoRef := range hostMoIDs {
794-
if _, ok := dvsHostSet[hostMoRef.Value]; !ok {
795-
foundAllHosts = false
796-
break
797-
}
798-
}
799-
}
800-
}
742+
var dvpgsMoRefs []vimtypes.ManagedObjectReference
743+
for _, n := range obj.Network {
744+
if n.Type == "DistributedVirtualPortgroup" {
745+
dvpgsMoRefs = append(dvpgsMoRefs, n.Reference())
801746
}
747+
}
802748

803-
// Implicit that lsID Matches at this point
804-
return foundAllHosts
749+
if len(dvpgsMoRefs) == 0 {
750+
return nil, fmt.Errorf("ClusterComputeResource %s has no DVPGs", ccr.Reference().Value)
805751
}
806-
return false
807-
}
808752

809-
// searchNsxtNetworkReference takes in nsx-t logical switch UUID and returns the reference of the network.
810-
func searchNsxtNetworkReference(ctx goctx.Context, finder *find.Finder, cluster *object.ClusterComputeResource, networkID string) (object.NetworkReference, error) {
811-
networks, err := finder.NetworkList(ctx, "*")
753+
var dvpgs []mo.DistributedVirtualPortgroup
754+
err := property.DefaultCollector(ccr.Client()).Retrieve(ctx, dvpgsMoRefs, []string{"config.logicalSwitchUuid"}, &dvpgs)
812755
if err != nil {
813756
return nil, err
814757
}
815758

816-
// Get the list of ESX host moRef objects for this cluster
817-
// TODO: ps: []string{"host"} instead of nil?
818-
var computeResource mo.ComputeResource
819-
if err := cluster.Properties(ctx, cluster.Reference(), nil, &computeResource); err != nil {
820-
return nil, err
759+
var dvpgMoRefs []vimtypes.ManagedObjectReference
760+
for _, dvpg := range dvpgs {
761+
if dvpg.Config.LogicalSwitchUuid == networkID {
762+
dvpgMoRefs = append(dvpgMoRefs, dvpg.Reference())
763+
}
821764
}
822765

823-
for _, network := range networks {
824-
if matchDistributedPortGroup(ctx, network, networkID, computeResource.Host) {
825-
return network, nil
826-
}
827-
if matchOpaqueNetwork(ctx, network, networkID) {
828-
return network, nil
829-
}
766+
switch len(dvpgMoRefs) {
767+
case 1:
768+
return object.NewDistributedVirtualPortgroup(ccr.Client(), dvpgMoRefs[0]), nil
769+
case 0:
770+
return nil, fmt.Errorf("no DVPG with NSX-T network ID %q found", networkID)
771+
default:
772+
// The LogicalSwitchUuid is supposed to be unique per CCR, so this is likely an NCP
773+
// misconfiguration, and we don't know which one to pick.
774+
return nil, fmt.Errorf("multiple DVPGs (%d) with NSX-T network ID %q found", len(dvpgMoRefs), networkID)
830775
}
831-
return nil, fmt.Errorf("opaque network with ID '%s' not found", networkID)
832776
}
833777

834778
// ToCidrNotation takes ip and mask as ip addresses and returns a cidr notation.

pkg/vmprovider/providers/vsphere/network/network_provider_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ var _ = Describe("NetworkProvider", func() {
578578

579579
It("should return an error", func() {
580580
_, err := np.EnsureNetworkInterface(vmCtx, &vmCtx.VM.Spec.NetworkInterfaces[0])
581-
Expect(err).To(MatchError(fmt.Sprintf("opaque network with ID '%s' not found", doesNotExist)))
581+
Expect(err).To(MatchError(fmt.Sprintf("no DVPG with NSX-T network ID %q found", doesNotExist)))
582582
})
583583
})
584584

0 commit comments

Comments
 (0)