Skip to content

Commit

Permalink
Fix issue when checking guest IP of the VM with docker installed
Browse files Browse the repository at this point in the history
When docker daemon runs in the VM, there will be a NIC created by
Docker and usually has IP like 172.17.x.x. When VM is booting up,
VM Tools sometimes reports this IP to vCenter, although the real IP
of the non-docker nic will be reported later.

This patch can filter out the docker IP by specifying the prefix of
the invalid machine IP via the bootstrap option 'invalid_ip_prefix'.
e.g. invalid_ip_prefix: '172.17'.
  • Loading branch information
jessehu committed Mar 15, 2019
1 parent 798fd54 commit a672a98
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 8 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ This will use chef-zero and needs no chef server (only works for ssh). Note that
- `[:bootstrap_ipv4]` - `true` / `false`, set to `true` to wait for an IPv4 address to become available before bootstrapping.
- `[:ipv4_timeout]` - use with `[:bootstrap_ipv4]`, set the time in seconds to wait before an IPv4 address is received (defaults to 30)
- `[:ip_ready_timeout]` - set the time in seconds to wait before the machine IP is ready and connectable (defaults to 300)
- `[:invalid_ip_prefix]` - set the invalid prefix of the machine IP, e.g. the docker NIC IP like 172.17.0.1 (defaults to `nil` and can be set to something like '172.17')
- `[:ssh][:user]` user to use for ssh/winrm (defaults to root on linux/administrator on windows)
- `[:ssh][:password]` - password to use for ssh/winrm
- `[:ssh][:paranoid]` - specifies the strictness of the host key verification checking
Expand Down
29 changes: 21 additions & 8 deletions lib/chef/provisioning/vsphere_driver/driver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -647,8 +647,8 @@ def wait_until_ready(action_handler, machine_spec, machine_options, vm)
if vm.guest.toolsRunningStatus != "guestToolsRunning"
if action_handler.should_perform_actions
action_handler.report_progress "waiting for #{machine_spec.name} (#{vm.config.instanceUuid} on #{driver_url}) to be ready ..."
until remaining_wait_time(machine_spec, machine_options) < 0 ||
(vm.guest.toolsRunningStatus == "guestToolsRunning" && vm.guest.ipAddress && !vm.guest.ipAddress.empty?)
invalid_ip_prefix = bootstrap_invalid_ip_prefix(machine_options[:bootstrap_options])
until remaining_wait_time(machine_spec, machine_options) < 0 || vm_guest_ip?(vm, invalid_ip_prefix)
print "."
sleep 5
end
Expand Down Expand Up @@ -872,6 +872,7 @@ def ip_to_bootstrap(bootstrap_options, vm)
vm_helper.find_port?(vm, bootstrap_options) unless vm_helper.port?

# First get the IP to be tested
invalid_ip_prefix = bootstrap_invalid_ip_prefix(bootstrap_options)
if has_static_ip(bootstrap_options)
if bootstrap_options[:customization_spec].is_a?(String)
spec = vsphere_helper.find_customization_spec(bootstrap_options[:customization_spec])
Expand All @@ -881,9 +882,9 @@ def ip_to_bootstrap(bootstrap_options, vm)
vm_ip = bootstrap_options[:customization_spec][:ipsettings][:ip]
end
elsif use_ipv4_during_bootstrap?(bootstrap_options)
vm_ip = wait_for_ipv4(bootstrap_ipv4_timeout(bootstrap_options), vm)
vm_ip = wait_for_ipv4(bootstrap_ipv4_timeout(bootstrap_options), invalid_ip_prefix, vm)
else
until vm_guest_ip?(vm) || Time.now.utc - start_time > timeout
until vm_guest_ip?(vm, invalid_ip_prefix) || Time.now.utc - start_time > timeout
print "."
sleep 1
end
Expand Down Expand Up @@ -920,11 +921,19 @@ def bootstrap_ip_ready_timeout(bootstrap_options)
bootstrap_options.key?(:ip_ready_timeout) ? bootstrap_options[:ip_ready_timeout].to_i : 300
end

# Get invalid IP prefix which is used to filter out invalid IP of the VM, e.g. IP of the docker nic.
#
# @param [Object] bootstrap_options The bootstrap options from Chef-Provisioning
def bootstrap_invalid_ip_prefix(bootstrap_options)
bootstrap_options.key?(:invalid_ip_prefix) ? bootstrap_options[:invalid_ip_prefix].to_s : nil
end

# Wait for IPv4 address
#
# @param [String] timeout_seconds A timeout in seconds, an error will be raised if it is reached
# @param [String] invalid_ip_prefix The invalid IP prefix
# @param [Object] vm The VM object from Chef-Provisioning
def wait_for_ipv4(timeout_seconds, vm)
def wait_for_ipv4(timeout_seconds, invalid_ip_prefix, vm)
Chef::Log.info("Waiting #{timeout_seconds}s for ipv4 address.")

start_time = Time.now.utc
Expand All @@ -933,7 +942,7 @@ def wait_for_ipv4(timeout_seconds, vm)
sleep 5
vm_ips = all_ips_for(vm)
Chef::Log.info("Found IP address(es): #{vm_ips}")
next unless vm_guest_ip?(vm)
next unless vm_guest_ip?(vm, invalid_ip_prefix)
vm_ips.each do |vm_ip|
if IPAddr.new(vm_ip).ipv4?
Chef::Log.info("Found ipv4 address: #{vm_ip}")
Expand All @@ -947,8 +956,12 @@ def wait_for_ipv4(timeout_seconds, vm)
# What is the VM guest IP
#
# @param [Object] vm The VM object from Chef-Provisioning
def vm_guest_ip?(vm)
vm.guest.guestState == "running" && vm.guest.toolsRunningStatus == "guestToolsRunning" && !vm.guest.ipAddress.nil?
# @param [String] invalid_ip_prefix The invalid IP prefix
def vm_guest_ip?(vm, invalid_ip_prefix)
# The docker interface usually has IP like 172.17.x.x, so need to filter it out.
vm.guest.guestState == "running" && vm.guest.toolsRunningStatus == "guestToolsRunning" &&
!vm.guest.ipAddress.nil? && !vm.guest.ipAddress.empty? &&
(!invalid_ip_prefix || !vm.guest.ipAddress.start_with?(invalid_ip_prefix))
end
end
end

0 comments on commit a672a98

Please sign in to comment.