ohai-16.13.0/0000755000175100017510000000000014034105661011630 5ustar pravipraviohai-16.13.0/bin/0000755000175100017510000000000014034105661012400 5ustar pravipraviohai-16.13.0/bin/ohai0000755000175100017510000000162014034105661013245 0ustar pravipravi#!/usr/bin/env ruby # frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) 2008-2016 Chef Software, 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. # # if we're in a source code checkout, we want to run the code from that. $:.unshift File.expand_path("../lib", __dir__) require "ohai/application" Ohai::Application.new.run ohai-16.13.0/ohai.gemspec0000644000175100017510000000250314034105661014115 0ustar pravipravi# frozen_string_literal: true $:.unshift File.expand_path("lib", __dir__) require "ohai/version" Gem::Specification.new do |s| s.name = "ohai" s.version = Ohai::VERSION s.summary = "Ohai profiles your system and emits JSON" s.description = s.summary s.license = "Apache-2.0" s.author = "Adam Jacob" s.email = "adam@chef.io" s.homepage = "https://github.com/chef/ohai/" s.required_ruby_version = ">= 2.6" s.add_dependency "chef-config", ">= 12.8", "< 17" s.add_dependency "chef-utils", ">= 16.0", "< 17" s.add_dependency "ffi", "~> 1.9" s.add_dependency "ffi-yajl", "~> 2.2" s.add_dependency "ipaddress" s.add_dependency "mixlib-cli", ">= 1.7.0" # 1.7+ needed to support passing multiple options s.add_dependency "mixlib-config", ">= 2.0", "< 4.0" s.add_dependency "mixlib-log", ">= 2.0.1", "< 4.0" s.add_dependency "mixlib-shellout", ">= 2.0", "< 4.0" s.add_dependency "plist", "~> 3.1" s.add_dependency "train-core" s.add_dependency "wmi-lite", "~> 1.0" # Note for ohai developers: If chef-config causes you grief, try: # bundle install --with development # this should work as long as chef is a development dependency in Gemfile. # s.bindir = "bin" s.executables = %w{ohai} s.require_path = "lib" s.files = %w{LICENSE Gemfile} + Dir.glob("*.gemspec") + Dir.glob("lib/**/*") end ohai-16.13.0/lib/0000755000175100017510000000000014034105661012376 5ustar pravipraviohai-16.13.0/lib/ohai.rb0000644000175100017510000000150314034105661013642 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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_relative "ohai/version" require_relative "ohai/config" require_relative "ohai/system" require_relative "ohai/exception" ohai-16.13.0/lib/ohai/0000755000175100017510000000000014034105661013316 5ustar pravipraviohai-16.13.0/lib/ohai/util/0000755000175100017510000000000014034105661014273 5ustar pravipraviohai-16.13.0/lib/ohai/util/win32.rb0000644000175100017510000000254314034105661015566 0ustar pravipravi# frozen_string_literal: true # Author:: Adam Edwards () # # Copyright:: Copyright (c) Chef Software 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. module Ohai module Util module Win32 if RUBY_PLATFORM.match?(/mswin|mingw|windows/) require "ffi" unless defined?(FFI) extend FFI::Library ffi_lib "advapi32" attach_function :lookup_account_sid, :LookupAccountSidA, %i{pointer pointer pointer pointer pointer pointer pointer}, :long attach_function :convert_string_sid_to_sid, :ConvertStringSidToSidA, %i{pointer pointer}, :long ffi_lib "kernel32" attach_function :local_free, :LocalFree, [ :pointer ], :long attach_function :get_last_error, :GetLastError, [], :long end end end end ohai-16.13.0/lib/ohai/util/ip_helper.rb0000644000175100017510000000320214034105661016564 0ustar pravipravi# frozen_string_literal: true # # Author:: Stafford Brunk () # 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. module Ohai module Util module IpHelper require "ipaddress" unless defined?(IPAddress) # Corresponding to RFC 4192 + RFC 4193 IPV6_LINK_LOCAL_UNICAST_BLOCK = IPAddress("fe80::/10") IPV6_PRIVATE_ADDRESS_BLOCK = IPAddress("fc00::/7") def private_address?(addr) ip = IPAddress(addr) if ip.respond_to? :private? ip.private? else IPV6_LINK_LOCAL_UNICAST_BLOCK.include?(ip) || IPV6_PRIVATE_ADDRESS_BLOCK.include?(ip) end end alias unique_local_address? private_address? def public_address?(addr) !private_address?(addr) end # The ipaddress gem doesn't implement loopback? # for IPv4 addresses # https://github.com/bluemonk/ipaddress/issues/25 def loopback?(addr) ip = IPAddress(addr) if ip.respond_to? :loopback? ip.loopback? else IPAddress("127.0.0.0/8").include? ip end end end end end ohai-16.13.0/lib/ohai/util/file_helper.rb0000644000175100017510000000037314034105661017101 0ustar pravipravi# frozen_string_literal: true $stderr.puts "WARN: Ohai::Util::FileHelper is deprecated, please use Ohai::Mixin::Which or remove if the reference is unnecessary" require_relative "../mixin/which" module Ohai::Util FileHelper = Ohai::Mixin::Which end ohai-16.13.0/lib/ohai/mash.rb0000644000175100017510000000153114034105661014573 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software 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 "chef-utils/mash" unless defined?(ChefUtils::Mash) # For historical reasons we inject Mash directly into the top level class namespace Mash = ChefUtils::Mash unless defined?(Mash) ohai-16.13.0/lib/ohai/train_transport.rb0000644000175100017510000000165714034105661017105 0ustar pravipravi# frozen_string_literal: true # Author:: Bryan McLellan # Copyright:: Copyright (c) Chef Software 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 "chef-config/mixin/train_transport" unless defined?(ChefConfig::Mixin::TrainTransport) module Ohai class TrainTransport include ChefConfig::Mixin::TrainTransport def config Ohai::Config end end end ohai-16.13.0/lib/ohai/application.rb0000644000175100017510000001273014034105661016151 0ustar pravipravi# frozen_string_literal: true # # Author:: Mathieu Sauve-Frankel # Copyright:: Copyright (c) 2009 Mathieu Sauve-Frankel. # 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 "chef-config/path_helper" require "chef-config/workstation_config_loader" require_relative "../ohai" require_relative "log" unless defined?(Ohai::Log) require "mixlib/cli" unless defined?(Mixlib::CLI) require "benchmark" unless defined?(Benchmark) # The Application class is what is called by the Ohai CLI binary. It handles: # - CLI options and attribute arguments # - Collecting data via the Ohai::System class # - Printing the results returned via the Ohai::System class class Ohai::Application include Mixlib::CLI option :config_file, short: "-c CONFIG", long: "--config CONFIG", description: "A configuration file to use", proc: lambda { |path| File.expand_path(path, Dir.pwd) } option :directory, short: "-d DIRECTORY", long: "--directory DIRECTORY", description: "A directory to add to the Ohai plugin search path. If passing multiple directories use this option more than once.", proc: lambda { |path, path_array| (path_array ||= []) << Ohai::Config.platform_specific_path(path) path_array } option :log_level, short: "-l LEVEL", long: "--log_level LEVEL", description: "Set the log level (debug, info, warn, error, fatal)", proc: lambda { |l| l.to_sym } option :log_location, short: "-L LOGLOCATION", long: "--logfile LOGLOCATION", description: "Set the log file location, defaults to STDOUT - recommended for daemonizing", proc: nil option :target, short: "-t TARGET", long: "--target TARGET", description: "Target Ohai against a remote system or device", proc: lambda { |target| Ohai::Log.warn "-- EXPERIMENTAL -- Target mode activated -- EXPERIMENTAL --" target } option :help, short: "-h", long: "--help", description: "Show this message", on: :tail, boolean: true, show_options: true, exit: 0 option :version, short: "-v", long: "--version", description: "Show Ohai version", boolean: true, proc: lambda { |v| puts "Ohai: #{::Ohai::VERSION}" }, exit: 0 # the method called by the Ohai binary to actually run the whole application # # @return void def run elapsed = Benchmark.realtime do configure_ohai run_application end Ohai::Log.debug("Ohai took #{elapsed} total seconds to run.") end # parses the CLI options, loads the config file if present, and initializes logging # # @return void def configure_ohai @attributes = parse_options @attributes = nil if @attributes.empty? load_workstation_config merge_configs if config[:target] Ohai::Config.target_mode.host = config[:target] if URI.parse(Ohai::Config.target_mode.host).scheme train_config = Train.unpack_target_from_uri(Ohai::Config.target_mode.host) Ohai::Config.target_mode = train_config end Ohai::Config.target_mode.enabled = true Ohai::Config.node_name = Ohai::Config.target_mode.host unless Ohai::Config.node_name end Ohai::Log.init(Ohai.config[:log_location]) end # @api private def config_file_defaults Ohai::Config.save(true) end # @api private def config_file_settings Ohai::Config.save(false) end # See lib/chef/knife.rb in the chef/chef github repo # # @api private def merge_configs config.replace(config_file_defaults.merge(default_config).merge(config_file_settings).merge(config)) Ohai::Config.merge!(config) # make them both the same end # Passes config and attributes arguments to Ohai::System then prints the results. # Called by the run method after config / logging have been initialized # # @return void def run_application config[:invoked_from_cli] = true config[:logger] = Ohai::Log.with_child ohai = Ohai::System.new(config) ohai.all_plugins(@attributes) if @attributes @attributes.each do |a| puts ohai.attributes_print(a) end else puts ohai.json_pretty_print end end class << self # Log a fatal error message to both STDERR and the Logger, exit the application # @param msg [String] the message to log # @param err [Integer] the exit code def fatal!(msg, err = -1) STDERR.puts("FATAL: #{msg}") Ohai::Log.fatal(msg) Process.exit err end # Log a debug message to the Logger and then exit the application # @param msg [String] the message to log # @param err [Integer] the exit code def exit!(msg, err = -1) Ohai::Log.debug(msg) Process.exit err end end private def load_workstation_config config_loader = ChefConfig::WorkstationConfigLoader.new( config[:config_file], Ohai::Log ) begin config_loader.load rescue ChefConfig::ConfigurationError => config_error Ohai::Application.fatal!(config_error.message) end end end ohai-16.13.0/lib/ohai/mixin/0000755000175100017510000000000014034105661014442 5ustar pravipraviohai-16.13.0/lib/ohai/mixin/seconds_to_human.rb0000644000175100017510000000322414034105661020320 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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. # module Ohai module Mixin module SecondsToHuman # given the number of seconds return a day/hours/minutes/seconds human form # # @param seconds [Integer] # # @return String def seconds_to_human(seconds) days = seconds.to_i / 86400 seconds -= 86400 * days hours = seconds.to_i / 3600 seconds -= 3600 * hours minutes = seconds.to_i / 60 seconds -= 60 * minutes if days > 1 sprintf("%d days %02d hours %02d minutes %02d seconds", days, hours, minutes, seconds) elsif days == 1 sprintf("%d day %02d hours %02d minutes %02d seconds", days, hours, minutes, seconds) elsif hours > 0 sprintf("%d hours %02d minutes %02d seconds", hours, minutes, seconds) elsif minutes > 0 sprintf("%d minutes %02d seconds", minutes, seconds) else sprintf("%02d seconds", seconds) end end end end end ohai-16.13.0/lib/ohai/mixin/azure_metadata.rb0000644000175100017510000001104314034105661017754 0ustar pravipravi# frozen_string_literal: true # # Author:: Tim Smith () # Copyright:: Copyright (c) Chef Software 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 "net/http" unless defined?(Net::HTTP) module Ohai module Mixin # # This code parses the Azure Instance Metadata API to provide details # of the running instance. # # The code probes the instance metadata endpoint for # available versions, determines the most advanced version known to # work and executes the metadata retrieval using that version. # # If no compatible version is found, an empty hash is returned. # module AzureMetadata AZURE_METADATA_ADDR ||= "169.254.169.254" # it's important that the newer versions are at the end of this array so we can skip sorting it AZURE_SUPPORTED_VERSIONS ||= %w{ 2017-04-02 2017-08-01 2017-12-01 2018-02-01 2018-04-02 2018-10-01 2019-02-01 2019-03-11 2019-04-30 2019-06-01 2019-06-04 2019-08-01 2019-08-15 2019-11-01 }.freeze def best_api_version @api_version ||= begin logger.trace("Mixin AzureMetadata: Fetching http://#{AZURE_METADATA_ADDR}/metadata/instance to determine the latest supported metadata release") response = http_get("/metadata/instance") if response.code == "404" logger.trace("Mixin AzureMetadata: Received HTTP 404 from metadata server while determining API version, assuming #{AZURE_SUPPORTED_VERSIONS.last}") return AZURE_SUPPORTED_VERSIONS.last elsif response.code != "400" # 400 is actually what we want raise "Mixin AzureMetadata: Unable to determine Azure metadata version (returned #{response.code} response)" end # azure returns a list of the 3 latest versions it supports versions = parse_json(response.body).fetch("newest-versions", []) versions.sort! until versions.empty? || AZURE_SUPPORTED_VERSIONS.include?(versions.last) pv = versions.pop logger.trace("Mixin AzureMetadata: Azure metadata version #{pv} is not present in the versions provided by the Azure Instance Metadata service") end if versions.empty? logger.debug "Mixin AzureMetadata: The short list of supported versions provided by Azure Instance Metadata service doesn't match any known versions to Ohai. Using the latest supported release known to Ohai instead: #{AZURE_SUPPORTED_VERSIONS.last}" return AZURE_SUPPORTED_VERSIONS.last end logger.trace("Mixin AzureMetadata: Latest supported Azure metadata version: #{versions.last}") versions.last end end # fetch the meta content with a timeout and the required header and a read timeout of 6s # # @param [String] the relative uri to fetch from the Azure Metadata Service URL # # @return [Net::HTTP] def http_get(uri) conn = Net::HTTP.start(AZURE_METADATA_ADDR) conn.read_timeout = 6 conn.get(uri, { "Metadata" => "true" }) end # parse JSON data from a String to a Hash # # @param [String] response_body json as string to parse # # @return [Hash] def parse_json(response_body) data = String(response_body) parser = FFI_Yajl::Parser.new parser.parse(data) rescue FFI_Yajl::ParseError logger.warn("Mixin AzureMetadata: Metadata response is NOT valid JSON") nil end def fetch_metadata(api_version = nil) metadata_url = "/metadata/instance?api-version=#{best_api_version}" logger.trace("Mixin AzureMetadata: Fetching metadata from host #{AZURE_METADATA_ADDR} at #{metadata_url}") response = http_get(metadata_url) if response.code == "200" parse_json(response.body) else logger.warn("Mixin AzureMetadata: Received response code #{response.code} requesting metadata") nil end end end end end ohai-16.13.0/lib/ohai/mixin/dmi_decode.rb0000644000175100017510000000301214034105661017037 0ustar pravipravi# frozen_string_literal: true # # Author:: Tim Smith # Copyright:: Copyright (c) Chef Software 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. # http://www.dmo.ca/blog/detecting-virtualization-on-linux module ::Ohai::Mixin::DmiDecode def guest_from_dmi_data(manufacturer, product, version) case manufacturer when /OpenStack/ return "openstack" when /Xen/ return "xen" when /VMware/ return "vmware" when /Microsoft/ return "hyperv" if /Virtual Machine/.match?(product) when /Amazon EC2/ return "amazonec2" when /QEMU/ return "kvm" when /Veertu/ return "veertu" when /Parallels/ return "parallels" end case product when /VirtualBox/ return "vbox" when /OpenStack/ # yes this is here twice. Product catches Red Hat's version return "openstack" when /(KVM|RHEV)/ return "kvm" when /BHYVE/ return "bhyve" end nil # doesn't look like a virt end end ohai-16.13.0/lib/ohai/mixin/command.rb0000644000175100017510000000042214034105661016403 0ustar pravipravi# frozen_string_literal: true $stderr.puts "WARN: Ohai::Mixin::Command is deprecated, please use Ohai::Mixin::ShellOut or remove if the reference is unnecessary" require_relative "shell_out" Ohai::Mixin::Command = Ohai::Mixin::ShellOut unless defined?(Ohai::Mixin::Command) ohai-16.13.0/lib/ohai/mixin/shell_out.rb0000644000175100017510000000351214034105661016766 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Author:: Tim Smith () # Copyright:: Copyright (c) Chef Software 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_relative "../exception" require_relative "../log" require "mixlib/shellout/helper" unless defined?(Mixlib::ShellOut::Helper) require_relative "chef_utils_wiring" unless defined?(Ohai::Mixin::ChefUtilsWiring) module Ohai module Mixin module ShellOut include Mixlib::ShellOut::Helper include Ohai::Mixin::ChefUtilsWiring def shell_out(cmd, **options) options = options.dup # unless specified by the caller timeout after configured timeout (default 30 seconds) options[:timeout] ||= Ohai::Config.ohai[:shellout_timeout] begin so = super(cmd, **options) logger.trace("Plugin #{name}: ran '#{cmd}' and returned #{so.exitstatus}") so rescue Errno::ENOENT => e logger.trace("Plugin #{name}: ran '#{cmd}' and failed #{e.inspect}") raise Ohai::Exceptions::Exec, e rescue Mixlib::ShellOut::CommandTimeout => e logger.trace("Plugin #{name}: ran '#{cmd}' and timed out after #{options[:timeout]} seconds") raise Ohai::Exceptions::Exec, e end end end end end ohai-16.13.0/lib/ohai/mixin/http_helper.rb0000644000175100017510000000402614034105661017307 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software 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 "socket" unless defined?(Socket) module Ohai module Mixin module HttpHelper # see if we can socket connect to an address/port # # @param addr [String] the address to connect to # @param port [Integer] the port to connect to # @param timeout [Integer] the seconds before timing out # # @return [Boolean] can we connect? def can_socket_connect?(addr, port, timeout = 2) t = Socket.new(Socket::Constants::AF_INET, Socket::Constants::SOCK_STREAM, 0) begin saddr = Socket.pack_sockaddr_in(port, addr) rescue SocketError => e # generally means dns resolution error logger.trace("Mixin HttpHelper: can_socket_connect? failed setting up socket connection: #{e}") return false end connected = false begin t.connect_nonblock(saddr) rescue Errno::EINPROGRESS _r, w, _e = IO.select(nil, [t], nil, timeout) if !w.nil? connected = true else begin t.connect_nonblock(saddr) rescue Errno::EISCONN t.close connected = true rescue SystemCallError end end rescue SystemCallError end logger.trace("Mixin HttpHelper: can_socket_connect? == #{connected}") connected end end end end ohai-16.13.0/lib/ohai/mixin/train_helpers.rb0000644000175100017510000000232314034105661017626 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software 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 "chef-utils/dsl/train_helpers" unless defined?(ChefUtils::DSL::TrainHelpers) require_relative "chef_utils_wiring" unless defined?(Ohai::Mixin::ChefUtilsWiring) module Ohai module Mixin module TrainHelpers include ChefUtils::DSL::TrainHelpers include ChefUtilsWiring # anything added to this file temporarily should be pushed back up # into ChefUtils::DSL::TrainHelpers # XXX: this needs better support directly in train def dir_glob(path) shell_out!("ls -d #{path}").stdout.split end end end end ohai-16.13.0/lib/ohai/mixin/gce_metadata.rb0000644000175100017510000000463114034105661017371 0ustar pravipravi# frozen_string_literal: true # # Author:: Ranjib Dey () # 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 "net/http" unless defined?(Net::HTTP) module Ohai module Mixin module GCEMetadata # Trailing dot to host is added to avoid DNS search path GCE_METADATA_ADDR ||= "metadata.google.internal." GCE_METADATA_URL ||= "/computeMetadata/v1/?recursive=true" # fetch the meta content with a timeout and the required header def http_get(uri) conn = Net::HTTP.start(GCE_METADATA_ADDR) conn.read_timeout = 6 conn.get(uri, { "Metadata-Flavor" => "Google", "User-Agent" => "chef-ohai/#{Ohai::VERSION}", }) end def fetch_metadata(id = "") response = http_get("#{GCE_METADATA_URL}/#{id}") return nil unless response.code == "200" if json?(response.body) data = String(response.body) parser = FFI_Yajl::Parser.new parser.parse(data) elsif has_trailing_slash?(id) || (id == "") temp = {} response.body.split("\n").each do |sub_attr| temp[sanitize_key(sub_attr)] = fetch_metadata("#{id}#{sub_attr}") end temp else response.body end end # @param [String] data that might be JSON # # @return [Boolean] is the data JSON or not? def json?(data) data = String(data) parser = FFI_Yajl::Parser.new begin parser.parse(data) true rescue FFI_Yajl::ParseError false end end # @param data [String] # # @return [Boolean] is there a trailing /? def has_trailing_slash?(data) !!( data =~ %r{/$} ) end def sanitize_key(key) key.gsub(%r{\-|/}, "_") end end end end ohai-16.13.0/lib/ohai/mixin/constant_helper.rb0000644000175100017510000000320614034105661020160 0ustar pravipravi# frozen_string_literal: true # # Author:: Serdar Sutay () # Copyright:: Copyright (c) Chef Software 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. # module Ohai module Mixin module ConstantHelper def remove_constants new_object_constants = Object.constants - @object_pristine.constants new_object_constants.each do |constant| Object.send(:remove_const, constant) unless Object.const_get(constant).is_a?(Module) end recursive_remove_constants(Ohai::NamedPlugin) end def recursive_remove_constants(object) if object.respond_to?(:constants) object.constants.each do |const| next unless strict_const_defined?(object, const) recursive_remove_constants(object.const_get(const)) object.send(:remove_const, const) end end end def strict_const_defined?(object, const) if object.method(:const_defined?).arity == 1 object.const_defined?(const) else object.const_defined?(const, false) end end end end end ohai-16.13.0/lib/ohai/mixin/chef_utils_wiring.rb0000644000175100017510000000251214034105661020473 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software 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_relative "../config" require "singleton" unless defined?(Singleton) module Ohai module Mixin # Common Dependency Injection wiring for ChefUtils-related modules module ChefUtilsWiring private def __config Ohai::Config end def __log logger end def __transport_connection transport_connection end # because of target mode we cache the PATH to avoid massive amounts of `echo $PATH` remote queries # def __env_path PathCache.instance.path_cache ||= super end class PathCache include Singleton attr_accessor :path_cache end end end end ohai-16.13.0/lib/ohai/mixin/which.rb0000644000175100017510000000234314034105661016073 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software 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 "chef-utils/dsl/which" unless defined?(ChefUtils::DSL::Which) require "chef-utils/dsl/default_paths" unless defined?(ChefUtils::DSL::DefaultPaths) require_relative "chef_utils_wiring" unless defined?(Ohai::Mixin::ChefUtilsWiring) module Ohai module Mixin module Which include ChefUtils::DSL::Which include ChefUtils::DSL::DefaultPaths include ChefUtilsWiring private # we dep-inject default paths into this API for historical reasons # # @api private def __extra_path __default_paths end end end end ohai-16.13.0/lib/ohai/mixin/scaleway_metadata.rb0000644000175100017510000000327214034105661020443 0ustar pravipravi# frozen_string_literal: true # # Author:: Jonathan Amiez () # 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 "net/http" unless defined?(Net::HTTP) module Ohai module Mixin module ScalewayMetadata SCALEWAY_METADATA_ADDR ||= "169.254.42.42" SCALEWAY_METADATA_URL ||= "/conf?format=json" # @return [Net::HTTP] net/http object without timeout set to 6 def http_client Net::HTTP.start(SCALEWAY_METADATA_ADDR).tap { |h| h.read_timeout = 6 } end # fetch scaleway metadata and parse the resulting JSON # # @return [Hash] def fetch_metadata uri = SCALEWAY_METADATA_URL.to_s response = http_client.get(uri) case response.code when "200" parser = FFI_Yajl::Parser.new parser.parse(response.body) when "404" logger.trace("Mixin ScalewayMetadata: Encountered 404 response retrieving Scaleway metadata: #{uri} ; continuing.") {} else raise "Mixin ScalewayMetadata: Encountered error retrieving Scaleway metadata (#{uri} returned #{response.code} response)" end end end end end ohai-16.13.0/lib/ohai/mixin/ec2_metadata.rb0000644000175100017510000002206314034105661017303 0ustar pravipravi# frozen_string_literal: true # # Author:: Tim Dysinger () # Author:: Benjamin Black () # Author:: Christopher Brown () # Copyright:: Copyright (c) Chef Software 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 "net/http" unless defined?(Net::HTTP) module Ohai module Mixin ## # This code parses the EC2 Instance Metadata API to provide details # of the running instance. # # Earlier version of this code assumed a specific version of the # metadata API was available. Unfortunately the API versions # supported by a particular instance are determined at instance # launch and are not extended over the life of the instance. As such # the earlier code would fail depending on the age of the instance. # # The updated code probes the instance metadata endpoint for # available versions, determines the most advanced version known to # work and executes the metadata retrieval using that version. # # If no compatible version is found, an empty hash is returned. # module Ec2Metadata EC2_METADATA_ADDR ||= "169.254.169.254" EC2_SUPPORTED_VERSIONS ||= %w{ 1.0 2007-01-19 2007-03-01 2007-08-29 2007-10-10 2007-12-15 2008-02-01 2008-09-01 2009-04-04 2011-01-01 2011-05-01 2012-01-12 2014-02-25 2014-11-05 2015-10-20 2016-04-19 2016-06-30 2016-09-02 2016-11-30 2018-08-17 2018-11-29 2019-10-01 2020-08-24 2020-11-01 }.freeze EC2_ARRAY_VALUES ||= %w{security-groups local_ipv4s}.freeze EC2_ARRAY_DIR ||= %w{network/interfaces/macs}.freeze EC2_JSON_DIR ||= %w{iam}.freeze # # The latest metadata version in EC2_SUPPORTED_VERSIONS that this instance supports # in AWS supported metadata versions are determined at instance start so we need to be # cautious here in case an instance has been running for a long time # # @return [String] the version # def best_api_version @api_version ||= begin logger.trace("Mixin EC2: Fetching http://#{EC2_METADATA_ADDR}/ to determine the latest supported metadata release") response = http_client.get("/", { 'X-aws-ec2-metadata-token': v2_token }) if response.code == "404" logger.trace("Mixin EC2: Received HTTP 404 from metadata server while determining API version, assuming 'latest'") return "latest" elsif response.code != "200" raise "Mixin EC2: Unable to determine EC2 metadata version (returned #{response.code} response)" end # NOTE: Sorting the list of versions may have unintended consequences in # non-EC2 environments. It appears to be safe in EC2 as of 2013-04-12. versions = response.body.split("\n").sort until versions.empty? || EC2_SUPPORTED_VERSIONS.include?(versions.last) pv = versions.pop logger.trace("Mixin EC2: EC2 lists metadata version: #{pv} not yet supported by Ohai") unless pv == "latest" end logger.trace("Mixin EC2: Latest supported EC2 metadata version: #{versions.last}") if versions.empty? raise "Mixin EC2: Unable to determine EC2 metadata version (no supported entries found)" end versions.last end end # a net/http client with a timeout of 10s and a keepalive of 10s # # @return [Net::HTTP] def http_client @conn ||= Net::HTTP.start(EC2_METADATA_ADDR).tap do |h| h.read_timeout = 10 h.keep_alive_timeout = 10 end end # # Fetch an API token for use querying AWS IMDSv2 or return nil if no token if found # AWS like systems (think OpenStack) will not respond with a token here # # @return [NilClass, String] API token or nil # def v2_token @v2_token ||= begin request = http_client.put("/latest/api/token", nil, { 'X-aws-ec2-metadata-token-ttl-seconds': "60" }) if request.code == "404" # not on AWS nil else request.body end end end # Get metadata for a given path and API version # # Typically, a 200 response is expected for valid metadata. # On certain instance types, traversing the provided metadata path # produces a 404 for some unknown reason. In that event, return # `nil` and continue the run instead of failing it. def metadata_get(id, api_version) path = "/#{api_version}/meta-data/#{id}" logger.trace("Mixin EC2: Fetching http://#{EC2_METADATA_ADDR}#{path}") response = http_client.get(path, { 'X-aws-ec2-metadata-token': v2_token }) case response.code when "200" response.body when "404" logger.trace("Mixin EC2: Encountered 404 response retrieving EC2 metadata path: #{path} ; continuing.") nil else raise "Mixin EC2: Encountered error retrieving EC2 metadata (#{path} returned #{response.code} response)" end end def fetch_metadata(id = "", api_version = nil) metadata = {} retrieved_metadata = metadata_get(id, best_api_version) if retrieved_metadata retrieved_metadata.split("\n").each do |o| key = expand_path("#{id}#{o}") if key[-1..-1] != "/" metadata[metadata_key(key)] = if EC2_ARRAY_VALUES.include? key retr_meta = metadata_get(key, best_api_version) retr_meta ? retr_meta.split("\n") : retr_meta else metadata_get(key, best_api_version) end elsif (!key.eql?(id)) && (!key.eql?("/")) name = key[0..-2] sym = metadata_key(name) if EC2_ARRAY_DIR.include?(name) metadata[sym] = fetch_dir_metadata(key, best_api_version) elsif EC2_JSON_DIR.include?(name) metadata[sym] = fetch_json_dir_metadata(key, best_api_version) else fetch_metadata(key, best_api_version).each { |k, v| metadata[k] = v } end end end metadata end end def fetch_dir_metadata(id, api_version) metadata = {} retrieved_metadata = metadata_get(id, api_version) if retrieved_metadata retrieved_metadata.split("\n").each do |o| key = expand_path(o) if key[-1..-1] != "/" retr_meta = metadata_get("#{id}#{key}", api_version) metadata[metadata_key(key)] = retr_meta || "" elsif !key.eql?("/") metadata[key[0..-2]] = fetch_dir_metadata("#{id}#{key}", api_version) end end metadata end end def fetch_json_dir_metadata(id, api_version) metadata = {} retrieved_metadata = metadata_get(id, api_version) if retrieved_metadata retrieved_metadata.split("\n").each do |o| key = expand_path(o) if key[-1..-1] != "/" retr_meta = metadata_get("#{id}#{key}", api_version) data = retr_meta || "" json = String(data) parser = FFI_Yajl::Parser.new metadata[metadata_key(key)] = parser.parse(json) elsif !key.eql?("/") metadata[key[0..-2]] = fetch_json_dir_metadata("#{id}#{key}", api_version) end end metadata end end def fetch_userdata logger.trace("Mixin EC2: Fetching http://#{EC2_METADATA_ADDR}/#{best_api_version}/user-data/") response = http_client.get("/#{best_api_version}/user-data/", { 'X-aws-ec2-metadata-token': v2_token }) response.code == "200" ? response.body : nil end def fetch_dynamic_data @fetch_dynamic_data ||= begin response = http_client.get("/#{best_api_version}/dynamic/instance-identity/document/", { 'X-aws-ec2-metadata-token': v2_token }) if json?(response.body) && response.code == "200" FFI_Yajl::Parser.parse(response.body) else {} end end end private def expand_path(file_name) path = file_name.gsub(/\=.*$/, "/") # ignore "./" and "../" path.gsub(%r{/\.\.?(?:/|$)}, "/") .sub(%r{^\.\.?(?:/|$)}, "") .sub(/^$/, "/") end def metadata_key(key) key.gsub(%r{\-|/}, "_") end end end end ohai-16.13.0/lib/ohai/mixin/softlayer_metadata.rb0000644000175100017510000000534614034105661020647 0ustar pravipravi# frozen_string_literal: true # # Author:: Alexey Karpik # Author:: Peter Schroeter # Author:: Stas Turlo # Copyright:: Copyright (c) 2010-2014 RightScale 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 "net/http" unless defined?(Net::HTTP) require "uri" unless defined?(URI) # https://softlayer.github.io/reference/services/SoftLayer_Resource_Metadata/ module ::Ohai::Mixin::SoftlayerMetadata SOFTLAYER_API_QUERY_URL ||= "https://api.service.softlayer.com/rest/v3.1/SoftLayer_Resource_Metadata" # fetch metadata items and build out hash of data # # @return [Hash] def fetch_metadata { "public_fqdn" => fetch_metadata_item("getFullyQualifiedDomainName.txt"), "local_ipv4" => fetch_metadata_item("getPrimaryBackendIpAddress.txt"), "public_ipv4" => fetch_metadata_item("getPrimaryIpAddress.txt"), "region" => fetch_metadata_item("getDatacenter.txt"), "instance_id" => fetch_metadata_item("getId.txt"), } end # Softlayer's metadata api is only available over HTTPS. # Ruby by default does not link to the system's CA bundle # however Chef-omnibus should set SSL_CERT_FILE to point to a valid file. # Manually supply and specify a suitable CA bundle here or # set the SSL_CERT_FILE file environment variable to a valid value otherwise. # # @return [String] def ca_file_location ::Ohai::Config[:ca_file] end # fetch a specified item from the Softlayer metadata API # @param item [String] the metadata item to fetch # # @return [String] the response body def fetch_metadata_item(item) full_url = "#{SOFTLAYER_API_QUERY_URL}/#{item}" u = URI(full_url) net = ::Net::HTTP.new(u.hostname, u.port) net.ssl_version = :TLSv1_2 net.use_ssl = true net.ca_file = ca_file_location res = net.get(u.request_uri) if res.code.to_i.between?(200, 299) res.body else logger.error("Mixin Softlayer: Unable to fetch item #{full_url}: status (#{res.code}) body (#{res.body})") nil end rescue => e logger.error("Mixin Softlayer: Unable to fetch softlayer metadata from #{u}: #{e.class}: #{e.message}") raise e end end ohai-16.13.0/lib/ohai/mixin/network_helper.rb0000644000175100017510000000214014034105661020014 0ustar pravipravi# frozen_string_literal: true # # Author:: Serdar Sutay () # Copyright:: Copyright (c) Chef Software 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. # module Ohai module Mixin module NetworkHelper FAMILIES = { "inet" => "default", "inet6" => "default_inet6", }.freeze def hex_to_dec_netmask(netmask) # example 'ffff0000' -> '255.255.0.0' dec = netmask[0..1].to_i(16).to_s(10) [2, 4, 6].each { |n| dec = dec + "." + netmask[n..n + 1].to_i(16).to_s(10) } dec end end end end ohai-16.13.0/lib/ohai/mixin/os.rb0000644000175100017510000001143614034105661015415 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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 "rbconfig" unless defined?(RbConfig) module Ohai module Mixin module OS # Using ruby configuration determine the OS we're running on # # @return [String] the OS def collect_os if target_mode? collect_os_target else collect_os_local end end # This should exactly preserve the semantics of collect_os_local below, which is authoritative # for the API and must adhere to pre-existing ohai semantics and not follow inspec's notion of # os/family/hierarchy. # # Right or wrong the ohai `os` variable has matched the ruby `host_os` definition for the past # 10+ years, preceding inspec/train's definitions and this is the documented correct API of # these methods. Mismatches between the ruby notion and the train version will be fixed as # bugfixes in these methods and may not be considered semver violating even though they make # break downstream consumers. Please ensure that both methods produce the same results if # you are on a platform which supports running ruby (train is considered authoritative for # any "OS" which cannot run ruby -- server consoles, REST APIs, etc...) # # @api private def collect_os_target case when transport_connection.os.aix? "aix" when transport_connection.os.darwin? "darwin" when transport_connection.os.linux? "linux" when transport_connection.os.family == "freebsd" "freebsd" when transport_connection.os.family == "openbsd" "openbsd" when transport_connection.os.family == "netbsd" "netbsd" when transport_connection.os.family == "dragonflybsd" "dragonflybsd" when transport_connection.os.solaris? "solaris2" when transport_connection.os.windows? "windows" # # The purpose of the next two lines is that anything which runs Unix is presumed to be able to run ruby, and # if it was not caught above, we MUST translate whatever train uses as the 'os' into the proper ruby host_os # string. If it is not unix and not caught above we assume it is something like a REST API which cannot run # ruby. If these assumptions are incorrect then it is a bug, which should be submitted to fix it, and the # values should not be relied upon until that bug is fixed. The train os is NEVER considered authoritative # for any target which can run ruby. # when transport_connection.os.unix? raise "Target mode unsupported on this Unix-like host, please update the collect_os_target case statement with the correct ruby host_os value." else # now we have something like an IPMI console that isn't Unix-like or Windows, presumably cannot run ruby, and # so we just trust the train O/S information. transport_connection.os end end # @api private def nonruby_target? transport_connection && !transport_connection.os.unix? && !transport_connection.os.windows end # @api private def collect_os_local case ::RbConfig::CONFIG["host_os"] when /aix(.+)$/ "aix" when /darwin(.+)$/ "darwin" when /linux/ "linux" when /freebsd(.+)$/ "freebsd" when /openbsd(.+)$/ "openbsd" when /netbsd(.*)$/ "netbsd" when /dragonfly(.*)$/ "dragonflybsd" when /solaris2/ "solaris2" when /mswin|mingw32|windows/ # After long discussion in IRC the "powers that be" have come to a consensus # that no Windows platform exists that was 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. "windows" else ::RbConfig::CONFIG["host_os"] end end extend self end end end ohai-16.13.0/lib/ohai/mixin/string.rb0000644000175100017510000000236314034105661016301 0ustar pravipravi# frozen_string_literal: true # # Author:: James Gartrell () # Copyright:: Copyright (c) Chef Software 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 # @return [String] def wmi_underscore gsub(/::/, "/").gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') .gsub(/([a-z\d])([A-Z])/, '\1_\2').tr("-", "_").downcase end end ohai-16.13.0/lib/ohai/mixin/do_metadata.rb0000644000175100017510000000276514034105661017243 0ustar pravipravi# frozen_string_literal: true # Author:: Dylan Page () # 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 "net/http" unless defined?(Net::HTTP) module Ohai module Mixin module DOMetadata DO_METADATA_ADDR ||= "169.254.169.254" DO_METADATA_URL ||= "/metadata/v1.json" def http_client Net::HTTP.start(DO_METADATA_ADDR).tap { |h| h.read_timeout = 6 } end def fetch_metadata uri = DO_METADATA_URL.to_s response = http_client.get(uri) case response.code when "200" parser = FFI_Yajl::Parser.new parser.parse(response.body) when "404" logger.trace("Mixin DOMetadata: Encountered 404 response retrieving Digital Ocean metadata: #{uri} ; continuing.") {} else raise "Mixin DOMetadata: Encountered error retrieving Digital Ocean metadata (#{uri} returned #{response.code} response)" end end end end end ohai-16.13.0/lib/ohai/common/0000755000175100017510000000000014034105661014606 5ustar pravipraviohai-16.13.0/lib/ohai/common/dmi.rb0000644000175100017510000001267514034105661015717 0ustar pravipravi# frozen_string_literal: true # # Author:: Kurt Yoder (ktyopscode@yoderhome.com) # Copyright:: Copyright (c) 2010 Kurt Yoder # 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. # module Ohai module Common module DMI # List of IDs and what they translate to # from 'man 8 dmidecode' # all-lowercase, all non-alphanumeric converted to '_' # 128-255 are 'oem_data_[id]' # Everything else is 'unknown' ID_TO_DESCRIPTION = { 0 => "bios", 1 => "system", 2 => "base_board", 3 => "chassis", 4 => "processor", 5 => "memory_controller", 6 => "memory_module", 7 => "cache", 8 => "port_connector", 9 => "system_slots", 10 => "on_board_devices", 11 => "oem_strings", 12 => "system_configuration_options", 13 => "bios_language", 14 => "group_associations", 15 => "system_event_log", 16 => "physical_memory_array", 17 => "memory_device", 18 => "32_bit_memory_error", 19 => "memory_array_mapped_address", 20 => "memory_device_mapped_address", 21 => "built_in_pointing_device", 22 => "portable_battery", 23 => "system_reset", 24 => "hardware_security", 25 => "system_power_controls", 26 => "voltage_probe", 27 => "cooling_device", 28 => "temperature_probe", 29 => "electrical_current_probe", 30 => "out_of_band_remote_access", 31 => "boot_integrity_services", 32 => "system_boot", 33 => "64_bit_memory_error", 34 => "management_device", 35 => "management_device_component", 36 => "management_device_threshold_data", 37 => "memory_channel", 38 => "ipmi_device", 39 => "power_supply", 40 => "additional_information", 41 => "onboard_devices_extended_information", 42 => "management_controller_host_interfaces", 126 => "disabled_entries", 127 => "end_of_table_marker", }.freeze # list of IDs to collect from config or default to a sane list that prunes # away some of the less useful IDs ID_TO_CAPTURE = [ 0, 1, 2, 3, 4, 6, 11 ].freeze # the allowlisted DMI IDs. This is combination of the defaults + any additional # IDs defined in the :additional_dmi_ids config # # @return [Array] the list of DMI IDs to capture def allowlisted_ids if Ohai.config[:additional_dmi_ids] if [ Integer, Array ].include?(Ohai.config[:additional_dmi_ids].class) return ID_TO_CAPTURE + Array(Ohai.config[:additional_dmi_ids]) else Ohai::Log.warn("The DMI plugin additional_dmi_ids config must be an array of IDs!") end end ID_TO_CAPTURE end ## # @deprecated Use the `allowlisted_ids` method instead. alias whitelisted_ids allowlisted_ids # the human readable description from a DMI ID # # @param id [String, Integer] the ID to lookup # # @return [String] def id_lookup(id) id = id.to_i if (id >= 128) && (id <= 255) id = "oem_data_#{id}" elsif DMI::ID_TO_DESCRIPTION.key?(id) id = DMI::ID_TO_DESCRIPTION[id] else Ohai::Log.debug("unrecognized header id; falling back to 'unknown'") id = "unknown_dmi_id_#{id}" end rescue Ohai::Log.debug("failed to look up id #{id}, returning unchanged") id end SKIPPED_CONVENIENCE_KEYS = %w{ application_identifier caption creation_class_name size system_creation_class_name record_id }.freeze # create simplified convenience access keys for each record type # for single occurrences of one type, copy to top level all fields and values # for multiple occurrences of same type, copy to top level all fields and values that are common to all records def convenience_keys(dmi) dmi.each do |type, records| in_common = Mash.new next unless records.is_a?(Mash) next unless records.key?("all_records") records[:all_records].each do |record| record.each do |field, value| next unless value.is_a?(String) translated = field.downcase.gsub(/[^a-z0-9]/, "_") next if SKIPPED_CONVENIENCE_KEYS.include?(translated.to_s) value = value.strip if in_common.key?(translated) in_common[translated] = nil unless in_common[translated] == value else in_common[translated] = value end end end in_common.each do |field, value| next if value.nil? dmi[type][field] = value.strip end end end module_function :id_lookup, :convenience_keys, :allowlisted_ids, :whitelisted_ids end end end ohai-16.13.0/lib/ohai/hints.rb0000644000175100017510000000516214034105661014774 0ustar pravipravi# frozen_string_literal: true # # Author:: Serdar Sutay () # Copyright:: Copyright (c) Chef Software 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 "ffi_yajl" unless defined?(FFI_Yajl) module Ohai # Ohai hints are json files on disk that give ohai a hint to things that are often # difficult to discover like certain clouds. Previously they were used for just about # every cloud, but we've since discoverd better ways to auto-detect these clouds. # They are generally dropped off by the knife plugins for those clouds during bootstrap, # but may also be manually dropped off and consumed by 3rd party plugins. module Hints # clear out any known hints in the @hints variable def self.refresh_hints @hints = {} end # parse the JSON contents of a hint file. Return an empty hash if the file has # no JSON content # @param filename [String] the hint file path def self.parse_hint_file(filename) json_parser = FFI_Yajl::Parser.new hash = json_parser.parse(File.read(filename)) hash || {} # hint # should exist because the file did, even if it didn't # contain anything rescue FFI_Yajl::ParseError => e Ohai::Log.error("Could not parse hint file at #{filename}: #{e.message}") end # retrieve hint contents given a hint name. Looks up in @hints variable first. Attempts # to load from file in config's :hints_path if not already cached. Saves the contents # to the hash if the file was successfully parsed # @param name [String] the name of the hint (not the path) def self.hint?(name) @hints ||= {} return @hints[name] if @hints[name] Ohai.config[:hints_path].each do |path| filename = File.join(path, "#{name}.json") next unless File.exist?(filename) Ohai::Log.trace("Found hint #{name}.json at #{filename}") @hints[name] = parse_hint_file(filename) end Ohai::Log.trace("Did not find hint #{name}.json in the hint path(s): #{Ohai.config[:hints_path].join(", ")} ") unless @hints.key?(name) @hints[name] end end end ohai-16.13.0/lib/ohai/system.rb0000644000175100017510000001670014034105661015173 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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_relative "version" require_relative "loader" require_relative "log" require_relative "mash" require_relative "runner" require_relative "dsl" require_relative "mixin/shell_out" require_relative "mixin/os" require_relative "mixin/string" require_relative "mixin/constant_helper" require_relative "provides_map" require_relative "hints" require_relative "config" require_relative "train_transport" require "ffi_yajl" unless defined?(FFI_Yajl) require "cgi" unless defined?(CGI) module Ohai # The class used by Ohai::Application and Chef to actually collect data class System include Ohai::Mixin::ConstantHelper attr_accessor :data attr_reader :config attr_reader :provides_map attr_reader :logger attr_writer :transport_connection # the cli flag is used to determine if we're being constructed by # something like chef-client (which doesn't set this flag) and # which sets up its own loggers, or if we're coming from Ohai::Application # and therefore need to configure Ohai's own logger. def initialize(config = {}) @cli = config[:invoked_from_cli] @plugin_path = "" @config = config @failed_plugins = [] @logger = config[:logger] || Ohai::Log.with_child @logger.metadata = { system: "ohai", version: Ohai::VERSION } reset_system end # clears the current collected data, clears the provides map for plugins, # refreshes hints, and reconfigures ohai. In short this gets Ohai into a first run state # # @return [void] def reset_system @data = Mash.new @provides_map = ProvidesMap.new configure_ohai configure_logging if @cli @loader = Ohai::Loader.new(self) Ohai::Hints.refresh_hints # Remove the previously defined plugins recursive_remove_constants(Ohai::NamedPlugin) end def runner @runner ||= Ohai::Runner.new(self, true).tap do |runner| runner.transport_connection = transport_connection unless transport_connection.nil? end end def [](key) @data[key] end # Resets the system and loads then runs the plugins. This is the primary method called # to run the system. # # @param [Array] attribute_filter the attributes to run. All will be run if not specified # # @return [void] def all_plugins(attribute_filter = nil) # Reset the system when all_plugins is called since this function # can be run multiple times in order to pick up any changes in the # config or plugins with Chef. reset_system load_plugins run_plugins(true, attribute_filter) end # load all plugins by calling Ohai::Loader.load_all # # @see Ohai::Loader.load_all def load_plugins @loader.load_all end # get backend parameters for target mode # # @return [Train::Transport] def transport_connection @transport_connection ||= Ohai::TrainTransport.new(logger).build_transport&.connection end # run all plugins or those that match the attribute filter is provided # # @param safe [Boolean] # @param [Array] attribute_filter the attributes to run. All will be run if not specified # # @return [Mash] def run_plugins(safe = false, attribute_filter = nil) begin @provides_map.all_plugins(attribute_filter).each do |plugin| runner.run_plugin(plugin) end transport_connection.close unless transport_connection.nil? rescue Ohai::Exceptions::AttributeNotFound, Ohai::Exceptions::DependencyCycle => e logger.error("Encountered error while running plugins: #{e.inspect}") raise end critical_failed = Ohai::Config.ohai[:critical_plugins] & runner.failed_plugins unless critical_failed.empty? msg = "The following Ohai plugins marked as critical failed: #{critical_failed}" if @cli logger.error(msg) exit(true) else raise Ohai::Exceptions::CriticalPluginFailure, "#{msg}. Failing Chef run." end end # Freeze all strings. freeze_strings! end # @param [String] plugin_path # # @return [void] # def run_additional_plugins(plugin_path) @loader.load_additional(plugin_path).each do |plugin| logger.trace "Running plugin #{plugin}" runner.run_plugin(plugin) end freeze_strings! end # # Serialize this object as a hash # def to_json FFI_Yajl::Encoder.new.encode(@data) end # # Pretty Print this object as JSON # def json_pretty_print(item = nil) FFI_Yajl::Encoder.new(pretty: true, validate_utf8: false).encode(item || @data) end def attributes_print(a) data = @data a.split("/").each do |part| data = data[part] end raise ArgumentError, "I cannot find an attribute named #{a}!" if data.nil? case data when Hash, Mash, Array, Integer json_pretty_print(data) when String if data.respond_to?(:lines) json_pretty_print(data.lines.to_a) else json_pretty_print(data.to_a) end else raise ArgumentError, "I can only generate JSON for Hashes, Mashes, Arrays and Strings. You fed me a #{data.class}!" end end private def configure_ohai Ohai.config.merge!(@config) # add any additional CLI passed directories to the plugin path excluding duplicates unless Ohai.config[:directory].nil? # make sure the directory config is an array since it could be a string set in client.rb Array(Ohai.config[:directory]).each do |dir| next if Ohai.config[:plugin_path].include?(dir) Ohai.config[:plugin_path] << dir end end logger.debug("Running Ohai with the following configuration: #{Ohai.config.configuration}") end def configure_logging if Ohai.config[:log_level] == :auto Ohai::Log.level = :info else Ohai::Log.level = Ohai.config[:log_level] end end # Freeze all string values in @data. This makes them immutable and saves # a bit of RAM. # # @api private # @return [void] def freeze_strings! # Recursive visitor pattern helper. visitor = lambda do |val| case val when Hash val.each_value { |v| visitor.call(v) } when Array val.each { |v| visitor.call(v) } when String val.freeze end end visitor.call(@data) end # Extract additional backend parameters from Target Mode URL. # # @api private # @return [Hash] def backend_parameters uri = URI.parse(config[:target]) return {} unless uri.query CGI.parse(uri.query).map { |k, v| [k.to_sym, v.first] }.to_h end end end ohai-16.13.0/lib/ohai/runner.rb0000644000175100017510000001025714034105661015161 0ustar pravipravi# frozen_string_literal: true # # Author:: Claire McQuin () # Copyright:: Copyright (c) Chef Software 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 expressed or # implied. # See the License for the specific language governing permissions and # limitations under the License # require_relative "dsl" require "benchmark" unless defined?(Benchmark) module Ohai class Runner attr_reader :failed_plugins, :logger attr_accessor :transport_connection # safe_run: set to true if this runner will run plugins in # safe-mode. default false. def initialize(controller, safe_run = false) @provides_map = controller.provides_map @safe_run = safe_run @failed_plugins = [] @logger = controller.logger.with_child @logger.metadata = { subsystem: "runner" } end # Runs plugins and any un-run dependencies. # If force is set to true, then this plugin and its dependencies # will be run even if they have been run before. # # @param [Ohai::DSL::Plugin] plugin # # @return void # def run_plugin(plugin) elapsed = Benchmark.realtime do unless plugin.is_a?(Ohai::DSL::Plugin) raise Ohai::Exceptions::InvalidPlugin, "Invalid plugin #{plugin} (must be an Ohai::DSL::Plugin or subclass)" end begin if plugin.version == :version7 run_v7_plugin(plugin) else raise Ohai::Exceptions::InvalidPlugin, "Invalid plugin version #{plugin.version} for plugin #{plugin}" end rescue Ohai::Exceptions::Error, SystemExit # SystemExit: abort or exit from plug-in should exit Ohai with failure code raise rescue Exception => e logger.trace("Plugin #{plugin.name} threw exception #{e.inspect} #{e.backtrace.join("\n")}") end end logger.trace("Plugin #{plugin.name} took #{"%f" % elapsed.truncate(6)} seconds to run.") end # @param [Ohai::DSL::Plugin] plugin # # @return void # def run_v7_plugin(plugin) return true if plugin.optional? && !Ohai.config[:run_all_plugins] && !Ohai.config[:optional_plugins].include?(plugin.name) visited = [ plugin ] until visited.empty? next_plugin = visited.pop next if next_plugin.has_run? if visited.include?(next_plugin) raise Ohai::Exceptions::DependencyCycle, "Dependency cycle detected. Please refer to the following plugins: #{get_cycle(visited, plugin).join(", ")}" end dependency_providers = fetch_plugins(next_plugin.dependencies) # Remove the already ran plugins from dependencies if force is not set # Also remove the plugin that we are about to run from dependencies as well. dependency_providers.delete_if do |dep_plugin| dep_plugin.has_run? || dep_plugin.eql?(next_plugin) end if dependency_providers.empty? next_plugin.transport_connection = transport_connection @safe_run ? next_plugin.safe_run : next_plugin.run if next_plugin.failed @failed_plugins << next_plugin.name end else visited << next_plugin << dependency_providers.first end end end # @param [Array] attributes # # @return [Array] # def fetch_plugins(attributes) @provides_map.find_closest_providers_for(attributes) end # Given a list of plugins and the first plugin in the cycle, # returns the list of plugin source files responsible for the # cycle. Does not include plugins that aren't a part of the cycle def get_cycle(plugins, cycle_start) cycle = plugins.drop_while { |plugin| !plugin.eql?(cycle_start) } names = [] cycle.each { |plugin| names << plugin.name } names end end end ohai-16.13.0/lib/ohai/dsl.rb0000644000175100017510000000142014034105661014422 0ustar pravipravi# frozen_string_literal: true # # Author:: Serdar Sutay () # Copyright:: Copyright (c) Chef Software 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_relative "dsl/plugin" require_relative "dsl/plugin/versionvii" ohai-16.13.0/lib/ohai/config.rb0000644000175100017510000000361114034105661015111 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Author:: Claire McQuin () # Copyright:: Copyright (c) Chef Software 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 "chef-config/config" require_relative "exception" require_relative "plugin_config" module Ohai Config = ChefConfig::Config # Reopens ChefConfig::Config to add Ohai configuration settings. # see: https://github.com/chef/chef/blob/master/lib/chef/config.rb class Config config_context :ohai do default :disabled_plugins, [] default :hints_path, [ ChefConfig::Config.platform_specific_path("/etc/chef/ohai/hints") ] default :log_level, :auto default :log_location, STDERR default :plugin, ( Ohai::PluginConfig.new { |h, k| h[k] = Ohai::PluginConfig.new } ) default :plugin_path, [ File.expand_path(File.join(__dir__, "plugins")), ChefConfig::Config.platform_specific_path("/etc/chef/ohai/plugins") ] default :critical_plugins, [] # causes all optional plugins to be run. default :run_all_plugins, false # optional plugins are the set of plugins that are marked optional but you wish to run. default(:optional_plugins, []).writes_value { |arr| arr.map(&:to_sym) } default :shellout_timeout, 30 end end # Shortcut for Ohai::Config.ohai def self.config Config.ohai end end ohai-16.13.0/lib/ohai/provides_map.rb0000644000175100017510000001521114034105661016333 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Author:: Daniel DeLeo () # Copyright:: Copyright (c) Chef Software 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_relative "mash" require_relative "exception" require_relative "mixin/os" require_relative "dsl" module Ohai class ProvidesMap attr_reader :map def initialize @map = Mash.new end # @param [Ohai::DSL::Plugin] plugin # @param [Array] provided_attributes # # @return void # def set_providers_for(plugin, provided_attributes) unless plugin.is_a?(Ohai::DSL::Plugin) raise ArgumentError, "set_providers_for only accepts Ohai Plugin classes (got: #{plugin})" end provided_attributes.each do |attribute| attrs = @map parts = normalize_and_validate(attribute) parts.each do |part| attrs[part] ||= Mash.new attrs = attrs[part] end attrs[:_plugins] ||= [] attrs[:_plugins] << plugin end end # # gather plugins providing exactly the attributes listed # # @param [Array] attributes # # @return [Array] plugin names # def find_providers_for(attributes) plugins = [] attributes.each do |attribute| attrs = select_subtree(@map, attribute) raise Ohai::Exceptions::AttributeNotFound, "No such attribute: \'#{attribute}\'" unless attrs raise Ohai::Exceptions::ProviderNotFound, "Cannot find plugin providing attribute: \'#{attribute}\'" unless attrs[:_plugins] plugins += attrs[:_plugins] end plugins.uniq end # This function is used to fetch the plugins for the attributes specified # in the CLI options to Ohai. # It first attempts to find the plugins for the attributes # or the sub attributes given. # If it can't find any, it looks for plugins that might # provide the parents of a given attribute and returns the # first parent found. # # @param [Array] attributes # # @return [Array] plugin names def deep_find_providers_for(attributes) plugins = [] attributes.each do |attribute| attrs = select_subtree(@map, attribute) unless attrs attrs = select_closest_subtree(@map, attribute) unless attrs raise Ohai::Exceptions::AttributeNotFound, "No such attribute: \'#{attribute}\'" end end collect_plugins_in(attrs, plugins) end plugins.uniq end # This function is used to fetch the plugins from # 'depends "languages"' statements in plugins. # It gathers plugins providing each of the attributes listed, or the # plugins providing the closest parent attribute # # @param [Array] attributes # # @return [Array] plugin names def find_closest_providers_for(attributes) plugins = [] attributes.each do |attribute| parts = normalize_and_validate(attribute) raise Ohai::Exceptions::AttributeNotFound, "No such attribute: \'#{attribute}\'" unless @map[parts[0]] attrs = select_closest_subtree(@map, attribute) raise Ohai::Exceptions::ProviderNotFound, "Cannot find plugin providing attribute: \'#{attribute}\'" unless attrs plugins += attrs[:_plugins] end plugins.uniq end def all_plugins(attribute_filter = nil) if attribute_filter.nil? collected = [] collect_plugins_in(map, collected).uniq else deep_find_providers_for(Array(attribute_filter)) end end private def normalize_and_validate(attribute) raise Ohai::Exceptions::AttributeSyntaxError, "Attribute contains duplicate '/' characters: #{attribute}" if %r{//+}.match?(attribute) raise Ohai::Exceptions::AttributeSyntaxError, "Attribute contains a trailing '/': #{attribute}" if %r{/$}.match?(attribute) parts = attribute.split("/") parts.shift if parts.length != 0 && parts[0].length == 0 # attribute begins with a '/' parts end def select_subtree(provides_map, attribute) subtree = provides_map parts = normalize_and_validate(attribute) parts.each do |part| return nil unless subtree[part] subtree = subtree[part] end subtree end def select_closest_subtree(provides_map, attribute) attr, *rest = normalize_and_validate(attribute) # return nil if the top-level part of the attribute is not a # top-level key in the provides_map (can't search any lower, and # no information to return from this level of the search) return nil unless provides_map[attr] # attr is a key in the provides_map, search for the sub # attribute under attr (if attribute = attr/sub1/sub2 then we # search provides_map[attr] for sub1/sub2) unless rest.empty? subtree = select_closest_subtree(provides_map[attr], rest.join("/")) end if subtree.nil? # no subtree of provides_map[attr] either 1) has a # subattribute, 2) has a plugin providing a subattribute. unless provides_map[attr][:_plugins] # no providers for this attribute, this subtree won't do. return nil # no providers for this attribute else # there are providers for this attribute, return its subtree # to indicate this is the closest subtree return provides_map[attr] end end # we've already found a closest subtree or we've search all # parent attributes of the original attribute and found no # providers (subtree is nil in this case) subtree end # Takes a section of the map, recursively searches for a `_plugins` key # to find all the plugins in that section of the map. If given the whole # map, it will find all of the plugins that have at least one provided # attribute. def collect_plugins_in(provides_map, collected) provides_map.each_key do |plugin| if plugin.eql?("_plugins") collected.concat(provides_map[plugin]) else collect_plugins_in(provides_map[plugin], collected) end end collected end end end ohai-16.13.0/lib/ohai/version.rb0000644000175100017510000000142114034105661015326 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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. # module Ohai OHAI_ROOT = File.expand_path(__dir__) VERSION = "16.13.0" end ohai-16.13.0/lib/ohai/exception.rb0000644000175100017510000000236314034105661015645 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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. # module Ohai # Ohai specific exceptions module Exceptions class Exec < RuntimeError; end class Error < StandardError; end class InvalidPlugin < Error; end class InvalidPluginName < Error; end class IllegalPluginDefinition < Error; end class AttributeNotFound < Error; end class ProviderNotFound < Error; end class DependencyCycle < Error; end class DependencyNotFound < Error; end class AttributeSyntaxError < Error; end class PluginConfigError < Error; end class CriticalPluginFailure < Error; end end end ohai-16.13.0/lib/ohai/plugin_config.rb0000644000175100017510000000240514034105661016467 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software 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_relative "exception" module Ohai class PluginConfig < Hash def []=(key, value_or_hash) enforce_symbol(key) enforce_symbol_keys(value_or_hash) if value_or_hash.is_a?(Hash) super(key, value_or_hash) end private def enforce_symbol(key) unless key.is_a?(Symbol) msg = "Expected Symbol, got #{key.inspect}" raise Ohai::Exceptions::PluginConfigError, msg end end def enforce_symbol_keys(hash) hash.each do |key, value| enforce_symbol(key) enforce_symbol_keys(value) if value.is_a?(Hash) end end end end ohai-16.13.0/lib/ohai/loader.rb0000644000175100017510000001461114034105661015114 0ustar pravipravi# # Author:: Claire McQuin () # Copyright:: Copyright (c) Chef Software 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 "chef-config/path_helper" require_relative "log" require_relative "mash" require_relative "dsl" require "pathname" unless defined?(Pathname) module Ohai # Ohai plugin loader. Finds all the plugins specified in the # Ohai.config :plugin_path (supports a single or multiple path setting # here), evaluates them and returns plugin objects. class Loader attr_reader :logger def initialize(controller) @controller = controller @logger = controller.logger.with_child(subsystem: "loader") @v7_plugin_classes = [] end # Searches all plugin paths and returns an Array of file paths to plugins # # @param dir [Array, String] directory/directories to load plugins from # @return [Array] def plugin_files_by_dir(plugin_dir = Ohai.config[:plugin_path]) Array(plugin_dir).map do |path| if Dir.exist?(path) Ohai::Log.trace("Searching for Ohai plugins in #{path}") escaped = ChefConfig::PathHelper.escape_glob_dir(path) Dir[File.join(escaped, "**", "*.rb")] else Ohai::Log.debug("The plugin path #{path} does not exist. Skipping...") [] end end.flatten end # loads all plugin classes # # @return [Array] def load_all plugin_files_by_dir.each do |plugin_file| load_plugin_class(plugin_file) end collect_v7_plugins end # load additional plugins classes from a given directory # @param from [String] path to a directory with additional plugins to load def load_additional(from) from = [ Ohai.config[:plugin_path], from].flatten plugin_files_by_dir(from).collect do |plugin_file| logger.trace "Loading additional plugin: #{plugin_file}" load_v7_plugin(load_plugin_class(plugin_file)) end end # Load a specified file as an ohai plugin and creates an instance of it. # Not used by ohai itself, but is used in the specs to load plugins for testing # # @private # @param plugin_path [String] def load_plugin(plugin_path) plugin_class = load_plugin_class(plugin_path) return nil unless plugin_class.is_a?(Class) if plugin_class < Ohai::DSL::Plugin::VersionVII load_v7_plugin(plugin_class) else raise Exceptions::IllegalPluginDefinition, "cannot create plugin of type #{plugin_class}" end end # load an ohai plugin object class from file # @param plugin_path String the path to the ohai plugin # # @return [Object] class object for the ohai plugin defined in the file def load_plugin_class(plugin_path) # Read the contents of the plugin to understand if it's a V6 or V7 plugin. contents = "" begin logger.trace("Loading plugin at #{plugin_path}") contents << IO.read(plugin_path) rescue IOError, Errno::ENOENT logger.warn("Unable to open or read plugin at #{plugin_path}") return nil end # We assume that a plugin is a V7 plugin if it contains Ohai.plugin in its contents. if contents.include?("Ohai.plugin") load_v7_plugin_class(contents, plugin_path) else raise Exceptions::IllegalPluginDefinition, "[DEPRECATION] Plugin at #{plugin_path}"\ " is a version 6 plugin. Version 6 plugins are no longer supported by Ohai. This"\ " plugin will need to be updated to the v7 Ohai plugin format. See"\ " https://docs.chef.io/ohai_custom.html for v7 syntax." end end private def collect_provides(plugin) plugin_provides = plugin.class.provides_attrs @controller.provides_map.set_providers_for(plugin, plugin_provides) end def collect_v7_plugins @v7_plugin_classes.each do |plugin_class| load_v7_plugin(plugin_class) end end # load an Ohai v7 plugin class from a string of the object # @param contents [String] text of the plugin object # @param plugin_path [String] the path to the plugin file where the contents came from # # @return [Ohai::DSL::Plugin::VersionVII] Ohai plugin object def load_v7_plugin_class(contents, plugin_path) plugin_class = eval(contents, TOPLEVEL_BINDING, plugin_path) # rubocop: disable Security/Eval unless plugin_class.is_a?(Class) && plugin_class < Ohai::DSL::Plugin raise Ohai::Exceptions::IllegalPluginDefinition, "Plugin file cannot contain any statements after the plugin definition" end plugin_class.sources << plugin_path @v7_plugin_classes << plugin_class unless @v7_plugin_classes.include?(plugin_class) plugin_class rescue SystemExit, Interrupt # rubocop: disable Lint/ShadowedException raise rescue Ohai::Exceptions::InvalidPluginName => e logger.warn("Plugin Name Error: <#{plugin_path}>: #{e.message}") rescue Ohai::Exceptions::IllegalPluginDefinition => e logger.warn("Plugin Definition Error: <#{plugin_path}>: #{e.message}") rescue NoMethodError => e logger.warn("Plugin Method Error: <#{plugin_path}>: unsupported operation \'#{e.name}\'") rescue SyntaxError => e # split on occurrences of # : syntax error, # :##: syntax error, # to remove from error message parts = e.message.split(/<.*>[:[0-9]+]*: syntax error, /) parts.each do |part| next if part.length == 0 logger.warn("Plugin Syntax Error: <#{plugin_path}>: #{part}") end rescue Exception => e logger.warn("Plugin Error: <#{plugin_path}>: #{e.message}") logger.trace("Plugin Error: <#{plugin_path}>: #{e.inspect}, #{e.backtrace.join('\n')}") end def load_v7_plugin(plugin_class) plugin = plugin_class.new(@controller.data, @controller.logger) collect_provides(plugin) plugin end end end ohai-16.13.0/lib/ohai/plugins/0000755000175100017510000000000014034105661014777 5ustar pravipraviohai-16.13.0/lib/ohai/plugins/network.rb0000644000175100017510000001607314034105661017024 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:NetworkAddresses) do require_relative "../mixin/network_helper" include Ohai::Mixin::NetworkHelper provides "ipaddress", "ip6address", "macaddress" depends "network/interfaces" # from interface data create array of hashes with ipaddress, scope, and iface # sorted by scope, prefixlen and then ipaddress where longest prefixes first def sorted_ips(family = "inet") raise "bad family #{family}" unless %w{inet inet6}.include? family # priority of ipv6 link scopes to sort by later scope_prio = [ "global", "site", "link", "host", "node", nil ] # grab ipaddress, scope, and iface for sorting later ipaddresses = [] Mash[network["interfaces"]].each do |iface, iface_v| next if iface_v.nil? || !iface_v.key?("addresses") iface_v["addresses"].each do |addr, addr_v| next if addr_v.nil? || (!addr_v.key? "family") || addr_v["family"] != family ipaddresses << { ipaddress: addr_v["prefixlen"] ? IPAddress("#{addr}/#{addr_v["prefixlen"]}") : IPAddress("#{addr}/#{addr_v["netmask"]}"), scope: addr_v["scope"].nil? ? nil : addr_v["scope"].downcase, iface: iface, } end end # sort ip addresses by scope, by prefixlen and then by ip address # 128 - prefixlen: longest prefixes first ipaddresses.sort_by do |v| [ ( scope_prio.index(v[:scope]) || 999999 ), 128 - v[:ipaddress].prefix.to_i, v[:ipaddress].to_i, ] end end # finds ip address / interface for interface with default route based on # passed in family. returns [ipaddress, interface] uses 1st ip if no default # route is found def find_ip(family = "inet") ips = sorted_ips(family) # return if there aren't any #{family} addresses! return [ nil, nil ] if ips.empty? # shortcuts to access default #{family} interface and gateway int_attr = Ohai::Mixin::NetworkHelper::FAMILIES[family] + "_interface" gw_attr = Ohai::Mixin::NetworkHelper::FAMILIES[family] + "_gateway" if network[int_attr] # working with the address(es) of the default network interface gw_if_ips = ips.select do |v| v[:iface] == network[int_attr] end if gw_if_ips.empty? logger.warn("Plugin Network: [#{family}] no ip address on #{network[int_attr]}") elsif network[gw_attr] && network["interfaces"][network[int_attr]] && network["interfaces"][network[int_attr]]["addresses"] if [ "0.0.0.0", "::", /^fe80:/ ].any? { |pat| pat === network[gw_attr] } # link level default route logger.trace("Plugin Network: link level default #{family} route, picking ip from #{network[gw_attr]}") r = gw_if_ips.first else # checking network masks r = gw_if_ips.find do |v| network_contains_address(network[gw_attr], v[:ipaddress], v[:iface]) end if r.nil? r = gw_if_ips.first logger.trace("Plugin Network: [#{family}] no ipaddress/mask on #{network[int_attr]} matching the gateway #{network[gw_attr]}, picking #{r[:ipaddress]}") else logger.trace("Plugin Network: [#{family}] Using default interface #{network[int_attr]} and default gateway #{network[gw_attr]} to set the default ip to #{r[:ipaddress]}") end end else # return the first ip address on network[int_attr] r = gw_if_ips.first end else r = ips.first logger.trace("Plugin Network: [#{family}] no default interface, picking the first ipaddress") end return [ nil, nil ] if r.nil? || r.empty? [ r[:ipaddress].to_s, r[:iface] ] end # select mac address of first interface with family of lladdr def find_mac_from_iface(iface) r = network["interfaces"][iface]["addresses"].select { |k, v| v["family"] == "lladdr" } r.nil? || r.first.nil? ? nil : r.first.first end # address_to_match: String # ipaddress: IPAddress # iface: String def network_contains_address(address_to_match, ipaddress, iface) if ( peer = network["interfaces"][iface]["addresses"][ipaddress.to_s][:peer] ) IPAddress(peer) == IPAddress(address_to_match) else ipaddress.include? IPAddress(address_to_match) end end # ipaddress, ip6address and macaddress are set for each interface by the # #{os}::network plugin. atm it is expected macaddress is set at the same # time as ipaddress. if ipaddress is set and macaddress is nil, that means # the interface ipaddress is bound to has the NOARP flag collect_data do require "ipaddress" unless defined?(IPAddress) results = {} network Mash.new unless network network[:interfaces] ||= Mash.new counters Mash.new unless counters counters[:network] ||= Mash.new # inet family is processed before inet6 to give ipv4 precedence Ohai::Mixin::NetworkHelper::FAMILIES.keys.sort.each do |family| r = {} # find the ip/interface with the default route for this family (r["ip"], r["iface"]) = find_ip(family) r["mac"] = find_mac_from_iface(r["iface"]) unless r["iface"].nil? # don't overwrite attributes if they've already been set by the "#{os}::network" plugin if (family == "inet") && ipaddress.nil? if r["ip"].nil? logger.warn("Plugin Network: unable to detect ipaddress") else ipaddress r["ip"] end elsif (family == "inet6") && ip6address.nil? if r["ip"].nil? logger.trace("Plugin Network: unable to detect ip6address") else ip6address r["ip"] end end # set the macaddress [only if we haven't already]. this allows the #{os}::network plugin to set macaddress # otherwise we set macaddress on a first-found basis (and we started with ipv4) if macaddress.nil? if r["mac"] logger.trace("Plugin Network: setting macaddress to '#{r["mac"]}' from interface '#{r["iface"]}' for family '#{family}'") macaddress r["mac"] else logger.trace("Plugin Network: unable to detect macaddress for family '#{family}'") end end results[family] = r end if results["inet"]["iface"] && results["inet6"]["iface"] && (results["inet"]["iface"] != results["inet6"]["iface"]) logger.trace("Plugin Network: ipaddress and ip6address are set from different interfaces (#{results["inet"]["iface"]} & #{results["inet6"]["iface"]})") end end end ohai-16.13.0/lib/ohai/plugins/dragonflybsd/0000755000175100017510000000000014034105661017455 5ustar pravipraviohai-16.13.0/lib/ohai/plugins/dragonflybsd/network.rb0000644000175100017510000001137714034105661021504 0ustar pravipravi# frozen_string_literal: true # # Author:: Bryan McLellan (btm@loftninjas.org) # 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(:Network) do provides "network", "network/interfaces" provides "counters/network", "counters/network/interfaces" collect_data(:dragonflybsd) do network Mash.new unless network network[:interfaces] ||= Mash.new counters Mash.new unless counters counters[:network] ||= Mash.new so = shell_out("route -n get default") so.stdout.lines do |line| if line =~ /(\w+): ([\w\.]+)/ case $1 when "gateway" network[:default_gateway] = $2 when "interface" network[:default_interface] = $2 end end end iface = Mash.new so = shell_out("#{Ohai.abs_path( "/sbin/ifconfig" )} -a") cint = nil so.stdout.lines do |line| if line =~ /^([0-9a-zA-Z\.]+):\s+/ cint = $1 iface[cint] = Mash.new if cint =~ /^(\w+)(\d+.*)/ iface[cint][:type] = $1 iface[cint][:number] = $2 end end # call the family lladdr to match linux for consistency if line =~ /\s+ether (.+?)\s/ iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "lladdr" } end if line =~ /\s+inet ([\d.]+) netmask ([\da-fx]+)\s*\w*\s*([\d.]*)/ iface[cint][:addresses] ||= Mash.new # convert the netmask to decimal for consistency netmask = "#{$2[2, 2].hex}.#{$2[4, 2].hex}.#{$2[6, 2].hex}.#{$2[8, 2].hex}" if $3.empty? iface[cint][:addresses][$1] = { "family" => "inet", "netmask" => netmask } else # found a broadcast address iface[cint][:addresses][$1] = { "family" => "inet", "netmask" => netmask, "broadcast" => $3 } end end if line =~ /\s+inet6 ([a-f0-9\:]+)%?(\w*)\s+prefixlen\s+(\d+)\s*\w*\s*([\da-fx]*)/ iface[cint][:addresses] ||= Mash.new if $4.empty? iface[cint][:addresses][$1] = { "family" => "inet6", "prefixlen" => $3 } else # found a zone_id / scope iface[cint][:addresses][$1] = { "family" => "inet6", "zoneid" => $2, "prefixlen" => $3, "scopeid" => $4 } end end if line =~ /flags=\d+<(.+)>/ flags = $1.split(",") iface[cint][:flags] = flags if flags.length > 0 end if line =~ /metric: (\d+) mtu: (\d+)/ iface[cint][:metric] = $1 iface[cint][:mtu] = $2 end end so = shell_out("arp -an") so.stdout.lines do |line| if line =~ /\((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\) at ([a-fA-F0-9\:]+) on ([0-9a-zA-Z\.\:\-]+)/ next unless iface[$3] # this should never happen iface[$3][:arp] ||= Mash.new iface[$3][:arp][$1] = $2.downcase end end network["interfaces"] = iface net_counters = Mash.new # From netstat(1), not sure of the implications: # Show the state of all network interfaces or a single interface # which have been auto-configured (interfaces statically configured # into a system, but not located at boot time are not shown). so = shell_out("netstat -ibdn") so.stdout.lines do |line| # Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll Drop # ed0 1500 54:52:00:68:92:85 333604 26 151905886 175472 0 24897542 0 905 # $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 if line =~ /^([\w\.\*]+)\s+\d+\s+\s+([\w:]*)\s*(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/ net_counters[$1] ||= Mash.new net_counters[$1]["rx"] ||= Mash.new net_counters[$1]["tx"] ||= Mash.new net_counters[$1]["rx"]["packets"] = $3 net_counters[$1]["rx"]["errors"] = $4 net_counters[$1]["rx"]["bytes"] = $5 net_counters[$1]["tx"]["packets"] = $6 net_counters[$1]["tx"]["errors"] = $7 net_counters[$1]["tx"]["bytes"] = $8 net_counters[$1]["tx"]["collisions"] = $9 net_counters[$1]["tx"]["dropped"] = $10 end end counters[:network][:interfaces] = net_counters end end ohai-16.13.0/lib/ohai/plugins/dragonflybsd/memory.rb0000644000175100017510000000452214034105661021315 0ustar pravipravi# frozen_string_literal: true # # Author:: Bryan McLellan (btm@loftninjas.org) # 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(:Memory) do provides "memory", "memory/swap" collect_data(:dragonflybsd) do memory Mash.new memory[:swap] = Mash.new # /usr/src/sys/sys/vmmeter.h so = shell_out("sysctl -n vm.stats.vm.v_page_size") memory[:page_size] = so.stdout.strip so = shell_out("sysctl -n vm.stats.vm.v_page_count") memory[:page_count] = so.stdout.strip memory[:total] = memory[:page_size].to_i * memory[:page_count].to_i so = shell_out("sysctl -n vm.stats.vm.v_free_count") memory[:free] = memory[:page_size].to_i * so.stdout.strip.to_i so = shell_out("sysctl -n vm.status.vm.v_active_count") memory[:active] = memory[:page_size].to_i * so.stdout.strip.to_i so = shell_out("sysctl -n vm.status.vm.v_inactive_count") memory[:inactive] = memory[:page_size].to_i * so.stdout.strip.to_i so = shell_out("sysctl -n vm.stats.vm.v_cache_count") memory[:cache] = memory[:page_size].to_i * so.stdout.strip.to_i so = shell_out("sysctl -n vm.stats.vm.v_wire_count") memory[:wired] = memory[:page_size].to_i * so.stdout.strip.to_i so = shell_out("sysctl -n vfs.bufspace") memory[:buffers] = so.stdout.strip so = shell_out("swapinfo") so.stdout.lines do |line| # Device 1K-blocks Used Avail Capacity # /dev/ad0s1b 253648 0 253648 0% if line =~ %r{^([\d\w/]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+([\d\%]+)} mdev = $1 memory[:swap][mdev] = Mash.new memory[:swap][mdev][:total] = $2 memory[:swap][mdev][:used] = $3 memory[:swap][mdev][:free] = $4 memory[:swap][mdev][:percent_free] = $5 end end end end ohai-16.13.0/lib/ohai/plugins/dragonflybsd/platform.rb0000644000175100017510000000174314034105661021633 0ustar pravipravi# frozen_string_literal: true # # Author:: Bryan McLellan (btm@loftninjas.org) # 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(:Platform) do provides "platform", "platform_version", "platform_family" collect_data(:dragonflybsd) do platform shell_out("uname -s").stdout.strip.downcase platform_version shell_out("uname -r").stdout.strip platform_family "dragonflybsd" end end ohai-16.13.0/lib/ohai/plugins/java.rb0000644000175100017510000000515414034105661016252 0ustar pravipravi# frozen_string_literal: true # # Author:: Benjamin Black () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Java) do provides "languages/java" depends "languages" def get_java_info so = shell_out("java -mx64m -version") # Sample output: # java version "1.8.0_60" # Java(TM) SE Runtime Environment (build 1.8.0_60-b27) # Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode) if so.exitstatus == 0 java = Mash.new so.stderr.split(/\r?\n/).each do |line| case line when /(?:java|openjdk) version \"([0-9\.\_]+)\"/ java[:version] = $1 when /^(.+Runtime Environment.*) \((build)\s*(.+)\)$/ java[:runtime] = { "name" => $1, "build" => $3 } when /^(.+ (Client|Server) VM) \(build\s*(.+)\)$/ java[:hotspot] = { "name" => $1, "build" => $3 } end end languages[:java] = java unless java.empty? end rescue Ohai::Exceptions::Exec logger.trace('Plugin Java: Could not shell_out "java -mx64m -version". Skipping plugin') end # On Mac OS X, the development tools include "stubs" for JVM executables that # prompt the user to install the JVM if they desire. In our case we simply # wish to detect if the JVM is there and do not want to trigger a popup # window. As a workaround, we can run the java_home executable and check its # exit status to determine if the `java` executable is the real one or the OS # X stub. In the terminal, it looks like this: # # $ /usr/libexec/java_home # Unable to find any JVMs matching version "(null)". # No Java runtime present, try --request to install. # # $ echo $? # 1 # # This check always returns true when not on darwin because it is just a # workaround for this particular annoyance. def has_real_java? return true unless on_darwin? shell_out("/usr/libexec/java_home").status.success? end def on_darwin? RUBY_PLATFORM.downcase.include?("darwin") end collect_data do get_java_info if has_real_java? end end ohai-16.13.0/lib/ohai/plugins/ssh_host_key.rb0000644000175100017510000000543114034105661020031 0ustar pravipravi# frozen_string_literal: true # # Author:: Bryan McLellan # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:SSHHostKey) do provides "keys/ssh" depends "keys" def extract_keytype?(content) case content[0] when "ssh-dss" [ "dsa", nil ] when "ssh-rsa" [ "rsa", nil ] when /^ecdsa/ [ "ecdsa", content[0] ] when "ssh-ed25519" [ "ed25519", nil ] else [ nil, nil ] end end collect_data do keys[:ssh] = Mash.new sshd_config = if file_exist?("/etc/ssh/sshd_config") "/etc/ssh/sshd_config" elsif file_exist?("/etc/sshd_config") # Darwin "/etc/sshd_config" else logger.trace("Plugin SSHHostKey: Failed to find sshd configuration file") nil end if sshd_config file_open(sshd_config) do |conf| conf.each_line do |line| if /^hostkey\s/i.match?(line) pub_file = "#{line.split[1]}.pub" content = file_read(pub_file).split key_type, key_subtype = extract_keytype?(content) keys[:ssh]["host_#{key_type}_public"] = content[1] unless key_type.nil? keys[:ssh]["host_#{key_type}_type"] = key_subtype unless key_subtype.nil? end end end end if keys[:ssh][:host_dsa_public].nil? && file_exist?("/etc/ssh/ssh_host_dsa_key.pub") keys[:ssh][:host_dsa_public] = file_read("/etc/ssh/ssh_host_dsa_key.pub").split[1] end if keys[:ssh][:host_rsa_public].nil? && file_exist?("/etc/ssh/ssh_host_rsa_key.pub") keys[:ssh][:host_rsa_public] = file_read("/etc/ssh/ssh_host_rsa_key.pub").split[1] end if keys[:ssh][:host_ecdsa_public].nil? && file_exist?("/etc/ssh/ssh_host_ecdsa_key.pub") content = file_read("/etc/ssh/ssh_host_ecdsa_key.pub") keys[:ssh][:host_ecdsa_public] = content.split[1] keys[:ssh][:host_ecdsa_type] = content.split[0] end if keys[:ssh][:host_ed25519_public].nil? && file_exist?("/etc/ssh/ssh_host_ed25519_key.pub") keys[:ssh][:host_ed25519_public] = file_read("/etc/ssh/ssh_host_ed25519_key.pub").split[1] end end end ohai-16.13.0/lib/ohai/plugins/cloud.rb0000644000175100017510000002557714034105661016452 0ustar pravipravi# frozen_string_literal: true # # Author:: Cary Penniman () # 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(:Cloud) do provides "cloud" depends "ec2" depends "gce" depends "rackspace" depends "eucalyptus" depends "linode" depends "openstack" depends "azure" depends "digital_ocean" depends "softlayer" # Class to help enforce the interface exposed to node[:cloud] (OHAI-542) # # cloud[:provider] - (String) the cloud provider the VM is running on. # # cloud[:public_hostname] - (String) a fully qualified hostname # cloud[:local_hostname] - (String) a hostname resolvable on the internal (private) network # # cloud[:public_ipv4_addrs] - (Array) a list of all publicly accessible IPv4 addresses # cloud[:local_ipv4_addrs] - (Array) a list of all private IPv4 addresses # cloud[:public_ipv4] - (String) the first public IPv4 address detected # cloud[:local_ipv4] - (String) the first private IPv4 address detected # # cloud[:public_ipv6_addrs] - (Array) a list of all publicly accessible IPv6 addresses # cloud[:local_ipv6_addrs] - (Array) a list of all private IPv6 addresses # cloud[:public_ipv6] - (String) the first public IPv6 address detected # cloud[:local_ipv6] - (String) the first private IPv6 address detected # class CloudAttrs attr_writer :provider, :public_hostname, :local_hostname def initialize @cloud = Mash.new end def add_ipv4_addr(ip, accessibility) return if ip.nil? # just skip if ip is nil ipaddr = validate_ip_addr(ip, :ipv4) case accessibility when :public @cloud[:public_ipv4_addrs] ||= [] @cloud[:public_ipv4_addrs] << ipaddr.to_s when :private @cloud[:local_ipv4_addrs] ||= [] @cloud[:local_ipv4_addrs] << ipaddr.to_s else raise "ERROR: invalid accessibility param of '#{accessibility}'. must be :public or :private." end end def add_ipv6_addr(ip, accessibility) return if ip.nil? # just skip if ip is nil ipaddr = validate_ip_addr(ip, :ipv6) raise "ERROR: invalid ipv6 address of '#{ip}' detected. " unless ipaddr.ipv6? case accessibility when :public @cloud[:public_ipv6_addrs] ||= [] @cloud[:public_ipv6_addrs] << ipaddr.to_s when :private @cloud[:local_ipv6_addrs] ||= [] @cloud[:local_ipv6_addrs] << ipaddr.to_s else raise "ERROR: invalid accessibility param of '#{accessibility}'. must be :public or :private." end end def cloud_mash @cloud[:provider] = @provider if @provider @cloud[:public_hostname] = @public_hostname if @public_hostname @cloud[:local_hostname] = @local_hostname if @local_hostname @cloud[:public_ipv4] = @cloud[:public_ipv4_addrs][0] if @cloud[:public_ipv4_addrs] @cloud[:local_ipv4] = @cloud[:local_ipv4_addrs][0] if @cloud[:local_ipv4_addrs] @cloud[:public_ipv6] = @cloud[:public_ipv6_addrs][0] if @cloud[:public_ipv6_addrs] @cloud[:local_ipv6] = @cloud[:local_ipv6_addrs][0] if @cloud[:local_ipv6_addrs] # if empty, return nil @cloud.empty? ? nil : @cloud end private def validate_ip_addr(ip, address_family = :ipv4) ipaddr = "" begin ipaddr = IPAddr.new(ip) raise ArgumentError, "not valid #{address_family} address" unless address_family == :ipv4 ? ipaddr.ipv4? : ipaddr.ipv6? rescue ArgumentError => e raise "ERROR: the ohai 'cloud' plugin failed with an IP address of '#{ip}' : #{e.message}" end ipaddr end end #--------------------------------------- # Google Compute Engine (gce) #-------------------------------------- def on_gce? gce != nil end def get_gce_values public_ips = gce["instance"]["networkInterfaces"].collect do |interface| if interface.key?("accessConfigs") interface["accessConfigs"].collect { |ac| ac["externalIp"] unless ac["externalIp"] == "" } end end.flatten.compact private_ips = gce["instance"]["networkInterfaces"].collect do |interface| interface["ip"] end.compact public_ips.each { |ipaddr| @cloud_attr_obj.add_ipv4_addr(ipaddr, :public) } private_ips.each { |ipaddr| @cloud_attr_obj.add_ipv4_addr(ipaddr, :private) } @cloud_attr_obj.local_hostname = gce["instance"]["hostname"] @cloud_attr_obj.provider = "gce" end # ---------------------------------------- # ec2 # ---------------------------------------- # Is current cloud ec2? # # === Return # true:: If ec2 Hash is defined # false:: Otherwise def on_ec2? ec2 != nil end # Fill cloud hash with ec2 values def get_ec2_values @cloud_attr_obj.add_ipv4_addr(ec2["public_ipv4"], :public) @cloud_attr_obj.add_ipv4_addr(ec2["local_ipv4"], :private) @cloud_attr_obj.public_hostname = ec2["public_hostname"] @cloud_attr_obj.local_hostname = ec2["local_hostname"] @cloud_attr_obj.provider = "ec2" end # ---------------------------------------- # rackspace # ---------------------------------------- # Is current cloud rackspace? # # === Return # true:: If rackspace Hash is defined # false:: Otherwise def on_rackspace? rackspace != nil end # Fill cloud hash with rackspace values def get_rackspace_values @cloud_attr_obj.add_ipv4_addr(rackspace["public_ipv4"], :public) @cloud_attr_obj.add_ipv4_addr(rackspace["local_ipv4"], :private) @cloud_attr_obj.add_ipv6_addr(rackspace["public_ipv6"], :public) @cloud_attr_obj.add_ipv6_addr(rackspace["local_ipv6"], :private) @cloud_attr_obj.public_hostname = rackspace["public_hostname"] @cloud_attr_obj.local_hostname = rackspace["local_hostname"] @cloud_attr_obj.provider = "rackspace" end # ---------------------------------------- # linode # ---------------------------------------- # Is current cloud linode? # # === Return # true:: If linode Hash is defined # false:: Otherwise def on_linode? linode != nil end # Fill cloud hash with linode values def get_linode_values @cloud_attr_obj.add_ipv4_addr(linode["public_ip"], :public) @cloud_attr_obj.add_ipv4_addr(linode["private_ip"], :private) @cloud_attr_obj.public_hostname = linode["public_hostname"] @cloud_attr_obj.local_hostname = linode["local_hostname"] @cloud_attr_obj.provider = "linode" end # ---------------------------------------- # eucalyptus # ---------------------------------------- # Is current cloud eucalyptus? # # === Return # true:: If eucalyptus Hash is defined # false:: Otherwise def on_eucalyptus? eucalyptus != nil end def get_eucalyptus_values @cloud_attr_obj.add_ipv4_addr(eucalyptus["public_ipv4"], :public) @cloud_attr_obj.add_ipv4_addr(eucalyptus["local_ipv4"], :private) @cloud_attr_obj.public_hostname = eucalyptus["public_hostname"] @cloud_attr_obj.local_hostname = eucalyptus["local_hostname"] @cloud_attr_obj.provider = "eucalyptus" end # ---------------------------------------- # openstack # ---------------------------------------- # Is current cloud openstack-based? # # === Return # true:: If openstack Hash is defined # false:: Otherwise def on_openstack? openstack != nil end # Fill cloud hash with openstack values def get_openstack_values @cloud_attr_obj.add_ipv4_addr(openstack["public_ipv4"], :public) @cloud_attr_obj.add_ipv4_addr(openstack["local_ipv4"], :private) @cloud_attr_obj.public_hostname = openstack["public_hostname"] @cloud_attr_obj.local_hostname = openstack["local_hostname"] @cloud_attr_obj.provider = openstack["provider"] end # ---------------------------------------- # azure # ---------------------------------------- # Is current cloud azure? # # === Return # true:: If azure Hash is defined # false:: Otherwise def on_azure? azure != nil end # Fill cloud hash with azure values def get_azure_values azure["metadata"]["network"]["public_ipv4"].each { |ipaddr| @cloud_attr_obj.add_ipv4_addr(ipaddr, :public) } azure["metadata"]["network"]["public_ipv6"].each { |ipaddr| @cloud_attr_obj.add_ipv6_addr(ipaddr, :public) } azure["metadata"]["network"]["local_ipv4"].each { |ipaddr| @cloud_attr_obj.add_ipv4_addr(ipaddr, :private) } azure["metadata"]["network"]["local_ipv6"].each { |ipaddr| @cloud_attr_obj.add_ipv6_addr(ipaddr, :private) } @cloud_attr_obj.public_hostname = azure["public_fqdn"] @cloud_attr_obj.provider = "azure" end # ---------------------------------------- # digital_ocean # ---------------------------------------- # Is current cloud digital_ocean? # # === Return # true:: If digital_ocean Mash is defined # false:: Otherwise def on_digital_ocean? digital_ocean != nil end # Fill cloud hash with digital_ocean values def get_digital_ocean_values @cloud_attr_obj.add_ipv4_addr(digital_ocean["interfaces"]["public"][0]["ipv4"]["ip_address"], :public) rescue NoMethodError @cloud_attr_obj.add_ipv4_addr(digital_ocean["interfaces"]["private"][0]["ipv4"]["ip_address"], :private) rescue NoMethodError @cloud_attr_obj.add_ipv6_addr(digital_ocean["interfaces"]["public"][0]["ipv6"]["ip_address"], :public) rescue NoMethodError @cloud_attr_obj.add_ipv6_addr(digital_ocean["interfaces"]["private"][0]["ipv6"]["ip_address"], :private) rescue NoMethodError @cloud_attr_obj.provider = "digital_ocean" end # ---------------------------------------- # softlayer # ---------------------------------------- # Is current cloud softlayer? # # === Return # true:: If softlayer Hash is defined # false:: Otherwise def on_softlayer? softlayer != nil end # Fill cloud hash with softlayer values def get_softlayer_values @cloud_attr_obj.add_ipv4_addr(softlayer["public_ipv4"], :public) @cloud_attr_obj.add_ipv4_addr(softlayer["local_ipv4"], :private) @cloud_attr_obj.public_hostname = softlayer["public_fqdn"] @cloud_attr_obj.provider = "softlayer" end collect_data do require "ipaddr" unless defined?(IPAddr) @cloud_attr_obj = CloudAttrs.new get_gce_values if on_gce? get_ec2_values if on_ec2? get_rackspace_values if on_rackspace? get_linode_values if on_linode? get_eucalyptus_values if on_eucalyptus? get_openstack_values if on_openstack? get_azure_values if on_azure? get_digital_ocean_values if on_digital_ocean? get_softlayer_values if on_softlayer? cloud @cloud_attr_obj.cloud_mash end end ohai-16.13.0/lib/ohai/plugins/darwin/0000755000175100017510000000000014034105661016263 5ustar pravipraviohai-16.13.0/lib/ohai/plugins/darwin/network.rb0000644000175100017510000001625414034105661020311 0ustar pravipravi# frozen_string_literal: true # # Author:: Benjamin Black () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Network) do require_relative "../../mixin/network_helper" provides "network", "network/interfaces" provides "counters/network", "counters/network/interfaces" include Ohai::Mixin::NetworkHelper def parse_media(media_string) media = {} line_array = media_string.split 0.upto(line_array.length - 1) do |i| unless line_array[i].eql?("none") if line_array[i + 1] =~ /^\<([a-zA-Z\-\,]+)\>$/ media[line_array[i]] = {} unless media.key?(line_array[i]) if media[line_array[i]].key?("options") $1.split(",").each do |opt| media[line_array[i]]["options"] << opt unless media[line_array[i]]["options"].include?(opt) end else media[line_array[i]]["options"] = $1.split(",") end elsif line_array[i].eql?("autoselect") media["autoselect"] = {} unless media.key?("autoselect") media["autoselect"]["options"] = [] end else media["none"] = { "options" => [] } end end media end def darwin_encaps_lookup(ifname) return "Loopback" if ifname.eql?("lo") return "1394" if ifname.eql?("fw") return "IPIP" if ifname.eql?("gif") return "6to4" if ifname.eql?("stf") return "dot1q" if ifname.eql?("vlan") "Unknown" end def scope_lookup(scope) return "Node" if scope.eql?("::1") return "Link" if /^fe80\:/.match?(scope) return "Site" if /^fec0\:/.match?(scope) "Global" end def excluded_setting?(setting) setting.match("_sw_cksum") end def locate_interface(ifaces, ifname, mac) return ifname unless ifaces[ifname].nil? # oh well, time to go hunting! return ifname.chop if /\*$/.match?(ifname) ifaces.each_key do |ifc| ifaces[ifc][:addresses].each_key do |addr| return ifc if addr.eql? mac end end nil end collect_data(:darwin) do network Mash.new unless network network[:interfaces] ||= Mash.new counters Mash.new unless counters counters[:network] ||= Mash.new so = shell_out("route -n get default") so.stdout.lines do |line| if line =~ /(\w+): ([\w\.]+)/ case $1 when "gateway" network[:default_gateway] = $2 when "interface" network[:default_interface] = $2 end end end iface = Mash.new so = shell_out("ifconfig -a") cint = nil so.stdout.lines do |line| if line =~ /^([0-9a-zA-Z\.\:\-]+): \S+ mtu (\d+)$/ cint = $1 iface[cint] ||= Mash.new iface[cint][:addresses] ||= Mash.new iface[cint][:mtu] = $2 if line =~ /\sflags\=\d+\<((UP|BROADCAST|DEBUG|SMART|SIMPLEX|LOOPBACK|POINTOPOINT|NOTRAILERS|RUNNING|NOARP|PROMISC|ALLMULTI|SLAVE|MASTER|MULTICAST|DYNAMIC|,)+)\>\s/ flags = $1.split(",") else flags = [] end iface[cint][:flags] = flags.flatten if cint =~ /^(\w+)(\d+.*)/ iface[cint][:type] = $1 iface[cint][:number] = $2 iface[cint][:encapsulation] = darwin_encaps_lookup($1) end end if line =~ /^\s+ether ([0-9a-f\:]+)/ iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "lladdr" } iface[cint][:encapsulation] = "Ethernet" end if line =~ /^\s+lladdr ([0-9a-f\:]+)\s/ iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "lladdr" } end if line =~ /\s+inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) netmask 0x(([0-9a-f]){1,8})\s*$/ iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "inet", "netmask" => hex_to_dec_netmask($2) } end if line =~ /\s+inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) netmask 0x(([0-9a-f]){1,8}) broadcast (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "inet", "netmask" => hex_to_dec_netmask($2), "broadcast" => $4 } end if line =~ /\s+inet6 ([a-f0-9\:]+)(\s*|(\%[a-z0-9]+)\s*) prefixlen (\d+)\s*/ iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "inet6", "prefixlen" => $4, "scope" => scope_lookup($1) } end if line =~ /\s+inet6 ([a-f0-9\:]+)(\s*|(\%[a-z0-9]+)\s*) prefixlen (\d+) scopeid 0x([a-f0-9]+)/ iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "inet6", "prefixlen" => $4, "scope" => scope_lookup($1) } end if line =~ /^\s+media: ((\w+)|(\w+ [a-zA-Z0-9\-\<\>]+)) status: (\w+)/ iface[cint][:media] ||= Mash.new iface[cint][:media][:selected] = parse_media($1) iface[cint][:status] = $4 end if line =~ /^\s+supported media: (.*)/ iface[cint][:media] ||= Mash.new iface[cint][:media][:supported] = parse_media($1) end end so = shell_out("arp -an") so.stdout.lines do |line| if line =~ /^\S+ \((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\) at ([a-fA-F0-9\:]+) on ([a-zA-Z0-9\.\:\-]+).*\[(\w+)\]/ # MAC addr really should be normalized to include all the zeroes. next if iface[$3].nil? # this should never happen iface[$3][:arp] ||= Mash.new iface[$3][:arp][$1] = $2 end end settings = Mash.new so = shell_out("sysctl net") so.stdout.lines do |line| if line =~ /^([a-zA-Z0-9\.\_]+)\: (.*)/ # should normalize names between platforms for the same settings. settings[$1] = $2 unless excluded_setting?($1) end end network[:settings] = settings network[:interfaces] = iface net_counters = Mash.new so = shell_out("netstat -i -d -l -b -n") so.stdout.lines do |line| if line =~ /^([a-zA-Z0-9\.\:\-\*]+)\s+\d+\s+\<[a-zA-Z0-9\#]+\>\s+([a-f0-9\:]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/ || line =~ /^([a-zA-Z0-9\.\:\-\*]+)\s+\d+\s+\<[a-zA-Z0-9\#]+\>(\s+)(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/ ifname = locate_interface(iface, $1, $2) next if iface[ifname].nil? # this shouldn't happen, but just in case net_counters[ifname] ||= Mash.new net_counters[ifname] = { rx: { bytes: $5, packets: $3, errors: $4, drop: 0, overrun: 0, frame: 0, compressed: 0, multicast: 0 }, tx: { bytes: $8, packets: $6, errors: $7, drop: 0, overrun: 0, collisions: $9, carrier: 0, compressed: 0 }, } end end counters[:network][:interfaces] = net_counters end end ohai-16.13.0/lib/ohai/plugins/darwin/memory.rb0000644000175100017510000000371414034105661020125 0ustar pravipravi# frozen_string_literal: true # # Author:: Patrick Collins () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Memory) do provides "memory" collect_data(:darwin) do memory Mash.new installed_memory = shell_out("sysctl -n hw.memsize").stdout.to_i / 1024 / 1024.0 memory[:total] = "#{installed_memory.to_i}MB" total_consumed = 0 active = 0 inactive = 0 vm_stat = shell_out("vm_stat").stdout vm_stat_match = /page size of (\d+) bytes/.match(vm_stat) page_size = if vm_stat_match && vm_stat_match[1] vm_stat_match[1].to_i else 4096 end vm_stat.split("\n").each do |line| ["wired down", "active", "inactive"].each do |match| unless line.index("Pages #{match}:").nil? pages = line.split.last.to_i megabyte_val = (pages * page_size) / 1024 / 1024.0 total_consumed += megabyte_val case match when "wired down", "active" active += megabyte_val.to_i when "inactive" inactive += megabyte_val.to_i end end end end memory[:active] = "#{active}MB" if active > 0 memory[:inactive] = "#{inactive}MB" if inactive > 0 free_memory = installed_memory - total_consumed memory[:free] = "#{free_memory.to_i}MB" if total_consumed > 0 end end ohai-16.13.0/lib/ohai/plugins/darwin/virtualization.rb0000644000175100017510000000477614034105661021712 0ustar pravipravi# frozen_string_literal: true # # Author:: Pavel Yudin () # Author:: Tim Smith () # Copyright:: Copyright (c) 2015 Pavel Yudin # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Virtualization) do provides "virtualization" depends "hardware" def vboxmanage_exists? which("VBoxManage") end def prlctl_exists? which("prlctl") end def ioreg_exists? which("ioreg") end def fusion_exists? file_exist?("/Applications/VMware\ Fusion.app/") end def docker_exists? which("docker") end collect_data(:darwin) do virtualization Mash.new unless virtualization virtualization[:systems] ||= Mash.new if docker_exists? virtualization[:system] = "docker" virtualization[:role] = "host" virtualization[:systems][:docker] = "host" end if vboxmanage_exists? virtualization[:system] = "vbox" virtualization[:role] = "host" virtualization[:systems][:vbox] = "host" end if hardware[:boot_rom_version].match?(/VirtualBox/i) virtualization[:system] = "vbox" virtualization[:role] = "guest" virtualization[:systems][:vbox] = "guest" end if fusion_exists? virtualization[:system] = "vmware" virtualization[:role] = "host" virtualization[:systems][:vmware] = "host" end if hardware[:boot_rom_version].match?(/VMW/i) virtualization[:system] = "vmware" virtualization[:role] = "guest" virtualization[:systems][:vmware] = "guest" end if prlctl_exists? virtualization[:system] = "parallels" virtualization[:role] = "host" virtualization[:systems][:parallels] = "host" elsif ioreg_exists? so = shell_out("ioreg -l") if /pci1ab8,4000/.match?(so.stdout) virtualization[:system] = "parallels" virtualization[:role] = "guest" virtualization[:systems][:parallels] = "guest" end end end end ohai-16.13.0/lib/ohai/plugins/darwin/hardware.rb0000644000175100017510000000702314034105661020407 0ustar pravipravi# frozen_string_literal: true # # Author:: Nate Walck () # Copyright:: Copyright (c) 2016-present Facebook, 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. # Ohai.plugin(:Hardware) do provides "hardware" def system_profiler(datatype) sp_cmd = "system_profiler #{datatype} -xml" # Hardware queries sp_std = shell_out(sp_cmd) Plist.parse_xml(sp_std.stdout) end collect_data(:darwin) do unless hardware hardware Mash.new else logger.trace("Plugin Hardware: namespace already exists") next end require "plist" hw_hash = system_profiler("SPHardwareDataType") hw_hash[0]["_items"][0].delete("_name") hardware.merge!(hw_hash[0]["_items"][0]) # ProductName: Mac OS X # ProductVersion: 10.15.6 # BuildVersion: 19G46c shell_out("sw_vers").stdout.lines.each do |line| case line when /^ProductName:\s*(.*)$/ hardware["operating_system"] = Regexp.last_match[1].strip when /^ProductVersion:\s*(.*)$/ hardware["operating_system_version"] = Regexp.last_match[1].strip when /^BuildVersion:\s*(.*)$/ hardware["build_version"] = Regexp.last_match[1].strip end end hardware["architecture"] = shell_out("uname -m").stdout.strip # Storage queries storage = [] storage_hash = system_profiler("SPStorageDataType") drives = storage_hash[0]["_items"] drives.each do |drive_entry| drive = Mash.new drive[:name] = drive_entry["_name"] drive[:bsd_name] = drive_entry["bsd_name"] drive[:capacity] = drive_entry["size_in_bytes"] if drive_entry.key?("com.apple.corestorage.pv") drive[:drive_type] = drive_entry["com.apple.corestorage.pv"][0]["medium_type"] drive[:smart_status] = drive_entry["com.apple.corestorage.pv"][0]["smart_status"] drive[:partitions] = drive_entry["com.apple.corestorage.pv"].count end storage << drive end hardware["storage"] = storage # Battery queries battery_hash = system_profiler("SPPowerDataType") power_entries = battery_hash[0]["_items"] battery = Mash.new power_entries.each do |entry| if entry.value?("spbattery_information") charge = entry["sppower_battery_charge_info"] health = entry["sppower_battery_health_info"] battery[:current_capacity] = charge["sppower_battery_current_capacity"] battery[:max_capacity] = charge["sppower_battery_max_capacity"] battery[:fully_charged] = charge["sppower_battery_fully_charged"].eql?("TRUE") battery[:is_charging] = charge["sppower_battery_is_charging"].eql?("TRUE") battery[:charge_cycle_count] = health["sppower_battery_cycle_count"] battery[:health] = health["sppower_battery_health"] battery[:serial] = entry["sppower_battery_model_info"]["sppower_battery_serial_number"] battery[:remaining] = (battery["current_capacity"].to_f / battery["max_capacity"].to_f * 100).to_i end end hardware[:battery] = battery end end ohai-16.13.0/lib/ohai/plugins/darwin/platform.rb0000644000175100017510000000227114034105661020436 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Platform) do provides "platform", "platform_version", "platform_build", "platform_family" collect_data(:darwin) do so = shell_out(Ohai.abs_path( "/usr/bin/sw_vers" ).to_s) so.stdout.lines do |line| case line when /^ProductVersion:\s+(.+)$/ platform_version $1 when /^BuildVersion:\s+(.+)$/ platform_build $1 end end # if we're on darwin assume we're on mac_os_x platform "mac_os_x" platform_family "mac_os_x" end end ohai-16.13.0/lib/ohai/plugins/scaleway.rb0000644000175100017510000000366114034105661017142 0ustar pravipravi# frozen_string_literal: true # # Author:: Jonathan Amiez () # 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(:Scaleway) do require_relative "../mixin/scaleway_metadata" require_relative "../mixin/http_helper" include Ohai::Mixin::ScalewayMetadata include Ohai::Mixin::HttpHelper provides "scaleway" # looks for `scaleway` keyword in kernel command line # @return [Boolean] do we have the keyword or not? def has_scaleway_cmdline? if file_exist?("/proc/cmdline") && /scaleway/.match?(file_read("/proc/cmdline")) logger.trace("Plugin Scaleway: has_scaleway_cmdline? == true") return true end logger.trace("Plugin Scaleway: has_scaleway_cmdline? == false") false end # a single check that combines all the various detection methods for Scaleway # @return [Boolean] Does the system appear to be on Scaleway def looks_like_scaleway? return true if hint?("scaleway") return true if has_scaleway_cmdline? && can_socket_connect?(Ohai::Mixin::ScalewayMetadata::SCALEWAY_METADATA_ADDR, 80) false end collect_data(:linux) do if looks_like_scaleway? logger.trace("Plugin Scaleway: looks_like_scaleway? == true") scaleway Mash.new fetch_metadata.each do |k, v| scaleway[k] = v end else logger.trace("Plugin Scaleway: No hints present for and doesn't look like scaleway") end end end ohai-16.13.0/lib/ohai/plugins/root_group.rb0000644000175100017510000000320614034105661017524 0ustar pravipravi# frozen_string_literal: true # # Author:: Joseph Anthony Pasquale Holsten () # Copyright:: Copyright (c) 2013 Joseph Anthony Pasquale Holsten # 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(:RootGroup) do provides "root_group" collect_data(:windows) do require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) wmi = WmiLite::Wmi.new # Per http://support.microsoft.com/kb/243330 SID: S-1-5-32-544 is the # internal name for the Administrators group, which lets us work # properly in environments with a renamed or localized name for the # Administrators group. # Use LocalAccount=True because otherwise WMI will attempt to include # (unneeded) Active Directory groups by querying AD, which is a performance # and reliability issue since AD might not be reachable. groups = wmi.query("select * from Win32_Group where sid like 'S-1-5-32-544' and LocalAccount=True") windows_root_group_name = groups[0]["name"] root_group windows_root_group_name end collect_data(:default) do root_group Etc.getgrgid(Etc.getpwnam("root").gid).name end end ohai-16.13.0/lib/ohai/plugins/eucalyptus.rb0000644000175100017510000000565414034105661017534 0ustar pravipravi# frozen_string_literal: true # # Author:: Tim Dysinger () # Author:: Benjamin Black () # Author:: Christopher Brown () # Copyright:: Copyright (c) Chef Software 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. Ohai.plugin(:Eucalyptus) do # eucalyptus metadata service is compatible with the ec2 service calls require_relative "../mixin/ec2_metadata" require_relative "../mixin/http_helper" include Ohai::Mixin::Ec2Metadata include Ohai::Mixin::HttpHelper provides "eucalyptus" depends "network/interfaces" MAC_MATCH = /^[dD]0:0[dD]:/.freeze unless defined?(MAC_MATCH) # returns the mac address from the collection of all address types def get_mac_address(addresses) detected_addresses = addresses.detect { |address, keypair| keypair == { "family" => "lladdr" } } if detected_addresses detected_addresses.first else "" end end # detect if the mac address starts with d0:0d def has_euca_mac? network[:interfaces].each_value do |iface| mac = get_mac_address(iface[:addresses]) if MAC_MATCH.match?(mac) logger.trace("Plugin Eucalyptus: has_euca_mac? == true (#{mac})") return true end end logger.trace("Plugin Eucalyptus: has_euca_mac? == false") false end def looks_like_euca? # Try non-blocking connect so we don't "block" if # the metadata service doesn't respond hint?("eucalyptus") || has_euca_mac? && can_socket_connect?(Ohai::Mixin::Ec2Metadata::EC2_METADATA_ADDR, 80) end collect_data do if looks_like_euca? logger.trace("Plugin Eucalyptus: looks_like_euca? == true") eucalyptus Mash.new fetch_metadata.each do |k, v| # Eucalyptus 3.4+ supports IAM roles and Instance Profiles much like AWS # https://www.eucalyptus.com/blog/2013/10/15/iam-roles-and-instance-profiles-eucalyptus-34 # # fetch_metadata returns IAM security credentials, including the IAM user's # secret access key. We'd rather not have ohai send this information # to the server. # http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html#instancedata-data-categories next if k == "iam" && !hint?("iam") eucalyptus[k] = v end eucalyptus[:userdata] = fetch_userdata else logger.trace("Plugin Eucalyptus: looks_like_euca? == false") false end end end ohai-16.13.0/lib/ohai/plugins/ec2.rb0000644000175100017510000001373214034105661016003 0ustar pravipravi# frozen_string_literal: true # # Author:: Tim Dysinger () # Author:: Benjamin Black () # Author:: Christopher Brown () # Author:: Tim Smith () # Copyright:: Copyright (c) Chef Software 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. # How we detect EC2 from easiest to hardest & least reliable # 1. Ohai ec2 hint exists. This always works # 2. Xen hypervisor UUID starts with 'ec2'. This catches Linux HVM & paravirt instances # 3. DMI bios version data mentions amazon. This catches HVM instances in a VPC on the Xen based hypervisor # 3. DMI bios vendor data mentions amazon. This catches HVM instances in a VPC on the non-Xen based hypervisor # 4. Kernel data mentioned Amazon. This catches Windows HVM & paravirt instances Ohai.plugin(:EC2) do require_relative "../mixin/ec2_metadata" require_relative "../mixin/http_helper" include Ohai::Mixin::Ec2Metadata include Ohai::Mixin::HttpHelper provides "ec2" # look for amazon string in dmi vendor bios data within the sys tree. # this works even if the system lacks dmidecode use by the Dmi plugin # this gets us detection of new Xen-less HVM instances that are within a VPC # @return [Boolean] do we have Amazon DMI data? def has_ec2_amazon_dmi? # detect a version of '4.2.amazon' if /Amazon/.match?(file_val_if_exists("/sys/class/dmi/id/bios_vendor")) logger.trace("Plugin EC2: has_ec2_amazon_dmi? == true") true else logger.trace("Plugin EC2: has_ec2_amazon_dmi? == false") false end end # look for amazon string in dmi bios version data within the sys tree. # this works even if the system lacks dmidecode use by the Dmi plugin # this gets us detection of HVM instances that are within a VPC # @return [Boolean] do we have Amazon DMI data? def has_ec2_xen_dmi? # detect a version of '4.2.amazon' if /amazon/.match?(file_val_if_exists("/sys/class/dmi/id/bios_version")) logger.trace("Plugin EC2: has_ec2_xen_dmi? == true") true else logger.trace("Plugin EC2: has_ec2_xen_dmi? == false") false end end # looks for a xen UUID that starts with ec2 from within the Linux sys tree # @return [Boolean] do we have a Xen UUID or not? def has_ec2_xen_uuid? if /^ec2/.match?(file_val_if_exists("/sys/hypervisor/uuid")) logger.trace("Plugin EC2: has_ec2_xen_uuid? == true") return true end logger.trace("Plugin EC2: has_ec2_xen_uuid? == false") false end # looks at the identifying number WMI value to see if it starts with ec2. # this is actually the same value we're looking at in has_ec2_xen_uuid? on # linux hosts # @return [Boolean] do we have a Xen Identifying Number or not? def has_ec2_identifying_number? if RUBY_PLATFORM.match?(/mswin|mingw32|windows/) require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) wmi = WmiLite::Wmi.new if /^ec2/.match?(wmi.first_of("Win32_ComputerSystemProduct")["identifyingnumber"]) logger.trace("Plugin EC2: has_ec2_identifying_number? == true") true end else logger.trace("Plugin EC2: has_ec2_identifying_number? == false") false end end # return the contents of a file if the file exists # @param path[String] abs path to the file # @return [String] contents of the file if it exists def file_val_if_exists(path) if file_exist?(path) file_read(path) end end # a single check that combines all the various detection methods for EC2 # @return [Boolean] Does the system appear to be on EC2 def looks_like_ec2? return true if hint?("ec2") # Even if it looks like EC2 try to connect first if has_ec2_xen_uuid? || has_ec2_amazon_dmi? || has_ec2_xen_dmi? || has_ec2_identifying_number? return true if can_socket_connect?(Ohai::Mixin::Ec2Metadata::EC2_METADATA_ADDR, 80) end end collect_data do require "base64" unless defined?(Base64) if looks_like_ec2? logger.trace("Plugin EC2: looks_like_ec2? == true") ec2 Mash.new fetch_metadata.each do |k, v| # this includes sensitive data we don't want to store on the node next if k == "identity_credentials_ec2_security_credentials_ec2_instance" # fetch_metadata returns IAM security credentials, including the IAM user's # secret access key. We'd rather not have ohai send this information # to the server. If the instance is associated with an IAM role we grab # only the "info" key and the IAM role name. # https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html if k == "iam" && !hint?("iam") ec2[:iam] = v.select { |key, value| key == "info" } if v["security-credentials"] && v["security-credentials"].keys.length == 1 ec2[:iam]["role_name"] = v["security-credentials"].keys[0] end else ec2[k] = v end end ec2[:userdata] = fetch_userdata ec2[:account_id] = fetch_dynamic_data["accountId"] ec2[:availability_zone] = fetch_dynamic_data["availabilityZone"] ec2[:region] = fetch_dynamic_data["region"] # ASCII-8BIT is equivalent to BINARY in this case if ec2[:userdata] && ec2[:userdata].encoding.to_s == "ASCII-8BIT" logger.trace("Plugin EC2: Binary UserData Found. Storing in base64") ec2[:userdata] = Base64.encode64(ec2[:userdata]) end else logger.trace("Plugin EC2: looks_like_ec2? == false") false end end end ohai-16.13.0/lib/ohai/plugins/solaris2/0000755000175100017510000000000014034105661016535 5ustar pravipraviohai-16.13.0/lib/ohai/plugins/solaris2/network.rb0000644000175100017510000001707114034105661020561 0ustar pravipravi# frozen_string_literal: true # # Author:: Benjamin Black () # Copyright:: Copyright (c) Chef Software 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. # # EXAMPLE SOLARIS IFCONFIG OUTPUT; CURRENTLY, ONLY SIMPLE STUFF IS SUPPORTED (E.G., NO TUNNELS) # DEAR SUN: YOU GET AN F FOR YOUR IFCONFIG # lo0:3: flags=2001000849 mtu 8232 index 1 # inet 127.0.0.1 netmask ff000000 # e1000g0:3: flags=201000843 mtu 1500 index 3 # inet 72.2.115.28 netmask ffffff80 broadcast 72.2.115.127 # e1000g2:1: flags=201000843 mtu 1500 index 4 # inet 10.2.115.28 netmask ffffff80 broadcast 10.2.115.127 # inet6 2001:0db8:3c4d:55:a00:20ff:fe8e:f3ad/64 # ip.tun0: flags=2200851 mtu 1480 index 3 # inet tunnel src 109.146.85.57 tunnel dst 109.146.85.212 # tunnel security settings --> use 'ipsecconf -ln -i ip.tun1' # tunnel hop limit 60 # inet6 fe80::6d92:5539/10 --> fe80::6d92:55d4 # ip.tun0:1: flags=2200851 mtu 1480 index 3 # inet6 2::45/128 --> 2::46 # lo0: flags=1000849 mtu 8232 index 1 # inet 127.0.0.1 netmask ff000000 # eri0: flags=1004843 mtu 1500 \ # index 2 # inet 172.17.128.208 netmask ffffff00 broadcast 172.17.128.255 # ip6.tun0: flags=10008d1 \ # mtu 1460 # index 3 # inet6 tunnel src fe80::1 tunnel dst fe80::2 # tunnel security settings --> use 'ipsecconf -ln -i ip.tun1' # tunnel hop limit 60 tunnel encapsulation limit 4 # inet 10.0.0.208 --> 10.0.0.210 netmask ff000000 # qfe1: flags=2000841 mtu 1500 index 3 # usesrc vni0 # inet6 fe80::203:baff:fe17:4be0/10 # ether 0:3:ba:17:4b:e0 # vni0: flags=2002210041 mtu 0 # index 5 # srcof qfe1 # inet6 fe80::203:baff:fe17:4444/128 # Extracted from http://illumos.org/hcl/ ETHERNET_ENCAPS ||= %w{ afe amd8111s arn atge ath bfe bge bnx bnxe ce cxgbe dmfe e1000g efe elxl emlxs eri hermon hme hxge igb iprb ipw iwh iwi iwk iwp ixgb ixgbe mwl mxfe myri10ge nge ntxn nxge pcn platform qfe qlc ral rge rtls rtw rwd rwn sfe tavor vr wpi xge yge aggr}.freeze Ohai.plugin(:Network) do require_relative "../../mixin/network_helper" provides "network", "network/interfaces" provides "counters/network", "counters/network/interfaces" include Ohai::Mixin::NetworkHelper def solaris_encaps_lookup(ifname) return "Ethernet" if ETHERNET_ENCAPS.include?(ifname) return "Ethernet" if ifname.eql?("net") return "Loopback" if ifname.eql?("lo") "Unknown" end def arpname_to_ifname(iface, arpname) iface.each_key do |ifn| return ifn if ifn.split(":")[0].eql?(arpname) end nil end def full_interface_name(iface, part_name, index) iface.each do |name, attrs| next unless attrs.respond_to?(:[]) return name if /^#{part_name}($|:)/.match(name) && attrs[:index] == index end nil end collect_data(:solaris2) do iface = Mash.new network Mash.new unless network network[:interfaces] ||= Mash.new counters Mash.new unless counters counters[:network] ||= Mash.new cint = nil shell_out("ifconfig -a").stdout.lines do |line| # regex: https://rubular.com/r/ZiIHbsnfiWPW1p if line =~ /^([0-9a-zA-Z\.\:\-]+): \S+ mtu (\d+)(?: index (\d+))?/ cint = $1 iface[cint] ||= Mash.new iface[cint][:mtu] = $2 iface[cint][:index] = $3 if line =~ / flags\=\d+\<((ADDRCONF|ANYCAST|BROADCAST|CoS|DEPRECATED|DHCP|DUPLICATE|FAILED|FIXEDMTU|INACTIVE|L3PROTECT|LOOPBACK|MIP|MULTI_BCAST|MULTICAST|NOARP|NOFAILOVER|NOLOCAL|NONUD|NORTEXCH|NOXMIT|OFFLINE|PHYSRUNNING|POINTOPOINT|PREFERRED|PRIVATE|ROUTER|RUNNING|STANDBY|TEMPORARY|UNNUMBERED|UP|VIRTUAL|XRESOLV|IPv4|IPv6|,)+)\>\s/ flags = $1.split(",") else flags = [] end iface[cint][:flags] = flags.flatten if cint =~ /^(\w+)(\d+.*)/ iface[cint][:type] = $1 iface[cint][:number] = $2 iface[cint][:encapsulation] = solaris_encaps_lookup($1) end end if line =~ /\s+inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) netmask (([0-9a-f]){1,8})\s*$/ iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "inet", "netmask" => hex_to_dec_netmask($2) } end if line =~ /\s+inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) netmask (([0-9a-f]){1,8}) broadcast (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "inet", "netmask" => hex_to_dec_netmask($2), "broadcast" => $4 } end if line =~ %r{\s+inet6 ([a-f0-9\:]+)(\s*|(\%[a-z0-9]+)\s*)/(\d+)\s*$} iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "inet6", "prefixlen" => $4 } end end # Device IP Address Mask Flags Phys Addr # bge1 172.16.0.129 255.255.255.255 SPLA 00:03:ba:xx:xx:xx so = shell_out("arp -an") so.stdout.lines do |line| if line =~ /([0-9a-zA-Z]+)\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+(\w+)?\s+([a-zA-Z0-9\.\:\-]+)/ next unless iface[arpname_to_ifname(iface, $1)] # this should never happen, except on solaris because sun hates you. iface[arpname_to_ifname(iface, $1)][:arp] ||= Mash.new iface[arpname_to_ifname(iface, $1)][:arp][$2] = $5 end end iface.each_key do |ifn| iaddr = nil if iface[ifn][:encapsulation].eql?("Ethernet") iface[ifn][:addresses].each_key do |addr| if iface[ifn][:addresses][addr]["family"].eql?("inet") iaddr = addr break end end iface[ifn][:arp]&.each_key do |addr| if addr.eql?(iaddr) iface[ifn][:addresses][iface[ifn][:arp][iaddr]] = { "family" => "lladdr" } break end end end end network[:interfaces] = iface so = shell_out("route -v -n get default") so.stdout.lines do |line| matches = /interface: (?\S+)\s+index\s+(?\d+)/.match(line) if matches network[:default_interface] = case when iface[matches[:name]] matches[:name] when int_name = full_interface_name(iface, matches[:name], matches[:index]) int_name else matches[:name] end logger.trace("Plugin Network: found interface device: #{network[:default_interface]} #{matches[:name]}") end matches = /gateway: (\S+)/.match(line) if matches logger.trace("Plugin Network: found gateway: #{matches[1]}") network[:default_gateway] = matches[1] end end end end ohai-16.13.0/lib/ohai/plugins/solaris2/dmi.rb0000644000175100017510000002006414034105661017635 0ustar pravipravi# frozen_string_literal: true # # Author:: Kurt Yoder (ktyopscode@yoderhome.com) # Copyright:: Copyright (c) 2010 Kurt Yoder # 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(:DMI) do provides "dmi" collect_data(:solaris2) do require_relative "../../common/dmi" # if we already have a "dmi" with keys (presumably from dmidecode), don't try smbios # note that a single key just means dmidecode exited with its version if dmi.is_a?(Mash) && dmi.keys.length > 1 logger.trace("Plugin DMI: skipping smbios output, since DMI information has already been provided") return end dmi Mash.new # bad Solaris shows strings defined by system instead of SMB IDs # this is what the *real* IDs are: # pulled from http://src.opensolaris.org/source/xref/nwam/nwam1/usr/src/uts/common/sys/smbios.h smb_to_id = { "SMB_TYPE_BIOS" => 0, # BIOS information (R) "SMB_TYPE_SYSTEM" => 1, # system information (R) "SMB_TYPE_BASEBOARD" => 2, # base board "SMB_TYPE_CHASSIS" => 3, # system enclosure or chassis (R) "SMB_TYPE_PROCESSOR" => 4, # processor (R) "SMB_TYPE_MEMCTL" => 5, # memory controller (O) "SMB_TYPE_MEMMOD" => 6, # memory module (O) "SMB_TYPE_CACHE" => 7, # processor cache (R) "SMB_TYPE_PORT" => 8, # port connector "SMB_TYPE_SLOT" => 9, # upgradeable system slot (R) "SMB_TYPE_OBDEVS" => 10, # on-board devices "SMB_TYPE_OEMSTR" => 11, # OEM string table "SMB_TYPE_SYSCONFSTR" => 12, # system configuration string table "SMB_TYPE_LANG" => 13, # BIOS language information "SMB_TYPE_GROUP" => 14, # group associations "SMB_TYPE_EVENTLOG" => 15, # system event log "SMB_TYPE_MEMARRAY" => 16, # physical memory array (R) "SMB_TYPE_MEMDEVICE" => 17, # memory device (R) "SMB_TYPE_MEMERR32" => 18, # 32-bit memory error information "SMB_TYPE_MEMARRAYMAP" => 19, # memory array mapped address (R) "SMB_TYPE_MEMDEVICEMAP" => 20, # memory device mapped address (R) "SMB_TYPE_POINTDEV" => 21, # built-in pointing device "SMB_TYPE_BATTERY" => 22, # portable battery "SMB_TYPE_RESET" => 23, # system reset settings "SMB_TYPE_SECURITY" => 24, # hardware security settings "SMB_TYPE_POWERCTL" => 25, # system power controls "SMB_TYPE_VPROBE" => 26, # voltage probe "SMB_TYPE_COOLDEV" => 27, # cooling device "SMB_TYPE_TPROBE" => 28, # temperature probe "SMB_TYPE_IPROBE" => 29, # current probe "SMB_TYPE_OOBRA" => 30, # out-of-band remote access facility "SMB_TYPE_BIS" => 31, # boot integrity services "SMB_TYPE_BOOT" => 32, # system boot status (R) "SMB_TYPE_MEMERR64" => 33, # 64-bit memory error information "SMB_TYPE_MGMTDEV" => 34, # management device "SMB_TYPE_MGMTDEVCP" => 35, # management device component "SMB_TYPE_MGMTDEVDATA" => 36, # management device threshold data "SMB_TYPE_MEMCHAN" => 37, # memory channel "SMB_TYPE_IPMIDEV" => 38, # IPMI device information "SMB_TYPE_POWERSUP" => 39, # system power supply "SMB_TYPE_ADDINFO" => 40, # additional information "SMB_TYPE_OBDEVEXT" => 41, # on-board device extended info "SMB_TYPE_MCHI" => 42, # mgmt controller host interface "SMB_TYPE_INACTIVE" => 126, # inactive table entry "SMB_TYPE_EOT" => 127, # end of table "SMB_TYPE_OEM_LO" => 128, # start of OEM-specific type range "SUN_OEM_EXT_PROCESSOR" => 132, # processor extended info "SUN_OEM_PCIEXRC" => 138, # PCIE RootComplex/RootPort info "SUN_OEM_EXT_MEMARRAY" => 144, # phys memory array extended info "SUN_OEM_EXT_MEMDEVICE" => 145, # memory device extended info "SMB_TYPE_OEM_HI" => 256, # end of OEM-specific type range }.freeze # all output lines should fall within one of these patterns header_type_line = /^ID\s+SIZE\s+TYPE/ header_information_line = /^(\d+)\s+(\d+)\s+(\S+)\s+\(([^\)]+)\)/ blank_line = /^\s*$/ data_key_value_line = /^ ([^:]+): (.*)/ data_key_only_line = /^ (\S.*)(:\s*)?$/ extended_data_line = /^\t(\S+) \((.+)\)/ dmi_record = nil field = nil # ==== EXAMPLE: ==== # ID SIZE TYPE # 0 40 SMB_TYPE_BIOS (BIOS information) # # Vendor: HP # Version String: 2.16 # ... similar lines trimmed # Characteristics: 0x7fc9da80 # SMB_BIOSFL_PCI (PCI is supported) # ... similar lines trimmed # note the second level of indentation is via a *tab* shell_out("smbios").stdout.lines do |raw_line| next if header_type_line.match(raw_line) next if blank_line.match(raw_line) # remove/replace any characters that don't fall inside permissible ASCII range, or whitespace line = raw_line.gsub(/[^\x20-\x7E\n\t\r]/, ".") if line != raw_line logger.trace("Plugin DMI: converted characters from line:\n#{raw_line}") end if ( header_information = header_information_line.match(line) ) dmi_record = {} # look up SMB ID if smb_to_id.key?(header_information[3]) id = smb_to_id[header_information[3]] # Don't overcapture for now (OHAI-260) unless Ohai::Common::DMI.allowlisted_ids.include?(id) dmi_record = nil next end dmi_record[:type] = Ohai::Common::DMI.id_lookup(id) else logger.trace("Plugin DMI: unrecognized header type; skipping") dmi_record = nil next end dmi[dmi_record[:type]] ||= Mash.new dmi[dmi_record[:type]][:all_records] = [] unless dmi[dmi_record[:type]].key?(:all_records) dmi_record[:position] = dmi[dmi_record[:type]][:all_records].length dmi[dmi_record[:type]][:all_records].push(Mash.new) dmi[dmi_record[:type]][:all_records][dmi_record[:position]][:record_id] = header_information[1] dmi[dmi_record[:type]][:all_records][dmi_record[:position]][:size] = header_information[2] dmi[dmi_record[:type]][:all_records][dmi_record[:position]][:application_identifier] = header_information[4] field = nil elsif ( data = data_key_value_line.match(line) ) if dmi_record.nil? logger.trace("Plugin DMI: unexpected data line found before header; discarding:\n#{line}") next end dmi[dmi_record[:type]][:all_records][dmi_record[:position]][data[1]] = data[2] field = data[1] elsif ( data = data_key_only_line.match(line) ) if dmi_record.nil? logger.trace("Plugin DMI: unexpected data line found before header; discarding:\n#{line}") next end dmi[dmi_record[:type]][:all_records][dmi_record[:position]][data[1]] = "" field = data[1] elsif ( extended_data = extended_data_line.match(line) ) if dmi_record.nil? logger.trace("Plugin DMI: unexpected extended data line found before header; discarding:\n#{line}") next end if field.nil? logger.trace("Plugin DMI: unexpected extended data line found outside data section; discarding:\n#{line}") next end # overwrite "raw" value with a new Mash dmi[dmi_record[:type]][:all_records][dmi_record[:position]][field] = Mash.new unless dmi[dmi_record[:type]][:all_records][dmi_record[:position]][field].is_a?(Mash) dmi[dmi_record[:type]][:all_records][dmi_record[:position]][field][extended_data[1]] = extended_data[2] else logger.trace("Plugin DMI: unrecognized output line; discarding:\n#{line}") end end Ohai::Common::DMI.convenience_keys(dmi) end end ohai-16.13.0/lib/ohai/plugins/solaris2/memory.rb0000644000175100017510000000213314034105661020371 0ustar pravipravi# frozen_string_literal: true # # 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(:Memory) do provides "memory" collect_data(:solaris2) do memory Mash.new memory[:swap] = Mash.new memory[:total] = "#{shell_out("prtconf | grep Memory").stdout.split[2].to_i * 1024}kB" tokens = shell_out("swap -s").stdout.strip.split used_swap = tokens[8][0..-1].to_i # strip k from end free_swap = tokens[10][0..-1].to_i # strip k from end memory[:swap][:total] = "#{used_swap + free_swap}kB" memory[:swap][:free] = "#{free_swap}kB" end end ohai-16.13.0/lib/ohai/plugins/solaris2/virtualization.rb0000644000175100017510000000610114034105661022144 0ustar pravipravi# frozen_string_literal: true # # Author:: Sean Walbran () # Author:: Kurt Yoder () # Copyright:: Copyright (c) Chef Software Inc. # Copyright:: Copyright (c) 2010 Kurt Yoder # 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(:Virtualization) do require_relative "../../mixin/dmi_decode" include Ohai::Mixin::DmiDecode provides "virtualization" depends "dmi" def collect_solaris_guestid shell_out("/usr/sbin/zoneadm list -p").stdout.split(":").first end collect_data(:solaris2) do virtualization Mash.new virtualization[:systems] = Mash.new # Detect paravirt KVM/QEMU from cpuinfo, report as KVM psrinfo_path = Ohai.abs_path( "/usr/sbin/psrinfo" ) if file_exist?(psrinfo_path) so = shell_out("#{psrinfo_path} -pv") if /QEMU Virtual CPU|Common KVM processor|Common 32-bit KVM processor/.match?(so.stdout) virtualization[:system] = "kvm" virtualization[:role] = "guest" virtualization[:systems][:kvm] = "guest" end end # parse dmi to discover various virtualization guests guest = guest_from_dmi_data(get_attribute(:dmi, :system, :manufacturer), get_attribute(:dmi, :system, :product), get_attribute(:dmi, :system, :version)) if guest logger.trace("Plugin Virtualization: DMI data indicates #{guest} guest") virtualization[:system] = guest virtualization[:role] = "guest" virtualization[:systems][guest.to_sym] = "guest" end if File.executable?("/usr/sbin/zoneadm") zones = Mash.new shell_out("zoneadm list -pc").stdout.lines do |line| info = line.chomp.split(":") zones[info[1]] = { "id" => info[0], "state" => info[2], "root" => info[3], "uuid" => info[4], "brand" => info[5], "ip" => info[6], } end if zones.length == 1 first_zone = zones.keys[0] virtualization[:system] = "zone" if first_zone == "global" virtualization[:role] = "host" virtualization[:systems][:zone] = "host" else virtualization[:role] = "guest" virtualization[:systems][:zone] = "guest" virtualization[:guest_uuid] = zones[first_zone]["uuid"] virtualization[:guest_id] = collect_solaris_guestid end elsif zones.length > 1 virtualization[:system] = "zone" virtualization[:role] = "host" virtualization[:systems][:zone] = "host" virtualization[:guests] = zones end end end end ohai-16.13.0/lib/ohai/plugins/solaris2/platform.rb0000644000175100017510000000330114034105661020703 0ustar pravipravi# frozen_string_literal: true # # Author:: Benjamin Black () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Platform) do provides "platform", "platform_version", "platform_build", "platform_family" collect_data(:solaris2) do if file_exist?("/sbin/uname") uname_exec = "/sbin/uname" else uname_exec = "uname" end shell_out("#{uname_exec} -X").stdout.lines do |line| case line when /^Release =\s+(.+)$/ platform_version $1 when /^KernelID =\s+(.+)$/ platform_build $1 end end file_open("/etc/release") do |file| while ( line = file.gets ) case line when /.*SmartOS.*/ platform "smartos" when /^\s*OmniOS.*r(\d+).*$/ platform "omnios" platform_version $1 when /^\s*OpenIndiana.*(Development oi_|Hipster )(\d\S*)/ # https://rubular.com/r/iMtOBwbnyqDz7u platform "openindiana" platform_version $2 when /^\s*(Oracle Solaris|Solaris)/ platform "solaris2" end end end platform_family platform end end ohai-16.13.0/lib/ohai/plugins/groovy.rb0000644000175100017510000000233414034105661016653 0ustar pravipravi# # Author:: Doug MacEachern # Copyright:: Copyright (c) 2009 VMware, 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. # Ohai.plugin(:Groovy) do provides "languages/groovy" depends "languages".freeze collect_data do so = shell_out("groovy -v") # Sample output: # Groovy Version: 2.4.6 JVM: 1.8.0_60 Vendor: Oracle Corporation OS: Mac OS X if so.exitstatus == 0 && so.stdout =~ /Groovy Version: (\S+).*JVM: (\S+)/ groovy = Mash.new groovy[:version] = $1 groovy[:jvm] = $2 languages[:groovy] = groovy end rescue Ohai::Exceptions::Exec logger.trace('Plugin Groovy: Could not shell_out "groovy -v". Skipping plugin') end end ohai-16.13.0/lib/ohai/plugins/freebsd/0000755000175100017510000000000014034105661016411 5ustar pravipraviohai-16.13.0/lib/ohai/plugins/freebsd/network.rb0000644000175100017510000001137214034105661020433 0ustar pravipravi# frozen_string_literal: true # # Author:: Bryan McLellan (btm@loftninjas.org) # 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(:Network) do provides "network", "network/interfaces" provides "counters/network", "counters/network/interfaces" collect_data(:freebsd) do network Mash.new unless network network[:interfaces] ||= Mash.new counters Mash.new unless counters counters[:network] ||= Mash.new so = shell_out("route -n get default") so.stdout.lines do |line| if line =~ /(\w+): ([\w\.]+)/ case $1 when "gateway" network[:default_gateway] = $2 when "interface" network[:default_interface] = $2 end end end iface = Mash.new so = shell_out("#{Ohai.abs_path( "/sbin/ifconfig" )} -a") cint = nil so.stdout.lines do |line| if line =~ /^([0-9a-zA-Z\.]+):\s+/ cint = $1 iface[cint] = Mash.new if cint =~ /^(\w+)(\d+.*)/ iface[cint][:type] = $1 iface[cint][:number] = $2 end end # call the family lladdr to match linux for consistency if line =~ /\s+ether (.+?)\s/ iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "lladdr" } end if line =~ /\s+inet ([\d.]+) netmask ([\da-fx]+)\s*\w*\s*([\d.]*)/ iface[cint][:addresses] ||= Mash.new # convert the netmask to decimal for consistency netmask = "#{$2[2, 2].hex}.#{$2[4, 2].hex}.#{$2[6, 2].hex}.#{$2[8, 2].hex}" if $3.empty? iface[cint][:addresses][$1] = { "family" => "inet", "netmask" => netmask } else # found a broadcast address iface[cint][:addresses][$1] = { "family" => "inet", "netmask" => netmask, "broadcast" => $3 } end end if line =~ /\s+inet6 ([a-f0-9\:]+)%?(\w*)\s+prefixlen\s+(\d+)\s*\w*\s*([\da-fx]*)/ iface[cint][:addresses] ||= Mash.new if $4.empty? iface[cint][:addresses][$1] = { "family" => "inet6", "prefixlen" => $3 } else # found a zone_id / scope iface[cint][:addresses][$1] = { "family" => "inet6", "zoneid" => $2, "prefixlen" => $3, "scopeid" => $4 } end end if line =~ /flags=\d+<(.+)>/ flags = $1.split(",") iface[cint][:flags] = flags if flags.length > 0 end if line =~ /metric: (\d+) mtu: (\d+)/ iface[cint][:metric] = $1 iface[cint][:mtu] = $2 end end so = shell_out("arp -an") so.stdout.lines do |line| if line =~ /\((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\) at ([a-fA-F0-9\:]+) on ([0-9a-zA-Z\.\:\-]+)/ next unless iface[$3] # this should never happen iface[$3][:arp] ||= Mash.new iface[$3][:arp][$1] = $2.downcase end end network["interfaces"] = iface net_counters = Mash.new # From netstat(1), not sure of the implications: # Show the state of all network interfaces or a single interface # which have been auto-configured (interfaces statically configured # into a system, but not located at boot time are not shown). so = shell_out("netstat -ibdn") so.stdout.lines do |line| # Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll Drop # ed0 1500 54:52:00:68:92:85 333604 26 151905886 175472 0 24897542 0 905 # $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 if line =~ /^([\w\.\*]+)\s+\d+\s+\s+([\w:]*)\s*(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/ net_counters[$1] ||= Mash.new net_counters[$1]["rx"] ||= Mash.new net_counters[$1]["tx"] ||= Mash.new net_counters[$1]["rx"]["packets"] = $3 net_counters[$1]["rx"]["errors"] = $4 net_counters[$1]["rx"]["bytes"] = $5 net_counters[$1]["tx"]["packets"] = $6 net_counters[$1]["tx"]["errors"] = $7 net_counters[$1]["tx"]["bytes"] = $8 net_counters[$1]["tx"]["collisions"] = $9 net_counters[$1]["tx"]["dropped"] = $10 end end counters[:network][:interfaces] = net_counters end end ohai-16.13.0/lib/ohai/plugins/freebsd/memory.rb0000644000175100017510000000451514034105661020253 0ustar pravipravi# frozen_string_literal: true # # Author:: Bryan McLellan (btm@loftninjas.org) # 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(:Memory) do provides "memory", "memory/swap" collect_data(:freebsd) do memory Mash.new memory[:swap] = Mash.new # /usr/src/sys/sys/vmmeter.h so = shell_out("sysctl -n vm.stats.vm.v_page_size") memory[:page_size] = so.stdout.strip so = shell_out("sysctl -n vm.stats.vm.v_page_count") memory[:page_count] = so.stdout.strip memory[:total] = memory[:page_size].to_i * memory[:page_count].to_i so = shell_out("sysctl -n vm.stats.vm.v_free_count") memory[:free] = memory[:page_size].to_i * so.stdout.strip.to_i so = shell_out("sysctl -n vm.status.vm.v_active_count") memory[:active] = memory[:page_size].to_i * so.stdout.strip.to_i so = shell_out("sysctl -n vm.status.vm.v_inactive_count") memory[:inactive] = memory[:page_size].to_i * so.stdout.strip.to_i so = shell_out("sysctl -n vm.stats.vm.v_cache_count") memory[:cache] = memory[:page_size].to_i * so.stdout.strip.to_i so = shell_out("sysctl -n vm.stats.vm.v_wire_count") memory[:wired] = memory[:page_size].to_i * so.stdout.strip.to_i so = shell_out("sysctl -n vfs.bufspace") memory[:buffers] = so.stdout.strip so = shell_out("swapinfo") so.stdout.lines do |line| # Device 1K-blocks Used Avail Capacity # /dev/ad0s1b 253648 0 253648 0% if line =~ %r{^([\d\w/]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+([\d\%]+)} mdev = $1 memory[:swap][mdev] = Mash.new memory[:swap][mdev][:total] = $2 memory[:swap][mdev][:used] = $3 memory[:swap][mdev][:free] = $4 memory[:swap][mdev][:percent_free] = $5 end end end end ohai-16.13.0/lib/ohai/plugins/freebsd/platform.rb0000644000175100017510000000173114034105661020564 0ustar pravipravi# frozen_string_literal: true # # Author:: Bryan McLellan (btm@loftninjas.org) # 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(:Platform) do provides "platform", "platform_version", "platform_family" collect_data(:freebsd) do platform shell_out("uname -s").stdout.strip.downcase platform_version shell_out("uname -r").stdout.strip platform_family "freebsd" end end ohai-16.13.0/lib/ohai/plugins/sysconf.rb0000644000175100017510000000250214034105661017007 0ustar pravipravi# frozen_string_literal: true # # Author:: Davide Cavalca # Copyright:: Copyright (c) 2016 Facebook # 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(:Sysconf) do provides "sysconf" collect_data(:aix, :linux, :solaris2) do getconf_path = which("getconf") if getconf_path getconf = shell_out("#{getconf_path} -a") if getconf.exitstatus == 0 sysconf Mash.new unless sysconf getconf.stdout.split("\n").each do |line| key, val = /^(\S+)\s*(.*)?$/.match(line).captures if val && !val.empty? begin sysconf[key] = Integer(val) rescue sysconf[key] = val end else sysconf[key] = nil end end end end end end ohai-16.13.0/lib/ohai/plugins/grub2.rb0000644000175100017510000000237514034105661016354 0ustar pravipravi# frozen_string_literal: true # # Author:: Davide Cavalca # Copyright:: Copyright (c) 2020 Facebook # 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(:Grub2) do provides "grub2/environment" optional true collect_data(:dragonflybsd, :freebsd, :linux, :netbsd) do editenv_path = which("grub2-editenv") if editenv_path editenv_out = shell_out("#{editenv_path} list") grub2 Mash.new unless grub2 grub2[:environment] ||= Mash.new editenv_out.stdout.each_line do |line| key, val = line.split("=", 2) grub2[:environment][key] = val.strip end else logger.trace("Plugin Grub2: Could not find grub2-editenv. Skipping plugin.") end end end ohai-16.13.0/lib/ohai/plugins/linux/0000755000175100017510000000000014034105661016136 5ustar pravipraviohai-16.13.0/lib/ohai/plugins/linux/network.rb0000644000175100017510000007122714034105661020165 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Author:: Chris Read # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Network) do provides "network", "network/interfaces" provides "counters/network", "counters/network/interfaces" provides "ipaddress", "ip6address", "macaddress" def linux_encaps_lookup(encap) return "Loopback" if encap.eql?("Local Loopback") || encap.eql?("loopback") return "PPP" if encap.eql?("Point-to-Point Protocol") return "SLIP" if encap.eql?("Serial Line IP") return "VJSLIP" if encap.eql?("VJ Serial Line IP") return "IPIP" if encap.eql?("IPIP Tunnel") return "6to4" if encap.eql?("IPv6-in-IPv4") return "Ethernet" if encap.eql?("ether") encap end def ipv6_enabled? file_exist? "/proc/net/if_inet6" end def ethtool_binary_path @ethtool ||= which("ethtool") end def is_openvz? @openvz ||= file_directory?("/proc/vz") end def is_openvz_host? is_openvz? && file_directory?("/proc/bc") end def extract_neighbors(family, iface, neigh_attr) so = shell_out("ip -f #{family[:name]} neigh show") so.stdout.lines do |line| if line =~ /^([a-f0-9\:\.]+)\s+dev\s+([^\s]+)\s+lladdr\s+([a-fA-F0-9\:]+)/ interface = iface[$2] unless interface logger.warn("neighbor list has entries for unknown interface #{interface}") next end interface[neigh_attr] ||= Mash.new interface[neigh_attr][$1] = $3.downcase end end iface end # checking the routing tables # why ? # 1) to set the default gateway and default interfaces attributes # 2) on some occasions, the best way to select node[:ipaddress] is to look at # the routing table source field. # 3) and since we're at it, let's populate some :routes attributes # (going to do that for both inet and inet6 addresses) def check_routing_table(family, iface, default_route_table) so = shell_out("ip -o -f #{family[:name]} route show table #{default_route_table}") so.stdout.lines do |line| line.strip! logger.trace("Plugin Network: Parsing #{line}") if /\\/.match?(line) parts = line.split('\\') route_dest = parts.shift.strip route_endings = parts elsif line =~ /^([^\s]+)\s(.*)$/ route_dest = $1 route_endings = [$2] else next end route_endings.each do |route_ending| if route_ending =~ /\bdev\s+([^\s]+)\b/ route_int = $1 else logger.trace("Plugin Network: Skipping route entry without a device: '#{line}'") next end route_int = "venet0:0" if is_openvz? && !is_openvz_host? && route_int == "venet0" && iface["venet0:0"] unless iface[route_int] logger.trace("Plugin Network: Skipping previously unseen interface from 'ip route show': #{route_int}") next end route_entry = Mash.new(destination: route_dest, family: family[:name]) %w{via scope metric proto src}.each do |k| # http://rubular.com/r/pwTNp65VFf route_entry[k] = $1 if route_ending =~ /\b#{k}\s+([^\s]+)/ end # https://rubular.com/r/k1sMrRn5yLjgVi route_entry["via"] = $1 if route_ending =~ /\bvia\s+inet6\s+([^\s]+)/ # a sanity check, especially for Linux-VServer, OpenVZ and LXC: # don't report the route entry if the src address isn't set on the node # unless the interface has no addresses of this type at all if route_entry[:src] addr = iface[route_int][:addresses] unless addr.nil? || addr.key?(route_entry[:src]) || addr.values.all? { |a| a["family"] != family[:name] } logger.trace("Plugin Network: Skipping route entry whose src does not match the interface IP") next end end iface[route_int][:routes] = [] unless iface[route_int][:routes] iface[route_int][:routes] << route_entry end end iface end # now looking at the routes to set the default attributes # for information, default routes can be of this form : # - default via 10.0.2.4 dev br0 # - default dev br0 scope link # - default dev eth0 scope link src 1.1.1.1 # - default via 10.0.3.1 dev eth1 src 10.0.3.2 metric 10 # - default via 10.0.4.1 dev eth2 src 10.0.4.2 metric 20 # using a temporary var to hold routes and their interface name def parse_routes(family, iface) iface.collect do |i, iv| next unless iv[:routes] iv[:routes].collect do |r| r.merge(dev: i) if r[:family] == family[:name] end.compact # @todo: when we drop ruby 2.6 this should be a filter_map end.compact.flatten # @todo: when we drop ruby 2.6 this should be a filter_map end # determine layer 1 details for the interface using ethtool def ethernet_layer_one(iface) return iface unless ethtool_binary_path keys = %w{Speed Duplex Port Transceiver Auto-negotiation MDI-X} iface.each_key do |tmp_int| next unless iface[tmp_int][:encapsulation] == "Ethernet" so = shell_out("#{ethtool_binary_path} #{tmp_int}") so.stdout.lines do |line| line.chomp! logger.trace("Plugin Network: Parsing ethtool output: #{line}") line.lstrip! k, v = line.split(": ") next unless keys.include? k k.downcase!.tr!("-", "_") if k == "speed" k = "link_speed" # This is not necessarily the maximum speed the NIC supports v = v[/\d+/].to_i end iface[tmp_int][k] = v end end iface end # determine ring parameters for the interface using ethtool def ethernet_ring_parameters(iface) return iface unless ethtool_binary_path iface.each_key do |tmp_int| next unless iface[tmp_int][:encapsulation] == "Ethernet" so = shell_out("#{ethtool_binary_path} -g #{tmp_int}") logger.trace("Plugin Network: Parsing ethtool output: #{so.stdout}") type = nil iface[tmp_int]["ring_params"] = {} so.stdout.lines.each do |line| next if line.start_with?("Ring parameters for") next if line.strip.nil? if /Pre-set maximums/.match?(line) type = "max" next end if /Current hardware settings/.match?(line) type = "current" next end key, val = line.split(/:\s+/) if type && val ring_key = "#{type}_#{key.downcase.tr(" ", "_")}" iface[tmp_int]["ring_params"][ring_key] = val.to_i end end end iface end # determine channel parameters for the interface using ethtool def ethernet_channel_parameters(iface) return iface unless ethtool_binary_path iface.each_key do |tmp_int| next unless iface[tmp_int][:encapsulation] == "Ethernet" so = shell_out("#{ethtool_binary_path} -l #{tmp_int}") logger.trace("Plugin Network: Parsing ethtool output: #{so.stdout}") type = nil iface[tmp_int]["channel_params"] = {} so.stdout.lines.each do |line| next if line.start_with?("Channel parameters for") next if line.strip.nil? if /Pre-set maximums/.match?(line) type = "max" next end if /Current hardware settings/.match?(line) type = "current" next end key, val = line.split(/:\s+/) if type && val channel_key = "#{type}_#{key.downcase.tr(" ", "_")}" iface[tmp_int]["channel_params"][channel_key] = val.to_i end end end iface end # determine coalesce parameters for the interface using ethtool def ethernet_coalesce_parameters(iface) return iface unless ethtool_binary_path iface.each_key do |tmp_int| next unless iface[tmp_int][:encapsulation] == "Ethernet" so = shell_out("#{ethtool_binary_path} -c #{tmp_int}") logger.trace("Plugin Network: Parsing ethtool output: #{so.stdout}") iface[tmp_int]["coalesce_params"] = {} so.stdout.lines.each do |line| next if line.start_with?("Coalesce parameters for") next if line.strip.nil? if line.start_with?("Adaptive") _, adaptive_rx, _, adaptive_tx = line.split(/:\s+|\s+TX|\n/) iface[tmp_int]["coalesce_params"]["adaptive_rx"] = adaptive_rx iface[tmp_int]["coalesce_params"]["adaptive_tx"] = adaptive_tx next end key, val = line.split(/:\s+/) if val coalesce_key = key.downcase.tr(" ", "_").to_s iface[tmp_int]["coalesce_params"][coalesce_key] = val.to_i end end end iface end # determine pause parameters for the interface using ethtool def ethernet_pause_parameters(iface) return iface unless ethtool_binary_path iface.each_key do |tmp_int| next unless iface[tmp_int][:encapsulation] == "Ethernet" so = shell_out("#{ethtool_binary_path} -a #{tmp_int}") logger.trace("Plugin Network: Parsing ethtool output: #{so.stdout}") iface[tmp_int]["pause_params"] = {} so.stdout.lines.each do |line| next if line.start_with?("Pause parameters for") next if line.strip.nil? key, val = line.split(/:\s+/) if val pause_key = "#{key.downcase.tr(" ", "_")}" iface[tmp_int]["pause_params"][pause_key] = val.strip.eql? "on" end end end iface end # determine driver info for the interface using ethtool def ethernet_driver_info(iface) return iface unless ethtool_binary_path iface.each_key do |tmp_int| next unless iface[tmp_int][:encapsulation] == "Ethernet" so = shell_out("#{ethtool_binary_path} -i #{tmp_int}") logger.trace("Plugin Network: Parsing ethtool output: #{so.stdout}") iface[tmp_int]["driver_info"] = {} so.stdout.lines.each do |line| next if line.strip.nil? key, val = line.split(/:\s+/) if val.nil? val = "" end driver_key = key.downcase.tr(" ", "_").to_s iface[tmp_int]["driver_info"][driver_key] = val.chomp end end iface end # determine link stats, vlans, queue length, and state for an interface using ip def link_statistics(iface, net_counters) so = shell_out("ip -d -s link") tmp_int = nil on_rx = true so.stdout.lines do |line| if line =~ IPROUTE_INT_REGEX tmp_int = $2 iface[tmp_int] ||= Mash.new net_counters[tmp_int] ||= Mash.new end if /^\s+(ip6tnl|ipip)/.match?(line) iface[tmp_int][:tunnel_info] = {} words = line.split words.each_with_index do |word, index| case word when "external" iface[tmp_int][:tunnel_info][word] = true when "any", "ipip6", "ip6ip6" iface[tmp_int][:tunnel_info][:proto] = word when "remote", "local", "encaplimit", "hoplimit", "tclass", "flowlabel", "addrgenmode", "numtxqueues", "numrxqueues", "gso_max_size", "gso_max_segs" iface[tmp_int][:tunnel_info][word] = words[index + 1] end end end if line =~ /(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/ int = on_rx ? :rx : :tx net_counters[tmp_int][int] ||= Mash.new net_counters[tmp_int][int][:bytes] = $1 net_counters[tmp_int][int][:packets] = $2 net_counters[tmp_int][int][:errors] = $3 net_counters[tmp_int][int][:drop] = $4 if int == :rx net_counters[tmp_int][int][:overrun] = $5 else net_counters[tmp_int][int][:carrier] = $5 net_counters[tmp_int][int][:collisions] = $6 end on_rx = !on_rx end if line =~ /qlen (\d+)/ net_counters[tmp_int][:tx] ||= Mash.new net_counters[tmp_int][:tx][:queuelen] = $1 end if line =~ /vlan id (\d+)/ || line =~ /vlan protocol ([\w\.]+) id (\d+)/ if $2 tmp_prot = $1 tmp_id = $2 else tmp_id = $1 end iface[tmp_int][:vlan] ||= Mash.new iface[tmp_int][:vlan][:id] = tmp_id iface[tmp_int][:vlan][:protocol] = tmp_prot if tmp_prot vlan_flags = line.scan(/(REORDER_HDR|GVRP|LOOSE_BINDING)/) if vlan_flags.length > 0 iface[tmp_int][:vlan][:flags] = vlan_flags.flatten.uniq end end # https://rubular.com/r/JRp6lNANmpcLV5 if line =~ /\sstate (\w+)/ iface[tmp_int]["state"] = $1.downcase end end iface end def match_iproute(iface, line, cint) if line =~ IPROUTE_INT_REGEX cint = $2 iface[cint] = Mash.new if cint =~ /^(\w+?)(\d+.*)/ iface[cint][:type] = $1 iface[cint][:number] = $2 end if line =~ /mtu (\d+)/ iface[cint][:mtu] = $1 end flags = line.scan(/(UP|BROADCAST|DEBUG|LOOPBACK|POINTTOPOINT|NOTRAILERS|LOWER_UP|NOARP|PROMISC|ALLMULTI|SLAVE|MASTER|MULTICAST|DYNAMIC)/) if flags.length > 1 iface[cint][:flags] = flags.flatten.uniq end end cint end def parse_ip_addr(iface) so = shell_out("ip addr") cint = nil so.stdout.lines do |line| cint = match_iproute(iface, line, cint) parse_ip_addr_link_line(cint, iface, line) cint = parse_ip_addr_inet_line(cint, iface, line) parse_ip_addr_inet6_line(cint, iface, line) end end def parse_ip_addr_link_line(cint, iface, line) if line =~ %r{link/(\w+) ([\da-f\:]+) } iface[cint][:encapsulation] = linux_encaps_lookup($1) unless $2 == "00:00:00:00:00:00" iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$2.upcase] = { "family" => "lladdr" } end end end def parse_ip_addr_inet_line(cint, iface, line) if line =~ %r{inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(/(\d{1,2}))?} tmp_addr, tmp_prefix = $1, $3 tmp_prefix ||= "32" original_int = nil # Are we a formerly aliased interface? if line =~ /#{cint}:(\d+)$/ sub_int = $1 alias_int = "#{cint}:#{sub_int}" original_int = cint cint = alias_int end iface[cint] ||= Mash.new # Create the fake alias interface if needed iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][tmp_addr] = { "family" => "inet", "prefixlen" => tmp_prefix } iface[cint][:addresses][tmp_addr][:netmask] = IPAddr.new("255.255.255.255").mask(tmp_prefix.to_i).to_s if line =~ /peer (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ iface[cint][:addresses][tmp_addr][:peer] = $1 end if line =~ /brd (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ iface[cint][:addresses][tmp_addr][:broadcast] = $1 end if line =~ /scope (\w+)/ iface[cint][:addresses][tmp_addr][:scope] = ($1.eql?("host") ? "Node" : $1.capitalize) end # If we found we were an alias interface, restore cint to its original value cint = original_int unless original_int.nil? end cint end def parse_ip_addr_inet6_line(cint, iface, line) if line =~ %r{inet6 ([a-f0-9\:]+)/(\d+) scope (\w+)( .*)?} iface[cint][:addresses] ||= Mash.new tmp_addr = $1 tags = $4 || "" tags = tags.split iface[cint][:addresses][tmp_addr] = { "family" => "inet6", "prefixlen" => $2, "scope" => ($3.eql?("host") ? "Node" : $3.capitalize), "tags" => tags, } end end # returns the macaddress for interface from a hash of interfaces (iface elsewhere in this file) def get_mac_for_interface(interfaces, interface) interfaces[interface][:addresses].find { |k, v| v["family"] == "lladdr" }.first unless interfaces[interface][:addresses].nil? || interfaces[interface][:flags].include?("NOARP") end # returns the default route with the lowest metric (unspecified metric is 0) def choose_default_route(routes) routes.select do |r| r[:destination] == "default" end.min do |x, y| (x[:metric].nil? ? 0 : x[:metric].to_i) <=> (y[:metric].nil? ? 0 : y[:metric].to_i) end end def interface_has_no_addresses_in_family?(iface, family) return true if iface[:addresses].nil? iface[:addresses].values.all? { |addr| addr["family"] != family } end def interface_have_address?(iface, address) return false if iface[:addresses].nil? iface[:addresses].key?(address) end def interface_address_not_link_level?(iface, address) !(iface[:addresses][address][:scope].casecmp("link") == 0) end def interface_valid_for_route?(iface, address, family) return true if interface_has_no_addresses_in_family?(iface, family) interface_have_address?(iface, address) && interface_address_not_link_level?(iface, address) end def route_is_valid_default_route?(route, default_route) # if the route destination is a default route, it's good return true if route[:destination] == "default" return false if default_route[:via].nil? dest_ipaddr = IPAddr.new(route[:destination]) default_route_via = IPAddr.new(default_route[:via]) # check if nexthop is the same address family return false if dest_ipaddr.ipv4? != default_route_via.ipv4? # the default route has a gateway and the route matches the gateway dest_ipaddr.include?(default_route_via) end # ipv4/ipv6 routes are different enough that having a single algorithm to select the favored route for both creates unnecessary complexity # this method attempts to deduce the route that is most important to the user, which is later used to deduce the favored values for {ip,mac,ip6}address # we only consider routes that are default routes, or those routes that get us to the gateway for a default route def favored_default_route_linux(routes, iface, default_route, family) routes.select do |r| if family[:name] == "inet" # the route must have a source address next if r[:src].nil? || r[:src].empty? # the interface specified in the route must exist route_interface = iface[r[:dev]] next if route_interface.nil? # the interface specified in the route must exist # the interface must have no addresses, or if it has the source address, the address must not # be a link-level address next unless interface_valid_for_route?(route_interface, r[:src], "inet") # the route must either be a default route, or it must have a gateway which is accessible via the route next unless route_is_valid_default_route?(r, default_route) true elsif family[:name] == "inet6" iface[r[:dev]] && iface[r[:dev]][:state] == "up" && route_is_valid_default_route?(r, default_route) end end.min_by do |r| # sorting the selected routes: # - getting default routes first # - then sort by metric # - then by prefixlen [ r[:destination] == "default" ? 0 : 1, r[:metric].nil? ? 0 : r[:metric].to_i, # for some reason IPAddress doesn't accept "::/0", it doesn't like prefix==0 # just a quick workaround: use 0 if IPAddress fails begin IPAddress( r[:destination] == "default" ? family[:default_route] : r[:destination] ).prefix rescue 0 end, ] end end # Both the network plugin and this plugin (linux/network) are run on linux. This plugin runs first. # If the 'ip' binary is available, this plugin may set {ip,mac,ip6}address. The network plugin should not overwrite these. # The older code section below that relies on the deprecated net-tools, e.g. netstat and ifconfig, provides less functionality. collect_data(:linux) do require "ipaddr" unless defined?(IPAddr) iface = Mash.new net_counters = Mash.new network Mash.new unless network network[:interfaces] ||= Mash.new counters Mash.new unless counters counters[:network] ||= Mash.new # ohai.plugin[:network][:default_route_table] = 'default' if configuration(:default_route_table).nil? || configuration(:default_route_table).empty? default_route_table = "main" else default_route_table = configuration(:default_route_table) end logger.trace("Plugin Network: default route table is '#{default_route_table}'") # Match the lead line for an interface from iproute2 # 3: eth0.11@eth0: mtu 1500 qdisc noqueue state UP # The '@eth0:' portion doesn't exist on primary interfaces and thus is optional in the regex IPROUTE_INT_REGEX ||= /^(\d+): ([0-9a-zA-Z@:\.\-_]*?)(@[0-9a-zA-Z]+|):\s/.freeze if which("ip") # families to get default routes from families = [{ name: "inet", default_route: "0.0.0.0/0", default_prefix: :default, neighbour_attribute: :arp, }] if ipv6_enabled? families << { name: "inet6", default_route: "::/0", default_prefix: :default_inet6, neighbour_attribute: :neighbour_inet6, } end parse_ip_addr(iface) iface = link_statistics(iface, net_counters) families.each do |family| neigh_attr = family[:neighbour_attribute] default_prefix = family[:default_prefix] iface = extract_neighbors(family, iface, neigh_attr) iface = check_routing_table(family, iface, default_route_table) routes = parse_routes(family, iface) default_route = choose_default_route(routes) if default_route.nil? || default_route.empty? attribute_name = if family[:name] == "inet" "default_interface" else "default_#{family[:name]}_interface" end logger.trace("Plugin Network: Unable to determine '#{attribute_name}' as no default routes were found for that interface family") else network["#{default_prefix}_interface"] = default_route[:dev] logger.trace("Plugin Network: #{default_prefix}_interface set to #{default_route[:dev]}") # setting gateway to 0.0.0.0 or :: if the default route is a link level one network["#{default_prefix}_gateway"] = default_route[:via] || family[:default_route].chomp("/0") logger.trace("Plugin Network: #{default_prefix}_gateway set to #{network["#{default_prefix}_gateway"]}") # deduce the default route the user most likely cares about to pick {ip,mac,ip6}address below favored_route = favored_default_route_linux(routes, iface, default_route, family) # FIXME: This entire block should go away, and the network plugin should be the sole source of {ip,ip6,mac}address # since we're at it, let's populate {ip,mac,ip6}address with the best values # if we don't set these, the network plugin may set them afterwards if favored_route && !favored_route.empty? if family[:name] == "inet" ipaddress favored_route[:src] m = get_mac_for_interface(iface, favored_route[:dev]) logger.trace("Plugin Network: Overwriting macaddress #{macaddress} with #{m} from interface #{favored_route[:dev]}") if macaddress macaddress m elsif family[:name] == "inet6" # this rarely does anything since we rarely have src for ipv6, so this usually falls back on the network plugin ip6address favored_route[:src] if macaddress logger.trace("Plugin Network: Not setting macaddress from ipv6 interface #{favored_route[:dev]} because macaddress is already set") else macaddress get_mac_for_interface(iface, favored_route[:dev]) end end else logger.trace("Plugin Network: Unable to deduce the favored default route for family '#{family[:name]}' despite finding a default route, and is not setting ipaddress/ip6address/macaddress. the network plugin may provide fallbacks.") logger.trace("Plugin Network: This potential default route was excluded: #{default_route}") end end end # end families.each else # ip binary not available, falling back to net-tools, e.g. route, ifconfig begin so = shell_out("route -n") route_result = so.stdout.split($/).grep( /^0.0.0.0/ )[0].split( /[ \t]+/ ) network[:default_gateway], network[:default_interface] = route_result.values_at(1, 7) rescue Ohai::Exceptions::Exec logger.trace("Plugin Network: Unable to determine default interface") end so = shell_out("ifconfig -a") cint = nil so.stdout.lines do |line| tmp_addr = nil # dev_valid_name in the kernel only excludes slashes, nulls, spaces # http://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=blob;f=net/core/dev.c#l851 if line =~ /^([0-9a-zA-Z@\.\:\-_]+)\s+/ cint = $1 iface[cint] = Mash.new if cint =~ /^(\w+?)(\d+.*)/ iface[cint][:type] = $1 iface[cint][:number] = $2 end end if line =~ /Link encap:(Local Loopback)/ || line =~ /Link encap:(.+?)\s/ iface[cint][:encapsulation] = linux_encaps_lookup($1) end if line =~ /HWaddr (.+?)\s/ iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "lladdr" } end if line =~ /inet addr:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "inet" } tmp_addr = $1 end if line =~ %r{inet6 addr: ([a-f0-9\:]+)/(\d+) Scope:(\w+)} iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "inet6", "prefixlen" => $2, "scope" => ($3.eql?("Host") ? "Node" : $3) } end if line =~ /Bcast:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ iface[cint][:addresses][tmp_addr]["broadcast"] = $1 end if line =~ /Mask:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ iface[cint][:addresses][tmp_addr]["netmask"] = $1 end flags = line.scan(/(UP|BROADCAST|DEBUG|LOOPBACK|POINTTOPOINT|NOTRAILERS|RUNNING|NOARP|PROMISC|ALLMULTI|SLAVE|MASTER|MULTICAST|DYNAMIC)\s/) if flags.length > 1 iface[cint][:flags] = flags.flatten end if line =~ /MTU:(\d+)/ iface[cint][:mtu] = $1 end if line =~ /P-t-P:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/ iface[cint][:peer] = $1 end if line =~ /RX packets:(\d+) errors:(\d+) dropped:(\d+) overruns:(\d+) frame:(\d+)/ net_counters[cint] ||= Mash.new net_counters[cint][:rx] = { "packets" => $1, "errors" => $2, "drop" => $3, "overrun" => $4, "frame" => $5 } end if line =~ /TX packets:(\d+) errors:(\d+) dropped:(\d+) overruns:(\d+) carrier:(\d+)/ net_counters[cint][:tx] = { "packets" => $1, "errors" => $2, "drop" => $3, "overrun" => $4, "carrier" => $5 } end if line =~ /collisions:(\d+)/ net_counters[cint][:tx]["collisions"] = $1 end if line =~ /txqueuelen:(\d+)/ net_counters[cint][:tx]["queuelen"] = $1 end if line =~ /RX bytes:(\d+) \((\d+?\.\d+ .+?)\)/ net_counters[cint][:rx]["bytes"] = $1 end if line =~ /TX bytes:(\d+) \((\d+?\.\d+ .+?)\)/ net_counters[cint][:tx]["bytes"] = $1 end end so = shell_out("arp -an") so.stdout.lines do |line| if line =~ /^\S+ \((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\) at ([a-fA-F0-9\:]+) \[(\w+)\] on ([0-9a-zA-Z\.\:\-]+)/ next unless iface[$4] # this should never happen iface[$4][:arp] ||= Mash.new iface[$4][:arp][$1] = $2.downcase end end end # end "ip else net-tools" block iface = ethernet_layer_one(iface) iface = ethernet_ring_parameters(iface) iface = ethernet_channel_parameters(iface) iface = ethernet_coalesce_parameters(iface) iface = ethernet_driver_info(iface) iface = ethernet_pause_parameters(iface) counters[:network][:interfaces] = net_counters network["interfaces"] = iface end end ohai-16.13.0/lib/ohai/plugins/linux/mdadm.rb0000644000175100017510000001056514034105661017554 0ustar pravipravi# frozen_string_literal: true # # Author:: Tim Smith # Author:: Phil Dibowitz # Copyright:: Copyright (c) 2013-2014, Limelight Networks, Inc. # Copyright:: Copyright (c) 2017 Facebook, Inc. # Plugin:: mdadm # # 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(:Mdadm) do provides "mdadm" def create_raid_device_mash(stdout) device_mash = Mash.new device_mash[:device_counts] = Mash.new stdout.lines.each do |line| case line when /Version\s+: ([0-9.]+)/ device_mash[:version] = Regexp.last_match[1].to_f when /Raid Level\s+: raid([0-9]+)/ device_mash[:level] = Regexp.last_match[1].to_i when /Array Size.*\(([0-9.]+)/ device_mash[:size] = Regexp.last_match[1].to_f when /State\s+: ([a-z]+)/ device_mash[:state] = Regexp.last_match[1] when /Total Devices\s+: ([0-9]+)/ device_mash[:device_counts][:total] = Regexp.last_match[1].to_i when /Raid Devices\s+: ([0-9]+)/ device_mash[:device_counts][:raid] = Regexp.last_match[1].to_i when /Working Devices\s+: ([0-9]+)/ device_mash[:device_counts][:working] = Regexp.last_match[1].to_i when /Failed Devices\s+: ([0-9]+)/ device_mash[:device_counts][:failed] = Regexp.last_match[1].to_i when /Active Devices\s+: ([0-9]+)/ device_mash[:device_counts][:active] = Regexp.last_match[1].to_i when /Spare Devices\s+: ([0-9]+)/ device_mash[:device_counts][:spare] = Regexp.last_match[1].to_i end end device_mash end collect_data(:linux) do # gather a list of all raid arrays if file_exist?("/proc/mdstat") devices = {} file_open("/proc/mdstat").each do |line| if line =~ /(md[0-9]+)/ device = Regexp.last_match[1] pieces = line.split(/\s+/) # there are variable numbers of fields until you hit the raid level # everything after that is members... # unless the array is inactive, in which case you don't get a raid # level. members = pieces.drop_while { |x| !x.start_with?("raid", "inactive") } # and drop that too members.shift unless members.empty? devices[device] = { "active" => [], "spare" => [], "journal" => nil, } members.each do |member| # We want to match the device, and optionally the type # most entries will look like: # sdc1[5] # but some will look like: # sdc1[5](J) # where the format is: # []() # Type can be things like "J" for a journal device, or "S" for # a spare device. m = member.match(/(.+)\[\d+\](?:\((\w)\))?/) member_device = m[1] member_type = m[2] case member_type when "J" devices[device]["journal"] = member_device when "S" devices[device]["spare"] << member_device else devices[device]["active"] << member_device end end end end # create the mdadm mash and gather individual information if devices are present unless devices.empty? mdadm Mash.new devices.keys.sort.each do |device| mdadm[device] = Mash.new # gather detailed information on the array so = shell_out("mdadm --detail /dev/#{device}") # if the mdadm command was successful pass so.stdout to create_raid_device_mash to grab the tidbits we want mdadm[device] = create_raid_device_mash(so.stdout) if so.stdout mdadm[device]["members"] = devices[device]["active"] mdadm[device]["spares"] = devices[device]["spare"] mdadm[device]["journal"] = devices[device]["journal"] end end end end end ohai-16.13.0/lib/ohai/plugins/linux/lsb.rb0000644000175100017510000000260414034105661017245 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:LSB) do provides "lsb" collect_data(:linux) do lsb Mash.new if file_exist?("/usr/bin/lsb_release") # From package redhat-lsb on Fedora/Redhat, lsb-release on Debian/Ubuntu shell_out("lsb_release -a").stdout.lines do |line| case line when /^Distributor ID:\s+(.+)/ lsb[:id] = $1 when /^Description:\s+(.+)/ lsb[:description] = $1 when /^Release:\s+(.+)/ lsb[:release] = $1 when /^Codename:\s+(.+)/ lsb[:codename] = $1 else lsb[:id] = line end end else logger.trace("Plugin LSB: Skipping LSB, cannot find /usr/bin/lsb_release") end end end ohai-16.13.0/lib/ohai/plugins/linux/block_device.rb0000644000175100017510000000343114034105661021075 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:BlockDevice) do provides "block_device" collect_data(:linux) do if file_exist?("/sys/block") block = Mash.new dir_glob("/sys/block/*").each do |block_device_dir| dir = File.basename(block_device_dir) block[dir] = Mash.new %w{size removable}.each do |check| if file_exist?("/sys/block/#{dir}/#{check}") file_open("/sys/block/#{dir}/#{check}") { |f| block[dir][check] = f.read_nonblock(1024).strip } end end %w{model rev state timeout vendor queue_depth}.each do |check| if file_exist?("/sys/block/#{dir}/device/#{check}") file_open("/sys/block/#{dir}/device/#{check}") { |f| block[dir][check] = f.read_nonblock(1024).strip } end end %w{rotational physical_block_size logical_block_size}.each do |check| if file_exist?("/sys/block/#{dir}/queue/#{check}") file_open("/sys/block/#{dir}/queue/#{check}") { |f| block[dir][check] = f.read_nonblock(1024).strip } end end end block_device block end end end ohai-16.13.0/lib/ohai/plugins/linux/ipc.rb0000644000175100017510000000272314034105661017242 0ustar pravipravi# frozen_string_literal: true # # Author:: Jay Vana # Author:: Davide Cavalca # Copyright:: Copyright (c) 2016-2020 Facebook, 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. # Ohai.plugin(:IPC) do provides "ipc" optional true collect_data(:linux) do ipcs_path = which("ipcs") if ipcs_path # NOTE: currently only supports shared memory cmd = "#{ipcs_path} -m" ipcs = shell_out(cmd) ipc Mash.new unless ipc ipc["shm"] = Mash.new unless ipc["shm"] ipcs.stdout.split("\n").each do |line| next unless line.start_with?("0x") parts = line.split segment = { "key" => parts[0], "owner" => parts[2], "perms" => parts[3], "bytes" => parts[4].to_i, "nattch" => parts[5].to_i, "status" => parts[6] || "", } ipc["shm"][parts[1].to_i] = segment end end end end ohai-16.13.0/lib/ohai/plugins/linux/memory.rb0000644000175100017510000000753414034105661020004 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Memory) do provides "memory", "memory/swap" collect_data(:linux) do memory Mash.new memory[:swap] = Mash.new memory[:hugepages] = Mash.new memory[:directmap] = Mash.new file_open("/proc/meminfo").each do |line| case line when /^MemTotal:\s+(\d+) (.+)/ memory[:total] = "#{$1}#{$2}" when /^MemFree:\s+(\d+) (.+)/ memory[:free] = "#{$1}#{$2}" when /^MemAvailable:\s+(\d+) (.+)/ memory[:available] = "#{$1}#{$2}" when /^Buffers:\s+(\d+) (.+)/ memory[:buffers] = "#{$1}#{$2}" when /^Cached:\s+(\d+) (.+)/ memory[:cached] = "#{$1}#{$2}" when /^Active:\s+(\d+) (.+)/ memory[:active] = "#{$1}#{$2}" when /^Inactive:\s+(\d+) (.+)/ memory[:inactive] = "#{$1}#{$2}" when /^HighTotal:\s+(\d+) (.+)/ memory[:high_total] = "#{$1}#{$2}" when /^HighFree:\s+(\d+) (.+)/ memory[:high_free] = "#{$1}#{$2}" when /^LowTotal:\s+(\d+) (.+)/ memory[:low_total] = "#{$1}#{$2}" when /^LowFree:\s+(\d+) (.+)/ memory[:low_free] = "#{$1}#{$2}" when /^Dirty:\s+(\d+) (.+)/ memory[:dirty] = "#{$1}#{$2}" when /^Writeback:\s+(\d+) (.+)/ memory[:writeback] = "#{$1}#{$2}" when /^AnonPages:\s+(\d+) (.+)/ memory[:anon_pages] = "#{$1}#{$2}" when /^Mapped:\s+(\d+) (.+)/ memory[:mapped] = "#{$1}#{$2}" when /^Slab:\s+(\d+) (.+)/ memory[:slab] = "#{$1}#{$2}" when /^SReclaimable:\s+(\d+) (.+)/ memory[:slab_reclaimable] = "#{$1}#{$2}" when /^SUnreclaim:\s+(\d+) (.+)/ memory[:slab_unreclaim] = "#{$1}#{$2}" when /^PageTables:\s+(\d+) (.+)/ memory[:page_tables] = "#{$1}#{$2}" when /^NFS_Unstable:\s+(\d+) (.+)/ memory[:nfs_unstable] = "#{$1}#{$2}" when /^Bounce:\s+(\d+) (.+)/ memory[:bounce] = "#{$1}#{$2}" when /^CommitLimit:\s+(\d+) (.+)/ memory[:commit_limit] = "#{$1}#{$2}" when /^Committed_AS:\s+(\d+) (.+)/ memory[:committed_as] = "#{$1}#{$2}" when /^VmallocTotal:\s+(\d+) (.+)/ memory[:vmalloc_total] = "#{$1}#{$2}" when /^VmallocUsed:\s+(\d+) (.+)/ memory[:vmalloc_used] = "#{$1}#{$2}" when /^VmallocChunk:\s+(\d+) (.+)/ memory[:vmalloc_chunk] = "#{$1}#{$2}" when /^SwapCached:\s+(\d+) (.+)/ memory[:swap][:cached] = "#{$1}#{$2}" when /^SwapTotal:\s+(\d+) (.+)/ memory[:swap][:total] = "#{$1}#{$2}" when /^SwapFree:\s+(\d+) (.+)/ memory[:swap][:free] = "#{$1}#{$2}" when /^HugePages_Total:\s+(\d+)/ memory[:hugepages][:total] = $1.to_s when /^HugePages_Free:\s+(\d+)/ memory[:hugepages][:free] = $1.to_s when /^HugePages_Rsvd:\s+(\d+)/ memory[:hugepages][:reserved] = $1.to_s when /^HugePages_Surp:\s+(\d+)/ memory[:hugepages][:surplus] = $1.to_s when /^Hugepagesize:\s+(\d+) (.+)/ memory[:hugepage_size] = "#{$1}#{$2}" when /^Hugetlb:\s+(\d+) (.+)/ memory[:hugetlb] = "#{$1}#{$2}" when /^DirectMap([0-9]+[a-zA-Z]):\s+(\d+) (.+)/ memory[:directmap][$1.to_sym] = "#{$2}#{$3}" end end end end ohai-16.13.0/lib/ohai/plugins/linux/selinux.rb0000644000175100017510000000367714034105661020167 0ustar pravipravi# frozen_string_literal: true # # Author:: Davide Cavalca # Copyright:: Copyright (c) 2020 Facebook # 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(:Selinux) do provides "selinux/status", "selinux/policy_booleans", "selinux/process_contexts", "selinux/file_contexts" optional true collect_data(:linux) do sestatus_path = which("sestatus") if sestatus_path sestatus = shell_out("#{sestatus_path} -v -b") selinux Mash.new unless selinux selinux[:status] ||= Mash.new selinux[:policy_booleans] ||= Mash.new selinux[:process_contexts] ||= Mash.new selinux[:file_contexts] ||= Mash.new section = nil sestatus.stdout.split("\n").each do |line| line.chomp! case line when "Policy booleans:" section = :policy_booleans next when "Process contexts:" section = :process_contexts next when "File contexts:" section = :file_contexts next else if section.nil? section = :status end end key, val = line.split(/:?\s\s+/, 2) next if key.nil? unless key.start_with?("/") key.downcase! key.tr!(" ", "_") end selinux[section][key] = val end else logger.debug("Plugin Selinux: Could not find sestatus. Skipping plugin.") end end end ohai-16.13.0/lib/ohai/plugins/linux/systemd_paths.rb0000644000175100017510000000213014034105661021346 0ustar pravipravi# frozen_string_literal: true # # Author:: Davide Cavalca # Copyright:: Copyright (c) 2017 Facebook # 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(:SystemdPaths) do provides "systemd_paths" collect_data(:linux) do systemd_path_path = which("systemd-path") if systemd_path_path systemd_path = shell_out(systemd_path_path) systemd_paths Mash.new unless systemd_paths systemd_path.stdout.each_line do |line| key, val = line.split(":") systemd_paths[key] = val.strip end end end end ohai-16.13.0/lib/ohai/plugins/linux/hostnamectl.rb0000644000175100017510000000212014034105661020777 0ustar pravipravi# frozen_string_literal: true # # Author:: Davide Cavalca () # Copyright:: Copyright (c) 2016 Facebook # 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(:Hostnamectl) do provides "hostnamectl" collect_data(:linux) do hostnamectl Mash.new unless hostnamectl hostnamectl_path = which("hostnamectl") if hostnamectl_path shell_out(hostnamectl_path).stdout.split("\n").each do |line| key, val = line.split(": ", 2) hostnamectl[key.chomp.lstrip.tr(" ", "_").downcase] = val end end end end ohai-16.13.0/lib/ohai/plugins/linux/sysctl.rb0000644000175100017510000000215314034105661020005 0ustar pravipravi# frozen_string_literal: true # # Author:: Joshua Miller # Copyright:: Copyright (c) 2019 Facebook # 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(:Sysctl) do provides "sysctl" optional true collect_data(:linux) do sysctl_path = which("sysctl") if sysctl_path sysctl_cmd = shell_out("#{sysctl_path} -a") if sysctl_cmd.exitstatus == 0 sysctl Mash.new unless sysctl sysctl_cmd.stdout.lines.each do |line| k, v = line.split("=").map(&:strip) sysctl[k] = v end end end end end ohai-16.13.0/lib/ohai/plugins/linux/virtualization.rb0000644000175100017510000002741714034105661021562 0ustar pravipravi# frozen_string_literal: true # # Author:: Thom May () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Virtualization) do provides "virtualization" depends "dmi" require_relative "../../mixin/dmi_decode" include Ohai::Mixin::DmiDecode def lxc_version_exists? which("lxc-version") || which("lxc-start") end def nova_exists? which("nova") end def docker_exists? which("docker") end collect_data(:linux) do virtualization Mash.new unless virtualization virtualization[:systems] ||= Mash.new # Docker hosts if docker_exists? virtualization[:system] = "docker" virtualization[:role] = "host" virtualization[:systems][:docker] = "host" end # Xen Notes: # - /proc/xen is an empty dir for EL6 + Linode Guests + Paravirt EC2 instances # - cpuid of guests, if we could get it, would also be a clue # - may be able to determine if under paravirt from /dev/xen/evtchn (See OHAI-253) # - Additional edge cases likely should not change the above assumptions # but rather be additive - btm if file_exist?("/proc/xen") virtualization[:system] = "xen" # Assume guest virtualization[:role] = "guest" virtualization[:systems][:xen] = "guest" # This file should exist on most Xen systems, normally empty for guests if file_exist?("/proc/xen/capabilities") if /control_d/i.match?(file_read("/proc/xen/capabilities")) logger.trace("Plugin Virtualization: /proc/xen/capabilities contains control_d. Detecting as Xen host") virtualization[:role] = "host" virtualization[:systems][:xen] = "host" end end end # Detect Virtualbox from kernel module if file_exist?("/proc/modules") modules = file_read("/proc/modules") if /^vboxdrv/.match?(modules) logger.trace("Plugin Virtualization: /proc/modules contains vboxdrv. Detecting as vbox host") virtualization[:system] = "vbox" virtualization[:role] = "host" virtualization[:systems][:vbox] = "host" elsif /^vboxguest/.match?(modules) logger.trace("Plugin Virtualization: /proc/modules contains vboxguest. Detecting as vbox guest") virtualization[:system] = "vbox" virtualization[:role] = "guest" virtualization[:systems][:vbox] = "guest" end end # if nova binary is present we're on an openstack host if nova_exists? logger.trace("Plugin Virtualization: nova command exists. Detecting as openstack host") virtualization[:system] = "openstack" virtualization[:role] = "host" virtualization[:systems][:openstack] = "host" end # Detect paravirt KVM/QEMU from cpuinfo, report as KVM if file_exist?("/proc/cpuinfo") if /QEMU Virtual CPU|Common KVM processor|Common 32-bit KVM processor/.match?(file_read("/proc/cpuinfo")) logger.trace("Plugin Virtualization: /proc/cpuinfo lists a KVM paravirt CPU string. Detecting as kvm guest") virtualization[:system] = "kvm" virtualization[:role] = "guest" virtualization[:systems][:kvm] = "guest" end end # Detect KVM systems via /sys # guests will have the hypervisor cpu feature that hosts don't have if file_exist?("/sys/devices/virtual/misc/kvm") virtualization[:system] = "kvm" if /hypervisor/.match?(file_read("/proc/cpuinfo")) logger.trace("Plugin Virtualization: /sys/devices/virtual/misc/kvm present and /proc/cpuinfo lists the hypervisor feature. Detecting as kvm guest") virtualization[:role] = "guest" virtualization[:systems][:kvm] = "guest" else logger.trace("Plugin Virtualization: /sys/devices/virtual/misc/kvm present and /proc/cpuinfo does not list the hypervisor feature. Detecting as kvm host") virtualization[:role] = "host" virtualization[:systems][:kvm] = "host" end end # parse dmi to discover various virtualization guests # we do this *after* the kvm detection so that OpenStack isn't detected as KVM logger.trace("Looking up DMI data manufacturer: '#{get_attribute(:dmi, :system, :manufacturer)}' product_name: '#{get_attribute(:dmi, :system, :product_name)}' version: '#{get_attribute(:dmi, :system, :version)}'") guest = guest_from_dmi_data(get_attribute(:dmi, :system, :manufacturer), get_attribute(:dmi, :system, :product_name), get_attribute(:dmi, :system, :version)) if guest logger.trace("Plugin Virtualization: DMI data indicates #{guest} guest") virtualization[:system] = guest virtualization[:role] = "guest" virtualization[:systems][guest.to_sym] = "guest" end # Detect OpenVZ / Virtuozzo. # http://wiki.openvz.org/BC_proc_entries if file_exist?("/proc/bc/0") logger.trace("Plugin Virtualization: /proc/bc/0 exists. Detecting as openvz host") virtualization[:system] = "openvz" virtualization[:role] = "host" virtualization[:systems][:openvz] = "host" elsif file_exist?("/proc/vz") logger.trace("Plugin Virtualization: /proc/vz exists. Detecting as openvz guest") virtualization[:system] = "openvz" virtualization[:role] = "guest" virtualization[:systems][:openvz] = "guest" end # Detect Hyper-V guest and the hostname of the host if file_exist?("/var/lib/hyperv/.kvp_pool_3") logger.trace("Plugin Virtualization: /var/lib/hyperv/.kvp_pool_3 contains string indicating Hyper-V guest") data = file_read("/var/lib/hyperv/.kvp_pool_3") hyperv_host = data[/\HostName(.*?)HostingSystemEditionId/, 1].scan(/[[:print:]]/).join.downcase virtualization[:system] = "hyperv" virtualization[:role] = "guest" virtualization[:systems][:hyperv] = "guest" virtualization[:hypervisor_host] = hyperv_host end # Detect Linux-VServer if file_exist?("/proc/self/status") proc_self_status = file_read("/proc/self/status") vxid = proc_self_status.match(/^(s_context|VxID):\s*(\d+)$/) if vxid && vxid[2] virtualization[:system] = "linux-vserver" if vxid[2] == "0" logger.trace("Plugin Virtualization: /proc/self/status contains 's_context' or 'VxID' with a value of 0. Detecting as linux-vserver host") virtualization[:role] = "host" virtualization[:systems]["linux-vserver"] = "host" else logger.trace("Plugin Virtualization: /proc/self/status contains 's_context' or 'VxID' with a non-0 value. Detecting as linux-vserver guest") virtualization[:role] = "guest" virtualization[:systems]["linux-vserver"] = "guest" end end end # Detect LXC/Docker/Nspawn # # /proc/self/cgroup will look like this inside a docker container: # ::/lxc/ # # /proc/self/cgroup could have a name including alpha/digit/dashes # ::/lxc/ # # /proc/self/cgroup could have a non-lxc cgroup name indicating other uses # of cgroups. This is probably not LXC/Docker. # ::/Charlie # # A host which supports cgroups, and has capacity to host lxc containers, # will show the subsystems and root (/) namespace. # ::/ # # Full notes, https://tickets.opscode.com/browse/OHAI-551 # Kernel docs, https://www.kernel.org/doc/Documentation/cgroups if file_exist?("/proc/self/cgroup") cgroup_content = file_read("/proc/self/cgroup") # These two REs catch many different examples. Here's a specific one # from when it is docker and there is no subsystem name. # https://rubular.com/r/dV13hiU9KxmiWB if cgroup_content =~ %r{^\d+:[^:]*:/(lxc|docker)/.+$} || cgroup_content =~ %r{^\d+:[^:]*:/[^/]+/(lxc|docker)-?.+$} logger.trace("Plugin Virtualization: /proc/self/cgroup indicates #{$1} container. Detecting as #{$1} guest") virtualization[:system] = $1 virtualization[:role] = "guest" virtualization[:systems][$1.to_sym] = "guest" elsif /container=lxc/.match?(file_read("/proc/1/environ")) logger.trace("Plugin Virtualization: /proc/1/environ indicates lxc container. Detecting as lxc guest") virtualization[:system] = "lxc" virtualization[:role] = "guest" virtualization[:systems][:lxc] = "guest" elsif /container=systemd-nspawn/.match?(file_read("/proc/1/environ")) logger.trace("Plugin Virtualization: /proc/1/environ indicates nspawn container. Detecting as nspawn guest") virtualization[:system] = "nspawn" virtualization[:role] = "guest" virtualization[:systems][:nspawn] = "guest" elsif lxc_version_exists? && file_read("/proc/self/cgroup") =~ %r{\d:[^:]+:/$} # lxc-version shouldn't be installed by default # Even so, it is likely we are on an LXC capable host that is not being used as such # So we're cautious here to not overwrite other existing values (OHAI-573) unless virtualization[:system] && virtualization[:role] logger.trace("Plugin Virtualization: /proc/self/cgroup and lxc-version command exist. Detecting as lxc host") virtualization[:system] = "lxc" virtualization[:role] = "host" virtualization[:systems][:lxc] = "host" end # In general, the 'systems' framework from OHAI-182 is less susceptible to conflicts # But, this could overwrite virtualization[:systems][:lxc] = "guest" # If so, we may need to look further for a differentiator (OHAI-573) virtualization[:systems][:lxc] = "host" end end # regardless of what we found above, if we're a docker container inside # of the above, lets report as a docker container if file_exist?("/.dockerenv") || file_exist?("/.dockerinit") logger.trace("Plugin Virtualization: .dockerenv or .dockerinit exist. Detecting as docker guest") virtualization[:system] = "docker" virtualization[:role] = "guest" virtualization[:systems][:docker] = "guest" end # Detect LXD # See https://github.com/lxc/lxd/blob/master/doc/dev-lxd.md if file_exist?("/dev/lxd/sock") logger.trace("Plugin Virtualization: /dev/lxd/sock exists. Detecting as lxd guest") virtualization[:system] = "lxd" virtualization[:role] = "guest" virtualization[:systems][:lxd] = "guest" else # 'How' LXD is installed dictates the runtime data location # # Installations of LXD from a .deb (Ubuntu's main and backports repos) utilize '/var/lib/lxd/' for runtime data # - used by stable releases 2.0.x in trusty/xenial, and 3.0.x in bionic # - xenial-backports includes versions 2.1 through 2.21 # # Snap based installations utilize '/var/snap/lxd/common/lxd/' # - includes all future releases starting with 2.21, and will be the only source of 3.1+ feature releases post-bionic ["/var/lib/lxd/devlxd", "/var/snap/lxd/common/lxd/devlxd"].each do |devlxd| if file_exist?(devlxd) logger.trace("Plugin Virtualization: #{devlxd} exists. Detecting as lxd host") virtualization[:system] = "lxd" virtualization[:role] = "host" virtualization[:systems][:lxd] = "host" break end end end end end ohai-16.13.0/lib/ohai/plugins/linux/sessions.rb0000644000175100017510000000320614034105661020332 0ustar pravipravi# frozen_string_literal: true # # Author:: Davide Cavalca # Copyright:: Copyright (c) 2016 Facebook # 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(:Sessions) do provides "sessions/by_session", "sessions/by_user" optional true collect_data(:linux) do loginctl_path = which("loginctl") if loginctl_path cmd = "#{loginctl_path} --no-pager --no-legend --no-ask-password " + "list-sessions" loginctl = shell_out(cmd) sessions Mash.new unless sessions sessions[:by_session] ||= Mash.new sessions[:by_user] ||= Mash.new loginctl.stdout.split("\n").each do |line| session, uid, user, seat = line.split s = { "session" => session, "uid" => uid, "user" => user, "seat" => seat, } sessions[:by_session][session] = s if sessions[:by_user][user] sessions[:by_user][user] << s else sessions[:by_user][user] = [s] end end else logger.trace("Plugin Sessions: Could not find loginctl. Skipping plugin.") end end end ohai-16.13.0/lib/ohai/plugins/linux/machineid.rb0000644000175100017510000000204614034105661020406 0ustar pravipravi# frozen_string_literal: true # # Author:: Davide Cavalca () # Copyright:: Copyright (c) 2016 Facebook # 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(:Machineid) do provides "machine_id" collect_data(:linux) do if file_exist?("/etc/machine-id") mid = file_read("/etc/machine-id").chomp elsif file_exist?("/var/lib/dbus/machine-id") mid = file_read("/var/lib/dbus/machine-id").chomp else mid = nil end if mid machine_id mid end end end ohai-16.13.0/lib/ohai/plugins/linux/platform.rb0000644000175100017510000003010714034105661020310 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Platform) do provides "platform", "platform_version", "platform_family" depends "lsb" # @deprecated def get_redhatish_platform(contents) contents[/^Red Hat/i] ? "redhat" : contents[/(\w+)/i, 1].downcase end # See https://rubular.com/r/78c1yXYa7zDhdV for example matches # # @param contents [String] the contents of /etc/redhat-release # # @returns [String] the version string # def get_redhatish_version(contents) contents[/(release)? ([\d\.]+)/, 2] end # # Reads an os-release-info file and parse it into a hash # # @param file [String] the filename to read (e.g. '/etc/os-release') # # @returns [Hash] the file parsed into a Hash or nil # def read_os_release_info(file) return nil unless file_exist?(file) file_read(file).split.inject({}) do |map, line| key, value = line.split("=") map[key] = value.gsub(/\A"|"\Z/, "") if value map end end # # Cached /etc/os-release info Hash. Also has logic for Cisco Nexus # switches that pulls the chained CISCO_RELEASE_INFO file into the Hash (other # distros can also reuse this method safely). # # @returns [Hash] the canonical, cached Hash of /etc/os-release info or nil # def os_release_info @os_release_info ||= begin os_release_info = read_os_release_info("/etc/os-release") cisco_release_info = os_release_info["CISCO_RELEASE_INFO"] if os_release_info if cisco_release_info && file_exist?(cisco_release_info) os_release_info.merge!(read_os_release_info(cisco_release_info)) end os_release_info end end # # If /etc/os-release indicates we are Cisco based # # @returns [Boolean] if we are Cisco according to /etc/os-release # def os_release_file_is_cisco? file_exist?("/etc/os-release") && os_release_info["CISCO_RELEASE_INFO"] end # # Determines the platform version for F5 Big-IP systems # # @deprecated # # @returns [String] bigip Linux version from /etc/f5-release # def bigip_version release_contents = file_read("/etc/f5-release") release_contents.match(/BIG-IP release (\S*)/)[1] # http://rubular.com/r/O8nlrBVqSb rescue NoMethodError, Errno::ENOENT, Errno::EACCES # rescue regex failure, file missing, or permission denied logger.warn("Detected F5 Big-IP, but /etc/f5-release could not be parsed to determine platform_version") nil end # our platform names don't match os-release. given a time machine they would but ohai # came before the os-release file. This method remaps the os-release names to # the ohai names # # @param id [String] the platform ID from /etc/os-release # # @returns [String] the platform name to use in Ohai # def platform_id_remap(id) # this catches the centos guest shell in the nexus switch which identifies itself as centos return "nexus_centos" if id == "centos" && os_release_file_is_cisco? # the platform mappings between the 'ID' field in /etc/os-release and the value # ohai uses. If you're adding a new platform here and you want to change the name # you'll want to add it here and then add a spec for the platform_id_remap method { "alinux" => "alibabalinux", "amzn" => "amazon", "archarm" => "arch", "cumulus-linux" => "cumulus", "ol" => "oracle", "opensuse-leap" => "opensuseleap", "rhel" => "redhat", "sles_sap" => "suse", "sles" => "suse", "xenenterprise" => "xenserver", }[id] || id end # # Determines the platform_family based on the platform # # @param plat [String] the platform name # # @returns [String] platform_family value # def platform_family_from_platform(plat) case plat when /debian/, /ubuntu/, /linuxmint/, /raspbian/, /cumulus/, /kali/, /pop/ # apt-get+dpkg almost certainly goes here "debian" when /oracle/, /centos/, /redhat/, /almalinux/, /scientific/, /enterpriseenterprise/, /xcp/, /xenserver/, /cloudlinux/, /ibm_powerkvm/, /parallels/, /nexus_centos/, /clearos/, /bigip/, /alibabalinux/, /sangoma/ # Note that 'enterpriseenterprise' is oracle's LSB "distributor ID" # NOTE: "rhel" should be reserved exclusively for recompiled rhel versions that are nearly perfectly compatible down to the platform_version. # The operating systems that are "rhel" should all be as compatible as rhel7 = centos7 = oracle7 = scientific7 (98%-ish core RPM version compatibility # and the version numbers MUST track the upstream). The appropriate EPEL version repo should work nearly perfectly. Some variation like the # oracle kernel version differences and tuning and extra packages are clearly acceptable. Almost certainly some distros above (xenserver?) # should not be in this list. Please use fedora, below, instead. Also note that this is the only platform_family with this strict of a rule, # see the example of the debian platform family for how the rest of the platform_family designations should be used. "rhel" when /amazon/ "amazon" when /suse/, /sles/, /opensuse/, /opensuseleap/, /sled/ "suse" when /fedora/, /pidora/, /arista_eos/ # In the broadest sense: RPM-based, fedora-derived distributions which are not strictly re-compiled RHEL (if it uses RPMs, and smells more like redhat and less like # SuSE it probably goes here). "fedora" when /nexus/, /ios_xr/ "wrlinux" when /gentoo/ "gentoo" when /slackware/ "slackware" when /arch/, /manjaro/, /antergos/ "arch" when /exherbo/ "exherbo" when /alpine/ "alpine" when /clearlinux/ "clearlinux" when /mangeia/ "mandriva" end end # modern linux distros include a /etc/os-release file, which we now rely on for # OS detection. For older distros that do not include that file we fall back to # our pre-Ohai 15 detection logic, which is the method below. No new functionality # should be added to this logic. # # @deprecated def legacy_platform_detection # platform [ and platform_version ? ] should be lower case to avoid dealing with RedHat/Redhat/redhat matching if file_exist?("/etc/oracle-release") contents = file_read("/etc/oracle-release").chomp platform "oracle" platform_version get_redhatish_version(contents) elsif file_exist?("/etc/enterprise-release") contents = file_read("/etc/enterprise-release").chomp platform "oracle" platform_version get_redhatish_version(contents) elsif file_exist?("/etc/f5-release") platform "bigip" platform_version bigip_version elsif file_exist?("/etc/debian_version") # Ubuntu and Debian both have /etc/debian_version # Ubuntu should always have a working lsb, debian does not by default if /Ubuntu/i.match?(lsb[:id]) platform "ubuntu" platform_version lsb[:release] else platform "debian" platform_version file_read("/etc/debian_version").chomp end elsif file_exist?("/etc/parallels-release") contents = file_read("/etc/parallels-release").chomp platform get_redhatish_platform(contents) platform_version contents.match(/(\d\.\d\.\d)/)[0] elsif file_exist?("/etc/Eos-release") platform "arista_eos" platform_version file_read("/etc/Eos-release").strip.split[-1] elsif file_exist?("/etc/redhat-release") contents = file_read("/etc/redhat-release").chomp platform get_redhatish_platform(contents) platform_version get_redhatish_version(contents) elsif file_exist?("/etc/system-release") contents = file_read("/etc/system-release").chomp platform get_redhatish_platform(contents) platform_version get_redhatish_version(contents) elsif file_exist?("/etc/SuSE-release") suse_release = file_read("/etc/SuSE-release") suse_version = suse_release.scan(/VERSION = (\d+)\nPATCHLEVEL = (\d+)/).flatten.join(".") suse_version = suse_release[/VERSION = ([\d\.]{2,})/, 1] if suse_version == "" platform_version suse_version if /^openSUSE/.match?(suse_release) # opensuse releases >= 42 are openSUSE Leap if platform_version.to_i < 42 platform "opensuse" else platform "opensuseleap" end else platform "suse" end elsif os_release_file_is_cisco? raise "unknown Cisco /etc/os-release or /etc/cisco-release ID_LIKE field" if os_release_info["ID_LIKE"].nil? || !os_release_info["ID_LIKE"].include?("wrlinux") case os_release_info["ID"] when "nexus" platform "nexus" when "ios_xr" platform "ios_xr" else raise "unknown Cisco /etc/os-release or /etc/cisco-release ID field" end platform_version os_release_info["VERSION"] elsif file_exist?("/etc/slackware-version") platform "slackware" platform_version file_read("/etc/slackware-version").scan(/(\d+|\.+)/).join elsif file_exist?("/etc/exherbo-release") platform "exherbo" # no way to determine platform_version in a rolling release distribution # kernel release will be used - ex. 3.13 platform_version shell_out("/bin/uname -r").stdout.strip elsif file_exist?("/usr/lib/os-release") contents = file_read("/usr/lib/os-release") if /clear-linux-os/.match?(contents) # Clear Linux https://clearlinux.org/ platform "clearlinux" platform_version contents[/VERSION_ID=(\d+)/, 1] end elsif /RedHat/i.match?(lsb[:id]) platform "redhat" platform_version lsb[:release] elsif /Amazon/i.match?(lsb[:id]) platform "amazon" platform_version lsb[:release] elsif /ScientificSL/i.match?(lsb[:id]) platform "scientific" platform_version lsb[:release] elsif /XenServer/i.match?(lsb[:id]) platform "xenserver" platform_version lsb[:release] elsif /XCP/i.match?(lsb[:id]) platform "xcp" platform_version lsb[:release] elsif lsb[:id] # LSB can provide odd data that changes between releases, so we currently fall back on it rather than dealing with its subtleties platform lsb[:id].downcase platform_version lsb[:release] end end # Grab the version from the VERSION_ID field and use the kernel release if that's not # available. It should be there for everything, but rolling releases like arch / gentoo # where we've traditionally used the kernel as the version # @return String the OS version def determine_os_version # centos only includes the major version in os-release for some reason if os_release_info["ID"] == "centos" get_redhatish_version(file_read("/etc/redhat-release").chomp) # debian testing and unstable don't have VERSION_ID set elsif os_release_info["ID"] == "debian" os_release_info["VERSION_ID"] || file_read("/etc/debian_version").chomp else os_release_info["VERSION_ID"] || shell_out("/bin/uname -r").stdout.strip end end collect_data(:linux) do if file_exist?("/etc/os-release") logger.trace("Plugin platform: Using /etc/os-release for platform detection") # fixup os-release names to ohai platform names platform platform_id_remap(os_release_info["ID"]) platform_version determine_os_version else # we're on an old Linux distro legacy_platform_detection end # unless we set it in a specific way with the platform logic above set based on platform data platform_family platform_family_from_platform(platform) if platform_family.nil? end end ohai-16.13.0/lib/ohai/plugins/linux/lspci.rb0000644000175100017510000000457214034105661017605 0ustar pravipravi# frozen_string_literal: true # # Author:: Joerg Herzinger # Author:: Phil Dibowitz # Copyright:: Copyright (c) 2011 GLOBAL 2000/Friends of the Earth Austria # Copyright:: Copyright (c) 2017 Facebook, 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. Ohai.plugin(:Lspci) do provides "pci" optional true collect_data(:linux) do devices = Mash.new h = /[0-9a-fA-F]/ # any hex digit hh = /#{h}#{h}/ # any 2 hex digits hhhh = /#{h}#{h}#{h}#{h}/ # any 4 hex digits d_id = "" # This identifies our pci devices def standard_form(devices, d_id, hhhh, tag, line) tmp = line.scan(/(.*)\s\[(#{hhhh})\]/)[0] devices[d_id]["#{tag}_name"] = tmp[0] devices[d_id]["#{tag}_id"] = tmp[1] end def standard_array(devices, d_id, tag, line) if !devices[d_id][tag].is_a?(Array) devices[d_id][tag] = [line] else devices[d_id][tag].push(line) end end shell_out("lspci -vnnmk").stdout.split("\n").each do |line| dev = line.scan(/^(.*):\s(.*)$/)[0] next if dev.nil? case dev[0] when "Device" # There are two different Device tags if ( tmp = dev[1].match(/(#{hh}:#{hh}.#{h})/) ) # We have a device id d_id = tmp[0] # From now on we will need this id devices[d_id] = Mash.new else standard_form(devices, d_id, hhhh, "device", dev[1]) end when "Class" standard_form(devices, d_id, hhhh, "class", dev[1]) when "Vendor" standard_form(devices, d_id, hhhh, "vendor", dev[1]) when "Driver" standard_array(devices, d_id, "driver", dev[1]) when "Module" standard_array(devices, d_id, "module", dev[1]) when "SDevice" standard_form(devices, d_id, hhhh, "sdevice", dev[1]) end end pci devices end end ohai-16.13.0/lib/ohai/plugins/linux/interrupts.rb0000644000175100017510000000555414034105661020713 0ustar pravipravi# frozen_string_literal: true # # Author:: Davide Cavalca # Copyright:: Copyright (c) 2020 Facebook # 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(:Interrupts) do depends "cpu" provides "interrupts", "interrupts/irq", "interrupts/smp_affinity_by_cpu" optional true # Documentation: https://www.kernel.org/doc/Documentation/IRQ-affinity.txt # format: comma-separate list of 32bit bitmask in hex # each bit is a CPU, right to left ordering (i.e. CPU0 is rightmost) def parse_smp_affinity(path, cpus) masks = file_read(path).strip bit_masks = [] masks.split(",").each do |mask| bit_masks << mask.rjust(8, "0").to_i(16).to_s(2) end affinity_mask = bit_masks.join affinity_by_cpu = affinity_mask.split("").reverse smp_affinity_by_cpu = Mash.new (0..cpus - 1).each do |cpu| smp_affinity_by_cpu[cpu] = affinity_by_cpu[cpu].to_i == 1 end smp_affinity_by_cpu end collect_data(:linux) do interrupts Mash.new cpus = cpu["total"] interrupts[:smp_affinity_by_cpu] = parse_smp_affinity("/proc/irq/default_smp_affinity", cpus) interrupts[:irq] = Mash.new file_open("/proc/interrupts").each do |line| # Documentation: https://www.kernel.org/doc/Documentation/filesystems/proc.txt # format is "{irqn}: {CPUn...} [type] [vector] [device]" irqn, fields = line.split(":", 2) # skip the header next if fields.nil? irqn.strip! Ohai::Log.debug("irq: processing #{irqn}") interrupts[:irq][irqn] = Mash.new interrupts[:irq][irqn][:events_by_cpu] = Mash.new fields = fields.split(nil, cpus + 1) (0..cpus - 1).each do |cpu| interrupts[:irq][irqn][:events_by_cpu][cpu] = fields[cpu].to_i end # Only regular IRQs have extra fields and affinity settings if /^\d+$/.match?(irqn) interrupts[:irq][irqn][:type], interrupts[:irq][irqn][:vector], interrupts[:irq][irqn][:device] = fields[cpus].split if file_exist?("/proc/irq/#{irqn}/smp_affinity") interrupts[:irq][irqn][:smp_affinity_by_cpu] = parse_smp_affinity("/proc/irq/#{irqn}/smp_affinity", cpus) end # ERR and MIS do not have any extra fields elsif fields[cpus] interrupts[:irq][irqn][:type] = fields[cpus].strip end end end end ohai-16.13.0/lib/ohai/plugins/linux/os_release.rb0000644000175100017510000000241714034105661020610 0ustar pravipravi# frozen_string_literal: true # # Author:: Lance Albertson (lance@osuosl.org>) # Copyright:: Copyright (c) 2021 Oregon State University # 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(:OsRelease) do provides "os_release" collect_data(:linux) do os_release Mash.new unless os_release # https://www.freedesktop.org/software/systemd/man/os-release.html if file_exist?("/etc/os-release") file_read("/etc/os-release").each_line do |line| key, value = line.split("=") if key == "ID_LIKE" os_release[key.downcase] = value.chomp.gsub(/\A"|"\Z/, "").split(" ") if value else os_release[key.downcase] = value.chomp.gsub(/\A"|"\Z/, "") if value end end end end end ohai-16.13.0/lib/ohai/plugins/haskell.rb0000644000175100017510000000606514034105661016756 0ustar pravipravi# frozen_string_literal: true # Author:: Chris Dituri () # Copyright:: Copyright (c) 2016 Chris Dituri # 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(:Haskell) do provides "languages/haskell", "languages/haskell/ghc", "languages/haskell/ghci", "languages/haskell/cabal", "languages/haskell/stack" depends "languages" collect_data(:default) do haskell = Mash.new # Check for ghc begin so = shell_out("ghc --version") # Sample output: # The Glorious Glasgow Haskell Compilation System, version 7.6.3 if so.exitstatus == 0 haskell[:ghc] = Mash.new haskell[:ghc][:version] = so.stdout.split[-1] haskell[:ghc][:description] = so.stdout.chomp end rescue Ohai::Exceptions::Exec logger.trace('Plugin Haskell: Could not shell_out "ghc --version". Skipping data') end # Check for ghci begin so = shell_out("ghci --version") # Sample output: # The Glorious Glasgow Haskell Compilation System, version 7.6.3 if so.exitstatus == 0 haskell[:ghci] = Mash.new haskell[:ghci][:version] = so.stdout.split[-1] haskell[:ghci][:description] = so.stdout.chomp end rescue Ohai::Exceptions::Exec logger.trace('Plugin Haskell: Could not shell_out "ghci --version". Skipping data') end # Check for cabal begin so = shell_out("cabal --version") # Sample output: # cabal-install version 1.16.0.2 # using version 1.16.0 of the Cabal library if so.exitstatus == 0 haskell[:cabal] = Mash.new haskell[:cabal][:version] = so.stdout.split("\n")[0].split[-1] haskell[:cabal][:description] = so.stdout.split("\n")[0].chomp end rescue Ohai::Exceptions::Exec logger.trace('Plugin Haskell: Could not shell_out "cabal --version". Skipping data') end # Check for stack begin so = shell_out("stack --version") # Sample output: # Version 1.1.0, Git revision 0e9430aad55841b5ff2c6c2851f0548c16bce7cf (3540 commits) x86_64 hpack-0.13.0 # or # Version 1.2.0 x86_64 hpack-0.14.0 if so.exitstatus == 0 haskell[:stack] = Mash.new haskell[:stack][:version] = /Version ([^\s,]*)/.match(so.stdout)[1] rescue nil haskell[:stack][:description] = so.stdout.chomp end rescue Ohai::Exceptions::Exec logger.trace('Plugin Haskell: Could not shell_out "stack --version". Skipping data') end languages[:haskell] = haskell unless haskell.empty? end end ohai-16.13.0/lib/ohai/plugins/perl.rb0000644000175100017510000000255614034105661016276 0ustar pravipravi# # Author:: Joshua Timberman () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Perl) do provides "languages/perl" depends "languages".freeze collect_data do so = shell_out("perl -V:version -V:archname") # Sample output: # version='5.18.2'; # archname='darwin-thread-multi-2level'; if so.exitstatus == 0 perl = Mash.new so.stdout.split(/\r?\n/).each do |line| case line when /^version=\'(.+)\';$/ perl[:version] = $1 when /^archname=\'(.+)\';$/ perl[:archname] = $1 end end languages[:perl] = perl unless perl.empty? end rescue Ohai::Exceptions::Exec logger.trace('Plugin Perl: Could not shell_out "perl -V:version -V:archname". Skipping plugin') end end ohai-16.13.0/lib/ohai/plugins/command.rb0000644000175100017510000000144314034105661016744 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Command) do provides "command" collect_data do command Mash.new end end ohai-16.13.0/lib/ohai/plugins/linode.rb0000644000175100017510000000417214034105661016602 0ustar pravipravi# frozen_string_literal: true # # Author:: Aaron Kalin () # 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(:Linode) do provides "linode" depends "domain" depends "network/interfaces" # Checks to see if the node is in the members.linode.com domain # # @return [Boolean] # def has_linode_domain? domain&.include?("linode") end # Checks for linode mirrors in the apt sources.list file # # @return [Boolean] # def has_linode_apt_repos? file_exist?("/etc/apt/sources.list") && file_read("/etc/apt/sources.list").include?("linode") end # Identifies the linode cloud by preferring the hint, then # # @return [Boolean] # def looks_like_linode? hint?("linode") || has_linode_domain? || has_linode_apt_repos? end # Alters linode mash with new interface based on name parameter # # @param [Symbol] name Ohai name (e.g. :public_ip) # @param [Symbol] eth Interface name (e.g. :eth0) # def get_ip_address(name, eth) if ( eth_iface = network[:interfaces][eth] ) eth_iface[:addresses].each do |key, info| linode[name] = key if info["family"] == "inet" end end end collect_data(:linux) do # Setup linode mash if it is a linode system if looks_like_linode? logger.trace("Plugin Linode: looks_like_linode? == true") linode Mash.new get_ip_address(:public_ip, :eth0) get_ip_address(:private_ip, "eth0:1") hint?("linode").each { |k, v| linode[k] = v } if hint?("linode").is_a?(Hash) else logger.trace("Plugin Linode: looks_like_linode? == false") end end end ohai-16.13.0/lib/ohai/plugins/c.rb0000644000175100017510000001425414034105661015554 0ustar pravipravi# frozen_string_literal: true # # Author:: Doug MacEachern # Copyright:: Copyright (c) 2010 VMware, 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. # Ohai.plugin(:C) do provides "languages/c" depends "languages" def collect(cmd, &block) so = shell_out(cmd) if so.exitstatus == 0 yield(so) else logger.trace("Plugin C: '#{cmd}' failed. Skipping data.") end rescue Ohai::Exceptions::Exec logger.trace("Plugin C: '#{cmd}' binary could not be found. Skipping data.") end def xcode_installed? logger.trace("Plugin C: Checking for Xcode Command Line Tools.") so = shell_out("/usr/bin/xcode-select -p") if so.exitstatus == 0 logger.trace("Plugin C: Xcode Command Line Tools found.") true else logger.trace("Plugin C: Xcode Command Line Tools not found.") false end rescue Ohai::Exceptions::Exec logger.trace("Plugin C: xcode-select binary could not be found. Skipping data.") end def collect_gcc # gcc # Sample output on os x: # Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 # Apple LLVM version 7.3.0 (clang-703.0.29) # Target: x86_64-apple-darwin15.4.0 # Thread model: posix # InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin # # # Sample output on Linux: # Using built-in specs. # COLLECT_GCC=gcc # COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper # Target: x86_64-linux-gnu # Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.4' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-trace --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu # Thread model: posix # gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) gcc = Mash.new collect("gcc -v") do |so| so.stderr.each_line do |line| case line when /^(.*version\s(\S*).*)/ gcc[:description] = $1 gcc[:version] = $2 when /^Target:\s(.*)/ gcc[:target] = $1 when /^Configured with:\s(.*)/ gcc[:configured_with] = $1 when /^Thread model:\s(.*)/ gcc[:thread_model] = $1 end end end @c[:gcc] = gcc unless gcc.empty? end def collect_glibc # glibc ["/lib/libc.so.6", "/lib64/libc.so.6"].each do |glibc| collect( Ohai.abs_path( glibc )) do |so| description = so.stdout.split($/).first if description =~ /(\d+\.\d+\.?\d*)/ @c[:glibc] = Mash.new @c[:glibc][:version] = $1 @c[:glibc][:description] = description end end end end def check_for_cl # ms cl collect("cl /?") do |so| description = so.stderr.lines.first.chomp if description =~ /Compiler Version ([\d\.]+)/ @c[:cl] = Mash.new @c[:cl][:version] = $1 @c[:cl][:description] = description end end end def check_for_devenv # ms vs collect("devenv.com /?") do |so| lines = so.stdout.split($/) description = lines[0].length == 0 ? lines[1] : lines[0] if description =~ /Visual Studio Version ([\d\.]+)/ @c[:vs] = Mash.new @c[:vs][:version] = $1.chop @c[:vs][:description] = description end end end def collect_xlc # IBM XL C/C++ for AIX, V13.1.3 (5725-C72, 5765-J07) # Version: 13.01.0003.0000 so = shell_out("xlc -qversion") if so.exitstatus == 0 || (so.exitstatus >> 8) == 249 description = so.stdout.split($/).first if description =~ /V(\d+\.\d+(.\d+)?)/ @c[:xlc] = Mash.new @c[:xlc][:version] = $1 @c[:xlc][:description] = description.strip end end rescue Ohai::Exceptions::Exec logger.trace("Plugin C: 'xlc' binary could not be found. Skipping data.") end def collect_sun_pro # sun pro collect("cc -V -flags") do |so| output = so.stderr.split if so.stderr =~ /^cc: Sun C/ && output.size >= 4 @c[:sunpro] = Mash.new @c[:sunpro][:version] = output[3] @c[:sunpro][:description] = so.stderr.chomp end end end collect_data(:aix) do @c = Mash.new collect_xlc collect_gcc languages[:c] = @c unless @c.empty? end collect_data(:darwin) do @c = Mash.new collect_gcc if xcode_installed? languages[:c] = @c unless @c.empty? end collect_data(:windows) do @c = Mash.new check_for_cl check_for_devenv languages[:c] = @c unless @c.empty? end collect_data(:default) do @c = Mash.new collect_gcc collect_glibc collect_sun_pro languages[:c] = @c unless @c.empty? end end ohai-16.13.0/lib/ohai/plugins/dmi.rb0000644000175100017510000001204214034105661016074 0ustar pravipravi# frozen_string_literal: true # # Author:: Kurt Yoder (ktyopscode@yoderhome.com) # Copyright:: Copyright (c) 2010 Kurt Yoder # 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(:DMI) do provides "dmi" # dmidecode does not return data without access to /dev/mem (or its equivalent) collect_data do require_relative "../common/dmi" dmi Mash.new # all output lines should fall within one of these patterns handle_line = /^Handle (0x[0-9A-F]{4}), DMI type (\d+), (\d+) bytes/ type_line = /^([A-Z][a-zA-Z ]+)( Information)?/ blank_line = /^\s*$/ data_line = /^\t([^:]+):(?: (.*))?/ extended_data_line = /^\t\t(.+)/ # first lines may contain some interesting information: # # dmidecode 2.10 # SMBIOS 2.5 present. # 5 structures occupying 352 bytes. # Table at 0x000E1000. dmidecode_version_line = /^# dmidecode (\d+\.\d+)/ smbios_version_line = /^SMBIOS (\d+\.\d+) present\./ structures_line = /^(\d+) structures occupying (\d+) bytes\./ table_location_line = /^Table at (0x[0-9A-E]+)\./ dmi_record = nil field = nil begin so = shell_out("dmidecode") # ==== EXAMPLE RECORD: ==== # Handle 0x0000, DMI type 0, 24 bytes # BIOS Information # Vendor: American Megatrends Inc. # Version: 080012 # ... similar lines trimmed # Characteristics: # ISA is supported # PCI is supported # ... similar lines trimmed so.stdout.lines do |line| next if blank_line.match(line) line = line.encode(line.encoding, universal_newline: true) if ( dmidecode_version = dmidecode_version_line.match(line) ) dmi[:dmidecode_version] = dmidecode_version[1] elsif ( smbios_version = smbios_version_line.match(line) ) dmi[:smbios_version] = smbios_version[1] elsif ( structures = structures_line.match(line) ) dmi[:structures] = Mash.new dmi[:structures][:count] = structures[1] dmi[:structures][:size] = structures[2] elsif ( table_location = table_location_line.match(line) ) dmi[:table_location] = table_location[1] elsif ( handle = handle_line.match(line) ) unless Ohai::Common::DMI.allowlisted_ids.include?(handle[2].to_i) dmi_record = nil next end dmi_record = { type: Ohai::Common::DMI.id_lookup(handle[2]) } dmi[dmi_record[:type]] ||= Mash.new dmi[dmi_record[:type]][:all_records] ||= [] dmi_record[:position] = dmi[dmi_record[:type]][:all_records].length dmi[dmi_record[:type]][:all_records].push(Mash.new) dmi[dmi_record[:type]][:all_records][dmi_record[:position]][:record_id] = handle[1] dmi[dmi_record[:type]][:all_records][dmi_record[:position]][:size] = handle[2] field = nil elsif ( type = type_line.match(line) ) if dmi_record.nil? logger.trace("Plugin DMI: unexpected data line found before header; discarding:\n#{line}") next end dmi[dmi_record[:type]][:all_records][dmi_record[:position]][:application_identifier] = type[1] elsif ( data = data_line.match(line) ) if dmi_record.nil? logger.trace("Plugin DMI: unexpected data line found before header; discarding:\n#{line}") next end dmi[dmi_record[:type]][:all_records][dmi_record[:position]][data[1]] = data[2] field = data[1] elsif ( extended_data = extended_data_line.match(line) ) if dmi_record.nil? logger.trace("Plugin DMI: unexpected extended data line found before header; discarding:\n#{line}") next end if field.nil? logger.trace("Plugin DMI: unexpected extended data line found outside data section; discarding:\n#{line}") next end # overwrite "raw" value with a new Mash 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" dmi[dmi_record[:type]][:all_records][dmi_record[:position]][field][extended_data[1]] = nil else logger.trace("Plugin DMI: unrecognized output line; discarding:\n#{line}") end end Ohai::Common::DMI.convenience_keys(dmi) rescue Ohai::Exceptions::Exec logger.trace('Plugin DMI: Could not shell_out "dmidecode". Skipping data') end end end ohai-16.13.0/lib/ohai/plugins/filesystem.rb0000644000175100017510000005277014034105661017523 0ustar pravipravi# # Author:: Phil Dibowitz # Author:: Adam Jacob # Author:: Kurt Yoder (ktyopscode@yoderhome.com) # Author:: Deepali Jagtap () # Author:: Prabhu Das () # Author:: Isa Farnik () # Author:: James Gartrell () # Copyright:: Copyright (c) Chef Software Inc. # Copyright:: Copyright (c) 2015 Facebook, 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. # Ohai.plugin(:Filesystem) do provides "filesystem".freeze def find_device(name) %w{/dev /dev/mapper}.each do |dir| path = File.join(dir, name) return path if file_exist?(path) end name end def parse_line(line, cmdtype) case cmdtype when "lsblk" regex = /NAME="(\S+).*?" UUID="(\S*)" LABEL="(\S*)" FSTYPE="(\S*)"/ if line =~ regex dev = $1 dev = find_device(dev) unless dev.start_with?("/") uuid = $2 label = $3 fs_type = $4 return { dev: dev, uuid: uuid, label: label, fs_type: fs_type } end when "blkid" bits = line.split dev = bits.shift.split(":")[0] f = { dev: dev } bits.each do |keyval| if keyval =~ /(\S+)="(\S+)"/ key = $1.downcase.to_sym key = :fs_type if key == :type f[key] = $2 end end return f end nil end def generate_device_view(fs) view = {} fs.each_value do |entry| view[entry[:device]] ||= Mash.new entry.each do |key, val| next if %w{device mount}.include?(key) view[entry[:device]][key] = val end view[entry[:device]][:mounts] ||= [] if entry[:mount] view[entry[:device]][:mounts] << entry[:mount] end end view end def generate_mountpoint_view(fs) view = {} fs.each_value do |entry| next unless entry[:mount] view[entry[:mount]] ||= Mash.new entry.each do |key, val| next if %w{mount device}.include?(key) view[entry[:mount]][key] = val end view[entry[:mount]][:devices] ||= [] if entry[:device] view[entry[:mount]][:devices] << entry[:device] end end view end def generate_deprecated_windows_view(fs) view = generate_mountpoint_view(fs) view.each do |mp, entry| view[mp].delete("devices") end view end def parse_common_df(out) fs = {} out.each_line do |line| case line when /^Filesystem\s+1024-blocks/ next when /^(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\%)\s+(.+)$/ key = "#{$1},#{$6}" fs[key] = Mash.new fs[key][:device] = $1 fs[key][:kb_size] = $2 fs[key][:kb_used] = $3 fs[key][:kb_available] = $4 fs[key][:percent_used] = $5 fs[key][:mount] = $6 end end fs end def run_with_check(bin, &block) yield rescue Ohai::Exceptions::Exec => e unless Ohai.config[:plugin][:filesystem][:allow_partial_data] raise e end logger.warn("Plugin Filesystem: #{bin} binary is not available. Some data will not be available.") end ### Windows specific methods BEGINS # Drive types DRIVE_TYPE ||= %w{unknown no_root_dir removable local network cd ram}.freeze # Volume encryption or decryption status # # @see https://docs.microsoft.com/en-us/windows/desktop/SecProv/getconversionstatus-win32-encryptablevolume#parameters # CONVERSION_STATUS ||= %w{ FullyDecrypted FullyEncrypted EncryptionInProgress DecryptionInProgress EncryptionPaused DecryptionPaused }.freeze # Returns a Mash loaded with logical details # # Uses Win32_LogicalDisk and logical_properties to return general details of volumes. # # Returns an empty Mash in case of any WMI exception. # # @see https://docs.microsoft.com/en-us/windows/desktop/CIMWin32Prov/win32-logicaldisk # # @return [Mash] # def logical_info wmi = WmiLite::Wmi.new("Root\\CIMV2") # TODO: We should really be parsing Win32_Volume and Win32_MountPoint. disks = wmi.instances_of("Win32_LogicalDisk") logical_properties(disks) rescue WmiLite::WmiException Ohai::Log.debug("Unable to access Win32_LogicalDisk. Skipping logical details") Mash.new end # Returns a Mash loaded with encryption details # # Uses Win32_EncryptableVolume and encryption_properties to return encryption details of volumes. # # Returns an empty Mash in case of any WMI exception. # # @note We are fetching Encryption Status only as of now # # @see https://msdn.microsoft.com/en-us/library/windows/desktop/aa376483(v=vs.85).aspx # # @return [Mash] # def encryptable_info wmi = WmiLite::Wmi.new("Root\\CIMV2\\Security\\MicrosoftVolumeEncryption") disks = wmi.instances_of("Win32_EncryptableVolume") encryption_properties(disks) rescue WmiLite::WmiException Ohai::Log.debug("Unable to access Win32_EncryptableVolume. Skipping encryptable details") Mash.new end # Refines and calculates logical properties out of given instances. # # Note that :device here is the same as Volume name and there for compatibility with other OSes. # # @param [WmiLite::Wmi::Instance] disks # # @return [Mash] Each drive containing following properties: # # * :kb_size (Integer) # * :kb_available (Integer) # * :kb_used (Integer) # * :percent_used (Integer) # * :mount (String) # * :fs_type (String) # * :volume_name (String) # * :device (String) # def logical_properties(disks) properties = Mash.new disks.each do |disk| property = Mash.new # In windows the closest thing we have to a device is the volume name # and the "mountpoint" is the drive letter... device = disk["volumename"].to_s.downcase mount = disk["deviceid"] property[:kb_size] = disk["size"] ? disk["size"].to_i / 1000 : 0 property[:kb_available] = disk["freespace"].to_i / 1000 property[:kb_used] = property[:kb_size] - property[:kb_available] property[:percent_used] = (property[:kb_size] == 0 ? 0 : (property[:kb_used] * 100 / property[:kb_size])) property[:mount] = mount property[:fs_type] = disk["filesystem"].to_s.downcase property[:drive_type] = disk["drivetype"].to_i property[:drive_type_string] = DRIVE_TYPE[disk["drivetype"].to_i] property[:drive_type_human] = disk["description"].to_s property[:volume_name] = disk["volumename"].to_s property[:device] = device key = "#{device},#{mount}" properties[key] = property end properties end # Refines and calculates encryption properties out of given instances # # @param [WmiLite::Wmi::Instance] disks # # @return [Mash] Each drive containing following properties: # # * :encryption_status (String) # def encryption_properties(disks) properties = Mash.new disks.each do |disk| property = Mash.new property[:encryption_status] = disk["conversionstatus"] ? CONVERSION_STATUS[disk["conversionstatus"]] : "" key = disk["driveletter"] properties[key] = property end properties end # Merges all the various properties of filesystems # # @param [Array] disks_info # Array of the Mashes containing disk properties # # @return [Mash] # def merge_info(logical_info, encryption_info) fs = Mash.new encryption_keys_used = Set.new logical_info.each do |key, info| if encryption_info[info["mount"]] encryption_keys_used.add(info["mount"]) fs[key] = info.merge(encryption_info[info["mount"]]) else fs[key] = info.dup end end left_enc = encryption_info.reject { |x| encryption_keys_used.include?(x) } left_enc.each do |key, info| fs[",#{key}"] = info end fs end collect_data(:linux) do fs = Mash.new # Grab filesystem data from df run_with_check("df") do fs.merge!(parse_common_df(shell_out("df -P").stdout)) # Grab filesystem inode data from df shell_out("df -iP").stdout.each_line do |line| case line when /^Filesystem\s+Inodes/ next when /^(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\%)\s+(.+)$/ key = "#{$1},#{$6}" fs[key] ||= Mash.new fs[key][:device] = $1 fs[key][:total_inodes] = $2 fs[key][:inodes_used] = $3 fs[key][:inodes_available] = $4 fs[key][:inodes_percent_used] = $5 fs[key][:mount] = $6 end end end # Grab mount information from /bin/mount run_with_check("mount") do shell_out("mount").stdout.each_line do |line| if line =~ /^(.+?) on (.+?) type (.+?) \((.+?)\)$/ key = "#{$1},#{$2}" fs[key] ||= Mash.new fs[key][:device] = $1 fs[key][:mount] = $2 fs[key][:fs_type] = $3 fs[key][:mount_options] = $4.split(",") end end end # We used to try to decide if we wanted to run lsblk or blkid # but they each have a variety of cases were they fail to report # data. For example, there are a variety of cases where lsblk won't # report unmounted filesystems, but blkid will. And vise-versa. Sweet. # So for reliability, we'll run both, if we have them. lsblk = which("lsblk") blkid = which("blkid") cmds = [] # These should be in order of preference... first writer wins. if lsblk cmds << "#{lsblk} -n -P -o NAME,UUID,LABEL,FSTYPE" end if blkid cmds << blkid end cmds.each do |cmd| cmdtype = File.basename(cmd.split.first) # setting the timeout here for `lsblk` and `blkid` commands to 60 # this is to allow machines with large amounts of attached LUNs # to respond back to the command successfully run_with_check(cmdtype) do shell_out(cmd, timeout: 60).stdout.each_line do |line| parsed = parse_line(line, cmdtype) next if parsed.nil? # lsblk lists each device once, so we need to update all entries # in the hash that are related to this device keys_to_update = [] fs.each_key do |key| keys_to_update << key if key.start_with?("#{parsed[:dev]},") end if keys_to_update.empty? key = "#{parsed[:dev]}," fs[key] = Mash.new fs[key][:device] = parsed[:dev] keys_to_update << key end keys_to_update.each do |k| %i{fs_type uuid label}.each do |subkey| if parsed[subkey] && !parsed[subkey].empty? fs[k][subkey] = parsed[subkey] end end end end end end # Grab any missing mount information from /proc/mounts if file_exist?("/proc/mounts") mounts = "" # Due to https://tickets.opscode.com/browse/OHAI-196 # we have to non-block read dev files. Ew. f = file_open("/proc/mounts") loop do data = f.read_nonblock(4096) mounts << data # We should just catch EOFError, but the kernel had a period of # bugginess with reading virtual files, so we're being extra # cautious here, catching all exceptions, and then we'll read # whatever data we might have rescue Exception break end f.close mounts.each_line do |line| if line =~ /^(\S+) (\S+) (\S+) (\S+) \S+ \S+$/ key = "#{$1},#{$2}" next if fs.key?(key) fs[key] = Mash.new fs[key][:device] = $1 fs[key][:mount] = $2 fs[key][:fs_type] = $3 fs[key][:mount_options] = $4.split(",") end end end by_pair = fs by_device = generate_device_view(fs) by_mountpoint = generate_mountpoint_view(fs) fs_data = Mash.new fs_data["by_device"] = by_device fs_data["by_mountpoint"] = by_mountpoint fs_data["by_pair"] = by_pair # Set the filesystem data filesystem fs_data end collect_data(:freebsd, :openbsd, :netbsd, :dragonflybsd) do fs = Mash.new # Grab filesystem data from df run_with_check("df") do so = shell_out("df") fs.merge!(parse_common_df(so.stdout)) so = shell_out("df -iP") so.stdout.lines do |line| case line when /^Filesystem/ # skip the header next when /^(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\%\s+(\d+)\s+(\d+)\s+(\d+)%\s+(\S+)$/ key = "#{$1},#{$9}" fs[key] ||= Mash.new fs[key][:device] = $1 fs[key][:inodes_used] = $6 fs[key][:inodes_available] = $7 fs[key][:total_inodes] = ($6.to_i + $7.to_i).to_s fs[key][:inodes_percent_used] = $8 fs[key][:mount] = $9 end end end # Grab mount information from mount run_with_check("mount") do so = shell_out("mount -l") so.stdout.lines do |line| if line =~ /^(.+?) on (.+?) \((.+?), (.+?)\)$/ key = "#{$1},#{$2}" fs[key] ||= Mash.new fs[key][:device] = $1 fs[key][:mount] = $2 fs[key][:fs_type] = $3 fs[key][:mount_options] = $4.split(/,\s*/) end end end # create views by_pair = fs by_device = generate_device_view(fs) by_mountpoint = generate_mountpoint_view(fs) fs_data = Mash.new fs_data["by_device"] = by_device fs_data["by_mountpoint"] = by_mountpoint fs_data["by_pair"] = by_pair # @todo in Chef 17 the filesystem2 part of this goes away filesystem fs_data filesystem2 fs_data end collect_data(:darwin) do fs = Mash.new block_size = 0 # on new versions of OSX, -i is default, on old versions it's not, so # specifying it gets consistent output run_with_check("df") do so = shell_out("df -i") so.stdout.each_line do |line| case line when /^Filesystem\s+(\d+)-/ block_size = $1.to_i next when /^(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+\%)\s+(\d+)\s+(\d+)\s+(\d+%)\s+(.+)$/ key = "#{$1},#{$9}" fs[key] = Mash.new fs[key][:block_size] = block_size fs[key][:device] = $1 fs[key][:kb_size] = ($2.to_i / (1024 / block_size)).to_s fs[key][:kb_used] = ($3.to_i / (1024 / block_size)).to_s fs[key][:kb_available] = ($4.to_i / (1024 / block_size)).to_s fs[key][:percent_used] = $5 fs[key][:inodes_used] = $6 fs[key][:inodes_available] = $7 fs[key][:total_inodes] = ($6.to_i + $7.to_i).to_s fs[key][:inodes_percent_used] = $8 fs[key][:mount] = $9 end end end run_with_check("mount") do so = shell_out("mount") so.stdout.lines do |line| if line =~ /^(.+?) on (.+?) \((.+?), (.+?)\)$/ key = "#{$1},#{$2}" fs[key] ||= Mash.new fs[key][:mount] = $2 fs[key][:fs_type] = $3 fs[key][:mount_options] = $4.split(/,\s*/) end end end by_pair = fs by_device = generate_device_view(fs) by_mountpoint = generate_mountpoint_view(fs) fs_data = Mash.new fs_data["by_device"] = by_device fs_data["by_mountpoint"] = by_mountpoint fs_data["by_pair"] = by_pair filesystem fs_data end collect_data(:solaris2) do fs = Mash.new # Grab filesystem data from df run_with_check("df") do so = shell_out("df -Pka") fs.merge!(parse_common_df(so.stdout)) # Grab file system type from df (must be done separately) so = shell_out("df -na") so.stdout.lines do |line| next unless line =~ /^(.+?)\s*: (\S+)\s*$/ mount = $1 fs.each do |key, fs_attributes| next unless fs_attributes[:mount] == mount fs[key][:fs_type] = $2 end end end # Grab mount information from /bin/mount run_with_check("mount") do so = shell_out("mount") so.stdout.lines do |line| next unless line =~ /^(.+?) on (.+?) (.+?) on (.+?)$/ key = "#{$2},#{$1}" fs[key] ||= Mash.new fs[key][:mount] = $1 fs[key][:mount_time] = $4 # $4 must come before "split", else it becomes nil fs[key][:mount_options] = $3.split("/") end end # Grab any zfs data from "zfs get" zfs = Mash.new zfs_get = "zfs get -p -H all" run_with_check("zfs") do so = shell_out(zfs_get) so.stdout.lines do |line| next unless line =~ /^([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)$/ filesystem = $1 property = $2 value = $3 source = $4.chomp zfs[filesystem] ||= Mash.new # if this fs doesn't exist, put in the bare minimum zfs[filesystem][property] = { value: value, source: source, } end end zfs.each do |fs_name, attributes| mountpoint = attributes[:mountpoint][:value] if attributes[:mountpoint] key = "#{fs_name},#{mountpoint}" fs[key] ||= Mash.new fs[key][:fs_type] = "zfs" fs[key][:mount] = mountpoint if mountpoint fs[key][:device] = fs_name fs[key][:zfs_properties] = attributes # find all zfs parents parents = fs_name.split("/") zfs_parents = [] (0..parents.length - 1).to_a.each do |parent_index| next_parent = parents[0..parent_index].join("/") zfs_parents.push(next_parent) end zfs_parents.pop fs[key][:zfs_parents] = zfs_parents fs[key][:zfs_zpool] = (zfs_parents.length == 0) end # create views by_pair = fs by_device = generate_device_view(fs) by_mountpoint = generate_mountpoint_view(fs) fs_data = Mash.new fs_data["by_device"] = by_device fs_data["by_mountpoint"] = by_mountpoint fs_data["by_pair"] = by_pair # @todo in Chef 17 the filesystem2 plugin goes away filesystem fs_data filesystem2 fs_data end collect_data(:aix) do def parse_df_or_mount(shell_out) oldie = Mash.new shell_out.lines.each do |line| fields = line.split case line # headers and horizontal rules to skip when /^\s*(node|---|^Filesystem\s+1024-blocks)/ next # strictly a df entry when /^(.+?)\s+([0-9-]+)\s+([0-9-]+)\s+([0-9-]+)\s+([0-9-]+\%*)\s+(.+)$/ if $1 == "Global" dev = "#{$1}:#{$6}" else dev = $1 end mountpoint = $6 key = "#{dev},#{mountpoint}" oldie[key] ||= Mash.new oldie[key][:kb_size] = $2 oldie[key][:kb_used] = $3 oldie[key][:kb_available] = $4 oldie[key][:percent_used] = $5 oldie[key][:mount] = mountpoint oldie[key][:device] = dev # an entry starting with 'G' or / (E.G. /tmp or /var) when %r{^\s*(G.*?|/\w)} if fields[0] == "Global" dev = fields[0] + ":" + fields[1] else dev = fields[0] end mountpoint = fields[1] key = "#{dev},#{mountpoint}" oldie[key] ||= Mash.new oldie[key][:mount] = mountpoint oldie[key][:fs_type] = fields[2] oldie[key][:mount_options] = fields[6].split(",") oldie[key][:device] = dev # entries occupying the 'Node' column parsed here else dev = fields[0] + ":" + fields[1] mountpoint = fields[2] key = "#{dev},#{mountpoint}" oldie[key] ||= Mash.new oldie[key][:mount] = mountpoint oldie[key][:device] = dev oldie[key][:fs_type] = fields[3] oldie[key][:mount_options] = fields[7].split(",") end end oldie end def collect_old_version(shell_outs) mount_hash = parse_df_or_mount shell_outs[:mount] df_hash = parse_df_or_mount shell_outs[:df_Pk] mount_hash.each do |key, hash| df_hash[key].merge!(hash) if df_hash.key?(key) end mount_hash.merge(df_hash) end # Cache the command output shell_outs = Mash.new run_with_check("mount") do shell_outs[:mount] = shell_out("mount").stdout end run_with_check("df") do shell_outs[:df_Pk] = shell_out("df -Pk").stdout end fs = collect_old_version(shell_outs) by_pair = fs by_device = generate_device_view(fs) by_mountpoint = generate_mountpoint_view(fs) fs_data = Mash.new fs_data["by_device"] = by_device fs_data["by_mountpoint"] = by_mountpoint fs_data["by_pair"] = by_pair # @todo in Chef 17 the filesystem2 plugin goes away here filesystem fs_data filesystem2 fs_data end collect_data(:windows) do require "set" unless defined?(Set) require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) require_relative "../mash" fs = merge_info(logical_info, encryptable_info) by_pair = fs by_device = generate_device_view(fs) by_mountpoint = generate_mountpoint_view(fs) fs_data = Mash.new fs_data["by_device"] = by_device fs_data["by_mountpoint"] = by_mountpoint fs_data["by_pair"] = by_pair # Set the filesystem data - Windows didn't do the conversion when everyone # else did, so 15 will have both be the new API and 16 will drop the old API filesystem generate_deprecated_windows_view(fs) filesystem2 fs_data end end ohai-16.13.0/lib/ohai/plugins/ohai.rb0000644000175100017510000000173214034105661016247 0ustar pravipravi# frozen_string_literal: true # # Author:: Tollef Fog Heen # Copyright:: Copyright (c) 2010 Tollef Fog Heen # 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(:Ohai) do provides "chef_packages/ohai" collect_data do chef_packages Mash.new unless chef_packages chef_packages[:ohai] = Mash.new chef_packages[:ohai][:version] = Ohai::VERSION chef_packages[:ohai][:ohai_root] = Ohai::OHAI_ROOT end end ohai-16.13.0/lib/ohai/plugins/azure.rb0000644000175100017510000001246514034105661016462 0ustar pravipravi# frozen_string_literal: true # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Azure) do require_relative "../mixin/azure_metadata" require_relative "../mixin/http_helper" include Ohai::Mixin::AzureMetadata include Ohai::Mixin::HttpHelper provides "azure" collect_data do # Before we had the metadata endpoint we relied exclusively on # the knife-azure plugin populating data to the hint file. # Please see the lib/chef/knife/azure_server_create.rb file in that # project for details azure_metadata_from_hints = hint?("azure") if azure_metadata_from_hints logger.trace("Plugin Azure: Azure hint is present. Parsing any hint data.") azure Mash.new azure_metadata_from_hints.each { |k, v| azure[k] = v } azure["metadata"] = parse_metadata elsif has_waagent? || has_dhcp_option_245? || has_reddog_dhcp_domain? logger.trace("Plugin Azure: No hints present, but system appears to be on Azure.") azure Mash.new azure["metadata"] = parse_metadata else logger.trace("Plugin Azure: No hints present and doesn't appear to be on Azure.") false end end # check for either the waagent or the unknown-245 DHCP option that Azure uses # http://blog.mszcool.com/index.php/2015/04/detecting-if-a-virtual-machine-runs-in-microsoft-azure-linux-windows-to-protect-your-software-when-distributed-via-the-azure-marketplace/ def has_waagent? if file_exist?("/usr/sbin/waagent") || dir_exist?('C:\WindowsAzure') logger.trace("Plugin Azure: Found waagent used by Azure.") true end end def has_dhcp_option_245? has_245 = false if file_exist?("/var/lib/dhcp/dhclient.eth0.leases") file_open("/var/lib/dhcp/dhclient.eth0.leases").each do |line| if /unknown-245/.match?(line) logger.trace("Plugin Azure: Found unknown-245 DHCP option used by Azure.") has_245 = true break end end end has_245 end def has_reddog_dhcp_domain? tcp_ip_dhcp_domain == "reddog.microsoft.com" end def tcp_ip_dhcp_domain return unless RUBY_PLATFORM.match?(/mswin|mingw32|windows/) require "win32/registry" unless defined?(Win32::Registry) begin key = Win32::Registry::HKEY_LOCAL_MACHINE.open("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters") dhcp_domain = key["DhcpDomain"] Ohai::Log.trace("Plugin Azure: DhcpDomain registry value is #{dhcp_domain}") rescue Win32::Registry::Error Ohai::Log.trace("Plugin Azure: DhcpDomain registry value cannot be found") end dhcp_domain end # create the basic structure we'll store our data in def initialize_metadata_mash_compute metadata = Mash.new metadata["compute"] = Mash.new metadata end def initialize_metadata_mash_network(metadata) metadata["network"] = Mash.new metadata["network"]["interfaces"] = Mash.new %w{public_ipv4 local_ipv4 public_ipv6 local_ipv6}.each do |type| metadata["network"][type] = [] end metadata end def fetch_ip_data(data, type, field) ips = [] data[type]["ipAddress"].each do |val| ips << val[field] unless val[field].empty? end ips end def parse_metadata return nil unless can_socket_connect?(Ohai::Mixin::AzureMetadata::AZURE_METADATA_ADDR, 80) endpoint_data = fetch_metadata return nil if endpoint_data.nil? metadata = initialize_metadata_mash_compute # blindly add everything in compute to our data structure endpoint_data["compute"].each do |k, v| metadata["compute"][k] = v end # receiving network output is not guaranteed unless endpoint_data["network"].nil? metadata = initialize_metadata_mash_network(metadata) # parse out per interface interface IP data endpoint_data["network"]["interface"].each do |int| metadata["network"]["interfaces"][int["macAddress"]] = Mash.new metadata["network"]["interfaces"][int["macAddress"]]["mac"] = int["macAddress"] metadata["network"]["interfaces"][int["macAddress"]]["public_ipv6"] = fetch_ip_data(int, "ipv6", "publicIpAddress") metadata["network"]["interfaces"][int["macAddress"]]["public_ipv4"] = fetch_ip_data(int, "ipv4", "publicIpAddress") metadata["network"]["interfaces"][int["macAddress"]]["local_ipv6"] = fetch_ip_data(int, "ipv6", "privateIpAddress") metadata["network"]["interfaces"][int["macAddress"]]["local_ipv4"] = fetch_ip_data(int, "ipv4", "privateIpAddress") end # aggregate the total IP data %w{public_ipv4 local_ipv4 public_ipv6 local_ipv6}.each do |type| metadata["network"]["interfaces"].each_value do |val| metadata["network"][type].concat val[type] unless val[type].empty? end end end metadata end end ohai-16.13.0/lib/ohai/plugins/php.rb0000644000175100017510000000316114034105661016114 0ustar pravipravi# # Author:: Doug MacEachern # Author:: Tim Smith # Copyright:: Copyright (c) 2009 VMware, Inc. # Copyright:: Copyright (c) 2014 Cozy Services, Ltd. # 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(:PHP) do provides "languages/php" depends "languages".freeze collect_data do so = shell_out("php -v") # Sample output: # PHP 5.5.31 (cli) (built: Feb 20 2016 20:33:10) # Copyright (c) 1997-2015 The PHP Group # Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies if so.exitstatus == 0 php = Mash.new so.stdout.each_line do |line| case line when /^PHP (\S+)(?:.*built: ([^)]+))?/ php[:version] = $1 php[:builddate] = $2 when /Zend Engine v([^\s]+),/ php[:zend_engine_version] = $1 when /Zend OPcache v([^\s]+),/ php[:zend_opcache_version] = $1 end end languages[:php] = php unless php.empty? end rescue Ohai::Exceptions::Exec logger.trace('Plugin Php: Could not shell_out "php -v". Skipping plugin') end end ohai-16.13.0/lib/ohai/plugins/erlang.rb0000644000175100017510000000441014034105661016573 0ustar pravipravi# frozen_string_literal: true # # Author:: Joe Williams () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Erlang) do provides "languages/erlang" depends "languages" collect_data do erlang = Mash.new begin so = shell_out("erl -eval '{ok, Ver} = file:read_file(filename:join([code:root_dir(), \"releases\", erlang:system_info(otp_release), \"OTP_VERSION\"])), Vsn = binary:bin_to_list(Ver, {0, byte_size(Ver) - 1}), io:format(\"~s,~s,~s\", [Vsn, erlang:system_info(version), erlang:system_info(nif_version)]), halt().' -noshell") # Sample output: # 19.1,8.1,2.11 if so.exitstatus == 0 output = so.stdout.split(",") erlang[:version] = output[0] erlang[:erts_version] = output[1] erlang[:nif_version] = output[2] end rescue Ohai::Exceptions::Exec logger.trace('Plugin Erlang: Could not shell_out "erl -eval \'erlang:display(erlang:system_info(otp_release)), erlang:display(erlang:system_info(version)), erlang:display(erlang:system_info(nif_version)), halt().\' -noshell". Skipping data') end begin so = shell_out("erl +V") # Sample output: # Erlang (SMP,ASYNC_THREADS,HIPE) (BEAM) emulator version 7.3 if so.exitstatus == 0 output = so.stderr.split if output.length >= 6 options = output[1] options.gsub!(/(\(|\))/, "") erlang[:options] = options.split(",") erlang[:emulator] = output[2].gsub!(/(\(|\))/, "") end end rescue Ohai::Exceptions::Exec logger.trace('Plugin Erlang: Could not shell_out "erl +V". Skipping data') end languages[:erlang] = erlang unless erlang.empty? end end ohai-16.13.0/lib/ohai/plugins/ps.rb0000644000175100017510000000210014034105661015737 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Author:: Bryan McLellan () # 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(:PS) do provides "command/ps" depends "command" collect_data(:aix, :darwin, :linux, :solaris2) do command[:ps] = "ps -ef" end collect_data(:freebsd, :netbsd, :openbsd, :dragonflybsd) do # ps -e requires procfs command[:ps] = "ps -axww" end end ohai-16.13.0/lib/ohai/plugins/scala.rb0000644000175100017510000000247414034105661016416 0ustar pravipravi# frozen_string_literal: true # Author:: Christopher M Luciano () # © Copyright IBM Corporation 2015. # 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(:Scala) do provides "languages/scala" depends "languages" collect_data(:default) do scala = Mash.new begin so = shell_out("scala -version") # Sample output: # cat: /release: No such file or directory # Scala code runner version 2.12.1 -- Copyright 2002-2016, LAMP/EPFL and Lightbend, Inc. if so.exitstatus == 0 scala[:version] = so.stderr.match(/.*version (\S*)/)[1] end rescue Ohai::Exceptions::Exec logger.trace('Plugin Scala: Could not shell_out "scala -version". Skipping data') end languages[:scala] = scala unless scala.empty? end end ohai-16.13.0/lib/ohai/plugins/shells.rb0000644000175100017510000000177714034105661016632 0ustar pravipravi# frozen_string_literal: true # # Author:: Tim Smith () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Shells) do provides "shells" collect_data do if file_exist?("/etc/shells") shells [] file_open("/etc/shells").readlines.each do |line| # remove carriage returns and skip over comments / empty lines shells << line.chomp if line[0] == "/" end end end end ohai-16.13.0/lib/ohai/plugins/windows/0000755000175100017510000000000014034105661016471 5ustar pravipraviohai-16.13.0/lib/ohai/plugins/windows/network.rb0000644000175100017510000001773614034105661020525 0ustar pravipravi# frozen_string_literal: true # # Author:: James Gartrell () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Network) do provides "network", "network/interfaces" provides "counters/network", "counters/network/interfaces" def windows_encaps_lookup(encap) return "Ethernet" if encap.eql?("Ethernet 802.3") encap end def mac_addresses(iface) prop = iface[:configuration][:mac_address] || iface[:instance][:network_addresses] [prop].flatten.map { |addr| addr.include?(":") ? addr : addr.scan(/.{1,2}/).join(":") } end def network_data @network_data ||= begin data = {} wmi = WmiLite::Wmi.new data[:addresses] = wmi.instances_of("Win32_NetworkAdapterConfiguration") # If we are running on windows nano or another operating system from the future # that does not populate the deprecated win32_* WMI classes, then we should # grab data from the newer MSFT_* classes return msft_adapter_data if data[:addresses].count == 0 data[:adapters] = wmi.instances_of("Win32_NetworkAdapter") data end end def msft_adapter_data data = {} wmi = WmiLite::Wmi.new("ROOT/StandardCimv2") data[:addresses] = wmi.instances_of("MSFT_NetIPAddress") data[:adapters] = wmi.instances_of("MSFT_NetAdapter") data end # Returns interface code for an interface # # Interface Index (if present, Index otherwise) will be converted in hexadecimal format # # @param int_idx [String or nil] the interface index of interface # @param idx [String] the index of interface # # @return [String] # # @example Interface Code when interface index is present # plugin.interface_code("1", "1") #=> "ox1" # @example Interface Code when interface index is not present # plugin.interface_code(nil, "2") #=> "ox2" # def interface_code(int_idx, idx) sprintf("0x%x", (int_idx || idx)).downcase end # Returns IPV4 address from list of addresses containing IPV4 and IPV6 formats # # @param addresses [Array] List of addresses # # @return [String] # # @example When list contains both IPV4 and IPV6 formats # plugin.prefer_ipv4([IPV4, IPV6]) #=> "IPV4" # @example When list contains only IPV6 format # plugin.prefer_ipv4([IPV6]) #=> "IPV6" # def prefer_ipv4(addresses) return nil unless addresses.is_a?(Array) addresses.find { |ip| IPAddress.valid_ipv4?(ip) } || addresses.find { |ip| IPAddress.valid_ipv6?(ip) } end # Selects default interface and returns its information # # @note Interface with least metric value should be preferred as default_route # # @param configuration [Mash] Configuration of interfaces as iface_config # [ => {}] # # @return [Hash<:index, :interface_index, :default_ip_gateway, :ip_connection_metric>] # def favored_default_route_windows(configuration) return nil unless configuration.is_a?(Hash) config = configuration.dup config.inject([]) do |arr, (k, v)| if v["default_ip_gateway"] arr << { index: v["index"], interface_index: v["interface_index"], default_ip_gateway: prefer_ipv4(v["default_ip_gateway"]), ip_connection_metric: v["ip_connection_metric"] } end arr end.min_by { |r| r[:ip_connection_metric] } end collect_data(:windows) do require "ipaddress" unless defined?(IPAddress) require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) iface = Mash.new iface_config = Mash.new iface_instance = Mash.new network Mash.new unless network network[:interfaces] ||= Mash.new counters Mash.new unless counters counters[:network] ||= Mash.new network_data[:addresses].each do |adapter| i = adapter["index"] || adapter["InterfaceIndex"] iface_config[i] ||= Mash.new iface_config[i][:ip_address] ||= [] iface_config[i][:ip_address] << adapter["IPAddress"] adapter.wmi_ole_object.properties_.each do |p| if iface_config[i][p.name.wmi_underscore.to_sym].nil? iface_config[i][p.name.wmi_underscore.to_sym] = adapter[p.name.downcase] end end end network_data[:adapters].each do |adapter| i = adapter["index"] || adapter["InterfaceIndex"] iface_instance[i] = Mash.new adapter.wmi_ole_object.properties_.each do |p| # skip wmi class name fields which make no sense in ohai next if %w{creation_class_name system_creation_class_name}.include?(p.name.wmi_underscore) iface_instance[i][p.name.wmi_underscore.to_sym] = adapter[p.name.downcase] end end iface_instance.each_key do |i| if iface_instance[i][:name] && iface_config[i] && iface_config[i][:ip_address][0] cint = interface_code(iface_instance[i][:interface_index], iface_instance[i][: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] = iface[cint][:configuration][:ip_address].flatten iface[cint][:configuration][:ip_address].each_index do |ip_index| ip = iface[cint][:configuration][:ip_address][ip_index] ip_and_subnet = ip.dup ip_and_subnet << "/#{iface[cint][:configuration][:ip_subnet][ip_index]}" if iface[cint][:configuration][:ip_subnet] ip2 = IPAddress(ip_and_subnet) iface[cint][:addresses][ip] = Mash.new(prefixlen: ip2.prefix) if ip2.ipv6? iface[cint][:addresses][ip][:family] = "inet6" iface[cint][:addresses][ip][:scope] = "Link" if /^fe80/i.match?(ip) else if iface[cint][:configuration][:ip_subnet] iface[cint][:addresses][ip][:netmask] = ip2.netmask.to_s if iface[cint][:configuration][:ip_use_zero_broadcast] iface[cint][:addresses][ip][:broadcast] = ip2.network.to_s else iface[cint][:addresses][ip][:broadcast] = ip2.broadcast.to_s end end iface[cint][:addresses][ip][:family] = "inet" end end mac_addresses(iface[cint]).each do |mac_addr| iface[cint][:addresses][mac_addr] = { "family" => "lladdr", } end iface[cint][:mtu] = iface[cint][:configuration][:mtu] if iface[cint][:configuration].key?(:mtu) iface[cint][:type] = iface[cint][:instance][:adapter_type] if iface[cint][:instance][:adapter_type] iface[cint][:arp] = {} iface[cint][:encapsulation] = windows_encaps_lookup(iface[cint][:instance][:adapter_type]) if iface[cint][:instance][:adapter_type] end end if (route = favored_default_route_windows(iface_config)) network[:default_gateway] = route[:default_ip_gateway] network[:default_interface] = interface_code(route[:interface_index], route[:index]) end cint = nil so = shell_out("arp -a") if so.exitstatus == 0 so.stdout.lines do |line| if line =~ /^Interface:\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+-+\s+(0x\S+)/ cint = $2.downcase 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.tr("-", ":").downcase end end end network["interfaces"] = iface end end ohai-16.13.0/lib/ohai/plugins/windows/drivers.rb0000644000175100017510000000331514034105661020476 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Drivers) do provides "kernel/pnp_drivers", "kernel/modules" depends "kernel" collect_data(:windows) do if configuration(:enabled) require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) kext = Mash.new pnp_drivers = Mash.new wmi = WmiLite::Wmi.new drivers = wmi.instances_of("Win32_PnPSignedDriver") drivers.each do |driver| pnp_drivers[driver["deviceid"]] = Mash.new driver.wmi_ole_object.properties_.each do |p| pnp_drivers[driver["deviceid"]][p.name.wmi_underscore.to_sym] = driver[p.name.downcase] 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 end end end ohai-16.13.0/lib/ohai/plugins/windows/system_enclosure.rb0000644000175100017510000000200314034105661022414 0ustar pravipravi# frozen_string_literal: true # # Author:: Stuart Preston () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin :SystemEnclosure do provides "system_enclosure" depends "dmi" collect_data(:windows) do system_enclosure Mash.new system_enclosure[:manufacturer] = get_attribute(:dmi, :chassis, :manufacturer) system_enclosure[:serialnumber] = get_attribute(:dmi, :chassis, :serial_number) end end ohai-16.13.0/lib/ohai/plugins/windows/dmi.rb0000644000175100017510000000645314034105661017577 0ustar pravipravi# frozen_string_literal: true # # Author:: Pete Higgins (pete@peterhiggins.org) # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:DMI) do provides "dmi" # Map the linux component types to their rough Windows API equivalents DMI_TO_WIN32OLE ||= { chassis: "SystemEnclosure", processor: "Processor", bios: "Bios", system: "ComputerSystemProduct", base_board: "BaseBoard", }.freeze # This regex is in 3 parts for the different supported patterns in camel # case names coming from the Windows API: # * Typical camelcase, eg Depth, PartNumber, NumberOfPowerCords # * Acronyms preceding camelcase, eg SMBIOSAssetTag # * Acronyms that occur at the end of the name, eg SKU, DeviceID # # This cannot handle some property names, eg SMBIOSBIOSVersion. # https://rubular.com/r/FBNtXod4wkZGAG SPLIT_REGEX ||= /[A-Z][a-z0-9]+|[A-Z]{2,}(?=[A-Z][a-z0-9])|[A-Z]{2,}/.freeze WINDOWS_TO_UNIX_KEYS ||= [ %w{vendor manufacturer}, %w{identifying_number serial_number}, %w{name family}, ].freeze collect_data(:windows) do require_relative "../../common/dmi" require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) wmi = WmiLite::Wmi.new dmi Mash.new # The Windows API returns property names in camel case, eg "SerialNumber", # while `dmi` returns them as space separated strings, eg "Serial Number". # `Ohai::Common::DMI.convenience_keys` expects property names in `dmi`'s # format, so build two parallel hashes with the keys as they come from the # Windows API and in a faked-out `dmi` version. After the call to # `Ohai::Common::DMI.convenience_keys` replace the faked-out `dmi` # collection with the one with the original property names. DMI_TO_WIN32OLE.each do |dmi_key, ole_key| wmi_objects = wmi.instances_of("Win32_#{ole_key}").map(&:wmi_ole_object) split_name_properties = [] properties = [] wmi_objects.each do |wmi_object| split_name_properties << Mash.new properties << Mash.new wmi_object.properties_.each do |property| property_name = property.name value = wmi_object.invoke(property_name) split_name = property_name.scan(SPLIT_REGEX).join(" ") split_name_properties.last[split_name] = value properties.last[property_name] = value end end dmi[dmi_key] = Mash.new(all_records: split_name_properties, _all_records: properties) end Ohai::Common::DMI.convenience_keys(dmi) dmi.each_value do |records| records[:all_records] = records.delete(:_all_records) WINDOWS_TO_UNIX_KEYS.each do |windows_key, unix_key| records[unix_key] = records.delete(windows_key) if records.key?(windows_key) end end end end ohai-16.13.0/lib/ohai/plugins/windows/memory.rb0000644000175100017510000000224014034105661020324 0ustar pravipravi# frozen_string_literal: true # # 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(:Memory) do provides "memory" collect_data(:windows) do require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) memory Mash.new memory[:swap] = Mash.new wmi = WmiLite::Wmi.new os = wmi.first_of("Win32_OperatingSystem") # MemTotal memory[:total] = os["TotalVisibleMemorySize"] + "kB" # MemFree memory[:free] = os["FreePhysicalMemory"] + "kB" # SwapTotal memory[:swap][:total] = os["SizeStoredInPagingFiles"] + "kB" # SwapFree memory[:swap][:free] = os["FreeSpaceInPagingFiles"] + "kB" end end ohai-16.13.0/lib/ohai/plugins/windows/virtualization.rb0000644000175100017510000000312014034105661022076 0ustar pravipravi# frozen_string_literal: true # # Author:: Pavel Yudin () # Author:: Tim Smith () # Copyright:: Copyright (c) 2015 Pavel Yudin # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Virtualization) do provides "virtualization" require_relative "../../mixin/dmi_decode" include Ohai::Mixin::DmiDecode collect_data(:windows) do require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) virtualization Mash.new unless virtualization virtualization[:systems] ||= Mash.new # Grab system DMI data from WMI to determine vendor information wmi = WmiLite::Wmi.new dmi = wmi.first_of("Win32_ComputerSystemProduct") guest = guest_from_dmi_data(dmi["vendor"], dmi["name"], dmi["version"]) if guest logger.trace("Plugin Virtualization: DMI data in Win32_ComputerSystemProduct indicates #{guest} guest") virtualization[:system] = guest virtualization[:role] = "guest" virtualization[:systems][guest.to_sym] = "guest" end end end ohai-16.13.0/lib/ohai/plugins/windows/platform.rb0000644000175100017510000000234014034105661020641 0ustar pravipravi# frozen_string_literal: true # # Author:: James Gartrell () # Copyright:: Copyright (c) Chef Software 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 consensus # 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. Ohai.plugin(:Platform) do provides "platform", "platform_version", "platform_family" collect_data(:windows) do platform os platform_version kernel["release"] platform_family "windows" end end ohai-16.13.0/lib/ohai/plugins/passwd.rb0000644000175100017510000000634414034105661016634 0ustar pravipravi# frozen_string_literal: true Ohai.plugin(:Passwd) do provides "etc", "current_user" optional true # @param [String] str # # @return [String] # def fix_encoding(str) str.force_encoding(Encoding.default_external) if str.respond_to?(:force_encoding) str end collect_data do require "etc" unless defined?(Etc) unless etc etc Mash.new etc[:passwd] = Mash.new etc[:group] = Mash.new Etc.passwd do |entry| user_passwd_entry = Mash.new(dir: entry.dir, gid: entry.gid, uid: entry.uid, shell: entry.shell, gecos: entry.gecos) user_passwd_entry.each_value { |v| fix_encoding(v) } entry_name = fix_encoding(entry.name) etc[:passwd][entry_name] = user_passwd_entry unless etc[:passwd].key?(entry_name) end Etc.group do |entry| group_entry = Mash.new(gid: entry.gid, members: entry.mem.map { |u| fix_encoding(u) }) etc[:group][fix_encoding(entry.name)] = group_entry end end unless current_user current_user fix_encoding(Etc.getpwuid(Process.euid).name) end end collect_data(:windows) do require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) unless etc etc Mash.new wmi = WmiLite::Wmi.new etc[:passwd] = Mash.new users = wmi.query("SELECT * FROM Win32_UserAccount WHERE LocalAccount = True") users.each do |user| uname = user["Name"].strip.downcase Ohai::Log.debug("processing user #{uname}") etc[:passwd][uname] = Mash.new wmi_obj = user.wmi_ole_object wmi_obj.properties_.each do |key| etc[:passwd][uname][key.name.downcase] = user[key.name] end end etc[:group] = Mash.new groups = wmi.query("SELECT * FROM Win32_Group WHERE LocalAccount = True") groups.each do |group| gname = group["Name"].strip.downcase Ohai::Log.debug("processing group #{gname}") etc[:group][gname] = Mash.new wmi_obj = group.wmi_ole_object wmi_obj.properties_.each do |key| etc[:group][gname][key.name.downcase] = group[key.name] end # This is the primary reason that we're using WMI instead of powershell # cmdlets - the powershell start up cost is huge, and you *must* do this # query for every. single. group. individually. # The query returns nothing unless you specify domain *and* name, it's # a path, not a set of queries. subq = "Win32_Group.Domain='#{group["Domain"]}',Name='#{group["Name"]}'" members = wmi.query( "SELECT * FROM Win32_GroupUser WHERE GroupComponent=\"#{subq}\"" ) etc[:group][gname]["members"] = members.map do |member| mi = {} info = Hash[ member["partcomponent"].split(",").map { |x| x.split("=") }.map { |a, b| [a, b.undump] } ] if info.keys.any? { |x| x.match?("Win32_UserAccount") } mi["type"] = :user else # NOTE: the type here is actually Win32_SystemAccount, because, # that's what groups are in the Windows universe. mi["type"] = :group end mi["name"] = info["Name"] mi end end end end end ohai-16.13.0/lib/ohai/plugins/fips.rb0000644000175100017510000000233614034105661016271 0ustar pravipravi# frozen_string_literal: true # # Author:: Matt Wrock () # Copyright:: Copyright (c) Chef Software 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. Ohai.plugin(:Fips) do provides "fips" collect_data(:linux, :windows) do fips Mash.new require "openssl" unless defined?(OpenSSL) fips["kernel"] = { "enabled" => OpenSSL::OPENSSL_FIPS } end end ohai-16.13.0/lib/ohai/plugins/powershell.rb0000644000175100017510000000541214034105661017512 0ustar pravipravi# # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Powershell) do provides "languages/powershell" depends "languages".freeze collect_data(:windows) do so = shell_out("powershell.exe -NoLogo -NonInteractive -NoProfile -command $PSVersionTable") # Sample output: # # Name Value # ---- ----- # PSVersion 4.0 # WSManStackVersion 3.0 # SerializationVersion 1.1.0.1 # CLRVersion 4.0.30319.34014 # BuildVersion 6.3.9600.16394 # PSCompatibleVersions {1.0, 2.0, 3.0, 4.0} # PSRemotingProtocolVersion 2.2 if so.exitstatus == 0 powershell = Mash.new version_info = {} so.stdout.strip.each_line do |line| kv = line.strip.split(/\s+/, 2) version_info[kv[0]] = kv[1] if kv.length == 2 end powershell[:version] = version_info["PSVersion"] powershell[:ws_man_stack_version] = version_info["WSManStackVersion"] powershell[:serialization_version] = version_info["SerializationVersion"] powershell[:clr_version] = version_info["CLRVersion"] powershell[:build_version] = version_info["BuildVersion"] powershell[:compatible_versions] = parse_compatible_versions powershell[:remoting_protocol_version] = version_info["PSRemotingProtocolVersion"] languages[:powershell] = powershell unless powershell.empty? end rescue Ohai::Exceptions::Exec logger.trace('Plugin Powershell: Could not shell_out "powershell.exe -NoLogo -NonInteractive -NoProfile -command $PSVersionTable". Skipping plugin') end def version_command [ "$progresspreference = 'silentlycontinue'", "$PSVersionTable.PSCompatibleVersions | foreach {$_.tostring()}", ].join("; ") end def powershell_command ["powershell.exe", "-NoLogo", "-NonInteractive", "-NoProfile", "-Command", ].join(" ") end def parse_compatible_versions so = shell_out("#{powershell_command} \"#{version_command}\"") versions = [] so.stdout.strip.each_line do |line| versions << line.strip end versions end end ohai-16.13.0/lib/ohai/plugins/hostname.rb0000644000175100017510000001272514034105661017151 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Author:: Benjamin Black () # Author:: Bryan McLellan () # Author:: Daniel DeLeo () # Author:: Doug MacEachern () # Author:: James Gartrell () # Author:: Isa Farnik () # Copyright:: Copyright (c) Chef Software Inc. # Copyright:: Copyright (c) 2009 Bryan McLellan # Copyright:: Copyright (c) 2009 Daniel DeLeo # Copyright:: Copyright (c) 2010 VMware, 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. # Ohai.plugin(:Hostname) do provides "domain", "hostname", "fqdn", "machinename" # hostname : short hostname # machinename : output of hostname command (might be short on solaris) # fqdn : result of canonicalizing hostname using DNS or /etc/hosts # domain : domain part of FQDN # # hostname and machinename should always exist # fqdn and domain may be broken if DNS is broken on the host def from_cmd(cmd) shell_out(cmd).stdout.strip end # forward and reverse lookup to canonicalize FQDN (hostname -f equivalent) # this is ipv6-safe, works on ruby 1.8.7+ def resolve_fqdn require "socket" unless defined?(Socket) require "ipaddr" unless defined?(IPAddr) hostname = from_cmd("hostname") addrinfo = Socket.getaddrinfo(hostname, nil).first iaddr = IPAddr.new(addrinfo[3]) Socket.gethostbyaddr(iaddr.hton)[0] rescue nil end def collect_domain # Domain is everything after the first dot if fqdn fqdn =~ /.+?\.(.*)/ domain $1 end end def collect_hostname # Hostname is everything before the first dot if machinename machinename =~ /([^.]+)\.?/ hostname $1 elsif fqdn fqdn =~ /(.+?)\./ hostname $1 end end collect_data(:default) do machinename from_cmd("hostname") fqdn resolve_fqdn collect_hostname collect_domain end collect_data(:aix) do machinename from_cmd("hostname -s") fqdn resolve_fqdn || from_cmd("hostname") collect_hostname collect_domain end collect_data(:netbsd, :openbsd, :dragonflybsd) do hostname from_cmd("hostname -s") fqdn resolve_fqdn machinename from_cmd("hostname") collect_domain end collect_data(:darwin) do hostname from_cmd("hostname -s") machinename from_cmd("hostname") begin our_fqdn = resolve_fqdn # Sometimes... very rarely, but sometimes, 'hostname --fqdn' falsely # returns a blank string. WTF. if our_fqdn.nil? || our_fqdn.empty? logger.trace("Plugin Hostname: hostname returned an empty string, retrying once.") our_fqdn = resolve_fqdn end if our_fqdn.nil? || our_fqdn.empty? logger.trace("Plugin Hostname: hostname returned an empty string twice and will" + "not be set.") else fqdn our_fqdn end rescue logger.trace( "Plugin Hostname: hostname returned an error, probably no domain set" ) end domain collect_domain end collect_data(:freebsd) do hostname from_cmd("hostname -s") machinename from_cmd("hostname") fqdn from_cmd("hostname -f") collect_domain end collect_data(:linux) do hostname from_cmd("hostname -s") machinename from_cmd("hostname") begin our_fqdn = from_cmd("hostname --fqdn") # Sometimes... very rarely, but sometimes, 'hostname --fqdn' falsely # returns a blank string. WTF. if our_fqdn.nil? || our_fqdn.empty? logger.trace("Plugin Hostname: hostname --fqdn returned an empty string, retrying " + "once.") our_fqdn = from_cmd("hostname --fqdn") end if our_fqdn.nil? || our_fqdn.empty? logger.trace("Plugin Hostname: hostname --fqdn returned an empty string twice and " + "will not be set.") else fqdn our_fqdn end rescue logger.trace("Plugin Hostname: hostname --fqdn returned an error, probably no domain set") end domain collect_domain end collect_data(:solaris2) do machinename from_cmd("hostname") hostname from_cmd("hostname") fqdn resolve_fqdn domain collect_domain end collect_data(:windows) do require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) require "socket" unless defined?(Socket) wmi = WmiLite::Wmi.new host = wmi.first_of("Win32_ComputerSystem") hostname host["dnshostname"].to_s machinename host["name"].to_s info = Socket.gethostbyname(Socket.gethostname) if /.+?\.(.*)/.match?(info.first) fqdn info.first else # host is not in dns. optionally use: # C:\WINDOWS\system32\drivers\etc\hosts info[3..info.length].reverse_each do |addr| hostent = Socket.gethostbyaddr(addr) if /.+?\.(.*)/.match?(hostent.first) fqdn hostent.first break end end fqdn info.first unless fqdn end domain collect_domain end end ohai-16.13.0/lib/ohai/plugins/ruby.rb0000644000175100017510000000416714034105661016315 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Ruby) do provides "languages/ruby" depends "languages" def run_ruby(command) cmd = "ruby -e \"require 'rbconfig'; #{command}\"" so = shell_out(cmd) so.stdout.strip end collect_data do languages[:ruby] = Mash.new values = { platform: "RUBY_PLATFORM", version: "RUBY_VERSION", release_date: "RUBY_RELEASE_DATE", target: "RbConfig::CONFIG['target']", target_cpu: "RbConfig::CONFIG['target_cpu']", target_vendor: "RbConfig::CONFIG['target_vendor']", target_os: "RbConfig::CONFIG['target_os']", host: "RbConfig::CONFIG['host']", host_cpu: "RbConfig::CONFIG['host_cpu']", host_os: "RbConfig::CONFIG['host_os']", host_vendor: "RbConfig::CONFIG['host_vendor']", bin_dir: "RbConfig::CONFIG['bindir']", ruby_bin: "::File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])", gem_bin: "::File.join(RbConfig::CONFIG['bindir'], ::Gem.default_exec_format % 'gem')", gems_dir: "::Gem.dir", } # Create a query string from above hash env_string = [] values.each_key do |v| env_string << "#{v}=\#{#{values[v]}}," end # Query the system ruby result = run_ruby "require 'rubygems'; puts %Q(#{env_string.join})" # Parse results to plugin hash result.split(",").each do |entry| key, value = entry.split("=") languages[:ruby][key.to_sym] = value || "" end end end ohai-16.13.0/lib/ohai/plugins/shard.rb0000644000175100017510000001003314034105661016422 0ustar pravipravi# # Author:: Phil Dibowitz # Copyright:: Copyright (c) 2016 Facebook, 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. # Ohai.plugin(:ShardSeed) do depends "hostname", "dmi", "machine_id", "machinename", "fips", "hardware", "kernel" provides "shard_seed".freeze def get_dmi_property(dmi, thing) %w{system base_board chassis}.each do |section| if dmi[section] && dmi[section][thing] && !dmi[section][thing].strip.empty? return dmi[section][thing] end end Ohai::Log.error("shard_seed: Failed to get dmi property #{thing}: is dmidecode installed?") raise "Failed to generate shard_seed" end def default_sources case collect_os when "linux", "darwin", "windows" %i{machinename serial uuid} else [:machinename] end end def default_digest_algorithm if fips && fips["kernel"]["enabled"] # Even though it is being used safely, FIPS-mode will still blow up on # any use of MD5 so default to SHA2 instead. "sha256" else "md5" end end def digest_algorithm case Ohai.config[:plugin][:shard_seed][:digest_algorithm] || default_digest_algorithm when "md5" require "digest/md5" unless defined?(Digest::MD5) Digest::MD5 when "sha256" require "openssl/digest" OpenSSL::Digest::SHA256 end end # Common sources go here. Put sources that need to be different per-platform # under their collect_data block. def create_seed(&block) sources = Ohai.config[:plugin][:shard_seed][:sources] || default_sources data = "" sources.each do |src| data << case src when :fqdn fqdn when :hostname hostname when :machine_id machine_id when :machinename machinename else yield(src) end end if data.empty? Ohai::Log.error("shard_seed: Unable to generate seed! Either ensure 'dmidecode' is installed, or use 'Ohai.config[:plugin][:shard_seed][:sources]' to set different sources.") raise "Failed to generate shard_seed" end shard_seed digest_algorithm.hexdigest(data)[0...7].to_i(16) end collect_data do create_seed do |src| Ohai::Log.error("shard_seed: No such source #{src}") raise "No such shard_seed source: #{src}" end end collect_data(:windows) do require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) wmi = WmiLite::Wmi.new create_seed do |src| case src when :serial wmi.first_of("Win32_BIOS")["SerialNumber"] when :os_serial kernel["os_info"]["serial_number"] when :uuid wmi.first_of("Win32_ComputerSystemProduct")["UUID"] else Ohai::Log.error("shard_seed: No such source #{src}") raise "No such shard_seed source: #{src}" end end end collect_data(:darwin) do create_seed do |src| case src when :serial hardware["serial_number"] when :uuid hardware["platform_UUID"] else Ohai::Log.error("shard_seed: No such source #{src}") raise "No such shard_seed source: #{src}" end end end collect_data(:linux) do create_seed do |src| case src when :serial get_dmi_property(dmi, :serial_number) when :uuid get_dmi_property(dmi, :uuid) else Ohai::Log.error("shard_seed: No such source #{src}") raise "No such shard_seed source: #{src}" end end end end ohai-16.13.0/lib/ohai/plugins/train.rb0000644000175100017510000000232514034105661016443 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Train) do provides "train" collect_data do if transport_connection train Mash.new train["family_hierarchy"] = transport_connection.platform.family_hierarchy train["family"] = transport_connection.platform.family train["platform"] = transport_connection.platform.platform train["backend"] = transport_connection.backend_type if transport_connection.respond_to?(:uri) train["scheme"] = URI.parse(transport_connection.uri).scheme train["uri"] = transport_connection.uri end end end end ohai-16.13.0/lib/ohai/plugins/softlayer.rb0000644000175100017510000000276214034105661017343 0ustar pravipravi# frozen_string_literal: true # # Author:: Alexey Karpik # Author:: Peter Schroeter # Author:: Stas Turlo # Copyright:: Copyright (c) 2010-2014 RightScale 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. Ohai.plugin(:Softlayer) do require_relative "../mixin/softlayer_metadata" include ::Ohai::Mixin::SoftlayerMetadata provides "softlayer" # Identifies the softlayer cloud # # === Return # true:: If the softlayer cloud can be identified # false:: Otherwise def looks_like_softlayer? hint?("softlayer") end collect_data do # Adds softlayer Mash if looks_like_softlayer? logger.trace("Plugin Softlayer: looks_like_softlayer? == true") metadata = fetch_metadata softlayer Mash.new metadata&.each { |k, v| softlayer[k] = v } else logger.trace("Plugin Softlayer: looks_like_softlayer? == false") end end end ohai-16.13.0/lib/ohai/plugins/libvirt.rb0000644000175100017510000000756514034105661017014 0ustar pravipravi# frozen_string_literal: true # # Author:: Benjamin Black () # Copyright:: Copyright (c) Chef Software 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. # # NOTE: This plugin requires libvirt-bin/libvirt-dev as well as the ruby-libvirt # gem to be installed before it will properly parse data Ohai.plugin(:Libvirt) do %w{uri capabilities nodeinfo domains networks storage}.each do |info| provides "libvirt/#{info}" depends "virtualization" end def emu @emu ||= (virtualization[:system].eql?("kvm") ? "qemu" : virtualization[:system]) end def load_libvirt require "libvirt" # this is the ruby-libvirt gem not the libvirt gem logger.trace("Plugin Libvirt: Successfully loaded ruby-libvirt gem") rescue LoadError logger.trace("Plugin Libvirt: Can't load gem ruby-libvirt.") end def virtconn @virt_connect ||= Libvirt.open_read_only("#{emu}:///system") end def get_node_data node_data = Mash.new ni = virtconn.node_get_info %w{cores cpus memory mhz model nodes sockets threads}.each { |a| node_data[a] = ni.send(a) } node_data end def get_domain_data domain_data = Mash.new virtconn.list_domains.each do |d| dv = virtconn.lookup_domain_by_id d domain_data[dv.name] = Mash.new domain_data[dv.name][:id] = d %w{os_type uuid}.each { |a| domain_data[dv.name][a] = dv.send(a) } %w{cpu_time max_mem memory nr_virt_cpu state}.each { |a| domain_data[dv.name][a] = dv.info.send(a) } end domain_data end def get_network_data network_data = Mash.new virtconn.list_networks.each do |n| nv = virtconn.lookup_network_by_name n network_data[n] = Mash.new %w{bridge_name uuid}.each { |a| network_data[n][a] = nv.send(a) } end network_data end def get_storage_data storage_data = Mash.new virtconn.list_storage_pools.each do |pool| sp = virtconn.lookup_storage_pool_by_name pool storage_data[pool] = Mash.new %w{autostart uuid}.each { |a| storage_data[pool][a] = sp.send(a) } %w{allocation available capacity state}.each { |a| storage_data[pool][a] = sp.info.send(a) } storage_data[pool][:volumes] = Mash.new sp.list_volumes.each do |v| storage_data[pool][:volumes][v] = Mash.new sv = sp.lookup_volume_by_name v %w{key name path}.each { |a| storage_data[pool][:volumes][v][a] = sv.send(a) } %w{allocation capacity type}.each { |a| storage_data[pool][:volumes][v][a] = sv.info.send(a) } end end storage_data end collect_data(:linux) do if virtualization[:role].eql?("host") load_libvirt begin libvirt_data = Mash.new libvirt_data[:uri] = virtconn.uri libvirt_data[:libvirt_version] = Libvirt.version(emu)[0].to_s libvirt_data[:nodeinfo] = get_node_data libvirt_data[:domains] = get_domain_data libvirt_data[:networks] = get_network_data libvirt_data[:storage] = get_storage_data virtconn.close libvirt libvirt_data rescue NameError logger.trace("Plugin Libvirt: Cannot load ruby-libvirt gem. Skipping...") rescue Libvirt::ConnectionError logger.trace("Plugin Libvirt: Failed to connect to #{emu}:///system. Skipping...") end else logger.trace("Plugin Libvirt: Node is not a virtualization host. Skipping...") end end end ohai-16.13.0/lib/ohai/plugins/elixir.rb0000644000175100017510000000227614034105661016627 0ustar pravipravi# Author:: Christopher M Luciano () # 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(:Elixir) do provides "languages/elixir" depends "languages".freeze collect_data do so = shell_out("elixir -v") # Sample output: # Erlang/OTP 18 [erts-7.3] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace] # # Elixir 1.2.4 if so.exitstatus == 0 && so.stdout =~ /^Elixir (\S*)/ elixir = Mash.new elixir[:version] = $1 languages[:elixir] = elixir end rescue Ohai::Exceptions::Exec logger.trace('Plugin Elixir: Could not shell_out "elixir -v". Skipping plugin') end end ohai-16.13.0/lib/ohai/plugins/digital_ocean.rb0000644000175100017510000000410414034105661020105 0ustar pravipravi# frozen_string_literal: true # # Author:: Dylan Page () # Author:: Stafford Brunk () # 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(:DigitalOcean) do require_relative "../mixin/do_metadata" require_relative "../mixin/http_helper" include Ohai::Mixin::DOMetadata include Ohai::Mixin::HttpHelper provides "digital_ocean" depends "dmi" # look for digitalocean string in dmi bios data def has_do_dmi? begin # detect a vendor of "DigitalOcean" if dmi[:bios][:all_records][0][:Vendor] == "DigitalOcean" logger.trace("Plugin DigitalOcean: has_do_dmi? == true") return true end rescue NoMethodError # dmi[:bios][:all_records][0][:Vendor] may not exist end logger.trace("Plugin DigitalOcean: has_do_dmi? == false") false end def looks_like_digital_ocean? return true if hint?("digital_ocean") return true if has_do_dmi? && can_socket_connect?(Ohai::Mixin::DOMetadata::DO_METADATA_ADDR, 80) false end # linux and freebsd is all digitalocean supports collect_data(:linux, :freebsd) do if looks_like_digital_ocean? logger.trace("Plugin Digitalocean: looks_like_digital_ocean? == true") digital_ocean Mash.new fetch_metadata.each do |k, v| next if k == "vendor_data" # this may have sensitive data we shouldn't store digital_ocean[k] = v end else logger.trace("Plugin Digitalocean: No hints present for and doesn't look like digitalocean") false end end end ohai-16.13.0/lib/ohai/plugins/rust.rb0000644000175100017510000000210514034105661016317 0ustar pravipravi# Author:: Christopher M Luciano () # 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(:Rust) do provides "languages/rust" depends "languages".freeze collect_data do so = shell_out("rustc --version") # Sample output: # rustc 1.7.0 if so.exitstatus == 0 rust = Mash.new rust[:version] = so.stdout.split[1] languages[:rust] = rust if rust[:version] end rescue Ohai::Exceptions::Exec logger.trace('Plugin Rust: Could not shell_out "rustc --version". Skipping plugin') end end ohai-16.13.0/lib/ohai/plugins/languages.rb0000644000175100017510000000145114034105661017273 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Languages) do provides "languages" collect_data do languages Mash.new end end ohai-16.13.0/lib/ohai/plugins/uptime.rb0000644000175100017510000000603414034105661016632 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Author:: Bryan McLellan () # Author:: Claire McQuin () # Author:: Doug MacEachern () # Author:: Kurt Yoder () # Author:: Paul Mooring () # Copyright:: Copyright (c) Chef Software Inc. # Copyright:: Copyright (c) 2009 Bryan McLellan # Copyright:: Copyright (c) 2010 VMware, 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. # Ohai.plugin(:Uptime) do require_relative "../mixin/seconds_to_human" provides "uptime", "uptime_seconds" provides "idletime", "idletime_seconds" # linux only def collect_uptime(path) # kern.boottime: { sec = 1232765114, usec = 823118 } Fri Jan 23 18:45:14 2009 so = shell_out("#{Ohai.abs_path(path)} kern.boottime") so.stdout.lines do |line| if line =~ /kern.boottime:\D+(\d+)/ usec = Time.new.to_i - $1.to_i return [usec, seconds_to_human(usec)] end end [nil, nil] end collect_data(:darwin) do data = collect_uptime("/usr/sbin/sysctl") uptime_seconds data.first uptime data.last end collect_data(:freebsd, :netbsd, :dragonflybsd) do data = collect_uptime("/sbin/sysctl") uptime_seconds data.first uptime data.last end collect_data(:linux) do uptime, idletime = file_open("/proc/uptime").gets.split uptime_seconds uptime.to_i uptime seconds_to_human(uptime.to_i) idletime_seconds idletime.to_i idletime seconds_to_human(idletime.to_i) end collect_data(:openbsd) do # kern.boottime=Tue Nov 1 14:45:52 2011 so = shell_out("#{Ohai.abs_path( "/sbin/sysctl" )} #kern.boottime") so.stdout.lines do |line| if line =~ /kern.boottime=(.+)/ uptime_seconds Time.new.to_i - Time.parse($1).to_i uptime seconds_to_human(uptime_seconds) end end end collect_data(:solaris2) do so = shell_out("kstat -p unix:0:system_misc:boot_time") # unix:0:system_misc:boot_time 1343860543 so.stdout.lines do |line| if line =~ /unix:0:system_misc:boot_time\s+(\d+)/ uptime_seconds Time.new.to_i - $1.to_i uptime seconds_to_human(uptime_seconds) end end end collect_data(:windows) do require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) wmi = WmiLite::Wmi.new last_boot_up_time = wmi.first_of("Win32_OperatingSystem")["lastbootuptime"] uptime_seconds Time.new.to_i - Time.parse(last_boot_up_time).to_i uptime seconds_to_human(uptime_seconds) end end ohai-16.13.0/lib/ohai/plugins/nodejs.rb0000644000175100017510000000234614034105661016613 0ustar pravipravi# # Author:: Jacques Marneweck () # Copyright:: Copyright (c) 2012 Jacques Marneweck. All rights reserved. # 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(:Nodejs) do provides "languages/nodejs" depends "languages".freeze collect_data do so = shell_out("node -v") # Sample output: # v5.10.1 if so.exitstatus == 0 nodejs = Mash.new output = so.stdout.split if output.length >= 1 nodejs[:version] = output[0][1..output[0].length] end languages[:nodejs] = nodejs if nodejs[:version] end rescue Ohai::Exceptions::Exec logger.trace('Plugin Nodejs: Could not shell_out "node -v". Skipping plugin') end end ohai-16.13.0/lib/ohai/plugins/keys.rb0000644000175100017510000000137214034105661016302 0ustar pravipravi# frozen_string_literal: true # # Cookbook Name:: apache2 # Recipe:: default # # Copyright:: Copyright (c) Chef Software Inc. # # 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(:Keys) do provides "keys" collect_data do keys Mash.new end end ohai-16.13.0/lib/ohai/plugins/os.rb0000644000175100017510000000270714034105661015753 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Author:: Isa Farnik () # Author:: Richard Manyanza () # Copyright:: Copyright (c) Chef Software Inc. # Copyright:: Copyright (c) 2014 Richard Manyanza. # 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(:OS) do require_relative "../mixin/os" provides "os", "os_version" depends "kernel" collect_data(:aix) do os collect_os os_version shell_out("oslevel -s").stdout.strip end collect_data(:dragonflybsd, :freebsd) do os collect_os # This is __DragonFly_version / __FreeBSD_version. See sys/param.h or # http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html. os_version shell_out("sysctl -n kern.osreldate").stdout.strip end collect_data(:target) do os collect_os end collect_data do os collect_os os_version kernel[:release] end end ohai-16.13.0/lib/ohai/plugins/vmware.rb0000644000175100017510000000477114034105661016636 0ustar pravipravi# frozen_string_literal: true # # Author:: "Dan Robinson" # Author:: "Christopher M. Luciano" # Copyright:: Copyright (c) Chef Software Inc. # Copyright (C) 2015 IBM Corp. # 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. # # # Provides a set of attributes for a VMware ESX virtual machine with results # obtained from vmware-toolbox-cmd. VMware Tools must be installed # on the virtual machine. # # Modify the path to vmware-toolbox-cmd in the call to get_vm_attributes for # your particular operating system and configuration # # Example: # # get_vm_attributes("/usr/bin/vmware-toolbox-cmd") # Ohai.plugin(:VMware) do provides "vmware" depends "virtualization" def from_cmd(cmd) shell_out(cmd).stdout.strip end def get_vm_attributes(vmtools_path) if !file_exist?(vmtools_path) logger.trace("Plugin VMware: #{vmtools_path} not found") else vmware Mash.new begin # vmware-toolbox-cmd stat commands # Iterate through each parameter supported by the "vwware-toolbox-cmd stat" command, assign value # to attribute "vmware[:]" %w{hosttime speed sessionid balloon swap memlimit memres cpures cpulimit}.each do |param| vmware[param] = from_cmd("#{vmtools_path} stat #{param}") if /UpdateInfo failed/.match?(vmware[param]) vmware[param] = nil end end # vmware-toolbox-cmd status commands # Iterate through each parameter supported by the "vmware-toolbox-cmd status" command, assign value # to attribute "vmware[:]" %w{upgrade timesync}.each do |param| vmware[param] = from_cmd("#{vmtools_path} #{param} status") end rescue logger.trace("Plugin VMware: Error while collecting VMware guest attributes") end end end collect_data(:linux) do get_vm_attributes("/usr/bin/vmware-toolbox-cmd") if virtualization[:systems][:vmware] end end ohai-16.13.0/lib/ohai/plugins/zpools.rb0000644000175100017510000000707114034105661016657 0ustar pravipravi# frozen_string_literal: true # # Author:: Jason J. W. Williams (williamsjj@digitar.com) # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Zpools) do provides "zpools" depends "platform_family" # If zpool status doesn't know about a field it returns '-'. # We don't want to fill a field with that def sanitize_value(value) value == "-" ? nil : value end def gather_pool_info pools = Mash.new begin # Grab ZFS zpools overall health and attributes so = shell_out("zpool list -H -o name,size,alloc,free,cap,dedup,health,version") so.stdout.lines do |line| case line when /^([-_0-9A-Za-z]*)\s+([.0-9]+[MGTPE])\s+([.0-9]+[MGTPE])\s+([.0-9]+[MGTPE])\s+(\d+%)\s+([.0-9]+x)\s+([-_0-9A-Za-z]+)\s+(\d+|-)$/ Ohai::Log.debug("Plugin Zpools: Parsing zpool list line: #{line.chomp}") pools[$1] = Mash.new pools[$1][:pool_size] = sanitize_value($2) pools[$1][:pool_allocated] = sanitize_value($3) pools[$1][:pool_free] = sanitize_value($4) pools[$1][:capacity_used] = sanitize_value($5) pools[$1][:dedup_factor] = sanitize_value($6) pools[$1][:health] = sanitize_value($7) pools[$1][:zpool_version] = sanitize_value($8) end end rescue Ohai::Exceptions::Exec Ohai::Log.debug('Plugin Zpools: Could not shell_out "zpool list -H -o name,size,alloc,free,cap,dedup,health,version". Skipping plugin.') end pools end collect_data(:solaris2, :linux, :freebsd, :openbsd, :netbsd, :dragonflybsd) do pools = gather_pool_info # Grab individual health for devices in the zpools pools.each_key do |pool| pools[pool][:devices] = Mash.new # Run "zpool status" as non-root user (adm) so that # the command won't try to open() each device which can # hang the command if any of the disks are bad. if platform_family == "solaris2" command = "su adm -c \"zpool status #{pool}\"" else # -L is used to give us real device names not label or uuid # for example sda instead of ata-WDC_WD60EZAZ-00SF3B0_WD-WX32D203UXYK command = "zpool status #{pool} -L" end so = shell_out(command) so.stdout.lines do |line| case line # linux: http://rubular.com/r/J3wQC6E2lH # solaris: http://rubular.com/r/FqOBzUQQ4p # freebsd: http://rubular.com/r/RYkMNlytXl when /^\s+((sd|c|ad|da|nvme|xvd)[-_a-zA-Z0-9]+)\s+([-_a-zA-Z0-9]+)\s+(\d+)\s+(\d+)\s+(\d+)$/ logger.trace("Plugin Zpools: Parsing zpool status line: #{line.chomp}") pools[pool][:devices][$1] = Mash.new pools[pool][:devices][$1][:state] = $3 pools[pool][:devices][$1][:errors] = Mash.new pools[pool][:devices][$1][:errors][:read] = $4 pools[pool][:devices][$1][:errors][:write] = $5 pools[pool][:devices][$1][:errors][:checksum] = $6 end end end # Set the zpools data zpools pools unless pools.empty? end end ohai-16.13.0/lib/ohai/plugins/netbsd/0000755000175100017510000000000014034105661016256 5ustar pravipraviohai-16.13.0/lib/ohai/plugins/netbsd/network.rb0000644000175100017510000001103214034105661020271 0ustar pravipravi# frozen_string_literal: true # # Author:: Bryan McLellan (btm@loftninjas.org) # 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(:Network) do provides "network", "network/interfaces" provides "counters/network", "counters/network/interfaces" collect_data(:netbsd) do network Mash.new unless network network[:interfaces] ||= Mash.new counters Mash.new unless counters counters[:network] ||= Mash.new shell_out("route -n get default").stdout.lines do |line| if line =~ /(\w+): ([\w\.]+)/ case $1 when "gateway" network[:default_gateway] = $2 when "interface" network[:default_interface] = $2 end end end iface = Mash.new cint = nil shell_out("#{Ohai.abs_path( "/sbin/ifconfig" )} -a").stdout.lines do |line| if line =~ /^([0-9a-zA-Z\.]+):\s+/ cint = $1 iface[cint] = Mash.new if cint =~ /^(\w+)(\d+.*)/ iface[cint][:type] = $1 iface[cint][:number] = $2 end end # call the family lladdr to match linux for consistency if line =~ /\s+address: (.+?)\s/ iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "lladdr" } end if line =~ /\s+inet ([\d.]+) netmask ([\da-fx]+)\s*\w*\s*([\d.]*)/ iface[cint][:addresses] ||= Mash.new # convert the netmask to decimal for consistency netmask = "#{$2[2, 2].hex}.#{$2[4, 2].hex}.#{$2[6, 2].hex}.#{$2[8, 2].hex}" if $3.empty? iface[cint][:addresses][$1] = { "family" => "inet", "netmask" => netmask } else # found a broadcast address iface[cint][:addresses][$1] = { "family" => "inet", "netmask" => netmask, "broadcast" => $3 } end end if line =~ /\s+inet6 ([a-f0-9\:]+)%?(\w*)\s+prefixlen\s+(\d+)\s*\w*\s*([\da-fx]*)/ iface[cint][:addresses] ||= Mash.new if $4.empty? iface[cint][:addresses][$1] = { "family" => "inet6", "prefixlen" => $3 } else # found a zone_id / scope iface[cint][:addresses][$1] = { "family" => "inet6", "zoneid" => $2, "prefixlen" => $3, "scopeid" => $4 } end end if line =~ /flags=\d+<(.+)>/ flags = $1.split(",") iface[cint][:flags] = flags if flags.length > 0 end if line =~ /metric: (\d+) mtu: (\d+)/ iface[cint][:metric] = $1 iface[cint][:mtu] = $2 end end shell_out("arp -an").stdout.lines do |line| if line =~ /\((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\) at ([a-fA-F0-9\:]+) on ([0-9a-zA-Z\.\:\-]+)/ next unless iface[$3] # this should never happen iface[$3][:arp] ||= Mash.new iface[$3][:arp][$1] = $2.downcase end end network["interfaces"] = iface net_counters = Mash.new # From netstat(1), not sure of the implications: # Show the state of all network interfaces or a single interface # which have been auto-configured (interfaces statically configured # into a system, but not located at boot time are not shown). shell_out("netstat -idn").stdout.lines do |line| # Name Mtu Network Address Ipkts Ierrs Opkts Oerrs Coll Drop # em0 1500 00:11:25:2d:90:be 3719557 0 3369969 0 0 0 # $1 $2 $3 $4 $5 $6 $7 $8 if line =~ /^([\w\.\*]+)\s+\d+\s+\s+([\w:]*)\s*(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/ net_counters[$1] ||= Mash.new net_counters[$1]["rx"] ||= Mash.new net_counters[$1]["tx"] ||= Mash.new net_counters[$1]["rx"]["packets"] = $3 net_counters[$1]["rx"]["errors"] = $4 net_counters[$1]["tx"]["packets"] = $5 net_counters[$1]["tx"]["errors"] = $6 net_counters[$1]["tx"]["collisions"] = $7 net_counters[$1]["tx"]["dropped"] = $8 end end counters[:network][:interfaces] = net_counters end end ohai-16.13.0/lib/ohai/plugins/netbsd/memory.rb0000644000175100017510000000660214034105661020117 0ustar pravipravi# frozen_string_literal: true # # Author:: Mathieu Sauve-Frankel # 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(:Memory) do provides "memory" collect_data(:netbsd) do memory Mash.new memory[:swap] = Mash.new # $ vmstat -s # 4096 bytes per page # 514011 pages managed # 224519 pages free # 209339 pages active # 4647 pages inactive # 0 pages being paged out # 5 pages wired # 0 pages zeroed # 4 pages reserved for pagedaemon # 6 pages reserved for kernel # 262205 swap pages # 0 swap pages in use # 0 total anon's in system # 0 free anon's # 1192991609 page faults # 1369579301 traps # 814549706 interrupts # 771702498 cpu context switches # 208810590 fpu context switches # 492361360 software interrupts # 1161998825 syscalls # 0 pagein operations # 0 swap ins # 0 swap outs # 768352 forks # 16 forks where vmspace is shared # 1763 kernel map entries # 0 number of times the pagedaemon woke up # 0 revolutions of the clock hand # 0 pages freed by pagedaemon # 0 pages scanned by pagedaemon # 0 pages reactivated by pagedaemon # 0 busy pages found by pagedaemon # 1096393776 total name lookups # cache hits (37% pos + 2% neg) system 1% per-directory # deletions 0%, falsehits 6%, toolong 26% # 0 select collisions so = shell_out("vmstat -s") so.stdout.lines do |line| case line when /(\d+) bytes per page/ memory[:page_size] = $1 when /(\d+) pages managed/ memory[:page_count] = $1 memory[:total] = memory[:page_size].to_i * memory[:page_count].to_i when /(\d+) pages free/ memory[:free] = memory[:page_size].to_i * $1.to_i when /(\d+) pages active/ memory[:active] = memory[:page_size].to_i * $1.to_i when /(\d+) pages inactive/ memory[:inactive] = memory[:page_size].to_i * $1.to_i when /(\d+) pages wired/ memory[:wired] = memory[:page_size].to_i * $1.to_i end end so = shell_out("swapctl -l") so.stdout.lines do |line| # Device 1024-blocks Used Avail Capacity Priority # swap_device 1048824 0 1048824 0% 0 if line =~ %r{^([\d\w/]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+([\d\%]+)} mdev = $1 memory[:swap][mdev] = Mash.new memory[:swap][mdev][:total] = $2 memory[:swap][mdev][:used] = $3 memory[:swap][mdev][:free] = $4 memory[:swap][mdev][:percent_free] = $5 end end end end ohai-16.13.0/lib/ohai/plugins/netbsd/platform.rb0000644000175100017510000000172714034105661020436 0ustar pravipravi# frozen_string_literal: true # # Author:: Bryan McLellan (btm@loftninjas.org) # 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(:Platform) do provides "platform", "platform_version", "platform_family" collect_data(:netbsd) do platform shell_out("uname -s").stdout.strip.downcase platform_version shell_out("uname -r").stdout.strip platform_family "netbsd" end end ohai-16.13.0/lib/ohai/plugins/openstack.rb0000644000175100017510000000546214034105661017322 0ustar pravipravi# frozen_string_literal: true # # Author:: Matt Ray () # Author:: Tim Smith () # Copyright:: Copyright (c) Chef Software 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. Ohai.plugin(:Openstack) do require_relative "../mixin/ec2_metadata" require_relative "../mixin/http_helper" include Ohai::Mixin::Ec2Metadata include Ohai::Mixin::HttpHelper provides "openstack" depends "virtualization" # use virtualization data def openstack_virtualization? if get_attribute(:virtualization, :systems, :openstack) logger.trace("Plugin Openstack: has_openstack_virtualization? == true") true end end # check for the ohai hint and log trace messaging def openstack_hint? if hint?("openstack") logger.trace("Plugin Openstack: openstack hint present") true else logger.trace("Plugin Openstack: openstack hint not present") false end end # dreamhost systems *had* the dhc-user on them < 2016. We should probably remove all this logic # https://help.dreamhost.com/hc/en-us/articles/228377408-How-to-find-the-default-user-of-an-image def openstack_provider # dream host doesn't support windows so bail early if we're on windows return "openstack" if RUBY_PLATFORM.match?(/mswin|mingw32|windows/) if Etc::Passwd.entries.map(&:name).include?("dhc-user") "dreamhost" else "openstack" end end collect_data do require "etc" unless defined?(Etc) # fetch data if we look like openstack if openstack_hint? || openstack_virtualization? openstack Mash.new openstack[:provider] = openstack_provider timeout = Ohai::Config.ohai[:openstack_metadata_timeout] || 2 # fetch the metadata if we can do a simple socket connect first if can_socket_connect?(Ohai::Mixin::Ec2Metadata::EC2_METADATA_ADDR, 80, timeout) fetch_metadata.each do |k, v| openstack[k] = v unless v.empty? end logger.trace("Plugin Openstack: Successfully fetched Openstack metadata from the metadata endpoint") else logger.trace("Plugin Openstack: Timed out connecting to Openstack metadata endpoint. Skipping metadata.") end else logger.trace("Plugin Openstack: Node does not appear to be an Openstack node") end end end ohai-16.13.0/lib/ohai/plugins/python.rb0000644000175100017510000000270114034105661016645 0ustar pravipravi# # Author:: Thom May () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Python) do provides "languages/python" depends "languages".freeze collect_data do so = shell_out("python -c \"import sys; print (sys.version)\"") # Sample output: # 2.7.11 (default, Dec 26 2015, 17:47:53) # [GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] if so.exitstatus == 0 python = Mash.new output = so.stdout.split python[:version] = output[0] if output.length >= 6 python[:builddate] = "%s %s %s %s" % [output[2], output[3], output[4], output[5].delete!(")")] end languages[:python] = python unless python.empty? end rescue Ohai::Exceptions::Exec logger.trace('Plugin Python: Could not shell_out "python -c "import sys; print (sys.version)"". Skipping plugin') end end ohai-16.13.0/lib/ohai/plugins/docker.rb0000644000175100017510000000433314034105661016576 0ustar pravipravi# frozen_string_literal: true # # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Docker) do provides "docker" depends "virtualization" def docker_info_json so = shell_out("docker info --format '{{json .}}'") if so.exitstatus == 0 JSON.parse(so.stdout) end rescue Ohai::Exceptions::Exec logger.trace('Plugin Docker: Could not shell_out "docker info --format \'{{json .}}\'". Skipping plugin') end def docker_ohai_data(shellout_data) docker Mash.new docker[:version_string] = shellout_data["ServerVersion"] docker[:version] = shellout_data["ServerVersion"].split("-")[0] if shellout_data["ServerVersion"] # guard this so missing data doesn't fail the run docker[:runtimes] = shellout_data["Runtimes"] docker[:root_dir] = shellout_data["DockerRootDir"] docker[:containers] = {} docker[:containers][:total] = shellout_data["Containers"] docker[:containers][:running] = shellout_data["ContainersRunning"] docker[:containers][:paused] = shellout_data["ContainersPaused"] docker[:containers][:stopped] = shellout_data["ContainersStopped"] docker[:plugins] = shellout_data["Plugins"] docker[:networking] = {} docker[:networking][:ipv4_forwarding] = shellout_data["IPv4Forwarding"] docker[:networking][:bridge_nf_iptables] = shellout_data["BridgeNfIptables"] docker[:networking][:bridge_nf_ipv6_iptables] = shellout_data["BridgeNfIp6tables"] docker[:swarm] = shellout_data["Swarm"] end collect_data(:linux, :windows, :darwin) do require "json" unless defined?(JSON) if virtualization[:systems][:docker] docker_ohai_data(docker_info_json) end end end ohai-16.13.0/lib/ohai/plugins/rackspace.rb0000644000175100017510000001326614034105661017270 0ustar pravipravi# frozen_string_literal: true # # Author:: Cary Penniman () # 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(:Rackspace) do provides "rackspace" depends "kernel", "network/interfaces" # Checks for matching rackspace kernel name # # === Return # true:: If kernel name matches # false:: Otherwise def has_rackspace_kernel? kernel[:release].end_with?("-rscloud") end # Checks for rackspace provider attribute # # === Return # true:: If rackspace provider attribute found # false:: Otherwise def has_rackspace_metadata? so = shell_out("xenstore-read vm-data/provider_data/provider") if so.exitstatus == 0 so.stdout.strip.casecmp("rackspace") == 0 end rescue Ohai::Exceptions::Exec false end # Checks for the rackspace manufacturer on Windows # === Return # true:: If the rackspace cloud can be identified # false:: Otherwise def has_rackspace_manufacturer? return false unless RUBY_PLATFORM.match?(/mswin|mingw32|windows/) require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) wmi = WmiLite::Wmi.new if wmi.first_of("Win32_ComputerSystem")["PrimaryOwnerName"] == "Rackspace" logger.trace("Plugin Rackspace: has_rackspace_manufacturer? == true") true end end # Identifies the rackspace cloud # # === Return # true:: If the rackspace cloud can be identified # false:: Otherwise def looks_like_rackspace? hint?("rackspace") || has_rackspace_metadata? || has_rackspace_kernel? || has_rackspace_manufacturer? end # Names rackspace ip address # # === Parameters # name:: Use :public_ip or :private_ip # eth:: Interface name of public or private ip def get_ip_address(name, eth) network[:interfaces][eth][:addresses].each do |key, info| if info["family"] == "inet" rackspace[name] = key break # break when we found an address end end end # Names rackspace ipv6 address for interface # # === Parameters # name:: Use :public_ip or :private_ip # eth:: Interface name of public or private ip def get_global_ipv6_address(name, eth) network[:interfaces][eth][:addresses].each do |key, info| # check if we got an ipv6 address and if its in global scope if info["family"] == "inet6" && info["scope"] == "Global" rackspace[name] = key break # break when we found an address end end end # Get the rackspace region # def get_region so = shell_out("xenstore-ls vm-data/provider_data") if so.exitstatus == 0 so.stdout.split("\n").each do |line| rackspace[:region] = line.split[2].delete('\"') if /^region/.match?(line) end end rescue Ohai::Exceptions::Exec logger.trace("Plugin Rackspace: Unable to find xenstore-ls, cannot capture region information for Rackspace cloud") nil end # Get the rackspace instance_id # def get_instance_id so = shell_out("xenstore-read name") if so.exitstatus == 0 rackspace[:instance_id] = so.stdout.gsub(/instance-/, "") end rescue Ohai::Exceptions::Exec logger.trace("Plugin Rackspace: Unable to find xenstore-read, cannot capture instance ID information for Rackspace cloud") nil end # Get the rackspace private networks # def get_private_networks so = shell_out("xenstore-ls vm-data/networking") if so.exitstatus == 0 networks = [] so.stdout.split("\n").map { |l| l.split("=").first.strip }.map do |item| so = shell_out("xenstore-read vm-data/networking/#{item}") if so.exitstatus == 0 networks.push(FFI_Yajl::Parser.new.parse(so.stdout)) else logger.trace("Plugin Rackspace: Unable to capture custom private networking information for Rackspace cloud") return false end end # these networks are already known to ohai, and are not 'private networks' networks.delete_if { |hash| hash["label"] == "private" } networks.delete_if { |hash| hash["label"] == "public" } end rescue Ohai::Exceptions::Exec logger.trace("Plugin Rackspace: Unable to capture custom private networking information for Rackspace cloud") nil end collect_data do require "resolv" # Adds rackspace Mash if looks_like_rackspace? rackspace Mash.new get_ip_address(:public_ip, :eth0) get_ip_address(:private_ip, :eth1) get_region get_instance_id # public_ip + private_ip are deprecated in favor of public_ipv4 and local_ipv4 to standardize. rackspace[:public_ipv4] = rackspace[:public_ip] get_global_ipv6_address(:public_ipv6, :eth0) unless rackspace[:public_ip].nil? rackspace[:public_hostname] = begin Resolv.getname(rackspace[:public_ip]) rescue Resolv::ResolvError, Resolv::ResolvTimeout rackspace[:public_ip] end end rackspace[:local_ipv4] = rackspace[:private_ip] get_global_ipv6_address(:local_ipv6, :eth1) rackspace[:local_hostname] = hostname private_networks = get_private_networks rackspace[:private_networks] = private_networks if private_networks end end end ohai-16.13.0/lib/ohai/plugins/scsi.rb0000644000175100017510000000300414034105661016262 0ustar pravipravi# frozen_string_literal: true # # Author:: Phil Dibowitz # Copyright:: Copyright (c) 2018 Facebook, 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. # Ohai.plugin(:Lsscsi) do provides "scsi" optional true require "mixlib/shellout" unless defined?(Mixlib::ShellOut::DEFAULT_READ_TIMEOUT) collect_data(:linux) do devices = Mash.new lsscsi = shell_out("lsscsi") lsscsi.stdout.each_line do |line| line_bits = line.split info = {} # The first three fields are consistent... info["scsi_addr"] = line_bits.shift[1..-2] info["type"] = line_bits.shift info["transport"] = line_bits.shift # After that the last two are consistent... info["device"] = line_bits.pop info["revision"] = line_bits.pop # What"s in the middle is the make and model... # which could have arbitrary spaces info["name"] = line_bits.join(" ") devices[info["scsi_addr"]] = info end scsi devices end end ohai-16.13.0/lib/ohai/plugins/ohai_time.rb0000644000175100017510000000150014034105661017256 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:OhaiTime) do provides "ohai_time" collect_data(:default, :target) do ohai_time Time.now.to_f end end ohai-16.13.0/lib/ohai/plugins/chef.rb0000644000175100017510000000357514034105661016243 0ustar pravipravi# frozen_string_literal: true # # Author:: Tollef Fog Heen # Copyright:: Copyright (c) 2010 Tollef Fog Heen # 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(:Chef) do provides "chef_packages/chef" def chef_effortless? # Determine if client is being run as a Habitat package. if Chef::CHEF_ROOT.include?("hab/pkgs/chef/chef") # Determine if client is running in zero mode which would show it is using the Effortless pattern. # Explicitly set response to true or nil, not false ChefConfig::Config["chef_server_url"].include?("chefzero://") end end collect_data(:default, :target) do begin require "chef/version" require "chef-config/config" unless defined?(ChefConfig::Config) rescue Gem::LoadError logger.trace("Plugin Chef: Unable to load the chef gem to determine the version") # this catches when you've done a major version bump of ohai, but # your chef gem is incompatible, so we can't load it in the same VM # (affects mostly internal testing) next # avoids us writing an empty mash end chef_packages Mash.new unless chef_packages chef_packages[:chef] = Mash.new chef_packages[:chef][:version] = Chef::VERSION chef_packages[:chef][:chef_root] = Chef::CHEF_ROOT chef_packages[:chef][:chef_effortless] = chef_effortless? end end ohai-16.13.0/lib/ohai/plugins/gce.rb0000644000175100017510000000536214034105661016070 0ustar pravipravi# frozen_string_literal: true # # Author:: Ranjib Dey () # 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(:GCE) do require_relative "../mixin/gce_metadata" require_relative "../mixin/http_helper" include Ohai::Mixin::GCEMetadata include Ohai::Mixin::HttpHelper provides "gce" # look for GCE string in dmi vendor bios data within the sys tree. # this works even if the system lacks dmidecode use by the Dmi plugin # @return [Boolean] do we have Google Compute Engine DMI data? def has_gce_dmi? if /Google Compute Engine/.match?(file_val_if_exists("/sys/class/dmi/id/product_name")) logger.trace("Plugin GCE: has_gce_dmi? == true") true else logger.trace("Plugin GCE: has_gce_dmi? == false") false end end # return the contents of a file if the file exists # @param path[String] abs path to the file # @return [String] contents of the file if it exists def file_val_if_exists(path) if file_exist?(path) file_read(path) end end # looks at the Manufacturer and Model WMI values to see if they starts with Google. # @return [Boolean] Are the manufacturer and model Google? def has_gce_system_info? if RUBY_PLATFORM.match?(/mswin|mingw32|windows/) require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) wmi = WmiLite::Wmi.new computer_system = wmi.first_of("Win32_ComputerSystem") if computer_system["Manufacturer"] =~ /^Google/ && computer_system["Model"] =~ /^Google/ logger.trace("Plugin GCE: has_gce_system_info? == true") true end else logger.trace("Plugin GCE: has_gce_system_info? == false") false end end # Identifies gce # # === Return # true:: If gce can be identified # false:: Otherwise def looks_like_gce? return true if hint?("gce") if has_gce_dmi? || has_gce_system_info? return true if can_socket_connect?(Ohai::Mixin::GCEMetadata::GCE_METADATA_ADDR, 80) end end collect_data do if looks_like_gce? logger.trace("Plugin GCE: looks_like_gce? == true") gce Mash.new fetch_metadata.each { |k, v| gce[k] = v } else logger.trace("Plugin GCE: looks_like_gce? == false") false end end end ohai-16.13.0/lib/ohai/plugins/timezone.rb0000644000175100017510000000150114034105661017153 0ustar pravipravi# frozen_string_literal: true # # Author:: John Bellone () # 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(:Timezone) do provides "time/timezone" collect_data(:default) do time Mash.new unless time time[:timezone] = Time.now.getlocal.zone end end ohai-16.13.0/lib/ohai/plugins/openbsd/0000755000175100017510000000000014034105661016431 5ustar pravipraviohai-16.13.0/lib/ohai/plugins/openbsd/network.rb0000644000175100017510000001103314034105661020445 0ustar pravipravi# frozen_string_literal: true # # Author:: Bryan McLellan (btm@loftninjas.org) # 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(:Network) do provides "network", "network/interfaces" provides "counters/network", "counters/network/interfaces" collect_data(:openbsd) do network Mash.new unless network network[:interfaces] ||= Mash.new counters Mash.new unless counters counters[:network] ||= Mash.new shell_out("route -n get default").stdout.lines do |line| if line =~ /(\w+): ([\w\.]+)/ case $1 when "gateway" network[:default_gateway] = $2 when "interface" network[:default_interface] = $2 end end end iface = Mash.new cint = nil shell_out( "#{Ohai.abs_path( "/sbin/ifconfig" )} -a" ).stdout.lines do |line| if line =~ /^([0-9a-zA-Z\.]+):\s+/ cint = $1 iface[cint] = Mash.new if cint =~ /^(\w+)(\d+.*)/ iface[cint][:type] = $1 iface[cint][:number] = $2 end end # call the family lladdr to match linux for consistency if line =~ /\s+lladdr (.+?)\s/ iface[cint][:addresses] ||= Mash.new iface[cint][:addresses][$1] = { "family" => "lladdr" } end if line =~ /\s+inet ([\d.]+) netmask ([\da-fx]+)\s*\w*\s*([\d.]*)/ iface[cint][:addresses] ||= Mash.new # convert the netmask to decimal for consistency netmask = "#{$2[2, 2].hex}.#{$2[4, 2].hex}.#{$2[6, 2].hex}.#{$2[8, 2].hex}" if $3.empty? iface[cint][:addresses][$1] = { "family" => "inet", "netmask" => netmask } else # found a broadcast address iface[cint][:addresses][$1] = { "family" => "inet", "netmask" => netmask, "broadcast" => $3 } end end if line =~ /\s+inet6 ([a-f0-9\:]+)%?(\w*)\s+prefixlen\s+(\d+)\s*\w*\s*([\da-fx]*)/ iface[cint][:addresses] ||= Mash.new if $4.empty? iface[cint][:addresses][$1] = { "family" => "inet6", "prefixlen" => $3 } else # found a zone_id / scope iface[cint][:addresses][$1] = { "family" => "inet6", "zoneid" => $2, "prefixlen" => $3, "scopeid" => $4 } end end if line =~ /flags=\d+<(.+)>/ flags = $1.split(",") iface[cint][:flags] = flags if flags.length > 0 end if line =~ /metric: (\d+) mtu: (\d+)/ iface[cint][:metric] = $1 iface[cint][:mtu] = $2 end end shell_out("arp -an").stdout.lines do |line| if line =~ /\((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\) at ([a-fA-F0-9\:]+) on ([0-9a-zA-Z\.\:\-]+)/ next unless iface[$3] # this should never happen iface[$3][:arp] ||= Mash.new iface[$3][:arp][$1] = $2.downcase end end network["interfaces"] = iface net_counters = Mash.new # From netstat(1), not sure of the implications: # Show the state of all network interfaces or a single interface # which have been auto-configured (interfaces statically configured # into a system, but not located at boot time are not shown). shell_out("netstat -idn").stdout.lines do |line| # Name Mtu Network Address Ipkts Ierrs Opkts Oerrs Coll Drop # em0 1500 00:11:25:2d:90:be 3719557 0 3369969 0 0 0 # $1 $2 $3 $4 $5 $6 $7 $8 if line =~ /^([\w\.\*]+)\s+\d+\s+\s+([\w:]*)\s*(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/ net_counters[$1] ||= Mash.new net_counters[$1]["rx"] ||= Mash.new net_counters[$1]["tx"] ||= Mash.new net_counters[$1]["rx"]["packets"] = $3 net_counters[$1]["rx"]["errors"] = $4 net_counters[$1]["tx"]["packets"] = $5 net_counters[$1]["tx"]["errors"] = $6 net_counters[$1]["tx"]["collisions"] = $7 net_counters[$1]["tx"]["dropped"] = $8 end end counters[:network][:interfaces] = net_counters end end ohai-16.13.0/lib/ohai/plugins/openbsd/memory.rb0000644000175100017510000000662214034105661020274 0ustar pravipravi# frozen_string_literal: true # # Author:: Mathieu Sauve-Frankel # 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(:Memory) do provides "memory", "memory/swap" collect_data(:openbsd) do memory Mash.new memory[:swap] = Mash.new # $ vmstat -s # 4096 bytes per page # 514011 pages managed # 224519 pages free # 209339 pages active # 4647 pages inactive # 0 pages being paged out # 5 pages wired # 0 pages zeroed # 4 pages reserved for pagedaemon # 6 pages reserved for kernel # 262205 swap pages # 0 swap pages in use # 0 total anon's in system # 0 free anon's # 1192991609 page faults # 1369579301 traps # 814549706 interrupts # 771702498 cpu context switches # 208810590 fpu context switches # 492361360 software interrupts # 1161998825 syscalls # 0 pagein operations # 0 swap ins # 0 swap outs # 768352 forks # 16 forks where vmspace is shared # 1763 kernel map entries # 0 number of times the pagedaemon woke up # 0 revolutions of the clock hand # 0 pages freed by pagedaemon # 0 pages scanned by pagedaemon # 0 pages reactivated by pagedaemon # 0 busy pages found by pagedaemon # 1096393776 total name lookups # cache hits (37% pos + 2% neg) system 1% per-directory # deletions 0%, falsehits 6%, toolong 26% # 0 select collisions so = shell_out("vmstat -s") so.stdout.lines do |line| case line when /(\d+) bytes per page/ memory[:page_size] = $1 when /(\d+) pages managed/ memory[:page_count] = $1 memory[:total] = memory[:page_size].to_i * memory[:page_count].to_i when /(\d+) pages free/ memory[:free] = memory[:page_size].to_i * $1.to_i when /(\d+) pages active/ memory[:active] = memory[:page_size].to_i * $1.to_i when /(\d+) pages inactive/ memory[:inactive] = memory[:page_size].to_i * $1.to_i when /(\d+) pages wired/ memory[:wired] = memory[:page_size].to_i * $1.to_i end end so = shell_out("swapctl -l") so.stdout.lines do |line| # Device 1024-blocks Used Avail Capacity Priority # swap_device 1048824 0 1048824 0% 0 if line =~ %r{^([\d\w/]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+([\d\%]+)} mdev = $1 memory[:swap][mdev] = Mash.new memory[:swap][mdev][:total] = $2 memory[:swap][mdev][:used] = $3 memory[:swap][mdev][:free] = $4 memory[:swap][mdev][:percent_free] = $5 end end end end ohai-16.13.0/lib/ohai/plugins/openbsd/platform.rb0000644000175100017510000000173114034105661020604 0ustar pravipravi# frozen_string_literal: true # # Author:: Bryan McLellan (btm@loftninjas.org) # 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(:Platform) do provides "platform", "platform_version", "platform_family" collect_data(:openbsd) do platform shell_out("uname -s").stdout.strip.downcase platform_version shell_out("uname -r").stdout.strip platform_family "openbsd" end end ohai-16.13.0/lib/ohai/plugins/platform.rb0000644000175100017510000000202414034105661017146 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Platform) do provides "platform", "platform_version", "platform_family" depends "os", "os_version" collect_data(:default) do platform os unless attribute?("platform") platform_version os_version unless attribute?("platform_version") platform_family platform unless attribute?("platform_family") end end ohai-16.13.0/lib/ohai/plugins/bsd/0000755000175100017510000000000014034105661015547 5ustar pravipraviohai-16.13.0/lib/ohai/plugins/bsd/virtualization.rb0000644000175100017510000001100714034105661021157 0ustar pravipravi# frozen_string_literal: true # # Author:: Bryan McLellan (btm@loftninjas.org) # Copyright:: Copyright (c) 2009 Bryan McLellan # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Virtualization) do provides "virtualization" depends "dmi" require_relative "../../mixin/dmi_decode" include Ohai::Mixin::DmiDecode collect_data(:freebsd, :openbsd, :netbsd, :dragonflybsd) do virtualization Mash.new unless virtualization virtualization[:systems] ||= Mash.new # detect when in a jail or when a jail is actively running (not in stopped state) so = shell_out("sysctl -n security.jail.jailed") if so.stdout.strip.to_i == 1 virtualization[:system] = "jail" virtualization[:role] = "guest" virtualization[:systems][:jail] = "guest" logger.trace("Plugin Virtualization: Guest running in FreeBSD jail detected") end # run jls to get a list of running jails # -n: name=value 1 line per jail format # -d: list the dying jails as well as active jails so = shell_out("jls -nd") if (so.stdout || "").lines.count >= 1 virtualization[:system] = "jail" virtualization[:role] = "host" virtualization[:systems][:jail] = "host" logger.trace("Plugin Virtualization: Host running FreeBSD jails detected") end # detect from modules so = shell_out(Ohai.abs_path("/sbin/kldstat").to_s) so.stdout.lines do |line| case line when /vboxdrv/ virtualization[:system] = "vbox" virtualization[:role] = "host" virtualization[:systems][:vbox] = "host" logger.trace("Plugin Virtualization: Guest running on VirtualBox detected") when /vboxguest/ virtualization[:system] = "vbox" virtualization[:role] = "guest" virtualization[:systems][:vbox] = "guest" logger.trace("Plugin Virtualization: Host running VirtualBox detected") end end # Detect bhyve by presence of /dev/vmm if file_exist?("/dev/vmm") virtualization[:system] = "bhyve" virtualization[:role] = "host" virtualization[:systems][:bhyve] = "host" logger.trace("Plugin Virtualization: Host running bhyve detected") end # Detect KVM/QEMU paravirt guests from cpu, report as KVM # hw.model: QEMU Virtual CPU version 0.9.1 so = shell_out("sysctl -n hw.model") if /QEMU Virtual CPU|KVM processor/.match?(so.stdout) virtualization[:system] = "kvm" virtualization[:role] = "guest" virtualization[:systems][:kvm] = "guest" logger.trace("Plugin Virtualization: Guest running on KVM detected") end # gather hypervisor of guests from sysctl kern.vm_guest # there are a limited number of hypervisors detected here, BUT it doesn't # require dmidecode to be installed and dmidecode isn't in freebsd out of the box so = shell_out("sysctl -n kern.vm_guest") hypervisor = case so.stdout when /vmware/ "vmware" when /hv/ "hyperv" when /xen/ "xen" when /kvm/ so = shell_out("sysctl -n kern.hostuuid") /^ec2/.match?(so.stdout) ? "amazonec2" : "kvm" when /bhyve/ "bhyve" end if hypervisor virtualization[:system] = hypervisor virtualization[:role] = "guest" virtualization[:systems][hypervisor.to_sym] = "guest" logger.trace("Plugin Virtualization: Guest running on #{hypervisor} detected") end # parse dmi to discover various virtualization guests guest = guest_from_dmi_data(get_attribute(:dmi, :system, :manufacturer), get_attribute(:dmi, :system, :product), get_attribute(:dmi, :system, :version)) if guest logger.trace("Plugin Virtualization: DMI data indicates #{guest} guest") virtualization[:system] = guest virtualization[:role] = "guest" virtualization[:systems][guest.to_sym] = "guest" end end end ohai-16.13.0/lib/ohai/plugins/init_package.rb0000644000175100017510000000161014034105661017740 0ustar pravipravi# frozen_string_literal: true # # Author:: Caleb Tennis () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:InitPackage) do provides "init_package" collect_data(:linux) do init_package file_exist?("/proc/1/comm") ? file_open("/proc/1/comm").gets.chomp : "init" end end ohai-16.13.0/lib/ohai/plugins/cpu.rb0000644000175100017510000003447614034105661016131 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Author:: Bryan McLellan (btm@loftninjas.org) # Author:: Tim Smith (tsmith@chef.io) # Author:: Mathieu Sauve-Frankel # Author:: Nathan L Smith () # Author:: Joshua Timberman # Author:: Prabhu Das () # Author:: Isa Farnik () # Author:: Doug MacEachern # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:CPU) do provides "cpu" def parse_bsd_dmesg(&block) cpuinfo = Mash.new cpuinfo["flags"] = [] file_open("/var/run/dmesg.boot").each do |line| case line when /CPU:\s+(.+) \(([\d.]+).+\)/ cpuinfo["model_name"] = $1 cpuinfo["mhz"] = $2 when /Features=.+<(.+)>/, /Features2=[a-f\dx]+<(.+)>/ cpuinfo["flags"].concat($1.downcase.split(",")) # Features2=0x80000001> else yield(cpuinfo, line) end end cpuinfo end collect_data(:linux) do cpuinfo = Mash.new real_cpu = Mash.new cpu_number = 0 current_cpu = nil file_open("/proc/cpuinfo").each do |line| case line when /processor\s+:\s(.+)/ cpuinfo[$1] = Mash.new current_cpu = $1 cpu_number += 1 when /vendor_id\s+:\s(.+)/ vendor_id = $1 if vendor_id.include?("IBM/S390") cpuinfo["vendor_id"] = vendor_id else cpuinfo[current_cpu]["vendor_id"] = vendor_id end when /cpu family\s+:\s(.+)/ cpuinfo[current_cpu]["family"] = $1 when /model\s+:\s(.+)/ cpuinfo[current_cpu]["model"] = $1 when /stepping\s+:\s(.+)/ cpuinfo[current_cpu]["stepping"] = $1 when /physical id\s+:\s(.+)/ cpuinfo[current_cpu]["physical_id"] = $1 real_cpu[$1] = true when /core id\s+:\s(.+)/ cpuinfo[current_cpu]["core_id"] = $1 when /cpu cores\s+:\s(.+)/ cpuinfo[current_cpu]["cores"] = $1 when /model name\s+:\s(.+)/ cpuinfo[current_cpu]["model_name"] = $1 when /cpu MHz\s+:\s(.+)/ cpuinfo[current_cpu]["mhz"] = $1 when /cache size\s+:\s(.+)/ cpuinfo[current_cpu]["cache_size"] = $1 when /flags\s+:\s(.+)/ cpuinfo[current_cpu]["flags"] = $1.split when /BogoMIPS\s+:\s(.+)/ cpuinfo[current_cpu]["bogomips"] = $1 when /Features\s+:\s(.+)/ cpuinfo[current_cpu]["features"] = $1.split when /bogomips per cpu:\s(.+)/ cpuinfo["bogomips_per_cpu"] = $1 when /features\s+:\s(.+)/ cpuinfo["features"] = $1.split when /processor\s(\d):\s(.+)/ current_cpu = $1 cpu_number += 1 cpuinfo[current_cpu] = Mash.new current_cpu_info = $2.split(",") current_cpu_info.each do |i| name_value = i.split("=") name = name_value[0].strip value = name_value[1].strip cpuinfo[current_cpu][name] = value end end end cpu cpuinfo cpu[:total] = cpu_number # use data we collected unless cpuinfo is lacking core information # which is the case on older linux distros if !real_cpu.empty? && cpu["0"]["cores"] cpu[:real] = real_cpu.keys.length cpu[:cores] = real_cpu.keys.length * cpu["0"]["cores"].to_i else begin logger.trace("Plugin CPU: Falling back to aggregate data from lscpu as real cpu & core data is missing in /proc/cpuinfo") so = shell_out("lscpu") if so.exitstatus == 0 lscpu_data = Mash.new so.stdout.each_line do |line| case line when /^Thread\(s\) per core:\s(.+)/ # http://rubular.com/r/lOw2pRrw1q lscpu_data[:threads] = $1.to_i when /^Core\(s\) per socket:\s(.+)/ # http://rubular.com/r/lOw2pRrw1q lscpu_data[:cores] = $1.to_i when /^Socket\(s\):\s(.+)/ # http://rubular.com/r/DIzmPtJFvK lscpu_data[:sockets] = $1.to_i end end cpu[:total] = lscpu_data[:sockets] * lscpu_data[:cores] * lscpu_data[:threads] cpu[:real] = lscpu_data[:sockets] cpu[:cores] = lscpu_data[:sockets] * lscpu_data[:cores] else logger.trace("Plugin CPU: Error executing lscpu. CPU data may not be available.") end rescue Ohai::Exceptions::Exec # util-linux isn't installed most likely logger.trace("Plugin CPU: Error executing lscpu. util-linux may not be installed.") end end end collect_data(:freebsd) do # all dmesg output for smp I can find only provides info about a single processor # identical processors is probably a hardware requirement so we'll duplicate data for each cpu # old examples: http://www.bnv-bamberg.de/home/ba3294/smp/rbuild/index.htm # /var/run/dmesg.boot # CPU: Intel(R) Core(TM) i7-4980HQ CPU @ 2.80GHz (2793.59-MHz K8-class CPU) # Origin="GenuineIntel" Id=0x40661 Family=0x6 Model=0x46 Stepping=1 # Features=0x783fbff # Features2=0x5ed8220b # AMD Features=0x28100800 # AMD Features2=0x21 # Structured Extended Features=0x2000 # TSC: P-state invariant # ... # FreeBSD/SMP: Multiprocessor System Detected: 16 CPUs # FreeBSD/SMP: 2 package(s) x 4 core(s) x 2 SMT threads info = parse_bsd_dmesg do |cpuinfo, line| case line when /Origin.*"(.*)".*Family.*0x(\S+).*Model.*0x(\S+).*Stepping.*(\S+)/ cpuinfo["vendor_id"] = $1 # convert from hex value to int, but keep a string to match Linux ohai cpuinfo["family"] = $2.to_i(16).to_s cpuinfo["model"] = $3.to_i(16).to_s cpuinfo["stepping"] = $4 # These _should_ match /AMD Features2?/ lines as well when %r{FreeBSD/SMP: Multiprocessor System Detected: (\d*) CPUs} cpuinfo["total"] = $1.to_i when %r{FreeBSD/SMP: (\d*) package\(s\) x (\d*) core\(s\)} cpuinfo["real"] = $1.to_i cpuinfo["cores"] = $1.to_i * $2.to_i end end cpu info end collect_data(:dragonflybsd) do # /var/run/dmesg.boot # CPU: Intel(R) Core(TM) i7-3615QM CPU @ 2.30GHz (3516.61-MHz K8-class CPU) # Origin = "GenuineIntel" Id = 0x306a9 Family = 6 Model = 3a Stepping = 9 # Features=0x783fbff # Features2=0x209 # AMD Features=0x28100800 # AMD Features2=0x1 info = parse_bsd_dmesg do |cpuinfo, line| case line when /Origin = "(.+)"\s+Id = (.+)\s+Stepping = (.+)/ cpuinfo["vendor_id"] = $1 cpuinfo["stepping"] = $3 end end so = shell_out("sysctl -n hw.ncpu") info[:total] = so.stdout.strip.to_i cpu info end collect_data(:openbsd) do cpuinfo = Mash.new # OpenBSD provides most cpu information via sysctl, the only thing we need to # to scrape from dmesg.boot is the cpu feature list. # cpu0: FPU,V86,DE,PSE,TSC,MSR,MCE,CX8,SEP,MTRR,PGE,MCA,CMOV,PAT,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,TM,SBF,EST,TM2 file_open("/var/run/dmesg.boot").each do |line| case line when /cpu\d+:\s+([A-Z]+$|[A-Z]+,.*$)/ cpuinfo["flags"] = $1.downcase.split(",") end end [["hw.model", :model_name], ["hw.ncpu", :total], ["hw.cpuspeed", :mhz]].each do |param, node| so = shell_out("sysctl -n #{param}") cpuinfo[node] = so.stdout.strip end cpu cpuinfo end collect_data(:netbsd) do cpuinfo = Mash.new # NetBSD provides some cpu information via sysctl, and a little via dmesg.boot # unlike OpenBSD and FreeBSD, NetBSD does not provide information about the # available instruction set # cpu0 at mainbus0 apid 0: Intel 686-class, 2134MHz, id 0x6f6 file_open("/var/run/dmesg.boot").each do |line| case line when /cpu[\d\w\s]+:\s([\w\s\-]+),\s+(\w+),/ cpuinfo[:model_name] = $1 cpuinfo[:mhz] = $2.gsub(/mhz/i, "") end end flags = [] so = shell_out("dmidecode") so.stdout.lines do |line| if line =~ /^\s+([A-Z\d-]+)\s+\([\w\s-]+\)$/ flags << $1.downcase end end cpuinfo[:flags] = flags unless flags.empty? cpu cpuinfo end collect_data(:darwin) do cpu Mash.new shell_out("sysctl hw machdep").stdout.lines.each do |line| case line when /^hw.packages: (.*)$/ cpu[:real] = Regexp.last_match[1].to_i when /^hw.physicalcpu: (.*)$/ cpu[:cores] = Regexp.last_match[1].to_i when /^hw.logicalcpu: (.*)$/ cpu[:total] = Regexp.last_match[1].to_i when /^hw.cpufrequency: (.*)$/ cpu[:mhz] = Regexp.last_match[1].to_i / 1000000 when /^machdep.cpu.vendor: (.*)$/ cpu[:vendor_id] = Regexp.last_match[1].chomp when /^machdep.cpu.brand_string: (.*)$/ cpu[:model_name] = Regexp.last_match[1].chomp when /^machdep.cpu.model: (.*)$/ cpu[:model] = Regexp.last_match[1].to_i when /^machdep.cpu.family: (.*)$/ cpu[:family] = Regexp.last_match[1].to_i when /^machdep.cpu.stepping: (.*)$/ cpu[:stepping] = Regexp.last_match[1].to_i when /^machdep.cpu.features: (.*)$/ cpu[:flags] = Regexp.last_match[1].downcase.split end end end collect_data(:aix) do cpu Mash.new cpu[:total] = shell_out("pmcycles -m").stdout.lines.length # The below is only relevent on an LPAR if shell_out("uname -W").stdout.strip == "0" # At least one CPU will be available, but we'll wait to increment this later. cpu[:available] = 0 cpudevs = shell_out("lsdev -Cc processor").stdout.lines # from http://www-01.ibm.com/software/passportadvantage/pvu_terminology_for_customers.html # on AIX number of cores and processors are considered same cpu[:real] = cpu[:cores] = cpudevs.length cpudevs.each.with_index do |c, i| name, status, location = c.split index = i.to_s cpu[index] = Mash.new cpu[index][:status] = status cpu[index][:location] = location if /Available/.match?(status) cpu[:available] += 1 lsattr = shell_out("lsattr -El #{name}").stdout.lines lsattr.each do |attribute| attrib, value = attribute.split if attrib == "type" cpu[index][:model_name] = value elsif attrib == "frequency" cpu[index][:mhz] = value.to_i / (1000 * 1000) # convert from hz to MHz else cpu[index][attrib] = value end end # IBM is the only maker of CPUs for AIX systems. cpu[index][:vendor_id] = "IBM" end end end end collect_data(:solaris2) do cpu Mash.new # This does assume that /usr/bin/kstat is in the path processor_info = shell_out("kstat -p cpu_info").stdout.lines cpu["total"] = 0 cpu["sockets"] = 0 cpu["cores"] = 0 cpu["corethreads"] = 0 cpu["cpustates"] = Mash.new currentcpu = 0 cpucores = [] cpusockets = [] processor_info.each do |processor| _desc, instance, _record, keyvalue = processor.split(":") cpu[instance] ||= Mash.new if currentcpu != instance cpu["total"] += 1 currentcpu = instance end kv = keyvalue.split(/\s+/) key = kv.shift value = kv.join(" ").chomp case key when /chip_id/ cpu[instance]["socket"] = value cpusockets.push(value) if cpusockets.index(value).nil? when /cpu_type/ cpu[instance]["arch"] = value when /clock_MHz/ cpu[instance]["mhz"] = value when /brand/ cpu[instance]["model_name"] = value.sub(/\s+/, " ") when /^state$/ cpu[instance]["state"] = value cpu["cpustates"][value] ||= 0 cpu["cpustates"][value] += 1 when /core_id/ cpu[instance]["core_id"] = value # Detect hyperthreading/multithreading cpucores.push(value) if cpucores.index(value).nil? when /family|fpu_type|model|stepping|vendor_id/ cpu[instance][key] = value end end cpu["cores"] = cpucores.size cpu["corethreads"] = (cpu["total"] / cpucores.size) cpu["sockets"] = cpusockets.size cpu["real"] = cpusockets.size end collect_data(:windows) do require "wmi-lite/wmi" unless defined?(WmiLite::Wmi) cpu Mash.new cores = 0 logical_processors = 0 wmi = WmiLite::Wmi.new processors = wmi.instances_of("Win32_Processor") processors.each_with_index do |processor, index| current_cpu = index.to_s cpu[current_cpu] = Mash.new cpu[current_cpu]["cores"] = processor["numberofcores"] cores += processor["numberofcores"] logical_processors += processor["numberoflogicalprocessors"] cpu[current_cpu]["vendor_id"] = processor["manufacturer"] cpu[current_cpu]["family"] = processor["family"].to_s cpu[current_cpu]["model"] = processor["revision"].to_s cpu[current_cpu]["stepping"] = if processor["stepping"].nil? processor["description"].match(/Stepping\s+(\d+)/)[1] else processor["stepping"] end cpu[current_cpu]["physical_id"] = processor["deviceid"] cpu[current_cpu]["model_name"] = processor["name"] cpu[current_cpu]["description"] = processor["description"] cpu[current_cpu]["mhz"] = processor["maxclockspeed"].to_s cpu[current_cpu]["cache_size"] = "#{processor["l2cachesize"]} KB" end cpu[:total] = logical_processors cpu[:cores] = cores cpu[:real] = processors.length end end ohai-16.13.0/lib/ohai/plugins/virtualbox.rb0000644000175100017510000001562714034105661017536 0ustar pravipravi# frozen_string_literal: true # # Author:: Tim Smith # Author:: Joshua Colson # Copyright:: Copyright (c) Chef Software Inc. # Copyright:: 2019 Joshua Colson # 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(:Virtualbox) do depends "virtualization" provides "virtualbox" # query virtualbox for each configured vm, as well as # each guest's individual configuration settings def vboxmanage_list_vms vms = Mash.new so_cmd = "VBoxManage list --sorted vms" logger.trace(so_cmd) so = shell_out(so_cmd) if so.exitstatus == 0 # parse the output so.stdout.lines.each do |line| case line when /^"(\S*)" \{(\S*)\}$/ name = Regexp.last_match(1) uuid = Regexp.last_match(2) vms[name] = vboxmanage_vminfo(uuid) end end end vms rescue Ohai::Exceptions::Exec logger.trace("Plugin VboxHost: Could not run 'VBoxManage list --sorted vms'. Skipping data") end # query the vminfo for particular guest instance, normalizing # the fields so that they're not enclosed in double-quotes (") def vboxmanage_vminfo(machine_id) vm = Mash.new so_cmd = "VBoxManage showvminfo #{machine_id} --machinereadable" logger.trace(so_cmd) so = shell_out(so_cmd) if so.exitstatus == 0 so.stdout.lines.each do |line| line.chomp! left, right = line.split("=") # remove enclosing quotes, if needed key = left.delete_prefix('"').delete_suffix('"') # skip the name attribute since that is the parent key next if key == "name" vm[key.downcase] = right.delete_prefix('"').delete_suffix('"') end end vm rescue Ohai::Exceptions::Exec logger.trace("Plugin VboxHost: Could not run '#{so_cmd}'. Skipping data") end # query virtualbox for a list of #{query_type} items # these queries return a result set that is delimited by # multiple successive newlines, with each block containing # key/value pairs delimited by a colon (:) and column aligned # # the keys of each k/v pair are normalized to lowercase def vboxmanage_list_blocks(query_type, name_key) # ignore unrecognized query type supported_queries = %w{ bridgedifs dhcpservers dvds hdds hostdvds hostfloppies hostonlyifs natnets } return nil unless supported_queries.include? query_type results = Mash.new so_cmd = "VBoxManage list --sorted #{query_type}" logger.trace(so_cmd) so = shell_out(so_cmd) # raise an exception if the command fails # so.error! if so.exitstatus == 0 # break the result into paragraph blocks, on successive newlines so.stdout.each_line("") do |blk| # remove the multiple newlines of each record blk.chomp!.chomp! # initialize a blank record hash record = Mash.new # parse the record block into key/value pairs blk.each_line do |line| next unless line.include? ":" # split the line into key/value pair key, right = line.split(":", 2) # strip the leading/trailing whitespace if the value is not nil value = right.nil? ? "" : right.strip record[key.downcase] = value end # insert the record into the list of results if record.key? name_key.downcase name = record.delete(name_key.downcase) results[name] = record end end end results rescue Ohai::Exceptions::Exec logger.trace("Plugin VboxHost: Could not run '#{so_cmd}'. Skipping data") end collect_data(:windows, :linux, :solaris2, :darwin) do case virtualization.dig("systems", "vbox") when "guest" logger.trace("Plugin Virtualbox: Node detected as vbox guest. Collecting guest data.") begin so = shell_out("VBoxControl guestproperty enumerate") if so.exitstatus == 0 virtualbox Mash.new virtualbox[:host] = Mash.new virtualbox[:guest] = Mash.new so.stdout.lines.each do |line| case line when /LanguageID, value: (\S*),/ virtualbox[:host][:language] = Regexp.last_match(1) when /VBoxVer, value: (\S*),/ virtualbox[:host][:version] = Regexp.last_match(1) when /VBoxRev, value: (\S*),/ virtualbox[:host][:revision] = Regexp.last_match(1) when %r{GuestAdd/VersionExt, value: (\S*),} virtualbox[:guest][:guest_additions_version] = Regexp.last_match(1) when %r{GuestAdd/Revision, value: (\S*),} virtualbox[:guest][:guest_additions_revision] = Regexp.last_match(1) end end end rescue Ohai::Exceptions::Exec logger.trace('Plugin Virtualbox: Could not execute "VBoxControl guestproperty enumerate". Skipping data collection.') end when "host" logger.trace("Plugin Virtualbox: Node detected as vbox host. Collecting host data.") virtualbox Mash.new begin # get a list of virtualbox guest vms virtualbox["guests"] = vboxmanage_list_vms # get a list of virtualbox virtual hard disk drives virtualbox["hdds"] = vboxmanage_list_blocks("hdds", "Location") # get a list of virtualbox virtual dvd drives virtualbox["dvds"] = vboxmanage_list_blocks("dvds", "Location") # get a list of virtualbox host dvd drives virtualbox["hostdvds"] = vboxmanage_list_blocks("hostdvds", "Name") # get a list of virtualbox host floppy drives virtualbox["hostfloppies"] = vboxmanage_list_blocks("hostfloppies", "Name") # get a list of virtualbox hostonly network interfaces virtualbox["hostonlyifs"] = vboxmanage_list_blocks("hostonlyifs", "Name") # get a list of virtualbox bridged network interfaces virtualbox["bridgedifs"] = vboxmanage_list_blocks("bridgedifs", "Name") # get a list of virtualbox dhcp servers virtualbox["dhcpservers"] = vboxmanage_list_blocks("dhcpservers", "NetworkName") # get a list of virtualbox nat networks virtualbox["natnets"] = vboxmanage_list_blocks("natnets", "NetworkName") rescue Ohai::Exceptions::Exec logger.trace("Plugin VboxHost: Could not collect data for VirtualBox host. Skipping data") end else logger.trace("Plugin Virtualbox: Not on a Virtualbox host or guest. Skipping plugin.") end end end ohai-16.13.0/lib/ohai/plugins/go.rb0000644000175100017510000000207014034105661015730 0ustar pravipravi# Author:: Christian Vozar () # 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(:Go) do provides "languages/go" depends "languages".freeze collect_data do so = shell_out("go version") # Sample output: # go version go1.6.1 darwin/amd64 if so.exitstatus == 0 && so.stdout =~ /go(\S+)/ go = Mash.new go[:version] = $1 languages[:go] = go end rescue Ohai::Exceptions::Exec logger.trace('Plugin Go: Could not shell_out "go version". Skipping plugin') end end ohai-16.13.0/lib/ohai/plugins/kernel.rb0000644000175100017510000002265514034105661016616 0ustar pravipravi# 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 ohai-16.13.0/lib/ohai/plugins/mono.rb0000644000175100017510000000333114034105661016274 0ustar pravipravi# # Author:: Doug MacEachern # Copyright:: Copyright (c) 2009 VMware, 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. # Ohai.plugin(:Mono) do provides "languages/mono" depends "languages".freeze collect_data do so = shell_out("mono -V") # Sample output: # Mono JIT compiler version 4.2.3 (Stable 4.2.3.4/832de4b Wed Mar 30 13:57:48 PDT 2016) # Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com # TLS: normal # SIGSEGV: altstack # Notification: kqueue # Architecture: amd64 # Disabled: none # Misc: softtrace # LLVM: supported, not enabled. # GC: sgen if so.exitstatus == 0 mono = Mash.new output = so.stdout.split mono[:version] = output[4] unless output[4].nil? if output.length >= 12 mono[:builddate] = "%s %s %s %s %s %s" % [output[7], output[8], output[9], output[10], output[11], output[12].delete!(")")] end languages[:mono] = mono unless mono.empty? end rescue Ohai::Exceptions::Exec logger.trace('Plugin Mono: Could not shell_out "mono -V". Skipping plugin') end end ohai-16.13.0/lib/ohai/plugins/lua.rb0000644000175100017510000000247414034105661016114 0ustar pravipravi# # Author:: Doug MacEachern # Copyright:: Copyright (c) 2009 VMware, 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. # Ohai.plugin(:Lua) do provides "languages/lua" depends "languages".freeze collect_data do so = shell_out("lua -v") # Sample output: # Lua 5.2.4 Copyright (C) 1994-2015 Lua.org, PUC-Rio if so.exitstatus == 0 lua = Mash.new # at some point in lua's history they went from outputting the version # on stderr to doing it on stdout. This handles old / new versions lua[:version] = so.stdout.empty? ? so.stderr.split[1] : so.stdout.split[1] languages[:lua] = lua if lua[:version] end rescue Ohai::Exceptions::Exec logger.trace('Plugin Lua: Could not shell_out "lua -v". Skipping plugin') end end ohai-16.13.0/lib/ohai/plugins/packages.rb0000644000175100017510000002063214034105661017105 0ustar pravipravi# frozen_string_literal: true # Author:: "Christian Höltje" # Author:: "Christopher M. Luciano" # Author:: Shahul Khajamohideen () # Copyright (C) 2015 IBM Corp. # Copyright (C) 2015 Bloomberg Finance L.P. # 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(:Packages) do provides "packages" depends "platform_family" WINDOWS_ATTRIBUTE_ALIASES ||= { "DisplayVersion" => "version", "Publisher" => "publisher", "InstallDate" => "installdate", }.freeze collect_data(:linux) do packages Mash.new case platform_family when "debian" format = '${Package}\t${Version}\t${Architecture}\n' so = shell_out("dpkg-query -W -f='#{format}'") pkgs = so.stdout.lines pkgs.each do |pkg| name, version, arch = pkg.split packages[name] = { "version" => version, "arch" => arch } end when "rhel", "fedora", "suse", "pld", "amazon" format = '%{NAME}\t%|EPOCH?{%{EPOCH}}:{0}|\t%{VERSION}\t%{RELEASE}\t%{INSTALLTIME}\t%{ARCH}\n' so = shell_out("rpm -qa --qf '#{format}'") pkgs = so.stdout.lines pkgs.each do |pkg| name, epoch, version, release, installdate, arch = pkg.split if packages[name] # We have more than one package with this exact name! # Create an "versions" array for tracking all versions of packages with this name. # The top-level package information will be the first one returned by rpm -qa, # all versions go in this list, with the same information they'd normally have. if packages[name]["versions"].nil? # add the data of the first package to the list, so that all versions are in the list. packages[name]["versions"] = [] packages[name]["versions"] << Mash.new({ "epoch" => packages[name]["epoch"], "version" => packages[name]["version"], "release" => packages[name]["release"], "installdate" => packages[name]["installdate"], "arch" => packages[name]["arch"] }) end packages[name]["versions"] << Mash.new({ "epoch" => epoch, "version" => version, "release" => release, "installdate" => installdate, "arch" => arch }) # Add this package version to the list # When this was originally written, it didn't account for multiple versions of the same package # so it just kept clobbering the package data if it encountered multiple versions # of the same package. As a result, the last duplicate returned by rpm -qa was what was present; # here we clobber that data for compatibility. Note that we can't overwrite the entire hash # without losing the versions array. packages[name]["epoch"] = epoch packages[name]["version"] = version packages[name]["release"] = release packages[name]["installdate"] = installdate packages[name]["arch"] = arch else packages[name] = { "epoch" => epoch, "version" => version, "release" => release, "installdate" => installdate, "arch" => arch } end end when "arch" require "date" unless defined?(DateTime) # Set LANG=C to force an easy to parse date format so = shell_out("LANG=C pacman -Qi") so.stdout.split("\n\n").each do |record| pacman_info = {} record.lines.each do |line| if line =~ /\A(.*?)\s+:\s(.*)\z/m key, value = Regexp.last_match[1..2] key = key.strip.downcase.gsub(/\s+/, "") pacman_info[key] = value.strip end end name = pacman_info["name"] installdate = DateTime.strptime(pacman_info["installdate"], "%Ec").strftime("%s") packages[name] = { "version" => pacman_info["version"], "installdate" => installdate, "arch" => pacman_info["architecture"], } end end end def collect_programs_from_registry_key(repo, key_path) # from http://msdn.microsoft.com/en-us/library/windows/desktop/aa384129(v=vs.85).aspx if ::RbConfig::CONFIG["target_cpu"] == "i386" reg_type = Win32::Registry::KEY_READ | 0x100 elsif ::RbConfig::CONFIG["target_cpu"] == "x86_64" reg_type = Win32::Registry::KEY_READ | 0x200 else reg_type = Win32::Registry::KEY_READ end repo.open(key_path, reg_type) do |reg| reg.each_key do |key, _wtime| pkg = reg.open(key) name = pkg["DisplayName"] rescue nil next if name.nil? package = packages[name] = Mash.new WINDOWS_ATTRIBUTE_ALIASES.each do |registry_attr, package_attr| value = pkg[registry_attr] rescue nil package[package_attr] = value unless value.nil? end end end end collect_data(:windows) do require "win32/registry" unless defined?(Win32::Registry) packages Mash.new collect_programs_from_registry_key(Win32::Registry::HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Uninstall') collect_programs_from_registry_key(Win32::Registry::HKEY_CURRENT_USER, 'Software\Microsoft\Windows\CurrentVersion\Uninstall') collect_programs_from_registry_key(Win32::Registry::HKEY_LOCAL_MACHINE, 'Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall') # on 64 bit systems, 32 bit programs are stored here end collect_data(:aix) do packages Mash.new so = shell_out("lslpp -L -q -c") pkgs = so.stdout.lines # Output format is # Package Name:Fileset:Level # On aix, filesets are packages and levels are versions pkgs.each do |pkg| name, fileset, version, _, _, _, pkg_type = pkg.split(":") if pkg_type == "R" # RPM packages[name] = { "version" => version } else # LPP packages[fileset] = { "version" => version } end end end collect_data(:freebsd) do packages Mash.new so = shell_out('pkg query -a "%n %v"') # Output format is # name version so.stdout.lines do |pkg| name, version = pkg.split packages[name] = { "version" => version } end end def collect_ips_packages so = shell_out("pkg list -H") # Output format is # NAME (PUBLISHER) VERSION IFO so.stdout.lines.each do |pkg| tokens = pkg.split if tokens.length == 3 # No publisher info name, version, = tokens else name, publisher, version, = tokens publisher = publisher[1..-2] end packages[name] = { "version" => version } packages[name]["publisher"] = publisher if publisher end end def collect_sysv_packages so = shell_out("pkginfo -l") # Each package info is separated by a blank line chunked_lines = so.stdout.lines.map(&:strip).chunk do |line| !line.empty? || nil end chunked_lines.each do |_, lines| # rubocop: disable Style/HashEachMethods package = {} lines.each do |line| key, value = line.split(":", 2) package[key.strip.downcase] = value.strip unless value.nil? end # pkginst is the installed package name packages[package["pkginst"]] = package.tap do |p| p.delete("pkginst") end end end collect_data(:solaris2) do packages Mash.new collect_ips_packages collect_sysv_packages end def collect_system_profiler_apps require "plist" sp_std = shell_out("system_profiler SPApplicationsDataType -xml") results = Plist.parse_xml(sp_std.stdout) sw_array = results[0]["_items"] sw_array.each do |pkg| packages[pkg["_name"]] = { "version" => pkg["version"], "lastmodified" => pkg["lastModified"], "source" => pkg["obtained_from"], } end end collect_data(:darwin) do packages Mash.new collect_system_profiler_apps end end ohai-16.13.0/lib/ohai/plugins/aix/0000755000175100017510000000000014034105661015560 5ustar pravipraviohai-16.13.0/lib/ohai/plugins/aix/network.rb0000644000175100017510000001254314034105661017603 0ustar pravipravi# frozen_string_literal: true # # Author:: Kaustubh Deorukhkar () # Author:: Prabhu Das () # Author:: Isa Farnik () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Network) do require_relative "../../mixin/network_helper" provides "network", "network/interfaces", "counters/network", "macaddress" include Ohai::Mixin::NetworkHelper collect_data(:aix) do require "ipaddr" unless defined?(IPAddr) # Loads following information. # :default_interface, :default_gateway - route -n get 0 # :interfaces # => routes(netstat -nr | grep en0) # => addresses (ifconfig en0 or lsattr -El en0), macaddress (entstat -d en0 = Hardware Address: be:42:80:00:b0:05) # => flags (ifconfig en0) # => state up/down (ifconfig/lsattr) # => arp (arp -an) ifaces = Mash.new network Mash.new unless network # We unfortunately have to do things a bit different here, if ohai is running # within a WPAR. For instance, the WPAR isn't aware of some of its own networking # minutia such as default gateway/route. lpars return 0 here. wpars return > 0 unless shell_out("uname -W").stdout.to_i > 0 # :default_interface, :default_gateway - route -n get 0 default_line = shell_out("netstat -rn") .stdout .each_line .detect { |l| l.start_with?("default") } .split network[:default_gateway] = default_line[1] network[:default_interface] = default_line[5] end # Splits the ifconfig output into arrays of interface strings shell_out("ifconfig -a").stdout.split(/\n(?=\w)/).each do |int_lines| int_name, int_data = int_lines.split(":", 2) ifaces[int_name] = Mash.new ifaces[int_name][:addresses] ||= Mash.new ifaces[int_name][:state] = (int_data.include?("/ ifaces[int_name][:flags] = $1.split(",") ifaces[int_name][:metric] = $1 if line =~ /metric\s(\S+)/ else # We have key value pairs. if line =~ %r{inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(/(\d{1,2}))?} tmp_addr = $1 tmp_prefix = $3 if tmp_prefix.nil? netmask = hex_to_dec_netmask($1) if line =~ /netmask\s0x(\S+)\s/ unless netmask tmp_prefix ||= "32" netmask = IPAddr.new("255.255.255.255").mask(tmp_prefix.to_i).to_s end else netmask = IPAddr.new("255.255.255.255").mask(tmp_prefix.to_i).to_s end ifaces[int_name][:addresses][tmp_addr] = { "family" => "inet", "prefixlen" => tmp_prefix } ifaces[int_name][:addresses][tmp_addr][:netmask] = netmask if line =~ /broadcast\s(\S+)\s/ ifaces[int_name][:addresses][tmp_addr][:broadcast] = $1 end elsif line =~ %r{inet6 ([a-f0-9\:]+)%?(\d*)/?(\d*)?} # TODO: do we have more properties on inet6 in aix? broadcast ifaces[int_name][:addresses] ||= Mash.new ifaces[int_name][:addresses][$1] = { "family" => "inet6", "zone_index" => $2, "prefixlen" => $3 } else # add all key value data into the interface mash # for example "tcp_sendspace 131072 tcp_recvspace 131072 rfc1323 1" # has keys tcp_sendspace, tcp_recvspace, and rfc1323 line.split.each_slice(2) do |key, value| ifaces[int_name][key] = value end end end end # Query macaddress shell_out("entstat -d #{int_name}").stdout =~ /Hardware Address: (\S+)/ if $1 ifaces[int_name][:addresses][$1.upcase] = { "family" => "lladdr" } macaddress $1.upcase unless shell_out("uname -W").stdout.to_i > 0 end end # ifconfig stdout # Query routes information %w{inet inet6}.each do |family| shell_out("netstat -nrf #{family}").stdout.each_line do |line| if line =~ /(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\S+)/ interface = $6 ifaces[interface][:routes] ||= [] ifaces[interface][:routes] << Mash.new( destination: $1, family: family, via: $2, flags: $3) end end end # List the arp entries in system. count = 0 network[:arp] ||= Mash.new shell_out("arp -an").stdout.each_line do |line| if line =~ /\s*(\S+) \((\S+)\) at ([a-fA-F0-9\:]+) \[(\w+)\] stored in bucket/ network[:arp][count] ||= Mash.new network[:arp][count][:remote_host] = $1 network[:arp][count][:remote_ip] = $2 network[:arp][count][:remote_mac] = $3.downcase count += 1 end end network["interfaces"] = ifaces end end ohai-16.13.0/lib/ohai/plugins/aix/memory.rb0000644000175100017510000000242614034105661017421 0ustar pravipravi# frozen_string_literal: true # # Author:: Joshua Timberman # Author:: Isa Farnik () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Memory) do provides "memory" collect_data(:aix) do memory Mash.new memory[:swap] = Mash.new meminfo = shell_out("svmon -G -O unit=KB,summary=longreal | grep '[0-9]'").stdout total_in_mb, _u, free_in_mb = meminfo.split memory[:total] = "#{total_in_mb.to_i}kB" memory[:free] = "#{free_in_mb.to_i}kB" swap_info = shell_out("swap -s").stdout.split # returns swap info in 4K blocks memory[:swap]["total"] = "#{swap_info[2].to_i * 4}kB" memory[:swap]["free"] = "#{swap_info[10].to_i * 4}kB" end end ohai-16.13.0/lib/ohai/plugins/aix/virtualization.rb0000644000175100017510000001204614034105661021174 0ustar pravipravi# # Author:: Julian C. Dunn () # Author:: Isa Farnik () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Virtualization) do provides "virtualization", "virtualization/wpars" collect_data(:aix) do virtualization Mash.new lpar_no, lpar_name = shell_out("uname -L").stdout.split(nil, 2) unless lpar_no.to_i == -1 || (lpar_no.to_i == 1 && lpar_name == "NULL") virtualization[:lpar_no] = lpar_no virtualization[:lpar_name] = lpar_name end wpar_no = shell_out("uname -W").stdout.strip if wpar_no.to_i > 0 virtualization[:wpar_no] = wpar_no else # the below parses the output of lswpar in the long format so = shell_out("lswpar -L").stdout.scan(/={65}.*?(?:EXPORTED\n\n)+/m) wpars = Mash.new so.each do |wpar| wpar_heading = wpar.lines[1].split wpar_name = wpar_heading[0] wpars[wpar_name] = Mash.new wpars[wpar_name][:state] = wpar_heading[2].downcase wpar.scan(/^[A-Z]{4,}.*?[A-Z\:0-9]$.*?\n\n/m).each do |section| # retrieve title of section title = section.lines.first[0..-2].downcase wpars[wpar_name][title] = Mash.new # discard trailing section newline+title # and save as array sections = section.lines[1..-2] sections.each do |line| case title when "network" next if /^Interface|^---/.match?(line) splat = line.strip.split key = splat[0].downcase value = { "address" => splat[1], "netmask" => splat[2], "broadcast" => splat[3], } wpars[wpar_name][title][key] = value when "user-specified routes" next if /^Type|^---/.match?(line) splat = line.strip.split key = splat[2].downcase value = { "destination" => splat[0], "gateway" => splat[1], } wpars[wpar_name][title][key] = value when "file systems" next if /^MountPoint|^---/.match?(line) splat = line.strip.split key = splat[1].downcase value = { "mountpoint" => splat[0], "device" => splat[1], "vfs" => splat[2], "options" => splat[3].split(","), } wpars[wpar_name][title][key] = value when "security settings" privileges ||= "" wpars[wpar_name][title]["Privileges"] ||= [] if /^Privileges/.match?(line) privileges << line.split(":")[1].strip else privileges << line.strip end wpars[wpar_name][title]["Privileges"] += privileges.split(",") when "device exports" next if /^Name|^---/.match?(line) splat = line.strip.split key = splat[0].downcase value = { "type" => splat[1], "status" => splat[2], } wpars[wpar_name][title][key] = value else # key-value pairs are handled here # such as GENERAL and RESOURCE- # CONTROL splat = line.strip.split(":") key = splat[0].downcase value = splat[1..-1].join(", ").strip value = value.empty? ? nil : value case value when "yes" value = true when "no" value = false end wpars[wpar_name][title][key] = value end end end top_level = [ "general.directory", "general.hostname", "general.private /usr", "general.type", "general.uuid", "resource controls.active", "network.en0.address", ] top_level.each do |attribute| evalstr = "wpars['#{wpar_name}']" breadcrumb = attribute.split(".") breadcrumb.each do |node| evalstr << "[\'#{node}\']" end wpars[wpar_name][breadcrumb[-1]] = eval evalstr # rubocop: disable Security/Eval end end virtualization[:wpars] = wpars unless wpars.empty? end end end ohai-16.13.0/lib/ohai/plugins/aix/uptime.rb0000644000175100017510000000431214034105661017410 0ustar pravipravi# frozen_string_literal: true # # Author:: Kurt Yoder () # Author:: Isa Farnik () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Uptime) do provides "uptime", "uptime_seconds" collect_data(:aix) do require "date" unless defined?(DateTime) # below we're going to assume that PID 1 is init (this is true 99.99999% of the time) # output will look like this # 1148-20:54:50 # This reads as 1148 days, 20 hours, 54 minutes, 50 seconds since the process was started (elapsed) # who -b does not return the YEAR, so we need something more concrete so = shell_out("LC_ALL=POSIX ps -o etime= -p 1").stdout.strip # Here we'll check our shell_out for a dash, which indicates there is a # of days involved # We'll chunk off the days, hours (where applicable), minutes, seconds into separate vars # We also need to do this because ps -o etime= will not display days if the machine has been up for less than 24 hours # If the machine has been up for less than one hour, the shell_out will not output hours hence our else # see here: https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.cmds4/ps.htm#ps__row-d3e109655 d = nil h = nil case so when /^\d+-\d/ (d, h, m, s) = so.split(/[-:]/) when /^\d+:\d+:\d/ (h, m, s) = so.split(":") else (m, s) = so.split(":") end elapsed_seconds = ((d.to_i * 86400) + (h.to_i * 3600) + (m.to_i * 60) + s.to_i) # uptime seconds below will return the elapsed time since boot uptime_seconds elapsed_seconds uptime seconds_to_human(elapsed_seconds) end end ohai-16.13.0/lib/ohai/plugins/aix/platform.rb0000644000175100017510000000175514034105661017741 0ustar pravipravi# frozen_string_literal: true # # Author:: Joshua Timberman # Author:: Isa Farnik () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Platform) do provides "platform", "platform_version", "platform_family" depends "kernel" collect_data(:aix) do platform "aix" platform_family "aix" platform_version [kernel[:version], kernel[:release]].join(".") end end ohai-16.13.0/lib/ohai/plugins/aix/kernel.rb0000644000175100017510000000344414034105661017372 0ustar pravipravi# frozen_string_literal: true # # Author:: Joshua Timberman # Author:: Isa Farnik () # Copyright:: Copyright (c) Chef Software 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. # Ohai.plugin(:Kernel) do provides "kernel", "kernel/modules" collect_data(:aix) do kernel Mash.new uname_so = shell_out("uname -rvp").stdout.split kernel[:name] = "aix" # this is here for historical reasons, but it's always aix kernel[:release] = uname_so[0] kernel[:version] = uname_so[1] kernel[:machine] = uname_so[2] kernel[:bits] = shell_out("getconf KERNEL_BITMODE").stdout.strip modules = Mash.new so = shell_out("genkex -d") # Text address Size Data address Size File # # f1000000c0338000 77000 f1000000c0390000 1ec8c /usr/lib/drivers/cluster # 6390000 20000 63a0000 ba8 /usr/lib/drivers/if_en # f1000000c0318000 20000 f1000000c0320000 17138 /usr/lib/drivers/random so.stdout.lines do |line| if line =~ %r{\s*([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+([a-zA-Z0-9/\._]+)} modules[$5] = { text: { address: $1, size: $2 }, data: { address: $3, size: $4 } } end end kernel[:modules] = modules end end ohai-16.13.0/lib/ohai/log.rb0000644000175100017510000000216614034105661014431 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Copyright:: Copyright (c) Chef Software 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 "mixlib/log" unless defined?(Mixlib::Log) module Ohai # the Ohai Logger which is just Mixlib::Log defaulting to STDERR and :info level # unless otherwise configured via CLI or config class Log extend Mixlib::Log # this class loading initialization is so that we don't lose early logger # messages when run from the CLI? init(STDERR) level = :info # rubocop:disable Lint/UselessAssignment end end ohai-16.13.0/lib/ohai/dsl/0000755000175100017510000000000014034105661014100 5ustar pravipraviohai-16.13.0/lib/ohai/dsl/plugin.rb0000644000175100017510000001360514034105661015730 0ustar pravipravi# frozen_string_literal: true # # Author:: Adam Jacob () # Author:: Claire McQuin () # Copyright:: Copyright (c) Chef Software 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_relative "../mixin/os" require_relative "../mixin/shell_out" require_relative "../mixin/seconds_to_human" require_relative "../mixin/which" require_relative "../mixin/train_helpers" require_relative "../hints" module Ohai # For plugin namespacing module NamedPlugin # Is the plugin a Symbol starting with a capital letter that has no underscores # # @param name [String] the plugin name # @return [Boolean] def self.valid_name?(name) name.is_a?(Symbol) && name.to_s.match(/^[^A-Z]|_/).nil? end # @return [Boolean] def self.strict_const_defined?(const) const_defined?(const, false) end end # @param name [String] def self.plugin(name, &block) raise Ohai::Exceptions::InvalidPluginName, "#{name} is not a valid plugin name. A valid plugin name is a symbol which begins with a capital letter and contains no underscores" unless NamedPlugin.valid_name?(name) plugin = nil # avoid already initialized constant warnings if already defined if NamedPlugin.strict_const_defined?(name) plugin = NamedPlugin.const_get(name) plugin.class_eval(&block) else klass = Class.new(DSL::Plugin::VersionVII, &block) plugin = NamedPlugin.const_set(name, klass) end plugin end # Cross platform /dev/null to support testability # # @return [String] def self.dev_null if RUBY_PLATFORM.match?(/mswin|mingw|windows/) "NUL" else "/dev/null" end end # Extracted abs_path to support testability: # This method gets overridden at test time, to force the shell to check # ohai/spec/unit/path/original/absolute/path/to/exe def self.abs_path( abs_path ) abs_path end module DSL class Plugin include Ohai::Mixin::OS include Ohai::Mixin::ShellOut include Ohai::Mixin::SecondsToHuman include Ohai::Mixin::Which include Ohai::Mixin::TrainHelpers attr_reader :data attr_reader :failed attr_reader :logger attr_accessor :transport_connection def initialize(data, logger) @data = data @logger = logger.with_child({ subsystem: "plugin", plugin: name }) @has_run = false @failed = false end def target_mode? !!@transport_connection end def run @has_run = true if Ohai.config[:disabled_plugins].include?(name) logger.trace("Skipping disabled plugin #{name}") else run_plugin end end def has_run? @has_run end def reset! @has_run = false end def [](key) @data[key] end def []=(key, value) @data[key] = value end def each(&block) @data.each do |key, value| yield(key, value) end end def has_key?(name) @data.key?(name) end def attribute?(name, *keys) !safe_get_attribute(name, *keys).nil? end def set(name, *value) set_attribute(name, *value) end def from(cmd) _status, stdout, _stderr = run_command(command: cmd) return "" if stdout.nil? || stdout.empty? stdout.strip end # Set the value equal to the stdout of the command, plus # run through a regex - the first piece of match data is\ # the value. def from_with_regex(cmd, *regex_list) regex_list.flatten.each do |regex| _status, stdout, _stderr = run_command(command: cmd) return "" if stdout.nil? || stdout.empty? stdout.chomp!.strip md = stdout.match(regex) return md[1] end end def set_attribute(name, *attrs, value) # Initialize the path in the @data Mash with new Mashes, if needed. # Will raise a TypeError if we hit a subattribute that is not a # Hash, Mash, or Array. keys = [name] + attrs attribute = keys[0..-2].inject(@data) do |atts, key| atts[key] ||= Mash.new atts[key] end # Set the subattribute to the value. attr_name = attrs.empty? ? name : attrs[-1] attribute[attr_name] = value @data[name] end def get_attribute(name, *keys) safe_get_attribute(name, *keys) end def hint?(name) Ohai::Hints.hint?(name) end # emulates the old plugin loading behavior def safe_run run rescue Ohai::Exceptions::Error => e @failed = true raise e rescue => e @failed = true logger.trace("Plugin #{name} threw #{e.inspect}") e.backtrace.each { |line| logger.trace( line ) } end def method_missing(name, *args) return get_attribute(name) if args.length == 0 set_attribute(name, *args) end private def safe_get_attribute(*keys) keys.inject(@data) do |attrs, key| unless attrs.nil? || attrs.is_a?(Array) || attrs.is_a?(Hash) raise TypeError, "Expected Hash but got #{attrs.class}." end attrs[key] end rescue NoMethodError # NoMethodError occurs when trying to access a key on nil nil end end end end ohai-16.13.0/lib/ohai/dsl/plugin/0000755000175100017510000000000014034105661015376 5ustar pravipraviohai-16.13.0/lib/ohai/dsl/plugin/versionvii.rb0000644000175100017510000001544114034105661020125 0ustar pravipravi# frozen_string_literal: true # # Author:: Serdar Sutay () # Copyright:: Copyright (c) Chef Software 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. # module Ohai module DSL class Plugin # The class for the "Version 7" plugin format we introduced in Ohai 7. This is the 2nd # generation of Ohai plugin and the previous generation (V6) was removed in Ohai 14 class VersionVII < Plugin attr_reader :version attr_reader :source def initialize(data, logger) super(data, logger) @source = self.class.sources @version = :version7 end # the plugin name we use through Ohai (Foo) vs. the class name (Ohai::NamedPlugin::Foo) # # @return [String] def name self.class.name.split("Ohai::NamedPlugin::")[1].to_sym end # return that we're a v7 plugin # # @return [Symbol] def self.version :version7 end # The source of the plugin on disk. This is an array since a plugin may exist for multiple # oses and this would include each of those os specific file paths # # @return [Array] def self.sources @source_list ||= [] end def self.provides_attrs @provides_attrs ||= [] end def self.depends_attrs @depends_attrs ||= [] end # A block per os for actually performing data collection constructed # by the collect_data method # # @return [Mash] def self.data_collector @data_collector ||= Mash.new end # set the attributes provided by the plugin # # @param attrs [Array] def self.provides(*attrs) attrs.each do |attr| provides_attrs << attr unless provides_attrs.include?(attr) end end # set the attributes depended on by the plugin # # @param attrs [Array] def self.depends(*attrs) attrs.each do |attr| depends_attrs << attr unless depends_attrs.include?(attr) end end # set the plugin optional state # # @param opt [Boolean] def self.optional(opt = true) @optional = opt end # check if the plugin is optional # # @return [Boolean] def self.optional? !!@optional end # define data collection methodology per os # # @param os [Array] the list of oses to collect data for # @param block [block] the actual code to collect data for the specified os # def self.collect_data(*os_list, &block) os_list = [ :default ] if os_list.empty? os_list.flatten.each do |os| Ohai::Log.warn("collect_data already defined on os '#{os}' for #{self}, last plugin seen will be used") if data_collector.key?(os) data_collector[os] = block end end # @return [Array] def dependencies self.class.depends_attrs end def run_plugin collector = self.class.data_collector os = collect_os # :default - means any remote or local unix or windows host # :target - means any remote API which is not unix/windows or otherwise rubyable (cisco switches, IPMI console, HTTP API, etc) # # Do not be confused by the fact that collectors tagged :target do not run against e.g. target-mode ubuntu boxes, that is not # what :target is intended for. Also, do not be confused by the fact that collectors tagged :default do not run by default against # pure-target mode targets like switches. That is all intended behavior, the names are problematic. The :default nomenclature was # invented 10 years before target mode and we are stuck with it. # if collector.key?(os) instance_eval(&collector[os]) elsif collector.key?(:default) && !nonruby_target? instance_eval(&collector[:default]) elsif collector.key?(:target) && nonruby_target? instance_eval(&collector[:target]) else logger.trace("Plugin #{name}: No data to collect. Skipping...") end end def optional? self.class.optional? end def provides(*paths) logger.warn("[UNSUPPORTED OPERATION] \'provides\' is no longer supported in a \'collect_data\' context. Please specify \'provides\' before collecting plugin data. Ignoring command \'provides #{paths.join(", ")}") end def require_plugin(*args) logger.warn("[UNSUPPORTED OPERATION] \'require_plugin\' is no longer supported. Please use \'depends\' instead.\nIgnoring plugin(s) #{args.join(", ")}") end def configuration(option, *options) return nil if plugin_config.nil? || !plugin_config.key?(option) value = plugin_config[option] options.each do |opt| return nil unless value.key?(opt) value = value[opt] end value end private def plugin_config @plugin_config ||= fetch_plugin_config end def fetch_plugin_config # DMI => ["DMI"] # Memory => ["", "Memory"] # NetworkListeners => ["", "Network", "", "Listeners"] # SSHHostKey => ["SSH", "Host", "", "Key"] parts = name.to_s.split(/([A-Z][a-z]+)/) # ["DMI"] => ["DMI"] # ["", "Memory"] => ["Memory"] # ["", "Network", "", "Listeners"] => ["Network", "Listeners"] # ["SSH", "Host", "", "Key"] => ["SSH", "Host", "Key"] parts.delete_if(&:empty?) # ["DMI"] => :dmi # ["Memory"] => :memory # ["Network", "Listeners"] => :network_listeners # ["SSH", "Host", "Key"] => :ssh_host_key snake_case_name = parts.map(&:downcase).join("_").to_sym # Plugin names in config hashes are auto-vivified, so we check with # key? to avoid falsely instantiating a configuration hash. if Ohai.config[:plugin].key?(snake_case_name) Ohai.config[:plugin][snake_case_name] end end end end end end ohai-16.13.0/Gemfile0000644000175100017510000000154414034105661013127 0ustar pravipravi# frozen_string_literal: true source "https://rubygems.org" gemspec # pull these gems from master of chef/chef so that we're testing against what we will release gem "chef-config", git: "https://github.com/chef/chef", branch: "chef-16", glob: "chef-config/chef-config.gemspec" gem "chef-utils", git: "https://github.com/chef/chef", branch: "chef-16", glob: "chef-utils/chef-utils.gemspec" # NOTE: do not submit PRs to add pry as a dep, add to your Gemfile.local group :development do gem "chefstyle", "1.6.2" gem "ipaddr_extensions" gem "rake", ">= 10.1.0" gem "rspec-collection_matchers", "~> 1.0" gem "rspec-core", "~> 3.0" gem "rspec-expectations", "~> 3.0" gem "rspec-mocks", "~> 3.0" gem "rubocop-performance", "1.9.2" gem "rubocop-rspec" end group :debug do gem "pry" gem "pry-byebug" gem "pry-stack_explorer" gem "rb-readline" end ohai-16.13.0/LICENSE0000644000175100017510000002514214034105661012641 0ustar pravipravi Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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.