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
@@ -0,0 +1,87 @@
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
+ require 'open-uri'
21
+ require 'socket'
22
+
23
+ module Ohai
24
+ module Mixin
25
+ module Ec2Metadata
26
+
27
+ EC2_METADATA_ADDR = "169.254.169.254" unless defined?(EC2_METADATA_ADDR)
28
+ EC2_METADATA_URL = "http://#{EC2_METADATA_ADDR}/2008-02-01/meta-data" unless defined?(EC2_METADATA_URL)
29
+ EC2_USERDATA_URL = "http://#{EC2_METADATA_ADDR}/2008-02-01/user-data" unless defined?(EC2_USERDATA_URL)
30
+ EC2_ARRAY_VALUES = %w(security-groups)
31
+
32
+ def can_metadata_connect?(addr, port, timeout=2)
33
+ t = Socket.new(Socket::Constants::AF_INET, Socket::Constants::SOCK_STREAM, 0)
34
+ saddr = Socket.pack_sockaddr_in(port, addr)
35
+ connected = false
36
+
37
+ begin
38
+ t.connect_nonblock(saddr)
39
+ rescue Errno::EINPROGRESS
40
+ r,w,e = IO::select(nil,[t],nil,timeout)
41
+ if !w.nil?
42
+ connected = true
43
+ else
44
+ begin
45
+ t.connect_nonblock(saddr)
46
+ rescue Errno::EISCONN
47
+ t.close
48
+ connected = true
49
+ rescue SystemCallError
50
+ end
51
+ end
52
+ rescue SystemCallError
53
+ end
54
+ Ohai::Log.debug("can_metadata_connect? == #{connected}")
55
+ connected
56
+ end
57
+
58
+ def fetch_metadata(id='')
59
+ metadata = Hash.new
60
+ OpenURI.open_uri("#{EC2_METADATA_URL}/#{id}").read.split("\n").each do |o|
61
+ key = "#{id}#{o.gsub(/\=.*$/, '/')}"
62
+ if key[-1..-1] != '/'
63
+ metadata[key.gsub(/\-|\//, '_').to_sym] =
64
+ if EC2_ARRAY_VALUES.include? key
65
+ OpenURI.open_uri("#{EC2_METADATA_URL}/#{key}").read.split("\n")
66
+ else
67
+ OpenURI.open_uri("#{EC2_METADATA_URL}/#{key}").read
68
+ end
69
+ else
70
+ next
71
+ end
72
+ end
73
+ metadata
74
+ end
75
+
76
+ def fetch_userdata()
77
+ # assumes the only expected error is the 404 if there's no user-data
78
+ begin
79
+ OpenURI.open_uri("#{EC2_USERDATA_URL}/").read
80
+ rescue OpenURI::HTTPError
81
+ nil
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+
@@ -37,13 +37,16 @@ if status == 0
37
37
  end
38
38
 
39
39
  #glibc
40
- status, stdout, stderr = run_command(:no_status_check => true, :command => "/lib/libc.so.6")
41
- if status == 0
42
- description = stdout.split($/).first
43
- if description =~ /(\d+\.\d+\.\d+)/
44
- c[:glibc] = Mash.new
45
- c[:glibc][:version] = $1
46
- c[:glibc][:description] = description
40
+ ["/lib/libc.so.6", "/lib64/libc.so.6"].each do |glibc|
41
+ status, stdout, stderr = run_command(:no_status_check => true, :command => glibc)
42
+ if status == 0
43
+ description = stdout.split($/).first
44
+ if description =~ /(\d+\.\d+\.?\d*)/
45
+ c[:glibc] = Mash.new
46
+ c[:glibc][:version] = $1
47
+ c[:glibc][:description] = description
48
+ end
49
+ break
47
50
  end
48
51
  end
49
52
 
@@ -72,12 +75,12 @@ end
72
75
 
73
76
  #ibm xlc
74
77
  status, stdout, stderr = run_command(:no_status_check => true, :command => "xlc -qversion")
75
- if status == 0
76
- lines = stdout.split($/)
77
- if lines.size >= 2
78
+ if status == 0 or (status >> 8) == 249
79
+ description = stdout.split($/).first
80
+ if description =~ /V(\d+\.\d+)/
78
81
  c[:xlc] = Mash.new
79
- c[:xlc][:version] = lines[1].split.last
80
- c[:xlc][:description] = lines[0]
82
+ c[:xlc][:version] = $1
83
+ c[:xlc][:description] = description.strip
81
84
  end
82
85
  end
83
86
 
@@ -85,7 +88,7 @@ end
85
88
  status, stdout, stderr = run_command(:no_status_check => true, :command => "cc -V -flags")
86
89
  if status == 0
87
90
  output = stderr.split
88
- if output.size >= 4
91
+ if stderr =~ /^cc: Sun C/ && output.size >= 4
89
92
  c[:sunpro] = Mash.new
90
93
  c[:sunpro][:version] = output[3]
91
94
  c[:sunpro][:description] = stderr.chomp
@@ -16,9 +16,10 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
- require 'chef'
19
+ require 'chef/version'
20
20
  provides "chef"
21
21
 
22
22
  self[:chef_packages] = Mash.new unless self[:chef_packages]
23
23
  self[:chef_packages][:chef] = Mash.new
24
24
  self[:chef_packages][:chef][:version] = Chef::VERSION
25
+ self[:chef_packages][:chef][:chef_root] = Chef::CHEF_ROOT
@@ -18,6 +18,7 @@ provides "cloud"
18
18
 
19
19
  require_plugin "ec2"
20
20
  require_plugin "rackspace"
21
+ require_plugin "eucalyptus"
21
22
 
22
23
  # Make top-level cloud hashes
23
24
  #
@@ -78,3 +79,27 @@ if on_rackspace?
78
79
  create_objects
79
80
  get_rackspace_values
80
81
  end
82
+
83
+ # ----------------------------------------
84
+ # eucalyptus
85
+ # ----------------------------------------
86
+
87
+ # Is current cloud eucalyptus?
88
+ #
89
+ # === Return
90
+ # true:: If eucalyptus Hash is defined
91
+ # false:: Otherwise
92
+ def on_eucalyptus?
93
+ eucalyptus != nil
94
+ end
95
+
96
+ def get_eucalyptus_values
97
+ cloud[:public_ips] << eucalyptus['public_ipv4']
98
+ cloud[:private_ips] << eucalyptus['local_ipv4']
99
+ cloud[:provider] = "eucalyptus"
100
+ end
101
+
102
+ if on_eucalyptus?
103
+ create_objects
104
+ get_eucalyptus_values
105
+ end
@@ -20,7 +20,16 @@ provides "network", "counters/network"
20
20
 
21
21
  require 'scanf'
22
22
 
23
- network[:default_interface] = from("route -n get default \| grep interface: \| awk \'/: / \{print \$2\}\'")
23
+ from("route -n get default").split("\n").each do |line|
24
+ if line =~ /(\w+): ([\w\.]+)/
25
+ case $1
26
+ when "gateway"
27
+ network[:default_gateway] = $2
28
+ when "interface"
29
+ network[:default_interface] = $2
30
+ end
31
+ end
32
+ end
24
33
 
25
34
  def parse_media(media_string)
26
35
  media = Hash.new
@@ -1,6 +1,6 @@
1
1
  #
2
- # Author:: Bryan McLellan (btm@loftninjas.org)
3
- # Copyright:: Copyright (c) 2009 Bryan McLellan
2
+ # Author:: Kurt Yoder (ktyopscode@yoderhome.com)
3
+ # Copyright:: Copyright (c) 2010 Kurt Yoder
4
4
  # License:: Apache License, Version 2.0
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,44 +16,107 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
+ require "ohai/plugins/dmi_common"
20
+
19
21
  provides "dmi"
20
22
 
21
23
  # dmidecode does not return data without access to /dev/mem (or its equivalent)
22
24
 
23
25
  dmi Mash.new
24
- dmi[:version] = from("dmidecode --version")
25
-
26
- dmi[:bios] = Mash.new
27
- dmi[:bios][:vendor] = from("dmidecode -s bios-vendor")
28
- dmi[:bios][:version] = from("dmidecode -s bios-version")
29
- dmi[:bios][:release_date] = from("dmidecode -s bios-release-date")
30
-
31
- dmi[:system] = Mash.new
32
- dmi[:system][:manufacturer] = from("dmidecode -s system-manufacturer")
33
- dmi[:system][:product_name] = from("dmidecode -s system-product-name")
34
- dmi[:system][:version] = from("dmidecode -s system-version")
35
- dmi[:system][:serial_number] = from("dmidecode -s system-serial-number")
36
-
37
- dmi[:baseboard] = Mash.new
38
- dmi[:baseboard][:manufacturer] = from("dmidecode -s baseboard-manufacturer")
39
- dmi[:baseboard][:product_name] = from("dmidecode -s baseboard-product-name")
40
- dmi[:baseboard][:version] = from("dmidecode -s baseboard-version")
41
- dmi[:baseboard][:serial_number] = from("dmidecode -s baseboard-serial-number")
42
- dmi[:baseboard][:asset_tag] = from("dmidecode -s baseboard-asset-tag")
43
-
44
- dmi[:chassis] = Mash.new
45
- dmi[:chassis][:manufacturer] = from("dmidecode -s chassis-manufacturer")
46
- dmi[:chassis][:version] = from("dmidecode -s chassis-version")
47
- dmi[:chassis][:serial_number] = from("dmidecode -s chassis-serial-number")
48
- dmi[:chassis][:asset_tag] = from("dmidecode -s chassis-asset-tag")
49
-
50
- dmi[:processor] = Mash.new
51
- dmi[:processor][:manufacturer] = from("dmidecode -s processor-manufacturer")
52
- dmi[:processor][:version] = from("dmidecode -s processor-version")
53
-
54
- if dmi[:version].to_f >= 2.8
55
- dmi[:chassis][:type] = from("dmidecode -s chassis-type")
56
- dmi[:system][:uuid] = from("dmidecode -s system-uuid")
57
- dmi[:processor][:family] = from("dmidecode -s processor-family")
58
- dmi[:processor][:frequency] = from("dmidecode -s processor-frequency")
26
+
27
+ # all output lines should fall within one of these patterns
28
+ handle_line = /^Handle (0x[0-9A-F]{4}), DMI type (\d+), (\d+) bytes/
29
+ type_line = /^([A-Z][a-zA-Z ]+)( Information)?/
30
+ blank_line = /^\s*$/
31
+ data_line = /^\t([^:]+):(?: (.*))?/
32
+ extended_data_line = /^\t\t(.+)/
33
+ # first lines may contain some interesting information:
34
+ # # dmidecode 2.10
35
+ # SMBIOS 2.5 present.
36
+ # 5 structures occupying 352 bytes.
37
+ # Table at 0x000E1000.
38
+ dmidecode_version_line = /^# dmidecode (\d+\.\d+)/
39
+ smbios_version_line = /^SMBIOS (\d+\.\d+) present\./
40
+ structures_line = /^(\d+) structures occupying (\d+) bytes\./
41
+ table_location_line = /^Table at (0x[0-9A-E]+)\./
42
+
43
+ dmi_record = nil
44
+ field = nil
45
+
46
+ popen4("dmidecode") do |pid, stdin, stdout, stderr|
47
+ stdin.close
48
+
49
+ # ==== EXAMPLE RECORD: ====
50
+ #Handle 0x0000, DMI type 0, 24 bytes
51
+ #BIOS Information
52
+ # Vendor: American Megatrends Inc.
53
+ # Version: 080012
54
+ # ... similar lines trimmed
55
+ # Characteristics:
56
+ # ISA is supported
57
+ # PCI is supported
58
+ # ... similar lines trimmed
59
+ stdout.each do |line|
60
+ next if blank_line.match(line)
61
+
62
+ if dmidecode_version = dmidecode_version_line.match(line)
63
+ dmi[:dmidecode_version] = dmidecode_version[1]
64
+
65
+ elsif smbios_version = smbios_version_line.match(line)
66
+ dmi[:smbios_version] = smbios_version[1]
67
+
68
+ elsif structures = structures_line.match(line)
69
+ dmi[:structures] = Mash.new
70
+ dmi[:structures][:count] = structures[1]
71
+ dmi[:structures][:size] = structures[2]
72
+
73
+ elsif table_location = table_location_line.match(line)
74
+ dmi[:table_location] = table_location[1]
75
+
76
+ elsif handle = handle_line.match(line)
77
+ dmi_record = {:type => DMI.id_lookup(handle[2])}
78
+
79
+ dmi[dmi_record[:type]] = Mash.new unless dmi.has_key?(dmi_record[:type])
80
+ dmi[dmi_record[:type]][:all_records] = [] unless dmi[dmi_record[:type]].has_key?(:all_records)
81
+ dmi_record[:position] = dmi[dmi_record[:type]][:all_records].length
82
+ dmi[dmi_record[:type]][:all_records].push(Mash.new)
83
+ dmi[dmi_record[:type]][:all_records][dmi_record[:position]][:record_id] = handle[1]
84
+ dmi[dmi_record[:type]][:all_records][dmi_record[:position]][:size] = handle[2]
85
+ field = nil
86
+
87
+ elsif type = type_line.match(line)
88
+ if dmi_record == nil
89
+ Ohai::Log.debug("unexpected data line found before header; discarding:\n#{line}")
90
+ next
91
+ end
92
+ dmi[dmi_record[:type]][:all_records][dmi_record[:position]][:application_identifier] = type[1]
93
+
94
+ elsif data = data_line.match(line)
95
+ if dmi_record == nil
96
+ Ohai::Log.debug("unexpected data line found before header; discarding:\n#{line}")
97
+ next
98
+ end
99
+ dmi[dmi_record[:type]][:all_records][dmi_record[:position]][data[1]] = data[2]
100
+ field = data[1]
101
+
102
+ elsif extended_data = extended_data_line.match(line)
103
+ if dmi_record == nil
104
+ Ohai::Log.debug("unexpected extended data line found before header; discarding:\n#{line}")
105
+ next
106
+ end
107
+ if field == nil
108
+ Ohai::Log.debug("unexpected extended data line found outside data section; discarding:\n#{line}")
109
+ next
110
+ end
111
+ # overwrite "raw" value with a new Mash
112
+ 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'
113
+ dmi[dmi_record[:type]][:all_records][dmi_record[:position]][field][extended_data[1]] = nil
114
+
115
+ else
116
+ Ohai::Log.debug("unrecognized output line; discarding:\n#{line}")
117
+
118
+ end
119
+ end
59
120
  end
121
+
122
+ DMI.convenience_keys(dmi)
@@ -0,0 +1,117 @@
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
+ module DMI
20
+ # List of IDs and what they translate to
21
+ # from 'man 8 dmidecode'
22
+ # all-lowercase, all non-alphanumeric converted to '_'
23
+ # 128-255 are 'oem_data_[id]'
24
+ # Everything else is 'unknown'
25
+ IdToDescription = {
26
+ 0 => 'bios',
27
+ 1 => 'system',
28
+ 2 => 'base_board',
29
+ 3 => 'chassis',
30
+ 4 => 'processor',
31
+ 5 => 'memory_controller',
32
+ 6 => 'memory_module',
33
+ 7 => 'cache',
34
+ 8 => 'port_connector',
35
+ 9 => 'system_slots',
36
+ 10 => 'on_board_devices',
37
+ 11 => 'oem_strings',
38
+ 12 => 'system_configuration_options',
39
+ 13 => 'bios_language',
40
+ 14 => 'group_associations',
41
+ 15 => 'system_event_log',
42
+ 16 => 'physical_memory_array',
43
+ 17 => 'memory_device',
44
+ 18 => '32_bit_memory_error',
45
+ 19 => 'memory_array_mapped_address',
46
+ 20 => 'memory_device_mapped_address',
47
+ 21 => 'built_in_pointing_device',
48
+ 22 => 'portable_battery',
49
+ 23 => 'system_reset',
50
+ 24 => 'hardware_security',
51
+ 25 => 'system_power_controls',
52
+ 26 => 'voltage_probe',
53
+ 27 => 'cooling_device',
54
+ 28 => 'temperature_probe',
55
+ 29 => 'electrical_current_probe',
56
+ 30 => 'out_of_band_remote_access',
57
+ 31 => 'boot_integrity_services',
58
+ 32 => 'system_boot',
59
+ 33 => '64_bit_memory_error',
60
+ 34 => 'management_device',
61
+ 35 => 'management_device_component',
62
+ 36 => 'management_device_threshold_data',
63
+ 37 => 'memory_channel',
64
+ 38 => 'ipmi_device',
65
+ 39 => 'power_supply',
66
+ 126 => 'disabled_entries',
67
+ 127 => 'end_of_table_marker',
68
+ }
69
+
70
+ # look up DMI ID
71
+ def DMI.id_lookup(id)
72
+ begin
73
+ id = id.to_i
74
+ if (id >= 128) and (id <= 255)
75
+ id = "oem_data_#{id}"
76
+ elsif DMI::IdToDescription.has_key?(id)
77
+ id = DMI::IdToDescription[id]
78
+ else
79
+ Ohai::Log.debug("unrecognized header id; falling back to 'unknown'")
80
+ id = 'unknown'
81
+ end
82
+ rescue
83
+ Ohai::Log.debug("failed to look up id #{id}, returning unchanged")
84
+ id
85
+ end
86
+ end
87
+
88
+ # create simplified convenience access keys for each record type
89
+ # for single occurrences of one type, copy to top level all fields and values
90
+ # for multiple occurrences of same type, copy to top level all fields and values that are common to all records
91
+ def DMI.convenience_keys(dmi)
92
+ dmi.each{ |type, records|
93
+ in_common = Mash.new
94
+ next unless records.class.to_s == 'Mash'
95
+ next unless records.has_key?('all_records')
96
+ records[:all_records].each{ |record|
97
+ record.each{ |field, value|
98
+ next if value.class.to_s == 'Mash'
99
+ next if field.to_s == 'application_identifier'
100
+ next if field.to_s == 'size'
101
+ next if field.to_s == 'record_id'
102
+ translated = field.downcase.gsub(/[^a-z0-9]/, '_')
103
+ if in_common.has_key?(translated)
104
+ in_common[translated] = nil unless in_common[translated] == value
105
+ else
106
+ in_common[translated] = value
107
+ end
108
+ }
109
+ }
110
+ in_common.each{ |field, value|
111
+ next if value == nil
112
+ dmi[type][field] = value
113
+ }
114
+ }
115
+ end
116
+
117
+ end