diff --git a/app/models/embedded_ansible_worker/runner.rb b/app/models/embedded_ansible_worker/runner.rb index 9c6f545078d..20b7a2ddec2 100644 --- a/app/models/embedded_ansible_worker/runner.rb +++ b/app/models/embedded_ansible_worker/runner.rb @@ -1,4 +1,5 @@ class EmbeddedAnsibleWorker::Runner < MiqWorker::Runner + attr_accessor :provider_server_last_synchronized def prepare ObjectSpace.garbage_collect # Overriding prepare so we can set started when we're ready @@ -22,6 +23,7 @@ def heartbeat end def do_work + synchronize_provider_with_server unless provider_in_sync_with_server? embedded_ansible.start if !embedded_ansible.alive? && !embedded_ansible.running? provider.authentication_check if embedded_ansible.alive? && !provider.authentication_status_ok? update_job_data_retention @@ -38,14 +40,7 @@ def setup_ansible end def update_embedded_ansible_provider - server = MiqServer.my_server(true) - - provider.name = "Embedded Ansible" - provider.zone = server.zone - provider.url = provider_url - provider.verify_ssl = 0 - - provider.save! + synchronize_provider_with_server api_connection = embedded_ansible.api_connection worker.remove_demo_data(api_connection) @@ -57,6 +52,25 @@ def update_embedded_ansible_provider provider.authentication_check end + def synchronize_provider_with_server + server = MiqServer.my_server(true) + + provider.name = "Embedded Ansible" + provider.zone = server.zone + provider.url = provider_url + provider.verify_ssl = 0 + + provider.save! + end + + def provider_in_sync_with_server? + now = Time.now.utc + return true if @provider_server_last_synchronized.kind_of?(Time) && (@provider_server_last_synchronized + worker_settings[:sync_provider_with_server_interval]) >= now + + @provider_server_last_synchronized = now + provider.reload.zone == server.reload.zone && provider.url == provider_url + end + # Base class methods we override since we don't have a separate process. We might want to make these opt-in features in the base class that this subclass can choose to opt-out. def set_process_title; end def set_database_application_name; end diff --git a/config/settings.yml b/config/settings.yml index fcde96071ee..6cd91fe7899 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -1141,6 +1141,7 @@ :starting_timeout: 20.minutes :poll: 10.seconds :memory_threshold: 0.megabytes + :sync_provider_with_server_interval: 1.minute :agent_coordinator_worker: :heartbeat_timeout: 30.minutes :poll: 30.seconds diff --git a/spec/models/embedded_ansible_worker/runner_spec.rb b/spec/models/embedded_ansible_worker/runner_spec.rb index 36aac12e9ab..9be17a20709 100644 --- a/spec/models/embedded_ansible_worker/runner_spec.rb +++ b/spec/models/embedded_ansible_worker/runner_spec.rb @@ -100,6 +100,7 @@ end it "starts embedded ansible if it is not alive and not running" do + allow(runner).to receive(:provider_in_sync_with_server?).and_return(true) allow(embedded_ansible_instance).to receive(:alive?).and_return(false) allow(embedded_ansible_instance).to receive(:running?).and_return(false) @@ -109,7 +110,7 @@ end context "with a provider" do - let(:provider) { FactoryGirl.create(:provider_embedded_ansible, :with_authentication) } + let!(:provider) { FactoryGirl.create(:provider_embedded_ansible, :with_authentication) } it "runs an authentication check if embedded ansible is alive and the credentials are not valid" do auth = provider.authentications.first @@ -139,6 +140,43 @@ expect(embedded_ansible_instance).to receive(:set_job_data_retention) runner.do_work end + + it "updates provider zone if appliance zone changed" do + allow(embedded_ansible_instance).to receive(:alive?).and_return(true) + miq_server.update(:zone => FactoryGirl.create(:zone)) + + runner.do_work + expect(provider.reload.zone).to eq(miq_server.zone) + end + + it "updates provider URL if appliance hostname changes" do + allow(embedded_ansible_instance).to receive(:alive?).and_return(true) + miq_server.update(:hostname => "example42.com") + + runner.do_work + expect(provider.reload.url).to include("example42.com") + end + + it "provider zone change is delayed 1 minute after appliance's zone changes" do + allow(embedded_ansible_instance).to receive(:alive?).and_return(true) + runner.sync_worker_settings + + # provider zone is checked + runner.do_work + + original_zone = miq_server.zone + miq_server.update(:zone => FactoryGirl.create(:zone)) + + # zone was just checked, doesn't do anything yet + runner.do_work + expect(provider.reload.zone).to eq(original_zone) + + # wait at least 1 minute and try again, it now matches the server zone + Timecop.travel(65.seconds) do + runner.do_work + expect(provider.reload.zone).to eq(miq_server.zone) + end + end end end