Add ohai plugin to gather additional hardward information
[chef.git] / cookbooks / hardware / templates / default / ohai.rb.erb
1 Ohai.plugin(:Hardware) do
2   provides "hardware"
3
4   def read_sysctl_link(file)
5     File.basename(File.readlink(file))
6   rescue Errno::ENOENT
7   end
8
9   def read_sysctl_file(file)
10     IO.read(file).strip
11   rescue Errno::ENOENT, Errno::EINVAL
12   end
13
14   def pci_devices
15     device = nil
16
17     IO.popen(["lspci", "-Dkvmm"]).each_with_object(Mash.new) do |line, devices|
18       if line =~ /^Slot:\s+((\h{4}):(\h{2}):(\h{2}).(\h))\s*$/
19         device = {
20           :slot => Regexp.last_match(1),
21           :domain => Regexp.last_match(2),
22           :bus => Regexp.last_match(3),
23           :device => Regexp.last_match(4),
24           :function => Regexp.last_match(5)
25         }
26       elsif device && line =~ /^([A-Z]+):\s+(.*)\s*$/i
27         case Regexp.last_match(1)
28         when "Class" then device[:class_name] = Regexp.last_match(2)
29         when "Vendor" then device[:vendor_name] = Regexp.last_match(2)
30         when "Device" then device[:device_name] = Regexp.last_match(2)
31         when "SVendor" then device[:subsystem_vendor_name] = Regexp.last_match(2)
32         when "SDevice" then device[:subsystem_device_name] = Regexp.last_match(2)
33         when "PhySlot" then device[:physical_slot] = Regexp.last_match(2)
34         when "Rev" then device[:revision] = Regexp.last_match(2)
35         when "ProgIf" then device[:programming_interface] = Regexp.last_match(2)
36         when "Driver" then device[:driver] = Regexp.last_match(2)
37         when "Module" then device[:modules] = Array(device[:modules]) << Regexp.last_match(2)
38         end
39       elsif device && line =~ /^\s*$/
40         devices[device[:slot]] = device
41         device = nil
42       end
43     end
44   end
45
46   def network_devices
47     Dir.glob("/sys/class/net/*").each_with_object(Mash.new) do |device, devices|
48       name = File.basename(device)
49
50       devices[name] = {
51         :device => read_sysctl_link("#{device}/device"),
52         :duplex => read_sysctl_file("#{device}/duplex"),
53         :speed => read_sysctl_file("#{device}/speed")
54       }.delete_if { |_, v| v.nil? }
55     end
56   end
57
58   def memory_devices
59     device = nil
60
61     IO.popen(["dmidecode", "-t", "memory"]).each_with_object([]) do |line, devices|
62       if line =~ /^Memory Device\s*$/
63         device = {}
64       elsif device && line =~ /^\s+([A-Z ]+):\s+(.*)\s*$/i
65         device[Regexp.last_match(1).tr(" ", "_").downcase.to_sym] = Regexp.last_match(2).strip
66       elsif device && line =~ /^\s*$/
67         devices << device
68         device = nil
69       end
70     end
71   end
72
73   collect_data(:default) do
74     hardware Mash.new
75
76     hardware[:pci] = pci_devices
77     hardware[:network] = network_devices
78     hardware[:memory] = memory_devices
79   end
80 end