ManageIQ/amazon_ssa_support

View on GitHub
lib/amazon_ssa_support/ssa_queue_extractor.rb

Summary

Maintainability
A
25 mins
Test Coverage
F
23%
require 'yaml'
require 'aws-sdk-ec2'

require_relative 'miq_ec2_vm/miq_ec2_vm'
require_relative 'ssa_queue'

module AmazonSsaSupport
  class SsaQueueExtractor
    include Logging

    CATEGORIES = %w(accounts services software system).freeze
    attr_reader :my_instance, :ssaq

    def initialize(aws_args)
      raise ArgumentError, "Region must be specified." if aws_args[:region].nil?
      @aws_args     = aws_args
      @extractor_id = @aws_args[:extractor_id]
      @region       = @aws_args[:region]

      @ec2          = @aws_args[:ec2] || Aws::EC2::Resource.new(:region => @region)
      @my_instance  = @ec2.instance(@extractor_id)
      @ssaq         = SsaQueue.new(@aws_args)
      @exit_code    = nil
    end

    def extract_loop(timeout)
      start = Time.now.to_i
      loop do
        begin
          @ssaq.request_loop do |req|
            _log.debug("Got message #{req[:sqs_msg].message_id}")
            process_request(req)
            start = Time.now.to_i # reset time counter after message is processed
            return @exit_code if @exit_code
            _log.info("Waiting for next message")
          end
        end
        break if (Time.now.to_i - start) >= timeout
      end
      _log.info("No messages received in #{timeout} seconds, agent shutting down!!!")
      @exit_code = :shutdown
    end

    def process_request(req)
      req_type = req[:request_type]
      _log.debug("Processing request - #{req_type}")
      case req_type
      when :extract
        do_extract(req)
      when :exit, :reboot, :shutdown
        do_ers(req)
      else
        _log.error("Unrecognized request #{req_type}")
        @ssaq.delete_request(req)
      end
      _log.debug("Completed processing request - #{req_type}")
    rescue => err
      _log.error(err.to_s)
      _log.error(err.backtrace.join("\n"))
    end

    def do_extract(req)
      @ssaq.delete_request(req)
      extract_reply = @ssaq.new_reply(req)
      begin
        ost = OpenStruct.new
        ost.scanData = req[:scan_data]

        ec2_vm = MiqEC2Vm.new(req[:ec2_id], @my_instance, @ec2, ost)
        categories = req[:categories] || CATEGORIES
        _log.info("categories: #{categories.inspect}")
        categories.each do |cat|
          begin
            xml = ec2_vm.extract(cat)
            extract_reply.add_category(cat, xml)
          # continue to extract other category even when one failed
          rescue => err
            _log.error(err.to_s)
            _log.error(err.backtrace.join("\n"))
          end
        end
      rescue => err
        extract_reply.error = err.to_s
        _log.error(err.to_s)
        _log.error(err.backtrace.join("\n"))
      ensure
        extract_reply.reply
        ec2_vm&.unmount
      end
    end

    def do_ers(req)
      if req[:extractor_id] != @extractor_id
        if req_target_exists?(req)
          _log.debug("Re-queueing request: #{req[:sqs_msg].id}")
          @ssaq.requeue_request(req)
        else
          _log.debug("Deleting request: #{req[:sqs_msg].id}")
          @ssaq.delete_request(req)
        end
        return
      end
      @exit_code = req[:request_type]
      @ssaq.delete_request(req)
      @ssaq.send_ers_reply(req)
    end

    def req_target_exists?(req)
      @ec2.instances[req[:extractor_id]].exists?
    end
    private :req_target_exists?
  end
end