]> git.openstreetmap.org Git - chef.git/blobdiff - cookbooks/hardware/templates/default/ohai.rb.erb
Recognise some extra disk statuses on HP controllers
[chef.git] / cookbooks / hardware / templates / default / ohai.rb.erb
index 7757dca80d0f70f9132d02a00048eab2462a385e..f6b854c99356054c76bb952ca8befc0d615b9325 100644 (file)
@@ -253,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|
@@ -260,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
@@ -287,9 +317,12 @@ Ohai.plugin(:Hardware) do
     disk = nil
 
     IO.popen(%w(ssacli controller all show config detail)).each do |line|
-      if line =~ /^Smart Array (\S+) /
+      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 => []
@@ -303,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)
@@ -320,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
@@ -336,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)
@@ -343,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)
@@ -355,6 +395,14 @@ 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
@@ -363,6 +411,26 @@ Ohai.plugin(:Hardware) do
         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
 
   def find_megaraid_disks(devices)
@@ -377,6 +445,7 @@ Ohai.plugin(:Hardware) do
       if line =~ /^PCI information for Controller (\d+)$/
         controller = {
           :id => devices[:controllers].count,
+          :type => "megaraid",
           :arrays => [],
           :disks => []
         }
@@ -384,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
@@ -437,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)
@@ -454,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
@@ -476,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)
@@ -512,6 +608,7 @@ Ohai.plugin(:Hardware) do
       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 => []
@@ -588,6 +685,7 @@ Ohai.plugin(:Hardware) do
       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 => [],
@@ -628,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)
@@ -642,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))
@@ -674,6 +801,7 @@ Ohai.plugin(:Hardware) do
       controller = {
         :id => devices[:controllers].count,
         :number => controller_number,
+        :type => "adaptec",
         :arrays => [],
         :disks => []
       }
@@ -715,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)
@@ -730,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)
@@ -762,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]
@@ -777,6 +921,7 @@ Ohai.plugin(:Hardware) do
   def find_areca_disks(devices)
     controller = {
       :id => devices[:controllers].count,
+      :type => "areca",
       :arrays => [],
       :disks => []
     }
@@ -829,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)
@@ -870,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