app/controllers/application_controller/miq_request_methods.rb
module ApplicationController::MiqRequestMethods
extend ActiveSupport::Concern
include RequestInfoHelper
included do
helper_method :dialog_partial_for_workflow
end
# AJAX driven routine to check for changes on the provision form
def prov_field_changed
assert_privileges("miq_request_edit")
if params[:tab_id]
@edit = session[:edit]
else
return unless load_edit("prov_edit__#{params[:id]}", "show_list")
end
if @edit.nil? || @edit.try(:[], :stamp_typ) # load tab for show screen
if params[:tab_id]
@options[:current_tab_key] = params[:tab_id].split('_')[0].to_sym
@options[:wf].refresh_field_values(@options)
end
prov_load_tab
else
if params[:tab_id]
@edit[:new][:current_tab_key] = params[:tab_id].split('_')[0].to_sym
@edit[:wf].refresh_field_values(@edit[:new])
end
refresh_divs = prov_get_form_vars # Get changed option, returns true if divs need refreshing
build_grid if refresh_divs
changed = (@edit[:new] != @edit[:current])
@record =
if @edit[:new][:src_configured_system_ids].present?
PhysicalServer.where(:id => @edit[:new][:src_configured_system_ids].first).first
else
MiqTemplate.where(:id => Array(@edit[:new][:src_vm_id]).first)
end
all_dialogs = @edit[:wf].get_all_dialogs rescue []
if @edit[:new] && @edit[:new][:addr_mode] && @edit[:new][:addr_mode][0] == "dhcp" && all_dialogs[:customize]
all_dialogs[:customize][:fields][:hostname]&.[]=(:read_only, true)
all_dialogs[:customize][:fields][:linux_host_name]&.[]=(:read_only, true)
all_dialogs[:customize][:fields][:subnet_mask][:read_only] = true
all_dialogs[:customize][:fields][:gateway][:read_only] = true
end
render :update do |page|
page << javascript_prologue
# Going thru all dialogs to see if model has set any of the dialog display to hide/ignore
all_dialogs.each do |dialog_name, dialog|
page << "miq_tabs_show_hide('#{dialog_name}_tab', #{dialog[:display] == :show});"
end
if refresh_divs
all_dialogs.each do |dialog_name, dialog|
if dialog[:display] == :show && dialog_name == @edit[:new][:current_tab_key]
page.replace_html(dialog_name, :partial => dialog_partial_for_workflow, :locals => {:wf => @edit[:wf], :dialog => dialog_name})
end
end
end
if @edit.fetch_path(:new, :schedule_type, 0) == "schedule"
page << "ManageIQ.calendar.calDateFrom = new Date(#{@timezone_offset});"
page << "miqBuildCalendar();"
end
if @edit.fetch_path(:new, :owner_email).blank?
page << javascript_hide("lookup_button_on")
page << javascript_show("lookup_button_off")
else
page << javascript_hide("lookup_button_off")
page << javascript_show("lookup_button_on")
end
if changed != session[:changed]
session[:changed] = changed
page << javascript_for_miq_button_visibility(changed)
end
page.replace("flash_msg_div", :partial => "layouts/flash_msg")
page << "miqScrollTop();" if @flash_array.present?
page << "miqSparkle(false);"
end
end
end
def pre_prov_continue
assert_privileges("miq_request_edit")
if params[:button] == "submit"
prov_edit
else
pre_prov
end
end
# Pre provisioning, select a template
def pre_prov
assert_privileges("miq_request_edit")
if params[:button] == "cancel"
flash_to_session(_("Add of new %{type} Request was cancelled by the user") % {:type => session[:edit][:prov_type]})
@explorer = session[:edit][:explorer] || false
@edit = session[:edit] = nil # Clear out session[:edit]
prov_request_cancel_submit_response
elsif params[:button] == "continue" # Template chosen, start vm provisioning
params[:button] = nil # Clear the incoming button
@edit = session[:edit] # Grab what we need from @edit
@explorer = @edit[:explorer]
if @edit[:wf].nil?
@src_vm_id = @edit[:src_vm_id] # Hang on to selected VM to populate prov
@edit = session[:edit] = nil
else
@workflow_exists = true
@src_vm_id = @edit[:wf].last_vm_id
validate_preprov
end
if @flash_array
javascript_flash
else
@redirect_controller = "miq_request"
@refresh_partial = "miq_request/prov_edit"
if @explorer
@_params[:org_controller] = "vm" # Set up for prov_edit
prov_edit
@sb[:action] = "pre_prov"
replace_right_cell
else
javascript_redirect(:controller => @redirect_controller,
:action => "prov_edit",
:src_vm_id => @src_vm_id,
:org_controller => "vm")
end
end
elsif params[:sort_choice]
@edit = session[:edit]
@edit[:vm_sortdir] = if @edit[:vm_sortcol] == params[:sort_choice] # if same column was selected
flip_sort_direction(@edit[:vm_sortdir])
else
'ASC'
end
@edit[:vm_sortcol] = params[:sort_choice]
render_updated_templates
elsif params[:sel_id]
@edit = session[:edit]
render :update do |page|
page << javascript_prologue
page << "$('#row_#{j_str(@edit[:src_vm_id])}').removeClass('selected');" if @edit[:src_vm_id]
page << "$('#row_#{j_str(params[:sel_id])}').addClass('selected');"
session[:changed] = true
page << javascript_for_miq_button_visibility(session[:changed])
@edit[:src_vm_id] = params[:sel_id].to_i
end
elsif params[:hide_deprecated_templates]
@edit = session[:edit]
@edit[:hide_deprecated_templates] = provisioning_is_cloud? ? params[:hide_deprecated_templates] == "true" : nil
render_updated_templates
else # First time in, build pre-provision screen
set_pre_prov_vars
end
end
alias instance_pre_prov pre_prov
alias vm_pre_prov pre_prov
def render_updated_templates
report_scopes = [:eligible_for_provisioning]
report_scopes.push([:filter_with_name, params[:search_text]])
report_scopes.push(:non_deprecated) if @edit[:hide_deprecated_templates]
options = options_for_provisioning(get_template_kls.to_s, report_scopes)
@report_data_additional_options = ApplicationController::ReportDataAdditionalOptions.from_options(options)
@report_data_additional_options.with_no_checkboxes(true)
render :update do |page|
page << javascript_prologue
page.replace("pre_prov_div", :partial => "miq_request/pre_prov")
page << "miqSparkle(false);"
end
end
def provisioning_is_cloud?
params[:template_klass] == 'cloud' || %w[auth_key_pair_cloud availability_zone cloud_tenant ems_cloud host_aggregate orchestration_stack vm_cloud].include?(params[:controller])
end
def provisioning_is_infra?
params[:template_klass] == 'infra' || %w[ems_cluster ems_infra host resource_pool storage vm_infra].include?(params[:controller])
end
def set_pre_prov_vars
@layout = "miq_request_vm"
@edit = {}
@edit[:explorer] = @explorer
@edit[:vm_sortdir] ||= "ASC"
@edit[:vm_sortcol] ||= "name"
@edit[:prov_type] = "VM Provision"
@edit[:hide_deprecated_templates] = true if provisioning_is_cloud?
unless %w[image_miq_request_new miq_template_miq_request_new].include?(params[:pressed])
path_to_report = ManageIQ::UI::Classic::Engine.root.join("product", "views", provisioning_report).to_s
@view = MiqReport.new(YAML.load(File.read(path_to_report)))
@view.db = get_template_kls.to_s
report_scopes = %i[eligible_for_provisioning non_deprecated]
options = options_for_provisioning(@view.db, report_scopes)
@report_data_additional_options = ApplicationController::ReportDataAdditionalOptions.from_options(options)
@report_data_additional_options.with_no_checkboxes(true)
@report_data_additional_options.in_a_form(true)
@report_data_additional_options.show_pagination(true)
@edit[:template_kls] = get_template_kls
end
session[:changed] = false # Turn off the submit button
@edit[:explorer] = true if @explorer
end
def get_template_kls
# when clone/migrate buttons are pressed from a sub list view,
# these buttons are only available on Infra side
return TemplateInfra if params[:prov_type]
if provisioning_is_cloud?
TemplateCloud
elsif provisioning_is_infra?
TemplateInfra
else
MiqTemplate
end
end
def prov_edit
assert_privileges("miq_request_edit")
if params[:button] == "cancel"
req = MiqRequest.find(session[:edit][:req_id]) if session[:edit] && session[:edit][:req_id]
flash_to_session(
if req && req.id
_("Edit of %{model} Request \"%{name}\" was cancelled by the user") %
{:model => session[:edit][:prov_type], :name => req.description}
else
_("Provision %{type} Request was cancelled by the user") % {:type => session[:edit][:prov_type]}
end
)
@explorer = session[:edit][:explorer] || false
@edit = session[:edit] = nil # Clear out session[:edit]
@breadcrumbs&.pop
prov_request_cancel_submit_response
elsif params[:button] == "submit" # Update or create the request from the workflow with the new options
prov_req_submit
else # First time in, build provision request screen
@layout = layout_from_tab_name(params[:org_controller])
if params[:commit] == "Upload" && session.fetch_path(:edit, :new, :sysprep_enabled, 1) == "Sysprep Answer File"
upload_sysprep_file
@tabactive = "customize"
elsif params[:commit] == 'Upload Script'
upload_user_script
@tabactive = "customize"
elsif params[:commit] == "Clear Script"
clear_user_script
@tabactive = "customize"
else
if params[:req_id]
prov_set_form_vars(MiqRequest.find(params[:req_id])) # Set vars from existing request
session[:changed] = false # Turn off the submit button
else
prov_set_form_vars # Set default vars
session[:changed] = true # Turn on the submit button
end
@edit[:explorer] = true if @explorer
@tabactive = @edit[:new][:current_tab_key]
end
title = if params[:prov_type] == "clone_to_template"
_('Publish Virtual Machine')
elsif params[:req_id]
_("Edit %{type}") % {:type => @edit[:prov_type]}
else
_("Add %{type}") % {:type => @edit[:prov_type]}
end
drop_breadcrumb(:name => title, :url => "/vm/provision")
@in_a_form = true
# render :action=>"show"
end
end
# get the sort column that was clicked on, else use the current one
def sort_ds_grid
assert_privileges("miq_request_edit")
return unless load_edit("prov_edit__#{params[:id]}", "show_list")
field = %w[miq_template vm service_template].include?(@edit[:org_controller]) ? :placement_ds_name : :attached_ds
sort_grid('ds', @edit[:wf].get_field(field, :environment)[:values])
end
# get the sort column that was clicked on, else use the current one
def sort_vm_grid
assert_privileges("miq_request_edit")
return unless load_edit("prov_edit__#{params[:id]}", "show_list")
sort_grid('vm', @edit[:wf].get_field(:src_vm_id, :service)[:values])
end
# get the sort column that was clicked on, else use the current one
def sort_host_grid
assert_privileges("miq_request_edit")
return unless load_edit("prov_edit__#{params[:id]}", "show_list")
sort_grid('host', @edit[:wf].get_field(:placement_host_name, :environment)[:values])
end
# get the sort column that was clicked on, else use the current one
def sort_configured_system_grid
assert_privileges("miq_request_edit")
return unless load_edit("prov_edit__#{params[:id]}", "show_list")
sort_grid('configured_system', @edit[:wf].get_field(:src_configured_system_ids, :service)[:values])
end
# get the sort column that was clicked on, else use the current one
def sort_pxe_img_grid
assert_privileges("miq_request_edit")
return unless load_edit("prov_edit__#{params[:id]}", "show_list")
sort_grid('pxe_img', @edit[:wf].get_field(:pxe_image_id, :service)[:values])
end
# get the sort column that was clicked on, else use the current one
def sort_iso_img_grid
assert_privileges("miq_request_edit")
return unless load_edit("prov_edit__#{params[:id]}", "show_list")
sort_grid('iso_img', @edit[:wf].get_field(:iso_image_id, :service)[:values])
end
def sort_windows_image_grid
assert_privileges("miq_request_edit")
return unless load_edit("prov_edit__#{params[:id]}", "show_list")
sort_grid('windows_image', @edit[:wf].get_field(:windows_image_id, :service)[:values])
end
# get the sort column that was clicked on, else use the current one
def sort_vc_grid
assert_privileges("miq_request_edit")
@edit = session[:edit]
sort_grid('vc', @edit[:wf].get_field(:sysprep_custom_spec, :customize)[:values])
end
# get the sort column that was clicked on, else use the current one
def sort_template_grid
assert_privileges("miq_request_edit")
@edit = session[:edit]
sort_grid('template', @edit[:wf].get_field(:customization_template_id, :customize)[:values])
end
private ############################
def _build_whatever_grid(what, list, headers, sort_order, sort_by, integer_fields = [], state = @edit)
state["#{what}_headers".to_sym] = headers
state["#{what}_columns".to_sym] = headers.keys
state["#{what}_sortcol".to_sym] = sort_by
state["#{what}_sortdir".to_sym] = sort_order
post_sort_method = integer_fields.include?(sort_by) ? :to_i : :downcase
sorted = list.sort_by { |item| item.deep_send(sort_by).to_s.send(post_sort_method) }.uniq
sort_order == "ASC" ? sorted : sorted.reverse
end
def build_configured_system_grid(configured_systems, sort_order = nil, sort_by = nil)
sort_by ||= "hostname"
sort_order ||= "ASC"
headers = if @edit[:wf].kind_of?(PhysicalServerProvisionWorkflow)
{
"name" => _("Server Name")
}
else
{
"hostname" => _("Hostname"),
"configuration_location_name" => _("Configuration Location"),
"configuration_organization_name" => _("Configuration Organization"),
"operating_system_flavor_name" => _("Operating System"),
"provider_name" => _("Provider"),
}
end
@configured_systems = _build_whatever_grid('configured_system', configured_systems, headers, sort_order, sort_by)
end
def build_pxe_img_grid(pxe_imgs, sort_order = nil, sort_by = nil)
sort_by ||= "name"
sort_order ||= "ASC"
headers = {
"name" => _("Name"),
"description" => _("Description"),
}
@pxe_imgs = _build_whatever_grid('pxe_img', pxe_imgs, headers, sort_order, sort_by)
end
def build_iso_img_grid(iso_imgs, sort_order = nil, sort_by = nil)
sort_by ||= "name"
sort_order ||= "ASC"
headers = {
"name" => _("Name"),
}
@iso_imgs = _build_whatever_grid('iso_img', iso_imgs, headers, sort_order, sort_by)
end
def build_windows_image_grid(windows_images, sort_order = nil, sort_by = nil)
sort_by ||= "name"
sort_order ||= "ASC"
headers = {
"name" => _("Name"),
"description" => _("Description"),
}
@windows_images = _build_whatever_grid('windows_image', windows_images, headers, sort_order, sort_by)
end
def build_ds_grid(datastores, sort_order = nil, sort_by = nil)
sort_by ||= "free_space"
sort_order ||= "DESC"
headers = {
"name" => _("Name"),
"free_space" => _("Free Space"),
"total_space" => _("Total Space"),
"storage_clusters" => _("Storage Clusters"),
}
integer_fields = %w[free_space total_space]
# :datastores, not :dss
@datastores = _build_whatever_grid('ds', datastores, headers, sort_order, sort_by, integer_fields)
end
def build_vc_grid(vcs, sort_order = nil, sort_by = nil)
sort_by ||= "name"
sort_order ||= "DESC"
headers = {
:name => _("Name"),
:description => _("Description"),
:last_update_time => _("Last Updated"),
}
integer_fields = %w[last_update_time]
@vcs = _build_whatever_grid('vc', vcs, headers, sort_order, sort_by, integer_fields)
end
def build_template_grid(templates, sort_order = nil, sort_by = nil)
sort_by ||= "name"
sort_order ||= "DESC"
headers = {
:name => _("Name"),
:description => _("Description"),
:last_update_time => _("Last Updated"),
}
integer_fields = %w[last_update_time]
@templates = _build_whatever_grid('template', templates, headers, sort_order, sort_by, integer_fields)
end
def build_vm_grid(vms, sort_order = nil, sort_by = nil, filter_by = nil)
sort_by ||= "name"
sort_order ||= "ASC"
filter_by ||= ->(_) { true }
headers = {
"name" => _("Name"),
"operating_system.product_name" => _("Operating System"),
"platform" => _("Platform"),
"cpu_total_cores" => _("CPUs"),
"mem_cpu" => _("Memory"),
"allocated_disk_storage" => _("Disk Size"),
"ext_management_system.name" => _("Provider"),
"v_total_snapshots" => _("Snapshots"),
}
headers["deprecated"] = _("Deprecated") if request.parameters[:controller] == "vm_cloud"
# add tenant column header to cloud workflows only
headers["cloud_tenant"] = _("Tenant") if vms.any? { |vm| vm.respond_to?(:cloud_tenant) }
# add snapshot/image column header to cloud workflows only, since they're
# currently the only ones that support the field.
headers["image?"] = _("Type") if vms.any? { |vm| vm.respond_to?(:image?) }
integer_fields = %w[allocated_disk_storage mem_cpu cpu_total_cores v_total_snapshots]
filtered_vms = vms.select { |x| filter_by.call(x) }
@vms = _build_whatever_grid('vm', filtered_vms, headers, sort_order, sort_by, integer_fields)
end
def build_host_grid(hosts, sort_order = nil, sort_by = nil)
sort_by ||= "name"
sort_order ||= "ASC"
# need to set options from @edit/@option based upon calling screen: show/edit
options = @edit || @options
# editable grid for vm/migrate prov screens
headers = { "name" => _("Name"),
"v_total_vms" => _("Total VMs"),
"vmm_product" => _("Platform"),
"vmm_version" => _("Version"),
"state" => _("State"),
"maintenance" => _("Maintenance") }
integer_fields = %w[v_total_vms]
@hosts = _build_whatever_grid('host', hosts, headers, sort_order, sort_by, integer_fields, options)
end
def build_grid
case @edit[:wf]
when MiqProvisionConfiguredSystemWorkflow
build_dialog_page_miq_provision_configured_system_workflow
when MiqProvisionVirtWorkflow
if @edit[:new][:current_tab_key] == :service
if @edit[:new][:st_prov_type]
build_vm_grid(@edit[:wf].get_field(:src_vm_id, :service)[:values], @edit[:vm_sortdir], @edit[:vm_sortcol], build_template_filter)
else
@vm = VmOrTemplate.find(@edit[:new][:src_vm_id] && @edit[:new][:src_vm_id][0])
end
if @edit[:wf].supports_pxe?
build_pxe_img_grid(@edit[:wf].send("allowed_images"), @edit[:pxe_img_sortdir], @edit[:pxe_img_sortcol])
end
if @edit[:wf].supports_iso?
build_iso_img_grid(@edit[:wf].send("allowed_iso_images"), @edit[:iso_img_sortdir], @edit[:iso_img_sortcol])
end
elsif @edit[:new][:current_tab_key] == :environment
build_host_grid(@edit[:wf].get_field(:placement_host_name, :environment)[:values], @edit[:host_sortdir], @edit[:host_sortcol]) if @edit[:wf].get_field(:placement_host_name, :environment).present?
build_ds_grid(@edit[:wf].get_field(:placement_ds_name, :environment)[:values], @edit[:ds_sortdir], @edit[:ds_sortcol]) if @edit[:wf].get_field(:placement_ds_name, :environment).present?
elsif @edit[:new][:current_tab_key] == :customize
@edit[:template_sortdir] ||= "ASC"
@edit[:template_sortcol] ||= "name"
if @edit[:wf].supports_customization_template?
build_template_grid(@edit[:wf].send("allowed_customization_templates"), @edit[:template_sortdir], @edit[:template_sortcol])
else
build_vc_grid(@edit[:wf].get_field(:sysprep_custom_spec, :customize)[:values], @edit[:vc_sortdir], @edit[:vc_sortcol])
end
@sb[:vm_os] = VmOrTemplate.find(@edit.fetch_path(:new, :src_vm_id, 0)).platform if @edit.fetch_path(:new, :src_vm_id, 0)
elsif @edit[:new][:current_tab_key] == :purpose
build_tags_for_provisioning(@edit[:wf], @edit[:new][:vm_tags], true)
end
when VmMigrateWorkflow
if @edit[:new][:current_tab_key] == :environment
build_host_grid(@edit[:wf].get_field(:placement_host_name, :environment)[:values], @edit[:host_sortdir], @edit[:host_sortcol]) if @edit[:wf].get_field(:placement_host_name, :environment).present?
build_ds_grid(@edit[:wf].get_field(:placement_ds_name, :environment)[:values], @edit[:ds_sortdir], @edit[:ds_sortcol]) if @edit[:wf].get_field(:placement_ds_name, :environment).present?
end
else
if @edit[:new][:current_tab_key] == :service
build_host_grid(@edit[:wf].get_field(:src_host_ids, :service)[:values], @edit[:host_sortdir], @edit[:host_sortcol])
build_pxe_img_grid(@edit[:wf].get_field(:pxe_image_id, :service)[:values], @edit[:pxe_img_sortdir], @edit[:pxe_img_sortcol])
build_iso_img_grid(@edit[:wf].get_field(:iso_image_id, :service)[:values], @edit[:iso_img_sortdir], @edit[:iso_img_sortcol]) if @edit[:wf].supports_iso?
elsif @edit[:new][:current_tab_key] == :purpose
build_tags_for_provisioning(@edit[:wf], @edit.fetch_path(:new, tag_symbol_for_workflow), true)
elsif @edit[:new][:current_tab_key] == :environment
build_ds_grid(@edit[:wf].get_field(:attached_ds, :environment)[:values], @edit[:ds_sortdir], @edit[:ds_sortcol])
elsif @edit[:new][:current_tab_key] == :customize
build_template_grid(@edit[:wf].get_field(:customization_template_id, :customize)[:values], @edit[:template_sortdir], @edit[:template_sortcol])
end
end
end
def build_dialog_page_miq_provision_configured_system_workflow
case @edit[:new][:current_tab_key]
when :purpose
build_tags_for_provisioning(@edit[:wf], @edit.fetch_path(:new, tag_symbol_for_workflow), true)
when :service
build_configured_system_grid(@edit[:wf].get_field(:src_configured_system_ids, :service)[:values], @edit[:configured_system_sortdir], @edit[:configured_system_sortcol])
end
end
def dialog_partial_for_workflow
workflow = @edit.try(:[], :wf) && !@edit[:stamp_typ] ? @edit[:wf] : @options[:wf]
case workflow
when MiqProvisionVirtWorkflow then "shared/views/prov_dialog"
when ManageIQ::Providers::Foreman::ConfigurationManager::ProvisionWorkflow then "prov_configured_system_foreman_dialog"
when VmMigrateWorkflow then "prov_vm_migrate_dialog"
when PhysicalServerProvisionWorkflow then "prov_physical_server_dialog"
end
end
def layout_from_tab_name(tab_name)
case tab_name
when "ae" then "miq_request_ae"
when "host" then "miq_request_host"
else "miq_request_vm" # Includes "vm"
end
end
def sort_grid(what, values)
sortdir = "#{what}_sortdir".to_sym
sortcol = "#{what}_sortcol".to_sym
unless params[:sort_choice].nil?
@edit[sortdir] = if @edit[sortcol] == params[:sort_choice] # if same column was selected
flip_sort_direction(@edit[sortdir])
else
"ASC"
end
@edit[sortcol] = params[:sort_choice]
end
send("build_#{what}_grid", values, @edit[sortdir], @edit[sortcol])
spec = params[:spec] == 'true'
render :json => {:initialData => prov_grid_component( params[:field].to_sym, params[:field_id].to_sym, spec, "data")}
end
def tag_symbol_for_workflow
(@edit || @options)[:wf].try(:tag_symbol) || :vm_tags
end
# This doesn't run validations, it creates flash messages for errors found in MiqRequestWorkflow#validate
def validate_fields
@edit[:wf].get_dialog_order.each do |d|
@edit[:wf].get_all_fields(d, false).each_value do |field|
if field[:error].present?
@error_div ||= d.to_s
add_flash(field[:error], :error)
end
end
end
end
def validate_preprov
@edit[:wf].get_dialog_order.each do |d|
@edit[:wf].get_all_fields(d, false).each_value do |field|
@edit[:wf].validate(@edit[:new])
unless field[:error].nil?
@error_div ||= d.to_s
add_flash(field[:error], :error)
end
end
end
end
def prov_request_cancel_submit_response
if @explorer
@sb[:action] = nil
replace_right_cell
elsif @breadcrumbs && (@breadcrumbs.empty? || last_screen_url == "/vm/show_list")
javascript_redirect(:action => "show_list", :controller => "vm")
else
javascript_redirect(last_screen_url)
end
end
def prov_req_submit
id = session[:edit][:req_id] || "new"
return unless load_edit("prov_edit__#{id}", "show_list")
@edit[:new][:schedule_time] = @edit[:new][:schedule_time].in_time_zone("Etc/UTC") if @edit[:new][:schedule_time]
begin
request = @edit[:wf].make_request(@edit[:req_id], @edit[:new])
rescue StandardError => bang
request = false
add_flash(bang.message, :error)
end
if request
@breadcrumbs&.pop
org_controller = @edit[:org_controller]
title = case org_controller
when "vm" then _("VMs")
when "miq_template" then _("Templates")
else _("Hosts")
end
flash_message = if @edit[:req_id].nil?
_("%{typ} Request was Submitted, you will be notified when your %{title} are ready")
else
_("%{typ} Request was re-submitted, you will be notified when your %{title} are ready")
end
flash_message = flash_message % {:typ => @edit[:prov_type], :title => title}
@explorer = @edit[:explorer] || false
@sb[:action] = @edit = session[:edit] = nil
add_flash(flash_message)
if role_allows?(:feature => "miq_request_show_list", :any => true)
flash_to_session
javascript_redirect(:controller => 'miq_request',
:action => 'show_list',
:typ => org_controller)
else
prov_request_cancel_submit_response
end
else
validate_fields
@edit[:new][:current_tab_key] = @error_div.split('_')[0].to_sym if @error_div
@edit[:wf].refresh_field_values(@edit[:new])
build_grid
render :update do |page|
page << javascript_prologue
page.replace("prov_wf_div", :partial => "/miq_request/prov_wf") if @error_div
page.replace("flash_msg_div", :partial => "layouts/flash_msg")
page << "miqScrollTop();" if @flash_array.present?
end
end
end
# Get variables from provisioning form
def prov_get_form_vars
if params[:ids_checked] # User checked/unchecked a tree node
ids = params[:ids_checked]
# for some reason if tree is not expanded clicking on radiobuttons this.getAllChecked() sends up extra blanks
@edit.store_path(:new, tag_symbol_for_workflow, ids.select(&:present?).collect(&:to_i))
end
id = params[:ou_id].gsub(/_-_/, ",") if params[:ou_id]
@edit[:new][:ldap_ous] = id.match(/(.*)\,(.*)/)[1..2] if id # ou selected in a tree
copy_params_if_present(@edit[:new], params, %i[start_hour start_min])
@edit[:new][:start_date] = params[:miq_date_1] if params[:miq_date_1]
@edit[:new][:schedule_time] = Time.zone.parse("#{@edit[:new][:start_date]} #{@edit[:new][:start_hour]}:#{@edit[:new][:start_min]}")
params.each do |key, _value|
next unless key.include?("__")
d, f = key.split("__") # Parse dialog and field names from the parameter key
field = @edit[:wf].get_field(f.to_sym, d.to_sym) # Get the field hash
val =
case field[:data_type] # Get the value, convert to integer or boolean if needed
when :integer
params[key].to_i
when :boolean
params[key].to_s == "true"
else
params[key]
end
if field[:values] # If a choice was made
if field[:values].kind_of?(Hash)
# set an array of selected ids for security groups field
if f == "security_groups"
if params[key] == ""
@edit[:new][f.to_sym] = [nil]
else
@edit[:new][f.to_sym] = []
params[key].split(",").each { |v| @edit[:new][f.to_sym].push(v.to_i) }
end
elsif f == "cloud_volumes"
if params[key] == ""
@edit[:new][f.to_sym] = [nil]
else
@edit[:new][f.to_sym] = []
params[key].split(",").each { |v| @edit[:new][f.to_sym].push(v) }
end
else
@edit[:new][f.to_sym] = [val, field[:values][val]] # Save [value, description]
end
else
field[:values].each do |v|
evm_object_class = v.try(:evm_object_class)
if evm_object_class == :Storage
if %w[miq_template service_template vm].include?(@edit[:org_controller])
if params[key] == "__DS__NONE__" # Added this to deselect datastore in grid
@edit[:new][f.to_sym] = [nil, nil] # Save [value, description]
elsif v.id.to_i == val.to_i
@edit[:new][f.to_sym] = [val, v.name] # Save [value, description]
end
elsif params[key] == "__DS__NONE__" # Added this to deselect datastore in grid
@edit[:new][f.to_sym] = [] # Save [value, description]
elsif v.id.to_i == val.to_i
if @edit[:new][f.to_sym].include?(val)
@edit[:new][f.to_sym].delete_if { |x| x == val }
else
@edit[:new][f.to_sym].push(val) # Save [value, description]
end
end
elsif evm_object_class == :Host
if params[key] == "__HOST__NONE__" # Added this to deselect datastore in grid
@edit[:new][f.to_sym] = [nil, nil] # Save [value, description]
elsif v.id.to_i == val.to_i
@edit[:new][f.to_sym] = [val, v.name] # Save [value, description]
end
elsif evm_object_class == :Vm
if params[key] == "__VM__NONE__" # Added this to deselect datastore in grid
@edit[:new][f.to_sym] = [nil, nil] # Save [value, description]
elsif v.id.to_i == val.to_i
@edit[:new][f.to_sym] = [val, v.name] # Save [value, description]
end
elsif evm_object_class == :PxeImage || evm_object_class == :WindowsImage
if params[key] == "__PXE_IMG__NONE__" # Added this to deselect datastore in grid
@edit[:new][f.to_sym] = [nil, nil] # Save [value, description]
elsif v.id == val
@edit[:new][f.to_sym] = [val, v.name] # Save [value, description]
end
elsif evm_object_class == :IsoImage
if params[key] == "__ISO_IMG__NONE__" # Added this to deselect datastore in grid
@edit[:new][f.to_sym] = [nil, nil] # Save [value, description]
elsif v.id == val
@edit[:new][f.to_sym] = [val, v.name] # Save [value, description]
end
elsif evm_object_class == :CustomizationTemplate
if params[key] == "__TEMPLATE__NONE__" # Added this to deselect datastore in grid
@edit[:new][f.to_sym] = [nil, nil] # Save [value, description]
elsif v.id.to_i == val.to_i
@edit[:new][f.to_sym] = [val, v.name] # Save [value, description]
end
elsif evm_object_class == :CustomizationSpec
if params[key] == "__VC__NONE__" # Added this to deselect custom_spec in grid
@edit[:new][f.to_sym] = [nil, nil] # Save [value, description]
elsif v.id.to_i == val.to_i
@edit[:new][f.to_sym] = [val, v.name] # Save [value, description]
end
elsif v[1].to_i == val.to_i
@edit[:new][f.to_sym] = [val, v[0]] # Save [value, description]
end
end
end
begin
@edit[:wf].refresh_field_values(@edit[:new])
rescue StandardError => bang
add_flash(bang.message, :error)
@edit[:new][f.to_sym] = val # Save value
# No need to refresh dialog divs
return false
else
return true
end
else
@edit[:new][f.to_sym] = val # Save value
# No need to refresh dialog divs
return false
end
end
end
def prov_set_show_vars
@showtype = "main"
@options = @miq_request.get_options # Get the provision options from the request record
@options[:org_controller] = "vm"
if @options[:schedule_time]
@options[:schedule_time] = format_timezone(@options[:schedule_time], Time.zone, "raw")
@options[:start_date] = "#{@options[:schedule_time].month}/#{@options[:schedule_time].day}/#{@options[:schedule_time].year}" # Set the start date
@options[:start_hour] = @options[:schedule_time].hour.to_s
@options[:start_min] = @options[:schedule_time].min.to_s
end
drop_breadcrumb(:name => @miq_request.description.to_s.split(' submitted')[0], :url => "/miq_request/show/#{@miq_request.id}")
if @miq_request.workflow_class
options = {}
begin
options[:wf] = @miq_request.workflow(@options)
rescue MiqException::MiqVmError => bang
@no_wf_msg = _("Cannot create Request Info, error: %{error_message}") % {:error_message => bang.message}
end
if options[:wf]
options[:wf].init_from_dialog(@options) # Create a new provision workflow for this edit session
# setting active tab to first visible tab
options[:wf].get_dialog_order.each do |d|
if options[:wf].get_dialog(d)[:display] == :show
@options[:current_tab_key] = d
break
end
end
@options[tag_symbol_for_workflow] ||= [] # Initialize if came back nil from record
unless ["VmMigrateRequest"].include?(@miq_request.resource_type)
svm = VmOrTemplate.where(:id => @options[:src_vm_id][0]).first if @options[:src_vm_id] && @options[:src_vm_id][0]
@sb[:vm_os] = svm.platform if svm
end
@options[:wf] = options[:wf]
end
elsif @miq_request.resource_type == 'ServiceRetireRequest'
@view, @pages = nil
if (service_id = @miq_request.options[:src_ids].first) && (service = Service.find_by(:id => service_id)) && Rbac.filtered_object(service)
@view, @pages = get_view(Vm, :parent => service, :view_suffix => 'OrchestrationStackRetireRequest')
end
elsif %w[PhysicalServerProvisionRequest PhysicalServerFirmwareUpdateRequest].include?(@miq_request.resource_type)
@selected_ids = @miq_request.options[:src_ids]
@view, @pages = get_view(PhysicalServer, :view_suffix => 'PhysicalServerProvisionRequest')
else
@options = @miq_request.options
@options[:memory], @options[:mem_typ] = reconfigure_calculations(@options[:vm_memory][0]) if @options[:vm_memory]
@force_no_grid_xml = true
@selected_ids = @miq_request.options[:src_ids]
@view, @pages = get_view(Vm, :view_suffix => "VmReconfigureRequest")
# FIXME: use selected_ids passed through get_view to replace all of
# gtl_selected_records after Gaprindashvili
end
@user = User.lookup_by_userid(@miq_request.stamped_by)
end
# Set form variables for provision request
def prov_set_form_vars(req = nil)
@edit ||= {}
session[:prov_options] = @options = nil # Clearing out options that were set on show screen
@edit[:req_id] = req.try(:id) # Save existing request record id, if passed in
@edit[:key] = "prov_edit__#{@edit[:req_id] || "new"}"
options = req.try(:get_options) || {} # Use existing request options, if passed in
@edit[:new] = options unless @workflow_exists
# request originated from controller
@edit[:org_controller] = params[:org_controller] || "vm"
@edit[:wf], pre_prov_values = workflow_instance_from_vars(req)
if @edit[:wf]
@edit[:wf].get_dialog_order.each do |d|
if @edit[:wf].get_dialog(d)[:display] == :show
@edit[:new][:current_tab_key] = d
break
end
end
@edit[:buttons] = @edit[:wf].get_buttons
@edit[:wf].init_from_dialog(@edit[:new]) # Create a new provision workflow for this edit session
@timezone_offset = get_timezone_offset
if @edit[:new][:schedule_time]
@edit[:new][:schedule_time] = format_timezone(@edit[:new][:schedule_time], Time.zone, "raw")
@edit[:new][:start_date] = "#{@edit[:new][:schedule_time].month}/#{@edit[:new][:schedule_time].day}/#{@edit[:new][:schedule_time].year}" # Set the start date
if params[:req_id]
@edit[:new][:start_hour] = @edit[:new][:schedule_time].hour.to_s
@edit[:new][:start_min] = @edit[:new][:schedule_time].min.to_s
else
@edit[:new][:start_hour] = "00"
@edit[:new][:start_min] = "00"
end
end
@edit[:new][:src_vm_id] = [nil, nil] unless @edit[:new][:src_vm_id]
# Check that the provisioning template exists
if @edit[:wf].request_type == 'template' && @edit[:new][:src_vm_id][0].present?
@edit[:new][:src_vm_id][0] = nil unless MiqTemplate.exists?(@edit[:new][:src_vm_id][0])
end
@edit[:new][tag_symbol_for_workflow] ||= [] # Initialize for new record
@edit[:current] ||= {}
@edit[:current] = copy_hash(@edit[:new])
# Give the model a change to modify the dialog based on the default settings
# common grids
@edit[:wf].refresh_field_values(@edit[:new])
if pre_prov_values
@edit[:new] = @edit[:new].delete_nils
@edit[:new] = @edit[:new].merge(pre_prov_values.reject { |k| @edit[:new].key?(k) })
end
if @edit[:wf].kind_of?(ManageIQ::Providers::Foreman::ConfigurationManager::ProvisionWorkflow) ||
@edit[:wf].kind_of?(PhysicalServerProvisionWorkflow)
# BD TODO
else
@edit[:ds_sortdir] ||= "DESC"
@edit[:ds_sortcol] ||= "free_space"
@edit[:host_sortdir] ||= "ASC"
@edit[:host_sortcol] ||= "name"
build_host_grid(@edit[:wf].send("allowed_hosts"), @edit[:host_sortdir], @edit[:host_sortcol])
build_ds_grid(@edit[:wf].send("allowed_storages"), @edit[:ds_sortdir], @edit[:ds_sortcol])
if @edit[:wf].kind_of?(MiqProvisionWorkflow)
@edit[:vm_sortdir] ||= "ASC"
@edit[:vm_sortcol] ||= "name"
@edit[:vc_sortdir] ||= "ASC"
@edit[:vc_sortcol] ||= "name"
@edit[:template_sortdir] ||= "ASC"
@edit[:template_sortcol] ||= "name"
build_vm_grid(@edit[:wf].send("allowed_templates"), @edit[:vm_sortdir], @edit[:vm_sortcol], build_template_filter)
if @edit[:wf].supports_pxe?
build_pxe_img_grid(@edit[:wf].send("allowed_images"), @edit[:pxe_img_sortdir], @edit[:pxe_img_sortcol])
build_host_grid(@edit[:wf].send("allowed_hosts"), @edit[:host_sortdir], @edit[:host_sortcol])
build_template_grid(@edit[:wf].send("allowed_customization_templates"), @edit[:template_sortdir], @edit[:template_sortcol])
elsif @edit[:wf].supports_iso?
build_iso_img_grid(@edit[:wf].send("allowed_iso_images"), @edit[:iso_img_sortdir], @edit[:iso_img_sortcol])
else
build_vc_grid(@edit[:wf].send("allowed_customization_specs"), @edit[:vc_sortdir], @edit[:vc_sortcol])
end
elsif @edit[:wf].kind_of?(VmMigrateWorkflow)
else
@edit[:template_sortdir] ||= "ASC"
@edit[:template_sortcol] ||= "name"
build_pxe_img_grid(@edit[:wf].send("allowed_images"), @edit[:pxe_img_sortdir], @edit[:pxe_img_sortcol])
build_iso_img_grid(@edit[:wf].send("allowed_iso_images"), @edit[:iso_img_sortdir], @edit[:iso_img_sortcol])
build_host_grid(@edit[:wf].send("allowed_hosts"), @edit[:host_sortdir], @edit[:host_sortcol])
build_template_grid(@edit[:wf].send("allowed_customization_templates"), @edit[:template_sortdir], @edit[:template_sortcol])
end
end
else
@edit[:current] ||= {}
@edit[:current] = copy_hash(@edit[:new])
end
end
def workflow_instance_from_vars(req)
options = {}
pre_prov_values = nil
if %w[miq_template service_template vm].include?(@edit[:org_controller])
if params[:prov_type] && !req # only do this new requests
@edit[:prov_id] = params[:prov_id]
wf_type =
if params[:prov_type] == "migrate"
@edit[:prov_type] = "VM Migrate"
@edit[:new][:src_ids] = params[:prov_id]
VmMigrateWorkflow
else
@edit[:prov_type] = "VM Provision"
if @edit[:org_controller] == "service_template"
options[:service_template_request] = true
ManageIQ::Providers::Vmware::InfraManager::ProvisionWorkflow
else
options[:src_vm_id] = @edit[:prov_id]
options[:request_type] = params[:prov_type].to_sym
MiqProvisionWorkflow.class_for_source(options[:src_vm_id])
end
end
else
options[:initial_pass] = true unless req
options[:service_template_request] = true if @edit[:org_controller] == "service_template"
options[:use_pre_dialog] = false if @workflow_exists
# setting class to ManageIQ::Providers::Vmware::InfraManager::ProvisionWorkflow for requests where src_vm_id is
# not already set, i.e catalogitem
src_vm_id =
if @edit.fetch_path(:new, :src_vm_id, 0).present?
@edit[:new][:src_vm_id]
elsif @src_vm_id || params[:src_vm_id] # Set vm id if pre-prov chose one
options[:src_vm_id] = [@src_vm_id || params[:src_vm_id].to_i]
end
src_vm = VmOrTemplate.where(:id => src_vm_id).first
wf_type =
if req.try(:type) == "VmMigrateRequest"
VmMigrateWorkflow
elsif src_vm
MiqProvisionWorkflow.class_for_source(src_vm)
elsif @edit[:st_prov_type]
MiqProvisionWorkflow.class_for_platform(@edit[:st_prov_type])
elsif @edit[:new][:st_prov_type]
MiqProvisionWorkflow.class_for_platform(@edit[:new][:st_prov_type])
end
pre_prov_values = copy_hash(@edit[:wf].values) if @edit[:wf]
@edit[:prov_type] = req.try(:request_type) && req.request_type_display
@edit[:prov_type] ||= req.try(:type) == "VmMigrateRequest" ? "VM Migrate" : "VM Provision"
end
elsif @edit[:org_controller] == "configured_system"
@edit[:prov_type] = "ConfiguredSystem"
@edit[:new][:src_configured_system_ids] = params[:prov_id].kind_of?(Array) ? params[:prov_id] : [params[:prov_id]]
wf_type = ManageIQ::Providers::Foreman::ConfigurationManager::ProvisionWorkflow
elsif @edit[:org_controller] == "physical_server"
@edit[:prov_type] = "PhysicalServer"
@edit[:new][:src_configured_system_ids] = params[:prov_id].kind_of?(Array) ? params[:prov_id] : [params[:prov_id]]
wf_type = PhysicalServerProvisionWorkflow
end
[wf_type.new(@edit[:new], current_user, options), pre_prov_values] # Return the new workflow and any pre_prov_values
rescue StandardError => bang
# only add this message if showing a list of Catalog items, show screen already handles this
@no_wf_msg = _("Cannot create Request Info, error: %{error_message}") % {:error_message => bang.message}
_log.log_backtrace(bang)
nil
end
def build_tags_for_provisioning(wf, vm_tags, _edit_mode)
# for some reason @tags is set in wf, and it is changed by map bellow which causes bugs
wf.instance_variable_set(:@tags, nil)
tags = wf.allowed_tags.map do |cat|
{
:values => cat[:children].map do |tag|
{:id => tag.first, :description => tag.second[:description]}
end,
:id => cat[:name],
:description => cat[:description],
:singleValue => cat[:single_value],
}
end
assignments = Classification.find(vm_tags)
assigned_tags = assignments.map do |tag|
{
:description => tag.parent.description,
:id => tag.parent.name,
:singleValue => tag.parent.single_value,
:values => ->(arr, single_value) { single_value ? [arr.last] : arr }.call(
assignments.select do |assignment|
assignment.parent.name == tag.parent.name
end,
tag.parent.single_value
).map do |assignment|
{ :description => assignment.description, :id => assignment.id }
end
}
end.uniq
@tags = {:tags => tags, :assignedTags => assigned_tags, :affectedItems => []}
end
def build_template_filter
return ->(x) { !x.deprecated } if @edit[:hide_deprecated_templates]
->(_) { true } # do not apply a filter
end
def options_for_provisioning(db, report_scopes)
{
:model => db,
:named_scope => report_scopes,
:report_name => provisioning_report,
:custom_action => {
:url => "/miq_request/pre_prov/?sel_id=",
:type => 'provisioning'
}
}
end
def provisioning_report
if provisioning_is_cloud?
'ProvisionCloudTemplates.yaml'
elsif provisioning_is_infra?
'ProvisionInfraTemplates.yaml'
end
end
end