Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Schedule time values #17547

Closed
wants to merge 9 commits into from
33 changes: 29 additions & 4 deletions app/models/miq_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class MiqRequest < ApplicationRecord
belongs_to :service_order
has_many :miq_approvals, :dependent => :destroy
has_many :miq_request_tasks, :dependent => :destroy
has_one :miq_schedule, :dependent => :destroy, :as => :resource

acts_as_miq_taggable

Expand Down Expand Up @@ -417,14 +418,39 @@ def task_check_on_execute
raise _("approval is required for %{task}") % {:task => self.class::TASK_DESCRIPTION} unless approved?
end

private def scheduled_time
return unless get_option(:schedule_type) == "schedule"
t = get_option(:schedule_time)
if t.kind_of?(Time)
t.utc
elsif t.kind_of?(String)
require 'time'
Time.parse(t).utc
end
end

def execute
task_check_on_execute

deliver_on = nil
if get_option(:schedule_type) == "schedule"
deliver_on = get_option(:schedule_time).utc rescue nil
if start_time = scheduled_time
MiqSchedule.create!(
:name => "Request scheduled",
:description => "Request scheduled",
:sched_action => {:method => "queue_create_request_tasks"},
:resource_id => id,
:towhat => "MiqRequest",
:run_at => {
:interval => {:unit => "once"},
:start_time => start_time,
:tz => "UTC",
},
)
else
queue_create_request_tasks
end
end

def queue_create_request_tasks
# self.create_request_tasks
MiqQueue.put(
:class_name => self.class.name,
Expand All @@ -434,7 +460,6 @@ def execute
:role => my_role(:create_request_tasks),
:tracking_label => tracking_label_id,
:msg_timeout => 3600,
:deliver_on => deliver_on
)
end

Expand Down
32 changes: 20 additions & 12 deletions app/models/miq_schedule.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
class MiqSchedule < ApplicationRecord
include DeprecationMixin
deprecate_attribute :towhat, :resource_type

validates :name, :uniqueness => {:scope => [:userid, :towhat]}
validates :name, :description, :towhat, :run_at, :presence => true
validate :validate_run_at, :validate_file_depot
Expand All @@ -11,6 +14,7 @@ class MiqSchedule < ApplicationRecord

belongs_to :file_depot
belongs_to :miq_search
belongs_to :resource, :polymorphic => true
belongs_to :zone

scope :in_zone, lambda { |zone_name|
Expand Down Expand Up @@ -72,21 +76,25 @@ def self.queue_scheduled_work(id, _rufus_job_id, at, _params)
_log.info("Queueing start of schedule id: [#{id}] [#{sched.name}] [#{sched.towhat}] [#{method}]")

action = "action_" + method
unless sched.respond_to?(action)

if sched.respond_to?(action)
msg = MiqQueue.submit_job(
:class_name => name,
:instance_id => sched.id,
:method_name => "invoke_actions",
:args => [action, at],
:msg_timeout => 1200
)

_log.info("Queueing start of schedule id: [#{id}] [#{sched.name}] [#{sched.towhat}] [#{method}]...complete")
msg
elsif sched.resource.respond_to?(method)
sched.resource.send(method)
sched.update_attributes(:last_run_on => Time.now.utc)
else
_log.warn("[#{sched.name}] no such action: [#{method}], aborting schedule")
return
end

msg = MiqQueue.submit_job(
:class_name => name,
:instance_id => sched.id,
:method_name => "invoke_actions",
:args => [action, at],
:msg_timeout => 1200
)

_log.info("Queueing start of schedule id: [#{id}] [#{sched.name}] [#{sched.towhat}] [#{method}]...complete")
msg
end

def invoke_actions(action, at)
Expand Down
44 changes: 44 additions & 0 deletions spec/models/miq_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,28 @@ def approvals
it_behaves_like "#calls create_request_tasks with the proper role"
end
end

it "scheduled - creates an associated schedule" do
EvmSpecHelper.local_miq_server
request = FactoryGirl.create(:automation_request, :options => {:schedule_type => "schedule", :schedule_time => Time.now.utc})
request.miq_approvals.all.each { |a| a.update_attributes!(:state => "approved") }

request.reload.execute

expect(MiqQueue.count).to eq(0)
expect(MiqSchedule.count).to eq(1)
end

it "non_scheduled - is queued directly" do
EvmSpecHelper.local_miq_server
request = FactoryGirl.create(:automation_request)
request.miq_approvals.all.each { |a| a.update_attributes!(:state => "approved") }

request.reload.execute

expect(MiqQueue.count).to eq(1)
expect(MiqSchedule.count).to eq(0)
end
end

context '#post_create_request_tasks' do
Expand Down Expand Up @@ -565,4 +587,26 @@ def approvals
expect(orch_stack_request.class::SOURCE_CLASS_NAME).to eq('OrchestrationStack')
end
end

context "private methods" do
context "#scheduled_time" do
it "without a schedule_type" do
expect(AutomationRequest.new(:options => {:schedule_time => "abc"}).send(:scheduled_time)).to be_nil
end

it "with a schedule_type and no schedule_time" do
expect(AutomationRequest.new(:options => {:schedule_type => "schedule"}).send(:scheduled_time)).to be_nil
end

it "with a schedule_type and a Time schedule_time" do
t = Time.now.utc
expect(AutomationRequest.new(:options => {:schedule_type => "schedule", :schedule_time => t}).send(:scheduled_time)).to eq(t)
end

it "with a schedule_type and a String schedule_time" do
t = Time.now.utc
expect(AutomationRequest.new(:options => {:schedule_type => "schedule", :schedule_time => t.to_s}).send(:scheduled_time)).to be_within(1.second).of(t)
end
end
end
end
34 changes: 34 additions & 0 deletions spec/models/miq_schedule_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -695,4 +695,38 @@
expect(MiqSchedule.updated_since(1.month.ago)).to eq([s])
end
end

context ".queue_scheduled_work" do
it "When action exists" do
s = FactoryGirl.create(:miq_schedule, :sched_action => {:method => "scan"})
MiqSchedule.queue_scheduled_work(s.id, nil, "abc", nil)

expect(MiqQueue.first).to have_attributes(
:class_name => "MiqSchedule",
:instance_id => s.id,
:method_name => "invoke_actions",
:args => ["action_scan", "abc"],
:msg_timeout => 1200
)
end

it "with no action method, but resource exists and responds to the method" do
resource = FactoryGirl.create(:host)
s = FactoryGirl.create(:miq_schedule, :resource => resource, :sched_action => {:method => "test_method"})

expect_any_instance_of(Host).to receive("test_method").once

MiqSchedule.queue_scheduled_work(s.id, nil, "abc", nil)
end

it "with no action or resource" do
s = FactoryGirl.create(:miq_schedule, :sched_action => {:method => "test_method"})

expect($log).to receive(:warn) do |message|
expect(message).to include("no such action: [test_method], aborting schedule")
end

MiqSchedule.queue_scheduled_work(s.id, nil, "abc", nil)
end
end
end