func WaitForGuestNet(client *govmomi.Client, vm *object.VirtualMachine, routable bool, timeout int, ignoredGuestIPs []interface{}) error {
	if timeout < 1 {
		log.Printf("[DEBUG] Skipping network waiter for VM %q", vm.InventoryPath)
		return nil
	}
	log.Printf(
		"[DEBUG] Waiting for an available IP address on VM %q (routable= %t, timeout = %dm)",
		vm.InventoryPath,
		routable,
		timeout,
	)
	var v4gw, v6gw net.IP

	p := client.PropertyCollector()
	ctx, cancel := context.WithTimeout(context.Background(), time.Minute*time.Duration(timeout))
	defer cancel()

	err := property.Wait(ctx, p, vm.Reference(), []string{"guest.net", "guest.ipStack"}, func(pc []types.PropertyChange) bool {
		for _, c := range pc {
			if c.Op != types.PropertyChangeOpAssign {
				continue
			}

			switch v := c.Val.(type) {
			case types.ArrayOfGuestStackInfo:
				for _, s := range v.GuestStackInfo {
					if s.IpRouteConfig != nil {
						for _, r := range s.IpRouteConfig.IpRoute {
							switch r.Network {
							case "0.0.0.0":
								v4gw = net.ParseIP(r.Gateway.IpAddress)
							case "::":
								v6gw = net.ParseIP(r.Gateway.IpAddress)
							}
						}
					}
				}
			case types.ArrayOfGuestNicInfo:
				for _, n := range v.GuestNicInfo {
					if n.IpConfig != nil {
						for _, addr := range n.IpConfig.IpAddress {
							ip := net.ParseIP(addr.IpAddress)
							if skipIPAddrForWaiter(ip, ignoredGuestIPs) {
								continue
							}
							if !routable {
								// We are done. The rest of this block concerns itself with
								// checking for a routable address, but the waiter has been
								// flagged to not wait for one.
								return true
							}
							var mask net.IPMask
							if ip.To4() != nil {
								mask = net.CIDRMask(int(addr.PrefixLength), 32)
							} else {
								mask = net.CIDRMask(int(addr.PrefixLength), 128)
							}
							if ip.Mask(mask).Equal(v4gw.Mask(mask)) || ip.Mask(mask).Equal(v6gw.Mask(mask)) {
								return true
							}
						}
					}
				}
			}
		}

		return false
	})

	if err != nil {
		// Provide a friendly error message if we timed out waiting for a routable IP.
		if ctx.Err() == context.DeadlineExceeded {
			return errors.New("timeout waiting for an available IP address")
		}
		return err
	}

	log.Printf("[DEBUG] IP address(es) is/are now available for VM %q", vm.InventoryPath)
	return nil
}
func WaitForGuestNet(client *govmomi.Client, vm *object.VirtualMachine, routable bool, timeout int, ignoredGuestIPs []interface{}) error {
	if timeout < 1 {
		log.Printf("[DEBUG] Skipping network waiter for VM %q", vm.InventoryPath)
		return nil
	}
	log.Printf(
		"[DEBUG] Waiting for an available IP address on VM %q (routable= %t, timeout = %dm)",
		vm.InventoryPath,
		routable,
		timeout,
	)
	var v4gw, v6gw net.IP

	p := client.PropertyCollector()
	ctx, cancel := context.WithTimeout(context.Background(), time.Minute*time.Duration(timeout))
	defer cancel()

	err := property.Wait(ctx, p, vm.Reference(), []string{"guest.net", "guest.ipStack"}, func(pc []types.PropertyChange) bool {
		for _, c := range pc {
			if c.Op != types.PropertyChangeOpAssign {
				continue
			}

			switch v := c.Val.(type) {
			case types.ArrayOfGuestStackInfo:
				for _, s := range v.GuestStackInfo {
					if s.IpRouteConfig != nil {
						for _, r := range s.IpRouteConfig.IpRoute {
							switch r.Network {
							case "0.0.0.0":
								v4gw = net.ParseIP(r.Gateway.IpAddress)
							case "::":
								v6gw = net.ParseIP(r.Gateway.IpAddress)
							}
						}
					}
				}
			case types.ArrayOfGuestNicInfo:
				for _, n := range v.GuestNicInfo {
					if n.IpConfig != nil {
						for _, addr := range n.IpConfig.IpAddress {
							ip := net.ParseIP(addr.IpAddress)
							if skipIPAddrForWaiter(ip, ignoredGuestIPs) {
								continue
							}
							if !routable {
								
								
								
								return true
							}
							var mask net.IPMask
							if ip.To4() != nil {
								mask = net.CIDRMask(int(addr.PrefixLength), 32)
							} else {
								mask = net.CIDRMask(int(addr.PrefixLength), 128)
							}
							if ip.Mask(mask).Equal(v4gw.Mask(mask)) || ip.Mask(mask).Equal(v6gw.Mask(mask)) {
								return true
							}
						}
					}
				}
			}
		}

		return false
	})

	if err != nil {
		
		if ctx.Err() == context.DeadlineExceeded {
			return errors.New("timeout waiting for an available IP address")
		}
		return err
	}

	log.Printf("[DEBUG] IP address(es) is/are now available for VM %q", vm.InventoryPath)
	return nil
}
func WaitForGuestNet ( client * govmomi . Client , vm * object . VirtualMachine , routable bool , timeout int , ignoredGuestIPs [ ] interface { } ) error { if timeout < 1 { log . Printf ( " " , vm . InventoryPath ) return nil } log . Printf ( " " , vm . InventoryPath , routable , timeout , ) var v4gw , v6gw net . IP p := client . PropertyCollector ( ) ctx , cancel := context . WithTimeout ( context . Background ( ) , time . Minute * time . Duration ( timeout ) ) defer cancel ( ) err := property . Wait ( ctx , p , vm . Reference ( ) , [ ] string { " " , " " } , func ( pc [ ] types . PropertyChange ) bool { for _ , c := range pc { if c . Op != types . PropertyChangeOpAssign { continue } switch v := c . Val . ( type ) { case types . ArrayOfGuestStackInfo : for _ , s := range v . GuestStackInfo { if s . IpRouteConfig != nil { for _ , r := range s . IpRouteConfig . IpRoute { switch r . Network { case " " : v4gw = net . ParseIP ( r . Gateway . IpAddress ) case " " : v6gw = net . ParseIP ( r . Gateway . IpAddress ) } } } } case types . ArrayOfGuestNicInfo : for _ , n := range v . GuestNicInfo { if n . IpConfig != nil { for _ , addr := range n . IpConfig . IpAddress { ip := net . ParseIP ( addr . IpAddress ) if skipIPAddrForWaiter ( ip , ignoredGuestIPs ) { continue } if ! routable { // We are done. The rest of this block concerns itself with // checking for a routable address, but the waiter has been // flagged to not wait for one. return true } var mask net . IPMask if ip . To4 ( ) != nil { mask = net . CIDRMask ( int ( addr . PrefixLength ) , 32 ) } else { mask = net . CIDRMask ( int ( addr . PrefixLength ) , 128 ) } if ip . Mask ( mask ) . Equal ( v4gw . Mask ( mask ) ) || ip . Mask ( mask ) . Equal ( v6gw . Mask ( mask ) ) { return true } } } } } } return false } ) if err != nil { // Provide a friendly error message if we timed out waiting for a routable IP. if ctx . Err ( ) == context . DeadlineExceeded { return errors . New ( " " ) } return err } log . Printf ( " " , vm . InventoryPath ) return nil }
// WaitForGuestNet waits for a virtual machine to have routable network
// access. This is denoted as a gateway, and at least one IP address that can
// reach that gateway. This function supports both IPv4 and IPv6, and returns
// the moment either stack is routable - it doesn't wait for both.
//
// The timeout is specified in minutes. If zero or a negative value is passed,
// the waiter returns without error immediately.
WaitForGuestNet waits for a virtual machine to have routable network access . This is denoted as a gateway and at least one IP address that can reach that gateway . This function supports both IPv4 and IPv6 and returns the moment either stack is routable - it doesn t wait for both . The timeout is specified in minutes . If zero or a negative value is passed the waiter returns without error immediately .