app/models/miq_report/import_export.rb
module MiqReport::ImportExport
extend ActiveSupport::Concern
module ClassMethods
def view_paths
@view_paths ||= begin
Vmdb::Plugins.map do |engine|
path = engine.root.join('product/views')
path if path.directory?
end.compact
end
end
def resolve_view_path(file_name, file_name_no_suffix = nil)
view_paths.each do |path|
full_path = File.join(path, file_name)
return full_path if File.exist?(full_path)
if file_name_no_suffix
full_path_no_suffix = File.join(path, file_name_no_suffix)
return full_path_no_suffix if File.exist?(full_path_no_suffix)
end
end
nil
end
def import_from_hash(report, options = nil)
raise _("No Report to Import") if report.nil?
report = report["MiqReport"] if report.keys.first == "MiqReport"
if !report["menu_name"] || !report["col_order"] || !report["cols"] || report["rpt_type"] != "Custom"
raise _("Incorrect format, only policy records can be imported.")
end
report[:db_options] ||= report["db_options"]
report[:db_options].deep_symbolize_keys! if report[:db_options]
user = options[:user] || User.lookup_by_userid(options[:userid])
if options[:preserve_owner]
userid = report.delete("userid")
group_description = report.delete("group_description")
report_user = userid.present? ? User.lookup_by_userid(userid) : User.find_by(:id => report["user_id"])
if report_user.nil?
_log.warn("User '#{userid.presence || report["user_id"]}' for imported report '#{report["name"]}' was not found")
report.delete("user_id")
else
report["user_id"] = report_user.id
end
group = group_description.present? ? MiqGroup.in_my_region.find_by(:description => group_description) : MiqGroup.find_by(:id => report["miq_group_id"])
if group.nil?
_log.warn("Group '#{group_description}' for imported report '#{report["name"]}' was not found")
report.delete("miq_group_id")
else
report["miq_group_id"] = group.id
end
raise _("Neither user or group to be preserved during import were found") if report_user.nil? && group.nil?
else
report["miq_group_id"] = user.current_group_id
report["user_id"] = user.id
end
report["name"] = report.delete("menu_name")
rep = MiqReport.find_by(:name => report["name"])
if rep
# if report exists
if options[:overwrite]
# if report exists delete and create new
if user.report_admin_user? || user.current_group_id == rep.miq_group_id
msg = "Overwriting Report: [#{report["name"]}]"
rep.attributes = report
result = {:message => "Replaced Report: [#{report["name"]}]", :level => :info, :status => :update}
else
# if report exists, do not overwrite
msg = "Skipping Report (already in DB under a different group): [#{report["name"]}]"
result = {:message => msg, :level => :error, :status => :skip}
end
else
# if report exists, do not overwrite
msg = "Skipping Report (already in DB): [#{report["name"]}]"
result = {:message => msg, :level => :info, :status => :keep}
end
else
# create new report
msg = "Importing Report: [#{report["name"]}]"
rep = MiqReport.new(report)
result = {:message => "Imported Report: [#{report["name"]}]", :level => :info, :status => :add}
end
_log.info(msg)
if options[:save] && result[:status].in?([:add, :update])
rep.save!
_log.info("- Completed.")
end
return rep, result
end
# @param db [Class] name of report (typically class name)
# @param current_user [User] User for restricted access to reports
# @param options [Hash]
# @option options :association [String] used for a view suffix
# @option options :view_suffix [String] used for a view suffix
# @param cache [Hash] cache that holds yaml for the views
def load_from_view_options(db, current_user = nil, options = {}, cache = {})
filename = MiqReport.view_yaml_filename(db, current_user, options)
raise Errno::ENOENT, "Unable to find view yaml file for db #{db.inspect}" if filename.nil?
view = load_from_filename(filename, cache)
view.db = db if filename.ends_with?("Vm__restricted.yaml")
view
end
def load_from_filename(filename, cache)
yaml = cache[filename] ||= YAML.load_file(filename)
view = MiqReport.new(yaml)
view.extras ||= {} # Always add in the extras hash
view.extras[:filename] = File.basename(filename, '.yaml')
view
end
def view_yaml_filename(db, current_user, options)
suffix = options[:association] || options[:view_suffix]
db = db.to_s
role = current_user.try(:miq_user_role)
# Special code to build the view file name for users of VM restricted roles
if %w[ManageIQ::Providers::CloudManager::Template ManageIQ::Providers::InfraManager::Template
ManageIQ::Providers::CloudManager::Vm ManageIQ::Providers::InfraManager::Vm VmOrTemplate].include?(db)
if role && role.settings && role.settings.fetch_path(:restrictions, :vms)
viewfilerestricted = resolve_view_path('Vm__restricted.yaml')
end
end
db = db.gsub("::", '_')
role = role.name.split("-").last if role.try(:read_only?)
suffix = suffix ? "-#{suffix}" : ''
viewfile = resolve_view_path("#{db}#{suffix}.yaml", "#{db}.yaml")
viewfilebyrole = resolve_view_path("#{db}#{suffix}-#{role}.yaml")
viewfilerestricted || viewfilebyrole || viewfile
end
end
def export_to_array
h = attributes
["id", "created_on", "updated_on"].each { |k| h.delete(k) }
h["menu_name"] = h.delete("name")
h["userid"] = User.find_by(:id => h["user_id"])&.userid.to_s
h["group_description"] = MiqGroup.find_by(:id => h["miq_group_id"])&.description.to_s
[{self.class.to_s => h}]
end
end