ManageIQ/manageiq-providers-vmware

View on GitHub
app/models/manageiq/providers/vmware/infra_manager/event_parser.rb

Summary

Maintainability
D
1 day
Test Coverage
D
61%
module ManageIQ::Providers::Vmware::InfraManager::EventParser
  def self.event_to_hash(event, ems_id = nil)
    log_header = "ems_id: [#{ems_id}] " unless ems_id.nil?

    event = vim_types_to_basic_types(event)

    _log.debug { "#{log_header}event: [#{event.inspect}]" }
    event_type = event['eventType']
    if event_type.nil?
      _log.error("#{log_header}eventType missing in event: [#{event.inspect}]")
      raise MiqException::Error, "event must have an eventType"
    end

    chain_id = event['chainId']
    if chain_id.nil?
      _log.error("#{log_header}chainId missing in event: [#{event.inspect}]")
      raise MiqException::Error, "event must have a chain_id"
    end

    is_task = (event_type == 'TaskEvent')
    if is_task
      changed_event = false

      sub_event_type = event.fetch_path('info', 'name')

      # Handle special cases
      case sub_event_type
      when nil
        # Handle cases where event name is missing
        sub_event_type = 'PowerOnVM_Task'       if event['fullFormattedMessage'].to_s.downcase == 'task: power on virtual machine'
        sub_event_type = 'DrsMigrateVM_Task'    if sub_event_type.nil? && event.fetch_path('info', 'descriptionId') == 'Drm.ExecuteVMotionLRO'
        sub_event_type = 'CnsUpdateVolume_Task' if sub_event_type.nil? && event.fetch_path('info', 'descriptionId') == 'com.vmware.cns.tasks.updatevolume'

        if sub_event_type.nil?
          _log.warn("#{log_header}Event Type cannot be determined for TaskEvent. Using generic eventType [TaskEvent] instead. event: [#{event.inspect}]")
          sub_event_type = 'TaskEvent'
        end
      when 'Rename_Task', 'Destroy_Task'
        # Handle case where event name is overloaded
        sub_event_name = event.fetch_path('info', 'descriptionId').split('.').first
        sub_event_name = case sub_event_name
                         when 'VirtualMachine' then 'VM'
                         when 'ClusterComputeResource' then 'Cluster'
                         else sub_event_name
                         end
        sub_event_type.gsub!(/_/, "#{sub_event_name}_")
      when 'MarkAsTemplate', 'MarkAsVirtualMachine'
        # Handle case where, due to timing issues, the data may not be as expected
        path_from, path_to = (sub_event_type == 'MarkAsTemplate' ? ['.vmtx', '.vmx'] : ['.vmx', '.vmtx'])

        path = event.fetch_path('vm', 'path')
        if !path.nil? && path[-(path_from.length)..-1] == path_from
          path[-(path_from.length)..-1] = path_to
          changed_event = true
        end
      end
      _log.debug { "#{log_header}changed event: [#{event.inspect}]" } if changed_event

      event_type = sub_event_type
    elsif event_type == "EventEx"
      sub_event_type = event['eventTypeId']
      event_type = sub_event_type unless sub_event_type.blank?
    end

    # Build the event hash
    result = {
      :event_type => event_type,
      :chain_id   => chain_id,
      :is_task    => is_task,
      :source     => 'VC',

      :message    => event['fullFormattedMessage'],
      :timestamp  => event['createdTime'],
      :ems_ref    => event['key'],
      :full_data  => event
    }
    result[:ems_id] = ems_id unless ems_id.nil?
    result[:username] = event['userName'] unless event['userName'].blank?

    # Get the vm information
    vm_key = 'vm' if event.key?('vm')
    vm_key = 'sourceVm' if event.key?('sourceVm')
    vm_key = 'srcTemplate' if event.key?('srcTemplate')
    unless vm_key.nil?
      vm_data = event[vm_key]
      vm_ems_ref = vm_data['vm']
      result[:vm_ems_ref] = vm_ems_ref.to_s unless vm_ems_ref.nil?
      vm_name = vm_data['name']
      result[:vm_name] = URI::DEFAULT_PARSER.unescape(vm_name) unless vm_name.nil?
      vm_location = vm_data['path']
      result[:vm_location] = vm_location unless vm_location.nil?
      vm_uid_ems = vm_data['uuid']
      result[:vm_uid_ems] = vm_uid_ems unless vm_uid_ems.nil?
    end

    # Get the dest vm information
    has_dest = false
    if ['sourceVm', 'srcTemplate'].include?(vm_key)
      vm_data = event['vm']
      unless vm_data.nil?
        vm_ems_ref = vm_data['vm']
        result[:dest_vm_ems_ref] = vm_ems_ref.to_s unless vm_ems_ref.nil?
        vm_name = vm_data['name']
        result[:dest_vm_name] = URI::DEFAULT_PARSER.unescape(vm_name) unless vm_name.nil?
        vm_location = vm_data['path']
        result[:dest_vm_location] = vm_location unless vm_location.nil?
      end

      has_dest = true
    elsif event.key?('destName')
      result[:dest_vm_name] = event['destName']
      has_dest = true
    end

    # Get the host information
    host_name = event.fetch_path('host', 'name')
    result[:host_name] = host_name unless host_name.nil?
    host_ems_ref = event.fetch_path('host', 'host')
    result[:host_ems_ref] = host_ems_ref.to_s unless host_ems_ref.nil?

    # Get the dest host information
    if has_dest
      host_data = event['destHost'] || event['host']
      unless host_data.nil?
        host_ems_ref = event['host']
        result[:dest_host_ems_ref] = host_ems_ref.to_s unless host_ems_ref.nil?
        host_name = event['name']
        result[:dest_host_name] = host_name unless host_name.nil?
      end
    end

    result
  end

  def self.vim_types_to_basic_types(obj)
    case obj
    when VimString
      obj = obj.to_s
    when VimHash
      obj = obj.to_h
      obj.each { |key, val| obj[key] = vim_types_to_basic_types(val) }
    when VimArray
      obj = obj.map { |v| vim_types_to_basic_types(v) }
    end

    obj
  end
end