ohai 0.5.8 → 0.6.0.beta.0

Sign up to get free protection for your applications and to get access to all the features.
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