lib/omnibus/health_check.rb in omnibus-5.4.0 vs lib/omnibus/health_check.rb in omnibus-5.5.0
- old
+ new
@@ -12,19 +12,20 @@
# 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 'omnibus/sugarable'
+require "omnibus/sugarable"
begin
- require 'pedump'
+ require "pedump"
rescue LoadError
STDERR.puts "pedump not found - windows health checks disabled"
end
module Omnibus
class HealthCheck
+ include Instrumentation
include Logging
include Util
include Sugarable
WHITELIST_LIBS = [
@@ -155,11 +156,11 @@
/libkvm\.so/,
/libprocstat\.so/,
/libmd\.so/,
].freeze
- IGNORED_ENDINGS = %w(
+ IGNORED_ENDINGS = %w{
.[ch]
.e*rb
.gemspec
.gitignore
.h*h
@@ -189,18 +190,18 @@
Gemfile
LICENSE
README
Rakefile
VERSION
- ).freeze
+ }.freeze
- IGNORED_PATTERNS = %w(
+ IGNORED_PATTERNS = %w{
/share/doc/
/share/postgresql/
/share/terminfo/
/terminfo/
- ).freeze
+ }.freeze
class << self
# @see (HealthCheck#new)
def run!(project)
new(project).run!
@@ -233,157 +234,159 @@
#
# @return [true]
# if the healthchecks pass
#
def run!
- log.info(log_key) {"Running health on #{project.name}"}
- bad_libs = case Ohai['platform']
- when 'mac_os_x'
- health_check_otool
- when 'aix'
- health_check_aix
- when 'windows'
- # TODO: objdump -p will provided a very limited check of
- # explicit dependencies on windows. Most dependencies are
- # implicit and hence not detected.
- log.warn(log_key) { 'Skipping dependency health checks on Windows.' }
- {}
- else
- health_check_ldd
- end
+ measure("Health check time") do
+ log.info(log_key) { "Running health on #{project.name}" }
+ bad_libs = case Ohai["platform"]
+ when "mac_os_x"
+ health_check_otool
+ when "aix"
+ health_check_aix
+ when "windows"
+ # TODO: objdump -p will provided a very limited check of
+ # explicit dependencies on windows. Most dependencies are
+ # implicit and hence not detected.
+ log.warn(log_key) { "Skipping dependency health checks on Windows." }
+ {}
+ else
+ health_check_ldd
+ end
- unresolved = []
- unreliable = []
- detail = []
+ unresolved = []
+ unreliable = []
+ detail = []
- if bad_libs.keys.length > 0
- bad_libs.each do |name, lib_hash|
- lib_hash.each do |lib, linked_libs|
- linked_libs.each do |linked, count|
- if linked =~ /not found/
- unresolved << lib unless unresolved.include? lib
- else
- unreliable << linked unless unreliable.include? linked
+ if bad_libs.keys.length > 0
+ bad_libs.each do |name, lib_hash|
+ lib_hash.each do |lib, linked_libs|
+ linked_libs.each do |linked, count|
+ if linked =~ /not found/
+ unresolved << lib unless unresolved.include? lib
+ else
+ unreliable << linked unless unreliable.include? linked
+ end
+ detail << "#{name}|#{lib}|#{linked}|#{count}"
end
- detail << "#{name}|#{lib}|#{linked}|#{count}"
end
end
- end
- log.error(log_key) { 'Failed!' }
- bad_omnibus_libs, bad_omnibus_bins = bad_libs.keys.partition { |k| k.include? 'embedded/lib' }
+ log.error(log_key) { "Failed!" }
+ bad_omnibus_libs, bad_omnibus_bins = bad_libs.keys.partition { |k| k.include? "embedded/lib" }
- log.error(log_key) do
- out = "The following libraries have unsafe or unmet dependencies:\n"
+ log.error(log_key) do
+ out = "The following libraries have unsafe or unmet dependencies:\n"
- bad_omnibus_libs.each do |lib|
- out << " --> #{lib}\n"
+ bad_omnibus_libs.each do |lib|
+ out << " --> #{lib}\n"
+ end
+
+ out
end
- out
- end
+ log.error(log_key) do
+ out = "The following binaries have unsafe or unmet dependencies:\n"
- log.error(log_key) do
- out = "The following binaries have unsafe or unmet dependencies:\n"
+ bad_omnibus_bins.each do |bin|
+ out << " --> #{bin}\n"
+ end
- bad_omnibus_bins.each do |bin|
- out << " --> #{bin}\n"
+ out
end
- out
- end
+ if unresolved.length > 0
+ log.error(log_key) do
+ out = "The following requirements could not be resolved:\n"
- if unresolved.length > 0
- log.error(log_key) do
- out = "The following requirements could not be resolved:\n"
+ unresolved.each do |lib|
+ out << " --> #{lib}\n"
+ end
- unresolved.each do |lib|
- out << " --> #{lib}\n"
+ out
end
+ end
- out
+ if unreliable.length > 0
+ log.error(log_key) do
+ out = "The following libraries cannot be guaranteed to be on "
+ out << "target systems:\n"
+
+ unreliable.each do |lib|
+ out << " --> #{lib}\n"
+ end
+
+ out
+ end
end
- end
- if unreliable.length > 0
log.error(log_key) do
- out = "The following libraries cannot be guaranteed to be on "
- out << "target systems:\n"
+ out = "The precise failures were:\n"
- unreliable.each do |lib|
- out << " --> #{lib}\n"
+ detail.each do |line|
+ item, dependency, location, count = line.split("|")
+ reason = location =~ /not found/ ? "Unresolved dependency" : "Unsafe dependency"
+
+ out << " --> #{item}\n"
+ out << " DEPENDS ON: #{dependency}\n"
+ out << " COUNT: #{count}\n"
+ out << " PROVIDED BY: #{location}\n"
+ out << " FAILED BECAUSE: #{reason}\n"
end
out
end
- end
- log.error(log_key) do
- out = "The precise failures were:\n"
-
- detail.each do |line|
- item, dependency, location, count = line.split('|')
- reason = location =~ /not found/ ? 'Unresolved dependency' : 'Unsafe dependency'
-
- out << " --> #{item}\n"
- out << " DEPENDS ON: #{dependency}\n"
- out << " COUNT: #{count}\n"
- out << " PROVIDED BY: #{location}\n"
- out << " FAILED BECAUSE: #{reason}\n"
- end
-
- out
+ raise HealthCheckFailed
end
- raise HealthCheckFailed
- end
+ conflict_map = {}
- conflict_map = {}
+ conflict_map = relocation_check if relocation_checkable?
- conflict_map = relocation_check if relocation_checkable?
+ if conflict_map.keys.length > 0
+ log.warn(log_key) { "Multiple dlls with overlapping images detected" }
- if conflict_map.keys.length > 0
- log.warn(log_key) { 'Multiple dlls with overlapping images detected' }
+ conflict_map.each do |lib_name, data|
+ base = data[:base]
+ size = data[:size]
+ next_valid_base = data[:base] + data[:size]
- conflict_map.each do |lib_name, data|
- base = data[:base]
- size = data[:size]
- next_valid_base = data[:base] + data[:size]
+ log.warn(log_key) do
+ out = "Overlapping dll detected:\n"
+ out << " #{lib_name} :\n"
+ out << " IMAGE BASE: #{hex}\n" % base
+ out << " IMAGE SIZE: #{hex} (#{size} bytes)\n" % size
+ out << " NEXT VALID BASE: #{hex}\n" % next_valid_base
+ out << " CONFLICTS:\n"
- log.warn(log_key) do
- out = "Overlapping dll detected:\n"
- out << " #{lib_name} :\n"
- out << " IMAGE BASE: #{hex}\n" % base
- out << " IMAGE SIZE: #{hex} (#{size} bytes)\n" % size
- out << " NEXT VALID BASE: #{hex}\n" % next_valid_base
- out << " CONFLICTS:\n"
+ data[:conflicts].each do |conflict_name|
+ cbase = conflict_map[conflict_name][:base]
+ csize = conflict_map[conflict_name][:size]
+ out << " - #{conflict_name} #{hex} + #{hex}\n" % [cbase, csize]
+ end
- data[:conflicts].each do |conflict_name|
- cbase = conflict_map[conflict_name][:base]
- csize = conflict_map[conflict_name][:size]
- out << " - #{conflict_name} #{hex} + #{hex}\n" % [cbase, csize]
+ out
end
-
- out
end
+
+ # Don't raise an error yet. This is only bad for FIPS mode.
end
- # Don't raise an error yet. This is only bad for FIPS mode.
+ true
end
-
- true
end
# Ensure the method relocation_check is able to run
#
# @return [Boolean]
#
def relocation_checkable?
return false unless windows?
begin
- require 'pedump'
+ require "pedump"
true
rescue LoadError
false
end
end
@@ -401,11 +404,11 @@
embedded_bin = "#{project.install_dir}/embedded/bin"
Dir.glob("#{embedded_bin}/*.dll") do |lib_path|
log.debug(log_key) { "Analyzing dependencies for #{lib_path}" }
- File.open(lib_path, 'rb') do |f|
+ File.open(lib_path, "rb") do |f|
dump = PEdump.new(lib_path)
pe = dump.pe f
# Don't scan dlls for a different architecture.
next if windows_arch_i386? == pe.x64?
@@ -416,11 +419,11 @@
conflicts = []
# This can be done more smartly but O(n^2) is just fine for n = small
conflict_map.each do |candidate_name, details|
unless details[:base] >= base + size ||
- details[:base] + details[:size] <= base
+ details[:base] + details[:size] <= base
details[:conflicts] << lib_name
conflicts << candidate_name
end
end
@@ -492,18 +495,18 @@
bad_libs
end
#
# Run healthchecks against ldd.
- #
+ #
# @return [Hash<String, Hash<String, Hash<String, Int>>>]
# the bad libraries (library_name -> dependency_name -> satisfied_lib_path -> count)
#
def health_check_ldd
- regexp_ends = '.*(' + IGNORED_ENDINGS.map { |e| e.gsub(/\./, '\.') }.join('|') + ')$'
- regexp_patterns = IGNORED_PATTERNS.map { |e| '.*' + e.gsub(/\//, '\/') + '.*' }.join('|')
- regexp = regexp_ends + '|' + regexp_patterns
+ regexp_ends = ".*(" + IGNORED_ENDINGS.map { |e| e.gsub(/\./, '\.') }.join("|") + ")$"
+ regexp_patterns = IGNORED_PATTERNS.map { |e| ".*" + e.gsub(/\//, '\/') + ".*" }.join("|")
+ regexp = regexp_ends + "|" + regexp_patterns
current_library = nil
bad_libs = {}
read_shared_libs("find #{project.install_dir}/ -type f -regextype posix-extended ! -regex '#{regexp}' | xargs ldd") do |line|
@@ -590,21 +593,21 @@
# @return the modified bad_library hash
#
def check_for_bad_library(bad_libs, current_library, name, linked)
safe = nil
- whitelist_libs = case Ohai['platform']
- when 'arch'
+ whitelist_libs = case Ohai["platform"]
+ when "arch"
ARCH_WHITELIST_LIBS
- when 'mac_os_x'
+ when "mac_os_x"
MAC_WHITELIST_LIBS
- when 'solaris2'
+ when "solaris2"
SOLARIS_WHITELIST_LIBS
- when 'smartos'
+ when "smartos"
SMARTOS_WHITELIST_LIBS
- when 'freebsd'
+ when "freebsd"
FREEBSD_WHITELIST_LIBS
- when 'aix'
+ when "aix"
AIX_WHITELIST_LIBS
else
WHITELIST_LIBS
end