Initial commit.
authorMahlon E. Smith <mahlon@martini.nu>
Wed, 24 Aug 2016 15:28:08 -0700
changeset 0 d99e1dffbc72
child 1 69f2ba4d4d93
Initial commit.
.gems
.hgignore
.rvmrc
README.md
Rakefile
lib/arborist/monitor/fping.rb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.gems	Wed Aug 24 15:28:08 2016 -0700
@@ -0,0 +1,1 @@
+
--- /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/*
--- /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
--- /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.
+
+
--- /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 <mahlon@martini.nu>', 'Michael Granger <ged@faeriemud.org>' ]
+	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
+
--- /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
+