lib/gems/pending/util/miq-ipmi.rb
# 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? endend