func()

in vsphere/nodemanager.go [83:248]


func (nm *NodeManager) DiscoverNode(node *v1.Node) error {
	type VmSearch struct {
		vc         string
		datacenter *vclib.Datacenter
	}

	var mutex = &sync.Mutex{}
	var globalErrMutex = &sync.Mutex{}
	var queueChannel chan *VmSearch
	var wg sync.WaitGroup
	var globalErr *error

	queueChannel = make(chan *VmSearch, QUEUE_SIZE)
	nodeUUID, err := GetNodeUUID(node)
	if err != nil {
		klog.Errorf("Node Discovery failed to get node uuid for node %s with error: %v", node.Name, err)
		return err
	}

	klog.V(4).Infof("Discovering node %s with uuid %s", node.ObjectMeta.Name, nodeUUID)

	vmFound := false
	globalErr = nil

	setGlobalErr := func(err error) {
		globalErrMutex.Lock()
		globalErr = &err
		globalErrMutex.Unlock()
	}

	setVMFound := func(found bool) {
		mutex.Lock()
		vmFound = found
		mutex.Unlock()
	}

	getVMFound := func() bool {
		mutex.Lock()
		found := vmFound
		mutex.Unlock()
		return found
	}

	go func() {
		var datacenterObjs []*vclib.Datacenter
		for vc, vsi := range nm.vsphereInstanceMap {

			found := getVMFound()
			if found == true {
				break
			}

			// Create context
			ctx, cancel := context.WithCancel(context.Background())
			defer cancel()

			err := nm.vcConnect(ctx, vsi)
			if err != nil {
				klog.V(4).Info("Discovering node error vc:", err)
				setGlobalErr(err)
				continue
			}

			if vsi.cfg.Datacenters == "" {
				datacenterObjs, err = vclib.GetAllDatacenter(ctx, vsi.conn)
				if err != nil {
					klog.V(4).Info("Discovering node 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.V(4).Info("Discovering node error dc:", err)
						setGlobalErr(err)
						continue
					}
					datacenterObjs = append(datacenterObjs, datacenterObj)
				}
			}

			for _, datacenterObj := range datacenterObjs {
				found := getVMFound()
				if found == true {
					break
				}

				klog.V(4).Infof("Finding node %s in vc=%s and datacenter=%s", node.Name, vc, datacenterObj.Name())
				queueChannel <- &VmSearch{
					vc:         vc,
					datacenter: datacenterObj,
				}
			}
		}
		close(queueChannel)
	}()

	for i := 0; i < POOL_SIZE; i++ {
		wg.Add(1)
		go func() {
			for res := range queueChannel {
				ctx, cancel := context.WithCancel(context.Background())
				vm, err := res.datacenter.GetVMByUUID(ctx, nodeUUID)
				if err != nil {
					klog.V(4).Infof("Error while looking for vm=%+v in vc=%s and datacenter=%s: %v",
						vm, res.vc, res.datacenter.Name(), err)
					if err != vclib.ErrNoVMFound {
						setGlobalErr(err)
					} else {
						klog.V(4).Infof("Did not find node %s in vc=%s and datacenter=%s",
							node.Name, res.vc, res.datacenter.Name())
					}
					cancel()
					continue
				}
				if vm != nil {
					klog.V(4).Infof("Found node %s as vm=%+v in vc=%s and datacenter=%s",
						node.Name, vm, res.vc, res.datacenter.Name())
					var vmObj mo.VirtualMachine
					err := vm.Properties(ctx, vm.Reference(), []string{"config"}, &vmObj)
					if err != nil || vmObj.Config == nil {
						klog.Errorf("failed to retrieve guest vmconfig for node: %s Err: %v", node.Name, err)
					} else {
						klog.V(4).Infof("vm hardware version for node:%s is %s", node.Name, vmObj.Config.Version)
						// vmconfig.Version returns vm hardware version as vmx-11, vmx-13, vmx-14, vmx-15 etc.
						vmhardwaredeprecated, err := isGuestHardwareVersionDeprecated(vmObj.Config.Version)
						if err != nil {
							klog.Errorf("failed to check if vm hardware version is deprecated. VM Hardware Version: %s Err: %v", vmObj.Config.Version, err)
						}
						if vmhardwaredeprecated {
							klog.Warningf("VM Hardware version: %s from node: %s is deprecated. Please consider upgrading virtual machine hardware version to vmx-15 or higher", vmObj.Config.Version, node.Name)
						}
					}
					// Get the node zone information
					nodeFd := node.ObjectMeta.Labels[v1.LabelTopologyZone]
					nodeRegion := node.ObjectMeta.Labels[v1.LabelTopologyRegion]
					nodeZone := &cloudprovider.Zone{FailureDomain: nodeFd, Region: nodeRegion}
					nodeInfo := &NodeInfo{dataCenter: res.datacenter, vm: vm, vcServer: res.vc, vmUUID: nodeUUID, zone: nodeZone}
					nm.addNodeInfo(node.ObjectMeta.Name, nodeInfo)
					for range queueChannel {
					}
					setVMFound(true)
					cancel()
					break
				}
			}
			wg.Done()
		}()
	}
	wg.Wait()
	if vmFound {
		return nil
	}
	if globalErr != nil {
		return *globalErr
	}

	klog.V(4).Infof("Discovery Node: %q vm not found", node.Name)
	return vclib.ErrNoVMFound
}