diff options
-rw-r--r-- | Rakefile | 1 | ||||
-rw-r--r-- | lib/ohai/mixin/command.rb | 50 | ||||
-rw-r--r-- | lib/ohai/mixin/string.rb | 29 | ||||
-rw-r--r-- | lib/ohai/plugins/erlang.rb | 22 | ||||
-rw-r--r-- | lib/ohai/plugins/java.rb | 10 | ||||
-rw-r--r-- | lib/ohai/plugins/kernel.rb | 17 | ||||
-rw-r--r-- | lib/ohai/plugins/os.rb | 7 | ||||
-rw-r--r-- | lib/ohai/plugins/python.rb | 14 | ||||
-rw-r--r-- | lib/ohai/plugins/windows/filesystem.rb | 44 | ||||
-rw-r--r-- | lib/ohai/plugins/windows/hostname.rb | 25 | ||||
-rw-r--r-- | lib/ohai/plugins/windows/kernel.rb | 75 | ||||
-rw-r--r-- | lib/ohai/plugins/windows/network.rb | 114 | ||||
-rw-r--r-- | lib/ohai/plugins/windows/platform.rb | 26 | ||||
-rw-r--r-- | lib/ohai/system.rb | 1 |
14 files changed, 382 insertions, 53 deletions
@@ -24,6 +24,7 @@ spec = Gem::Specification.new do |s| s.add_dependency "json" s.add_dependency "extlib" + s.add_dependency "systemu" s.bindir = "bin" s.executables = %w(ohai) diff --git a/lib/ohai/mixin/command.rb b/lib/ohai/mixin/command.rb index 77de69f7..4f909cba 100644 --- a/lib/ohai/mixin/command.rb +++ b/lib/ohai/mixin/command.rb @@ -25,6 +25,7 @@ require 'ohai/log' require 'tmpdir' require 'fcntl' require 'etc' +require 'systemu' module Ohai module Mixin @@ -40,24 +41,7 @@ module Ohai stdout_string = nil stderr_string = nil - - exec_processing_block = lambda do |pid, stdin, stdout, stderr| - stdin.close - - stdout_string = stdout.gets(nil) - if stdout_string - Ohai::Log.debug("---- Begin #{args[:command]} STDOUT ----") - Ohai::Log.debug(stdout_string.strip) - Ohai::Log.debug("---- End #{args[:command]} STDOUT ----") - end - stderr_string = stderr.gets(nil) - if stderr_string - Ohai::Log.debug("---- Begin #{args[:command]} STDERR ----") - Ohai::Log.debug(stderr_string.strip) - Ohai::Log.debug("---- End #{args[:command]} STDERR ----") - end - end - + args[:cwd] ||= Dir.tmpdir unless File.directory?(args[:cwd]) raise Ohai::Exception::Exec, "#{args[:cwd]} does not exist or is not a directory" @@ -68,26 +52,44 @@ module Ohai if args[:timeout] begin Timeout.timeout(args[:timeout]) do - status = popen4(args[:command], args, &exec_processing_block) + status, stdout_string, stderr_string = systemu(args[:command]) end rescue Exception => e Ohai::Log.error("#{args[:command_string]} exceeded timeout #{args[:timeout]}") raise(e) end else - status = popen4(args[:command], args, &exec_processing_block) + status, stdout_string, stderr_string = systemu(args[:command]) + end + + # systemu returns 42 when it hits unexpected errors + if status.exitstatus == 42 and stderr_string == "" + stderr_string = "Failed to run: #{args[:command]}, assuming command not found" + Ohai::Log.debug(stderr_string) + end + + if stdout_string + Ohai::Log.debug("---- Begin #{args[:command]} STDOUT ----") + Ohai::Log.debug(stdout_string.strip) + Ohai::Log.debug("---- End #{args[:command]} STDOUT ----") + end + if stderr_string + Ohai::Log.debug("---- Begin #{args[:command]} STDERR ----") + Ohai::Log.debug(stderr_string.strip) + Ohai::Log.debug("---- End #{args[:command]} STDERR ----") end args[:returns] ||= 0 - if status.exitstatus != args[:returns] - raise Ohai::Exception::Exec, "#{args[:command_string]} returned #{status.exitstatus}, expected #{args[:returns]}" + args[:no_status_check] ||= false + if status.exitstatus != args[:returns] and not args[:no_status_check] + raise Ohai::Exception::Exec, "#{args[:command]} returned #{status.exitstatus}, expected #{args[:returns]}" else Ohai::Log.debug("Ran #{args[:command_string]} (#{args[:command]}) returned #{status.exitstatus}") end end return status, stdout_string, stderr_string end - + module_function :run_command # This is taken directly from Ara T Howard's Open4 library, and then @@ -195,4 +197,4 @@ module Ohai module_function :popen4 end end -end
\ No newline at end of file +end diff --git a/lib/ohai/mixin/string.rb b/lib/ohai/mixin/string.rb new file mode 100644 index 00000000..169711a2 --- /dev/null +++ b/lib/ohai/mixin/string.rb @@ -0,0 +1,29 @@ +# +# Author:: James Gartrell (<jgartrel@gmail.com>) +# Copyright:: Copyright (c) 2009 Opscode, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +class String + # Add string function to handle WMI property conversion to json hash keys + # Makes an underscored, lowercase form from the expression in the string. + # underscore will also change ’::’ to ’/’ to convert namespaces to paths. + # This should implement the same functionality as underscore method in + # ActiveSupport::CoreExtensions::String::Inflections + def wmi_underscore + self.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). + gsub(/([a-z\d])([A-Z])/,'\1_\2').tr("-", "_").downcase + end +end diff --git a/lib/ohai/plugins/erlang.rb b/lib/ohai/plugins/erlang.rb index 6c58589f..23343937 100644 --- a/lib/ohai/plugins/erlang.rb +++ b/lib/ohai/plugins/erlang.rb @@ -20,18 +20,18 @@ require_plugin "languages" output = nil erlang = Mash.new -status = popen4("erl +V") do |pid, stdin, stdout, stderr| - stdin.close - output = stderr.gets.split if stderr - options = output[1] - options.gsub!(/(\(|\))/, '') - erlang[:version] = output[5] - erlang[:options] = options.split(',') - erlang[:emulator] = output[2].gsub!(/(\(|\))/, '') -end +status, stdout, stderr = run_command(:no_status_check => true, :command => "erl +V") if status == 0 - if erlang[:version] and erlang[:options] and erlang[:emulator] - languages[:erlang] = erlang + output = stderr.split + if output.length >= 6 + options = output[1] + options.gsub!(/(\(|\))/, '') + erlang[:version] = output[5] + erlang[:options] = options.split(',') + erlang[:emulator] = output[2].gsub!(/(\(|\))/, '') + if erlang[:version] and erlang[:options] and erlang[:emulator] + languages[:erlang] = erlang + end end end diff --git a/lib/ohai/plugins/java.rb b/lib/ohai/plugins/java.rb index b7cfab1f..a6777e78 100644 --- a/lib/ohai/plugins/java.rb +++ b/lib/ohai/plugins/java.rb @@ -19,17 +19,17 @@ require_plugin "languages" java = Mash.new -status = popen4("java -version") do |pid, stdin, stdout, stderr| - stdin.close - stderr.each do |line| + +status, stdout, stderr = run_command(:no_status_check => true, :command => "java -version") + +if status == 0 + stderr.split("\n").each do |line| case line when /java version \"([0-9\.\_]+)\"/: java[:version] = $1 when /^(.+Runtime Environment.*) \(build (.+)\)$/: java[:runtime] = { "name" => $1, "build" => $2 } when /^(.+ Client VM) \(build (.+)\)$/: java[:hotspot] = { "name" => $1, "build" => $2 } end end -end -if status == 0 languages[:java] = java if java[:version] end diff --git a/lib/ohai/plugins/kernel.rb b/lib/ohai/plugins/kernel.rb index 514b4294..b178751c 100644 --- a/lib/ohai/plugins/kernel.rb +++ b/lib/ohai/plugins/kernel.rb @@ -16,9 +16,16 @@ # limitations under the License. # +require_plugin 'ruby' + kernel Mash.new -kernel[:name] = from("uname -s") -kernel[:release] = from("uname -r") -kernel[:version] = from("uname -v") -kernel[:machine] = from("uname -m") -kernel[:modules] = Mash.new +case languages[:ruby][:host_os] +when /mswin/ + require_plugin "windows::kernel" +else + kernel[:name] = from("uname -s") + kernel[:release] = from("uname -r") + kernel[:version] = from("uname -v") + kernel[:machine] = from("uname -m") + kernel[:modules] = Mash.new +end diff --git a/lib/ohai/plugins/os.rb b/lib/ohai/plugins/os.rb index 114f75d2..b133062d 100644 --- a/lib/ohai/plugins/os.rb +++ b/lib/ohai/plugins/os.rb @@ -26,6 +26,13 @@ when /linux/ os "linux" when /freebsd(.+)$/ os "freebsd" +when /mswin/ + # After long discussion in IRC the "powers that be" have come to a concensus + # that there is no other Windows platforms exist that were not based on the + # Windows_NT kernel, so we herby decree that "windows" will refer to all + # platforms built upon the Windows_NT kernel and have access to win32 or win64 + # subsystems. + os "windows" else os languages[:ruby][:host_os] end diff --git a/lib/ohai/plugins/python.rb b/lib/ohai/plugins/python.rb index c2e63745..fbc4fc75 100644 --- a/lib/ohai/plugins/python.rb +++ b/lib/ohai/plugins/python.rb @@ -20,16 +20,14 @@ require_plugin "languages" output = nil python = Mash.new -status = popen4("python -c \"import sys; print sys.version\"") do |pid, stdin, stdout, stderr| - stdin.close - output_string = stdout.gets - if output_string - output = output_string.split - python[:version] = output[0] +status, stdout, stderr = run_command(:no_status_check => true, :command => "python -c \"import sys; print sys.version\"") + +if status == 0 + output = stdout.split + python[:version] = output[0] + if output.length >= 6 python[:builddate] = "%s %s %s %s" % [output[2],output[3],output[4],output[5].gsub!(/\)/,'')] end -end -if status == 0 languages[:python] = python if python[:version] and python[:builddate] end diff --git a/lib/ohai/plugins/windows/filesystem.rb b/lib/ohai/plugins/windows/filesystem.rb new file mode 100644 index 00000000..192bca25 --- /dev/null +++ b/lib/ohai/plugins/windows/filesystem.rb @@ -0,0 +1,44 @@ +# +# Author:: James Gartrell (<jgartrel@gmail.com>) +# Copyright:: Copyright (c) 2009 Opscode, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'ruby-wmi' + +fs = Mash.new +ld_info = Mash.new + +# Grab filesystem data from WMI +# Note: we should really be parsing Win32_Volume and Win32_Mapped drive +disks = WMI::Win32_LogicalDisk.find(:all) +disks.each do |disk| + filesystem = disk.DeviceID + fs[filesystem] = Mash.new + ld_info[filesystem] = Mash.new + disk.properties_.each do |p| + ld_info[filesystem][p.name.wmi_underscore.to_sym] = disk[p.name] + end + fs[filesystem][:kb_size] = ld_info[filesystem][:size].to_i / 1000 + fs[filesystem][:kb_available] = ld_info[filesystem][:free_space].to_i / 1000 + fs[filesystem][:kb_used] = fs[filesystem][:kb_size].to_i - fs[filesystem][:kb_available].to_i + fs[filesystem][:percent_used] = fs[filesystem][:kb_used].to_i * 100 / fs[filesystem][:kb_size].to_i + fs[filesystem][:mount] = ld_info[filesystem][:name] + fs[filesystem][:fs_type] = ld_info[filesystem][:file_system].downcase + fs[filesystem][:volume_name] = ld_info[filesystem][:volume_name] +end + +# Set the filesystem data +filesystem fs diff --git a/lib/ohai/plugins/windows/hostname.rb b/lib/ohai/plugins/windows/hostname.rb new file mode 100644 index 00000000..f68560b4 --- /dev/null +++ b/lib/ohai/plugins/windows/hostname.rb @@ -0,0 +1,25 @@ +# +# Author:: James Gartrell (<jgartrel@gmail.com>) +# Copyright:: Copyright (c) 2009 Opscode, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'ruby-wmi' +require 'socket' + +host = WMI::Win32_ComputerSystem.find(:first) +hostname "#{host.Name}" +#hostname "#{Socket.gethostname}" +fqdn "#{Socket.gethostbyname(Socket.gethostname).first}" diff --git a/lib/ohai/plugins/windows/kernel.rb b/lib/ohai/plugins/windows/kernel.rb new file mode 100644 index 00000000..2f487847 --- /dev/null +++ b/lib/ohai/plugins/windows/kernel.rb @@ -0,0 +1,75 @@ +# +# Author:: James Gartrell (<jgartrel@gmail.com>) +# Copyright:: Copyright (c) 2009 Opscode, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'ruby-wmi' + +def machine_lookup(sys_type) + return "i386" if sys_type.eql?("X86-based PC") + return "x86_64" if sys_type.eql?("x64-based PC") + sys_type +end + +def os_lookup(sys_type) + return "Unknown" if sys_type.to_s.eql?("0") + return "Other" if sys_type.to_s.eql?("1") + return "MSDOS" if sys_type.to_s.eql?("14") + return "WIN3x" if sys_type.to_s.eql?("15") + return "WIN95" if sys_type.to_s.eql?("16") + return "WIN98" if sys_type.to_s.eql?("17") + return "WINNT" if sys_type.to_s.eql?("18") + return "WINCE" if sys_type.to_s.eql?("19") + return nil +end + +host = WMI::Win32_OperatingSystem.find(:first) +kernel[:os_info] = Mash.new +host.properties_.each do |p| + kernel[:os_info][p.name.wmi_underscore.to_sym] = host[p.name] +end + +kernel[:name] = "#{kernel[:os_info][:caption]}" +kernel[:release] = "#{kernel[:os_info][:version]}" +kernel[:version] = "#{kernel[:os_info][:version]} #{kernel[:os_info][:csd_version]} Build #{kernel[:os_info][:build_number]}" +kernel[:os] = os_lookup(kernel[:os_info][:os_type]) || languages[:ruby][:host_os] + +host = WMI::Win32_ComputerSystem.find(:first) +kernel[:cs_info] = Mash.new +host.properties_.each do |p| + kernel[:cs_info][p.name.wmi_underscore.to_sym] = host[p.name] +end + +kernel[:machine] = machine_lookup("#{kernel[:cs_info][:system_type]}") + +kext = Mash.new +pnp_drivers = Mash.new + +drivers = WMI::Win32_PnPSignedDriver.find(:all) +drivers.each do |driver| + pnp_drivers[driver.DeviceID] = Mash.new + driver.properties_.each do |p| + pnp_drivers[driver.DeviceID][p.name.wmi_underscore.to_sym] = driver[p.name] + end + if driver.DeviceName + kext[driver.DeviceName] = pnp_drivers[driver.DeviceID] + kext[driver.DeviceName][:version] = pnp_drivers[driver.DeviceID][:driver_version] + kext[driver.DeviceName][:date] = pnp_drivers[driver.DeviceID][:driver_date] ? pnp_drivers[driver.DeviceID][:driver_date].to_s[0..7] : nil + end +end + +kernel[:pnp_drivers] = pnp_drivers +kernel[:modules] = kext diff --git a/lib/ohai/plugins/windows/network.rb b/lib/ohai/plugins/windows/network.rb new file mode 100644 index 00000000..e1e815c5 --- /dev/null +++ b/lib/ohai/plugins/windows/network.rb @@ -0,0 +1,114 @@ +# +# Author:: James Gartrell (<jgartrel@gmail.com>) +# Copyright:: Copyright (c) 2008 Opscode, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require 'ruby-wmi' + +def encaps_lookup(encap) + return "Ethernet" if encap.eql?("Ethernet 802.3") + encap +end + +def derive_bcast(ipaddr, ipmask, zero_bcast = false) + begin + ipaddr_int = ipaddr.split(".").collect{ |x| x.to_i}.pack("C4").unpack("N").first + ipmask_int = ipmask.split(".").collect{ |x| x.to_i}.pack("C4").unpack("N").first + if zero_bcast + bcast_int = ipaddr_int & ipmask_int + else + bcast_int = ipaddr_int | 2 ** 32 - ipmask_int - 1 + end + bcast = [bcast_int].pack("N").unpack("C4").join(".") + return bcast + rescue + return nil + end +end + +iface = Mash.new +iface_config = Mash.new +iface_instance = Mash.new + +adapters = WMI::Win32_NetworkAdapterConfiguration.find(:all) +adapters.each do |adapter| + i = adapter.Index + iface_config[i] = Mash.new + adapter.properties_.each do |p| + iface_config[i][p.name.wmi_underscore.to_sym] = adapter[p.name] + end +end + +adapters = WMI::Win32_NetworkAdapter.find(:all) +adapters.each do |adapter| + i = adapter.Index + iface_instance[i] = Mash.new + adapter.properties_.each do |p| + iface_instance[i][p.name.wmi_underscore.to_sym] = adapter[p.name] + end +end + +iface_instance.keys.each do |i| + if iface_config[i][:ip_enabled] and iface_instance[i][:net_connection_id] and iface_instance[i][:interface_index] + cint = sprintf("0x%X", iface_instance[i][:interface_index]) + iface[cint] = Mash.new + iface[cint][:configuration] = iface_config[i] + iface[cint][:instance] = iface_instance[i] + + iface[cint][:counters] = Mash.new + iface[cint][:addresses] = Mash.new + iface[cint][:configuration][:ip_address].each_index do |i| + begin + if iface[cint][:configuration][:ip_address][i] =~ /./ + iface[cint][:addresses][iface[cint][:configuration][:ip_address][i]] = { + "family" => "inet", + "netmask" => iface[cint][:configuration][:ip_subnet][i], + "broadcast" => derive_bcast( iface[cint][:configuration][:ip_address][i], + iface[cint][:configuration][:ip_subnet][i], + iface[cint][:configuration][:ip_use_zero_broadcast] + ) + } + end + rescue + end + end + iface[cint][:configuration][:mac_address].each do |mac_addr| + iface[cint][:addresses][mac_addr] = { + "family" => "lladdr" + } + end + iface[cint][:mtu] = iface[cint][:configuration][:mtu] + iface[cint][:type] = iface[cint][:instance][:adapter_type] + iface[cint][:arp] = {} + iface[cint][:encapsulation] = encaps_lookup(iface[cint][:instance][:adapter_type]) + end +end + +cint=nil +from("arp /a").split("\n").each do |line| + if line == "" + cint = nil + end + if line =~ /^Interface:\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+[-]+\s+(0x\d+)/ + cint = $2 + end + next unless iface[cint] + if line =~ /^\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+([a-fA-F0-9\:-]+)/ + iface[cint][:arp][$1] = $2.gsub("-",":").downcase + end +end + +network["interfaces"] = iface diff --git a/lib/ohai/plugins/windows/platform.rb b/lib/ohai/plugins/windows/platform.rb new file mode 100644 index 00000000..c40675aa --- /dev/null +++ b/lib/ohai/plugins/windows/platform.rb @@ -0,0 +1,26 @@ +# +# Author:: James Gartrell (<jgartrel@gmail.com>) +# Copyright:: Copyright (c) 2009 Opscode, Inc. +# License:: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# After long discussion in IRC the "powers that be" have come to a concensus +# that there is no other Windows platforms exist that were not based on the +# Windows_NT kernel, so we herby decree that "windows" will refer to all +# platforms built upon the Windows_NT kernel and have access to win32 or win64 +# subsystems. +platform os +platform_version kernel['release'] + diff --git a/lib/ohai/system.rb b/lib/ohai/system.rb index ed80c59d..90adedd7 100644 --- a/lib/ohai/system.rb +++ b/lib/ohai/system.rb @@ -21,6 +21,7 @@ require 'extlib' require 'ohai/log' require 'ohai/mixin/from_file' require 'ohai/mixin/command' +require 'ohai/mixin/string' require 'json' module Ohai |