=head1 NAME

gdnsd-plugin-extmon - gdnsd plugin for monitoring via external commands

=head1 SYNOPSIS

Example plugin config:

  service_types => {
    wget_ssl_index => {
      plugin => "extmon",
      timeout => 15,
      interval => 30,
      cmd => ["/usr/bin/wget", "-T", "3", "-q", "-O", "/dev/null", "https://%%ITEM%%/index.html"]
    },
    svc_alwaysok => {
      plugin => "extmon",
      timeout => 1,
      direct => true,
      cmd => ["/bin/sh", "-c", "exit 0"]
    },
    svc_alwaysfail_via_timeout => {
      plugin => "extmon",
      timeout => 2,
      max_proc => 10,
      cmd => ["/bin/sh", "-c", "sleep 5"]
    }
  }

  # optional, if installed path confuses the daemon...
  plugins => {
    extmon => { helper_path => "@GDNSD_DEFPATH_LIBEXEC@/gdnsd_extmon_helper" }
  }

=head1 DESCRIPTION

B<gdnsd-plugin-extmon> allows you to configure external commands
to provide monitoring feedback to the dynamic address plugins.

=head1 CONFIGURATION - GLOBAL

These are plugin-global settings which are configured within
C<plugins =E<gt> { extmon =E<gt> { ... } }>.

=over 4

=item B<helper_path>

String pathname, optional.

Normally, this plugin will successfully locate its helper
binary F<gdnsd_extmon_helper> in the installation libexec
directory at F<@GDNSD_DEFPATH_LIBEXEC@/gdnsd_extmon_helper>.
If for some reason it can't do so, e.g. due to a relocated
installation, you can set an explicit full pathname to the
helper here.

=item B<helper_failure_action>

String, either C<stasis> or C<kill_daemon>.
Default is C<stasis>.

This configures the behavior of the plugin if the helper
process F<gdnsd_extmon_helper> unexpectedly dies, which prevents
the gathering of any further legitimate monitoring state updates.

Regardless of this setting, there will be at least one
syslog message indicating the failure.

If set to C<stasis>, all monitored states are left as-is with
no further updates.  The downside is that unless someone notices
the syslog message, this failure mode is hard to notice.

If set to C<kill_daemon>, the whole gdnsd daemon will fail fatally.

=back

=head1 CONFIGURATION - PER-SERVICE-TYPE

The universal, plugin-neutral service_type parameters all apply
in their usual sense: C<up_thresh>, C<ok_thresh>, C<down_thresh>,
C<interval>, C<plugin>, and C<timeout>.  See L<gdnsd.config(5)> for
basic information on these.  The following are specific to this
C<extmon> plugin:

=over 4

=item B<cmd>

Array of one or more strings, required.

This sets the command and arguments to execute for the monitoring check.
The array is passed directly to C<execv()> for execution (with re-use of
the first element as the pathname to execute).  If you need to use shell
facilities, start the argument list with e.g. C<"/bin/sh", "-c", ...>.

All argument strings are searched for the magic string C<%%ITEM%%> (which
can appear multiple times per argument).  Everywhere this magic string is
found, the IP address or CNAME text of the resource being monitored will
be substituted in its place.

The command must exit with an exit value of zero for success or non-zero
for failure.

=item B<direct>

Boolean, default false.

Normally extmon's results are processed by the same anti-flap state machine
used for traditional monitors like the HTTP and TCP monitoring plugins.  This
means the results are subject to the various thresholds (C<ok_thresh>, C<up_thresh>,
C<down_thresh>) and it may take some time for a new persistent state to actually
affect resolution.

If C<direct> is set to C<true>, the results of extmon's monitoring are applied
directly and immediately as the final state of the monitored resources after
every monitoring check.  If your command flaps back and forther between success
and failure on every run, so will the internal state and so will the resulting
changes in resolution.  Useful if extmon is actually gathering state from an
external complex monitoring environment that has already taken care of things
like anti-flap measures.

=item B<max_proc>

Integer, default 0 (unlimited).

The maximum number of concurrent processes to spawn.

This sets the limit on the number of concurrent commands that will be run.
If the limit is exceeded, excess commands are rescheduled for 0.1 seconds
later. After a few runs, the processes will be spread out enough to run
without running into the limit.

=back

=head1 EXECUTION ENVIRONMENT

The plugin launches a helper binary F<gdnsd_extmon_helper>
during daemon startup, and this helper does
the actual runtime command executions.  It manages the timeouts
and intervals and feeds results back to the plugin over a pipe.  This
communication is one-way at runtime (no daemon -> helper traffic)
for security reasons (to help ensure that a compromised daemon can't
easily leverage the helper to muck with the execution of the external
commands).  This separation also prevents a class of functional and
security bugs related to mixing runtime pthreads with routine forking
to exec the child processes.

The executed scripts will run with the same userid the daemon normally
drops privileges to.

The stdout, stdin, and stderr descriptors will usually be
set to F</dev/null>.  stdout and stderr may be open to the current
tty if the main daemon was started in foreground debugging mode
via C<-f start>.

=head1 SEE ALSO

L<gdnsd.config(5)>, L<gdnsd(8)>

The gdnsd manual.

=head1 COPYRIGHT AND LICENSE

Copyright (c) 2012 Brandon L Black <blblack@gmail.com>

This file is part of gdnsd.

gdnsd is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

gdnsd is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with gdnsd.  If not, see <http://www.gnu.org/licenses/>.

=cut
