ohai 0.5.8 → 0.6.0.beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. data/Rakefile +16 -48
  2. data/bin/ohai +1 -1
  3. data/lib/ohai.rb +1 -3
  4. data/lib/ohai/mash.rb +211 -0
  5. data/lib/ohai/mixin/command.rb +157 -44
  6. data/lib/ohai/mixin/ec2_metadata.rb +87 -0
  7. data/lib/ohai/plugins/c.rb +16 -13
  8. data/lib/ohai/plugins/chef.rb +2 -1
  9. data/lib/ohai/plugins/cloud.rb +25 -0
  10. data/lib/ohai/plugins/darwin/network.rb +10 -1
  11. data/lib/ohai/plugins/dmi.rb +100 -37
  12. data/lib/ohai/plugins/dmi_common.rb +117 -0
  13. data/lib/ohai/plugins/ec2.rb +12 -61
  14. data/lib/ohai/plugins/eucalyptus.rb +65 -0
  15. data/lib/ohai/plugins/freebsd/network.rb +11 -2
  16. data/lib/ohai/plugins/java.rb +4 -4
  17. data/lib/ohai/plugins/linux/filesystem.rb +24 -0
  18. data/lib/ohai/plugins/linux/network.rb +14 -1
  19. data/lib/ohai/plugins/linux/platform.rb +3 -0
  20. data/lib/ohai/plugins/linux/virtualization.rb +28 -6
  21. data/lib/ohai/plugins/netbsd/network.rb +10 -1
  22. data/lib/ohai/plugins/network.rb +3 -1
  23. data/lib/ohai/plugins/ohai.rb +1 -0
  24. data/lib/ohai/plugins/openbsd/network.rb +10 -1
  25. data/lib/ohai/plugins/ruby.rb +1 -1
  26. data/lib/ohai/plugins/sigar/filesystem.rb +2 -0
  27. data/lib/ohai/plugins/solaris2/dmi.rb +176 -0
  28. data/lib/ohai/plugins/solaris2/filesystem.rb +101 -0
  29. data/lib/ohai/plugins/solaris2/hostname.rb +10 -1
  30. data/lib/ohai/plugins/solaris2/network.rb +6 -1
  31. data/lib/ohai/plugins/solaris2/uptime.rb +36 -0
  32. data/lib/ohai/plugins/solaris2/virtualization.rb +91 -0
  33. data/lib/ohai/plugins/virtualization.rb +1 -1
  34. data/lib/ohai/plugins/windows/network.rb +17 -11
  35. data/lib/ohai/system.rb +22 -32
  36. data/lib/ohai/version.rb +23 -0
  37. data/spec/ohai/plugins/c_spec.rb +58 -7
  38. data/spec/ohai/plugins/cloud_spec.rb +24 -0
  39. data/spec/ohai/plugins/dmi_spec.rb +107 -47
  40. data/spec/ohai/plugins/ec2_spec.rb +3 -3
  41. data/spec/ohai/plugins/eucalyptus_spec.rb +84 -0
  42. data/spec/ohai/plugins/java_spec.rb +55 -2
  43. data/spec/ohai/plugins/linux/platform_spec.rb +13 -0
  44. data/spec/ohai/plugins/linux/virtualization_spec.rb +47 -6
  45. data/spec/ohai/plugins/perl_spec.rb +15 -14
  46. data/spec/ohai/plugins/rackspace_spec.rb +14 -14
  47. data/spec/ohai/plugins/solaris2/hostname_spec.rb +3 -8
  48. data/spec/ohai/plugins/solaris2/kernel_spec.rb +6 -6
  49. data/spec/ohai/plugins/solaris2/network_spec.rb +22 -22
  50. data/spec/ohai/plugins/solaris2/virtualization_spec.rb +133 -0
  51. data/spec/spec_helper.rb +5 -13
  52. metadata +182 -179
@@ -19,78 +19,26 @@
19
19
 
20
20
  provides "ec2"
21
21
 
22
- require 'open-uri'
23
- require 'socket'
22
+ require 'ohai/mixin/ec2_metadata'
24
23
 
25
24
  require_plugin "hostname"
26
25
  require_plugin "kernel"
27
26
  require_plugin "network"
28
27
 
29
- EC2_METADATA_ADDR = "169.254.169.254" unless defined?(EC2_METADATA_ADDR)
30
- EC2_METADATA_URL = "http://#{EC2_METADATA_ADDR}/2008-02-01/meta-data" unless defined?(EC2_METADATA_URL)
31
- EC2_USERDATA_URL = "http://#{EC2_METADATA_ADDR}/2008-02-01/user-data" unless defined?(EC2_USERDATA_URL)
32
- EC2_ARRAY_VALUES = %w(security-groups)
33
-
34
- def can_metadata_connect?(addr, port, timeout=2)
35
- t = Socket.new(Socket::Constants::AF_INET, Socket::Constants::SOCK_STREAM, 0)
36
- saddr = Socket.pack_sockaddr_in(port, addr)
37
- connected = false
38
-
39
- begin
40
- t.connect_nonblock(saddr)
41
- rescue Errno::EINPROGRESS
42
- r,w,e = IO::select(nil,[t],nil,timeout)
43
- if !w.nil?
44
- connected = true
45
- else
46
- begin
47
- t.connect_nonblock(saddr)
48
- rescue Errno::EISCONN
49
- t.close
50
- connected = true
51
- rescue SystemCallError
52
- end
53
- end
54
- rescue SystemCallError
55
- end
56
-
57
- connected
58
- end
28
+ extend Ohai::Mixin::Ec2Metadata
59
29
 
60
30
  def has_ec2_mac?
61
31
  network[:interfaces].values.each do |iface|
62
32
  unless iface[:arp].nil?
63
- return true if iface[:arp].value?("fe:ff:ff:ff:ff:ff")
33
+ has_mac = iface[:arp].value?("fe:ff:ff:ff:ff:ff")
34
+ Ohai::Log.debug("has_ec2_mac? == true")
35
+ return true if has_mac
64
36
  end
65
37
  end
38
+ Ohai::Log.debug("has_ec2_mac? == false")
66
39
  false
67
40
  end
68
41
 
69
- def metadata(id='')
70
- OpenURI.open_uri("#{EC2_METADATA_URL}/#{id}").read.split("\n").each do |o|
71
- key = "#{id}#{o.gsub(/\=.*$/, '/')}"
72
- if key[-1..-1] != '/'
73
- ec2[key.gsub(/\-|\//, '_').to_sym] =
74
- if EC2_ARRAY_VALUES.include? key
75
- OpenURI.open_uri("#{EC2_METADATA_URL}/#{key}").read.split("\n")
76
- else
77
- OpenURI.open_uri("#{EC2_METADATA_URL}/#{key}").read
78
- end
79
- else
80
- metadata(key)
81
- end
82
- end
83
- end
84
-
85
- def userdata()
86
- ec2[:userdata] = nil
87
- # assumes the only expected error is the 404 if there's no user-data
88
- begin
89
- ec2[:userdata] = OpenURI.open_uri("#{EC2_USERDATA_URL}/").read
90
- rescue OpenURI::HTTPError
91
- end
92
- end
93
-
94
42
  def looks_like_ec2?
95
43
  # Try non-blocking connect so we don't "block" if
96
44
  # the Xen environment is *not* EC2
@@ -98,8 +46,11 @@ def looks_like_ec2?
98
46
  end
99
47
 
100
48
  if looks_like_ec2?
49
+ Ohai::Log.debug("looks_like_ec2? == true")
101
50
  ec2 Mash.new
102
- self.metadata
103
- self.userdata
51
+ self.fetch_metadata.each {|k, v| ec2[k] = v }
52
+ ec2[:userdata] = self.fetch_userdata
53
+ else
54
+ Ohai::Log.debug("looks_like_ec2? == false")
55
+ false
104
56
  end
105
-
@@ -0,0 +1,65 @@
1
+ #
2
+ # Author:: Tim Dysinger (<tim@dysinger.net>)
3
+ # Author:: Benjamin Black (<bb@opscode.com>)
4
+ # Author:: Christopher Brown (<cb@opscode.com>)
5
+ # Copyright:: Copyright (c) 2009 Opscode, Inc.
6
+ # License:: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+
20
+ provides "eucalyptus"
21
+
22
+ require 'ohai/mixin/ec2_metadata'
23
+
24
+ require_plugin "hostname"
25
+ require_plugin "kernel"
26
+ require_plugin "network"
27
+
28
+ extend Ohai::Mixin::Ec2Metadata
29
+
30
+ def get_mac_address(addresses)
31
+ detected_addresses = addresses.detect { |address, keypair| keypair == {"family"=>"lladdr"} }
32
+ if detected_addresses
33
+ return detected_addresses.first
34
+ else
35
+ return ""
36
+ end
37
+ end
38
+
39
+ def has_euca_mac?
40
+ network[:interfaces].values.each do |iface|
41
+ has_mac = (get_mac_address(iface[:addresses]) =~ /^[dD]0:0[dD]:/)
42
+ Ohai::Log.debug("has_euca_mac? == #{!!has_mac}")
43
+ return true if has_mac
44
+ end
45
+
46
+ Ohai::Log.debug("has_euca_mac? == false")
47
+ false
48
+ end
49
+
50
+ def looks_like_euca?
51
+ # Try non-blocking connect so we don't "block" if
52
+ # the Xen environment is *not* EC2
53
+ has_euca_mac? && can_metadata_connect?(EC2_METADATA_ADDR,80)
54
+ end
55
+
56
+ if looks_like_euca?
57
+ Ohai::Log.debug("looks_like_euca? == true")
58
+ eucalyptus Mash.new
59
+ self.fetch_metadata.each {|k, v| eucalyptus[k] = v }
60
+ eucalyptus[:userdata] = self.fetch_userdata
61
+ else
62
+ Ohai::Log.debug("looks_like_euca? == false")
63
+ false
64
+ end
65
+
@@ -18,7 +18,16 @@
18
18
 
19
19
  provides "network", "counters/network"
20
20
 
21
- network[:default_interface] = from("route -n get default \| grep interface: \| awk \'/: / \{print \$2\}\'")
21
+ from("route -n get default").split("\n").each do |line|
22
+ if line =~ /(\w+): ([\w\.]+)/
23
+ case $1
24
+ when "gateway"
25
+ network[:default_gateway] = $2
26
+ when "interface"
27
+ network[:default_interface] = $2
28
+ end
29
+ end
30
+ end
22
31
 
23
32
  iface = Mash.new
24
33
  popen4("/sbin/ifconfig -a") do |pid, stdin, stdout, stderr|
@@ -109,4 +118,4 @@ popen4("netstat -ibdn") do |pid, stdin, stdout, stderr|
109
118
  end
110
119
  end
111
120
 
112
- counters[:network][:interfaces] = net_counters
121
+ counters[:network][:interfaces] = net_counters
@@ -28,10 +28,10 @@ if status == 0
28
28
  case line
29
29
  when /java version \"([0-9\.\_]+)\"/
30
30
  java[:version] = $1
31
- when /^(.+Runtime Environment.*) \(build (.+)\)$/
32
- java[:runtime] = { "name" => $1, "build" => $2 }
33
- when /^(.+ Client VM) \(build (.+)\)$/
34
- java[:hotspot] = { "name" => $1, "build" => $2 }
31
+ when /^(.+Runtime Environment.*) \((build )?(.+)\)$/
32
+ java[:runtime] = { "name" => $1, "build" => $3 }
33
+ when /^(.+ (Client|Server) VM) \(build (.+)\)$/
34
+ java[:hotspot] = { "name" => $1, "build" => $3 }
35
35
  end
36
36
  end
37
37
 
@@ -53,5 +53,29 @@ popen4("mount -l") do |pid, stdin, stdout, stderr|
53
53
  end
54
54
  end
55
55
 
56
+ # Grab UUID from /dev/disk/by-uuid/*
57
+ popen4("ls -l /dev/disk/by-uuid/* | awk '{print $11, $9}'") do |pid, stdin, stdout, stderr|
58
+ stdin.close
59
+ stdout.each do |line|
60
+ if line =~ /^[.\/]+\/([a-z]+\d) \/.\/(.)$/
61
+ filesystem = "/dev/" + $1
62
+ fs[filesystem] = Mash.new unless fs.has_key?(filesystem)
63
+ fs[filesystem][:uuid] = $2
64
+ end
65
+ end
66
+ end
67
+
68
+ # Grab any missing mount information from /proc/mounts
69
+ File.open('/proc/mounts').each do |line|
70
+ if line =~ /^(\S+) (\S+) (\S+) (\S+) \S+ \S+$/
71
+ filesystem = $1
72
+ next if fs.has_key?(filesystem)
73
+ fs[filesystem] = Mash.new
74
+ fs[filesystem][:mount] = $2
75
+ fs[filesystem][:fs_type] = $3
76
+ fs[filesystem][:mount_options] = $4.split(",")
77
+ end
78
+ end
79
+
56
80
  # Set the filesystem data
57
81
  filesystem fs
@@ -18,7 +18,17 @@
18
18
 
19
19
  provides "network", "counters/network"
20
20
 
21
- network[:default_interface] = from("route -n \| grep -m 1 ^0.0.0.0 \| awk \'{print \$8\}\'")
21
+ begin
22
+ route_result = from("route -n \| grep -m 1 ^0.0.0.0").split(/[ \t]+/)
23
+ if route_result.last =~ /(venet\d+)/
24
+ network[:default_interface] = from("ip addr show dev #{$1} | grep -v 127.0.0.1 | grep -m 1 inet").split(/[ \t]+/).last
25
+ network[:default_gateway] = route_result[1]
26
+ else
27
+ network[:default_gateway], network[:default_interface] = route_result.values_at(1,7)
28
+ end
29
+ rescue Ohai::Exceptions::Exec
30
+ Ohai::Log.debug("Unable to determine default interface")
31
+ end
22
32
 
23
33
  def encaps_lookup(encap)
24
34
  return "Loopback" if encap.eql?("Local Loopback")
@@ -74,6 +84,9 @@ popen4("ifconfig -a") do |pid, stdin, stdout, stderr|
74
84
  if line =~ /MTU:(\d+)/
75
85
  iface[cint][:mtu] = $1
76
86
  end
87
+ if line =~ /P-t-P:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/
88
+ iface[cint][:peer] = $1
89
+ end
77
90
  if line =~ /RX packets:(\d+) errors:(\d+) dropped:(\d+) overruns:(\d+) frame:(\d+)/
78
91
  net_counters[cint] = Mash.new unless net_counters[cint]
79
92
  net_counters[cint][:rx] = { "packets" => $1, "errors" => $2, "drop" => $3, "overrun" => $4, "frame" => $5 }
@@ -47,6 +47,9 @@ elsif File.exists?('/etc/gentoo-release')
47
47
  elsif File.exists?('/etc/SuSE-release')
48
48
  platform "suse"
49
49
  platform_version File.read("/etc/SuSE-release").scan(/VERSION = (\d+)\nPATCHLEVEL = (\d+)/).flatten.join(".")
50
+ elsif File.exists?('/etc/slackware-version')
51
+ platform "slackware"
52
+ platform_version File.read("/etc/slackware-version").scan(/(\d+|\.+)/).join
50
53
  elsif File.exists?('/etc/arch-release')
51
54
  platform "arch"
52
55
  # no way to determine platform_version in a rolling release distribution
@@ -23,17 +23,17 @@ virtualization Mash.new
23
23
  # if it is possible to detect paravirt vs hardware virt, it should be put in
24
24
  # virtualization[:mechanism]
25
25
  if File.exists?("/proc/xen/capabilities") && File.read("/proc/xen/capabilities") =~ /control_d/i
26
- virtualization[:emulator] = "xen"
26
+ virtualization[:system] = "xen"
27
27
  virtualization[:role] = "host"
28
28
  elsif File.exists?("/proc/sys/xen/independent_wallclock")
29
- virtualization[:emulator] = "xen"
29
+ virtualization[:system] = "xen"
30
30
  virtualization[:role] = "guest"
31
31
  end
32
32
 
33
33
  # Detect KVM hosts by kernel module
34
34
  if File.exists?("/proc/modules")
35
35
  if File.read("/proc/modules") =~ /^kvm/
36
- virtualization[:emulator] = "kvm"
36
+ virtualization[:system] = "kvm"
37
37
  virtualization[:role] = "host"
38
38
  end
39
39
  end
@@ -45,7 +45,7 @@ end
45
45
  # Wait for reply to: http://article.gmane.org/gmane.comp.emulators.kvm.devel/27885
46
46
  if File.exists?("/proc/cpuinfo")
47
47
  if File.read("/proc/cpuinfo") =~ /QEMU Virtual CPU/
48
- virtualization[:emulator] = "kvm"
48
+ virtualization[:system] = "kvm"
49
49
  virtualization[:role] = "guest"
50
50
  end
51
51
  end
@@ -58,17 +58,39 @@ if File.exists?("/usr/sbin/dmidecode")
58
58
  case dmi_info
59
59
  when /Manufacturer: Microsoft/
60
60
  if dmi_info =~ /Product Name: Virtual Machine/
61
- virtualization[:emulator] = "virtualpc"
61
+ virtualization[:system] = "virtualpc"
62
62
  virtualization[:role] = "guest"
63
63
  end
64
64
  when /Manufacturer: VMware/
65
65
  if dmi_info =~ /Product Name: VMware Virtual Platform/
66
- virtualization[:emulator] = "vmware"
66
+ virtualization[:system] = "vmware"
67
67
  virtualization[:role] = "guest"
68
68
  end
69
+ when /Manufacturer: Xen/
70
+ if dmi_info =~ /Product Name: HVM domU/
71
+ virtualization[:system] = "xen"
72
+ virtualization[:role] = "guest"
73
+ end
69
74
  else
70
75
  nil
71
76
  end
72
77
 
73
78
  end
74
79
  end
80
+
81
+ # Detect Linux-VServer
82
+ if File.exists?("/proc/self/status")
83
+ proc_self_status = File.read("/proc/self/status")
84
+ vxid = proc_self_status.match(/^(s_context|VxID): (\d+)$/)
85
+ if vxid and vxid[2]
86
+ virtualization[:system] = "linux-vserver"
87
+ if vxid[2] == "0"
88
+ virtualization[:role] = "host"
89
+ else
90
+ virtualization[:role] = "guest"
91
+ end
92
+ end
93
+ end
94
+
95
+ # Detect OpenVZ
96
+ # something in /proc/vz/veinfo
@@ -18,7 +18,16 @@
18
18
 
19
19
  provides "network", "counters/network"
20
20
 
21
- network[:default_interface] = from("route -n get default \| grep interface: \| awk \'/: / \{print \$2\}\'")
21
+ from("route -n get default").split("\n").each do |line|
22
+ if line =~ /(\w+): ([\w\.]+)/
23
+ case $1
24
+ when "gateway"
25
+ network[:default_gateway] = $2
26
+ when "interface"
27
+ network[:default_interface] = $2
28
+ end
29
+ end
30
+ end
22
31
 
23
32
  iface = Mash.new
24
33
  popen4("/sbin/ifconfig -a") do |pid, stdin, stdout, stderr|
@@ -36,13 +36,15 @@ def find_ip_and_mac(addresses)
36
36
  [ip, mac]
37
37
  end
38
38
 
39
- unless network[:default_interface].nil?
39
+ if network[:default_interface]
40
+ Ohai::Log.debug("Using default interface for default ip and mac address")
40
41
  im = find_ip_and_mac(network["interfaces"][network[:default_interface]]["addresses"])
41
42
  ipaddress im.shift
42
43
  macaddress im.shift
43
44
  else
44
45
  network["interfaces"].keys.sort.each do |iface|
45
46
  if network["interfaces"][iface]["encapsulation"].eql?("Ethernet")
47
+ Ohai::Log.debug("Picking ip and mac address from first Ethernet interface")
46
48
  im = find_ip_and_mac(network["interfaces"][iface]["addresses"])
47
49
  ipaddress im.shift
48
50
  macaddress im.shift
@@ -22,3 +22,4 @@ provides "ohai"
22
22
  self[:chef_packages] = Mash.new unless self[:chef_packages]
23
23
  self[:chef_packages][:ohai] = Mash.new
24
24
  self[:chef_packages][:ohai][:version] = Ohai::VERSION
25
+ self[:chef_packages][:ohai][:ohai_root] = Ohai::OHAI_ROOT
@@ -18,7 +18,16 @@
18
18
 
19
19
  provides "network", "counters/network"
20
20
 
21
- network[:default_interface] = from("route -n get default \| grep interface: \| awk \'/: / \{print \$2\}\'")
21
+ from("route -n get default").split("\n").each do |line|
22
+ if line =~ /(\w+): ([\w\.]+)/
23
+ case $1
24
+ when "gateway"
25
+ network[:default_gateway] = $2
26
+ when "interface"
27
+ network[:default_interface] = $2
28
+ end
29
+ end
30
+ end
22
31
 
23
32
  iface = Mash.new
24
33
  popen4("/sbin/ifconfig -a") do |pid, stdin, stdout, stderr|
@@ -58,7 +58,7 @@ result = run_ruby "puts %Q(#{env_string})"
58
58
  # Parse results to plugin hash
59
59
  result.split(',').each do |entry|
60
60
  key, value = entry.split('=')
61
- languages[:ruby][key.to_sym] = value
61
+ languages[:ruby][key.to_sym] = value || ""
62
62
  end
63
63
 
64
64
  # Perform one more (conditional) query
@@ -36,6 +36,8 @@ sigar.file_system_list.each do |fsys|
36
36
  fs[filesystem][:kb_used] = ((usage.total - usage.free) / 1024).to_s
37
37
  fs[filesystem][:kb_available] = (usage.free / 1024).to_s
38
38
  fs[filesystem][:percent_used] = (usage.use_percent * 100).to_s + '%'
39
+ rescue SystemExit => e
40
+ raise
39
41
  rescue Exception => e
40
42
  #e.g. floppy or cdrom drive
41
43
  end
@@ -0,0 +1,176 @@
1
+ #
2
+ # Author:: Kurt Yoder (ktyopscode@yoderhome.com)
3
+ # Copyright:: Copyright (c) 2010 Kurt Yoder
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require_plugin "dmi"
20
+
21
+ # if we already have a "dmi" with keys (presumably from dmidecode), don't try smbios
22
+ # note that a single key just means dmidecode exited with its version
23
+ if (dmi.class.to_s == 'Mash') and (dmi.keys.length > 1)
24
+ Ohai::Log.debug('skipping smbios output, since DMI information has already been provided')
25
+ return
26
+ end
27
+
28
+ dmi Mash.new
29
+
30
+ # bad Solaris shows strings defined by system instead of SMB IDs
31
+ # this is what the *real* IDs are:
32
+ # pulled from http://src.opensolaris.org/source/xref/nwam/nwam1/usr/src/uts/common/sys/smbios.h
33
+ smb_to_id = {
34
+ 'SMB_TYPE_BIOS' => 0, # BIOS information (R)
35
+ 'SMB_TYPE_SYSTEM' => 1, # system information (R)
36
+ 'SMB_TYPE_BASEBOARD' => 2, # base board
37
+ 'SMB_TYPE_CHASSIS' => 3, # system enclosure or chassis (R)
38
+ 'SMB_TYPE_PROCESSOR' => 4, # processor (R)
39
+ 'SMB_TYPE_MEMCTL' => 5, # memory controller (O)
40
+ 'SMB_TYPE_MEMMOD' => 6, # memory module (O)
41
+ 'SMB_TYPE_CACHE' => 7, # processor cache (R)
42
+ 'SMB_TYPE_PORT' => 8, # port connector
43
+ 'SMB_TYPE_SLOT' => 9, # upgradeable system slot (R)
44
+ 'SMB_TYPE_OBDEVS' => 10, # on-board devices
45
+ 'SMB_TYPE_OEMSTR' => 11, # OEM string table
46
+ 'SMB_TYPE_SYSCONFSTR' => 12, # system configuration string table
47
+ 'SMB_TYPE_LANG' => 13, # BIOS language information
48
+ 'SMB_TYPE_GROUP' => 14, # group associations
49
+ 'SMB_TYPE_EVENTLOG' => 15, # system event log
50
+ 'SMB_TYPE_MEMARRAY' => 16, # physical memory array (R)
51
+ 'SMB_TYPE_MEMDEVICE' => 17, # memory device (R)
52
+ 'SMB_TYPE_MEMERR32' => 18, # 32-bit memory error information
53
+ 'SMB_TYPE_MEMARRAYMAP' => 19, # memory array mapped address (R)
54
+ 'SMB_TYPE_MEMDEVICEMAP' => 20, # memory device mapped address (R)
55
+ 'SMB_TYPE_POINTDEV' => 21, # built-in pointing device
56
+ 'SMB_TYPE_BATTERY' => 22, # portable battery
57
+ 'SMB_TYPE_RESET' => 23, # system reset settings
58
+ 'SMB_TYPE_SECURITY' => 24, # hardware security settings
59
+ 'SMB_TYPE_POWERCTL' => 25, # system power controls
60
+ 'SMB_TYPE_VPROBE' => 26, # voltage probe
61
+ 'SMB_TYPE_COOLDEV' => 27, # cooling device
62
+ 'SMB_TYPE_TPROBE' => 28, # temperature probe
63
+ 'SMB_TYPE_IPROBE' => 29, # current probe
64
+ 'SMB_TYPE_OOBRA' => 30, # out-of-band remote access facility
65
+ 'SMB_TYPE_BIS' => 31, # boot integrity services
66
+ 'SMB_TYPE_BOOT' => 32, # system boot status (R)
67
+ 'SMB_TYPE_MEMERR64' => 33, # 64-bit memory error information
68
+ 'SMB_TYPE_MGMTDEV' => 34, # management device
69
+ 'SMB_TYPE_MGMTDEVCP' => 35, # management device component
70
+ 'SMB_TYPE_MGMTDEVDATA' => 36, # management device threshold data
71
+ 'SMB_TYPE_MEMCHAN' => 37, # memory channel
72
+ 'SMB_TYPE_IPMIDEV' => 38, # IPMI device information
73
+ 'SMB_TYPE_POWERSUP' => 39, # system power supply
74
+ 'SMB_TYPE_INACTIVE' => 126, # inactive table entry
75
+ 'SMB_TYPE_EOT' => 127, # end of table
76
+ 'SMB_TYPE_OEM_LO' => 128, # start of OEM-specific type range
77
+ 'SUN_OEM_EXT_PROCESSOR' => 132, # processor extended info
78
+ 'SUN_OEM_PCIEXRC' => 138, # PCIE RootComplex/RootPort info
79
+ 'SUN_OEM_EXT_MEMARRAY' => 144, # phys memory array extended info
80
+ 'SUN_OEM_EXT_MEMDEVICE' => 145, # memory device extended info
81
+ 'SMB_TYPE_OEM_HI' => 256, # end of OEM-specific type range
82
+ }
83
+
84
+ # all output lines should fall within one of these patterns
85
+ header_type_line = /^ID\s+SIZE\s+TYPE/
86
+ header_information_line = /^(\d+)\s+(\d+)\s+(\S+)\s+\(([^\)]+)\)/
87
+ blank_line = /^\s*$/
88
+ data_key_value_line = /^ ([^:]+): (.*)/
89
+ data_key_only_line = /^ (\S.*)(:\s*)?$/
90
+ extended_data_line = /^\t(\S+) \((.+)\)/
91
+
92
+ dmi_record = nil
93
+ field = nil
94
+
95
+ popen4("smbios") do |pid, stdin, stdout, stderr|
96
+ stdin.close
97
+
98
+ # ==== EXAMPLE: ====
99
+ # ID SIZE TYPE
100
+ # 0 40 SMB_TYPE_BIOS (BIOS information)
101
+ #
102
+ # Vendor: HP
103
+ # Version String: 2.16
104
+ # ... similar lines trimmed
105
+ # Characteristics: 0x7fc9da80
106
+ # SMB_BIOSFL_PCI (PCI is supported)
107
+ # ... similar lines trimmed
108
+ # note the second level of indentation is via a *tab*
109
+ stdout.each do |raw_line|
110
+ next if header_type_line.match(raw_line)
111
+ next if blank_line.match(raw_line)
112
+
113
+ # remove/replace any characters that don't fall inside permissible ASCII range, or whitespace
114
+ line = raw_line.gsub(/[^\x20-\x7E\n\t\r]/, '.')
115
+ if (line != raw_line)
116
+ Ohai::Log.debug("converted characters from line:\n#{raw_line}")
117
+ end
118
+
119
+ if header_information = header_information_line.match(line)
120
+ dmi_record = {}
121
+
122
+ # look up SMB ID
123
+ if smb_to_id.has_key?(header_information[3])
124
+ dmi_record[:type] = DMI.id_lookup(smb_to_id[header_information[3]])
125
+
126
+ else
127
+ dmi_record[:type] = header_information[3].downcase
128
+ Ohai::Log.debug("unrecognized header type; falling back to #{dmi_record[:type]}")
129
+ end
130
+
131
+ dmi[dmi_record[:type]] = Mash.new unless dmi.has_key?(dmi_record[:type])
132
+ dmi[dmi_record[:type]][:all_records] = [] unless dmi[dmi_record[:type]].has_key?(:all_records)
133
+ dmi_record[:position] = dmi[dmi_record[:type]][:all_records].length
134
+ dmi[dmi_record[:type]][:all_records].push(Mash.new)
135
+ dmi[dmi_record[:type]][:all_records][dmi_record[:position]][:record_id] = header_information[1]
136
+ dmi[dmi_record[:type]][:all_records][dmi_record[:position]][:size] = header_information[2]
137
+ dmi[dmi_record[:type]][:all_records][dmi_record[:position]][:application_identifier] = header_information[4]
138
+ field = nil
139
+
140
+ elsif data = data_key_value_line.match(line)
141
+ if dmi_record == nil
142
+ Ohai::Log.debug("unexpected data line found before header; discarding:\n#{line}")
143
+ next
144
+ end
145
+ dmi[dmi_record[:type]][:all_records][dmi_record[:position]][data[1]] = data[2]
146
+ field = data[1]
147
+
148
+ elsif data = data_key_only_line.match(line)
149
+ if dmi_record == nil
150
+ Ohai::Log.debug("unexpected data line found before header; discarding:\n#{line}")
151
+ next
152
+ end
153
+ dmi[dmi_record[:type]][:all_records][dmi_record[:position]][data[1]] = ''
154
+ field = data[1]
155
+
156
+ elsif extended_data = extended_data_line.match(line)
157
+ if dmi_record == nil
158
+ Ohai::Log.debug("unexpected extended data line found before header; discarding:\n#{line}")
159
+ next
160
+ end
161
+ if field == nil
162
+ Ohai::Log.debug("unexpected extended data line found outside data section; discarding:\n#{line}")
163
+ next
164
+ end
165
+ # overwrite "raw" value with a new Mash
166
+ dmi[dmi_record[:type]][:all_records][dmi_record[:position]][field] = Mash.new unless dmi[dmi_record[:type]][:all_records][dmi_record[:position]][field].class.to_s == 'Mash'
167
+ dmi[dmi_record[:type]][:all_records][dmi_record[:position]][field][extended_data[1]] = extended_data[2]
168
+
169
+ else
170
+ Ohai::Log.debug("unrecognized output line; discarding:\n#{line}")
171
+
172
+ end
173
+ end
174
+ end
175
+
176
+ DMI.convenience_keys(dmi)