ManageIQ/manageiq-providers-ovirt

View on GitHub
app/models/manageiq/providers/ovirt/infra_manager/vm_or_template_shared/scanning.rb

Summary

Maintainability
A
0 mins
Test Coverage
F
59%
module ManageIQ::Providers::Ovirt::InfraManager::VmOrTemplateShared::Scanning
  extend ActiveSupport::Concern

  included do
    supports :smartstate_analysis do
      if storage.nil?
        "Vm is not located on a storage"
      elsif !storage.storage_type_supported_for_ssa?
        "Smartstate Analysis unsupported for storage type %{store_type}" % {:store_type => storage.store_type}
      else
        unuspported_reason(:action)
      end
    end
  end

  def scan_job_class
    ManageIQ::Providers::Ovirt::InfraManager::Scanning::Job
  end

  def require_snapshot_for_scan?
    false
  end

  def perform_metadata_scan(ost)
    require 'MiqVm/MiqRhevmVm'
    require 'manageiq-smartstate'

    log_pref = "MIQ(#{self.class.name}##{__method__})"
    vm_name  = ManageIQ::Smartstate::Util.uri_to_local_path(ost.args[0])
    $log.debug "#{log_pref} VM = #{vm_name}"

    args1 = ost.args[1]
    args1['ems']['connect'] = true if args1[:mount].blank?

    begin
      $log.debug "perform_metadata_scan: vm_name = #{vm_name}"
      @vm_cfg_file = vm_name
      connect_to_ems(ost)
      miq_vm = MiqRhevmVm.new(@vm_cfg_file, ost)
      scan_via_miq_vm(miq_vm, ost)
    rescue => err
      $log.error "#{log_pref}: #{err}"
      $log.debug err.backtrace.join("\n")
      raise
    ensure
      miq_vm.unmount if miq_vm
    end
  end

  def perform_metadata_sync(ost)
    sync_stashed_metadata(ost)
  end

  RHEVM_NO_PROXIES_ERROR_MSG = N_('VMs must be scanned from an EVM server whose host is attached to the same
  storage as the VM unless overridden via SmartProxy affinity.
  Please verify that:
  1) Direct LUNs are attached to ManageIQ appliance
  2) Management Relationship is set for the ManageIQ appliance')

  def proxies4job(_job = nil)
    _log.debug "Enter (RHEVM)"
    msg = N_('Perform SmartState Analysis on this VM')

    all_proxy_list = storage2proxies
    proxies = storage2active_proxies(all_proxy_list)
    _log.debug "# proxies = #{proxies.length}"

    if proxies.empty?
      msg = RHEVM_NO_PROXIES_ERROR_MSG
      log_all_proxies(all_proxy_list, msg)
    end

    {:proxies => proxies.flatten, :message => _(msg)}
  end

  def miq_server_proxies
    _log.debug "Enter (RHEVM)"

    _log.debug "RedHat: storage_id.blank? = #{storage_id.blank?}"
    return [] if storage_id.blank?

    miq_servers = select_miq_servers(servers_by_storage_affinity)

    _log.debug "miq_servers2.length = #{miq_servers.length}"

    miq_servers
  end

  private

  def servers_by_storage_affinity
    storage_server_ids = groups_of_vms_in_affinity_to_storage

    all_storage_server_ids = flat_storage_server_ids(storage_server_ids)

    srs = self.class.miq_servers_for_scan
    _log.debug "srs.length = #{srs.length}"

    miq_servers = srs.select do |svr|
      svr.vm_scan_storage_affinity? ? all_storage_server_ids.detect { |id| id == svr.id } : storage_server_ids.empty?
    end
    _log.debug "miq_servers1.length = #{miq_servers.length}"

    miq_servers
  end

  def groups_of_vms_in_affinity_to_storage
    storage_server_ids = storages.collect { |s| s.vm_scan_affinity.collect(&:id) }.reject(&:blank?)
    _log.debug "storage_server_ids.length = #{storage_server_ids.length}"
    storage_server_ids
  end

  def flat_storage_server_ids(group_storage_server_ids)
    all_storage_server_ids = group_storage_server_ids.inject(:&) || []
    _log.debug "all_storage_server_ids.length = #{all_storage_server_ids.length}"
    all_storage_server_ids
  end

  def select_miq_servers(miq_servers)
    miq_servers.select do |svr|
      # RedHat VMs must be scanned from an EVM server who's host is attached to the same
      # storage as the VM unless overridden via SmartProxy affinity
      started_in_same_zone?(svr) && (svr.vm_scan_storage_affinity? || same_storage_ids?(svr))
    end
  end

  def started_in_same_zone?(svr)
    svr.status == "started" && svr.has_zone?(my_zone)
  end

  def same_storage_ids?(svr)
    svr_vm = svr.vm
    return false unless svr_vm && svr_vm.host
    missing_storage_ids = storages.collect(&:id) - svr_vm.host.storages.collect(&:id)
    missing_storage_ids.empty?
  end

  def storage2active_proxies(all_proxy_list = nil)
    _log.debug "Enter (RHEVM)"

    all_proxy_list ||= storage2proxies
    _log.debug "all_proxy_list.length = #{all_proxy_list.length}"
    proxies = all_proxy_list.select(&:is_proxy_active?)
    _log.debug "proxies.length = #{proxies.length}"

    proxies
  end

  # Moved from MIQExtract.rb
  # TODO: Should this be in the ems?
  def connect_to_ems(ost)
    log_header = "MIQ(#{self.class.name}.#{__method__})"

    # Check if we've been told explicitly not to connect to the ems
    # TODO: See vm_scan.rb: config_ems_list() - is this always false for RedHat?
    if ost.scanData.fetch_path("ems", 'connect') == false
      $log.debug "#{log_header}: returning, ems/connect == false"
      return
    end

    st = Time.now
    ems_display_text = "ems(directly):#{ext_management_system.address}"
    $log.info "#{log_header}: Connecting to [#{ems_display_text}] for VM:[#{@vm_cfg_file}]"

    begin
      ost.miqRhevm = ManageIQ::Providers::Ovirt::Inventory::Collector.new(ext_management_system, nil)
      $log.info "Connection to [#{ems_display_text}] completed for VM:[#{@vm_cfg_file}] in [#{Time.now - st}] seconds"
    rescue Timeout::Error => err
      msg = "#{log_header}: Connection to [#{ems_display_text}] timed out for VM:[#{@vm_cfg_file}] with error [#{err}] after [#{Time.now - st}] seconds"
      $log.error msg
      raise
    rescue Exception => err
      msg = "#{log_header}: Connection to [#{ems_display_text}] failed for VM:[#{@vm_cfg_file}] with error [#{err}] after [#{Time.now - st}] seconds"
      $log.error msg
      raise
    end
  end
end