From d0b43d558a650a8447030829d5830f6d3ca6176f Mon Sep 17 00:00:00 2001 From: Nick Vathis Date: Thu, 16 Feb 2017 13:42:34 +0200 Subject: [PATCH] Add wait on floating IP assignment Currently, vagrant fails when run with an openstack backend that assigns a floating IP asynchronously. With this patch, vagrant will wait after sending the floating IP assign command until the floating IP is actually assigned to the server. --- .../action/create_server.rb | 17 +++++++++++++++++ .../vagrant-openstack-provider/client/nova.rb | 13 +++++++++++++ source/lib/vagrant-openstack-provider/config.rb | 6 ++++++ source/locales/en.yml | 2 ++ .../action/create_server_spec.rb | 2 ++ 5 files changed, 40 insertions(+) diff --git a/source/lib/vagrant-openstack-provider/action/create_server.rb b/source/lib/vagrant-openstack-provider/action/create_server.rb index b818ac3..1e3f5c3 100644 --- a/source/lib/vagrant-openstack-provider/action/create_server.rb +++ b/source/lib/vagrant-openstack-provider/action/create_server.rb @@ -50,6 +50,7 @@ def execute(env) waiting_for_server_to_be_built(env, server_id) assign_floating_ip(env, server_id) + waiting_for_floating_ip_to_be_assigned(env, server_id) attach_volumes(env, server_id, options[:volumes]) unless options[:volumes].empty? @app.call(env) @@ -152,6 +153,22 @@ def assign_floating_ip(env, server_id) @logger.info 'Vagrant was unable to resolve FloatingIP, continue assuming it is not necessary' end + def waiting_for_floating_ip_to_be_assigned(env, server_id, retry_interval = 3) + floating_ip = @resolver.resolve_floating_ip(env) + return if !floating_ip || floating_ip.empty? + @logger.info "Waiting for floating IP #{floating_ip} to be assigned" + env[:ui].info(I18n.t('vagrant_openstack.waiting_for_floating_ip', floating_ip: floating_ip)) + config = env[:machine].provider_config + Timeout.timeout(config.floating_ip_assign_timeout, Errors::Timeout) do + until env[:openstack_client].nova.check_assigned_floating_ip(env, server_id, floating_ip) + sleep retry_interval + end + return + end + rescue Errors::UnableToResolveFloatingIP + @logger.info 'Vagrant was unable to resolve FloatingIP, not waiting for assignment' + end + def attach_volumes(env, server_id, volumes) @logger.info("Attaching volumes #{volumes} to server #{server_id}") volumes.each do |volume| diff --git a/source/lib/vagrant-openstack-provider/client/nova.rb b/source/lib/vagrant-openstack-provider/client/nova.rb index b33fc52..21a54be 100644 --- a/source/lib/vagrant-openstack-provider/client/nova.rb +++ b/source/lib/vagrant-openstack-provider/client/nova.rb @@ -145,6 +145,19 @@ def add_floating_ip(env, server_id, floating_ip) end end + def check_assigned_floating_ip(env, server_id, floating_ip) + instance_exists do + addresses = get_server_details(env, server_id)['addresses'] + addresses.each do |_, network| + network.each do |network_detail| + return true if network_detail['addr'] == floating_ip + end + end + + return false + end + end + def import_keypair(env, public_key) keyname = "vagrant-generated-#{Kernel.rand(36**8).to_s(36)}" diff --git a/source/lib/vagrant-openstack-provider/config.rb b/source/lib/vagrant-openstack-provider/config.rb index 854eed3..fce08f8 100644 --- a/source/lib/vagrant-openstack-provider/config.rb +++ b/source/lib/vagrant-openstack-provider/config.rb @@ -217,6 +217,10 @@ class Config < Vagrant.plugin('2', :config) # @return [Integer] attr_accessor :stack_delete_timeout + # + # @return [Integer] + attr_accessor :floating_ip_assign_timeout + # # @return [HttpConfig] attr_accessor :http @@ -282,6 +286,7 @@ def initialize @server_delete_timeout = UNSET_VALUE @stack_create_timeout = UNSET_VALUE @stack_delete_timeout = UNSET_VALUE + @floating_ip_assign_timeout = UNSET_VALUE @meta_args_support = UNSET_VALUE @http = HttpConfig.new @use_legacy_synced_folders = UNSET_VALUE @@ -390,6 +395,7 @@ def finalize! @server_delete_timeout = 200 if @server_delete_timeout == UNSET_VALUE @stack_create_timeout = 200 if @stack_create_timeout == UNSET_VALUE @stack_delete_timeout = 200 if @stack_delete_timeout == UNSET_VALUE + @floating_ip_assign_timeout = 200 if @floating_ip_assign_timeout == UNSET_VALUE @meta_args_support = false if @meta_args_support == UNSET_VALUE @networks = nil if @networks.empty? @volumes = nil if @volumes.empty? diff --git a/source/locales/en.yml b/source/locales/en.yml index d70f20c..f89d53b 100644 --- a/source/locales/en.yml +++ b/source/locales/en.yml @@ -69,6 +69,8 @@ en: Rsyncing folder: %{hostpath} => %{guestpath} using_floating_ip: |- Using floating IP %{floating_ip} + waiting_for_floating_ip: |- + Waiting for floating IP %{floating_ip} to be assigned... waiting_for_build: |- Waiting for the server to be built... waiting_for_ssh: |- diff --git a/source/spec/vagrant-openstack-provider/action/create_server_spec.rb b/source/spec/vagrant-openstack-provider/action/create_server_spec.rb index f0758aa..695b9b1 100644 --- a/source/spec/vagrant-openstack-provider/action/create_server_spec.rb +++ b/source/spec/vagrant-openstack-provider/action/create_server_spec.rb @@ -109,10 +109,12 @@ allow(@action).to receive(:waiting_for_server_to_be_built) allow(@action).to receive(:attach_volumes) allow(@action).to receive(:waiting_for_server_to_be_reachable) + allow(@action).to receive(:waiting_for_floating_ip_to_be_assigned) expect(@action).to receive(:waiting_for_server_to_be_built).with(env, '45678') expect(@action).to receive(:assign_floating_ip).with(env, '45678').and_return('1.2.3.4') expect(@action).to receive(:attach_volumes).with(env, '45678', [{ id: 'vol-01', device: nil }]) + expect(@action).to receive(:waiting_for_floating_ip_to_be_assigned).with(env, '45678') @action.call(env) end