app/models/service_template_provision_task.rb
class ServiceTemplateProvisionTask < MiqRequestTask
validate :validate_request_type, :validate_state
virtual_belongs_to :service_resource, :class_name => "ServiceResource"
AUTOMATE_DRIVES = true
def self.base_model
ServiceTemplateProvisionTask
end
def statemachine_task_status
%w[finished provisioned].include?(state) ? status.to_s.downcase : "retry"
end
def my_zone
dialog_zone || source.my_zone || MiqServer.my_zone
end
def provision_priority
return 0 if service_resource.nil?
service_resource.provision_index
end
def sibling_sequence_run_now?
return true if miq_request_task.nil? || miq_request_task.miq_request_tasks.count == 1
return false if miq_request_task.miq_request_tasks.detect { |t| t.provision_priority < provision_priority && t.state != "finished" }
true
end
def group_sequence_run_now?
parent = miq_request_task
return true if parent.nil?
return false unless parent.group_sequence_run_now?
return false unless sibling_sequence_run_now?
true
end
def self.get_description(req_obj)
prov_source = req_obj.source
svc_target_name = req_obj.get_option(:target_name)
if svc_target_name.blank?
svc_target_name = prov_source.respond_to?(:get_source_name) ? prov_source.get_source_name : prov_source.name
end
if req_obj.kind_of?(ServiceTemplateProvisionRequest)
result = _("Provisioning Service [%{svc_target_name}] from [%{prov_source_name}]") % {:svc_target_name => svc_target_name, :prov_source_name => prov_source.name}
else
service_resource = prov_source
rsc_name = service_resource.name if service_resource.respond_to?(:name)
if rsc_name.blank?
req_template = service_resource.resource
rsc_name = req_template.respond_to?(:get_source_name) ? req_template.get_source_name : req_template.name
end
if svc_target_name.blank?
svc_tmp_id = req_obj.get_option(:src_id)
svc_tmp = ServiceTemplate.find_by(:id => svc_tmp_id)
svc_target_name = svc_tmp.name
end
result = case req_template
when ServiceTemplate
_("Provisioning Service [%{rsc_name}] for Service [%{svc_target_name}]") % {:rsc_name => rsc_name, :svc_target_name => svc_target_name}
when MiqProvisionRequestTemplate
_("Provisioning VM [%{rsc_name}] for Service [%{svc_target_name}]") % {:rsc_name => rsc_name, :svc_target_name => svc_target_name}
else
_("Provisioning [%{rsc_name}] for Service [%{svc_target_name}]") % {:rsc_name => rsc_name, :svc_target_name => svc_target_name}
end
end
result
end
def after_request_task_create
update_attribute(:description, get_description)
create_child_tasks
end
def create_child_tasks
parent_svc = Service.find_by(:id => options[:parent_service_id])
parent_name = parent_svc.nil? ? 'none' : "#{parent_svc.class.name}:#{parent_svc.id}"
_log.info("- creating service tasks for service <#{self.class.name}:#{id}> with parent service <#{parent_name}>")
tasks = source.create_tasks_for_service(self, parent_svc)
tasks.each { |t| miq_request_tasks << t }
_log.info("- created <#{tasks.length}> service tasks for service <#{self.class.name}:#{id}> with parent service <#{parent_name}>")
end
def do_request
if miq_request_tasks.size.zero?
message = "Service does not have children processes"
_log.info(message)
update_and_notify_parent(:state => 'provisioned', :message => message)
else
miq_request_tasks.each(&:deliver_queue)
message = "Service Provision started"
_log.info(message)
update_and_notify_parent(:message => message)
queue_post_provision
end
destination.update_lifecycle_state
end
def queue_post_provision
_log.info("Queuing post provision of #{self.class.name} id: #{id}, zone: #{my_zone}")
MiqQueue.put(
:class_name => self.class.name,
:instance_id => id,
:method_name => "do_post_provision",
:zone => my_zone,
:deliver_on => 1.minute.from_now.utc,
:tracking_label => tracking_label_id,
:miq_callback => {:class_name => self.class.name, :instance_id => id, :method_name => :execute_callback}
)
end
def do_post_provision
update_request_status
queue_post_provision unless state == "finished"
end
def deliver_to_automate(req_type = request_type, _zone = nil)
args = {
:object_type => self.class.name,
:object_id => id,
:namespace => "Service/Provisioning/StateMachines",
:class_name => "ServiceProvision_Template",
:instance_name => req_type,
:automate_message => "create",
:attrs => dialog_values.merge("request" => req_type)
}
# Automate entry point overrides from the resource_action
ra = resource_action
unless ra.nil?
if ra.configuration_script_payload
args[:namespace] = "Service/Provisioning/StateMachines"
args[:class_name] = "ServiceProvision_Template"
args[:instance_name] = "CatalogItemInitialization"
args[:automate_message] = nil
else
args[:namespace] = ra.ae_namespace if ra.ae_namespace.present?
args[:class_name] = ra.ae_class if ra.ae_class.present?
args[:instance_name] = ra.ae_instance if ra.ae_instance.present?
args[:automate_message] = ra.ae_message if ra.ae_message.present?
end
args[:attrs].merge!(ra.ae_attributes)
end
args[:attrs].merge!(MiqAeEngine.create_automation_attributes(destination.class.base_model.name => destination)) if destination.present?
args[:user_id] = get_user.id
args[:miq_group_id] = get_user.current_group.id
args[:tenant_id] = get_user.current_tenant.id
MiqQueue.put(
:class_name => 'MiqAeEngine',
:method_name => 'deliver',
:args => [args],
:role => 'automate',
:zone => options.fetch(:miq_zone, my_zone),
:tracking_label => tracking_label_id
)
update_and_notify_parent(:state => "pending", :status => "Ok", :message => "Automation Starting")
end
def resource_action
@resource_action ||= source.resource_actions.find_by(:action => 'Provision') if source.respond_to?(:resource_actions)
end
def service_resource
return nil if options[:service_resource_id].blank?
ServiceResource.find_by(:id => options[:service_resource_id])
end
def mark_pending_items_as_finished
miq_request.miq_request_tasks.each do |s|
if s.state == 'pending'
s.update_and_notify_parent(:state => "finished", :status => "Warn", :message => "Error in Request: #{miq_request.id}. Setting pending Task: #{id} to finished.") unless id == s.id
end
end
end
def before_ae_starts(_options)
reload
if state.to_s.downcase.in?(%w[pending queued])
_log.info("Executing #{request_class::TASK_DESCRIPTION} request: [#{description}]")
update_and_notify_parent(:state => "active", :status => "Ok", :message => "In Process")
end
end
def after_ae_delivery(ae_result)
_log.info("ae_result=#{ae_result.inspect}")
reload
return if ae_result == 'retry'
return if miq_request.state == 'finished'
if ae_result == 'ok'
update_and_notify_parent(:state => "finished", :status => "Ok", :message => display_message("#{request_class::TASK_DESCRIPTION} completed"))
else
mark_pending_items_as_finished
update_and_notify_parent(:state => "finished", :status => "Error", :message => display_message("#{request_class::TASK_DESCRIPTION} failed"))
end
end
def update_and_notify_parent(*args)
prev_state = state
super
try("task_#{state}") if prev_state != state
end
def task_finished
service = destination
return if service.nil?
service.raise_provisioned_event
service.update_lifecycle_state if service_template_source?
end
private
def service_template_source?
source_type == "ServiceTemplate"
end
def valid_states
super + ["provisioned"]
end
end