Skip to content

Commit

Permalink
Enable cancel operation for service template transformation plan request
Browse files Browse the repository at this point in the history
  • Loading branch information
hsong-rh committed Aug 13, 2018
1 parent 68e9e3b commit 4a43e3f
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 20 deletions.
48 changes: 41 additions & 7 deletions app/models/miq_request.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
class MiqRequest < ApplicationRecord
extend InterRegionApiMethodRelay

ACTIVE_STATES = %w(active queued)
ACTIVE_STATES = %w(active queued).freeze
REQUEST_UNIQUE_KEYS = %w(id state status created_on updated_on type).freeze

CANCEL_STATE_REQUESTED = "cancel_requested".freeze
CANCEL_STATE_PROCESSING = "canceling".freeze
CANCEL_STATE_FINISHED = "canceled".freeze
CANCEL_STATES = [CANCEL_STATE_REQUESTED, CANCEL_STATE_PROCESSING, CANCEL_STATE_FINISHED].freeze

belongs_to :source, :polymorphic => true
belongs_to :destination, :polymorphic => true
belongs_to :requester, :class_name => "User"
Expand All @@ -14,7 +19,7 @@ class MiqRequest < ApplicationRecord

alias_attribute :state, :request_state

serialize :options, Hash
serialize :options, Hash

default_value_for(:message) { |r| "#{r.class::TASK_DESCRIPTION} - Request Created" }
default_value_for :options, {}
Expand All @@ -23,8 +28,14 @@ class MiqRequest < ApplicationRecord
default_value_for :status, 'Ok'
default_value_for :process, true

include ReservedMixin
reserve_attribute :cancel_state, :string

validates_inclusion_of :approval_state, :in => %w(pending_approval approved denied), :message => "should be 'pending_approval', 'approved' or 'denied'"
validates_inclusion_of :status, :in => %w(Ok Warn Error Timeout Denied)
validates :cancel_state, :inclusion => { :in => CANCEL_STATES,
:allow_nil => true,
:message => "should be one of #{CANCEL_STATES.join(", ")}" }

validate :validate_class, :validate_request_type

Expand Down Expand Up @@ -54,17 +65,18 @@ class MiqRequest < ApplicationRecord

scope :created_recently, ->(days_ago) { where("miq_requests.created_on > ?", days_ago.days.ago) }
scope :with_approval_state, ->(state) { where(:approval_state => state) }
scope :with_cancel_state, ->(state) { where(:cancel_state => state) }
scope :with_type, ->(type) { where(:type => type) }
scope :with_request_type, ->(type) { where(:request_type => type) }
scope :with_requester, ->(id) { where(:requester_id => User.with_same_userid(id).collect(&:id)) }

MODEL_REQUEST_TYPES = {
:Automate => {
:Automate => {
:AutomationRequest => {
:automation => N_("Automation")
}
},
:Service => {
:Service => {
:MiqProvisionConfiguredSystemRequest => {
:provision_via_foreman => N_("%{config_mgr_type} Provision") % {:config_mgr_type => ui_lookup(:ui_title => 'foreman')}
},
Expand Down Expand Up @@ -199,8 +211,7 @@ def build_request_event(event_name)
)

{'EventStream::event_stream' => event_obj.id,
:event_stream_id => event_obj.id
}
:event_stream_id => event_obj.id}
end

def call_automate_event(event_name, synchronous: false)
Expand Down Expand Up @@ -432,6 +443,11 @@ def execute
end

def create_request_tasks
if cancel_requested?
do_cancel
return
end

# Quota denial will result in automate_event_failed? being true
return if automate_event_failed?("request_starting")

Expand Down Expand Up @@ -589,12 +605,30 @@ def cancel
raise _("Cancel operation is not supported for #{self.class.name}")
end

def cancel_requested?
cancel_state == CANCEL_STATE_REQUESTED
end

def canceling?
false
cancel_state == CANCEL_STATE_PROCESSING
end

def canceled?
cancel_state == CANCEL_STATE_FINISHED
end

private

def do_cancel
update_attributes(:cancel_state => CANCEL_STATE_PROCESSING)
cancel_cleanup
update_attributes(:cancel_state => CANCEL_STATE_FINISHED, :request_state => "finished", :status => "Error", :message => "Request is canceled by user.")
_log.info("Request #{description} is canceled by user.")
end

def cancel_cleanup
end

def clean_up_keys_for_request_task
req_task_attributes = attributes.dup
(req_task_attributes.keys - MiqRequestTask.column_names + REQUEST_UNIQUE_KEYS).each { |key| req_task_attributes.delete(key) }
Expand Down
21 changes: 20 additions & 1 deletion app/models/miq_request_task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ class MiqRequestTask < ApplicationRecord

include MiqRequestMixin
include TenancyMixin
include ReservedMixin
reserve_attribute :cancel_state, :string

CANCEL_STATE_REQUESTED = "cancel_requested".freeze
CANCEL_STATE_PROCESSING = "canceling".freeze
CANCEL_STATE_FINISHED = "canceled".freeze
CANCEL_STATES = [CANCEL_STATE_REQUESTED, CANCEL_STATE_PROCESSING, CANCEL_STATE_FINISHED].freeze

validates :cancel_state, :inclusion => { :in => CANCEL_STATES,
:allow_nil => true,
:message => "should be one of #{CANCEL_STATES.join(", ")}" }

def approved?
if miq_request.class.name.include?('Template') && miq_request_task
Expand Down Expand Up @@ -208,8 +219,16 @@ def cancel
raise _("Cancel operation is not supported for #{self.class.name}")
end

def cancel_requested?
cancel_state == MiqRequestTask::CANCEL_STATE_REQUESTED
end

def canceling?
false
cancel_state == MiqRequestTask::CANCEL_STATE_PROCESSING
end

def canceled?
cancel_state == MiqRequestTask::CANCEL_STATE_FINISHED
end

private
Expand Down
5 changes: 5 additions & 0 deletions app/models/service_template_provision_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ class ServiceTemplateProvisionRequest < MiqRequest
include MiqProvisionQuotaMixin

def process_service_order
if cancel_requested?
do_cancel
return
end

case options[:cart_state]
when ServiceOrder::STATE_ORDERED
ServiceOrder.order_immediately(self, requester)
Expand Down
7 changes: 1 addition & 6 deletions app/models/service_template_transformation_plan_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,7 @@ def approve_vm(vm_id)
end

def cancel
options['cancel_requested'] = true
save!
update_attributes(:cancel_state => MiqRequest::CANCEL_STATE_REQUESTED)
miq_request_tasks.each(&:cancel)
end

def canceling?
options['cancel_requested']
end
end
7 changes: 1 addition & 6 deletions app/models/service_template_transformation_plan_task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,7 @@ def transformation_log_queue(userid = nil)
end

def cancel
options['cancel_requested'] = true
save!
end

def canceling?
options['cancel_requested']
update_attributes(:cancel_state => MiqRequestTask::CANCEL_STATE_REQUESTED)
end

private
Expand Down
20 changes: 20 additions & 0 deletions spec/models/service_template_transformation_plan_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,24 @@
expect(ServiceResource.find_by(:resource => vms[0]).status).to eq(ServiceResource::STATUS_APPROVED)
end
end

context "gets cancel request" do
it "gets cancel_requested request" do
request.cancel
expect(request.cancel_state).to eq(MiqRequest::CANCEL_STATE_REQUESTED)
expect(request.cancel_requested?).to be_truthy
expect(request.canceling?).to be_falsey
expect(request.canceled?).to be_falsey
end

it "calls do_cancel" do
request.cancel

request.send(:do_cancel)
expect(request.cancel_state).to eq(MiqRequest::CANCEL_STATE_FINISHED)
expect(request.request_state).to eq('finished')
expect(request.status).to eq('Error')
expect(request.message).to eq('Request is canceled by user.')
end
end
end
8 changes: 8 additions & 0 deletions spec/models/service_template_transformation_plan_task_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -196,5 +196,13 @@
expect(vm).to be_is_tagged_with("migrated", :ns => "/managed", :cat => "transformation_status")
end
end

describe '#cancel' do
it 'catches cancel state' do
task.cancel
expect(task.cancel_state).to eq(MiqRequestTask::CANCEL_STATE_REQUESTED)
expect(task.cancel_requested?).to be_truthy
end
end
end
end

0 comments on commit 4a43e3f

Please sign in to comment.