# frozen_string_literal: true # # Author:: Adam Jacob () # Author:: Benjamin Black () # Author:: Bryan McLellan () # Author:: Claire McQuin () # Author:: James Gartrell () # Copyright:: Copyright (c) Chef Software Inc. # Copyright:: Copyright (c) 2009 Bryan McLellan # 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. # Ohai.plugin(:Kernel) do provides "kernel", "kernel/modules" # common initial kernel attribute values # @return [Mash] basic kernel properties from uname def init_kernel kernel Mash.new [["uname -s", :name], ["uname -r", :release], ["uname -v", :version], ["uname -m", :machine], ["uname -p", :processor]].each do |cmd, property| so = shell_out(cmd) kernel[property] = so.stdout.strip end kernel end # common *bsd code for collecting modules data # @return [Mash] def bsd_modules(path) modules = Mash.new so = shell_out(Ohai.abs_path(path).to_s) so.stdout.lines do |line| # 1 7 0xc0400000 97f830 kernel if line =~ /(\d+)\s+(\d+)\s+([0-9a-fx]+)\s+([0-9a-fx]+)\s+([a-zA-Z0-9\_]+)/ modules[$5] = { size: $4, refcount: $2 } end end modules end # given the OperatingSystemSKU value from WMI's Win32_OperatingSystem class # https://msdn.microsoft.com/en-us/library/aa394239(v=vs.85).aspx # return if we're on a Server Core installation # @param [String] sku OperatingSystemSKU value from Win32_OperatingSystem # @return [boolean] def server_core?(sku) return true if [ 12, # Server Datacenter Core 39, # Server Datacenter without Hyper-V Core 14, # Server Enterprise Core 41, # Server Enterprise without Hyper-V Core 13, # Server Standard Core 40, # Server Standard without Hyper-V Core 63, # Small Business Server Premium Core 53, # Server Solutions Premium Core 46, # Storage Server Enterprise Core 43, # Storage Server Express Core 44, # Storage Server Standard Core 45, # Storage Server Workgroup Core 29, # Web Server Core ].include?(sku) false end # given the SystemType value from WMI's Win32_ComputerSystem class # https://msdn.microsoft.com/en-us/library/aa394102(v=vs.85).aspx # return the architecture type # @param [String] sys_type SystemType value from Win32_ComputerSystem # @return [String] x86_64 or i386 def arch_lookup(sys_type) return "x86_64" if sys_type == "x64-based PC" return "i386" if sys_type == "X86-based PC" sys_type end # given the ProductType value from WMI's Win32_OperatingSystem class # https://msdn.microsoft.com/en-us/library/aa394239(v=vs.85).aspx # return either workstation or server # @param [Integer] type ProductType value from Win32_OperatingSystem # @return [String] Workstation or Server def product_type_decode(type) return "Workstation" if type == 1 "Server" end # decode the OSType field from WMI Win32_OperatingSystem class # https://msdn.microsoft.com/en-us/library/aa394239(v=vs.85).aspx # @param [Integer] sys_type OSType value from Win32_OperatingSystem # @return [String] the human consumable OS type value def os_type_decode(sys_type) case sys_type when 18 then "WINNT" # most likely so first when 0 then "Unknown" when 1 then "Other" when 14 then "MSDOS" when 15 then "WIN3x" when 16 then "WIN95" when 17 then "WIN98" when 19 then "WINCE" end end # decode the PCSystemType field from WMI Win32_OperatingSystem class # https://msdn.microsoft.com/en-us/library/aa394239(v=vs.85).aspx # @param [Integer] type the integer value from PCSystemType # @return [String] the human consumable OS type value def pc_system_type_decode(type) case type when 4 then "Enterprise Server" # most likely so first when 0 then "Unspecified" when 1 then "Desktop" when 2 then "Mobile" when 3 then "Workstation" when 5 then "SOHO Server" when 6 then "Appliance PC" when 7 then "Performance Server" when 8 then "Maximum" end end # see if a WMI name is in the blocked list so we can avoid writing # out useless data to ohai # # @param [String] name the wmi name to check # @return [Boolean] is the wmi name in the blocked list def blocked_wmi_name?(name) [ "creation_class_name", # this is just the wmi name "cs_creation_class_name", # this is just the wmi name "oem_logo_bitmap", # this is the entire OEM bitmap file "total_swap_space_size", # already in memory plugin "total_virtual_memory_size", # already in memory plugin "total_virtual_memory_size", # already in memory plugin "free_physical_memory", # already in memory plugin "free_space_in_paging_files", # already in memory plugin "free_virtual_memory", # already in memory plugin ].include?(name) end collect_data(:target) do # intentionally left blank end collect_data(:default) do kernel init_kernel end collect_data(:darwin) do kernel init_kernel kernel[:os] = kernel[:name] so = shell_out("sysctl -n hw.optional.x86_64") if so.stdout.strip.to_i == 1 kernel[:machine] = "x86_64" end modules = Mash.new so = shell_out("kextstat -k -l") so.stdout.lines do |line| if line =~ /(\d+)\s+(\d+)\s+0x[0-9a-f]+\s+0x([0-9a-f]+)\s+0x[0-9a-f]+\s+([a-zA-Z0-9\.]+) \(([0-9\.]+)\)/ modules[$4] = { version: $5, size: $3.hex, index: $1, refcount: $2 } end end kernel[:modules] = modules end collect_data(:freebsd, :dragonflybsd) do kernel init_kernel kernel[:os] = kernel[:name] so = shell_out("uname -i") kernel[:ident] = so.stdout.strip so = shell_out("sysctl kern.securelevel") kernel[:securelevel] = so.stdout.split($/).select { |e| e =~ /kern.securelevel: (.+)$/ } kernel[:modules] = bsd_modules("/sbin/kldstat") end collect_data(:linux) do kernel init_kernel so = shell_out("uname -o") kernel[:os] = so.stdout.strip modules = Mash.new so = shell_out("env lsmod") so.stdout.lines do |line| if line =~ /([a-zA-Z0-9\_]+)\s+(\d+)\s+(\d+)/ modules[$1] = { size: $2, refcount: $3 } # Making sure to get the module version that has been loaded if file_exist?("/sys/module/#{$1}/version") version = file_read("/sys/module/#{$1}/version").chomp.strip modules[$1]["version"] = version unless version.empty? end end end kernel[:modules] = modules end collect_data(:netbsd, :openbsd) do kernel init_kernel kernel[:os] = kernel[:name] so = shell_out("sysctl kern.securelevel") kernel[:securelevel] = so.stdout.split($/).select { |e| e =~ /kern.securelevel:\ (.+)$/ } kernel[:modules] = bsd_modules("/usr/bin/modstat") end collect_data(:solaris2) do kernel init_kernel so = shell_out("uname -s") kernel[:os] = so.stdout.strip so = file_open("/etc/release", &:gets) md = /(?\d.*\d)/.match(so) kernel[:update] = md[:update] if md modules = Mash.new so = shell_out("modinfo") # EXAMPLE: # Id Loadaddr Size Info Rev Module Name # 6 1180000 4623 1 1 specfs (filesystem for specfs) module_description = /\s*(\d+)\s+([a-f\d]+)\s+([a-f\d]+)\s+(?:[\-\d]+)\s+(?:\d+)\s+(\S+)\s+\((.+)\)$/ so.stdout.lines do |line| if ( mod = module_description.match(line) ) modules[mod[4]] = { id: mod[1].to_i, loadaddr: mod[2], size: mod[3].to_i(16), description: mod[5] } end end kernel[:modules] = modules end collect_data(:windows) do require "win32ole" unless defined?(WIN32OLE) require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) WIN32OLE.codepage = WIN32OLE::CP_UTF8 wmi = WmiLite::Wmi.new kernel Mash.new host = wmi.first_of("Win32_OperatingSystem") kernel[:os_info] = Mash.new host.wmi_ole_object.properties_.each do |p| next if blocked_wmi_name?(p.name.wmi_underscore) kernel[:os_info][p.name.wmi_underscore.to_sym] = host[p.name.downcase] end kernel[:name] = (kernel[:os_info][:caption]).to_s kernel[:release] = (kernel[:os_info][:version]).to_s kernel[:version] = "#{kernel[:os_info][:version]} #{kernel[:os_info][:csd_version]} Build #{kernel[:os_info][:build_number]}" kernel[:os] = os_type_decode(kernel[:os_info][:os_type]) || languages[:ruby][:host_os] kernel[:product_type] = product_type_decode(kernel[:os_info][:product_type]) kernel[:server_core] = server_core?(kernel[:os_info][:operating_system_sku]) kernel[:cs_info] = Mash.new host = wmi.first_of("Win32_ComputerSystem") host.wmi_ole_object.properties_.each do |p| next if blocked_wmi_name?(p.name.wmi_underscore) kernel[:cs_info][p.name.wmi_underscore.to_sym] = host[p.name.downcase] end kernel[:machine] = arch_lookup((kernel[:cs_info][:system_type]).to_s) kernel[:system_type] = pc_system_type_decode(kernel[:cs_info][:pc_system_type]) end end