X-Git-Url: https://git.openstreetmap.org./chef.git/blobdiff_plain/0f6cb50501b33d9b59c0ddcc8405cd933b8999cc..0b5222cd7e08c5c8fdcd7cfada9f75ecc1c7a4e2:/cookbooks/hardware/templates/default/ohai.rb.erb diff --git a/cookbooks/hardware/templates/default/ohai.rb.erb b/cookbooks/hardware/templates/default/ohai.rb.erb index 1e7ca8713..f6b854c99 100644 --- a/cookbooks/hardware/templates/default/ohai.rb.erb +++ b/cookbooks/hardware/templates/default/ohai.rb.erb @@ -5,12 +5,12 @@ Ohai.plugin(:Hardware) do def read_sysctl_link(file) File.basename(File.readlink(file)) - rescue Errno::ENOENT + rescue Errno::ENOENT, Errno::ENOTDIR end def read_sysctl_file(file) IO.read(file).strip - rescue Errno::ENOENT, Errno::EINVAL + rescue Errno::ENOENT, Errno::ENOTDIR, Errno::EINVAL end def parse_memory_size(size) @@ -148,16 +148,17 @@ Ohai.plugin(:Hardware) do find_direct_disks(disk) find_nvme_disks(disk) - find_hp_disks(disk) if File.exist?("/usr/sbin/hpssacli") + find_hp_disks(disk) if File.exist?("/usr/sbin/ssacli") find_megaraid_disks(disk) if File.exist?("/usr/sbin/megacli") - find_mpt_disks(disk) if File.exist?("/usr/sbin/sas2ircu") + find_mpt1_disks(disk) if File.exist?("/usr/sbin/lsiutil") + find_mpt2_disks(disk) if File.exist?("/usr/sbin/sas2ircu") find_adaptec_disks(disk) if File.exist?("/usr/sbin/arcconf") find_areca_disks(disk) if File.exist?("/opt/areca/x86_64/cli64") find_md_arrays(disk) disk[:disks].each do |disk| - if disk[:vendor] =~ /^CVPR/ && disk[:model] == "INTEL" + if disk[:vendor] =~ /^(BTWA|CVPR|PHDV)/ && disk[:model] == "INTEL" disk[:model] = disk[:serial_number] disk[:serial_number] = disk[:vendor] disk[:vendor] = "INTEL" @@ -180,7 +181,7 @@ Ohai.plugin(:Hardware) do end end - disk[:model].sub!(/-.*$/, "") + disk[:model].sub!(/-.*$/, "") if disk[:model] end disk @@ -214,7 +215,7 @@ Ohai.plugin(:Hardware) do end def find_nvme_disks(devices) - Dir.glob("/sys/class/misc/nvme*") do |device| + Dir.glob("/sys/class/nvme/nvme*") do |device| controller = { :id => devices[:controllers].count, :pci_slot => File.basename(Pathname.new("#{device}/device").realpath), @@ -232,7 +233,7 @@ Ohai.plugin(:Hardware) do end end - Dir.glob("#{device}/device/block/*").each do |block| + Dir.glob("#{device}/nvme*").each do |block| size = read_sysctl_file("#{block}/size").to_f / 2 disk = { @@ -252,6 +253,15 @@ Ohai.plugin(:Hardware) do end def find_md_arrays(devices) + controller = { + :id => devices[:controllers].count, + :type => "md", + :arrays => [], + :disks => [] + } + + devices[:controllers] << controller + array = nil File.new("/proc/mdstat", "r").each do |line| @@ -259,20 +269,41 @@ Ohai.plugin(:Hardware) do array = { :id => devices[:arrays].count, :device => "/dev/#{Regexp.last_match(1)}", + :status => "optimal", :raid_level => Regexp.last_match(2), :disks => [] } - Regexp.last_match(3).scan(/ (sd[a-z]+|nvme\d+n\d+)\d*\[\d+\](?:\([A-Z]\))*/).flatten.each do |device| - if disk = devices[:disks].find { |d| d[:device] == "/dev/#{device}" } - disk[:arrays] << array[:id] - array[:disks] << disk[:id] + Regexp.last_match(3).split(" ").each do |member| + if member =~ /^(sd[a-z]+|nvme\d+n\d+).*/ + device = Regexp.last_match(1) + + if disk = devices[:disks].find { |d| d[:device] == "/dev/#{device}" } + if member =~ /\(F\)/ + disk[:status] = "failed" + elsif member =~ /\(S\)/ + disk[:status] = "hotspare" + else + disk[:status] = "online" + end + + disk[:arrays] << array[:id] + array[:disks] << disk[:id] + end end end devices[:arrays] << array - elsif array && line =~ /^\s+(\d+) blocks/ + controller[:arrays] << array[:id] + elsif array && line =~ /^\s+(\d+) blocks.*(?:\[([U_]+)\])?/ array[:size] = format_disk_size(Regexp.last_match(1).to_i) + array[:status] = "degraded" if Regexp.last_match(2) =~ /_/ + elsif array && line =~ /^\s+\[.*\]\s+(\S+)\s+=/ + case Regexp.last_match(1) + when "recovery" then array[:status] = "rebuilding" + when "resync" then array[:status] = "rebuilding" + when "checking" then array[:status] = "checking" + end end end end @@ -285,10 +316,13 @@ Ohai.plugin(:Hardware) do array = nil disk = nil - IO.popen(%w(hpssacli controller all show config detail)).each do |line| - if line =~ /^Smart Array (\S+) / + IO.popen(%w(ssacli controller all show config detail)).each do |line| + next unless line.valid_encoding? + + if line =~ /^Smart (?:Array|HBA) (\S+) / controller = { :id => devices[:controllers].count, + :type => "hp", :model => Regexp.last_match(1), :arrays => [], :disks => [] @@ -302,6 +336,7 @@ Ohai.plugin(:Hardware) do disk = nil elsif controller && line =~ /^ (\S.*):\s+(.*)$/ case Regexp.last_match(1) + when "Slot" then controller[:slot] = Regexp.last_match(2) when "Serial Number" then controller[:serial_number] = Regexp.last_match(2) when "Hardware Revision" then controller[:hardware_version] = Regexp.last_match(2) when "Firmware Version" then controller[:firmware_version] = Regexp.last_match(2) @@ -319,15 +354,12 @@ Ohai.plugin(:Hardware) do controller[:arrays] << array[:id] disk = nil - elsif controller && line =~ /^ physicaldrive (\S+) / - disks << Regexp.last_match(1) elsif array && line =~ /^ physicaldrive (\S+)$/ disk = { :id => devices[:disks].count, :controller => controller[:id], :arrays => [array[:id]], - :location => Regexp.last_match(1), - :smart_device => "cciss,#{disks.find_index(Regexp.last_match(1))}" + :location => Regexp.last_match(1) } devices[:disks] << disk @@ -335,6 +367,8 @@ Ohai.plugin(:Hardware) do array[:disks] << disk[:id] elsif disk && line =~ /^ (\S[^:]+):\s+(.*\S)\s*$/ case Regexp.last_match(1) + when "Status" then disk[:status] = Regexp.last_match(2) + when "Drive Type" then disk[:drive_type] = Regexp.last_match(2) when "Interface Type" then disk[:interface] = Regexp.last_match(2) when "Size" then disk[:size] = Regexp.last_match(2) when "Rotational Speed" then disk[:rpm] = Regexp.last_match(2) @@ -342,10 +376,17 @@ Ohai.plugin(:Hardware) do when "Serial Number" then disk[:serial_number] = Regexp.last_match(2) when "Model" then disk[:model] = Regexp.last_match(2) end + elsif array && line =~ /^ Status:\s+(.*\S)\s*$/ + case Regexp.last_match(1) + when "OK" then array[:status] = "optimal" + when "Interim Recovery Mode" then array[:status] = "degraded" + else array[:status] = "unknown" + end elsif array && line =~ /^ (\S[^:]+):\s+(.*\S)\s*$/ case Regexp.last_match(1) when "Size" then array[:size] = Regexp.last_match(2) when "Fault Tolerance" then array[:raid_level] = Regexp.last_match(2) + when "Status" then array[:status] = Regexp.last_match(2) when "Disk Name" then array[:device] = Regexp.last_match(2).strip when "Mount Points" then array[:mount_point] = Regexp.last_match(2).split.first when "Unique Identifier" then array[:wwn] = Regexp.last_match(2) @@ -354,11 +395,41 @@ Ohai.plugin(:Hardware) do end controllers.each do |controller| + slot = controller[:slot] + + IO.popen(%W(ssacli controller slot=#{slot} pd all show status)).each do |line| + if line =~ /^ physicaldrive (\S+) / + disks << Regexp.last_match(1) + end + end + if device = Dir.glob("/sys/bus/pci/devices/#{controller[:pci_slot]}/cciss*").first controller[:device] = File.basename(device).sub(/^cciss(\d+)$/, "/dev/cciss/c\\1d0") elsif device = Dir.glob("/sys/bus/pci/devices/#{controller[:pci_slot]}/host*/target*:3:0/*:3:0:0/scsi_generic/sg*").first controller[:device] = "/dev/#{File.basename(device)}" + elsif device = Dir.glob("/sys/bus/pci/devices/#{controller[:pci_slot]}/host*/target*:1:0/*:1:0:*/scsi_generic/sg*").first + controller[:device] = "/dev/#{File.basename(device)}" + end + end + + devices[:disks].each do |disk| + disk[:smart_device] = "cciss,#{disks.find_index(disk[:location])}" + + if disk[:status] == "Failed" + disk[:status] = "failed" + elsif disk[:status] == "Predictive Failure" + disk[:status] = "failed" + elsif disk[:status] == "OK" && disk[:drive_type] == "Data Drive" + disk[:status] = "online" + elsif disk[:status] == "OK" && disk[:drive_type] == "Spare Drive" + disk[:status] = "hotspare" + elsif disk[:status] == "OK" && disk[:drive_type] == "Unassigned Drive" + disk[:status] = "unconfigured" + else + disk[:status] = "unknown" end + + disk.delete(:drive_type) end end @@ -374,6 +445,7 @@ Ohai.plugin(:Hardware) do if line =~ /^PCI information for Controller (\d+)$/ controller = { :id => devices[:controllers].count, + :type => "megaraid", :arrays => [], :disks => [] } @@ -381,11 +453,11 @@ Ohai.plugin(:Hardware) do devices[:controllers] << controller controllers << controller - elsif line =~ /^Bus Number\s+:\s+(\d+)$/ + elsif line =~ /^Bus Number\s+:\s+([0-9a-f]+)$/i controller[:pci_slot] = format "0000:%02x", Integer("0x#{Regexp.last_match(1)}") - elsif line =~ /^Device Number\s+:\s+(\d+)$/ + elsif line =~ /^Device Number\s+:\s+([0-9a-f]+)$/i controller[:pci_slot] = format "%s:%02x", controller[:pci_slot], Integer("0x#{Regexp.last_match(1)}") - elsif line =~ /^Function Number\s+:\s+(\d+)$/ + elsif line =~ /^Function Number\s+:\s+([0-9a-f]+)$/i controller[:pci_slot] = format "%s.%01x", controller[:pci_slot], Integer("0x#{Regexp.last_match(1)}") end end @@ -434,14 +506,22 @@ Ohai.plugin(:Hardware) do devices[:disks] << disk controller[:disks] << disk[:id] array[:disks] << disk[:id] - elsif disk && line =~ /^Firmware state:\s+(.*\S)\s*$/ - Regexp.last_match(1).split(/,\s*/).each do |state| - case state - when "Online" then disk[:status] = "online" - when "Hotspare" then disk[:status] = "hotspare" - when "Spun Up" then disk[:spun_down] = false - when "Spun down" then disk[:spun_down] = true - end + elsif disk && line =~ /^Firmware state:\s+(.*\S),\s*(.*\S)\s*$/ + case Regexp.last_match(1) + when "Unconfigured(good)" then disk[:status] = "unconfigured" + when "Unconfigured(bad)" then disk[:status] = "unconfigured" + when "Hotspare" then disk[:status] = "hotspare" + when "Offline" then disk[:status] = "offline" + when "Online" then disk[:status] = "online" + when "Rebuild" then disk[:status] = "rebuilding" + when "Failed" then disk[:status] = "failed" + when "Copyback" then disk[:status] = "rebuilding" + else disk[:status] = "unknown" + end + case Regexp.last_match(2) + when "Spun Up" then disk[:state] = "spun_up" + when "Spun down" then disk[:state] = "spun_down" + else disk[:state] = "unknown" end elsif disk && line =~ /^(\S.*\S)\s*:\s+(\S.*)$/ case Regexp.last_match(1) @@ -451,6 +531,17 @@ Ohai.plugin(:Hardware) do when "Raw Size" then disk[:size] = memory_to_disk_size(Regexp.last_match(2).sub(/\s*\[.*\]$/, "")) when "Inquiry Data" then disk[:vendor], disk[:model], disk[:serial_number] = Regexp.last_match(2).split end + elsif array && line =~ /^State\s*:\s+(.*\S)\s*$/ + case Regexp.last_match(1) + when "Partially Degraded" then array[:status] = "degraded" + when "Degraded" then array[:status] = "degraded" + when "Optimal" then array[:status] = "optimal" + when "Consistency Check" then array[:status] = "checking" + when "Background Initialization" then array[:status] = "initialising" + when "Initialization" then array[:status] = "initialising" + when "Reconstruction" then array[:status] = "rebuilding" + else array[:status] = "unknown" + end elsif array && line =~ /^(\S.*\S)\s*:\s+(\S.*)$/ case Regexp.last_match(1) when "RAID Level" then array[:raid_level] = Regexp.last_match(2).scan(/Primary-(\d+)/).first.first @@ -473,14 +564,22 @@ Ohai.plugin(:Hardware) do devices[:disks] << disk end - elsif disk && line =~ /^Firmware state:\s+(.*\S)\s*$/ - Regexp.last_match(1).split(/,\s*/).each do |state| - case state - when "Online" then disk[:status] = "online" - when "Hotspare" then disk[:status] = "hotspare" - when "Spun Up" then disk[:state] = "spun_up" - when "Spun down" then disk[:state] = "spun_down" - end + elsif disk && line =~ /^Firmware state:\s+(.*\S),\s*(.*\S)\s*$/ + case Regexp.last_match(1) + when "Unconfigured(good)" then disk[:status] = "unconfigured" + when "Unconfigured(bad)" then disk[:status] = "unconfigured" + when "Hotspare" then disk[:status] = "hotspare" + when "Offline" then disk[:status] = "offline" + when "Online" then disk[:status] = "online" + when "Rebuild" then disk[:status] = "rebuilding" + when "Failed" then disk[:status] = "failed" + when "Copyback" then disk[:status] = "rebuilding" + else disk[:status] = "unknown" + end + case Regexp.last_match(2) + when "Spun Up" then disk[:state] = "spun_up" + when "Spun down" then disk[:state] = "spun_down" + else disk[:state] = "unknown" end elsif disk && line =~ /^(\S.*\S)\s*:\s+(\S.*)$/ case Regexp.last_match(1) @@ -499,13 +598,94 @@ Ohai.plugin(:Hardware) do end end - def find_mpt_disks(devices) + def find_mpt1_disks(devices) + controllers = [] + disks = [] + + controller = nil + + IO.popen(%w(lsiutil -s)).each do |line| + if line =~ /^\/proc\/mpt\/ioc(\d+)\s+LSI Logic\s+(\S+)\s+/ + controller = { + :id => devices[:controllers].count, + :type => "mpt1", + :model => Regexp.last_match(1), + :arrays => [], + :disks => [] + } + + controllers << controller + devices[:controllers] << controller + elsif line =~ /^\s+(\d+)\s+(\d+)\s+PhysDisk (\d+)\s+(\S+)\s+(\S+)\s+\d+\s+(\S+)\s+/ + disks[Regexp.last_match(3).to_i] = { + :id => devices[:disks].count, + :controller => controller[:id], + :vendor => Regexp.last_match(4), + :model => Regexp.last_match(5), + :sas_address => Regexp.last_match(6), + :arrays => [] + } + + controller[:disks] << devices[:disks].count + devices[:disks] << disks[Regexp.last_match(3).to_i] + end + end + + controllers.each_with_index do |controller, index| + port = index + 1 + array = nil + + IO.popen(["lsiutil", "-p", port.to_s, "-a", "69,0"]).each do |line| + if line =~ /^ (\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+RAID/ + seg = Regexp.last_match(1).to_i + bus = Regexp.last_match(2).to_i + dev = Regexp.last_match(3).to_i + fun = Regexp.last_match(4).to_i + + controller[:pci_slot] = sprintf("%04x:%02x:%02x.%01x", seg, bus, dev, fun) + end + end + + IO.popen(["lsiutil", "-p", port.to_s, "-a", "21,1,0,0"]).each do |line| + if line =~ /^Volume (\d+) is/ + array = { + :id => devices[:arrays].count, + :controller => controller[:id], + :number => Regexp.last_match(1), + :disks => [] + } + + devices[:arrays] << array + controller[:arrays] << array[:id] + elsif line =~ /^ Member \d+ is PhysDisk (\d+) / + array[:disks] << disks[Regexp.last_match(1).to_i][:id] + disks[Regexp.last_match(1).to_i][:arrays] << array[:id] + end + end + end + + disks.each do |disk| + slot = controllers[disk[:controller]][:pci_slot] + sas_address = "0x#{disk[:sas_address]}" + + Dir.glob("/sys/bus/pci/devices/#{slot}/host*/port-*:*/end_device-*:*/sas_device/end_device-*:*").each do |sas_device| + if read_sysctl_file("#{sas_device}/sas_address") == sas_address + if device = Dir.glob("#{sas_device}/device/target*:0:*/*:0:*:0/scsi_generic/sg*").first + disk[:device] = "/dev/#{File.basename(device)}" + end + end + end + end + end + + def find_mpt2_disks(devices) controllers = [] IO.popen(%w(sas2ircu list)).each do |line| next unless line =~ /^\s+(\d+)\s+(\S+)\s+\h+h\s+\h+h\s+(\S+)\s+\h+h\s+\h+h\s*$/ controllers[Regexp.last_match(1).to_i] = { :id => devices[:controllers].count, + :type => "mpt2", :model => Regexp.last_match(2), :pci_slot => Regexp.last_match(3).sub(/^(\h{2})h:(\h{2})h:(\h{2})h:0(\h)h$/, "00\\1:\\2:\\3.\\4"), :arrays => [], @@ -546,6 +726,23 @@ Ohai.plugin(:Hardware) do controller[:disks] << disk[:id] disks << disk + elsif disk && line =~ /^ State\s+:\s+(.*\S)\s*$/ + Regexp.last_match(1).split(/,\s*/).each do |state| + case state + when "Online (ONL)" then disk[:status] = "online" + when "Hot Spare (HSP)" then disk[:status] = "hotspare" + when "Ready (RDY)" then disk[:status] = "unconfigured" + when "Available (AVL)" then disk[:status] = "unconfigured" + when "Failed (FLD)" then disk[:status] = "failed" + when "Missing (MIS)" then disk[:status] = "missing" + when "Standby (SBY)" then disk[:status] = "unconfigured" + when "Out of Sync (OSY)" then disk[:status] = "degraded" + when "Degraded (DGD)" then disk[:status] = "degraded" + when "Rebuilding (RBLD)" then disk[:status] = "rebuilding" + when "Optimal (OPT)" then disk[:status] = "online" + else disk[:status] = "unknown" + end + end elsif disk && line =~ /^ (\S.*\S)\s+:\s+(.*\S)\s*$/ case Regexp.last_match(1) when "Enclosure #" then disk[:location] = Regexp.last_match(2) @@ -560,6 +757,18 @@ Ohai.plugin(:Hardware) do end elsif array && line =~ /^ PHY\[\d+\] Enclosure#\/Slot#\s+:\s+(\d+:\d+)\s*$/ array[:disks] << Regexp.last_match(1) + elsif array && line =~ /^ Status of volume\s+:\s+(.*\S)\s*$/ + Regexp.last_match(1).split(/,\s*/).each do |state| + case state + when "Okay (OKY)" then array[:status] = "optimal" + when "Degraded (DGD)" then array[:status] = "degraded" + when "Failed (FLD)" then array[:status] = "failed" + when "Missing (MIS)" then array[:status] = "missing" + when "Initializing (INIT)" then array[:status] = "initialising" + when "Online (ONL)" then array[:status] = "optimal" + else array[:status] = "unknown" + end + end elsif array && line =~ /^ (\S.*\S)\s+:\s+(.*\S)\s*$/ case Regexp.last_match(1) when "Volume wwid" then array[:device] = find_sas_device(Regexp.last_match(2)) @@ -592,6 +801,7 @@ Ohai.plugin(:Hardware) do controller = { :id => devices[:controllers].count, :number => controller_number, + :type => "adaptec", :arrays => [], :disks => [] } @@ -633,6 +843,16 @@ Ohai.plugin(:Hardware) do elsif disk && line =~ /^ Reported Channel,Device\(T:L\)\s*:\s+(\d+),(\d+)\(\d+:0\)\s*$/ disk[:channel_number] = Regexp.last_match(1) disk[:device_number] = Regexp.last_match(2) + elsif disk && line =~ /^ State\s*:\s+(\S.*\S)\s*$/ + case Regexp.last_match(1) + when "Online" then disk[:status] = "online" + when "Online (JBOD)" then disk[:status] = "online" + when "Hot Spare" then disk[:status] = "hotspare" + when "Ready" then disk[:status] = "unconfigured" + when "Global Hot-Spare" then disk[:status] = "hostspare" + when "Dedicated Hot-Spare" then disk[:status] = "hotspare" + else disk[:status] = "unknown" + end elsif disk && line =~ /^ (\S.*\S)\s*:\s+(\S.*\S)\s*$/ case Regexp.last_match(1) when "Reported Location" then disk[:location] = Regexp.last_match(2) @@ -648,6 +868,11 @@ Ohai.plugin(:Hardware) do end elsif array && line =~ / Present \(.*((?:Connector|Enclosure):\d+,\s*(?:Device|Slot):\d+)\) / array[:disks] << Regexp.last_match(1).tr(":", " ").gsub(/,\s*/, ", ") + elsif array && line =~ /^ Status of Logical Device\s*:\s+(\S.*\S)\s*$/ + case Regexp.last_match(1) + when "Optimal" then array[:status] = "optimal" + else array[:status] = "unknown" + end elsif array && line =~ /^ (\S.*\S)\s*:\s+(\S.*\S)\s*$/ case Regexp.last_match(1) when "RAID level" then array[:raid_level] = Regexp.last_match(2) @@ -680,10 +905,11 @@ Ohai.plugin(:Hardware) do array[:disks].map! do |location| disk = disks.find { |disk| disk[:location] == location } + controller_number = controller[:number] - 1 device_number = disk[:device_number] - device = Dir.glob("#{host}/device/target*:1:#{device_number}/*:1:#{device_number}:0/scsi_generic/*").first disk[:device] = "/dev/#{File.basename(device)}" + disk[:smart_device] = "aacraid,#{controller_number},0,#{device_number}" disk[:arrays] << array[:id] disk[:id] @@ -695,6 +921,7 @@ Ohai.plugin(:Hardware) do def find_areca_disks(devices) controller = { :id => devices[:controllers].count, + :type => "areca", :arrays => [], :disks => [] } @@ -747,6 +974,11 @@ Ohai.plugin(:Hardware) do device = Dir.glob("/sys/bus/pci/devices/#{pci_slot}/host*/target*:0:0/0:#{channel}:#{id}:#{lun}/block/*").first array[:device] = "/dev/#{File.basename(device)}" + elsif line =~ /^Volume State\s+:\s+(.*\S)\s*$/ + case Regexp.last_match(1) + when "Normal" then array[:status] = "optimal" + else array[:status] = "unknown" + end elsif line =~ /^(\S.*\S)\s+:\s+(.*\S)\s*$/ case Regexp.last_match(1) when "Volume Set Name" then array[:volume_set] = Regexp.last_match(2) @@ -788,6 +1020,11 @@ Ohai.plugin(:Hardware) do disk[:smart_device] = "areca,#{Regexp.last_match(1)}" elsif line =~ /^Device Location\s+:\s+Enclosure#(\d+) Slot#?\s*0*(\d+)\s*$/i disk[:smart_device] = "areca,#{Regexp.last_match(2)}/#{Regexp.last_match(1)}" + elsif line =~ /^Device State\s+:\s+(.*\S)\s*$/ + case Regexp.last_match(1) + when "NORMAL" then disk[:status] = "online" + else disk[:status] = "unknown" + end elsif line =~ /^(\S.*\S)\s+:\s+(.*\S)\s*$/ case Regexp.last_match(1) when "Model Name" then disk[:vendor], disk[:model] = Regexp.last_match(2).split