ManageIQ/manageiq-gems-pending

View on GitHub
lib/gems/pending/util/miq-ipmi.rb

Summary

Maintainability
C
1 day
Test Coverage
F
59%
# IPMI - Intelligent Platform Management Interface
# IPMI Tools man page
# http://ipmitool.sourceforge.net/manpage.html
 
# This utility relies on the following Linux packages
# OpenIPMI-tools.x86_64
# freeipmi.x86_64
 
require 'awesome_spawn'
require_relative 'miq-extensions'
 
Class `MiqIPMI` has 26 methods (exceeds 20 allowed). Consider refactoring.
class MiqIPMI
def initialize(server = nil, username = nil, password = nil)
@server = server
@username = username
@password = password
@status = chassis_status rescue nil
@vendor = nil
end
 
def connected?
!@status.nil?
end
 
def power_state
result = run_command("chassis", "power", "status")
result.split(" ").last
end
 
def power_on
run_command("chassis", "power", "on")
end
 
def power_off
run_command("chassis", "power", "off")
end
 
def power_reset
if power_state == "off"
power_on
else
power_state_change('reset')
end
end
 
def power_state_change(new_state)
# status, on, off, cycle, reset, diag, soft
run_command("chassis", "power", "#{new_state}")
end
 
def chassis_status
parse_key_value(["chassis", "status"])
end
 
def lan_info
parse_key_value(["lan", "print"])
end
 
def mc_info
parse_key_value(["mc", "info"])
end
 
def manufacturer
mc_info['Manufacturer Name']
end
 
def model
# This method tries to return the model of the device, but depending on what inforamtion
# comes back from the RFU (Field Replaceable Unit) this may not be accurate.
fru = fru_info.first
return fru["Board Product"] unless fru.blank?
nil
end
 
Method `fru_info` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.
def fru_info
return @devices unless @devices.nil?
 
@devices = []
dev_id = nil
dev_descript = nil
dev_lines = nil
cmd_output = run_command(["fru", "print"], true)
cmd_output.each_line do |line|
if line =~ /^FRU Device Description : (.*) \(ID (\d+)\)/i
@devices << fru_process_info(dev_id, dev_descript, dev_lines) unless dev_lines.nil?
dev_descript, dev_id, dev_lines = $1, $2, ''
else
dev_lines += line unless dev_lines.nil?
end
end
 
@devices << fru_process_info(dev_id, dev_descript, dev_lines)
@devices.compact
end
 
def fru_process_info(id, description, lines)
dh = nil
unless lines.blank?
dh = parse_output(lines)
Use `dh["output"] = lines` instead of `dh.merge!("output" => lines)`.
dh.merge!("output" => lines) if dh.blank?
Use `dh["ID"] = id; dh["Description"] = description` instead of `dh.merge!("ID" => id, "Description" => description)`.
dh.merge!("ID" => id, "Description" => description)
end
dh
end
 
def mac_address
macs = mac_addresses
return nil if macs.blank?
result = macs.detect { |mac| mac[:enabled] == true }
return result[:address] unless result.nil?
nil
end
 
def mac_addresses
vendor = manufacturer.to_s.downcase
return dell_mac_addresses if vendor.include?('dell')
nil
end
 
# Sample "delloem mac" output
# System LOMs
# NIC Number MAC Address Status
#
# 0 78:2b:cb:00:f6:6c Enabled
# 1 78:2b:cb:00:f6:6d Enabled
#
# iDRAC6 MAC Address 78:2b:cb:00:f6:6e
#
Method `dell_mac_addresses` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.
def dell_mac_addresses
macs = []
result = run_command(["delloem", "mac"])
result.each_line do |line|
data = line.split(' ')
if data[0].to_i.to_s == data[0].to_s
macs << mac = {:index => data[0], :address => data[1]}
unless data[2].blank?
mac[:enabled] = data[2] == 'Enabled'
else
mac[:enabled] = true
end
end
end
macs
end
 
def parse_key_value(ipmi_cmd_and_args, continue_on_error = false)
run_command_args = ipmi_cmd_and_args[1..-1] << continue_on_error
parse_output(run_command(ipmi_cmd_and_args.first, *run_command_args))
end
 
Method `parse_output` has a Cognitive Complexity of 21 (exceeds 5 allowed). Consider refactoring.
Cyclomatic complexity for parse_output is too high. [12/11]
def parse_output(cmd_text)
last_key = nil
lines = cmd_text.kind_of?(Array) ? cmd_text : cmd_text.split("\n")
lines.inject({}) do |a, line|
idx = line.index(": ")
if idx.nil?
key = nil
value = line.strip
else
key = line[0, idx].strip
value = line[idx + 1..-1].strip
end
next(a) if key.blank? && value.blank?
 
# Determine if this line has its own key value or not
if key.blank? && !last_key.blank?
key = last_key
a[key] = [a[key]] unless a[key].kind_of?(Array)
end
 
unless key.blank? || value.blank?
a[key].kind_of?(Array) ? a[key] << value : a[key] = value
end
last_key = key
a
end
end
 
Method `run_command` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.
def run_command(ipmi_cmd, *args)
# -E: The remote server password is specified by the environment variable IPMI_PASSWORD.
Use `any?(args.last)` instead of block.
continue_on_error = args.pop if [true, false, nil].any? { |type| args.last == type }
continue_on_error ||= false
ENV['IPMI_PASSWORD'] = @password
command_args = { :I => interface_mode, :H => @server, :U => @username, :E => ipmi_cmd }
command_args[nil] = args unless args.empty?
 
begin
AwesomeSpawn.run!("ipmitool", :params => command_args, :combined_output => true).output
rescue AwesomeSpawn::CommandResultError => err
result = err.result
return err.to_s if continue_on_error == true && result.exit_status == 1
 
raise "Command:<#{result.command_line}> exited with status:<#{result.exit_status}>\nCommand output:\n#{err}"
end
end
 
def self.is_available?(ip_address)
self.is_any_available?(ip_address)
# return true if self.is_2_0_available?(ip_address)
# return true if self.is_1_5_available?(ip_address)
# false
end
 
def self.is_any_available?(ip_address)
# One ping reply if machine supports IPMI
is_available_check(ip_address, nil)
end
 
def interface_mode
@if_mode ||= self.class.is_2_0_available?(@server) ? "lanplus" : "lan"
end
 
def self.is_2_0_available?(ip_address)
# One ping reply if machine supports IPMI V2.0
is_available_check(ip_address, "2.0")
end
 
def self.is_1_5_available?(ip_address)
# One ping reply if machine supports IPMI V1.5
is_available_check(ip_address, "1.5")
end
 
def self.is_available_check(ip_address, version = nil)
params =
if version.nil?
[[ip_address], [:c, 1]]
else
[[ip_address], [:r, version], [:c, 1]]
end
 
AwesomeSpawn.run("ipmiping", :params => params).success?
end
end