# HG changeset patch # User Mahlon E. Smith # Date 1472077688 25200 # Node ID d99e1dffbc72d3902b75d1ac383cc7cf73abcd6f Initial commit. diff -r 000000000000 -r d99e1dffbc72 .gems --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.gems Wed Aug 24 15:28:08 2016 -0700 @@ -0,0 +1,1 @@ + diff -r 000000000000 -r d99e1dffbc72 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Wed Aug 24 15:28:08 2016 -0700 @@ -0,0 +1,2 @@ +docs/* +pkg/* diff -r 000000000000 -r d99e1dffbc72 .rvmrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.rvmrc Wed Aug 24 15:28:08 2016 -0700 @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +environment_id="ruby-2.3@arborist-fping" + +if [[ -d "${rvm_path:-$HOME/.rvm}/environments" + && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]] +then + \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id" + for __hook in "${rvm_path:-$HOME/.rvm}/hooks/after_use"* + do + if [[ -f "${__hook}" && -x "${__hook}" && -s "${__hook}" ]] + then \. "${__hook}" || true + fi + done + unset __hook + if (( ${rvm_use_flag:=1} >= 2 )) # display only when forced + then + if [[ $- == *i* ]] # check for interactive shells + then printf "%b" "Using: $(tput setaf 2 2>/dev/null)$GEM_HOME$(tput sgr0 2>/dev/null)\n" # show the user the ruby and gemset they are using in green + else printf "%b" "Using: $GEM_HOME\n" # don't use colors in non-interactive shells + fi + fi +else + # If the environment file has not yet been created, use the RVM CLI to select. + rvm --create "$environment_id" || { + echo "Failed to create RVM environment '${environment_id}'." + return 1 + } +fi diff -r 000000000000 -r d99e1dffbc72 README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.md Wed Aug 24 15:28:08 2016 -0700 @@ -0,0 +1,96 @@ +# Arborist-fping + +home +: http://bitbucket.org/mahlon/Arborist-fping + +code +: http://code.martini.nu/Arborist-fping + +fping +: http://fping.org/ + + +## Description + +Arborist is a monitoring toolkit that follows the UNIX philosophy +of small parts and loose coupling for stability, reliability, and +customizability. + +This adds fping sweeping support to Arborist monitoring, which is an +efficient means to check the ICMP reachability of many, many hosts +simultaneously. + +It requires the fping binary to be installed in your path. Use your +package manager of choice. + + +## Prerequisites + +* Ruby 2.2 or better + + +## Installation + + $ gem install arborist-fping + + +## Usage + +In this example, we're using ICMP reachability as the method to +determine if a host node is available/present on network. + + Arborist::Host( 'example' ) do + description "Example host" + address '10.6.0.169' + end + + +From a monitor file, require this library, and exec() to fping. We'll +record RTT per node in this example with the -e flag, and lower the +timeout-per-host: + + require 'arborist/monitor/fping' + + Arborist::Monitor 'ping check' do + every 10.seconds + match type: 'host' + include_down true + use :addresses + exec 'fping', '-e', '-t', '150' + exec_callbacks( Arborist::Monitor::FPing ) + end + +That's it. + + +## License + +Copyright (c) 2016, Michael Granger and Mahlon E. Smith +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the author/s, nor the names of the project's + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + diff -r 000000000000 -r d99e1dffbc72 Rakefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Rakefile Wed Aug 24 15:28:08 2016 -0700 @@ -0,0 +1,112 @@ +#!/usr/bin/env rake +# vim: set nosta noet ts=4 sw=4: + +require 'pathname' + +PROJECT = 'fping' +BASEDIR = Pathname.new( __FILE__ ).expand_path.dirname.relative_path_from( Pathname.getwd ) +LIBDIR = BASEDIR + 'lib' + +if Rake.application.options.trace + $trace = true + $stderr.puts '$trace is enabled' +end + +# parse the current library version +$version = ( LIBDIR + 'arborist' + 'monitor' + "#{PROJECT}.rb" ).read.split(/\n/). + select{|line| line =~ /VERSION =/}.first.match(/([\d|.]+)/)[1] + +task :default => [ :spec, :docs, :package ] + + +######################################################################## +### P A C K A G I N G +######################################################################## + +require 'rubygems' +require 'rubygems/package_task' +spec = Gem::Specification.new do |s| + s.email = 'mahlon@martini.nu' + s.homepage = 'http://bitbucket.org/mahlon/Arborist-fping' + s.authors = [ 'Mahlon E. Smith ', 'Michael Granger ' ] + s.platform = Gem::Platform::RUBY + s.summary = "Efficient ping strobing for Arborist" + s.name = 'arborist-' + PROJECT + s.version = $version + s.license = 'BSD-3-Clause' + s.has_rdoc = true + s.require_path = 'lib' + s.bindir = 'bin' + s.files = File.read( __FILE__ ).split( /^__END__/, 2 ).last.split + # s.executables = %w[] + s.description = <<-EOF + This library adds fping output parsing support to Arborist monitors. + EOF + s.required_ruby_version = '>= 2' + + s.add_dependency 'arborist', "~> 1.0" +end + +Gem::PackageTask.new( spec ) do |pkg| + pkg.need_zip = true + pkg.need_tar = true +end + + +######################################################################## +### D O C U M E N T A T I O N +######################################################################## + +begin + require 'rdoc/task' + + desc 'Generate rdoc documentation' + RDoc::Task.new do |rdoc| + rdoc.name = :docs + rdoc.rdoc_dir = 'docs' + rdoc.main = "README.rdoc" + rdoc.options = [ '-f', 'fivefish' ] + rdoc.rdoc_files = [ 'lib', *FileList['*.rdoc'] ] + end + + RDoc::Task.new do |rdoc| + rdoc.name = :doc_coverage + rdoc.options = [ '-C1' ] + end + +rescue LoadError + $stderr.puts "Omitting 'docs' tasks, rdoc doesn't seem to be installed." +end + + +######################################################################## +### T E S T I N G +######################################################################## + +begin + require 'rspec/core/rake_task' + task :test => :spec + + desc "Run specs" + RSpec::Core::RakeTask.new do |t| + t.pattern = "spec/**/*_spec.rb" + end + + desc "Build a coverage report" + task :coverage do + ENV[ 'COVERAGE' ] = "yep" + Rake::Task[ :spec ].invoke + end + +rescue LoadError + $stderr.puts "Omitting testing tasks, rspec doesn't seem to be installed." +end + + + +######################################################################## +### M A N I F E S T +######################################################################## +__END__ +lib/arborist/monitor/fping.rb + diff -r 000000000000 -r d99e1dffbc72 lib/arborist/monitor/fping.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/arborist/monitor/fping.rb Wed Aug 24 15:28:08 2016 -0700 @@ -0,0 +1,64 @@ +# -*- ruby -*- +# vim: set noet nosta sw=4 ts=4 : +# encoding: utf-8 +# +# This library parses fping output when provided a list of nodes to +# monitor. Require it from your monitor file(s), and call the Arborist +# exec() with this class -- that's it. +# +# require 'arborist/monitor/fping' +# +# Arborist::Monitor 'ping check' do +# every 20.seconds +# match type: 'host' +# include_down true +# use :addresses +# exec 'fping', '-e', '-t', '150' +# exec_callbacks( Arborist::Monitor::FPing ) +# end + + +require 'loggability' +require 'arborist/monitor' unless defined?( Arborist::Monitor ) + +# Parse Fping output for better batch ICMP checks. +# +module Arborist::Monitor::FPing + extend Loggability + log_to :arborist + + # The version of this library. + VERSION = '0.1.0' + + attr_accessor :identifiers + + def exec_arguments( nodes ) + self.log.debug "Building fping arguments for %d nodes" % [ nodes.size ] + self.identifiers = nodes.each_with_object({}) do |(identifier, props), hash| + next unless props.key?( 'addresses' ) + address = props[ 'addresses' ].first + hash[ address ] = identifier + end + + return {} if self.identifiers.empty? + return self.identifiers.keys + end + + def handle_results( pid, stdout, stderr ) + # 8.8.8.8 is alive (32.1 ms) + # 8.8.4.4 is alive (14.9 ms) + # 8.8.0.1 is unreachable + + return stdout.each_line.with_object({}) do |line, hash| + address, remainder = line.split( ' ', 2 ) + identifier = self.identifiers[ address ] or next + + if remainder =~ /is alive \((\d+\.\d+) ms\)/ + hash[ identifier ] = { rtt: Float( $1 ) } + else + hash[ identifier ] = { error: remainder.chomp } + end + end + end +end # Arborist::Monitor::FPing +