app/lib/actions/proxy_action.rb in foreman-tasks-0.15.0 vs app/lib/actions/proxy_action.rb in foreman-tasks-0.15.1

- old
+ new

@@ -24,12 +24,19 @@ class ProxyActionStopped; end def plan(proxy, klass, options) options[:connection_options] ||= {} - default_connection_options.each { |key, value| options[:connection_options][key] ||= value } - plan_self(options.merge(:proxy_url => proxy.url, :proxy_action_name => klass.to_s)) + default_connection_options.each do |key, value| + options[:connection_options][key] = value unless options[:connection_options].key?(key) + end + plan_self(options.merge(:proxy_url => proxy.url, :proxy_action_name => klass.to_s, :proxy_version => proxy_version(proxy))) + # Just saving the RemoteTask is enough when using batch triggering + # It will be picked up by the ProxyBatchTriggering middleware + if input[:use_batch_triggering] && with_batch_triggering?(input[:proxy_version]) + prepare_remote_task.save! + end end def run(event = nil) with_connection_error_handling(event) do |event| case event @@ -62,24 +69,26 @@ @remote_task ||= ForemanTasks::RemoteTask.find_by(:execution_plan_id => execution_plan_id, :step_id => run_step_id) end def trigger_proxy_task suspend do |_suspended_action| - response = proxy.trigger_task(proxy_action_name, - input.merge(:callback => { :task_id => task.id, - :step_id => run_step_id })) - ::ForemanTasks::RemoteTask.new(:remote_task_id => response['task_id'], :execution_plan_id => execution_plan_id, - :state => 'triggered', :proxy_url => input[:proxy_url], :step_id => run_step_id).save! - output[:proxy_task_id] = response['task_id'] + remote_task = prepare_remote_task + remote_task.trigger(proxy_action_name, proxy_input) + output[:proxy_task_id] = remote_task.remote_task_id end end + def proxy_input(task_id = task.id) + input.merge(:callback => { :task_id => task_id, + :step_id => run_step_id }) + end + def check_task_status - response = proxy.status_of_task(output[:proxy_task_id]) + response = proxy.status_of_task(proxy_task_id) if %w[stopped paused].include? response['state'] if response['result'] == 'error' - raise ::Foreman::Exception, _('The smart proxy task %s failed.') % output[:proxy_task_id] + raise ::Foreman::Exception, _('The smart proxy task %s failed.') % proxy_task_id else on_data(response['actions'].find { |block_action| block_action['class'] == proxy_action_name }['output']) end else suspend @@ -88,18 +97,18 @@ def cancel_proxy_task if output[:cancel_sent] error! ForemanTasks::Task::TaskCancelledException.new(_('Cancel enforced: the task might be still running on the proxy')) else - proxy.cancel_task(output[:proxy_task_id]) + proxy.cancel_task(proxy_task_id) output[:cancel_sent] = true suspend end end def abort_proxy_task - proxy.cancel_task(output[:proxy_task_id]) + proxy.cancel_task(proxy_task_id) error! ForemanTasks::Task::TaskCancelledException.new(_('Task aborted: the task might be still running on the proxy')) end def on_resume # TODO: add logic to load the data from the external action @@ -130,19 +139,24 @@ # @override String name of an action to be triggered on server def proxy_action_name input[:proxy_action_name] end + # @override String name of a operation to be triggered on server + def proxy_operation_name + input[:proxy_operation_name] + end + def proxy ProxyAPI::ForemanDynflow::DynflowProxy.new(:url => input[:proxy_url]) end def proxy_output(live = false) if output.key?(:proxy_output) || state == :error output.fetch(:proxy_output, {}) - elsif live && output[:proxy_task_id] - proxy_data = proxy.status_of_task(output[:proxy_task_id])['actions'].detect { |action| action['class'] == proxy_action_name } + elsif live && proxy_task_id + proxy_data = proxy.status_of_task(proxy_task_id)['actions'].detect { |action| action['class'] == proxy_action_name } proxy_data.fetch('output', {}) else {} end end @@ -172,19 +186,30 @@ def default_connection_options # Fails if the plan is not finished within 60 seconds from the first task trigger attempt on the smart proxy # If the triggering fails, it retries 3 more times with 15 second delays { :retry_interval => Setting['foreman_tasks_proxy_action_retry_interval'] || 15, - :retry_count => Setting['foreman_tasks_proxy_action_retry_count'] || 4 } + :retry_count => Setting['foreman_tasks_proxy_action_retry_count'] || 4, + :proxy_batch_triggering => Setting['foreman_tasks_proxy_batch_trigger'] || false } end + def with_batch_triggering?(proxy_version) + (proxy_version[:major] == 1 && proxy_version[:minor] > 20) || proxy_version[:major] > 1 && + input.fetch(:connection_options, {}).fetch(:proxy_batch_triggering, false) + end + def clean_remote_task(*_args) remote_task.destroy! if remote_task end private + def proxy_version(proxy) + match = proxy.statuses[:version].version['version'].match(/(\d+)\.(\d+)\.(\d+)/) + { :major => match[1].to_i, :minor => match[2].to_i, :patch => match[3].to_i } + end + def failed_proxy_tasks metadata[:failed_proxy_tasks] ||= [] end def with_connection_error_handling(event = nil) @@ -196,11 +221,11 @@ handle_connection_exception(e, event) end end def format_exception(exception) - { :proxy_task_id => output[:proxy_task_id], + { :proxy_task_id => proxy_task_id, :exception_class => exception.class.name, :exception_message => exception.message, :timestamp => Time.now.to_f } end @@ -215,8 +240,19 @@ event end else raise exception end + end + + def prepare_remote_task + ::ForemanTasks::RemoteTask.new(:execution_plan_id => execution_plan_id, + :proxy_url => input[:proxy_url], + :step_id => run_step_id, + :operation => proxy_operation_name) + end + + def proxy_task_id + output[:proxy_task_id] ||= remote_task.try(:remote_task_id) end end end