Class: Proxy::Onboard::BMC::IPMIScanner

Inherits:
BaseScanner show all
Includes:
Log, Util
Defined in:
lib/bmc/ipmiscanner.rb

Instance Method Summary collapse

Methods inherited from BaseScanner

#error_string, #initialize, #max_range_size, #valid?

Constructor Details

This class inherits a constructor from Proxy::Onboard::BMC::BaseScanner

Instance Method Details

#address_pings?(address) ⇒ Boolean

This is an IPMI ping, not an ICMP ping.

Returns:

  • (Boolean)


12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/bmc/ipmiscanner.rb', line 12

def address_pings?(address)
  begin
    socket = UDPSocket.new
  rescue Errno::EMFILE
    logger.warn 'IPMIScanner: Ran out of free file descriptors while creating UDPSocket! Consider increasing file open limit.'
    retry
  end
  socket.connect(address.to_s, 623)
  socket.send([0x6, 0x0, 0xff, 0x6, 0x0, 0x0, 0x11, 0xbe, 0x80, 0x0, 0x0, 0x0].pack('C*'), 0)
  selections = IO.select([socket], nil, nil, (Proxy::Onboard::Plugin.settings.bmc_scanner_socket_timeout_seconds || 1))
  socket.close
  !selections.nil?
end

#calculate_max_threadsObject

Determine maximum number of threads



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/bmc/ipmiscanner.rb', line 37

def calculate_max_threads
  max_threads = Proxy::Onboard::Plugin.settings.bmc_scanner_max_threads_per_request || 500
  begin
    sockets = []
    # @range.first(max_threads).size performs much better than @range.count if @range is large.
    (1..[max_threads, @range.first(max_threads).size].min).each do
      sockets << UDPSocket.new
    end
  rescue Errno::EMFILE
    # Running low on free file descriptors; only allow use of half of the remaining
    max_threads = [sockets.length / 2, 1].max
    # Clean up sockets
    sockets.each(&:close)
    logger.warn "IPMIScanner: Running low on free file descriptors! Can only allocate #{sockets.length}, so using #{max_threads} to avoid hitting the limit."
  end
  max_threads
end

#scan_threaded_to_listObject



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/bmc/ipmiscanner.rb', line 55

def scan_threaded_to_list
  return false unless valid?
  pinged = []
  pool = Concurrent::ThreadPoolExecutor.new(max_threads: calculate_max_threads)
  @range.each do |address|
    pool.post do
      pinged << address if address_pings?(address)
    end
  end
  pool.shutdown
  pool.wait_for_termination
  pinged
end

#scan_to_listObject



69
70
71
72
# File 'lib/bmc/ipmiscanner.rb', line 69

def scan_to_list
  return false unless valid?
  scan_threaded_to_list
end

#scan_unthreaded_to_listObject

Not used because of slowness



27
28
29
30
31
32
33
34
# File 'lib/bmc/ipmiscanner.rb', line 27

def scan_unthreaded_to_list
  return false unless valid?
  pinged = []
  @range.each do |address|
    pinged << address if address_pings?(address)
  end
  pinged
end