From 6d3362f300bb1bb8a0f3b099d6b57d8552950288 Mon Sep 17 00:00:00 2001 From: Joe Rafaniello Date: Tue, 6 Jun 2017 15:29:31 -0400 Subject: [PATCH 1/2] Make spawn an option again instead of just fork Use run_single_worker script for worker spawning Embedded ansible worker overrides start_runner to implement a thread based worker implementation. --- app/models/embedded_ansible_worker.rb | 1 + app/models/miq_worker.rb | 21 +++++++++++++++++++++ app/models/miq_worker/runner.rb | 1 + spec/models/miq_worker_spec.rb | 26 ++++++++++++++++++++++++++ 4 files changed, 49 insertions(+) diff --git a/app/models/embedded_ansible_worker.rb b/app/models/embedded_ansible_worker.rb index 2c6fa0c3517..05b49e7c924 100644 --- a/app/models/embedded_ansible_worker.rb +++ b/app/models/embedded_ansible_worker.rb @@ -17,6 +17,7 @@ def start_runner Thread.exit end end + nil # return no pid end def kill diff --git a/app/models/miq_worker.rb b/app/models/miq_worker.rb index 227ef77658e..00e9971c6c2 100644 --- a/app/models/miq_worker.rb +++ b/app/models/miq_worker.rb @@ -335,6 +335,10 @@ def self.close_pg_sockets_inherited_from_parent end def start_runner + ENV['MIQ_SPAWN_WORKERS'] ? start_runner_via_spawn : start_runner_via_fork + end + + def start_runner_via_fork self.class.before_fork pid = fork(:cow_friendly => true) do self.class.after_fork @@ -346,6 +350,23 @@ def start_runner pid end + def self.build_command_line(guid) + command_line = "#{Gem.ruby} #{runner_script} --heartbeat --guid=#{guid} #{name}" + ENV['APPLIANCE'] ? "nice #{nice_increment} #{command_line}" : command_line + end + + def self.runner_script + script = ManageIQ.root.join("lib/workers/bin/run_single_worker.rb") + raise "script not found: #{script}" unless File.exist?(script) + script + end + + def start_runner_via_spawn + pid = Kernel.spawn(self.class.build_command_line(guid), :out => "/dev/null", :err => [Rails.root.join("log", "evm.log"), "a"]) + Process.detach(pid) + pid + end + def start self.pid = start_runner save diff --git a/app/models/miq_worker/runner.rb b/app/models/miq_worker/runner.rb index 4dd26790e4d..31ca970cf71 100644 --- a/app/models/miq_worker/runner.rb +++ b/app/models/miq_worker/runner.rb @@ -11,6 +11,7 @@ class TemporaryFailure < RuntimeError INTERRUPT_SIGNALS = ["SIGINT", "SIGTERM"] + # DELETE ME OPTIONS_PARSER_SETTINGS = [ [:guid, 'EVM Worker GUID', String], ] diff --git a/spec/models/miq_worker_spec.rb b/spec/models/miq_worker_spec.rb index bf458efb772..704d0218cbe 100644 --- a/spec/models/miq_worker_spec.rb +++ b/spec/models/miq_worker_spec.rb @@ -29,6 +29,32 @@ def all_workers expect(result.command_line).to eq "renice -n 5 -p 123" end + context ".build_command_line" do + before do + allow(MiqGenericWorker).to receive(:nice_increment).and_return("+10") + end + + it "with ENV['APPLIANCE']" do + begin + old_env = ENV.delete('DATABASE_URL') + ENV['APPLIANCE'] = 'true' + w = FactoryGirl.build(:miq_generic_worker) + cmd = w.class.build_command_line(123) + expect(cmd).to start_with("nice +10") + expect(cmd).to end_with("MiqGenericWorker") + ensure + # ENV['x'] = nil deletes the key because ENV accepts only string values + ENV['APPLIANCE'] = old_env + end + end + + it "without ENV['APPLIANCE']" do + w = FactoryGirl.build(:miq_generic_worker) + cmd = w.class.build_command_line(123) + expect(cmd).to_not start_with("nice +10") + end + end + context ".has_required_role?" do def check_has_required_role(worker_role_names, expected_result) allow(described_class).to receive(:required_roles).and_return(worker_role_names) From 3f3a823770d4f145c97a256d62e7f679d4d76e70 Mon Sep 17 00:00:00 2001 From: Nick LaMuro Date: Wed, 7 Jun 2017 16:14:46 -0500 Subject: [PATCH 2/2] Allow using existing guid for run_single_worker When running single workers in the context of a worker monitor, the worker records are usually already created by the monitor process by the time the worker is forked/spawned. Allowing the lib/worker/bin/run_single_worker.rb script to pass a guid allows it to use those records instead of creating new ones. If this option isn't used, the already created ones exist along side the other worker records, and cause evm:stop to not function properly. --- lib/workers/bin/run_single_worker.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/workers/bin/run_single_worker.rb b/lib/workers/bin/run_single_worker.rb index 5a446dc576c..5b22aeff807 100644 --- a/lib/workers/bin/run_single_worker.rb +++ b/lib/workers/bin/run_single_worker.rb @@ -23,6 +23,10 @@ options[:dry_run] = val end + opts.on("-g=GUID", "--guid=GUID", "Find an existing worker record instead of creating") do |val| + options[:guid] = val + end + opts.on("-h", "--help", "Displays this help") do puts opts exit @@ -52,7 +56,12 @@ worker_class = worker_class.constantize worker_class.before_fork unless options[:dry_run] - worker = worker_class.create_worker_record + worker = if options[:guid] + worker_class.find_by!(:guid => options[:guid]) + else + worker_class.create_worker_record + end + begin worker.class::Runner.start_worker(:guid => worker.guid) ensure