chef-boneyard / chef-provisioning-vsphere

DEPRECATED: A chef-provisioning provisioner for VMware vSphere
MIT License
17 stars 15 forks source link

IPv6 address returned by VM can cause failures #52

Closed lomeroe closed 6 years ago

lomeroe commented 7 years ago

Versions:

Platform Details

Scenario:

Creating Windows Server 2016 VMs to converge/test fail during create phase due to IPv6 link local address being returned from VMWare tools. The failure at the create phase also leaves a VM in the vCenter inventory that must be manually cleaned up (no yml config file created/etc).

Steps to Reproduce:

Create a Windows Server 2016 VM with VMWare tools installed/set to DHCP. Utilize VM as source for test-kitchen run. (Occasionally, the DHCP'd IPv4 address will be returned appropriately and the create will function and the test-kitchen run will work)

Expected Result:

create phase completes

Actual Result:

Running test-kitchen on a linux node yields the following error:

>>>>>> ------Exception-------
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: 1 actions failed.
>>>>>>     Failed to complete #create action: [Invalid argument - connect(2) for [fe80::4947:7c44:2262:4fcb]:5985] on 2016-vmware
>>>>>> ----------------------
>>>>>> Please see .kitchen/logs/kitchen.log for more details
>>>>>> Also try running `kitchen diagnose --all` for configuration

Running test-kitchen on a Windows system returns:

>>>>>> ------Exception-------
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: 1 actions failed.
>>>>>>     Failed to complete #create action: [bad URI(is not URI?): http://fe80
::f80e:a236:5c97:b22b:5985/wsman] on 2016-vmware
>>>>>> ----------------------
>>>>>> Please see .kitchen/logs/kitchen.log for more details
>>>>>> Also try running `kitchen diagnose --all` for configuration

Systems running test-kitchen have IPv6 enabled, a link local address of their own, and are on the same subnet. They should be able to connect over IPv6 link local addresses.

This error is returning during the "ip_to_bootstrap" function, in the line

vm_ip = vm.guest.ipAddress until vm_guest_ip?(vm) && @vm_helper.open_port?(vm_ip, @vm_helper.port, 1) # Don't set empty ip

The vm_guest_ip? function verifies the address that is returned is an IPv4 address, however vm_helper.open_port performs no checks and will attempt to connect to the IPv6 address.

Altering the "open_port?" function in vm_helper to add a check for IPv6 resolves the issue for me:

    def open_port?(host, port, timeout = 5)
      return false if host.to_s.empty?
      return false if IPAddr.new(host).ipv6?
      true if ::Socket.tcp(host, port, connect_timeout: timeout)
    rescue *RESCUE_EXCEPTIONS_ON_ESTABLISH
      false
    end

I'm not sure if this is the best and/or most appropriate fix (I'm happy to submit a PR if it is agreeable). Socket supports IPv6, but it appears you may have create the socket to IPv6 with the SOCKET::AF_INET6 constant (my ruby is super weak and I couldn't find much in the way of IPv6 documentation/examples to really confirm that).

alrf commented 7 years ago

The same issue for me.

>>>>>> ------Exception-------
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: 1 actions failed.
>>>>>>     Failed to complete #create action: [bad URI(is not URI?): http://fe80::b852:737c:79b3:b245:5986/wsman] on windows-devenv01-windows-2012r2
>>>>>> ----------------------
jjasghar commented 7 years ago

@lomeroe the fix seems reasonable, but we should probably put in feature flag to turn it on or off. I know i don't use ipv6 at all, but some shops might. I'd love to see a PR on this if you have the time to create one.