app/controllers/storage_controller.rb
class StorageController < ApplicationController
include StorageD
include StoragePod
include Mixins::GenericSessionMixin
include Mixins::GenericShowMixin
include Mixins::MoreShowActions
include Mixins::ExplorerPresenterMixin
include Mixins::FindRecord
include Mixins::BreadcrumbsMixin
before_action :check_privileges
before_action :get_session_data
after_action :cleanup_action
after_action :set_session_data
def self.display_methods
%w[all_vms hosts all_miq_templates registered_vms unregistered_vms custom_button_events]
end
def self.custom_display_method
%w[all_miq_templates]
end
def display_all_miq_templates
nested_list(MiqTemplate, :parent => @record, :association => "all_miq_templates")
end
def display_registered_vms
nested_list(Vm, :parent_method => "registered_vms", :breadcrumb_title => _('Managed/Registered VMs'))
end
def display_unregistered_vms
nested_list(Vm, :parent_method => "unregistered_vms", :breadcrumb_title => _('Managed/Unregistered VMs'))
end
def show_list
flash_to_session
redirect_to(:action => 'explorer')
end
alias_method :index, :show_list
def init_show
return unless super
if !@explorer && @display == "main"
tree_node_id = TreeBuilder.build_node_id(@record)
session[:exp_parms] = {:display => @display, :refresh => params[:refresh], :id => tree_node_id}
# redirect user back to where they came from if they dont have access to any of vm explorers
# or redirect them to the one they have access to
redirect_controller = role_allows?(:feature => "storage_show") ? "storage" : nil
if redirect_controller
action = "explorer"
else
url = request.env['HTTP_REFERER'].split('/')
flash_to_session(_("User '%{username}' is not authorized to access '%{controller_name}'") %
{:username => current_userid, :controller_name => ui_lookup(:table => controller_name)}, :warning)
redirect_controller = url[3]
action = url[4]
end
redirect_to(:controller => redirect_controller,
:action => action)
return
end
@gtl_url = "/show"
true
end
# handle buttons pressed on the button bar
def button
@edit = session[:edit] # Restore @edit for adv search box
params[:display] = @display if %w[all_vms vms hosts].include?(@display) # Were we displaying vms or hosts
if params[:pressed].starts_with?("vm_", # Handle buttons from sub-items screen
"miq_template_",
"guest_",
"host_")
case params[:pressed]
when 'host_analyze_check_compliance'
analyze_check_compliance_hosts
when 'host_check_compliance'
check_compliance_hosts
when 'host_compare'
comparemiq
when 'host_delete'
deletehosts
when 'host_edit'
edit_record
when 'host_protect'
assign_policies(Host)
when 'host_refresh'
refreshhosts
when 'host_scan'
scanhosts
when 'host_tag'
tag(Host)
end
pfx = pfx_for_vm_button_pressed(params[:pressed])
# Handle Host power buttons
if host_power_button?(params[:pressed])
handle_host_power_button(params[:pressed])
else
process_vm_buttons(pfx)
return if ["host_tag", "#{pfx}_policy_sim", "host_scan", "host_refresh", "host_protect",
'host_compare', "#{pfx}_compare", "#{pfx}_tag", "#{pfx}_protect", "#{pfx}_retire",
"#{pfx}_ownership", "#{pfx}_right_size", "#{pfx}_reconfigure"].include?(params[:pressed]) &&
@flash_array.nil? # Tag screen is showing, so return
unless ["host_edit", "#{pfx}_edit", "#{pfx}_miq_request_new", "#{pfx}_clone", "#{pfx}_migrate", "#{pfx}_publish", 'vm_rename'].include?(params[:pressed])
@refresh_div = "main_div"
@refresh_partial = "layouts/gtl"
show
@display = "vms"
end
end
else
@refresh_div = "main_div" # Default div for button.rjs to refresh
tag(Storage) if params[:pressed] == "storage_tag"
scanstorage if params[:pressed] == "storage_scan"
deletestorages if params[:pressed] == "storage_delete"
custom_buttons if params[:pressed] == "custom_button"
end
return if ["custom_button"].include?(params[:pressed]) # custom button screen, so return, let custom_buttons method handle everything
return if ["storage_tag"].include?(params[:pressed]) && @flash_array.nil? # Tag screen showing, so return
check_if_button_is_implemented
if single_delete_test
single_delete_redirect
elsif params[:pressed].ends_with?("_edit") ||
["#{pfx}_miq_request_new", "#{pfx}_clone", "#{pfx}_migrate", "#{pfx}_publish"].include?(params[:pressed]) ||
params[:pressed] == 'vm_rename' && @flash_array.nil?
render_or_redirect_partial(pfx)
elsif !flash_errors? && @refresh_div == "main_div" && @lastaction == "show_list"
replace_gtl_main_div
else
javascript_flash unless performed?
end
end
def files
assert_privileges('storage_show')
show_association('files', _('All Files'), :storage_files, StorageFile, 'files')
end
def disk_files
assert_privileges('storage_show')
show_association('disk_files',
_('VM Provisioned Disk Files'),
:storage_files,
StorageFile,
'disk_files')
end
def snapshot_files
assert_privileges('storage_show')
show_association('snapshot_files',
_('VM Snapshot Files'),
:storage_files,
StorageFile,
'snapshot_files')
end
def vm_ram_files
assert_privileges('storage_show')
show_association('vm_ram_files',
_('VM Memory Files'),
:storage_files, StorageFile,
'vm_ram_files')
end
def vm_misc_files
assert_privileges('storage_show')
show_association('vm_misc_files',
_('Other VM Files'),
:storage_files, StorageFile,
'vm_misc_files')
end
def debris_files
assert_privileges('storage_show')
show_association('debris_files',
_('Non-VM Files'),
:storage_files, StorageFile,
'debris_files')
end
def accordion_select
@lastaction = "explorer"
@explorer = true
@sb[:storage_search_text] ||= {}
@sb[:storage_search_text]["#{x_active_accord}_search_text"] = @search_text
self.x_active_accord = params[:id].sub(/_accord$/, '')
self.x_active_tree = "#{x_active_accord}_tree"
assert_accordion_and_tree_privileges(x_active_tree)
get_node_info(x_node)
@search_text = @sb[:storage_search_text]["#{x_active_accord}_search_text"]
load_or_clear_adv_search
replace_right_cell(:nodetype => x_node)
end
def load_or_clear_adv_search
adv_search_build("Storage")
session[:edit] = @edit
@explorer = true
if x_tree[:tree] != :storage_tree || x_node == "root"
listnav_search_selected(0)
else
@nodetype, id = parse_nodetype_and_id(valid_active_node(x_node))
if x_tree[:tree] == :storage_tree && (@nodetype == "root" || @nodetype == "ms")
search_id = @nodetype == "root" ? 0 : id
listnav_search_selected(search_id) unless params.key?(:search_text) # Clear or set the adv search filter
if @edit[:adv_search_applied] &&
MiqExpression.quick_search?(@edit[:adv_search_applied][:exp]) &&
%w[reload tree_select].include?(params[:action])
self.x_node = params[:id]
quick_search_show
return
end
end
end
end
def x_show
@record = identify_record(params[:id], Storage)
generic_x_show
end
def tree_select
@lastaction = "explorer"
self.x_active_tree = params[:tree] if params[:tree]
self.x_node = params[:id]
assert_accordion_and_tree_privileges(x_active_tree)
load_or_clear_adv_search
replace_right_cell(:nodetype => x_node)
end
def show_record(_id = nil)
@display = params[:display] || "main" unless pagination_or_gtl_request?
@lastaction = "show"
@showtype = "config"
if @record.nil?
add_flash(_("Error: Record no longer exists in the database"), :error)
if request.xml_http_request? && params[:id] # Is this an Ajax request clicking on a node that no longer exists?
@delete_node = params[:id] # Set node to be removed from the tree
end
return
end
return unless @display == 'main'
@showtype = "main"
end
def explorer
@showtype = nil
@breadcrumbs = []
@explorer = true
@lastaction = "explorer"
# if AJAX request, replace right cell, and return
if request.xml_http_request?
replace_right_cell
return
end
params.instance_variable_get(:@parameters).merge!(session[:exp_parms]) if session[:exp_parms] # Grab any explorer parm overrides
session.delete(:exp_parms)
@in_a_form = false
if params[:id] # If a tree node id came in, show in one of the trees
nodetype, id = params[:id].split("-")
# treebuilder initializes x_node to root first time in locals_for_render,
# need to set this here to force & activate node when link is clicked outside of explorer.
self.x_active_tree = :storage_tree
self.x_node = "#{nodetype}-#{id}"
end
build_accordions_and_trees
get_tagdata(@record) if @record
@lastaction = "explorer" # restore the explorer layout, which was changed by process_show_list() to "show_list"
render :layout => "application"
end
def tagging
assert_privileges("storage_tag") if x_active_accord == :storage
tagging_edit('Storage', false)
render_tagging_form
end
def storage_delete
deletestorages
end
def features
[
{
:role => "storage",
:role_any => true,
:name => :storage,
:title => _("Datastores")
},
{
:role => "storage_pod",
:role_any => true,
:name => :storage_pod,
:title => _("Datastore Clusters")
}
].map { |hsh| ApplicationController::Feature.new_with_hash(hsh) }
end
def get_node_info(node, _show_list = true)
node = valid_active_node(node)
session_reset # Reset session to same values as first time in
case x_active_tree
when :storage_tree then storage_get_node_info(node)
when :storage_pod_tree then storage_pod_get_node_info(node)
end
set_right_cell_text
end
def leaf_record
get_node_info(x_node)
@delete_node = params[:id] if @replace_trees
type, _id = parse_nodetype_and_id(x_node)
type && ["Storage"].include?(TreeBuilder.get_model_for_prefix(type))
end
def storage_record?(node = x_node)
type, _id = parse_nodetype_and_id(node)
type && ["Storage"].include?(TreeBuilder.get_model_for_prefix(type))
end
def valid_storage_record?(record)
record.try(:id)
end
def replace_right_cell(options = {})
# FIXME: nodetype passed here, but not used
_nodetype, replace_trees = options.values_at(:nodetype, :replace_trees)
replace_trees = @replace_trees if @replace_trees # get_node_info might set this
# FIXME
@explorer = true
if params[:action] == 'x_button' && params[:pressed] == 'storage_tag'
tagging
return
end
return if @in_a_form
record_showing = leaf_record
trees = build_replaced_trees(replace_trees, %i[storage storage_pod])
presenter = rendering_objects
update_partials(record_showing, presenter)
replace_search_box(presenter, :nameonly => x_active_tree == :storage)
handle_bottom_cell(presenter)
reload_trees_by_presenter(presenter, trees)
rebuild_toolbars(record_showing, presenter)
case x_active_tree
when :storage_tree
presenter.update(:main_div, r[:partial => "storage_list"])
when :storage_pod_tree
presenter.update(:main_div, r[:partial => "storage_pod_list"])
end
presenter[:right_cell_text] = @right_cell_text
presenter[:osf_node] = x_node # Open, select, and focus on this node
presenter.update(:breadcrumbs, r[:partial => 'layouts/breadcrumbs'])
render :json => presenter.for_render
end
def search_text_type(node)
return "storage" if storage_record?(node)
node
end
def update_partials(record_showing, presenter)
if record_showing
get_tagdata(@record)
presenter.hide(:form_buttons_div)
presenter.update(:main_div, r[:partial => "layouts/textual_groups_generic"])
elsif valid_storage_record?(@record)
presenter.hide(:form_buttons_div)
presenter.update(:main_div, r[:partial => "storage_list",
:locals => {:controller => 'storage'}])
else
presenter.update(:main_div, r[:partial => 'layouts/x_gtl'])
end
end
def replace_search_box(presenter, locals = {})
super(presenter, locals)
end
def handle_bottom_cell(presenter)
# Handle bottom cell
if @pages || @in_a_form
if @pages && !@in_a_form
presenter.hide(:form_buttons_div)
elsif @in_a_form
presenter.remove_paging.show(:form_buttons_div)
end
presenter.show(:paging_div)
else
presenter.hide(:paging_div)
end
end
def render_tagging_form
return if %w[cancel save].include?(params[:button])
@in_a_form = true
@right_cell_text = _("Edit Tags for Datastore")
clear_flash_msg
presenter = rendering_objects
update_tagging_partials(presenter)
# update_title(presenter)
rebuild_toolbars(false, presenter)
handle_bottom_cell(presenter)
render :json => presenter.for_render
end
def rebuild_toolbars(record_showing, presenter)
c_tb = build_toolbar(center_toolbar_filename) unless @in_a_form
v_tb = build_toolbar('download_view_tb') unless record_showing || (x_active_tree == :storage_pod_tree && x_node == 'root') || @in_a_form
cb_tb = build_toolbar(custom_toolbar_explorer)
presenter.reload_toolbars(:center => c_tb, :view => v_tb, :custom => cb_tb)
presenter.set_visibility(c_tb.present? || v_tb.present?, :toolbar)
presenter[:record_id] = @record.try(:id)
# Hide/show searchbox depending on if a list is showing
presenter.set_visibility(display_adv_searchbox, :adv_searchbox_div)
presenter[:clear_search_toggle] = clear_search_status
presenter.hide(:blocker_div) unless @edit && @edit[:adv_search_open]
presenter.hide(:quicksearchbox)
presenter[:hide_modal] = true
presenter[:lock_sidebar] = @in_a_form
end
def display_adv_searchbox
if !@record.nil? && @record[:type] == 'StorageCluster'
return false
end
!(@in_a_form || (x_active_tree == :storage_tree && @record) || (x_active_tree == :storage_pod_tree && (x_node == 'root' || @record)))
end
def breadcrumb_name(_model)
_("Datastores")
end
def tagging_explorer_controller?
@explorer && @showtype.nil?
end
# called by explorer.rb x_button
def storage_scan
scanstorage
end
def download_data
assert_privileges('storage_show_list')
super
end
def download_summary_pdf
assert_privileges('storage_show')
super
end
private
def record_class
%w[all_vms vms].include?(params[:display]) ? VmOrTemplate : Storage
end
def session_reset
if @record
session[:edit] = @edit = nil
session[:adv_search]['Storage'] = nil if session[:adv_search]
end
end
def set_right_cell_text
@right_cell_text += _(" (Names with \"%{search_text}\")") % {:search_text => @search_text} if @search_text.present? && @nodetype != 'ds' && !@in_a_form
@right_cell_text += @edit[:adv_search_applied][:text] if x_tree && x_tree[:tree] == :storage_tree && @edit && @edit[:adv_search_applied]
end
def textual_group_list
[
%i[properties registered_vms relationships],
%i[content smart_management]
]
end
helper_method :textual_group_list
def custom_toolbar_explorer
@record.present? ? Mixins::CustomButtons::Result.new(:single) : Mixins::CustomButtons::Result.new(:list)
end
def breadcrumbs_options
{
:breadcrumbs => [
{:title => _("Compute")},
{:title => _("Infrastructure")},
{:title => _("Datastores"), :url => File.join(controller_url, 'explorer')},
],
}
end
menu_section :inf
feature_for_actions "#{controller_name}_show_list", *ADV_SEARCH_ACTIONS
feature_for_actions "#{controller_name}_perf", :perf_top_chart
has_custom_buttons
end