-
Notifications
You must be signed in to change notification settings - Fork 896
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Right now, this is a worker that doesn't have a separate process. Instead, it's just a thread running in the server that monitors the supervisord process and handles restarting it when it goes down. https://www.pivotaltracker.com/story/show/135450841
- Loading branch information
Showing
7 changed files
with
152 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
class EmbeddedAnsibleWorker < MiqWorker | ||
require_nested :Runner | ||
|
||
self.required_roles = ['embedded_ansible'] | ||
|
||
def start_runner | ||
self.class::Runner.start_worker(worker_options) | ||
# TODO: return supervisord pid | ||
end | ||
|
||
def kill | ||
# Does the base class's kill -9 work on the supervisord process as we want? | ||
end | ||
|
||
def status_update | ||
# don't monitor the memory/cpu usage of this process yet | ||
# If we don't have a pid of a process we want to monitor,super will catch an Errno::ESRCH and abort the worker | ||
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 release_db_connection; end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
class EmbeddedAnsibleWorker::Runner < MiqWorker::Runner | ||
def prepare | ||
update_embedded_ansible_manager | ||
|
||
Thread.new do | ||
setup_ansible | ||
started_worker_record | ||
end | ||
|
||
self | ||
end | ||
|
||
# This thread runs forever until a stop request is received, which with send us to do_exit to exit our thread | ||
def do_work_loop | ||
Thread.new do | ||
_log.info("waiting for ansible to start...") | ||
loop do | ||
# handle if the ansible setup blew up or timed out | ||
break if worker.reload.started? | ||
heartbeat | ||
send(poll_method) | ||
end | ||
|
||
_log.info("entering ansible monitor loop") | ||
loop do | ||
heartbeat | ||
do_work | ||
send(poll_method) | ||
end | ||
end | ||
end | ||
|
||
def setup_ansible | ||
_log.info("calling EmbeddedAnsible.configure") | ||
EmbeddedAnsible.configure unless EmbeddedAnsible.configured? | ||
|
||
_log.info("calling EmbeddedAnsible.start") | ||
EmbeddedAnsible.start | ||
_log.info("calling EmbeddedAnsible.start finished") | ||
end | ||
|
||
def do_work | ||
if EmbeddedAnsible.running? | ||
_log.info("#{log_prefix} supervisord is ok!") | ||
else | ||
_log.warn("#{log_prefix} supervisord is not running, restarting!") | ||
EmbeddedAnsible.start | ||
end | ||
end | ||
|
||
# Because we're running in a thread on the Server | ||
# we need to intercept SystemExit and exit our thread, | ||
# not the main server thread! | ||
def do_exit(*args) | ||
# ensure this doesn't fail or that we can still get to the super call | ||
EmbeddedAnsible.disable | ||
super | ||
rescue SystemExit | ||
_log.info("#{log_prefix} SystemExit received, exiting monitoring Thread") | ||
Thread.exit | ||
end | ||
|
||
def update_embedded_ansible_manager | ||
ansible = ManageIQ::Providers::EmbeddedAnsible::AutomationManager.first_or_initialize | ||
server = MiqServer.my_server(true) | ||
ansible.default_endpoint.url = URI::HTTPS.build(:host => server.hostname, :path => "/ansibleapi/v1") | ||
ansible.name = "Embedded Ansible" | ||
ansible.zone = server.zone | ||
ansible.save! | ||
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_connection_pool_size; end | ||
def message_sync_active_roles(*_args); end | ||
def message_sync_config(*_args); end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
describe EmbeddedAnsibleWorker::Runner do | ||
context ".new" do | ||
let(:miq_server) { | ||
s = EvmSpecHelper.create_guid_miq_server_zone[1] | ||
s.update(:hostname => "fancyserver") | ||
s | ||
} | ||
let(:worker_guid) { MiqUUID.new_guid } | ||
let(:worker) { FactoryGirl.create(:embedded_ansible_worker, :guid => worker_guid, :miq_server_id => miq_server.id) } | ||
let(:runner) { | ||
worker | ||
allow_any_instance_of(described_class).to receive(:worker_initialization) | ||
described_class.new(:guid => worker_guid) | ||
} | ||
|
||
context "#update_embedded_ansible_manager" do | ||
it "creates initial" do | ||
runner.update_embedded_ansible_manager | ||
|
||
ansible = ManageIQ::Providers::EmbeddedAnsible::AutomationManager.first | ||
expect(ansible.zone).to eq(miq_server.zone) | ||
expect(ansible.default_endpoint.url).to eq("https://fancyserver/ansibleapi/v1") | ||
end | ||
|
||
it "updates existing" do | ||
runner.update_embedded_ansible_manager | ||
new_zone = FactoryGirl.create(:zone) | ||
miq_server.update(:hostname => "boringserver", :zone => new_zone) | ||
|
||
runner.update_embedded_ansible_manager | ||
expect(ManageIQ::Providers::EmbeddedAnsible::AutomationManager.count).to eq(1) | ||
|
||
ansible = ManageIQ::Providers::EmbeddedAnsible::AutomationManager.first | ||
expect(ansible.zone).to eq(new_zone) | ||
expect(ansible.default_endpoint.url).to eq("https://boringserver/ansibleapi/v1") | ||
end | ||
end | ||
end | ||
end | ||
|