in pkg/common/connectionmanager/zones.go [127:291]
func (cm *ConnectionManager) getDIFromMultiVCorDC(ctx context.Context,
zoneLabel string, regionLabel string, zoneLooking string, regionLooking string) (*ZoneDiscoveryInfo, error) {
klog.V(4).Infof("getDIFromMultiVCorDC called with zone: %s and region: %s", zoneLooking, regionLooking)
if len(zoneLabel) == 0 || len(regionLabel) == 0 || len(zoneLooking) == 0 || len(regionLooking) == 0 {
err := ErrMultiVCRequiresZones
klog.Errorf("%v", err)
return nil, err
}
type zoneSearch struct {
tenantRef string
vc string
datacenter *vclib.Datacenter
host *object.HostSystem
}
var mutex = &sync.Mutex{}
var globalErrMutex = &sync.Mutex{}
var queueChannel chan *zoneSearch
var wg sync.WaitGroup
var globalErr *error
queueChannel = make(chan *zoneSearch, QueueSize)
zoneFound := false
globalErr = nil
setGlobalErr := func(err error) {
globalErrMutex.Lock()
globalErr = &err
globalErrMutex.Unlock()
}
setZoneFound := func(found bool) {
mutex.Lock()
zoneFound = found
mutex.Unlock()
}
getZoneFound := func() bool {
mutex.Lock()
found := zoneFound
mutex.Unlock()
return found
}
go func() {
for _, vsi := range cm.VsphereInstanceMap {
var datacenterObjs []*vclib.Datacenter
if getZoneFound() {
break
}
var err error
for i := 0; i < NumConnectionAttempts; i++ {
err = cm.Connect(ctx, vsi)
if err == nil {
break
}
time.Sleep(time.Duration(RetryAttemptDelaySecs) * time.Second)
}
if err != nil {
klog.Error("getDIFromMultiVCorDC error vc:", err)
setGlobalErr(err)
continue
}
if vsi.Cfg.Datacenters == "" {
datacenterObjs, err = vclib.GetAllDatacenter(ctx, vsi.Conn)
if err != nil {
klog.Error("getDIFromMultiVCorDC error dc:", err)
setGlobalErr(err)
continue
}
} else {
datacenters := strings.Split(vsi.Cfg.Datacenters, ",")
for _, dc := range datacenters {
dc = strings.TrimSpace(dc)
if dc == "" {
continue
}
datacenterObj, err := vclib.GetDatacenter(ctx, vsi.Conn, dc)
if err != nil {
klog.Error("getDIFromMultiVCorDC error dc:", err)
setGlobalErr(err)
continue
}
datacenterObjs = append(datacenterObjs, datacenterObj)
}
}
for _, datacenterObj := range datacenterObjs {
if getZoneFound() {
break
}
finder := find.NewFinder(datacenterObj.Client(), false)
finder.SetDatacenter(datacenterObj.Datacenter)
hostList, err := finder.HostSystemList(ctx, "*/*")
if err != nil {
klog.Errorf("HostSystemList failed: %v", err)
continue
}
for _, host := range hostList {
klog.V(3).Infof("Finding zone in vc=%s and datacenter=%s for host: %s", vsi.Cfg.VCenterIP, datacenterObj.Name(), host.Name())
queueChannel <- &zoneSearch{
tenantRef: vsi.Cfg.TenantRef,
vc: vsi.Cfg.VCenterIP,
datacenter: datacenterObj,
host: host,
}
}
}
}
close(queueChannel)
}()
var zoneInfo *ZoneDiscoveryInfo
for i := 0; i < PoolSize; i++ {
wg.Add(1)
go func() {
for res := range queueChannel {
klog.V(3).Infof("Checking zones for host: %s", res.host.Name())
result, err := cm.LookupZoneByMoref(ctx, res.tenantRef, res.host.Reference(), zoneLabel, regionLabel)
if err != nil {
klog.Errorf("Failed to find zone: %s and region: %s for host %s", zoneLabel, regionLabel, res.host.Name())
continue
}
if !strings.EqualFold(result[ZoneLabel], zoneLooking) ||
!strings.EqualFold(result[RegionLabel], regionLooking) {
klog.V(4).Infof("Does not match region: %s and zone: %s", result[RegionLabel], result[ZoneLabel])
continue
}
klog.Infof("Found zone: %s and region: %s for host %s", zoneLooking, regionLooking, res.host.Name())
zoneInfo = &ZoneDiscoveryInfo{
TenantRef: res.tenantRef,
VcServer: res.vc,
DataCenter: res.datacenter,
}
setZoneFound(true)
break
}
wg.Done()
}()
}
wg.Wait()
if zoneFound {
return zoneInfo, nil
}
if globalErr != nil {
return nil, *globalErr
}
klog.V(4).Infof("getDIFromMultiVCorDC: zone: %s and region: %s not found", zoneLabel, regionLabel)
return nil, vclib.ErrNoZoneRegionFound
}