unix/0000755000000000001440000000000012166524015010730 5ustar rootusersunix/FreeBSD/0000755000000000001440000000000012166524015012142 5ustar rootusersunix/FreeBSD/pandora_agent.conf0000644000000000000000000001273112166524015015430 0ustar rootroot# Base config file for Pandora FMS agents # Version 4.1, FreeBSD Version # Licensed under GPL license v2, # Copyright (c) 2003-2010 Artica Soluciones Tecnologicas # http://www.pandorafms.com # General Parameters # ================== server_ip localhost server_path /var/spool/pandora/data_in temporal /tmp logfile /var/log/pandora/pandora_agent.log #include /etc/pandora/pandora_agent_alt.conf #broker_agent name_agent # Interval in seconds, 300 by default interval 300 # Debug mode only generate XML, and stop after first execution, # and does not copy XML to server. debug 0 # By default, agent takes machine name #agent_name adama #Parent agent_name #parent_agent_name parent_name # Agent description #description Demo agent # Group assigned for this agent (descriptive, p.e: Servers) #group Servers # Autotime: Enforce to server to ignore timestamp coming from this # agent, used when agents has no timer or it's inestable. 1 to enable # this feature # autotime 1 # Timezone offset: Difference with the server timezone #timezone_offset 0 # Agent position paramters # Those parameters define the geographical position of the agent # latitude #latitude 0 # longitude #longitude 0 # altitude #altitude 0 #Position description #position_description Madrid, centro # By default agent try to take default encoding defined in host. # encoding UTF-8 # Listening TCP port for remote server. By default is 41121 (for tentacle) # if you want to use SSH use 22, and FTP uses 21. server_port 41121 # Transfer mode: tentacle, ftp, ssh or local transfer_mode tentacle # Server password (Tentacle or FTP). Leave empty for no password (default). # server_pwd mypassword # Set to yes/no to enable/disable OpenSSL support for Tentacle (disabled by default). # server_ssl no # Extra options for the Tentacle client (for example, server_opts "-v -r 5"). # server_opts # delayed_startup defines number of seconds before start execution # for first time when startup Pandora FMS Agent # delayed_startup 10 # Pandora nice defines priority of execution. Less priority means more intensive execution # A recommended value is 10. 0 priority means no Pandora CPU protection enabled (default) # pandora_nice 0 # Cron mode replace Pandora FMS own task schedule each XX interval seconds by the use # of old style cron. You should add to crontab Pandora FMS agent script to use this mode. # This is disabled by default, and is not recommended. Use Pandora FMS internal scheduler # is much more safe. # cron_mode # If set to 1 allows the agent to be configured via the web console (Only Enterprise version) # remote_config 1 # If set to 1 start Drone Agent's Proxy Mode # proxy_mode 1 # Max number of simmultaneus connection for proxy (by default 10) # proxy_max_connection 10 # Proxy timeout (by default 1s) # proxy_timeout 1 # Number of threads to execute modules in parallel #agent_threads 1 # User the agent will run as #pandora_user root # Secondary server configuration # ============================== # If secondary_mode is set to on_error, data files are copied to the secondary # server only if the primary server fails. If set to always, data files are # always copied to the secondary server. # secondary_mode on_error # secondary_server_ip localhost # secondary_server_path /var/spool/pandora/data_in # secondary_server_port 41121 # secondary_transfer_mode tentacle # secondary_server_pwd mypassword # secondary_server_ssl no # secondary_server_opts # Module Definition # ================= # System information # vmstat syntax depends on system configuration, please check before use it module_begin module_name cpu_user module_type generic_data module_interval 1 module_exec vmstat -n0 1 2 | tail -1 | awk '{ print $15 }' module_max 100 module_min 0 module_description User CPU Usage (%) module_end module_begin module_name cpu_system module_type generic_data module_interval 1 module_exec vmstat -n0 1 2 | tail -1 | awk '{ print $16 }' module_max 100 module_min 0 module_description System CPU Usage (%) module_end module_begin module_name cpu_idle module_type generic_data module_interval 1 module_exec vmstat -n0 1 2 | tail -1 | awk '{ print $17 }' module_max 100 module_min 0 module_description CPU Idle (%) module_end module_begin module_name Load Average module_type generic_data module_exec uptime | cut -d "," -f 4 | cut -d ":" -f 2 | sed "s/ //g" module_description Average process in CPU (Last minute) module_end module_begin module_name disk_root_free module_type generic_data module_exec df -kh / | tail -1 | awk '{ print 100-$5 }' module_max 100 module_min 0 module_description Free disk Percentage of root partition module_end module_begin module_name memfree module_type generic_data module_exec vmstat -H 1 2 | tail -1 | awk '{print $5}' module_description Unused RAM memory module_end module_begin module_name proctotal module_type generic_data module_exec ps -A | wc -l | sed "s/ //g" module_end # Process information module_begin module_name sshDaemon module_type generic_proc module_exec ps -Af | grep sshd | grep -v "grep" | wc -l | sed "s/ //g" module_end # Async data example module_begin module_name LastLogin module_type async_string module_exec last | head -1 module_end # Plugin example # This parses /var/log/auth.log file, under the module name "syslog" # And search for "sshd" string into it, sending only that information. module_plugin grep_log /var/log/auth.log Syslog sshd # Plugin for inventory on the agent (Only Enterprise) # module_plugin inventory 1 cpu ram video nic hd cdrom software unix/FreeBSD/pandora_agent0000755000000000001440000000201711673617616014706 0ustar rootusers#!/bin/sh # ********************************************************************** # Pandora FMS Agent Daemon launcher for FreeBSD # (c) 2010 Junichi Satoh # # ********************************************************************** # PROVIDE: pandora_agent # REQUIRE: LOGIN # KEYWORD: shutdown # Add the following line to /etc/rc.conf to enable `pandora_agent': # # pandora_agent_enable="YES" # . "/etc/rc.subr" name="pandora_agent" rcvar=`set_rcvar` # read configuration and set defaults pandora_agent_enable=${pandora_agent_enable:-"NO"} load_rc_config "$name" PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin command=/usr/local/bin/pandora_agent command_args="/usr/local/etc/pandora &" pidfile=/var/run/$name.pid required_files="/usr/local/etc/pandora/pandora_agent.conf" start_postcmd=start_postcmd stop_postcmd=stop_postcmd procname="/usr/bin/perl" start_postcmd() { sleep 1 PANDORA_PID=`pgrep -f -j none $name` echo $PANDORA_PID > $pidfile } stop_postcmd() { rm -f $pidfile } run_rc_command "$1" unix/pandora_agent.redhat.spec0000644000000000000000000000747412166524015015501 0ustar rootroot# #Pandora FMS Linux Agent # %define name pandorafms_agent_unix %define version 4.1 %define release 1 Summary: Pandora FMS Linux agent, PERL version Name: %{name} Version: %{version} Release: %{release} License: GPL Vendor: ArticaST Source0: %{name}-%{version}.tar.gz URL: http://pandorafms.org Group: System/Monitoring Packager: Sancho Lerena Prefix: /usr/share BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot BuildArch: noarch PreReq: /bin/sed /bin/grep /usr/sbin/useradd Requires: coreutils unzip AutoReq: 0 Provides: %{name}-%{version} %description Pandora FMS agent for unix. Pandora FMS is an OpenSource full-featured monitoring software. %prep rm -rf $RPM_BUILD_ROOT %setup -q -n unix %build %install rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT%{prefix}/pandora_agent/ mkdir -p $RPM_BUILD_ROOT/usr/bin/ mkdir -p $RPM_BUILD_ROOT/usr/sbin/ mkdir -p $RPM_BUILD_ROOT/etc/pandora/ mkdir -p $RPM_BUILD_ROOT/etc/init.d/ mkdir -p $RPM_BUILD_ROOT/var/log/pandora/ mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1/ cp -aRf * $RPM_BUILD_ROOT%{prefix}/pandora_agent/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/tentacle_client $RPM_BUILD_ROOT/usr/bin/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent $RPM_BUILD_ROOT/usr/bin/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent_exec $RPM_BUILD_ROOT/usr/bin/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent_daemon $RPM_BUILD_ROOT/etc/init.d/pandora_agent_daemon cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent_daemon $RPM_BUILD_ROOT/etc/init.d/pandora_agent_daemon cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/man/man1/pandora_agent.1.gz $RPM_BUILD_ROOT/usr/share/man/man1/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/man/man1/tentacle_client.1.gz $RPM_BUILD_ROOT/usr/share/man/man1/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/Linux/pandora_agent.conf $RPM_BUILD_ROOT/usr/share/pandora_agent/pandora_agent.conf.rpmnew if [ -f $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent.spec ] ; then rm $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent.spec fi %clean rm -Rf $RPM_BUILD_ROOT %pre getent passwd pandora >/dev/null || \ /usr/sbin/useradd -d %{prefix}/pandora -s /bin/false -M -g 0 pandora exit 0 %post if [ ! -d /etc/pandora ] ; then mkdir -p /etc/pandora fi # Checking old config file (if exists) if [ -e /etc/pandora/pandora_agent.conf ] ; then echo "Current configuration file exist." else cp /usr/share/pandora_agent/pandora_agent.conf.rpmnew /etc/pandora/pandora_agent.conf fi if [ ! -e /etc/pandora/plugins ]; then ln -s /usr/share/pandora_agent/plugins /etc/pandora fi if [ ! -e /etc/pandora/collections ]; then ln -s /usr/share/pandora_agent/collections /etc/pandora fi mkdir -p /var/spool/pandora/data_out /sbin/chkconfig --add pandora_agent_daemon /sbin/chkconfig pandora_agent_daemon on %preun # Upgrading if [ "$1" = "1" ]; then exit 0 fi /sbin/chkconfig --del pandora_agent_daemon /etc/init.d/pandora_agent_daemon stop rm /etc/init.d/pandora_agent_daemon /usr/sbin/userdel pandora rm -Rf /etc/pandora/pandora_agent.conf rm -Rf /var/log/pandora/pandora_agent* 2> /dev/null rm -Rf /usr/share/pandora_agent rm -Rf /usr/share/man/man1/pandora_agent.1.gz rm -Rf /usr/share/man/man1/tentacle_client.1.gz exit 0 %files %defattr(750,pandora,root) /usr/bin/pandora_agent /usr/bin/pandora_agent_exec %defattr(770,pandora,root) /var/log/pandora/ %defattr(755,pandora,root) /usr/bin/tentacle_client /etc/init.d/pandora_agent_daemon %docdir %{prefix}/pandora_agents/docs %{prefix}/pandora_agent %defattr(644,pandora,root) /usr/share/man/man1/pandora_agent.1.gz /usr/share/man/man1/tentacle_client.1.gz unix/tentacle_server0000755000000000001440000010642611673617616014070 0ustar rootusers#!/usr/bin/perl ########################################################################## # Tentacle Server # See http://www.openideas.info/wiki for protocol description. # Tentacle have IANA assigned port tpc/41121 as official port. ########################################################################## # Copyright (c) 2007-2008 Ramon Novoa # Copyright (c) 2005-2010 Artica Soluciones Tecnologicas S.L # # tentacle_server.pl Tentacle Server. See http://www.openideas.info/wiki for # protocol description. # # This program 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; version 2 of the License. # # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ########################################################################## package tentacle::server; =head1 NAME tentacle_server - Tentacle Server =head1 VERSION Version 0.3.0 =head1 USAGE tentacle_server B<< -s F >> [I] =head1 DESCRIPTION B is a server for B, a B file transfer protocol that aims to be: =over =item * Secure by design. =item * Easy to use. =item * Versatile and cross-platform. =back Tentacle was created to replace more complex tools like SCP and FTP for simple file transfer/retrieval, and switch from authentication mechanisms like .netrc, interactive logins and SSH keys to X.509 certificates. Simple password authentication over a SSL secured connection is supported too. The client and server (B) are designed to be run from the command line or called from a shell script, and B. =cut use strict; use warnings; use Getopt::Std; use IO::Select; use IO::Socket::INET; use Thread::Semaphore; use POSIX ":sys_wait_h"; # Program version our $VERSION = '0.3.0'; # Address to listen on my $t_address = '0.0.0.0'; # Block size for socket read/write operations in bytes my $t_block_size = 1024; # Client socket my $t_client_socket; # Run as daemon, 1 true, 0 false my $t_daemon = 0; # Storage directory my $t_directory = ''; # Filters my @t_filters; # String containing quoted invalid file name characters my $t_invalid_chars = '\?\[\]\/\\\=\+\<\>\:\;\'\,\*\~'; # Log messages, 1 enabled, 0 disabled my $t_log = 0; # Maximum number of simultaneous connections my $t_max_conn = 10; # Maximum file size allowed by the server in bytes my $t_max_size = 2000000; # File overwrite, 1 enabled, 0 disabled my $t_overwrite = 0; # Port to listen on my $t_port = 41121; # Server password my $t_pwd = ''; # Do not output error messages, 1 enabled, 0 disabled my $t_quiet = 0; # Number of retries for socket read/write operations my $t_retries = 3; # Select handler my $t_select; # Semaphore my $t_sem; # Server socket my $t_server_socket; # Use SSL, 1 true, 0 false my $t_ssl = 0; # SSL ca certificate file my $t_ssl_ca = ''; # SSL certificate file my $t_ssl_cert = ''; # SSL private key file my $t_ssl_key = ''; # SSL private key password my $t_ssl_pwd = ''; # Timeout for socket read/write operations in seconds my $t_timeout = 1; #Bridge IP to actuate as a proxy my $t_proxy_ip = undef; # Proxy port by default 41121 my $t_proxy_port = 41121; # Proxy socket my $t_proxy_socket; # Proxy selected handler my $t_proxy_select; ################################################################################ ## SUB print_help ## Print help screen. ################################################################################ sub print_help { print ("Usage: $0 -s [options]\n\n"); print ("Tentacle server v$VERSION. See http://www.openideas.info/wiki for protocol description.\n\n"); print ("Options:\n"); print ("\t-a ip_address\tAddress to listen on (default $t_address).\n"); print ("\t-c number\tMaximum number of simultaneous connections (default $t_max_conn).\n"); print ("\t-d\t\tRun as daemon.\n"); print ("\t-e cert\t\tOpenSSL certificate file. Enables SSL.\n"); print ("\t-f ca_cert\tVerify that the peer certificate is signed by a ca.\n"); print ("\t-h\t\tShow help.\n"); print ("\t-i\t\tFilters.\n"); print ("\t-k key\t\tOpenSSL private key file.\n"); print ("\t-m size\t\tMaximum file size in bytes (default ${t_max_size}b).\n"); print ("\t-o\t\tEnable file overwrite.\n"); print ("\t-p port\t\tPort to listen on (default $t_port).\n"); print ("\t-q\t\tQuiet. Do now print error messages.\n"); print ("\t-r number\tNumber of retries for network opertions (default $t_retries).\n"); print ("\t-t time\t\tTime-out for network operations in seconds (default ${t_timeout}s).\n"); print ("\t-v\t\tBe verbose.\n"); print ("\t-w\t\tPrompt for OpenSSL private key password.\n"); print ("\t-x pwd\t\tServer password.\n\n"); print ("\t-b proxy_ip_address\t\tProxied server address.\n\n"); print ("\t-g proxy_port\t\tPort of proxied server.\n\n"); } ################################################################################ ## SUB daemonize ## Turn the current process into a daemon. ################################################################################ sub daemonize { my $pid; require POSIX; chdir ('/') || error ("Cannot chdir to /: $!."); umask 0; open (STDIN, '/dev/null') || error ("Cannot read /dev/null: $!."); # Do not be verbose when running as a daemon open (STDOUT, '>/dev/null') || error ("Cannot write to /dev/null: $!."); open (STDERR, '>/dev/null') || error ("Cannot write to /dev/null: $!."); # Fork $pid = fork (); if (! defined ($pid)) { error ("Cannot fork: $!."); } # Parent if ($pid != 0) { exit; } # Child POSIX::setsid () || error ("Cannot start a new session: $!."); } ################################################################################ ## SUB start_win_service ## Turn the current process into a Windows service. ################################################################################ #sub start_win_service { # require Win32::Daemon; # # # Tell the OS to start the service # Win32::Daemon::StartService (); # # # Wait until the service manager is ready # while (SERVICE_START_PENDING != Win32::Daemon::State()) { # sleep (1); # } # # # Tell the service manager we are running # Win32::Daemon::State (SERVICE_RUNNING); # # # Call Win32::Daemon::StopService() when done #} ################################################################################ ## SUB parse_options ## Parse command line options and initialize global variables. ################################################################################ sub parse_options { my %opts; my $tmp; # Get options if (getopts ('a:c:de:f:hi:k:m:op:qr:s:t:vwx:b:g:', \%opts) == 0 || defined ($opts{'h'})) { print_help (); exit 1; } # Address if (defined ($opts{'a'})) { $t_address = $opts{'a'}; if ($t_address !~ /^[a-zA-Z\.]+$/ && ($t_address !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ || $1 < 0 || $1 > 255 || $2 < 0 || $2 > 255 || $3 < 0 || $3 > 255 || $4 < 0 || $4 > 255)) { error ("Address $t_address is not valid."); } } # Maximum simultaneous connections if (defined ($opts{'c'})) { $t_max_conn = $opts{'c'}; if ($t_max_conn !~ /^\d+$/ || $t_max_conn < 1) { error ("Invalid number of maximum simultaneous connections."); } } # Run as daemon if (defined ($opts{'d'})) { if ($^ eq 'MSWin32') { error ("-d flag not available for this OS."); } $t_daemon = 1; } # Enable SSL if (defined ($opts{'e'})) { require IO::Socket::SSL; $t_ssl_cert = $opts{'e'}; if (! -f $t_ssl_cert) { error ("File $t_ssl_cert does not exist."); } $t_ssl = 1; } # Verify peer certificate if (defined ($opts{'f'})) { $t_ssl_ca = $opts{'f'}; if (! -f $t_ssl_ca) { error ("File $t_ssl_ca does not exist."); } } # Filters (regexp:dir;regexp:dir...) if (defined ($opts{'i'})) { my @filters = split (';', $opts{'i'}); foreach my $filter (@filters) { my ($regexp, $dir) = split (':', $filter); next unless defined ($regexp) && defined ($dir); # Remove any trailing / my $char = chop ($dir); $dir .= $char if ($char) ne '/'; push(@t_filters, [$regexp, $dir]); } } # SSL private key file if (defined ($opts{'k'})) { $t_ssl_key = $opts{'k'}; if (! -f $t_ssl_key) { error ("File $t_ssl_key does not exist."); } } # Maximum file size if (defined ($opts{'m'})) { $t_max_size = $opts{'m'}; if ($t_max_size !~ /^\d+$/ || $t_max_size < 1) { error ("Invalid maximum file size."); } } # File overwrite if (defined ($opts{'o'})) { $t_overwrite = 1; } # Port if (defined ($opts{'p'})) { $t_port = $opts{'p'}; if ($t_port !~ /^\d+$/ || $t_port < 1 || $t_port > 65535) { error ("Port $t_port is not valid."); } } # Quiet mode if (defined ($opts{'q'})) { $t_quiet = 1; } # Retries if (defined ($opts{'r'})) { $t_retries = $opts{'r'}; if ($t_retries !~ /^\d+$/ || $t_retries < 1) { error ("Invalid number of retries for network operations."); } } # Storage directory if (defined ($opts{'s'})) { $t_directory = $opts{'s'}; # Check that directory exists if (! -d $t_directory) { error ("Directory $t_directory does not exist."); } # Check directory permissions if (! -w $t_directory) { error ("Cannot write to directory $t_directory."); } # Remove the trailing / if present $tmp = chop ($t_directory); if ($tmp ne '/') { $t_directory .= $tmp; } } else { if (! defined($opts{'b'})) { print_help (); exit 1; } } # Timeout if (defined ($opts{'t'})) { $t_timeout = $opts{'t'}; if ($t_timeout !~ /^\d+$/ || $t_timeout < 1) { error ("Invalid timeout for network operations."); } } # Be verbose if (defined ($opts{'v'})) { $t_log = 1; } # SSL private key password if (defined ($opts{'w'})) { $t_ssl_pwd = ask_passwd ("Enter private key file password: ", "Enter private key file password again for confirmation: "); } # Server password if (defined ($opts{'x'})) { $t_pwd = $opts{'x'}; } #Proxy IP address if (defined ($opts{'b'})) { $t_proxy_ip = $opts{'b'}; if ($t_proxy_ip !~ /^[a-zA-Z\.]+$/ && ($t_proxy_ip !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ || $1 < 0 || $1 > 255 || $2 < 0 || $2 > 255 || $3 < 0 || $3 > 255 || $4 < 0 || $4 > 255)) { error ("Proxy address $t_proxy_ip is not valid."); } } # Proxy Port if (defined ($opts{'g'})) { $t_proxy_port = $opts{'g'}; if ($t_proxy_port !~ /^\d+$/ || $t_proxy_port < 1 || $t_proxy_port > 65535) { error ("Proxy port $t_port is not valid."); } } } ################################################################################ ## SUB sigchld_handler ## Handle child process termination. ################################################################################ sub sigchld_handler { while (waitpid(-1, &WNOHANG) > 0) { $t_sem->up (); } $SIG{CHLD} = \&sigchld_handler; } ################################################################################ ## SUB start_proxy ## Open the server socket. ################################################################################ sub open_proxy { # Connect to server $t_proxy_socket = IO::Socket::INET->new ( PeerAddr => $t_proxy_ip, PeerPort => $t_proxy_port, ); if (! defined ($t_proxy_socket)) { error ("Cannot connect to $t_proxy_ip on port $t_proxy_port: $!."); } # Create proxy selector $t_proxy_select = IO::Select->new (); $t_proxy_select->add ($t_proxy_socket); } ################################################################################ ## SUB start_server ## Open the server socket. ################################################################################ sub start_server { $t_server_socket = IO::Socket::INET->new ( Listen => $t_max_conn, LocalAddr => $t_address, LocalPort => $t_port, Proto => 'tcp', ReuseAddr => 1, ); if (! defined ($t_server_socket)) { error ("Cannot open socket for address $t_address on port $t_port: $!."); } print_log ("Server listening on $t_address port $t_port (press to stop)"); # Say message if tentacle proxy is enable if (defined ($t_proxy_ip)) { print_log ("Proxy Mode enable, data will be sent to $t_proxy_ip port $t_proxy_port"); } } ################################################################################ ## SUB send_data_proxy ## Send data to proxy socket. ################################################################################ sub send_data_proxy { my $data = $_[0]; my $retries = 0; my $size; my $total = 0; my $written; $size = length ($data); while (1) { # Try to write data to the socket if ($t_proxy_select->can_write ($t_timeout)) { $written = syswrite ($t_proxy_socket, $data, $size - $total, $total); # Write error if (! defined ($written)) { error ("Connection error from " . $t_proxy_socket->sockhost () . ": $!."); } # EOF if ($written == 0) { error ("Connection from " . $t_proxy_socket->sockhost () . " unexpectedly closed."); } } $total += $written; # Check if all data was written if ($total == $size) { return; } # Retry $retries++; # But check for error conditions first if ($retries > $t_retries) { error ("Connection from " . $t_proxy_socket->sockhost () . " timed out."); } } } ################################################################################ ## SUB close_proxy ## Close the proxy socket. ################################################################################ sub close_proxy { $t_proxy_socket->close (); print_log ("Proxy socket closed"); } ################################################################################ ## SUB stop_server ## Close the server socket. ################################################################################ sub stop_server { $t_server_socket->close (); print_log ("Server going down"); exit 0; } ################################################################################ ## SUB start_ssl ## Convert the client socket to an IO::Socket::SSL socket. ################################################################################ sub start_ssl { my $err; if ($t_ssl_ca eq '') { IO::Socket::SSL->start_SSL ( $t_client_socket, SSL_cert_file => $t_ssl_cert, SSL_key_file => $t_ssl_key, SSL_passwd_cb => sub {return $t_ssl_pwd}, SSL_server => 1, # Verify peer SSL_verify_mode => 0x01, ); } else { IO::Socket::SSL->start_SSL ( $t_client_socket, SSL_ca_file => $t_ssl_ca, SSL_cert_file => $t_ssl_cert, SSL_key_file => $t_ssl_key, SSL_passwd_cb => sub {return $t_ssl_pwd}, SSL_server => 1, # Fail verification if no peer certificate exists SSL_verify_mode => 0x03, ); } $err = IO::Socket::SSL::errstr (); if ($err ne '') { error ($err); } print_log ("SSL started for " . $t_client_socket->sockhost ()); } ################################################################################ ## SUB accept_connection ## Accept an incoming connection and fork. ################################################################################ sub accept_connection { my $pid; while (1) { # Accept connection $t_client_socket = $t_server_socket->accept (); if (! defined ($t_client_socket)) { # EINTR if ($! ne '') { next; } error ("accept: $!."); } last; } print_log ("Client connected from " . $t_client_socket->sockhost ()); # Fork and serve the client $pid = fork (); if (! defined ($pid)) { error ("Cannot fork: $!."); } # Child if ($pid == 0) { # We do not need the server socket $t_server_socket->close (); # Add client socket to select queue $t_select = IO::Select->new (); $t_select->add ($t_client_socket); # Start SSL if ($t_ssl == 1) { start_ssl (); } # Authenticate client if ($t_pwd ne '') { auth_pwd (); } # Check if proxy mode is enable if (defined ($t_proxy_ip)) { serve_proxy_connection (); } else { serve_connection (); } $t_client_socket->close (); # Must exit now exit; } # Parent $t_client_socket->close (); } ################################################################################ ## SUB serve_proxy_connection ## Actuate as a proxy between its client and other tentacle server. ################################################################################ sub serve_proxy_connection { my $read; my $data=1; # Start a connection with the other Tentacle Server open_proxy(); my $command; # Read commands while ($command = recv_command ($t_block_size)) { # Client wants to send a file if ($command =~ /^SEND <(.*)> SIZE (\d+)$/) { recv_file_proxy($command, $2); } # Client wants to receive a file elsif ($command =~ /^RECV <(.*)>$/) { send_file_proxy ($command); } # Quit elsif ($command =~ /^QUIT$/) { print_log ("Connection closed from " . $t_client_socket->sockhost ()); # End proxy connection send_data_proxy("QUIT\n"); last; } # Unknown command else { print_log ("Unknown command '$command' from " . $t_client_socket->sockhost ()); last; } } # End a connection with the other Tentacle Server close_proxy(); } ################################################################################ ## SUB serve_connection ## Read and process commands from the client. ################################################################################ sub serve_connection { my $command; # Read commands while ($command = recv_command ($t_block_size)) { # Client wants to send a file if ($command =~ /^SEND <(.*)> SIZE (\d+)$/) { print_log ("Request to send file '$1' size ${2}b from " . $t_client_socket->sockhost ()); recv_file ($1, $2); } # Client wants to receive a file elsif ($command =~ /^RECV <(.*)>$/) { print_log ("Request to receive file '$1' from " . $t_client_socket->sockhost ()); send_file ($1); } # Quit elsif ($command =~ /^QUIT$/) { print_log ("Connection closed from " . $t_client_socket->sockhost ()); last; } # Unknown command else { print_log ("Unknown command '$command' from " . $t_client_socket->sockhost ()); last; } } } ################################################################################ ## SUB auth_pwd ## Authenticate client with server password. ################################################################################ sub auth_pwd { my $client_digest; my $command; my $pwd_digest; require Digest::MD5; # Wait for password $command = recv_command ($t_block_size); if ($command !~ /^PASS (.*)$/) { error ("Client " . $t_client_socket->sockhost () . " did not authenticate."); } $client_digest = $1; $pwd_digest = Digest::MD5::md5 ($t_pwd); $pwd_digest = Digest::MD5::md5_hex ($pwd_digest); if ($client_digest ne $pwd_digest) { error ("Invalid password from " . $t_client_socket->sockhost () . "."); } print_log ("Client " . $t_client_socket->sockhost () . " authenticated"); send_data ("PASS OK\n"); } ################################################################################ ## SUB recv_file_proxy ## Redirect file from agent to proxy ################################################################################ sub recv_file_proxy ($$) { my ($command, $size) = @_; # Send command to proxy print_log ("[PROXY] Host: ".$t_client_socket->sockhost()." send ".$command." to ".$t_proxy_socket->sockhost ()); send_data_proxy($command."\n"); # Proxied server response my $rc = dump_data($t_proxy_socket, $t_client_socket); # Check if there was an error if ($rc == -1) { return; } # Client send data to server $rc = dump_data($t_client_socket, $t_proxy_socket, $size); # Check if there was an error if ($rc == -1) { return; } # Server says if data was recieved or not $rc = dump_data($t_proxy_socket, $t_client_socket); # Check if there was an error if ($rc == -1) { return; } } ################################################################################ ## SUB recv_file ## Receive a file of size $_[1] and save it in $t_directory as $_[0]. ################################################################################ sub recv_file { my $base_name = $_[0]; my $data = ''; my $file; my $size = $_[1]; # Check file name if ($base_name =~ /[$t_invalid_chars]/) { print_log ("File '$base_name' size ${size}b from " . $t_client_socket->sockhost () . " has an invalid file name"); send_data ("SEND ERR\n"); return; } # Check file size, empty files are not allowed if ($size < 1 || $size > $t_max_size) { print_log ("File '$base_name' size ${size}b from " . $t_client_socket->sockhost () . " is too big"); send_data ("SEND ERR\n"); return; } # Apply filters $file = "$t_directory/" . apply_filters ($base_name) . $base_name; # Check if file exists if (-f $file && $t_overwrite == 0) { print_log ("File '$base_name' size ${size}b from " . $t_client_socket->sockhost () . " already exists"); send_data ("SEND ERR\n"); return; } send_data ("SEND OK\n"); # Receive file $data = recv_data_block ($size); # Write it to disk open (FILE, "> $file") || error ("Cannot open file '$file' for writing."); binmode (FILE); print (FILE $data); close (FILE); send_data ("SEND OK\n"); print_log ("Received file '$base_name' size ${size}b from " . $t_client_socket->sockhost ()); } ################################################################################ ## SUB send_file_proxy ## Redirect file from agent to proxy ################################################################################ sub send_file_proxy ($) { my ($command) = @_; my $size; # Send command to proxy print_log ("[PROXY] ".$t_client_socket->sockhost()." send ".$command." to ".$t_proxy_socket->sockhost ()); send_data_proxy($command."\n"); $command = recv_command_proxy($t_block_size); if ($command =~ /^RECV SIZE (\d+)$/) { $size = $1; } print_log ("[PROXY] ".$t_proxy_socket->sockhost()." send ".$command." to ".$t_client_socket->sockhost ()); send_data($command."\n"); # Client send OK to server my $rc = dump_data($t_client_socket, $t_proxy_socket); # Check if there was an error if ($rc == -1) { return; } # Proxied server send the file to client $rc = dump_data($t_proxy_socket, $t_client_socket, $size); # Check if there was an error if ($rc == -1) { return; } } ################################################################################ ## SUB send_file ## Send a file to the client ################################################################################ sub send_file { my $base_name = $_[0]; my $data = ''; my $file; my $response; my $size; # Check file name if ($base_name =~ /[$t_invalid_chars]/) { print_log ("Requested file '$base_name' from " . $t_client_socket->sockhost () . " has an invalid file name"); send_data ("RECV ERR\n"); return; } # Apply filters $file = "$t_directory/" . apply_filters ($base_name) . $base_name; # Check if file exists if (! -f $file) { print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " does not exist"); send_data ("RECV ERR\n"); return; } $size = -s $file; send_data ("RECV SIZE $size\n"); # Wait for client response $response = recv_command ($t_block_size); if ($response ne "RECV OK") { print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " not sent"); return; } # Send the file open (FILE, $file) || error ("Cannot open file '$file' for reading."); binmode (FILE); while ($data = ) { send_data ($data); } close (FILE); print_log ("Requested file '$file' from " . $t_client_socket->sockhost () . " sent"); } ################################################################################ # Common functions ################################################################################ ################################################################################ ## SUB print_log ## Print log messages. ################################################################################ sub print_log { if ($t_log == 1) { print (STDOUT "[log] $_[0]\n"); } } ################################################################################ ## SUB error ## Print an error and exit the program. ################################################################################ sub error { if ($t_quiet == 0) { print (STDERR "[err] $_[0]\n"); } exit 1; } ################################################################################ ## SUB recv_data_proxy ## Recv data from proxy socket. ################################################################################ sub recv_data_proxy { my $data; my $read; my $retries = 0; my $size = $_[0]; while (1) { # Try to read data from the socket if ($t_proxy_select->can_read ($t_timeout)) { # Read at most $size bytes $read = sysread ($t_proxy_socket, $data, $size); # Read error if (! defined ($read)) { error ("Read error from " . $t_proxy_socket->sockhost () . ": $!."); } # EOF if ($read == 0) { error ("Connection from " . $t_proxy_socket->sockhost () . " unexpectedly closed."); } return ($read, $data); } # Retry $retries++; # But check for error conditions first if ($retries > $t_retries) { error ("Connection from " . $t_proxy_socket->sockhost () . " timed out."); } } } ################################################################################ ## SUB recv_data ## Read data from the client socket. Returns the number of bytes read and the ## string of bytes as a two element array. ################################################################################ sub recv_data { my $data; my $read; my $retries = 0; my $size = $_[0]; while (1) { # Try to read data from the socket if ($t_select->can_read ($t_timeout)) { # Read at most $size bytes $read = sysread ($t_client_socket, $data, $size); # Read error if (! defined ($read)) { error ("Read error from " . $t_client_socket->sockhost () . ": $!."); } # EOF if ($read == 0) { error ("Connection from " . $t_client_socket->sockhost () . " unexpectedly closed."); } return ($read, $data); } # Retry $retries++; # But check for error conditions first if ($retries > $t_retries) { error ("Connection from " . $t_client_socket->sockhost () . " timed out."); } } } ################################################################################ ## SUB send_data ## Write data to the client socket. ################################################################################ sub send_data { my $data = $_[0]; my $retries = 0; my $size; my $total = 0; my $written; $size = length ($data); while (1) { # Try to write data to the socket if ($t_select->can_write ($t_timeout)) { $written = syswrite ($t_client_socket, $data, $size - $total, $total); # Write error if (! defined ($written)) { error ("Connection error from " . $t_client_socket->sockhost () . ": $!."); } # EOF if ($written == 0) { error ("Connection from " . $t_client_socket->sockhost () . " unexpectedly closed."); } } $total += $written; # Check if all data was written if ($total == $size) { return; } # Retry $retries++; # But check for error conditions first if ($retries > $t_retries) { error ("Connection from " . $t_client_socket->sockhost () . " timed out."); } } } ################################################################################ ## SUB dump_data ## Dump data from a socket to another one. Following Tentacle Protocol. ################################################################################ sub dump_data($$;$) { my ($from, $to, $size) = @_; my $read; my $data; my $buffer = ""; my $written; my $total = $size; my $t_select_read = undef; my $t_select_write = undef; # Assign the correct selector for each socket if ($from == $t_proxy_socket) { # We must read from t_proxy_socket $t_select_read = $t_proxy_select; $t_select_write = $t_select; } else { # We must read from t_client_socket $t_select_read = $t_select; $t_select_write = $t_proxy_select; } while (1) { # Ensure we can read from socket if ($t_select_read->can_read()) { # Ensure we can write from socket if ($t_select_write->can_write()) { $read = ""; $read = sysread ($from, $data, $t_block_size); # Read error if (! defined ($read)) { error ("Read error from " . $from->sockhost () . ": $!."); return -1; } # EOF if ($read == 0) { error ("Connection from " . $from->sockhost () . " unexpectedly closed."); return -1; } $written = syswrite ($to, $data, $read); if ($written != $read) { error ("Connection from " . $to->sockhost () . " unexpectedly closed."); return -1; } $buffer .= $data; if (! defined ($size)) { # If no size defined check for \n # because a command was sent. if ($buffer =~ /\n$/) { # Delete CHAR \n chop($buffer); print_log ("[PROXY] ".$from->sockhost()." send ".$buffer." to ".$to->sockhost ()); # Returns error if proxy returns error to end connection if ($buffer =~ /SEND ERR/) { return -1; } else { return 0; } } } else { # If size is defined check if all bytes were sent $size = $size - $read; if ($size == 0) { print_log ("[PROXY] ".$from->sockhost()." send ".$total."b to ".$to->sockhost()); return 0; } } } } } } ################################################################################ ## SUB recv_command_proxy ## Read a command from the proxied server, ended by a new line character. ################################################################################ sub recv_command_proxy { my $buffer; my $char; my $command = ''; my $read; my $total = 0; while (1) { ($read, $buffer) = recv_data_proxy ($t_block_size); $command .= $buffer; $total += $read; # Check if the command is complete $char = chop ($command); if ($char eq "\n") { return $command; } $command .= $char; # Avoid overflow if ($total > $t_block_size) { error ("Received too much data from " . $t_proxy_socket->sockhost () . "."); } } } ################################################################################ ## SUB recv_command ## Read a command from the client, ended by a new line character. ################################################################################ sub recv_command { my $buffer; my $char; my $command = ''; my $read; my $total = 0; while (1) { ($read, $buffer) = recv_data ($t_block_size); $command .= $buffer; $total += $read; # Check if the command is complete $char = chop ($command); if ($char eq "\n") { return $command; } $command .= $char; # Avoid overflow if ($total > $t_block_size) { error ("Received too much data from " . $t_client_socket->sockhost () . "."); } } } ################################################################################ ## SUB recv_data_block ## Read $_[0] bytes of data from the client. ################################################################################ sub recv_data_block { my $buffer = ''; my $data = ''; my $read; my $size = $_[0]; my $total = 0; while (1) { ($read, $buffer) = recv_data ($size - $total); $data .= $buffer; $total += $read; # Check if all data has been read if ($total == $size) { return $data; } } } ################################################################################ ## SUB ask_passwd ## Asks the user for a password. ################################################################################ sub ask_passwd { my $msg1 = $_[0]; my $msg2 = $_[1]; my $pwd1; my $pwd2; require Term::ReadKey; # Disable keyboard echo Term::ReadKey::ReadMode('noecho'); # Promt for password print ($msg1); $pwd1 = Term::ReadKey::ReadLine(0); print ("\n$msg2"); $pwd2 = Term::ReadKey::ReadLine(0); print ("\n"); # Restore original settings Term::ReadKey::ReadMode('restore'); if ($pwd1 ne $pwd2) { print ("Error: passwords do not match.\n"); exit 1; } # Remove the trailing new line character chop $pwd1; return $pwd1; } ################################################################################ ## SUB apply_filters ## Applies filters to the given file. ################################################################################ sub apply_filters ($) { my ($file_name) = @_; foreach my $filter (@t_filters) { my ($regexp, $dir) = @{$filter}; if ($file_name =~ /$regexp/) { print_log ("File '$file_name' matches filter '$regexp' (changing to directory '$dir')"); return $dir . '/'; } } return ''; } ################################################################################ # Main ################################################################################ # Never run as root if ($> == 0 && $^O ne 'MSWin32') { print ("Error: for safety reasons $0 cannot be run with root privileges.\n"); exit 1; } # Parse command line options parse_options (); # Check command line arguments if ($#ARGV != -1) { print_help (); exit 1; } # Run as daemon? if ($t_daemon == 1 && $^O ne 'MSWin32') { daemonize (); } # Handle ctr-c if ($^O eq 'MSWin32') { $SIG{INT2} = \&stop_server; } else { $SIG{INT} = \&stop_server; } # Handle SIGCHLD $SIG{CHLD} = \&sigchld_handler; start_server (); # Initialize semaphore $t_sem = Thread::Semaphore->new ($t_max_conn); # Accept connections while (1) { $t_sem->down (); accept_connection (); } __END__ =head1 REQUIRED ARGUMENTES =over =item B<< -s F >> Root directory to store the files received by the server =back =head1 OPTIONS =over =item I<-a ip_address> Address to B on (default I<0.0.0.0>). =item I<-c number> B number of simultaneous B (default I<10>). =item I<-d> Run as B. =item I<-e cert> B file. Enables SSL. =item I<-f ca_cert> Verify that the peer certificate is signed by a B. =item I<-h> Show B. =item I<-i> B. =item I<-k key> B file. =item I<-m size> B in bytes (default I<2000000b>). =item I<-o> Enable file B. =item I<-p port> B on (default I<41121>). =item I<-q> B. Do now print error messages. =item I<-r number> B for network opertions (default I<3>). =item I<-t time> B for network operations in B (default I<1s>). =item I<-v> Be B. =item I<-w> Prompt for B. =item I<-x> pwd B. =back =head1 EXIT STATUS =over =item 0 on Success =item 1 on Error =back =head1 CONFIGURATION Tentacle doesn't use any configurationf files, all the configuration is done by the options passed when it's started. =head1 DEPENDENCIES L, L, L, L, L =head1 LICENSE This is released under the GNU Lesser General Public License. =head1 SEE ALSO L, L, L, L, L Protocol description and more info at: L<< http://openideas.info/wiki/index.php?title=Tentacle >> =head1 COPYRIGHT Copyright (c) 2005-2010 Artica Soluciones Tecnologicas S.L =cut unix/pandora_agent_daemon0000755000000000001440000000631711673617616015026 0ustar rootusers#!/bin/sh # ********************************************************************** # Pandora FMS Agent Daemon launcher for Unix (AIX, HP-UX, SunOS, Linux) # (c) 2008-2010 Artica ST # (c) 2008-2010 Sancho Lerena # # Please see http://www.pandorafms.org # v3.2 Build 101115 # This code is licensed under GPL 2.0 license. # ********************************************************************** ### BEGIN INIT INFO # Provides: pandora_agent # Required-Start: $network # Required-Stop: $network # Default-Start: 2 3 5 # Default-Stop: 0 1 6 # Short-Description: Startup script daemon for Pandora FMS agent # Description: Startup script daemon for Pandora FMS agent (linux) ### END INIT INFO PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin PANDORA_PATH=/etc/pandora DAEMON=/usr/bin/pandora_agent DAEMON_TENTACLE=/usr/bin/tentacle_server LOGFILE=/var/log/pandora/pandora_agent.log PANDORA_USER=root # This function replace pidof, not working in the same way in different linux distros pidof_pandora () { COLUMNS=400 OS_NAME=`uname -s` if [ $OS_NAME = "HP-UX" ] then PANDORA_PID=`ps -ex | grep "$DAEMON $PANDORA_PATH" | grep -v grep | head -1 | awk '{ print $1 }'` else if [ "$OS_NAME" = "SunOS" ] then ZONENAME_CMD="/bin/zonename" TRUNCATED_DAEMON=`echo "$DAEMON $PANDORA_PATH" | cut -c1-40` if [ -x $ZONENAME_CMD ] then ZONE=`$ZONENAME_CMD` else ZONE= fi if [ "$ZONE" = "global" ] then PANDORA_PID=`ps -f -z global | grep "$TRUNCATED_DAEMON" | grep -v grep | head -1 | awk '{ print $2 }'` else PANDORA_PID=`ps -Af | grep "$TRUNCATED_DAEMON" | grep -v grep | head -1 | awk '{ print $2 }'` fi elif [ "$OS_NAME" = "Linux" -a -x /usr/sbin/vzpid ] then for _pid in `ps -Af | grep "$DAEMON $PANDORA_PATH" | grep -v grep | awk '{ print $2 }'` do _ctid=`/usr/sbin/vzpid $_pid | awk '$1 == '$_pid' { print $2 }'` if [ "X$_ctid" = "X0" ] then PANDORA_PID=$_pid break fi done else PANDORA_PID=`ps -Af | grep "$DAEMON $PANDORA_PATH" | grep -v grep | head -1 | awk '{ print $2 }'` fi fi echo $PANDORA_PID } if [ ! -f $DAEMON ] then echo "Pandora FMS Agent not found at $DAEMON, please check setup" exit fi case "$1" in start) PANDORA_PID=`pidof_pandora` if [ ! -z "$PANDORA_PID" ] then echo "Pandora FMS Agent is currently running on this machine with PID $PANDORA_PID" echo "Cannot launch again. Aborting." exit 1 fi su $PANDORA_USER -c "PATH=$PATH nohup $DAEMON $PANDORA_PATH >/dev/null 2>$LOGFILE &" sleep 2 PANDORA_PID=`pidof_pandora` echo "Pandora FMS Agent is now running with PID $PANDORA_PID" ;; stop) PANDORA_PID=`pidof_pandora` if [ -z "$PANDORA_PID" ] then echo "Pandora FMS Agent is not running, cannot stop it. Aborting now..." exit 1 else echo "Stopping Pandora Agent." su $PANDORA_USER -c "kill $PANDORA_PID >/dev/null 2>&1" fi ;; status) PANDORA_PID=`pidof_pandora` if [ -z "$PANDORA_PID" ] then echo "Pandora FMS Agent is not running." else echo "Pandora FMS Agent is running with PID $PANDORA_PID." fi exit 0 ;; force-reload|restart) $0 stop sleep 2 $0 start ;; *) echo "Usage: /etc/init.d/pandora_agent_daemon {start|stop|restart|status}" exit 1 esac unix/pandora_agent.spec0000644000000000000000000000757512166524015014235 0ustar rootroot# #Pandora FMS Linux Agent # %define name pandorafms_agent_unix %define version 4.1 %define release 1 Summary: Pandora FMS Linux agent, PERL version Name: %{name} Version: %{version} Release: %{release} License: GPL Vendor: ArticaST Source0: %{name}-%{version}.tar.gz URL: http://pandorafms.org Group: System/Monitoring Packager: Sancho Lerena Prefix: /usr/share BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot BuildArch: noarch PreReq: %fillup_prereq %insserv_prereq /usr/bin/sed /usr/bin/grep /usr/sbin/useradd BuildRequires: sysvinit cron rsyslog sysconfig Requires: coreutils unzip AutoReq: 0 Provides: %{name}-%{version} %description Pandora FMS agent for unix. Pandora FMS is an OpenSource full-featured monitoring software. %prep rm -rf $RPM_BUILD_ROOT %setup -q -n unix %build %install rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT%{prefix}/pandora_agent/ mkdir -p $RPM_BUILD_ROOT/usr/bin/ mkdir -p $RPM_BUILD_ROOT/usr/sbin/ mkdir -p $RPM_BUILD_ROOT/etc/pandora/ mkdir -p $RPM_BUILD_ROOT/etc/init.d/ mkdir -p $RPM_BUILD_ROOT/var/log/pandora/ mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1/ cp -aRf * $RPM_BUILD_ROOT%{prefix}/pandora_agent/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/tentacle_client $RPM_BUILD_ROOT/usr/bin/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent $RPM_BUILD_ROOT/usr/bin/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent_exec $RPM_BUILD_ROOT/usr/bin/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent_daemon $RPM_BUILD_ROOT/etc/init.d/pandora_agent_daemon cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent_daemon $RPM_BUILD_ROOT/etc/init.d/pandora_agent_daemon cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/man/man1/pandora_agent.1.gz $RPM_BUILD_ROOT/usr/share/man/man1/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/man/man1/tentacle_client.1.gz $RPM_BUILD_ROOT/usr/share/man/man1/ cp -aRf $RPM_BUILD_ROOT%{prefix}/pandora_agent/Linux/pandora_agent.conf $RPM_BUILD_ROOT/usr/share/pandora_agent/pandora_agent.conf.rpmnew if [ -f $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent.spec ] ; then rm $RPM_BUILD_ROOT%{prefix}/pandora_agent/pandora_agent.spec fi %clean rm -Rf $RPM_BUILD_ROOT %pre if [ "`id pandora | grep uid | wc -l`" = 0 ] then /usr/sbin/useradd -d %{prefix}/pandora -s /bin/false -M -g 0 pandora fi %post if [ ! -d /etc/pandora ] ; then mkdir -p /etc/pandora fi # Checking old config file (if exists) if [ -e /etc/pandora/pandora_agent.conf ] ; then echo "Current configuration file exist." else cp /usr/share/pandora_agent/pandora_agent.conf.rpmnew /etc/pandora/pandora_agent.conf fi if [ ! -e /etc/pandora/plugins ]; then ln -s /usr/share/pandora_agent/plugins /etc/pandora fi if [ ! -e /etc/pandora/collections ]; then ln -s /usr/share/pandora_agent/collections /etc/pandora fi mkdir -p /var/spool/pandora/data_out chkconfig pandora_agent_daemon on %preun # Upgrading if [ "$1" = "1" ]; then exit 0 fi chkconfig --del pandora_agent_daemon /etc/init.d/pandora_agent_daemon stop rm /etc/init.d/pandora_agent_daemon /usr/sbin/userdel pandora rm -Rf /etc/pandora/pandora_agent.conf rm -Rf /var/log/pandora/pandora_agent* 2> /dev/null rm -Rf /usr/share/pandora_agent rm -Rf /usr/share/man/man1/pandora_agent.1.gz rm -Rf /usr/share/man/man1/tentacle_client.1.gz exit 0 %files %defattr(750,pandora,root) /usr/bin/pandora_agent /usr/bin/pandora_agent_exec %defattr(770,pandora,root) /var/log/pandora/ %defattr(755,pandora,root) /usr/bin/tentacle_client /etc/init.d/pandora_agent_daemon %docdir %{prefix}/pandora_agents/docs %{prefix}/pandora_agent %defattr(644,pandora,root) /usr/share/man/man1/pandora_agent.1.gz /usr/share/man/man1/tentacle_client.1.gz unix/OpenWRT/0000755000000000001440000000000011673617613012237 5ustar rootusersunix/OpenWRT/pandora_agent_daemon0000755000000000001440000000314211673617613016312 0ustar rootusers#!/bin/sh # Pandora FMS Embedded Agent, startup script # Copyright (c) 2011 Artica ST, # Tested on Busybox 1.13 # v4.0 Build 110122 # http://www.pandorafms.com PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin PANDORA_PATH=/etc/pandora DAEMON=/usr/bin/pandora_agent LOGFILE=/dev/null # This function replace pidof # not working in the same way in different linux distros pidof_pandora() { COLUMNS=250 PANDORA_PID=`ps | grep $DAEMON | grep -v grep | head -1 | awk '{ print $1 }'` echo $PANDORA_PID } if [ ! -f $DAEMON ] then echo "Pandora FMS Agent not found at $DAEMON, please check setup" exit fi case "$1" in start) PANDORA_PID=`pidof_pandora` if [ ! -z "$PANDORA_PID" ] then echo "Pandora FMS Agent is currently running on this machine with PID $PANDORA_PID" echo "Cannot launch again. Aborting." exit 1 fi nohup $DAEMON $PANDORA_PATH 2> $LOGFILE & sleep 1 PANDORA_PID=`pidof_pandora` echo "Pandora FMS Agent is now running with PID $PANDORA_PID" ;; stop) PANDORA_PID=`pidof_pandora` if [ -z "$PANDORA_PID" ] then echo "Pandora FMS Agent is not running, cannot stop it. Aborting now..." exit 1 else echo "Stopping Pandora FMS Agent." kill $PANDORA_PID > /dev/null 2>&1 fi ;; status) PANDORA_PID=`pidof_pandora` if [ -z "$PANDORA_PID" ] then echo "Pandora FMS Agent is not running." else echo "Pandora FMS Agent is running with PID $PANDORA_PID." fi exit 0 ;; force-reload|restart) $0 stop sleep 2 $0 start ;; *) echo "Usage: /etc/init.d/pandora_agent_daemon {start|stop|restart|status|force-reload}" exit 1 esac unix/OpenWRT/INSTALL0000644000000000001440000000336511673617613013277 0ustar rootusersPerl Agent =========== Dependencies ------------ This is the generic Unix package, developed in Perl. In order to use it, you need to install a few packages first. This will be done using opkg (command line packager tool): opkg install perl opkg install perlbase-autoloader opkg install perlbase-base opkg install perlbase-config opkg install perlbase-errno opkg install perlbase-essential opkg install perlbase-fcntl opkg install perlbase-file opkg install perlbase-hostname opkg install perlbase-io opkg install perlbase-posix opkg install perlbase-selectsaver opkg install perlbase-socket opkg install perlbase-symbol opkg install perlbase-sys opkg install perlbase-tie opkg install perlbase-xsloader opkg install coreutils-nohup opkg install perlbase-getopt Install procedure ----------------- Step 1 - Get the latest package and copy to /tmp, you can get the latest package at: http://sourceforge.net/projects/pandora/files/Pandora%20FMS%203.2/Stable%20release/Unix%20%28Tarball%29/pandorafms_agent_unix-3.2.tar.gz/download Note: You will get a special version of the launcher, you can get it from our SVN repository and replace the perl daemon launcher with this special version for OpenWRT. Just replace it after do the package install for the Unix/Perl generic agent. Step 2 - Install it cd /tmp tar xvzf pandorafms_agent_unix-3.2.tar.gz cd unix ./pandora_agent --install Step 3 - Create the startup link to run pandora agent when device restarts ln -s /etc/init.d/pandora_agent_daemon /etc/rc.d/S99pandora_agent Step 4 - Customize the agent name and server_ip for this device vi /etc/pandora/pandora_agent.conf Alter line "agent_name" for the devicename you want Step 5 - Start it manually: /etc/init.d/pandora_agent_daemon start unix/AIX/0000755000000000001440000000000012166524015011351 5ustar rootusersunix/AIX/pandora_agent.conf0000644000000000000000000001006412166524015014634 0ustar rootroot# Base config file for Pandora FMS agents # Version 4.1, AIX version # Licensed under GPL license v2, # Copyright (c) 2003-2010 Artica Soluciones Tecnologicas # http://www.pandorafms.com # General Parameters # ================== server_ip localhost server_path /var/spool/pandora/data_in temporal /tmp logfile /var/log/pandora/pandora_agent.log # Interval in seconds, 300 by default interval 300 # Debug mode only generate XML, and stop after first execution, # and does not copy XML to server. debug 0 # By default, agent takes machine name #agent_name xxxxxx # Agent description #description Demo agent # Group assigned for this agent (descriptive, p.e: Servers) #group Servers # Autotime: Enforce to server to ignore timestamp coming from this # agent, used when agents has no timer or it's inestable. 1 to enable # this feature # autotime 1 # Timezone offset: Difference with the server timezone #timezone_offset 0 # Agent position paramters # Those parameters define the geographical position of the agent # latitude #latitude 0 # longitude #longitude 0 # altitude #altitude 0 # By default agent try to take default encoding defined in host. # encoding UTF-8 # Listening TCP port for remote server. By default is 41121 (for tentacle) # if you want to use SSH use 22, and FTP uses 21. server_port 41121 # Transfer mode: tentacle, ftp, ssh or local transfer_mode tentacle # Server password (Tentacle or FTP). Leave empty for no password (default). # server_pwd mypassword # Set to yes/no to enable/disable OpenSSL support for Tentacle (disabled by default). # server_ssl no # Extra options for the Tentacle client (for example, server_opts "-v -r 5"). # server_opts # delayed_startup defines number of seconds before start execution # for first time when startup Pandora FMS Agent # delayed_startup 10 # Pandora nice defines priority of execution. Less priority means more intensive execution # A recommended value is 10. 0 priority means no Pandora CPU protection enabled (default) # pandora_nice 0 # Cron mode replace Pandora FMS own task schedule each XX interval seconds by the use # of old style cron. You should add to crontab Pandora FMS agent script to use this mode. # This is disabled by default, and is not recommended. Use Pandora FMS internal scheduler # is much more safe. # cron_mode # If set to 1 allows the agent to be configured via the web console (Only Enterprise version) # remote_config 1 # If set to 1 start Drone Agent's Proxy Mode # proxy_mode 1 # Max number of simmultaneus connection for proxy (by default 10) # proxy_max_connection 10 # Proxy timeout (by default 1s) # proxy_timeout 1 # User the agent will run as #pandora_user root # Secondary server configuration # ============================== # If secondary_mode is set to on_error, data files are copied to the secondary # server only if the primary server fails. If set to always, data files are # always copied to the secondary server. # secondary_mode on_error # secondary_server_ip localhost # secondary_server_path /var/spool/pandora/data_in # secondary_server_port 41121 # secondary_transfer_mode tentacle # secondary_server_pwd mypassword # secondary_server_ssl no # secondary_server_opts # Module Definition # ================= # System information module_begin module_name disk_root_free module_type generic_data module_exec df -k / | tail -1 | awk '{ print 100-$4 }' module_max 100 module_min 0 module_description Free disk Percentage of root partition module_end module_begin module_name proctotal module_type generic_data module_exec ps aux | wc -l | awk '{ print $1 }' module_end # Process information module_begin module_name InetdDaemon module_type generic_proc module_exec ps -Af | grep inetd | grep -v "grep" | wc -l | awk '{ print $1 }' module_end # Async data example module_begin module_name LastLogin module_type async_string module_exec last | head -1 module_end module_begin module_name Pandora_Agent_RAM module_type generic_data module_exec ps axu | grep perl | grep -v grep | awk '{ print $4 }' | tr "," "." module_end module_plugin grep_log /var/adm/syslog Syslog . unix/README0000644000000000001440000000341711673617616011631 0ustar rootusersPandora FMS : The Flexible Monitoring System ============================================ http://www.pandorafms.org How to install -------------- Run this command to see available options: ./pandora_agent_installer What is Pandora FMS? -------------------- Pandora FMS is a monitoring application to watch systems and applications. Pandora FMS allows to know the status of any element of your bussiness systems. Pandora FMS watches your hardware, your software, your multilayer system and, of course, your Operating System. Pandora FMS can detect a network interface down or the movement of any NASDAQ new technology market value. If you wish, Pandora FMS can send a SMS message when your system or your application fails... or when Google stock value drops below 330 US$. Pandora FMS will adjust, like an octopus, to your systems and requirements, because it has been designed to be open, modular, multiplattform and easy to customize. Pandora FMS is developed for system administrators. About the generic Unix agent ---------------------------- This agent is build on Perl and needs the following minimal requisites: PERL version 5.8 or higher. By default this minimum OS has all the requisites to run "standalone": - Linux: Redhat 6, SUSE 5, Debian 2.x and any distro with Perl 5.6 - IBM AIX: 5.1 - Hewlett Packard HPUX: 11.10 or higher. 11.0 comes with Perl 4.0 :( - Sun Solaris: 2.9. With 2.8 you can install BlastWare Perl 5.8 package, see more information in our FAQ about how to install Blashware packages. - Other Unix: TRU, IRIX, etc not tested, if you want to port the agent to this unixes, please contact with us, we'll glad to port them !!! License ------- The project is distributed under the GPL License v2 or later. Copyright (C) 2004-2011 Pandora FMS development team unix/tentacle_client0000755000000000000000000005166112007324574013637 0ustar rootroot#!/usr/bin/perl ################################################################################ # # Copyright (c) 2007-2008 Ramon Novoa # Copyright (c) 2007-2008 Artica Soluciones Tecnologicas S.L. # # tentacle_client.pl Tentacle Client. See http://www.openideas.info/wiki for # protocol description. # # This program 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; version 2 of the License. # # This program 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. # ################################################################################ package tentacle::client; =head1 NAME tentacle_client - Tentacle Client =head1 VERSION Version 0.3.0 =head1 USAGE tentacle_client [options] [file] [file] ... =head1 DESCRIPTION B is a client for B, a B file transfer protocol that aims to be: =over =item * Secure by design. =item * Easy to use. =item * Versatile and cross-platform. =back Tentacle was created to replace more complex tools like SCP and FTP for simple file transfer/retrieval, and switch from authentication mechanisms like .netrc, interactive logins and SSH keys to X.509 certificates. Simple password authentication over a SSL secured connection is supported too. The client and server (B) are designed to be run from the command line or called from a shell script, and B. =cut use strict; use File::Basename; use Getopt::Std; use IO::Select; use IO::Socket::INET; # Program version our $VERSION = '0.3.0'; # Server address my $t_address = '127.0.0.1'; # Block size for socket read/write operations in bytes my $t_block_size = 1024; # Log messages, 1 enabled, 0 disabled my $t_log = 0; # Server port my $t_port = 41121; # Do not output error messages, 1 enabled, 0 disabled my $t_quiet = 0; # Proxy address my $t_proxy_address = ''; # Proxy user my $t_proxy_user = ''; # Proxy password my $t_proxy_pass = ''; # Proxy port my $t_proxy_port = 0; # Server password my $t_pwd = ''; # Receive mode, 1 enabled, 0 disabled my $t_recv = 0; # Retries for socket read/write operations my $t_retries = 3; # Select handler my $t_select; # Server socket my $t_socket; # Use SSL, 1 true, 0 false my $t_ssl = 0; # SSL ca certificate file my $t_ssl_ca = ''; # SSL certificate file my $t_ssl_cert = ''; # SSL private key file my $t_ssl_key = ''; # SSL private key file password my $t_ssl_pwd = ''; # Timeout for socket read/write operations in seconds my $t_timeout = 1; ################################################################################ ## SUB print_help ## Print help screen. ################################################################################ sub print_help { print ("Usage: $0 [options] [file] [file] ...\n\n"); print ("Tentacle client v$VERSION. See http://www.openideas.info/wiki for protocol description.\n\n"); print ("Options:\n"); print ("\t-a address\tServer address (default $t_address).\n"); print ("\t-c\t\tEnable SSL without a client certificate.\n"); print ("\t-e cert\t\tOpenSSL certificate file. Enables SSL.\n"); print ("\t-f ca\t\tVerify that the peer certificate is signed by a ca.\n"); print ("\t-g\t\tGet files from the server.\n"); print ("\t-h\t\tShow help.\n"); print ("\t-k key\t\tOpenSSL private key file.\n"); print ("\t-p port\t\tServer port (default $t_port).\n"); print ("\t-q\t\tQuiet. Do now print error messages.\n"); print ("\t-r number\tNumber of retries for network operations (default $t_retries).\n"); print ("\t-t time\t\tTime-out for network operations in seconds (default ${t_timeout}s).\n"); print ("\t-v\t\tBe verbose.\n"); print ("\t-w\t\tPrompt for OpenSSL private key password.\n"); print ("\t-x pwd\t\tServer password.\n"); print ("\t-y proxy\tProxy server string (user:password\@address:port).\n\n"); } ################################################################################ ## SUB parse_options ## Parse command line options and initialize global variables. ################################################################################ sub parse_options { my %opts; my $tmp; # Get options if (getopts ('a:ce:f:ghk:p:qr:t:vwx:y:', \%opts) == 0 || defined ($opts{'h'})) { print_help (); exit 1; } # Address if (defined ($opts{'a'})) { $t_address = $opts{'a'}; if ($t_address !~ /^[a-zA-Z\.][a-zA-Z0-9\.\-]+$/ && ($t_address !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ || $1 < 0 || $1 > 255 || $2 < 0 || $2 > 255 || $3 < 0 || $3 > 255 || $4 < 0 || $4 > 255)) { error ("Address $t_address is not valid."); } } # Enable SSL without a client certificate if (defined ($opts{'c'})) { require IO::Socket::SSL; $t_ssl = 1; } # Enable SSL if (defined ($opts{'e'})) { if (defined ($opts{'c'})) { error ("Flags -c and -e can not be used at the same time."); } require IO::Socket::SSL; $t_ssl_cert = $opts{'e'}; if (! -f $t_ssl_cert) { error ("File $t_ssl_cert does not exist."); } $t_ssl = 1; } # Verify peer certificate if (defined ($opts{'f'})) { if (! defined ($opts{'e'})) { error ("Flag -e must be set to enable peer certificate verify."); } $t_ssl_ca = $opts{'f'}; if (! -f $t_ssl_ca) { error ("File $t_ssl_ca does not exist."); } } # Get files if (defined ($opts{'g'})) { $t_recv = 1; } # SSL private key file if (defined ($opts{'k'})) { if (! defined ($opts{'e'})) { error ("Flag -e must be set to use a private key file."); } $t_ssl_key = $opts{'k'}; if (! -f $t_ssl_key) { error ("File $t_ssl_key does not exist."); } } # Port if (defined ($opts{'p'})) { $t_port = $opts{'p'}; if ($t_port !~ /^\d+$/ || $t_port < 1 || $t_port > 65535) { error ("Port $t_port is not valid."); } } # Quiet mode if (defined ($opts{'q'})) { $t_quiet = 1; } # Retries if (defined ($opts{'r'})) { $t_retries = $opts{'r'}; if ($t_retries !~ /^\d+$/ || $t_retries < 1) { error ("Invalid number of retries for network operations."); } } # Timeout if (defined ($opts{'t'})) { $t_timeout = $opts{'t'}; if ($t_timeout !~ /^\d+$/ || $t_timeout < 1) { error ("Invalid timeout for network operations."); } } # Be verbose if (defined ($opts{'v'})) { $t_log = 1; } # SSL private key password if (defined ($opts{'w'})) { if (! defined ($opts{'e'})) { error ("Flag -k must be set to provide a private key password."); } $t_ssl_pwd = ask_passwd ("Enter private key file password: ", "Enter private key file password again for confirmation: "); } # Server password if (defined ($opts{'x'})) { $t_pwd = $opts{'x'}; } # Proxy server if (defined ($opts{'y'})) { if ($opts{'y'} !~ /^((.*):(.*)@){0,1}(\S+):(\d+)$/) { error ("Invalid proxy string: " . $opts{'y'}); } ($t_proxy_user, $t_proxy_pass, $t_proxy_address, $t_proxy_port) = ($2, $3, $4, $5); $t_proxy_user = '' unless defined ($t_proxy_user); $t_proxy_pass = '' unless defined ($t_proxy_pass); if ($t_proxy_port < 1 || $t_proxy_port > 65535) { error ("Proxy port $t_proxy_port is not valid."); } } } ################################################################################ ## SUB start_client ## Open the server socket. ################################################################################ sub start_client { # Connect to server $t_socket = IO::Socket::INET->new ( PeerAddr => $t_address, PeerPort => $t_port, Type => SOCK_STREAM ); if (! defined ($t_socket)) { error ("Cannot connect to $t_address on port $t_port: $!."); } # Add server socket to select queue $t_select = IO::Select->new (); $t_select->add ($t_socket); print_log ("Connected to $t_address port $t_port"); } ################################################################################ ## SUB start_client_proxy ## Open the server socket. Connects to the Tentacle server through an HTTP proxy. ################################################################################ sub start_client_proxy { # Connect to proxy $t_socket = IO::Socket::INET->new ( PeerAddr => $t_proxy_address, PeerPort => $t_proxy_port, ); if (! defined ($t_socket)) { error ("Cannot connect to proxy server $t_proxy_address on port $t_proxy_port: $!."); } # Add server socket to select queue $t_select = IO::Select->new (); $t_select->add ($t_socket); print_log ("Connected to proxy server $t_proxy_address port $t_proxy_port"); # Try to CONNECT to the Tentacle server send_data ("CONNECT " . $t_address . ":" . $t_port . " HTTP/1.0\r\n"); # Authenticate to the proxy if ($t_proxy_user ne '') { send_data ("Proxy-Authorization: Basic " . base64 ($t_proxy_user . ":" . $t_proxy_pass) . "\r\n"); } send_data ("\r\n"); # Check for an HTTP 200 response my $response = recv_data ($t_block_size); if ($response !~ m/HTTP.* 200 /) { my $error = (split (/\r\n/, $response))[0]; error ("CONNECT error: $error"); } print_log ("Connected to $t_address port $t_port"); } ################################################################################ ## SUB stop_client ## Close the server socket. ################################################################################ sub stop_client { $t_socket->close (); } ################################################################################ ## SUB start_ssl ## Convert the server socket to an IO::Socket::SSL socket. ################################################################################ sub start_ssl { my $err; if ($t_ssl_cert eq ''){ IO::Socket::SSL->start_SSL ( $t_socket, ); } elsif ($t_ssl_ca eq '') { IO::Socket::SSL->start_SSL ( $t_socket, SSL_cert_file => $t_ssl_cert, SSL_key_file => $t_ssl_key, SSL_passwd_cb => sub {return $t_ssl_pwd}, SSL_use_cert =>'1', # No authentication SSL_verify_mode => '0x00', ); } else { IO::Socket::SSL->start_SSL ( $t_socket, SSL_ca_file => $t_ssl_ca, SSL_cert_file => $t_ssl_cert, SSL_key_file => $t_ssl_key, SSL_passwd_cb => sub {return $t_ssl_pwd}, SSL_use_cert =>'1', # Verify peer SSL_verify_mode => '0x01', ); } $err = IO::Socket::SSL::errstr (); if ($err ne '') { error ($err); } } ################################################################################ ## SUB auth_pwd ## Authenticate client with server password. ################################################################################ sub auth_pwd { my $command; my $pwd_digest; require Digest::MD5; $pwd_digest = Digest::MD5::md5 ($t_pwd); $pwd_digest = Digest::MD5::md5_hex ($pwd_digest); send_data ("PASS $pwd_digest\n"); $command = recv_command ($t_block_size); if ($command !~ /^PASS OK$/) { error ("Authentication failed."); } } ################################################################################ ## SUB base64 ## Returns the base 64 encoding of a string. ################################################################################ my @alphabet = ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'); sub base64 { my $str = shift; my $str64; # Pre-processing my $msg = unpack ("B*", pack ("A*", $str)); my $bit_len = length ($msg); # Process the message in successive 24-bit chunks for (my $i = 0; $i < $bit_len; $i += 24) { my $chunk_len = length (substr ($msg, $i, 24)); $str64 .= $alphabet[ord (pack ("B8", "00" . substr ($msg, $i, 6)))]; $str64 .= $alphabet[ord (pack ("B8", "00" . substr ($msg, $i+6, 6)))]; $str64 .= ($chunk_len <= 12) ? "=" : $alphabet[ord (pack ("B8", "00" . substr ($msg, $i+12, 6)))]; $str64 .= ($chunk_len <= 18) ? "=" : $alphabet[ord (pack ("B8", "00" . substr ($msg, $i+18, 6)))]; } return $str64; } ################################################################################ ## SUB recv_file ## Receive a file from the server ################################################################################ sub recv_file { my $data = ''; my $file = $_[0]; my $response; my $size; # Request file send_data ("RECV <$file>\n"); # Wait for server response $response = recv_command (); if ($response !~ /^RECV SIZE (\d+)$/) { error ("Server responded $response."); } $size = $1; send_data ("RECV OK\n"); # Receive file $data = recv_data_block ($size); # Write it to disk open (FILE, "> $file") || error ("Cannot open file '$file' for writing."); binmode (FILE); print (FILE $data); close (FILE); print_log ("Received file '$file'"); } ################################################################################ ## SUB send_file ## Send a file to the server ################################################################################ sub send_file { my $base_name; my $data = ''; my $response = ''; my $retries; my $file = $_[0]; my $size; my $written; $base_name = basename ($file); $size = -s $file; # Request to send file send_data ("SEND <$base_name> SIZE $size\n"); print_log ("Request to send file '$base_name' size ${size}b"); # Wait for server response $response = recv_command (); # Server rejected the file if ($response ne "SEND OK") { send_data ("QUIT\n"); error ("Server responded $response."); } print_log ("Server responded SEND OK"); # Send the file open (FILE, $file) || error ("Cannot open file '$file' for reading."); binmode (FILE); while ($data = ) { send_data ($data); } close (FILE); # Wait for server response $response = recv_command (); if ($response ne "SEND OK") { send_data ("QUIT\n"); error ("Server responded $response."); } print_log ("File sent"); } ################################################################################ # Common functions ################################################################################ ################################################################################ ## SUB print_log ## Print log messages. ################################################################################ sub print_log { if ($t_log == 1) { print (STDOUT "[log] $_[0]\n"); } } ################################################################################ ## SUB error ## Print an error and exit the program. ################################################################################ sub error { if ($t_quiet == 0) { print (STDERR "[err] $_[0]\n"); } exit 1; } ################################################################################ ## SUB recv_data ## Read data from the client socket. Returns the number of bytes read and the ## string of bytes as a two element array. ################################################################################ sub recv_data { my $data; my $read; my $retries = 0; my $size = $_[0]; while (1) { # Try to read data from the socket if ($t_select->can_read ($t_timeout)) { # Read at most $size bytes $read = sysread ($t_socket, $data, $size); # Read error if (! defined ($read)) { error ("Read error from " . $t_socket->sockhost () . ": $!."); } # EOF if ($read == 0) { error ("Connection from " . $t_socket->sockhost () . " unexpectedly closed."); } return ($read, $data); } # Retry $retries++; # But check for error conditions first if ($retries > $t_retries) { error ("Connection from " . $t_socket->sockhost () . " timed out."); } } } ################################################################################ ## SUB send_data ## Write data to the client socket. ################################################################################ sub send_data { my $data = $_[0]; my $retries = 0; my $size; my $total = 0; my $written; $size = length ($data); while (1) { # Try to write data to the socket if ($t_select->can_write ($t_timeout)) { $written = syswrite ($t_socket, $data, $size - $total, $total); # Read error if (! defined ($written)) { error ("Connection error from " . $t_socket->sockhost () . ": $!."); } # EOF if ($written == 0) { error ("Connection from " . $t_socket->sockhost () . " unexpectedly closed."); } $total += $written; # All data was written if ($total == $size) { return; } # Retry } else { $retries++; if ($retries > $t_retries) { error ("Connection from " . $t_socket->sockhost () . " timed out."); } } } } ################################################################################ ## SUB recv_command ## Read a command from the client, ended by a new line character. ################################################################################ sub recv_command { my $buffer; my $char; my $command = ''; my $read; my $total = 0; while (1) { ($read, $buffer) = recv_data ($t_block_size); $command .= $buffer; $total += $read; # Check if the command is complete $char = chop ($command); if ($char eq "\n") { return $command; } $command .= $char; # Avoid overflow if ($total > $t_block_size) { error ("Received too much data from " . $t_socket->sockhost ()); } } } ################################################################################ ## SUB recv_data_block ## Read $_[0] bytes of data from the client. ################################################################################ sub recv_data_block { my $buffer = ''; my $data = ''; my $read; my $size = $_[0]; my $total = 0; while (1) { ($read, $buffer) = recv_data ($size - $total); $data .= $buffer; $total += $read; # Check if all data has been read if ($total == $size) { return $data; } } } ################################################################################ ## SUB ask_passwd ## Asks the user for a password. ################################################################################ sub ask_passwd { my $msg1 = $_[0]; my $msg2 = $_[1]; my $pwd1; my $pwd2; require Term::ReadKey; # Disable keyboard echo Term::ReadKey::ReadMode('noecho'); # Promt for password print ($msg1); $pwd1 = Term::ReadKey::ReadLine(0); print ("\n$msg2"); $pwd2 = Term::ReadKey::ReadLine(0); print ("\n"); # Restore original settings Term::ReadKey::ReadMode('restore'); if ($pwd1 ne $pwd2) { # Call print to bypass quiet mode. print ("[err] Passwords do not match.\n"); exit 1; } # Remove the trailing new line character chop $pwd1; return $pwd1; } ################################################################################ # Main ################################################################################ my $file; # Parse command line options parse_options (); # Check command line arguments if ($t_recv == 0 && $#ARGV == -1) { error ("No files to send."); } # Connect to the server if ($t_proxy_address eq '') { start_client (); } else { start_client_proxy (); } # Start SSL if ($t_ssl == 1) { start_ssl (); } # Authenticate with server if ($t_pwd ne '') { auth_pwd (); } if ($t_recv == 0) { # Check that all files exist before trying to send them foreach $file (@ARGV) { if (! -f $file) { error ("File '$file' does not exist."); } } # Send the files foreach $file (@ARGV) { send_file ($file); } } else { # Send the files foreach $file (@ARGV) { recv_file ($file); } } # Tell the server that we are finished send_data ("QUIT\n"); stop_client (); exit 0; __END__ =head1 OPTIONS =over =item I<-a address> B (default 127.0.0.1). =item I<-c> Enable B without a client certificate. =item I<-e cert> B file. Enables SSL. =item I<-f ca> Verify that the peer certificate is signed by a B (Certificate Authority). =item I<-g> B files from the server. =item I<-h> Show B. =item I<-k key> B file. =item I<-p port> B (default I<41121>). =item I<-q> B. Do now print error messages. =item I<-r number> B for network operations (default I<3>). =item I<-t time> B for network operations in seconds (default I<1s>). =item I<-v> Be B. =item I<-w> Prompt for B. =item I<-x pwd> B. =back =head1 EXIT STATUS =over =item 0 on Success =item 1 on Error =back =head1 CONFIGURATION Tentacle doesn't use any configurationf files, all the configuration is done by the options passed when it's started. =head1 DEPENDENCIES L, L, L, L =head1 LICENSE This is released under the GNU Lesser General Public License. =head1 SEE ALSO L, L, L, L Protocol description and more info at: L<< http://openideas.info/wiki/index.php?title=Tentacle >> =head1 COPYRIGHT Copyright (c) 2005-2010 Artica Soluciones Tecnologicas S.L =cut unix/pandora_agent0000644000000000000000000017001212166524015013267 0ustar rootroot#!/usr/bin/perl # ********************************************************************** # Pandora FMS Generic Unix/Perl Agent # (c) 2009-2013 Artica Soluciones Tecnológicas # with the help of many people. Please see http://pandorafms.org # This code is licensed under GPL 2.0 license. # ********************************************************************** =head1 NAME pandora_agent - Pandora FMS Agent =head1 VERSION Version 4.0.3 =head1 USAGE << pandora_agent F >> =cut use strict; use warnings; use POSIX qw(strftime floor); use Sys::Hostname; use File::Basename; use File::Copy; use IO::Socket; # Agent XML data my $Xml; # Semaphore used to acces $Xml my $Sem = undef; # Semaphore used to control the number of threads my $ThreadSem = undef; use constant AGENT_VERSION => '4.1'; use constant AGENT_BUILD => '130708'; # Commands to retrieve total memory information in kB use constant TOTALMEMORY_CMDS => { linux => 'cat /proc/meminfo | grep MemTotal: | awk \'{ print $2 }\'', solaris => '/usr/sbin/prtconf | awk \'/Memory/ { print $3 * 1024 }\'', hpux => 'swapinfo -t | grep memory | awk \'{print $2}\'', freebsd => '/sbin/sysctl hw.physmem | awk \'{print $2 / 1024}\'', }; # Commands to retrieve free memory information in kB use constant FREEMEMORY_CMDS => { linux => 'cat /proc/meminfo | grep MemFree: | awk \'{ print $2 }\'', solaris => 'vmstat 1 2 | tail -1 | awk \'{ print $5 }\'', hpux => 'swapinfo -t | grep memory | awk \'{print $4}\'', freebsd => '/sbin/sysctl -n vm.stats.vm.v_page_size vm.stats.vm.v_free_count | tr "\n" " " | awk \'{ print $1 * $2 / 1024 }\'', }; # Commands to retrieve cpu information use constant CPUUSAGE_CMDS => { linux => 'vmstat 1 2 | tail -1 | awk \'{ print $13 }\'', solaris => 'vmstat 1 2 | tail -1 | awk \'{ print $21 }\'', hpux => 'vmstat 1 2 | tail -1 | awk \'{ print $16 }\'', freebsd => 'vmstat -n 0 1 2 | tail -1 | awk \'{ print $15 }\'' }; # Commands to retrieve process information use constant PROC_CMDS => { # cpu usage, memory usage, command name linux => 'ps aux | awk \'NR > 1 {ps = ""; for (i = 11; i <= NF; ++i) {ps = (ps " " $i) }; print $3, $6, ps}\'', solaris => 'prstat 1 1 | awk \'NR > 1 {split ($10, ps, "/"); cpu = substr ($9, 1, length ($9) - 1); mem = substr ($3, 1, length ($3) - 1); print cpu, mem, ps[1]}\'', hpux => 'ps -elf | awk \'NR > 1 {ps = ""; for (i = 15; i <= NF; ++i) {ps = (ps " " $i) }; print 0, $10, ps}\'', aix => 'ps aux | awk \'NR > 1 {print $3, $6, $11}\'', freebsd => 'ps axww -o %cpu= -o %mem= -o command= | sed -e "s/^ *//"', }; # Commands to retrieve partition information in kB use constant PART_CMDS => { # total, available, mount point linux => 'df -P | awk \'NR > 1 {print $2, $4, $6}\'', solaris => 'df -k | awk \'NR > 1 {print $2, $4, $6}\'', hpux => 'df -P | awk \'NR > 1 {print $2, $4, $6}\'', aix => 'df -kP | awk \'NR > 1 {print $2, $4, $6}\'', freebsd => 'df -k | awk \'NR > 1 {print $2, $4, $6}\'' }; # Commands to call df with POSIX output format use constant DF_CMDS => { # total, available, mount point linux => 'df -P', solaris => 'df -k', hpux => 'df -P', aix => 'df -kP', freebsd => 'df -k' }; # OS and OS version my $OS = $^O; my $OS_VERSION; # Used to calculate the MD5 checksum of a string use constant MOD232 => 2**32; # Directory where pandora_agent.conf is located my $ConfDir = ''; # Pandora FMS agent configuration file my $ConfFile = 'pandora_agent.conf'; # Broker agent configuration files my @BrokerPid; # Configuration tokens my %Conf = ( 'server_ip' => 'localhost', 'server_path' => '/var/spool/pandora/data_in', 'logfile' =>'/var/log/pandora/pandora_agent.log', 'temporal' => '/var/spool/pandora', 'interval' => 300, 'debug' => 0, 'agent_name' => hostname (), 'description' => '', 'group' => '', 'encoding' => 'UTF-8', 'server_port' => 41121, 'transfer_mode' => 'tentacle', 'server_pwd' => '', 'server_ssl' => 'no', 'server_opts' => '', 'delayed_startup' => 0, 'pandora_nice' => 10, 'cron_mode' => 0, 'remote_config' => 0, 'secondary_mode' => 'never', 'secondary_server_ip' => 'localhost', 'secondary_server_path' => '/var/spool/pandora/data_in', 'secondary_server_port' => 41121, 'secondary_transfer_mode' => 'tentacle', 'secondary_server_pwd' => '', 'secondary_server_ssl' => 'no', 'secondary_server_opts' => '', 'autotime' => 0, 'temporal_min_size' => 1, 'timezone_offset' => 0, 'pandora_exec' => 'pandora_agent_exec', 'agent_threads' => 1, 'udp_server_port' => 41122, 'udp_server_auth_address' => '0.0.0.0', 'udp_server' => 0, 'proxy_mode' => 0, 'proxy_max_connection' => 10, 'proxy_timeout' => 1, 'xml_buffer' => 0, ); # Modules my @Modules; # Plugins my @Plugins; # Logfile file handle my $LogFileFH; # Agent name MD5; my $AgentMD5; # Remote configuration file name my $RemoteConfFile; # Remote md5 file name my $RemoteMD5File; # Process data my %Procs = ( '__utimestamp__' => 0 ); # Partition data my %Parts = ( '__utimestamp__' => 0 ); # Collections my %Collections; # $DevNull my $DevNull = '/dev/null'; # Shell command separator my $CmdSep = ';'; # PID of tentacle proxy, used in proxy mode my $tentacle_pid = undef; ################################################################################ # Print usage information and exit. ################################################################################ sub print_usage () { print "\nUsage: $0 \n\n"; print "\tPandora home is the directory where pandora_agent.conf is located,\n"; print "\tby default /etc/pandora.\n\n"; exit 1; } ################################################################################ # Print an error message and exit. ################################################################################ sub error ($) { my $msg = shift; print ("[ERROR] $msg\n\n"); `logger -i -t pandora_agent_daemon [ERROR] $msg 2>/dev/null`; exit 1; } ################################################################################ # Check a regular expression. Returns 1 if its valid, 0 otherwise. ################################################################################ sub valid_regexp ($) { my $regexp = shift; eval { '' =~ /$regexp/; }; # Something went wrong return 0 if ($@); return 1; } ################################################################################ # Recursively delete files and directories. ################################################################################ sub rmrf { my $path = shift; local *DIR; if (-d $path) { opendir (DIR, $path) || return; while (defined (my $file_name = readdir(DIR))) { next if ($file_name eq '.' || $file_name eq '..'); rmrf ("$path/$file_name"); } closedir (DIR); rmdir ($path); } else { unlink ($path); } } ################################################################################ # Recursively set file permissions. ################################################################################ sub chmodr { my ($perm, $path) = @_; local *DIR; if (-d $path) { opendir (DIR, $path) || return; while (defined (my $file_name = readdir(DIR))) { next if ($file_name eq '.' || $file_name eq '..'); chmodr ($perm, "$path/$file_name"); } closedir (DIR); } chmod ($perm, $path); } ################################################################################ # Open the agent logfile and start logging. ################################################################################ sub start_log (;$) { my $quiet = shift; # Get the logfile my $log_file_name = read_config ('logfile'); $log_file_name = '/var/log/pandora/pandora_agent.log' unless defined ($log_file_name); # Open it open ($LogFileFH, "> $log_file_name") or error ("Could not open log file '$log_file_name' for writing: $!."); if (! defined ($quiet)) { print "Logging to $log_file_name\n"; } } ################################################################################ # Close the agent logfile and stop logging. ################################################################################ sub stop_log () { close ($LogFileFH); } ################################################################################ # Log a message to the agent logfile. ################################################################################ sub log_message ($$;$) { my ($source, $msg, $dest) = @_; if (defined ($dest)) { print $dest strftime ('%Y/%m/%d %H:%M:%S', localtime ()) . " - [$source] - $msg\n"; } else { #Trying to write into log file to test its writable syswrite ($LogFileFH, ""); #If no error, the file is writable if (!$!) { print $LogFileFH strftime ('%Y/%m/%d %H:%M:%S', localtime ()) . " - [$source] - $msg\n"; } else { #If error then log into syslog! `logger -i -t pandora_agent_daemon [ERROR] $msg 2>/dev/null`; } } } ################################################################################ # Parse configuration file (modules, plugins and collections) ################################################################################ sub parse_conf_modules($) { my ($param) = @_; my $module; foreach my $line (@{$param}) { next if ($line =~ m/^\s*#/) or ($line =~ m/^\s*$/); # Module definition if ($line =~ /^\s*module_begin\s*$/) { $module = { 'name' => '', 'type' => 'generic_data', 'description' => '', 'func' => 0, 'params' => '', 'description' => '', 'interval' => 1, 'timeout' => 0, 'counter' => 0, 'max' => undef, 'min' => undef, 'post_process' => undef, 'min_critical' => undef, 'max_critical' => undef, 'min_warning' => undef, 'max_warning' => undef, 'disabled' => undef, 'min_ff_event' => undef, 'save' => '', 'conditions' => [], 'cron' => '', 'cron_utimestamp' => 0, 'cron_interval' => -1, 'precondition' => [], 'precon'=> 0 }; } elsif ($line =~ /^\s*module_name\s+(.+)$/) { $module->{'name'} = $1; } elsif ($line =~ /^\s*module_description\s+(.+)$/) { $module->{'description'} = $1; } elsif ($line =~ /^\s*module_type\s+(\S+)\s*$/) { $module->{'type'} = $1; }elsif ($line =~ /^\s*module_precondition\s+(.*)$/) { my $action = $1; $module->{'precon'} = 1; # Numeric comparison if ($action =~ /^\s*([<>!=]+)\s+(\d+(?:\.\d*)?)\s+(.*)$/) { push (@{$module->{'precondition'}}, {'operator' => $1, 'value_1' => $2, 'command' => $3}); # Interval } elsif ($action =~ /^\s*[(]\s*(\d+(?:\.\d*)?)\s*,\s*(\d+(?:\.\d*)?)\s*[)]\s+(.*)$/) { push (@{$module->{'precondition'}}, {'operator' => '()', 'value_1' => $1, 'value_2' => $2, 'command' => $3}); # Regular expression } elsif ($action =~ /^\s*=~\s+(\S*)\s+(.*)$/) { if (valid_regexp ($1)) { push (@{$module->{'precondition'}}, {'operator' => '=~', 'value_1' => $1, 'command' => $2}); } else { log_message ('setup', "Invalid regular expression in module precondition: $line"); } } } elsif ($line =~ /^\s*module_exec\s+(.+)$/) { $module->{'func'} = \&module_exec; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_cpuusage\s+(.*)$/) { $module->{'func'} = \&module_cpuusage; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_freememory\s+(.*)$/) { $module->{'func'} = \&module_freememory; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_freepercentmemory\s+(.*)$/) { $module->{'func'} = \&module_freepercentmemory; $module->{'params'} = $1; } elsif ($line =~ /^\s*(module_proc|module_service)\s+(.+)$/) { $module->{'func'} = \&module_proc; $module->{'params'} = $2; } elsif ($line =~ /^\s*module_cpuproc\s+(.+)$/) { $module->{'func'} = \&module_cpuproc; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_memproc\s+(.+)$/) { $module->{'func'} = \&module_memproc; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_freedisk\s+(.*)$/) { $module->{'func'} = \&module_freedisk; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_freepercentdisk\s+(.*)$/) { $module->{'func'} = \&module_freepercentdisk; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_occupiedpercentdisk\s+(.*)$/) { $module->{'func'} = \&module_occupiedpercentdisk; $module->{'params'} = $1; } elsif ($line =~ /^\s*module_max\s+(.*)\s*$/) { $module->{'max'} = $1; } elsif ($line =~ /^\s*module_min\s+(.*)\s*$/) { $module->{'min'} = $1; } elsif ($line =~ /^\s*module_postprocess\s+(.*)\s*$/) { $module->{'post_process'} = $1; } elsif ($line =~ /^\s*module_interval\s+(\d+)\s*$/) { $module->{'interval'} = $1; # Make the module run the first time $module->{'counter'} = $1; } elsif ($line =~ /^\s*module_timeout\s+(\d+)\s*$/) { $module->{'timeout'} = $1; } elsif ($line =~ /^\s*module_save\s+(\w+)$/) { $module->{'save'} = $1; } elsif ($line =~ /^\s*module_condition\s+(.*)$/) { my $action = $1; # Numeric comparison if ($action =~ /^\s*([<>!=]+)\s+(\d+(?:\.\d*)?)\s+(.*)$/) { push (@{$module->{'conditions'}}, {'operator' => $1, 'value_1' => $2, 'command' => $3}); # Interval } elsif ($action =~ /^\s*[(]\s*(\d+(?:\.\d*)?)\s*,\s*(\d+(?:\.\d*)?)\s*[)]\s+(.*)$/) { push (@{$module->{'conditions'}}, {'operator' => '()', 'value_1' => $1, 'value_2' => $2, 'command' => $3}); # Regular expression } elsif ($action =~ /^\s*=~\s+(\S*)\s+(.*)$/) { if (valid_regexp ($1)) { push (@{$module->{'conditions'}}, {'operator' => '=~', 'value_1' => $1, 'command' => $2}); } else { log_message ('setup', "Invalid regular expression in module condition: $line"); } } } elsif ($line =~ /^\s*module_crontab\s+(((\*|(\d+(-\d+){0,1}))\s*){5}).*$/) { $module->{'cron'} = $1; } elsif ($line =~ /^\s*module_cron_interval\s+(\d+).*$/) { $module->{'cron_interval'} = $1; } elsif ($line =~ /^\s*module_end\s*$/) { next unless ($module->{'name'} ne '') and ($module->{'func'} != 0); push (@Modules, $module); # Plugin } elsif ($line =~ /^\s*module_plugin\s+(.+)$/) { push (@Plugins, $1); # Module proc command redefinition } elsif ($line =~ /^\s*module_proc_cmd\s+(.+)$/) { PROC_CMDS->{$OS} = $1; # Module freedisk command redefinition } elsif ($line =~ /^\s*module_freedisk_cmd\s+(.+)$/) { PART_CMDS->{$OS} = $1; # Collection } elsif ($line =~ /^\s*file_collection\s+(.+)$/) { my $collection = $1; # Prevent path traversal attacks if ($collection !~ m/(\.\.)|\//) { $Collections{$collection} = 0; } # Min critical } elsif ($line =~ /^\s*module_min_critical\s+(.*)\s*$/) { $module->{'min_critical'} = $1; # Max critical } elsif ($line =~ /^\s*module_max_critical\s+(.*)\s*$/) { $module->{'max_critical'} = $1; # Min warning } elsif ($line =~ /^\s*module_min_warning\s+(.*)\s*$/) { $module->{'min_warning'} = $1; # Max warning } elsif ($line =~ /^\s*module_max_warning\s+(.*)\s*$/) { $module->{'max_warning'} = $1; # Disabled } elsif ($line =~ /^\s*module_disabled\s+(.*)\s*$/) { $module->{'disabled'} = $1; # Min ff event } elsif ($line =~ /^\s*module_min_ff_event\s+(.*)\s*$/) { $module->{'min_ff_event'} = $1; } } return; } ################################################################################ # Create configuration file for broker agents. ################################################################################ sub write_broker_conf($){ my ($broker_agent) = @_; my $content = ''; open (CONF_FILE, "$ConfDir/$ConfFile") or error ("Could not open file '$ConfDir/$ConfFile': $!."); open (BROKER_FILE, ">$ConfDir/${broker_agent}.conf") or error ("Could not write configuration file: $!"); while (my $line = ){ # Skip broker definitions if ($line =~ m/^\s*broker_agent/) { next; } # Change the agent name if ($line =~ m/^\s*#*\s*agent_name\s+/) { $line = "agent_name $broker_agent\n"; } # Change the logfile elsif ($line =~ m/^\s*logfile\s+(.*)/) { $line = 'logfile ' . dirname ($1) . "/$broker_agent.log\n"; } print BROKER_FILE $line; } close (BROKER_FILE); close (CONF_FILE); } ################################################################################ # Read configuration file. Exit on error. ################################################################################ sub read_config (;$) { my $token = shift; my @found_tokens; my $module; error ("File '$ConfDir/$ConfFile' not found.") unless (-e "$ConfDir/$ConfFile"); open (CONF_FILE, "$ConfDir/$ConfFile") or error ("Could not open file '$ConfDir/$ConfFile': $!."); my @file = ; close(CONF_FILE); foreach my $line (@file){ # Skip comments and empty lines next if ($line =~ m/^\s*#/) or ($line =~ m/^\s*$/); # Replace CRLF with LF $line =~ s/\r\n/\n/g; # Token search if (defined ($token)) { if ($line =~ /^\s*(\S+)\s+(.*)$/ && $1 eq $token) { # Multiple value token if (wantarray ()) { push (@found_tokens, $2); } # Single value token else { return $2; } } next; } next if ($line =~ /^module\s*\w*/); # Additional configuration file if ($line =~ /^include\s+(.*)\s*/) { log_message ('setup', "include is $1"); $Conf{'include'} = $Conf{'include'} ? "$Conf{'include'} $1" : $1; foreach my $file_name (glob("$1")) { open (FILE, "$file_name") or next; log_message ('setup', "reading $file_name"); my @file_conf = ; parse_conf_modules(\@file_conf); close (FILE); } next; } #Configuration token if ($line =~ /^\s*(\S+)\s+(.*)$/) { log_message ('setup', "$1 is $2"); $Conf{$1} = $2; # Remove trailing spaces $Conf{$1} =~ s/\s*$//; } } # Token search if (defined ($token)) { # Multiple value token if (wantarray ()) { return @found_tokens; } # Single value token not found. return undef; } # Module, plugin and collection definitions parse_conf_modules(\@file); # Update the agent MD5 since agent_name may have changed $AgentMD5 = md5 ($Conf{'agent_name'}); $RemoteConfFile = "$AgentMD5.conf"; $RemoteMD5File = "$AgentMD5.md5"; # Set the maximun number of threads $ThreadSem = Thread::Semaphore->new ($Conf{'agent_threads'}) if defined ($Sem); # Set tentacle client options if ($Conf{'transfer_mode'} eq 'tentacle') { $Conf{'server_opts'} = '-x \'' . $Conf{'server_pwd'} . '\' ' . $Conf{'server_opts'} if ($Conf{'server_pwd'} ne ''); $Conf{'server_opts'} = '-c ' . $Conf{'server_opts'} if ($Conf{'server_ssl'} eq 'yes'); } # Set tentacle client options for secondary server if ($Conf{'secondary_transfer_mode'} eq 'tentacle') { $Conf{'secondary_server_opts'} = '-x \'' . $Conf{'secondary_server_pwd'} . '\' ' . $Conf{'secondary_server_opts'} if ($Conf{'secondary_server_pwd'} ne ''); $Conf{'secondary_server_opts'} = '-c ' . $Conf{'secondary_server_opts'} if ($Conf{'secondary_server_ssl'} eq 'yes'); } } ################################################################################# ## Remove any trailing / from directory names. ################################################################################# sub fix_directory ($) { my $dir = shift; my $char = chop ($dir); return $dir if ($char eq '/'); return $dir . $char; } ################################################################################ # Sends a file to the server. ################################################################################ #sub send_file ($;$) { sub send_file { my ($file, $secondary) = @_; my $output; if ($Conf{'transfer_mode'} eq 'tentacle') { $output = `tentacle_client -v -a $Conf{'server_ip'} -p $Conf{'server_port'} $Conf{'server_opts'} "$file" 2>&1 >$DevNull`; } elsif ($Conf{'transfer_mode'} eq 'ssh') { $output = `scp -P $Conf{'server_port'} "$file" pandora@"$Conf{'server_ip'}:$Conf{'server_path'}" 2>&1 >$DevNull`; } elsif ($Conf{'transfer_mode'} eq 'ftp') { my $base = basename ($file); my $dir = dirname ($file); $output = `ftp -n $Conf{'server_ip'} $Conf{'server_port'} 2>&1 >$DevNull <&1 >$DevNull`; } # Get the errorlevel my $rc = $? >> 8; if ($rc != 0) { log_message ('error', "Error sending file '$file': $output"); } return $rc unless (defined ($secondary)); # Send the file to the secondary server return $rc unless ($Conf{'secondary_mode'} eq 'always' || ($Conf{'secondary_mode'} eq 'on_error' && $rc != 0)); swap_servers (); $rc = send_file ($file); swap_servers (); return $rc; } ################################################################################ # Send buffered XML files. ################################################################################ sub send_buffered_xml_files () { # Read XML files from the temporal directory opendir(TEMPORAL, $Conf{'temporal'}) or return; while (my $xml_file = readdir(TEMPORAL)) { # Skip non data files and symlinks next if ($xml_file !~ m/\.data$/ || -l "$Conf{'temporal'}/$xml_file"); my $rc = send_file ("$Conf{'temporal'}/$xml_file", 1); unlink ("$Conf{'temporal'}/$xml_file") if ($rc == 0); } } ################################################################################ # Swap primary and secondary servers. ################################################################################ sub swap_servers () { ($Conf{'server_ip'}, $Conf{'secondary_server_ip'}) = ($Conf{'secondary_server_ip'}, $Conf{'server_ip'}); ($Conf{'server_path'}, $Conf{'secondary_server_path'}) = ($Conf{'secondary_server_path'}, $Conf{'server_path'}); ($Conf{'server_port'}, $Conf{'secondary_server_port'}) = ($Conf{'secondary_server_port'}, $Conf{'server_port'}); ($Conf{'transfer_mode'}, $Conf{'secondary_transfer_mode'}) = ($Conf{'secondary_transfer_mode'}, $Conf{'transfer_mode'}); ($Conf{'server_pwd'}, $Conf{'secondary_server_pwd'}) = ($Conf{'secondary_server_pwd'}, $Conf{'server_pwd'}); ($Conf{'server_ssl'}, $Conf{'secondary_server_ssl'}) = ($Conf{'secondary_server_ssl'}, $Conf{'server_ssl'}); ($Conf{'server_opts'}, $Conf{'secondary_server_opts'}) = ($Conf{'secondary_server_opts'}, $Conf{'server_opts'}); } ################################################################################ # Receive a file from the server. ################################################################################ sub recv_file ($) { my $file = shift; my $output; if ($Conf{'transfer_mode'} eq 'tentacle') { $output = `cd "$Conf{'temporal'}"$CmdSep tentacle_client -v -g -a $Conf{'server_ip'} -p $Conf{'server_port'} $Conf{'server_opts'} $file 2>&1 >$DevNull` } elsif ($Conf{'transfer_mode'} eq 'ssh') { $output = `scp -P $Conf{'server_port'} pandora@"$Conf{'server_ip'}:$Conf{'server_path'}/$file" $Conf{'temporal'} 2>&1 >$DevNull`; } elsif ($Conf{'transfer_mode'} eq 'ftp') { my $base = basename ($file); my $dir = dirname ($file); $output = `ftp -n $Conf{'server_ip'} $Conf{'server_port'} 2>&1 >$DevNull <&1 >$DevNull`; } # Get the errorlevel my $rc = $? >> 8; if ($rc != 0) { log_message ('error', "Error retrieving file: $output"); } return $rc; } ################################################################################ # Check the server for a remote configuration. ################################################################################ sub check_remote_config () { return unless ($Conf{'remote_config'} eq '1'); # Calculate the configuration file MD5 digest open (CONF_FILE, "$ConfDir/$ConfFile") or error ("Could not open file '$ConfDir/$ConfFile': $!."); binmode(CONF_FILE); my $conf_md5 = md5 (join ('', )); close (CONF_FILE); # Remove temporary files if they exist as symlink to avoid symlink attack for my $file ("$Conf{'temporal'}/$RemoteMD5File", "$Conf{'temporal'}/$RemoteConfFile") { error ("File '$file' already exists as a symlink and could not be removed: $!") if (-l $file && ! unlink($file)); } # Get the remote MD5 file if (recv_file ($RemoteMD5File) != 0) { open (MD5_FILE, "> $Conf{'temporal'}/$RemoteMD5File") || error ("Could not open file '$ConfDir/$RemoteMD5File' for writing: $!."); print MD5_FILE $conf_md5; close (MD5_FILE); copy ("$ConfDir/$ConfFile", "$Conf{'temporal'}/$RemoteConfFile"); send_file ("$Conf{'temporal'}/$RemoteConfFile"); send_file ("$Conf{'temporal'}/$RemoteMD5File"); log_message ('remote config', 'Uploading configuration for the first time.'); unlink ("$Conf{'temporal'}/$RemoteConfFile"); unlink ("$Conf{'temporal'}/$RemoteMD5File"); return; } open (MD5_FILE, "< $Conf{'temporal'}/$RemoteMD5File") || error ("Could not open file '$ConfDir/$RemoteMD5File' for writing: $!."); my $remote_conf_md5 = ; close (MD5_FILE); # No changes return if ($remote_conf_md5 eq $conf_md5); # Get the new configuration file return if (recv_file ($RemoteConfFile) != 0); log_message ('remote config', 'Configuration has changed!'); # Empty modules, plugins and collections @Modules = (); @Plugins = (); %Collections = (); # Save the new configuration and reload it move ("$Conf{'temporal'}/$RemoteConfFile", "$ConfDir/$ConfFile"); read_config (); # Log file may have changed stop_log (); start_log ('quiet'); #Set nice of the pandora_agent my $PID = $$; `renice "$Conf{'pandora_nice'}" "$PID"`; } ################################################################################ # SUB launch_tentacle_proxy # Launchs tentacle server in proxy mode. ################################################################################ sub launch_tentacle_proxy () { # Check if proxy server ip is right. if ($Conf{'server_ip'} ne "localhost") { #Create a new process and launch tentacle. $tentacle_pid = fork(); if ($tentacle_pid == 0) { #Execute tentacle server as a daemon my $new_process = "tentacle_server -b ".$Conf{'server_ip'}." -g ".$Conf{'server_port'}." -c ".$Conf{'proxy_max_connection'}." -t ".$Conf{'proxy_timeout'}; log_message ('setup', 'Proxy mode enabled'); exec ($new_process); } } else { error ('You can not proxy to localhost'); } } ################################################################################ # Delete old collections and download new collections. ################################################################################ sub check_collections () { # Delete old collections opendir (DIR, "$ConfDir/collections") || return; while (defined (my $file_name = readdir(DIR))) { next if ($file_name eq '.' || $file_name eq '..'); # Do not delete md5 files associated to a collection $file_name =~ s/\.md5$//; if (! defined ($Collections{$file_name})) { rmrf ("$ConfDir/collections/$file_name"); unlink ("$ConfDir/collections/$file_name.md5"); } } closedir (DIR); # Download new collections while (my ($collection, $in_path) = each (%Collections)) { my $collection_file = $collection . ".zip"; my $collection_md5_file = $collection . ".md5"; # Add the collection directory to the PATH if ($in_path == 0) { $Collections{$collection} = 1; $ENV{'PATH'} .= ":$ConfDir/collections/$collection"; } # Get remote md5 error ("File '$Conf{'temporal'}/$collection_md5_file' already exists as a symlink and could not be removed: $!.") if (-l "$Conf{'temporal'}/$collection_md5_file" && !unlink("$Conf{'temporal'}/$collection_md5_file")); next unless (recv_file ($collection_md5_file) == 0); open (MD5_FILE, "< $Conf{'temporal'}/$collection_md5_file") || error ("Could not open file '$Conf{'temporal'}/$collection_md5_file' for reading: $!."); my $remote_collection_md5 = ; close (MD5_FILE); unlink ("$Conf{'temporal'}/$collection_md5_file"); # Read local md5 my $local_collection_md5 = ''; if (defined (open (MD5_FILE, "< $ConfDir/collections/$collection_md5_file"))) { $local_collection_md5 = ; close MD5_FILE; } # Check for changes $local_collection_md5 = $remote_collection_md5 unless defined ($local_collection_md5); next if ($local_collection_md5 eq $remote_collection_md5); # Download and unzip next unless (recv_file ($collection_file) == 0); rmrf ("$ConfDir/collections/$collection"); `unzip -d "$ConfDir/collections/$collection" "$Conf{'temporal'}/$collection_file" 2>$DevNull`; unlink ("$Conf{'temporal'}/$collection_file"); # Save the new md5 open (MD5_FILE, "> $ConfDir/collections/$collection_md5_file") || error ("Could not open file '$ConfDir/collections/$collection_md5_file' for writing: $!."); print MD5_FILE "$remote_collection_md5"; close (MD5_FILE); # Set proper file permissions chmodr (0750, "$ConfDir/collections/$collection"); } } ############################################################################### # MD5 leftrotate function. See http://en.wikipedia.org/wiki/MD5#Pseudocode. ############################################################################### sub leftrotate ($$) { my ($x, $c) = @_; return (0xFFFFFFFF & ($x << $c)) | ($x >> (32 - $c)); } ############################################################################### # Initialize some variables needed by the MD5 algorithm. # See http://en.wikipedia.org/wiki/MD5#Pseudocode. ############################################################################### my (@R, @K); sub md5_init () { # R specifies the per-round shift amounts @R = (7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21); # Use binary integer part of the sines of integers (radians) as constants for (my $i = 0; $i < 64; $i++) { $K[$i] = floor(abs(sin($i + 1)) * MOD232); } } ############################################################################### # Return the MD5 checksum of the given string. # Pseudocode from http://en.wikipedia.org/wiki/MD5#Pseudocode. ############################################################################### sub md5 ($) { my $str = shift; # Note: All variables are unsigned 32 bits and wrap modulo 2^32 when calculating # Initialize variables my $h0 = 0x67452301; my $h1 = 0xEFCDAB89; my $h2 = 0x98BADCFE; my $h3 = 0x10325476; # Pre-processing my $msg = unpack ("B*", pack ("A*", $str)); my $bit_len = length ($msg); # Append "1" bit to message $msg .= '1'; # Append "0" bits until message length in bits ≡ 448 (mod 512) $msg .= '0' while ((length ($msg) % 512) != 448); # Append bit /* bit, not byte */ length of unpadded message as 64-bit little-endian integer to message $msg .= unpack ("B64", pack ("VV", $bit_len)); # Process the message in successive 512-bit chunks for (my $i = 0; $i < length ($msg); $i += 512) { my @w; my $chunk = substr ($msg, $i, 512); # Break chunk into sixteen 32-bit little-endian words w[i], 0 <= i <= 15 for (my $j = 0; $j < length ($chunk); $j += 32) { push (@w, unpack ("V", pack ("B32", substr ($chunk, $j, 32)))); } # Initialize hash value for this chunk my $a = $h0; my $b = $h1; my $c = $h2; my $d = $h3; my $f; my $g; # Main loop for (my $y = 0; $y < 64; $y++) { if ($y <= 15) { $f = $d ^ ($b & ($c ^ $d)); $g = $y; } elsif ($y <= 31) { $f = $c ^ ($d & ($b ^ $c)); $g = (5 * $y + 1) % 16; } elsif ($y <= 47) { $f = $b ^ $c ^ $d; $g = (3 * $y + 5) % 16; } else { $f = $c ^ ($b | (0xFFFFFFFF & (~ $d))); $g = (7 * $y) % 16; } my $temp = $d; $d = $c; $c = $b; $b = ($b + leftrotate (($a + $f + $K[$y] + $w[$g]) % MOD232, $R[$y])) % MOD232; $a = $temp; } # Add this chunk's hash to result so far $h0 = ($h0 + $a) % MOD232; $h1 = ($h1 + $b) % MOD232; $h2 = ($h2 + $c) % MOD232; $h3 = ($h3 + $d) % MOD232; } # Digest := h0 append h1 append h2 append h3 #(expressed as little-endian) return unpack ("H*", pack ("V", $h0)) . unpack ("H*", pack ("V", $h1)) . unpack ("H*", pack ("V", $h2)) . unpack ("H*", pack ("V", $h3)); } ################################################################################ # Try to guess the OS version. ################################################################################ sub guess_os_version ($) { my $os = shift; my $os_version; # Linux if ($os eq 'linux') { $os_version = `lsb_release -sd 2>$DevNull`; # AIX } elsif ($os eq 'aix') { $os_version = "$2.$1" if (`uname -rv` =~ /\s*(\d)\s+(\d)\s*/); # Windows } elsif ($os =~ /win/i && ! $os =~ /Darwin/) { $os_version = `ver`; $DevNull = '/Nul'; $CmdSep = '\&'; $OS = "windows"; # Solaris, HP-UX, BSD and others } else { $os_version = `uname -r`; } # Something went wrong return '' unless defined ($os_version); # Remove any trailing new lines chomp ($os_version); return $os_version; } ################################################################################ # Execute the given module. ################################################################################ sub exec_module ($) { my $module = shift; # Need something to execute if ($module->{'func'} == 0) { $ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); return; } # Check module interval if (++($module->{'counter'}) < $module->{'interval'}) { $ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); return; } # Check module cron if (check_module_cron ($module) != 1) { $ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); return; } # Reset module counter $module->{'counter'} = 0; # Temporarily disable strict refs no strict 'refs'; # Run my @value = &{$module->{'func'}}($module); # Save the module value if needed (only works for the first returned value) if ($module->{'save'} ne '') { if (defined ($value[0])) { $ENV{$module->{'save'}} = $value[0] ; } else { $ENV{$module->{'save'}} = ''; } } write_module_xml ($module, @value); $ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); } ################################################################################ # Load process information. ################################################################################ sub load_procs () { my $utimestamp = time (); # Do we know hoy to get process information in this OS? return unless defined (PROC_CMDS->{$OS}); # Update at most once every interval return if ($Procs{'__utimestamp__'} > ($utimestamp - $Conf{'interval'})); # Get process information my $cmd = PROC_CMDS->{$OS}; my @procs = `$cmd`; return undef unless ($? eq 0); # Clear past process infomation %Procs = (); # Parse process information foreach my $proc (@procs) { chomp ($proc); my @proc_info = split (/\s+/, $proc); next unless ($#proc_info >= 2); # Process command my $proc_cmd = join (' ', @proc_info[2..$#proc_info]); # Process command $Procs{$proc_cmd} = (); # Process CPU usage $Procs{$proc_cmd}{'cpu'} = $proc_info[0]; # Process virtual size $Procs{$proc_cmd}{'size'} = $proc_info[1]; } $Procs{'__utimestamp__'} = $utimestamp; } ################################################################################ # Load partition information. ################################################################################ sub load_parts () { my $utimestamp = time (); # Do we know hoy to get partition information in this OS? return unless defined (PART_CMDS->{$OS}); # Update at most once every interval return if ($Parts{'__utimestamp__'} > ($utimestamp - $Conf{'interval'})); # Get partition information my $cmd = PART_CMDS->{$OS}; my @parts = `$cmd`; return undef unless ($? eq 0); # Parse partition information foreach my $part (@parts) { chomp ($part); my @part_info = split (/\s+/, $part); next unless ($#part_info >= 2); my $part = join (' ', @part_info[2..$#part_info]); # Mount point $Parts{$part} = (); # Total space in kB $Parts{$part}{'total'} = $part_info[0]; # Available space in kB $Parts{$part}{'avail'} = $part_info[1]; } $Parts{'__utimestamp__'} = $utimestamp; } ################################################################################ # Execute the given command precondition. ################################################################################ sub module_precondition_exec ($) { my $module = shift; my @data; # Check module parameters return () unless ($module->{'params_precon'} ne ''); # Execute the command if ($module->{'timeout'} == 0) { @data = `$module->{'params_precon'} 2> $DevNull`; } else { my $cmd = quotemeta ($module->{'params_precon'}); @data = `$Conf{'pandora_exec'} $module->{'timeout'} $cmd 2> $DevNull`; } # Something went wrong or no data return () unless ($? eq 0 && defined ($data[0])); # Evaluate module preconditions evaluate_module_preconditions ($module, $data[0]); return @data; } ################################################################################ # Execute the given command. ################################################################################ sub module_exec ($) { my $module = shift; my @data; my $exe; $exe = evaluate_module_preconditions ($module); return @data if ($exe == 0); # Check module parameters return () unless ($module->{'params'} ne ''); # Execute the command if ($module->{'timeout'} == 0) { @data = `$module->{'params'} 2> $DevNull`; } else { my $cmd = quotemeta ($module->{'params'}); @data = `$Conf{'pandora_exec'} $module->{'timeout'} $cmd 2> $DevNull`; } # Something went wrong or no data return () unless ($? eq 0 && defined ($data[0])); # Evaluate module conditions evaluate_module_conditions ($module, $data[0]); return @data; } ################################################################################ # Get the status of a process. 1 running, 0 not running. ################################################################################ sub module_proc ($) { my $module = shift; # Check module parameters return () unless ($module->{'params'} ne ''); # Data collection layer load_procs (); return (1) if defined ($Procs{$module->{'params'}}); return (0); } ################################################################################ # Get the CPU usage of a process. ################################################################################ sub module_cpuproc ($) { my $module = shift; # Check module parameters return () unless ($module->{'params'} ne ''); # Data collection layer load_procs (); return () unless defined ($Procs{$module->{'params'}}) and defined ($Procs{$module->{'params'}}{'cpu'}); return ($Procs{$module->{'params'}}{'cpu'}); } ################################################################################ # Get the memory usage of a process in Mbytes. ################################################################################ sub module_memproc ($) { my $module = shift; # Check module parameters return () unless ($module->{'params'} ne ''); # Data collection layer load_procs (); return () unless defined ($Procs{$module->{'params'}}) and defined ($Procs{$module->{'params'}}{'size'}); return (sprintf ("%d", $Procs{$module->{'params'}}{'size'} / 1024)); } ################################################################################ # Get the free space in a partition in Mbytes. ################################################################################ sub module_freedisk ($) { my $module = shift; # Check module parameters return () unless ($module->{'params'} ne ''); # Data collection layer load_parts (); return () unless defined ($Parts{$module->{'params'}}) and defined ($Parts{$module->{'params'}}{'avail'}); my $avail = sprintf("%d", $Parts{$module->{'params'}}{'avail'} / 1024); return ($avail); } ################################################################################ # Get the free space in a partition in %. ################################################################################ sub module_freepercentdisk ($) { my $module = shift; # Check module parameters return () unless ($module->{'params'} ne ''); # Data collection layer load_parts (); return () unless defined ($Parts{$module->{'params'}}) and defined ($Parts{$module->{'params'}}{'avail'}); my $availp = sprintf("%d", $Parts{$module->{'params'}}{'avail'} * 100 / $Parts{$module->{'params'}}{'total'}); return ($availp); } ################################################################################ # Get the occupied space in a partition in %. ################################################################################ sub module_occupiedpercentdisk ($) { my $module = shift; # Check module parameters return () unless ($module->{'params'} ne ''); # Data collection layer load_parts (); return () unless defined ($Parts{$module->{'params'}}) and defined ($Parts{$module->{'params'}}{'avail'}); my $occupiedp = sprintf("%d", ($Parts{$module->{'params'}}{'total'} - $Parts{$module->{'params'}}{'avail'}) * 100 / $Parts{$module->{'params'}}{'total'}); return ($occupiedp); } ################################################################################ # Get the CPU usage %. ################################################################################ sub module_cpuusage ($) { my $module = shift; # Do we know hoy to get CPU usage in this OS? return unless defined (CPUUSAGE_CMDS->{$OS}); # Get CPU usage my $cmd = CPUUSAGE_CMDS->{$OS}; my @data = `$cmd 2> $DevNull`; # Something went wrong or no data return () unless ($? eq 0 && defined ($data[0])); return ($data[0]); } ################################################################################ # Get the free space in a partition in Mbytes. ################################################################################ sub module_freememory ($) { my $module = shift; # Do we know hoy to get memory information in this OS? return () unless defined (FREEMEMORY_CMDS->{$OS}); # Get available memory my $cmd = FREEMEMORY_CMDS->{$OS}; my @data = `$cmd 2> $DevNull`; # Something went wrong or no data return () unless ($? eq 0 && defined ($data[0])); return (sprintf ("%d", $data[0] / 1024)); } ################################################################################ # Get the free space in a partition in %. ################################################################################ sub module_freepercentmemory ($) { my $module = shift; # Do we know hoy to get memory information in this OS? return unless defined (TOTALMEMORY_CMDS->{$OS}); # Get CPU usage my $cmd = TOTALMEMORY_CMDS->{$OS}; my @data = `$cmd 2> $DevNull`; # Something went wrong or no data return () unless ($? eq 0 && defined ($data[0])); # Get total memory in MB my $total = sprintf ("%d", $data[0] / 1024); # Get available memory in MB my ($avail) = module_freememory ($module); return () unless defined ($avail); return sprintf (("%d", $avail * 100 / $total)); } ################################################################################ # Evaluate and execute module preconditions. ################################################################################ sub evaluate_module_preconditions ($) { my ($module) = @_; # Evaluate preconditions if ($module->{'precon'}){ foreach my $precondition (@{$module->{'precondition'}}) { my $data = `$precondition->{'command'} 2> $DevNull`; { # Do not display a warning if the output of the command is not numeric no warnings; if (($precondition->{'operator'} eq '>' && $data > $precondition->{'value_1'}) || ($precondition->{'operator'} eq '<' && $data < $precondition->{'value_1'}) || ($precondition->{'operator'} eq '=' && $data == $precondition->{'value_1'}) || ($precondition->{'operator'} eq '!=' && $data != $precondition->{'value_1'}) || ($precondition->{'operator'} eq '=~' && $data =~ /$precondition->{'value_1'}/) || ($precondition->{'operator'} eq '()' && $data > $precondition->{'value_1'} && $data < $precondition->{'value_2'})) { } else { return 0; } }; } } return 1; } ################################################################################ # Evaluate and execute module conditions. ################################################################################ sub evaluate_module_conditions ($$) { my ($module, $data) = @_; # Evaluate conditions foreach my $condition (@{$module->{'conditions'}}) { if (($condition->{'operator'} eq '>' && $data > $condition->{'value_1'}) || ($condition->{'operator'} eq '<' && $data < $condition->{'value_1'}) || ($condition->{'operator'} eq '=' && $data == $condition->{'value_1'}) || ($condition->{'operator'} eq '!=' && $data != $condition->{'value_1'}) || ($condition->{'operator'} eq '=~' && $data =~ /$condition->{'value_1'}/) || ($condition->{'operator'} eq '()' && $data > $condition->{'value_1'} && $data < $condition->{'value_2'})) { `$condition->{'command'} 2> $DevNull`; } } } ################################################################################ # Checks the module's cron string. Returns 1 if the module should be run, 0 if # not. ################################################################################ sub check_module_cron ($) { my $module = shift; # No cron string defined return 1 unless ($module->{'cron'} ne ''); # Check if the module was already executed return 0 unless (time() > $module->{'cron_utimestamp'}); # Get cron configuration my @cron_params = split (/\s/, $module->{'cron'}); # Get current time my $current_time = time(); my @time = localtime($current_time); # Minutes, hours, day of the month, month and day of the week my @time_params = @time[1, 2, 3, 4, 6]; # Fix month (localtime retuns 0..11 and we need 1..12) $time_params[3] += 1; # Check cron parameters for (my $i = 0; $i < 5; $i++) { # Wildcard next if ($cron_params[$i] eq '*'); # Get interval my ($bottom, $top) = split (/-/, $cron_params[$i]); $top = $bottom unless defined ($top); # Check interval if ($bottom <= $top) { return 0 if ($time_params[$i] < $bottom || $time_params[$i] > $top); } else { return 0 if ($time_params[$i] < $bottom && $time_params[$i] > $top); } } # Do not check in the next minute, hour, day or month. my $offset = 0; if ($module->{'cron_interval'} >= 0) { $offset = $module->{'cron_interval'}; } elsif($cron_params[0] ne '*') { # 1 minute $offset = 60; } elsif($cron_params[1] ne '*') { # 1 hour $offset = 3600; } elsif($cron_params[2] ne '*' || $cron_params[4] ne '*') { # 1 day $offset = 86400; } elsif($cron_params[3] ne '*') { # 31 days $offset = 2678400; } $module->{'cron_utimestamp'} = $current_time + $offset; return 1; } ################################################################################ # Write module data in XML format. ################################################################################ sub write_module_xml ($@) { my ($module, @data) = @_; # No data return unless (defined $data[0]); # Critical section $Sem->down () if (defined ($Sem)); $Xml .= " \n" . " {'name'} . "]]>\n" . " {'description'} . "]]>\n" . " " . $module->{'type'} . "\n"; # Interval $Xml .= " " . $module->{'interval'} . "\n" if ($module->{'interval'} > 1); # Min $Xml .= " " . $module->{'min'} . "\n" if (defined ($module->{'min'})); # Max $Xml .= " " . $module->{'max'} . "\n" if (defined ($module->{'max'})); # Post process $Xml .= " " . $module->{'post_process'} . "\n" if (defined ($module->{'post_process'})); # Min critical $Xml .= " " . $module->{'min_critical'} . "\n" if (defined ($module->{'min_critical'})); # Max critical $Xml .= " " . $module->{'max_critical'} . "\n" if (defined ($module->{'max_critical'})); # Min warning $Xml .= " " . $module->{'min_warning'} . "\n" if (defined ($module->{'min_warning'})); # Max warning $Xml .= " " . $module->{'max_warning'} . "\n" if (defined ($module->{'max_warning'})); # Disabled $Xml .= " " . $module->{'disabled'} . "\n" if (defined ($module->{'disabled'})); # Min ff event $Xml .= " " . $module->{'min_ff_event'} . "\n" if (defined ($module->{'min_ff_event'})); # Data list if ($#data > 0) { $Xml .= " \n"; foreach my $data_item (@data) { chomp ($data_item); $Xml .= " \n"; } $Xml .= " \n"; # Single data } else { chomp ($data[0]); $Xml .= " \n"; } $Xml .= " \n"; $Sem->up () if (defined ($Sem)); } ################################################################################ # Receive a UDP server signal to restart agent ################################################################################ sub udp_server_signal () { log_message ('udp server', 'Received signal to restart the agent.'); } ################################################################################ # Basic UDP server to restart agent on UDP signal received ################################################################################ sub udp_server ($$) { my $udp_port = shift; my $udp_auth_address = shift; my $parent_pid = getppid(); my($sock, $oldmsg, $newmsg, $hisaddr, $hishost, $MAXLEN); $MAXLEN = 1024; log_message ('udp server', 'Starting UDP server listening on '.$udp_auth_address.":".$udp_port); $sock = IO::Socket::INET->new(LocalPort => $udp_port, Proto => 'udp') or die "socket: $@"; while ($sock->recv($newmsg, $MAXLEN)) { my($port, $ipaddr) = sockaddr_in($sock->peername); $hishost = gethostbyaddr($ipaddr, AF_INET); log_message ('udp server', 'Received signal from '.$hishost); if (($udp_auth_address eq "0.0.0.0") || ($hishost eq $udp_auth_address)){ if ($newmsg =~ /REFRESH AGENT/){ # Send signal to restart agent kill 'SIGINT' , $parent_pid; } } } } ################################################################################ # Execute the given plugin. ################################################################################ sub exec_plugin ($) { my $plugin = shift; my $output = `$plugin 2>$DevNull`; # Do not save the output if there was an error if ($? != 0) { $ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); return; } # Critical section $Sem->down () if (defined ($Sem)); $Xml .= $output; $Sem->up () if (defined ($Sem)); $ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); } ################################################################################ # TERM Handler ################################################################################ sub kill_signal_handler (){ # Kill tentacle server if it was launched if (defined ($tentacle_pid)) { print "kill -9 $tentacle_pid\n"; `kill -9 $tentacle_pid`; } exit (0); } ################################################################################ # Get the free disk space in the temporal directory (in bytes). ################################################################################ sub temporal_freedisk () { # Call df return 0 unless defined (DF_CMDS->{$OS}); my $cmd = DF_CMDS->{$OS} . ' ' . $Conf{'temporal'} . ' | awk \'NR > 1 {print $4}\''; my $temporal_freedisk = `$cmd`; # Check for errors return 0 unless ($? eq 0); # Convert to bytes return 1024 * int ($temporal_freedisk); } ################################################################################ # Main. ################################################################################ #Handler TERM signal. $SIG{'TERM'} = \&kill_signal_handler; # Check command line arguments print_usage unless ($#ARGV == 0); $ConfDir = fix_directory ($ARGV[0]); error ("Directory '$ConfDir' does not exist.") unless (-d "$ConfDir"); #Pandora home path $ENV{'PANDORA_HOME'}=$ConfDir; # Get user to run as my $pandora_user = read_config ('pandora_user'); if (defined ($pandora_user)) { # Change the EUID my $pandora_user_uid = getpwnam ($pandora_user); if (!defined ($pandora_user_uid)) { error ("Cannot get uid for user $pandora_user. Does the user exist and can we read /etc/passwd?"); } $> = $pandora_user_uid; if ($> != $pandora_user_uid) { error ("Cannot run as $pandora_user: Insufficient permissions."); } } # Guess the OS version $OS_VERSION = guess_os_version ($OS); # Initialize MD5 variables md5_init (); # Start logging start_log (); log_message ('log', 'Running as user ' . getpwuid ($>)); # Read configuration file read_config (); $ENV{'PANDORA_AGENT'}=$Conf{'agent_name'}; # Fix directory names $Conf{'temporal'} = fix_directory ($Conf{'temporal'}); error ("Temporal directory '" . $Conf{'temporal'} . "' does not exist.") unless (-d "$Conf{'temporal'}"); $Conf{'server_path'} = fix_directory ($Conf{'server_path'}); $Conf{'secondary_server_path'} = fix_directory ($Conf{'secondary_server_path'}); # Load thread support if agent_threads is greater than 1. if ($Conf{'agent_threads'} > 1) { eval { local $SIG{__DIE__}; require threads; require threads::shared; require Thread::Semaphore; }; if (!$@) { $Sem = Thread::Semaphore->new; threads::shared::share (\$Xml); threads::shared::share (\$Sem); log_message ('log', 'Using thread library.'); } else { log_message ('log', 'Thread library is not available. agent_threads is set to 1 (disabled).'); $Conf{'agent_threads'} = 1; } } else { log_message ('log', 'Thread is disabled.'); } # Startup delay log_message ('log', 'Sleeping for ' . $Conf{'delayed_startup'} . ' seconds.') if ($Conf{'delayed_startup'} > 0); sleep ($Conf{'delayed_startup'}); #Set nice of the pandora_agent my $PID = $$; `renice "$Conf{'pandora_nice'}" "$PID"`; #Launch tentacle server in proxy mode if configured if ($Conf{'proxy_mode'}) { #Check if user is root if ($> != 0) { launch_tentacle_proxy(); } else { error ('Proxy mode can not be launched as root'); } } # Add the plugins directory to the PATH $ENV{'PATH'} .= ":$ConfDir/plugins"; # Start UDP server if configured if ($Conf{'udp_server'} == 1){ my $pid = fork(); if ($pid == 0){ udp_server ($Conf{'udp_server_port'}, $Conf{'udp_server_auth_address'}); exit; } } # Must be set to 0 if the agent is a broker agent my $main_agent = -1; # Loop while (1) { # Ignore signals from UDP and Tentacle server while processing execution if ($Conf{'udp_server'} == 1 || $Conf{'proxy_mode'}){ $SIG{'INT'} = 'DEFAULT'; } # Check for a new configuration check_remote_config () unless ($Conf{'debug'} eq '1'); # Check file collections check_collections () unless ($Conf{'debug'} eq '1'); # Launch broker agents @BrokerPid = (); my @broker_agents = read_config ('broker_agent'); foreach my $broker_agent (@broker_agents) { # Create broker conf file if it does not exist if (! -e "$ConfDir/${broker_agent}.conf") { write_broker_conf($broker_agent); } $main_agent = fork (); # Broker agent if ($main_agent == 0) { # Set the configuration file $ConfFile = "${broker_agent}.conf"; # Log to a new file stop_log (); start_log ('quiet'); # Read configuration file @Modules = (); @Plugins = (); %Collections = (); read_config (); # Check for a new configuration check_remote_config () unless ($Conf{'debug'} eq '1'); # Check file collections check_collections () unless ($Conf{'debug'} eq '1'); # Execute last; } else { push (@BrokerPid, $main_agent); } } my $address; if(defined($Conf{'address'})) { # Check if address is auto to get the local ip if ($Conf{'address'} eq 'auto') { # Tested on Ubuntu, debian, Suse, Solaris 10 and AIX 5.1 $address = `ifconfig -a | grep -v '127.0.0' | grep '[0-9]*\\.[0-9]*\\.[0-9]*' | awk '{ print \$2 }' | head -1 | sed -e 's/addr\\://' | sed -e 's/inet\\://'`; chomp($address); } else { $address = $Conf{'address'}; } } $Xml = "\n" . " 1) { $ThreadSem->down (); my $thr = threads->create (\&exec_module, $module); if (! defined ($thr)) { $ThreadSem->up (); } else { $thr->detach(); } # Execute the module } else { exec_module ($module); } } # Execute plugins foreach my $plugin (@Plugins) { # Execute the plugin in a separate thread if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1) { $ThreadSem->down (); my $thr = threads->create (\&exec_plugin, $plugin); if (! defined ($thr)) { $ThreadSem->up (); } else { $thr->detach(); } # Execute the plugin } else { exec_plugin ($plugin); } } # Wait for all the threads $ThreadSem->down ($Conf{'agent_threads'}) if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); $ThreadSem->up ($Conf{'agent_threads'}) if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1); $Xml .= ""; # Save XML data file my $temp_file = $Conf{'temporal'} . '/' . $Conf{'agent_name'} . '.' . time () . '.data'; error ("File '$temp_file' already exists as a symlink and could not be removed: $!") if (-l $temp_file && !unlink($temp_file)); open (TEMP_FILE, "> $temp_file") || error ("Could not write XML data file: $!"); print TEMP_FILE $Xml; close (TEMP_FILE); # Debug mode if ($Conf{'debug'} eq '1') { log_message ('debug', "Wrote XML data file '$temp_file'"); log_message ('debug', "Wrote XML data file '$temp_file'", *STDOUT); last; } # Send the XML data file my $rc = send_file ($temp_file, 1); if ($rc == 0 || $Conf{'xml_buffer'} == 0 || temporal_freedisk () < $Conf{'temporal_min_size'}) { unlink ($temp_file); } # Send buffered XML data files if ($Conf{'xml_buffer'} == 1) { send_buffered_xml_files (); } # Cron mode last if ($Conf{'cron_mode'} == 1); # Enable signal capture to break the Sleep interval on UDP signal if ($Conf{'udp_server'} == 1){ $SIG{'INT'} = \&udp_server_signal; } # Sleep if main agent if ($main_agent != 0) { foreach my $broker_pid (@BrokerPid) { waitpid ($broker_pid, 0); } sleep ($Conf{'interval'}); } # Finish if broker agent else { exit (0); } } __END__ =head1 EXIT STATUS =over =item 0 on Success =item 1 on Error =back =head1 CONFIGURATION By default pandora_agent uses F as B. There is the F file with all the configuration of the agent. =head1 DEPENDENCIES =head1 LICENSE This is released under the GNU Lesser General Public License. =head1 SEE ALSO =head1 COPYRIGHT Copyright (c) 2005-2010 Artica Soluciones Tecnologicas S.L =cut unix/DEBIAN/0000755000000000001440000000000012166524015011652 5ustar rootusersunix/DEBIAN/control0000644000000000000000000000141412166524015013066 0ustar rootrootpackage: pandorafms-agent-unix Version: 4.1 Architecture: all Priority: optional Section: admin Installed-Size: 260 Maintainer: Miguel de Dios Homepage: http://pandorafms.org/ Depends: coreutils, perl, unzip Description: Pandora FMS agents are based on native languages in every platform: scripts that can be written in any language. It’s possible to reproduce any agent in any programming language and can be extended without difficulty the existing ones in order to cover aspects not taken into account up to the moment. These scripts are formed by modules that each one gathers a "chunk" of information. Thus, every agent gathers several "chunks" of information; this one is organized in a data set and stored in a single file, called data file. unix/DEBIAN/md5sums0000755000000000001440000000000011673617612013173 0ustar rootusersunix/DEBIAN/postinst0000755000000000000000000000273611747073173013314 0ustar rootroot#!/bin/bash PANDORA_LOG=/var/log/pandora/pandora_agent.log PANDORA_BIN=/usr/bin/pandora_agent PANDORA_EXEC_BIN=/usr/bin/pandora_agent PANDORA_HOME=/usr/share/pandora_agent PANDORA_CFG=/etc/pandora LOG_TIMESTAMP=`date +"%Y/%m/%d %H:%M:%S"` #Disabled, now the package overwrite the previous files. #echo "Copy new version of plugins into dir" #cp -i /tmp/plugins/* /usr/share/pandora_agent/plugins/ #rm /tmp/plugins -rf echo "Linking Pandora FMS Agent plugins directory to $PANDORA_CFG/plugins..." rm $PANDORA_CFG/plugins 2> /dev/null ln -s $PANDORA_HOME/plugins $PANDORA_CFG 2> /dev/null echo "Linking Pandora FMS Agent configuration to $PANDORA_CFG/pandora_agent.conf..." #~ rm $PANDORA_CFG/pandora_agent.conf 2> /dev/null #~ ln -s $PANDORA_HOME/pandora_agent.conf $PANDORA_CFG/pandora_agent.conf echo "Start log of agent." echo "$LOG_TIMESTAMP Pandora FMS installer has created this file at startup" > $PANDORA_LOG echo "Setting secure permissions and ownership for all Pandora FMS Agent files..." chmod 700 $PANDORA_BIN chmod 700 $PANDORA_EXEC_BIN #~ chmod 600 $PANDORA_HOME/pandora_agent.conf chmod -R 700 $PANDORA_HOME/plugins chown -R root $PANDORA_HOME chmod 640 $PANDORA_LOG chgrp root $PANDORA_LOG chown -R root:root $PANDORA_BIN chown -R root:root $PANDORA_EXEC_BIN echo "Linking start-up daemon script to /etc/rc$INITLV.d"; update-rc.d pandora_agent_daemon defaults echo "Please, now setup the $PANDORA_HOME/pandora_agent.conf and before start the /etc/init.d/pandora_agent_daemon" unix/DEBIAN/make_deb_package.sh0000644000000000000000000000667712166524015015241 0ustar rootroot#!/bin/bash #Pandora FMS- http:#pandorafms.com # ================================================== # Copyright (c) 2005-2010 Artica Soluciones Tecnologicas # Please see http:#pandorafms.org for full contribution list # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public License # as published by the Free Software Foundation; version 2 # This program 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. pandora_version="4.1" echo "Test if you has the tools for to make the packages." whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null if [ $? = 1 ] then echo "No found \"dpkg-deb\" aplication, please install." exit 1 else echo "Found \"dpkg-debs\"." fi cd .. echo "Make a \"temp_package\" temp dir for job." mkdir -p temp_package/usr mkdir -p temp_package/usr/share/pandora_agent/ mkdir -p temp_package/usr/bin/ mkdir -p temp_package/usr/sbin/ mkdir -p temp_package/etc/pandora/plugins mkdir -p temp_package/etc/pandora/collections mkdir -p temp_package/etc/init.d/ mkdir -p temp_package/var/log/pandora/ mkdir -p temp_package/var/spool/pandora/data_out mkdir -p temp_package/usr/share/man/man1/ mkdir -p temp_package/usr/share/pandora_agent/plugins mkdir -p temp_package/tmp echo "Make directory system tree for package." cp DEBIAN temp_package -R chmod 755 -R temp_package/DEBIAN #Next lines is same to #cp -aRf * temp_package/usr/share/pandora_agent/ #but don't copy recursive the temp_package into temp_package for item in `ls | grep -v NT4 | grep -v AIX | grep -v FreeBSD | grep -v HP-UX | grep -v SunOS | grep -v temp_package` do #if [ \( $item != 'temp_package' \) -a \( $item != 'NT4' \) ] #then cp -aRf $item temp_package/usr/share/pandora_agent/ #fi done cp -aRf tentacle_client temp_package/usr/bin/ cp -aRf pandora_agent temp_package/usr/bin/ cp -aRf pandora_agent_exec temp_package/usr/bin/pandora_agent_exec cp -aRf pandora_agent_daemon temp_package/etc/init.d/pandora_agent_daemon cp Linux/pandora_agent.conf temp_package/etc/pandora/ cp -aRf man/man1/* temp_package/usr/share/man/man1/ #Disabled, now the package overwrite the previous files. ##Create a temp file for to update files of plugins dir but don't crush dir. ##cp -aRf temp_package/usr/share/pandora_agent/plugins temp_package/tmp ##rm -rf temp_package/usr/share/pandora_agent/plugins/* echo "Remove the SVN files and other temp files." for item in `find temp_package` do echo -n "." echo $item | grep "svn" > /dev/null #last command success if [ $? -eq 0 ] then rm -rf $item fi echo $item | grep "make_deb_package.sh" > /dev/null #last command success if [ $? -eq 0 ] then rm -rf $item fi done echo "END" echo "Calcule md5sum for md5sums file control of package" for item in `find temp_package` do echo -n "." if [ ! -d $item ] then echo $item | grep "DEBIAN" > /dev/null #last command success if [ $? -eq 1 ] then md5=`md5sum $item | cut -d" " -f1` #delete "temp_package" in the path final_path=${item#temp_package} echo $md5" "$final_path >> temp_package/DEBIAN/md5sums fi fi done echo "END" echo "Make the package \"Pandorafms console\"." dpkg-deb --build temp_package mv temp_package.deb pandorafms.agent_unix_$pandora_version.deb echo "Delete the \"temp_package\" temp dir for job." rm -rf temp_package unix/DEBIAN/conffiles0000755000000000001440000000004011673617612013552 0ustar rootusers/etc/pandora/pandora_agent.conf unix/DEBIAN/prerm0000755000000000001440000000033611673617612012737 0ustar rootusers#!/bin/bash echo Stop Pandora agent daemon /etc/init.d/pandora_agent_daemon stop PANDORA_CFG=/etc/pandora #rm -rf $PANDORA_CFG/plugins #rm -rf $PANDORA_CFG/pandora_agent.conf update-rc.d -f pandora_agent_daemon remove unix/man/0000755000000000001440000000000011673617616011517 5ustar rootusersunix/man/man1/0000755000000000001440000000000011673617616012353 5ustar rootusersunix/man/man1/pandora_agent.1.gz0000644000000000001440000000134511673617616015661 0ustar rootusers\Kpandora_agent.1TN1}WRZ%IRzQ"<*zg۵H VϜ9Lu>B~@BpnJmkrcX-9m)Mr1ÂB[%Fdyb~3\ /G% ?'$|w10fp -\o6B]l81p{ҝ.[b^ۤv6_d%g6ΦT,*庱KV+K`mT6 "֯H>)!WǍV~>-ϖ(;,חR`҅f{9wX7܅m%EEw 5fӾ7j-W{.:@CEvC~emq)įF y1Aٱ W+o5?|C^-\(Ɨ[[ӉW;ʕh_BN $^]FR>4.;Fbjh6κMϺ1=]hh/M[$ضѴ[a,kX9MSmPKBf,,wb*K_㗝zE ۄ*|9cmW#i`A 'ɧ@kzmc-xrMp[Vo^X*`x͟lT }scAOunix/man/man1/tentacle_client.1.gz0000644000000000001440000000232311673617616016211 0ustar rootusersKtentacle_client.1Vo6/Fukahk ck-m";ҿ!bSw޽;# YdɤvTk䗶g4b Ӛ),u:[/_+CZS`TU{ G᧋K|NO㓗EqDG'i~;uN?g6ր+zm|1R9G7YKK[l(3g9=~md2w1 Ma)'eԔzod5yvvxUC@sG6GnRu7Ltp݇Ǖ:tYffG,պV**%@.X2kkǹxʋ1 &( 1;V~m=r4w!!t$MjZ*} \M`P.4 Hk=89)Vyn4F*\GCJ1)#4wmk]@F{,!XEȚ X8Τ_2K`WN!1f$6׋Υ̅_f!? 6vx46=8AᇳO/[\nx}?ʋ 9[9j3*g~=5^7]^y()F,Ͽ5=M-I|m 02cy [Dvߟd>K".ɯ8s҂~;fKPήʛ4齢!dVY unix/COPYING0000644000000000001440000003503311673617616012003 0ustar rootusersGNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONSunix/collections/0000755000000000001440000000000011673617616013262 5ustar rootusersunix/plugins/0000755000000000001440000000000012130124376012406 5ustar rootusersunix/plugins/nagios_plugin_wrapper0000755000000000001440000000462011673617612016747 0ustar rootusers#!/usr/bin/perl ########################################################################## # nagios_plugin_wrapper # # Executes the given nagios plugin and produces an XML with data for pandora # to be used as agent plugin. This allows to have DATA based on the errorlevel # and use the descriptive information on description for the module # # Usage: nagios_plugin_wrapper ########################################################################## # Copyright (c) 2010 Artica Soluciones Tecnologicas S.L # # This program 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; version 2. # # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ########################################################################## use strict; use warnings; my $command = ""; my @opts = @ARGV; my $module_name = shift(@opts); $command = join(' ', @opts); if ($command ne ""){ my $module_data = `$command`; my $module_description = $module_data; my $ReturnCode = ($? >> 8) & 0xff; # Get the errorlevel if is a Nagios plugin type (parsing the errorlevel) # Nagios errorlevels: #('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4); # By default is unknown $module_data = ""; if ($ReturnCode == 2){ $module_data = 0; } elsif ($ReturnCode == 3){ $module_data = ''; # not defined = Uknown } elsif ($ReturnCode == 0){ $module_data = 1; } elsif ($ReturnCode == 1){ $module_data = 2; # need to be managed on module thresholds } elsif ($ReturnCode == 4){ $module_data = 3; # need to be managed on module thresholds } print ""; print "".$module_name."\n"; print "generic_proc\n"; print "".$module_data."\n"; print "\n"; print "\n"; } unix/plugins/grep_log0000755000000000001440000001404511673617612014151 0ustar rootusers#!/usr/bin/perl ############################################################################### # # Copyright (c) 2008 Ramon Novoa # Copyright (c) 2008 Artica Soluciones Tecnologicas S.L. # # grep_log Perl script to search log files for a matching pattern. The last # searched position is saved in an index file so that consecutive # runs do not return the same results. The log file inode number is # also saved to detect log rotation. # # This program 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; version 2 of the License. # # This program 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. # ############################################################################### use strict; use File::Basename; # Be verbose my $Verbose = 0; # Index file storage directory, with a trailing '/' my $Idx_dir='/tmp/'; # Log file my $Log_file = ''; # Module name my $Module_name = "default_log"; # Index file my $Idx_file = ''; # Log file position index my $Idx_pos = 0; # Log file inode number my $Idx_ino = ''; # Regular expression to be matched my $Reg_exp = ''; ############################################################################### # SUB error_msg # Print an error message and exit. ############################################################################### sub error_msg ($) { my $err_msg = $_[0]; if (! -z $err_msg) { print(stderr "[error] $err_msg.\n"); } exit 1; } ############################################################################### # SUB print_help # Print a help message. ############################################################################### sub print_help () { print "Usage: $0 \n"; } ############################################################################### # SUB log_msg # Print a log message. ############################################################################### sub log_msg ($) { my $log_msg = $_[0]; if (! -z $log_msg && $Verbose == 1) { print(stdout "[log] $log_msg.\n"); } } ############################################################################### # SUB load_idx # Load index file. ############################################################################### sub load_idx () { my $line; my $current_ino; log_msg("Loading index file $Idx_file"); open(IDXFILE, $Idx_file) || error_msg("Error opening file $Idx_file: " . $!); # Read position and date $line = ; ($Idx_pos, $Idx_ino) = split(' ', $line); close(IDXFILE); # Reset the file index if the file has changed $current_ino = (stat($Log_file))[1]; if ($current_ino != $Idx_ino) { log_msg("File changed, resetting index"); $Idx_pos = 0; $Idx_ino = $current_ino; } return; } ############################################################################### # SUB save_idx # Save index file. ############################################################################### sub save_idx () { log_msg("Saving index file $Idx_file"); open(IDXFILE, "> $Idx_file") || error_msg("Error opening file $Idx_file: " . $!); print (IDXFILE $Idx_pos . " " . $Idx_ino); close(IDXFILE); return; } ############################################################################### # SUB create_idx # Create index file. ############################################################################### sub create_idx () { my $first_line; log_msg("Creating index file $Idx_file"); open(LOGFILE, $Log_file) || error_msg("Error opening file $Log_file: " . $!); # Go to EOF and save the position seek(LOGFILE, 0, 2); $Idx_pos = tell(LOGFILE); close(LOGFILE); # Save the file inode number $Idx_ino = (stat($Log_file))[1]; # Save the index file save_idx(); return; } ############################################################################### # SUB parse_log # Parse log file starting from position $Idx_pos. ############################################################################### sub parse_log () { my $line; log_msg("Parsing log file $Log_file"); # Open log file for reading open(LOGFILE, $Log_file) || error_msg("Error opening file $Log_file: " . $!); # Go to starting position. seek(LOGFILE, $Idx_pos, 0); print (stdout "\n"); print (stdout "\n"); print (stdout "\n"); print (stdout "\n"); # Parse log file while ($line = ) { if ($line =~ m/$Reg_exp/i) { # Remove the trailing '\n' chop($line); print (stdout "\n"); } } print (stdout "\n"); print (stdout "\n"); $Idx_pos = tell(LOGFILE); close(LOGFILE); # Save the index file save_idx(); return; } ############################################################################### ############################################################################### ## Main ############################################################################### ############################################################################### # Check command line parameters if ($#ARGV != 2) { print_help(); exit 1; } $Log_file = $ARGV[0]; $Module_name = $ARGV[1]; $Reg_exp = $ARGV[2]; # Create index file storage directory if ( ! -d $Idx_dir) { mkdir($Idx_dir) || error_msg("Error creating directory $Idx_dir: " . $!); } # Check that log file exists if (! -e $Log_file) { error_msg("File $Log_file does not exist"); } # Create index file if it does not exist $Idx_file=$Idx_dir . $Module_name . "_" . basename($Log_file) . ".idx"; if (! -e $Idx_file) { create_idx(); exit 0; } # Load index file load_idx(); # Parse log file parse_log(); exit 0; unix/plugins/who.sh0000755000000000000000000000022212064335633013355 0ustar rootrootecho ""; echo "who"; echo "generic_data_string"; echo "" echo "" unix/plugins/top.sh0000755000000000000000000000023212064335633013363 0ustar rootrootecho ""; echo "top"; echo "generic_data_string"; echo "" echo "" unix/plugins/pandora_df0000755000000000001440000000376311673617612014455 0ustar rootusers#!/usr/bin/perl ############################################################################### # # Copyright (c) 2009 Ramon Novoa # Copyright (c) 2009 Artica Soluciones Tecnologicas S.L. # # pandora_df Retrieve filesystem disk usage. By default information for all # filesystems is returned, but one or more filesystems may be # specified as command line parameters. # # Sample usage: ./pandora_df tmpfs /dev/sda1 # # This program 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; version 2 of the License. # # This program 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. # ############################################################################### use strict; # Retrieve information from all filesystems my $all_filesystems = 0; # Check command line parameters if ($#ARGV < 0) { $all_filesystems = 1; } # Parse command line parameters my %filesystems; foreach my $fs (@ARGV) { $filesystems{$fs} = '-1%'; } # Retrieve filesystem information # -P use the POSIX output format for portability my @df = `df -P`; shift (@df); # No filesystems? Something went wrong. if ($#df < 0) { exit 1; } # Parse filesystem usage foreach my $row (@df) { my @columns = split (' ', $row); exit 1 if ($#columns < 4); $filesystems{$columns[0]} = $columns[4] if (defined ($filesystems{$columns[0]}) || $all_filesystems == 1); } while (my ($filesystem, $use) = each (%filesystems)) { # Remove the trailing % chop ($use); # Print module output print "\n"; print "\n"; print "\n"; print "\n"; print "% of usage in this volume\n"; print "\n"; } exit 0; unix/plugins/pandora_update0000755000000000001440000001222111673617612015333 0ustar rootusers#!/usr/bin/perl # Update binary tool # Copyright (c) 2010 Artica Soluciones Tecnologicas S.L. # Copyright (c) Sancho Lerena use strict; use warnings; use POSIX qw(strftime); use Cwd 'abs_path'; use File::Basename; use File::Copy; use FindBin; use Digest::MD5 qw(md5); # Time to wait before the service stops use constant SERVICE_STOP_WAIT => 5; # This tool is intented to be used to update pandora agent binaries using # the file collection feature. This will work using a module like this: # Unix # module_begin # module_name Pandora_Update # module_type async_string # module_exec nohup pandora_update fc_1 2> /dev/null && tail -1 nohup.out 2> /dev/null # module_description Module to check new version of pandora agent and update itself # module_end # Windows: # module_begin # module_name Pandora_Update # module_type async_string # module_exec pandora_update.exe fc_1 # module_description Module to check new version of pandora agent and update itself # module_end # This small function return the current base path (where this tool is stored) sub return_basepath () { return $FindBin::Bin; } # Function to compare two binary files. Return 0 if different 1 if equal, 2 error sub compare_twofiles ($$) { my $file1 = $_[0]; my $file2 = $_[1]; my $size1 = -s $file1; my $size2 = -s $file2; # Size matters; if ((!defined($size1)) || (!defined($size2))){ return 2; } if ($size1 != $size2){ return 0; } open FILE1, $file1; binmode FILE1; my $data1 = join ('', ); close FILE1; my $hash1 = md5($data1); open FILE2, $file2; binmode FILE2; my $data2 = join ('', ); close FILE2; my $hash2 = md5($data2); if ($hash1 eq $hash2){ return 1; } return 0; } # Get agent pid sub get_agent_pid ($$) { my $daemon = shift; my $app_path = shift; $ENV{'COLUMNS'}=400; my $os_name=`uname -s`; my $pid = ""; my $cmd = ""; if ($os_name eq "HP-UX") { $cmd ="ps -ex | grep \"$daemon $app_path\" | grep -v grep | head -1 | awk '{ print \$1 }'"; } elsif ($os_name =~ /SunOS/) { my $cmd_aux="echo \"$daemon $app_path\" | cut -c1-40"; my $truncated_daemon = `$cmd_aux`; chop($truncated_daemon); my $zone = `/bin/zonename`; if ( $zone =~ /global/) { $cmd ="ps -f -z global | grep \"$truncated_daemon\" | grep -v grep | head -1 | awk '{ print \$2 }'"; } else { $cmd ="ps -Af | grep \"$truncated_daemon\" | grep -v grep | head -1 | awk '{ print \$2 }'"; } } else { $cmd ="ps -Af | grep \"$daemon $app_path\" | grep -v grep | head -1 | awk '{ print \$2 }'"; } $pid = `$cmd`; return $pid; } # ------------------------------------------------------------------------- # MAIN CODE starts here # Get the required path (relative to basepath) to find pandora agent binary if ($#ARGV < 0) { print "Usage: $0 $local_log"); close (FILE3); my $ppid = get_agent_pid($running_binary, $conf_path); # Kill parent process (a.k.a the Agent) my $output = `kill -9 $ppid`; sleep SERVICE_STOP_WAIT; # Copy the updated agent copy($updated_binary, $running_binary) or unlink $local_log; # Starting the agent again my $log = $opt_dir."/var/log/pandora/pandora_agent.log"; $output = `nohup $running_binary $conf_path >/dev/null 2>$log &` } else { if (-e $local_log){ print "Updated binary from $updated_binary\n"; unlink $local_log; } } exit; unix/plugins/inventory0000755000000000000000000002322512130124376014206 0ustar rootroot#!/usr/bin/perl ############################################################################### # # Copyright (c) 2009 Artica Soluciones Tecnologicas S.L. # # inventory Generate a hardware/software inventory. # # Sample usage: ./inventory [cpu] [ram] [video] [nic] [hd] [cdrom] [software] [init_services] [filesystem] [process] [users] # # This program 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; version 2 of the License. # # This program 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. # ############################################################################### use strict; use constant TSTAMP_FILE => '/tmp/pandora_inventory.tstamp'; # Operation mode (LSHW or HWINFO) my $Mode; # Item separator my $Separator; # Parse module information sub get_module_data ($$$$) { my ($name, $hwinfo, $keys, $modules) = @_; my %module; # Parse module data while (my $line = shift (@{$hwinfo})) { if ($line =~ /$Separator/) { unshift (@{$hwinfo}, $line); last; } foreach my $key (@{$keys}) { if ($line =~ /$key:\s+(.+)/) { $module{$key} = $1; push (@{$module{'_keys'}}, $key); } } } # No data found my @data = keys (%module); return unless ($#data >= 0); push (@{$modules->{$name}}, \%module); } # Get a list of information file system in machine sub get_file_system($$) { my ($name, $modules) = @_; my @fileSystems = `df -h | tail -n +2`; #remove the titles of columns foreach my $row (@fileSystems) { next unless ($row =~ /^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s+\S+\s+(\S+)/); my %module; $module{'filesystem'} = $1; $module{'used'} = $2; $module{'avail'} = $3; $module{'mount'} = $4; $module{'_keys'} = ['filesystem', 'used','avail', 'mount']; push (@{$modules->{$name}}, \%module); } } # Get a list of services init in machine sub get_servicies_init_machine($$) { my ($name, $modules) = @_; my $runlevel = `runlevel | cut -d' ' -f2`; #ini trim($runlevel) $runlevel =~ s/^\s*//; #ltrim $runlevel =~ s/\s*$//; #rtrim #end trim($runlevel) # We ned to strip ";" characters because will be used as field separator! my $script = "ls /etc/rc" . $runlevel .".d/ -l | grep \"^l.*\" | grep \" S.* \" | cut -d' ' -f11 | tr -d \";\" "; my @services = `$script`; foreach my $row (@services) { next unless ($row =~ /^\S+\/(\S+)$/); my %module; $module{'service'} = $1; $module{'_keys'} = ['service']; push (@{$modules->{$name}}, \%module); } } # Get a list of running processes sub get_processes ($$) { my ($name, $modules) = @_; # We ned to strip ";" characters because will be used as field separator! my $script = "ps -eo command | tr -d \";\" "; my @services = `$script`; foreach my $row (@services) { my %module; # Remove carriage returns $row =~ s/[\n\l\f]//g; $module{'service'} = $row; $module{'_keys'} = ['service']; push (@{$modules->{$name}}, \%module); } } # Get a list of valid users in the system sub get_users ($$) { my ($name, $modules) = @_; my $script = "cat /etc/passwd"; my $user = ""; my $estado = ""; my @services = `$script`; foreach my $row (@services) { my %module; next unless ($row =~ /^([A-Za-z0-9\-\_]*)/); $user = $1; $script = `passwd -S $user`; if ( $script =~ /^(\S+)\sP./){ $module{'user'} = $user; $module{'_keys'} = ['user']; push (@{$modules->{$name}}, \%module); } } } # Show Kernel Information sub get_kernel_info ($$) { my ($name, $modules) = @_; my $script = `uname -a | tr -d \";\"`; my %module; $module{'Kernel'} = $script; $module{'_keys'} = ['Kernel']; push (@{$modules->{$name}}, \%module); } # Get a list of installed programs sub get_software_module_data ($$) { my ($name, $modules) = @_; # Guess the current distribution my $distrib_id = ""; if ( -e "/etc/SuSE-release"){ $distrib_id = "SUSE"; } elsif ( -e "/etc/redhat-release"){ $distrib_id = "REDHAT"; } else { $distrib_id = "DEBIAN"; } # List installed programs my @soft; if ($distrib_id eq 'DEBIAN') { @soft = `dpkg -l | grep ii`; } else { # Sometimes rpm return data splitted in two lines, and with dupes. Thats bad for our inventory system @soft = `rpm -q -a --qf "ii %{NAME} %{VERSION} %{SUMMARY}\n" | grep "^ii" | sort -u`; } # Parse data foreach my $row (@soft) { next unless ($row =~ /^ii\s+(\S+)\s+(\S+)\s+([^\n]+)/); my %module; $module{'program'} = $1; $module{'version'} = $2; $module{'description'} = $3; $module{'_keys'} = ['program', 'version','description']; push (@{$modules->{$name}}, \%module); } } # Print module data sub print_module ($$) { my ($name, $module) = @_; print " \n"; print " \n"; print " \n"; foreach my $item (@{$module}) { # Compose module data my $data = ''; foreach my $key (@{$item->{'_keys'}}) { next unless defined ($item->{$key}); $data .= ($data eq '' ? '' : ';') . $item->{$key}; } print " \n"; } print " \n"; print " \n"; } # Check command line parameters if ($#ARGV < 0) { print "Usage: $0 [cpu] [ram] [video] [nic] [hd] [cdrom] [software] [init_services] [filesystem] [users] [process] [kernel] \n\n"; exit 1; } # Parse command line parameters my %enabled; my $interval = 1; my $enable_all = 0; $interval = $ARGV[0]; if ($#ARGV == 0){ $enable_all = 1; } foreach my $module (@ARGV) { if ($module eq "all"){ $enable_all = 1; } $enabled{$module} = 1; } # Check execution interval if (-f TSTAMP_FILE) { open (FILE, '<' . TSTAMP_FILE) || exit 1; my $last_execution = ; close (FILE); exit 0 if ($last_execution + 86400 * $interval > time ()); } open (FILE, '>' . TSTAMP_FILE) || exit 1; print FILE time (); close (FILE); # Retrieve hardware information $Mode = 'LSHW'; $Separator = ''; my @hwinfo = `lshw 2>/dev/null`; if ($? != 0) { $Mode = 'HWINFO'; $Separator = 'Hardware Class:'; @hwinfo = `hwinfo --cpu --memory --gfxcard --netcard --cdrom --disk 2>/dev/null`; } # Parse hardware information my %modules; while (my $line = shift (@hwinfo)) { chomp ($line); # CPU if (($line =~ /\*\-cpu/ || $line =~ /Hardware Class: cpu/) && ($enable_all == 1 || $enabled{'cpu'} == 1)) { if ($Mode eq 'LSHW') { get_module_data ('CPU', \@hwinfo, ['product', 'vendor', 'capacity'], \%modules); } else { get_module_data ('CPU', \@hwinfo, ['Model', 'Vendor', 'Clock'], \%modules); } } # RAM if (($line =~ /\*\-bank/ || $line =~ /Hardware Class: memory/) && ($enable_all == 1 || $enabled{'ram'} == 1)) { if ($Mode eq 'LSHW') { get_module_data ('RAM', \@hwinfo, ['description', 'size'], \%modules); } else { get_module_data ('RAM', \@hwinfo, ['Model', 'Memory Size'], \%modules); } } # VIDEO if (($line =~ /\*\-display/ || $line =~ /Hardware Class: graphics card/) && ($enable_all == 1 || $enabled{'video'} == 1)) { if ($Mode eq 'LSHW') { get_module_data ('VIDEO', \@hwinfo, ['product', 'description', 'vendor'], \%modules); } else { # Spaces before Device and Vendor are intentional to avoid matching SubDevice and SubVendor get_module_data ('VIDEO', \@hwinfo, ['Model', ' Device', ' Vendor'], \%modules); } } # NIC if (($line =~ /\*\-network/ || $line =~ /Hardware Class: network/) && ($enable_all == 1 || $enabled{'nic'} == 1)) { if ($Mode eq 'LSHW') { get_module_data ('NIC', \@hwinfo, ['product', 'description', 'vendor'], \%modules); } else { # Spaces before Device and Vendor are intentional to avoid matching SubDevice and SubVendor get_module_data ('NIC', \@hwinfo, ['Model', ' Device', ' Vendor'], \%modules); } } # CDROM if (($line =~ /\*\-cdrom/ || $line =~ /Hardware Class: cdrom/) && ($enable_all == 1 || $enabled{'cdrom'} == 1)) { if ($Mode eq 'LSHW') { get_module_data ('CDROM', \@hwinfo, ['product', 'description', 'vendor'], \%modules); } else { # Spaces before Device and Vendor are intentional to avoid matching SubDevice and SubVendor get_module_data ('CDROM', \@hwinfo, ['Model', ' Device', ' Vendor'], \%modules); } } # HD if (($line =~ /\*\-disk/ || $line =~ /Hardware Class: disk/) && ($enable_all == 1 || $enabled{'hd'} == 1)) { if ($Mode eq 'LSHW') { get_module_data ('HD', \@hwinfo, ['product', 'description', 'size'], \%modules); } else { get_module_data ('HD', \@hwinfo, ['Model', 'Serial ID', 'Size'], \%modules); } } } # Software if ($enable_all == 1 || $enabled{'software'} == 1) { get_software_module_data ('Software', \%modules); } #init_services if ($enable_all == 1 || $enabled{'init_services'} == 1) { get_servicies_init_machine ('Init services', \%modules); } #filesystem if ($enable_all == 1 || $enabled{'filesystem'} == 1) { get_file_system('File system', \%modules); } #processes if ($enable_all == 1 || $enabled{'process'} == 1) { get_processes('Process', \%modules); } #users if ($enable_all == 1 || $enabled{'users'} == 1){ get_users ('Users', \%modules); } #kernel if ($enable_all == 1 || $enabled{'kernel'} == 1){ get_kernel_info ('Kernel', \%modules); } # Print module data print "\n"; while (my ($name, $module) = each (%modules)) { print_module ($name, $module); } print "\n"; exit 0; unix/plugins/files_indir0000755000000000001440000000172511673617612014643 0ustar rootusers#!/bin/sh # Syntax: # # Directory_Name : Directory to check if [ -z "$1" ] then echo "You need too pass target directory to monitor" echo "Plugin will report CRITICAL if previous number" echo "of files in directory is greater than actual number" exit fi DIRE=$1 if [ `uname -s` = "FreeBSD" ];then DIRETMP=`echo $DIRE | /sbin/md5`; else DIRETMP=`echo $DIRE | md5sum | awk '{ print $1 }'` fi DIRETMP=/tmp/$DIRETMP CURRENT=`ls -la ${DIRE} | wc -l | tr -d ' '` if [ -e $DIRETMP ] then ANTERIOR=`cat $DIRETMP` else ANTERIOR=0 fi if [ $ANTERIOR -gt $CURRENT ] then DISPARA=0 else DISPARA=1 fi echo $CURRENT > $DIRETMP echo " Number of files in directory generic_proc $DISPARA Number of files generic_data $CURRENT " unix/Darwin/0000755000000000000000000000000012166524015011765 5ustar rootrootunix/Darwin/pandora_agent.conf0000644000000000000000000001417112166524015015442 0ustar rootroot# Base config file for Pandora FMS agents # Version 4.1, GNU/Linux # Licensed under GPL license v2, # Copyright (c) 2003-2012 Artica Soluciones Tecnologicas # http://www.pandorafms.com # General Parameters # ================== server_ip localhost server_path /var/spool/pandora/data_in temporal /tmp logfile /var/log/pandora/pandora_agent.log #include /etc/pandora/pandora_agent_alt.conf #broker_agent name_agent # Interval in seconds, 300 by default interval 300 # Debug mode only generate XML, and stop after first execution, # and does not copy XML to server. debug 0 # Optional. UDP Server to receive orders from outside # By default is disabled, set 1 to enable # Set port (41122 by default) # Set address to restrict who can order a agent restart (0.0.0.0 = anybody) # udp_server 0 udp_server_port 41122 udp_server_auth_address 0.0.0.0 # By default, agent takes machine name #agent_name adama #Parent agent_name #parent_agent_name caprica # Agent description #description This is a demo agent for Mac OS X. # Group assigned for this agent (descriptive, p.e: Servers) #group Servers # address: Enforce to server a ip address to this agent # You can also try to detect the first IP using "auto", for example #address auto # or setting a fixed IP address, like for example: #address 192.168.36.73 # Autotime: Enforce to server to ignore timestamp coming from this # agent, used when agents has no timer or it's inestable. 1 to enable # this feature #autotime 1 # Timezone offset: Difference with the server timezone #timezone_offset 0 # Agent position paramters # Those parameters define the geographical position of the agent # gis_exec: Call a script that returns a string with a fixed # format of latitude,longitude,altitude # i.e.: 41.377,-5.105,2.365 #gis_exec /tmp/gis.sh # This sets the GIS coordinates as fixed values: # latitude #latitude 0 # longitude #longitude 0 # altitude #altitude 0 #GPS Position description #position_description Madrid, centro # By default agent try to take default encoding defined in host. #encoding UTF-8 # Listening TCP port for remote server. By default is 41121 (for tentacle) # if you want to use SSH use 22, and FTP uses 21. server_port 41121 # Transfer mode: tentacle, ftp, ssh or local transfer_mode tentacle # Server password (Tentacle or FTP). Leave empty for no password (default). #server_pwd mypassword # Set to yes/no to enable/disable OpenSSL support for Tentacle (disabled by default). #server_ssl no # Extra options for the Tentacle client (for example, server_opts "-v -r 5"). #server_opts # delayed_startup defines number of seconds before start execution # for first time when startup Pandora FMS Agent #delayed_startup 10 # Pandora nice defines priority of execution. Less priority means more intensive execution # A recommended value is 10. 0 priority means no Pandora CPU protection enabled (default) #pandora_nice 0 # Cron mode replace Pandora FMS own task schedule each XX interval seconds by the use # of old style cron. You should add to crontab Pandora FMS agent script to use this mode. # This is disabled by default, and is not recommended. Use Pandora FMS internal scheduler # is much more safe #cron_mode # If set to 1 allows the agent to be configured via the web console (Only Enterprise version) #remote_config 1 # If set to 1 start Drone Agent's Proxy Mode # proxy_mode 1 # Max number of simmultaneus connection for proxy (by default 10) # proxy_max_connection 10 # Proxy timeout (by default 1s) # proxy_timeout 1 # Number of threads to execute modules in parallel #agent_threads 1 # User the agent will run as #pandora_user root # Enable or disable XML buffer. # If you are in a secured environment and want to enable the XML buffer you # should consider changing the temporal directory, since /tmp is world writable. #xml_buffer 0 # Minimum available bytes in the temporal directory to enable the XML buffer #temporal_min_size 1024 # Secondary server configuration # ============================== # If secondary_mode is set to on_error, data files are copied to the secondary # server only if the primary server fails. If set to always, data files are # always copied to the secondary server. #secondary_mode on_error #secondary_server_ip localhost #secondary_server_path /var/spool/pandora/data_in #secondary_server_port 41121 #secondary_transfer_mode tentacle #secondary_server_pwd mypassword #secondary_server_ssl no #secondary_server_opts # Module Definition # ================= # System information # vmstat syntax depends on linux distro and vmstat command version, please check before use it module_begin module_name cpu_user module_type generic_data module_interval 1 module_exec sar 1 2 | tail -1 | awk '{ print $2 }' module_max 100 module_min 0 module_description User CPU Usage (%) module_min_warning 70 module_max_warning 90 module_min_critical 91 module_max_critical 100 module_end #Get load average module_begin module_name Load Average module_type generic_data module_exec uptime | sed 's/.*load averages: //'|awk '{print $1}' module_description Average process in CPU (Last minute) module_end #Get free memory in MB module_begin module_name Cache mem free module_type generic_data module_exec vm_stat | grep 'Pages free'| awk '{print $3/256}' module_description Free cache memory in MB module_min_warning 500 module_max_warning 600 module_min_critical 100 module_max_critical 499 module_end #Count total number of processes module_begin module_name proctotal module_type generic_data module_exec ps -A | tail -n +2 | wc -l | sed 's/ //g' module_description Total processes module_min_warning 150 module_max_warning 249 module_min_critical 250 module_max_critical 300 module_end # Async data example module_begin module_name LastLogin module_type async_string module_exec last | head -1 | awk '{print $1}' module_description Monitor last user loggin module_end # Get disk space free in % module_begin module_name disk_root_free module_type generic_data module_exec df -kh / | tail -1 | awk '{ print 100-$5 }' module_max 100 module_min 0 module_description Free disk Percentage of root partition module_min_warning 70 module_max_warning 90 module_min_critical 91 module_max_critical 100 module_end unix/Darwin/com.pandorafms.pandorafms.plist0000644000000000000000000000116312112254021020067 0ustar rootroot Label com.pandorafms.pandorafms ProgramArguments /usr/bin/pandora_agent /etc/pandora RunAtLoad ServiceDescription PandoraFMS agent UserName root unix/Linux/0000755000000000001440000000000012166524015012027 5ustar rootusersunix/Linux/pandora_agent.conf0000644000000000000000000002050112166524015015307 0ustar rootroot# Base config file for Pandora FMS agents # Version 4.1, GNU/Linux # Licensed under GPL license v2, # Copyright (c) 2003-2009 Artica Soluciones Tecnologicas # http://www.pandorafms.com # General Parameters # ================== server_ip localhost server_path /var/spool/pandora/data_in temporal /tmp logfile /var/log/pandora/pandora_agent.log #include /etc/pandora/pandora_agent_alt.conf #broker_agent name_agent # Interval in seconds, 300 by default interval 300 # Debug mode only generate XML, and stop after first execution, # and does not copy XML to server. debug 0 # Optional. UDP Server to receive orders from outside # By default is disabled, set 1 to enable # Set port (41122 by default) # Set address to restrict who can order a agent restart (0.0.0.0 = anybody) # udp_server 0 udp_server_port 41122 udp_server_auth_address 0.0.0.0 # By default, agent takes machine name #agent_name adama #Parent agent_name #parent_agent_name caprica # Agent description #description This is a demo agent for Linux # Group assigned for this agent (descriptive, p.e: Servers) #group Servers # address: Enforce to server a ip address to this agent # You can also try to detect the first IP using "auto", for example address auto # or setting a fixed IP address, like for example: #address 192.168.36.73 # Autotime: Enforce to server to ignore timestamp coming from this # agent, used when agents has no timer or it's inestable. 1 to enable # this feature #autotime 1 # Timezone offset: Difference with the server timezone #timezone_offset 0 # Agent position paramters # Those parameters define the geographical position of the agent # gis_exec: Call a script that returns a string with a fixed # format of latitude,longitude,altitude # i.e.: 41.377,-5.105,2.365 #gis_exec /tmp/gis.sh # This sets the GIS coordinates as fixed values: # latitude #latitude 0 # longitude #longitude 0 # altitude #altitude 0 #GPS Position description #position_description Madrid, centro # By default agent try to take default encoding defined in host. #encoding UTF-8 # Listening TCP port for remote server. By default is 41121 (for tentacle) # if you want to use SSH use 22, and FTP uses 21. server_port 41121 # Transfer mode: tentacle, ftp, ssh or local transfer_mode tentacle # Server password (Tentacle or FTP). Leave empty for no password (default). #server_pwd mypassword # Set to yes/no to enable/disable OpenSSL support for Tentacle (disabled by default). #server_ssl no # Extra options for the Tentacle client (for example, server_opts "-v -r 5"). #server_opts # delayed_startup defines number of seconds before start execution # for first time when startup Pandora FMS Agent #delayed_startup 10 # Pandora nice defines priority of execution. Less priority means more intensive execution # A recommended value is 10. 0 priority means no Pandora CPU protection enabled (default) #pandora_nice 0 # Cron mode replace Pandora FMS own task schedule each XX interval seconds by the use # of old style cron. You should add to crontab Pandora FMS agent script to use this mode. # This is disabled by default, and is not recommended. Use Pandora FMS internal scheduler # is much more safe #cron_mode # If set to 1 allows the agent to be configured via the web console (Only Enterprise version) remote_config 0 # If set to 1 start Drone Agent's Proxy Mode # proxy_mode 1 # Max number of simmultaneus connection for proxy (by default 10) # proxy_max_connection 10 # Proxy timeout (by default 1s) # proxy_timeout 1 # Number of threads to execute modules in parallel #agent_threads 1 # User the agent will run as #pandora_user root # Enable or disable XML buffer. # If you are in a secured environment and want to enable the XML buffer you # should consider changing the temporal directory, since /tmp is world writable. #xml_buffer 0 # Minimum available bytes in the temporal directory to enable the XML buffer #temporal_min_size 1024 # Secondary server configuration # ============================== # If secondary_mode is set to on_error, data files are copied to the secondary # server only if the primary server fails. If set to always, data files are # always copied to the secondary server. #secondary_mode on_error #secondary_server_ip localhost #secondary_server_path /var/spool/pandora/data_in #secondary_server_port 41121 #secondary_transfer_mode tentacle #secondary_server_pwd mypassword #secondary_server_ssl no #secondary_server_opts # Module Definition # ================= # System information # vmstat syntax depends on linux distro and vmstat command version, please check before use it module_begin module_name cpu_user module_type generic_data module_interval 1 module_exec vmstat 1 2 | tail -1 | awk '{ print $13 }' module_max 100 module_min 0 module_description User CPU Usage (%) module_min_warning 70 module_max_warning 90 module_min_critical 91 module_max_critical 100 module_unit % module_end #Get load average module_begin module_name Load Average module_type generic_data module_exec cat /proc/loadavg | cut -d' ' -f1 module_description Average process in CPU (Last minute) module_end #Get free memory in MB module_begin module_name Cache mem free module_type generic_data module_exec free -m | grep buffers/cache | awk '{print $4}' module_description Free cache memory in MB module_min_warning 500 module_max_warning 600 module_min_critical 100 module_max_critical 499 module_unit MB module_end #Count total number of processes module_begin module_name proctotal module_type generic_data module_exec ps -A | tail --lines=+5 | wc -l module_description Total processes module_min_warning 150 module_max_warning 249 module_min_critical 250 module_max_critical 300 module_unit processes module_end # Process information module_begin module_name sshDaemon module_type generic_proc module_exec ps -Af | grep sshd | grep -v "grep" | wc -l module_description Check ssh service module_end # Async data example module_begin module_name LastLogin module_type async_string module_exec last | head -1 module_description Monitor last user loggin module_end # Module that get the number of cron file # This module uses a precondition, if cron is running the # module will check the folder /etc/cron.d to get the number of files module_begin module_name Cron task files module_type async_string module_precondition =~ .*cron.* ps aux | grep cron module_exec ls -l /etc/cron.d | awk 'NR>1 {print $0}' | wc -l module_description Number of cron task files module_unit files module_end # Plugin example # This plugin detects all disk partitions and monitor the free spaces module_plugin pandora_df # This parses /var/log/syslog file, under the module name "syslog" # And search for "ssh" string into it, sending only that information. module_plugin grep_log /var/log/syslog Syslog ssh # Get disk space free in MB #module_begin #module_name disk_root_free #module_type generic_data #module_exec df -kh / | tail -1 | awk '{ print 100-$5 }' #module_max 100 #module_min 0 #module_description Free disk Percentage of root partition #module_min_warning 70 #module_max_warning 90 #module_min_critical 91 #module_max_critical 100 #module_end # This module uses postprocess feature to unit conversion #module_begin #module_name memused #module_type generic_data #module_exec free -k | grep buffers/cache | awk '{print $3}' #module_postprocess 0,000976 #module_description Used memory in KB postprocessed to be in MB #module_end # Plugin for inventory on the agent (Only Enterprise) # module_plugin inventory 1 cpu ram video nic hd cdrom software init_services filesystem users process ip route # Example of preconditions #module_begin #module_name Test Precondicion #module_type generic_data #module_precondition < 10 echo 5 #module_precondition > 10 echo 15 #module_precondition = 10 echo 10 #module_precondition != 10 echo 5 #module_precondition =~ 10 echo 10 #module_precondition (5,15) echo 10 #module_freepercentmemory #module_description Precondition test module #module_end # Example of postconditions #module_begin #module_name Test Postcondicion #module_type generic_data #module_condition < 10 echo min >> /tmp/log.txt #module_condition > 3 echo max >> /tmp/log.txt #module_condition = 5 echo equal >> /tmp/log.txt #module_condition != 10 echo diff >> /tmp/log.txt #module_condition =~ 5 echo regexp >> /tmp/log.txt #module_condition (3,8) echo range >> /tmp/log.txt #module_exec echo 5 #module_description Postcondition test module #module_end unix/SunOS/0000755000000000001440000000000012166524015011737 5ustar rootusersunix/SunOS/pandora_agent.conf0000644000000000000000000001174612166524015015232 0ustar rootroot# Base config file for Pandora FMS agents # Version 4.1, Solaris Version # Licensed under GPL license v2, # Copyright (c) 2003-2009 Artica Soluciones Tecnologicas # http://www.pandorafms.com # General Parameters # ================== server_ip localhost server_path /var/spool/pandora/data_in temporal /tmp logfile /var/log/pandora/pandora_agent.log #include /etc/pandora/pandora_agent_alt.conf #broker_agent name_agent # Interval in seconds, 300 by default interval 300 # Debug mode only generate XML, and stop after first execution, # and does not copy XML to server. debug 0 # By default, agent takes machine name #agent_name xxxxxx # Agent description #description Demo agent # Group assigned for this agent (descriptive, p.e: Servers) #group Servers # Autotime: Enforce to server to ignore timestamp coming from this # agent, used when agents has no timer or it's inestable. 1 to enable # this feature # autotime 1 # Timezone offset: Difference with the server timezone #timezone_offset 0 # Agent position paramters # Those parameters define the geographical position of the agent # latitude #latitude 0 # longitude #longitude 0 # altitude #altitude 0 # By default agent try to take default encoding defined in host. # encoding UTF-8 # Listening TCP port for remote server. By default is 41121 (for tentacle) # if you want to use SSH use 22, and FTP uses 21. server_port 41121 # Transfer mode: tentacle, ftp, ssh or local transfer_mode tentacle # Server password (Tentacle or FTP). Leave empty for no password (default). # server_pwd mypassword # Set to yes/no to enable/disable OpenSSL support for Tentacle (disabled by default). # server_ssl no # Extra options for the Tentacle client (for example, server_opts "-v -r 5"). # server_opts # delayed_startup defines number of seconds before start execution # for first time when startup Pandora FMS Agent # delayed_startup 10 # Pandora nice defines priority of execution. Less priority means more intensive execution # A recommended value is 10. 0 priority means no Pandora CPU protection enabled (default) # pandora_nice 0 # Cron mode replace Pandora FMS own task schedule each XX interval seconds by the use # of old style cron. You should add to crontab Pandora FMS agent script to use this mode. # This is disabled by default, and is not recommended. Use Pandora FMS internal scheduler # is much more safe. # cron_mode # If set to 1 allows the agent to be configured via the web console (Only Enterprise version) # remote_config 1 # If set to 1 start Drone Agent's Proxy Mode # proxy_mode 1 # Max number of simmultaneus connection for proxy (by default 10) # proxy_max_connection 10 # Proxy timeout (by default 1s) # proxy_timeout 1 # User the agent will run as #pandora_user root # Secondary server configuration # ============================== # If secondary_mode is set to on_error, data files are copied to the secondary # server only if the primary server fails. If set to always, data files are # always copied to the secondary server. # secondary_mode on_error # secondary_server_ip localhost # secondary_server_path /var/spool/pandora/data_in # secondary_server_port 41121 # secondary_transfer_mode tentacle # secondary_server_pwd mypassword # secondary_server_ssl no # secondary_server_opts # Module Definition # ================= # System information module_begin module_name disk_root_free module_type generic_data module_exec df -k / | tail -1 | tr -d "%" | awk '{ print 100-$5 }' module_max 100 module_min 0 module_description Free disk Percentage of root partition module_end module_begin module_name proctotal module_type generic_data module_exec ps -Alf | wc -l | awk '{ print $1 }' module_end module_begin module_name sshDaemon module_type generic_proc module_exec ps -Af | grep sshd | grep -v "grep" | wc -l | awk '{ print $1 }' module_end # Async data example module_begin module_name LastLogin module_type async_string module_exec last | head -1 module_end module_begin module_name Swap_Free module_type generic_data module_exec vmstat 1 2 | tail -1 | awk '{ print $4 }' module_description Unused swap memory module_end module_begin module_name RAM_Free module_type generic_data module_exec vmstat 1 2 | tail -1 | awk '{ print $5 }' module_description Unused RAM memory module_end module_begin module_name CPU_User module_type generic_data module_exec vmstat 1 2 | tail -1 | awk '{ print $20 }' module_description % of USER CPU module_end module_begin module_name CPU_System module_type generic_data module_exec vmstat 1 2 | tail -1 | awk '{ print $21 }' module_description % of system CPU module_end module_begin module_name Disk_Seek_Operations module_type generic_data module_exec vmstat 1 2 | tail -1 | awk '{ print $14 }' module_description Disk Seek operations module_end module_begin module_name Pandora_Agent_RAM module_type generic_data module_exec ps -Afly | grep perl | grep -v grep | awk '{ print $9 }' module_description Return size in KB of memory used by process Pandora module_end module_plugin grep_log /var/adm/syslog Syslog . unix/SunOS/make_solaris_package/0000755000000000001440000000000012074374423016067 5ustar rootusersunix/SunOS/make_solaris_package/README0000644000000000001440000000053111673617616016756 0ustar rootusersThis directory contains Pandora FMS agent package builder for Solaris. To make the Solaris package, execute: ./make_solaris_package.sh It works with x86/SPARC Solaris 9 or 10. The package file, named "PandoraFMS-agent-X.X.X.pkg", will be created. You can install it to Solaris 9 or 10 like this: pkgadd -d ./PandoraFMS-agent-X.X.X.pkg unix/SunOS/make_solaris_package/make_solaris_package.sh0000755000000000000000000000427512074374423022373 0ustar rootroot#!/bin/sh # ********************************************************************** # Pandora FMS Agent package builder for Solaris # (c) 2010-2013 Junichi Satoh # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public License # as published by the Free Software Foundation; version 2 # # This program 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. # # ********************************************************************** AGENT_VERSION="4.0.3" PKGFILE="PandoraFMS-agent-$AGENT_VERSION.pkg" # make pkginfo file DATE=`date '+%Y%m%d%H'` echo "PKG=PandoraAgent" > pkginfo echo "NAME=Pandora FMS agent" >> pkginfo echo "ARCH=all" >> pkginfo echo "CATEGORY=application" >> pkginfo echo "VERSION=$AGENT_VERSION" >> pkginfo echo "VENDOR=http://pandorafms.org/" >> pkginfo echo "PSTAMP=$DATE" >> pkginfo echo "CLASSES=none" >> pkginfo echo "BASEDIR=/" >> pkginfo # make work directory. mkdir -p /tmp/pandora/usr/bin mkdir -p /tmp/pandora/usr/man/man1 mkdir -p /tmp/pandora/etc/pandora mkdir -p /tmp/pandora/etc/init.d mkdir -p /tmp/pandora/usr/share/pandora_agent/plugins # copy executables cp ../../pandora_agent /tmp/pandora/usr/bin cp ../../tentacle_client /tmp/pandora/usr/bin cp ../../tentacle_server /tmp/pandora/usr/bin cp ../../pandora_agent_daemon /tmp/pandora/etc/init.d cp ../../pandora_agent_exec /tmp/pandora/usr/bin # copy plugin files cp ../../plugins/* /tmp/pandora/usr/share/pandora_agent/plugins # copy configuration file cp ../pandora_agent.conf /tmp/pandora/etc/pandora # copy man pages cp ../../man/man1/pandora_agent.1.gz /tmp/pandora/usr/man/man1 gunzip /tmp/pandora/usr/man/man1/pandora_agent.1.gz cp ../../man/man1/tentacle_client.1.gz /tmp/pandora/usr/man/man1 gunzip /tmp/pandora/usr/man/man1/tentacle_client.1.gz # make package. pkgmk -o -r /tmp/pandora -d /tmp/pandora CURRENT_DIR=`pwd` pkgtrans -s /tmp/pandora $CURRENT_DIR/$PKGFILE PandoraAgent # delete work files rm -rf /tmp/pandora echo "" echo "pkg file is created: $PKGFILE" unix/SunOS/make_solaris_package/prototype0000644000000000001440000000220311673617616020064 0ustar rootusersi pkginfo i copyright f none usr/bin/pandora_agent 0755 root root f none usr/bin/tentacle_client 0755 root root f none usr/bin/tentacle_server 0755 root root f none usr/bin/pandora_agent_exec 0755 root root d none usr/share/pandora_agent 0755 root root d none usr/share/pandora_agent/plugins 0755 root root f none usr/share/pandora_agent/plugins/files_indir 0755 root root f none usr/share/pandora_agent/plugins/grep_log 0755 root root f none usr/share/pandora_agent/plugins/inventory 0755 root root f none usr/share/pandora_agent/plugins/pandora_df 0755 root root f none usr/share/pandora_agent/plugins/nagios_plugin_wrapper 0755 root root f none usr/share/pandora_agent/plugins/pandora_update 0755 root root d none etc/pandora/ 0755 root root f none etc/pandora/pandora_agent.conf 0755 root root f none usr/man/man1/pandora_agent.1 0644 root root f none usr/man/man1/tentacle_client.1 0644 root root d none var/spool/pandora 0755 root root d none var/spool/pandora/data_out 0755 root root d none var/log/pandora 0755 root root f none etc/init.d/pandora_agent_daemon 0755 root root s none etc/rc2.d/S90pandora_agent_daemon=../init.d/pandora_agent_daemon unix/SunOS/make_solaris_package/copyright0000644000000000001440000000012611673617616020031 0ustar rootusersLicensed under GPL license v2. Copyright (c) 2003-2010 Artica Soluciones Tecnologicas unix/HP-UX/0000755000000000001440000000000012166524015011571 5ustar rootusersunix/HP-UX/pandora_agent.conf0000644000000000000000000001152112166524015015053 0ustar rootroot# Base config file for Pandora FMS agents # Version 4.1, HP-UX Version # Licensed under GPL license v2, # Copyright (c) 2003-2009 Artica Soluciones Tecnologicas # http://www.pandorafms.com # General Parameters # ================== server_ip localhost server_path /var/spool/pandora/data_in temporal /tmp logfile /var/log/pandora/pandora_agent.log #include /etc/pandora/pandora_agent_alt.conf #broker_agent name_agent # Interval in seconds, 300 by default interval 300 # Debug mode only generate XML, and stop after first execution, # and does not copy XML to server. debug 0 # By default, agent takes machine name #agent_name xxxxxx # Agent description #description Demo agent # Group assigned for this agent (descriptive, p.e: Servers) #group Servers # Autotime: Enforce to server to ignore timestamp coming from this # agent, used when agents has no timer or it's inestable. 1 to enable # this feature # autotime 1 # Timezone offset: Difference with the server timezone #timezone_offset 0 # Agent position paramters # Those parameters define the geographical position of the agent # latitude #latitude 0 # longitude #longitude 0 # altitude #altitude 0 # By default agent try to take default encoding defined in host. # encoding UTF-8 # Listening TCP port for remote server. By default is 41121 (for tentacle) # if you want to use SSH use 22, and FTP uses 21. server_port 41121 # Transfer mode: tentacle, ftp, ssh or local transfer_mode tentacle # Server password (Tentacle or FTP). Leave empty for no password (default). # server_pwd mypassword # Set to yes/no to enable/disable OpenSSL support for Tentacle (disabled by default). # server_ssl no # Extra options for the Tentacle client (for example, server_opts "-v -r 5"). # server_opts # delayed_startup defines number of seconds before start execution # for first time when startup Pandora FMS Agent # delayed_startup 10 # Pandora nice defines priority of execution. Less priority means more intensive execution # A recommended value is 10. 0 priority means no Pandora CPU protection enabled (default) # pandora_nice 0 # Cron mode replace Pandora FMS own task schedule each XX interval seconds by the use # of old style cron. You should add to crontab Pandora FMS agent script to use this mode. # This is disabled by default, and is not recommended. Use Pandora FMS internal scheduler # is much more safe. # cron_mode # If set to 1 allows the agent to be configured via the web console (Only Enterprise version) # remote_config 1 # If set to 1 start Drone Agent's Proxy Mode # proxy_mode 1 # Max number of simmultaneus connection for proxy (by default 10) # proxy_max_connection 10 # Proxy timeout (by default 1s) # proxy_timeout 1 # User the agent will run as #pandora_user root # Secondary server configuration # ============================== # If secondary_mode is set to on_error, data files are copied to the secondary # server only if the primary server fails. If set to always, data files are # always copied to the secondary server. # secondary_mode on_error # secondary_server_ip localhost # secondary_server_path /var/spool/pandora/data_in # secondary_server_port 41121 # secondary_transfer_mode tentacle # secondary_server_pwd mypassword # secondary_server_ssl no # secondary_server_opts # Module Definition # ================= # System information # All this commands has been tested on a Standard HP-UX B.11.31 module_begin module_name disk_usage_/ module_type generic_data module_exec df -P | grep -e "/$" | awk '{print $5}' | tr -d % module_description Disk usage on / (%) module_end module_begin module_name disk_usage_/var module_type generic_data module_exec df -P | grep -e "/var$" | awk '{print $5}' | tr -d % module_description Disk usage on / var(%) module_end module_begin module_name proctotal module_type generic_data module_exec ps -ex | wc -l | awk '{ print $1 }' module_end module_begin module_name sshDaemon module_type generic_proc module_exec ps -Af | grep "sshd" | grep -v "grep" | wc -l | awk '{ print $1 }' module_end # Async data example module_begin module_name LastLogin module_type async_string module_exec last | head -1 module_end module_begin module_name Swap_Free module_type generic_data module_exec /usr/sbin/swapinfo -t | grep memory | tr -d "%" | awk '{ print 100-$5 }' module_description Unused swap memory module_end module_begin module_name RAM_Free module_type generic_data module_exec /usr/sbin/swapinfo -t | grep memory | awk '{print $4}' module_description Unused RAM memory module_end module_begin module_name CPU_User module_type generic_data module_exec vmstat 1 2 | tail -1 | awk '{ print $16 }' module_description % of USER CPU module_end module_begin module_name CPU_System module_type generic_data module_exec vmstat 1 2 | tail -1 | awk '{ print $17 }' module_description % of system CPU module_end module_plugin grep_log /var/adm/syslog/syslog.log Syslog . unix/pandora_agent_exec0000755000000000001440000000332011673617616014476 0ustar rootusers#!/usr/bin/perl ########################################################################## # pandora_agent_exec # # Executes the given command and prints its output to stdout. If the # execution times out or the command does not exist nothing is printed # to stdout. This is part of Pandora FMS Plugin server, do not delete!. # # Usage: pandora_agent_exec ########################################################################## # Copyright (c) 2008-2010 Ramon Novoa, rnovoa@gmail.com # (c) 2008-2010 Artica Soluciones Tecnologicas S.L # # This program 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; version 2. # # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ########################################################################## use strict; use warnings; # Check command line parameters if ($#ARGV < 1) { exit 1; } my @opts = @ARGV; my $timeout = shift(@opts); my $command = join(' ', @opts); my $output = ''; my $ReturnCode = 0; # Execute the command eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm $timeout; $output = `$command`; $ReturnCode = ($? >> 8) & 0xff; alarm 0; }; # Timeout if ($@ eq "alarm\n") { exit 3; } print $output; exit $ReturnCode; unix/AUTHORS0000644000000000001440000000015711673617616012017 0ustar rootusersSancho Lerena Manuel Arostegui Ramon Novoa unix/pandora_agent_installer0000755000000000000000000004214712112254021015342 0ustar rootroot#!/bin/sh #trap 'echo error at line $LINENO 1>&2' ERR set -u set -e # ********************************************************************** # Pandora FMS Agent Installer for Unix (generic installer) # (c) 2008-2013 Artica ST # (c) 2008-2013 Sancho Lerena # # This is a generic installer for all Unix-like systems.(AIX, HP-UX, SunOS, Linux, FreeBSD) # Please see http://www.pandorafms.org. This code is licensed under GPL 2.0 license. # ********************************************************************** PI_VERSION=4.0.3s PI_BUILD=130108 OS_NAME=`uname -s` FORCE=0 LOG_TIMESTAMP=`date +"%Y/%m/%d %H:%M:%S"` PANDORA_HOME=/usr/share/pandora_agent PANDORA_BIN=/usr/bin/pandora_agent PANDORA_EXEC_BIN=/usr/bin/pandora_agent_exec PANDORA_TEMP=/var/spool/pandora PANDORA_CFG=/etc/pandora PANDORA_LOG_DIR=/var/log/pandora PANDORA_LOG=pandora_agent.log TENTACLE=/usr/bin/tentacle_client TENTACLE_SERVER=/usr/bin/tentacle_server PANDORA_MAN=/usr/share/man MODE=${1:-} PANDORA_BASE=`echo ${2:-} | sed -e 's/\/$//'` if [ "${3:-}" != "" ] then PANDORA_USER=$3 else PANDORA_USER="root" fi # Check for Perl 5.6.x or higher available PERL_VERSION=`perl -v | egrep 'v5.6|v5.7|v5.8|v5.9|v5.1[0-9]' | grep perl` if [ -z "$PERL_VERSION" ] then echo "Perl 5.6.x or higher is not detected. This is required for Pandora FMS" 1>&2 echo "Detected: $PERL_VERSION " 1>&2 echo "Aborting install..." 1>&2 exit 2 fi UNIX_KIND=`uname -s` if [ -z "`echo Linux HP-UX SunOS AIX Solaris Darwin BSD bsd FreeBSD | grep \"$UNIX_KIND\"`" ] then echo "This system: '$UNIX_KIND' is not supported by this script" 1>&2 echo "Please make the install yourself as it's described in documentation" 1>&2 exit 1 fi # check for root to do the install if [ -z "`id | grep \"uid=0(root)\"`" ] then echo "You need to be root to do the install. Please made a manual install" 1>&2 echo "if you want to install Pandora FMS agent without root" 1>&2 echo " " 1>&2 echo "Aborting install" 1>&2 exit 2 fi help () { cat < [ destination_path ] [ user_to_run_as ] Modes: --force-install To force installation if already installed on system --install To install Pandora FMS Agent on this system --uninstall To uninstall/remove Pandora FMS Agent on this System Some exaples of how to use the installer: ./pandora_agent_installer --install ./pandora_agent_installer --install /opt/pandora ./pandora_agent_installer --install "" pandora ./pandora_agent_installer --uninstall /opt/pandora EOF } uninstall () { OS_NAME=`uname -s` if [ "$OS_NAME" = "FreeBSD" ] then PANDORA_HOME=/usr/local/share/pandora_agent PANDORA_BIN=/usr/local/bin/pandora_agent PANDORA_EXEC_BIN=/usr/local/bin/pandora_agent_exec PANDORA_CFG=/usr/local/etc/pandora TENTACLE=/usr/local/bin/tentacle_client TENTACLE_SERVER=/usr/local/bin/tentacle_server PANDORA_MAN=/usr/local/man fi echo "Removing Pandora FMS Agent..." rm -Rf $PANDORA_BASE$PANDORA_BIN 2> /dev/null rm -Rf $PANDORA_BASE$PANDORA_EXEC_BIN 2> /dev/null #Test if exist Pandora Server in this machine if [ -d $PANDORA_BASE$PANDORA_TEMP/data_in ] then echo "You have a Pandora Server in this machine. Then don't delete "$PANDORA_TEMP rm -Rf $PANDORA_BASE$PANDORA_TEMP/data_out 2> /dev/null else rm -Rf $PANDORA_BASE$PANDORA_TEMP 2> /dev/null rm -Rf $PANDORA_BASE$TENTACLE_SERVER 2> /dev/null fi rm -Rf $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf 2> /dev/null rm -Rf $PANDORA_BASE/etc/init.d/pandora_agent_daemon 2> /dev/null rm -Rf $PANDORA_BASE/sbin/init.d/pandora_agent_daemon 2> /dev/null rm -Rf $PANDORA_BASE/etc/rc.pandora_agent_daemon 2> /dev/null rm -Rf $PANDORA_BASE/etc/rc?.d/S90pandora_agent_daemon 2> /dev/null rm -Rf $PANDORA_BASE/sbin/rc?.d/S90pandora_agent_daemon 2> /dev/null rm -Rf $PANDORA_BASE/etc/rc?.d/S90pandora_agent 2> /dev/null rm -Rf $PANDORA_BASE/sbin/rc?.d/S90pandora_agent 2> /dev/null rm -Rf $PANDORA_BASE/etc/rc.d/rc?.d/S90pandora_agent_daemon 2> /dev/null rm -Rf $PANDORA_BASE/etc/rc.d/rc?.d/S90pandora_agent 2> /dev/null rm -Rf $PANDORA_BASE/usr/local/etc/rc.d/pandora_agent 2> /dev/null rm -Rf /etc/init.d/pandora_agent_daemon 2> /dev/null rm -Rf /sbin/init.d/pandora_agent_daemon 2> /dev/null rm -Rf /etc/rc.pandora_agent_daemon 2> /dev/null rm -Rf /etc/rc?.d/S90pandora_agent_daemon 2> /dev/null rm -Rf /sbin/rc?.d/S90pandora_agent_daemon 2> /dev/null rm -Rf /etc/rc?.d/S90pandora_agent 2> /dev/null rm -Rf /sbin/rc?.d/S90pandora_agent 2> /dev/null rm -Rf /etc/rc.d/rc?.d/S90pandora_agent_daemon 2> /dev/null rm -Rf /etc/rc.d/rc?.d/S90pandora_agent 2> /dev/null rm -Rf /usr/local/etc/rc.d/pandora_agent 2> /dev/null rm -Rf $PANDORA_BASE$PANDORA_HOME 2> /dev/null rm -Rf $PANDORA_BASE$PANDORA_LOG_DIR 2> /dev/null rm -Rf $PANDORA_BASE$TENTACLE 2> /dev/null rm -Rf $PANDORA_BASE$PANDORA_MAN/{man1,cat1}/tentacle_client.1.gz 2> /dev/null rm -Rf $PANDORA_BASE$PANDORA_MAN/{man1,cat1}/pandora_agent.1.gz 2> /dev/null # Skip delete of /etc/pandora if exists configuration of a server if [ ! -f $PANDORA_BASE/$PANDORA_CFG/pandora_server.conf ] then rm -Rf $PANDORA_BASE/$PANDORA_CFG 2> /dev/null fi if [ ! -z "$PANDORA_BASE" ] then echo "Please delete manually $PANDORA_BASE for complete uninstall" fi echo " " echo "Done" } install () { OS_VERSION=`uname -r` OS_NAME=`uname -s` OLDFILENAMETMP=`date +"%Y-%m-%d"` if [ "$OS_NAME" = "FreeBSD" ] then PANDORA_HOME=/usr/local/share/pandora_agent PANDORA_BIN=/usr/local/bin/pandora_agent PANDORA_EXEC_BIN=/usr/local/bin/pandora_agent_exec PANDORA_CFG=/usr/local/etc/pandora TENTACLE=/usr/local/bin/tentacle_client TENTACLE_SERVER=/usr/local/bin/tentacle_server PANDORA_MAN=/usr/local/man fi echo "Detecting Unix distribution: $OS_NAME version $OS_VERSION" if [ -f $PANDORA_BASE$PANDORA_HOME ] && [ "$FORCE" = "0" ] then echo "Seems that default dir already exists. Please use --force-install to" 1>&2 echo "force installer to install on $PANDORA_BASE$PANDORA_HOME" 1>&2 exit 1 else echo "Checking default dir $PANDORA_BASE$PANDORA_HOME..." fi if [ -f $PANDORA_BASE$PANDORA_BIN ] && [ "$FORCE" = "0" ] then echo "Seems that $PANDORA_BASE$PANDORA_BIN already exists. Please use --force-install to" 1>&2 echo "force installer to reinstall overwriting it" 1>&2 echo " " 1>&2 exit 1 else echo "Checking Pandora FMS Agent on $PANDORA_BASE$PANDORA_BIN...." fi # Alter dynamically the daemon launcher and setup the new path # if PANDORA_BASE is customized. if [ ! -z "$PANDORA_BASE" ] then if [ "$OS_NAME" = "FreeBSD" ] then DAEMON_SCRIPT=FreeBSD/pandora_agent DAEMON_TEMP=pandora_agent_daemon_temp else DAEMON_SCRIPT=pandora_agent_daemon DAEMON_TEMP=pandora_agent_daemon_temp fi # Backup the daemon script cp -f "$DAEMON_SCRIPT" "$DAEMON_SCRIPT.bak" AGENT_CFG=$OS_NAME/pandora_agent.conf AGENT_CFG_TEMP=$OS_NAME/pandora_agent.conf.temp # Check existence. if [ ! -r "$AGENT_CFG" ]; then echo "There is no default agent for the platform $OS_NAME. Please create one as $OS_NAME/pandora_agent.conf and send it to Pandora." 1>&2 exit 1 fi # Backup the configuration file cp -f "$AGENT_CFG" "$AGENT_CFG.bak" echo $PANDORA_BASE > PANDORA_BASE.temp sed 's/\//\\\//g' PANDORA_BASE.temp > PANDORA_BASE.temp2 PANDORA_BASE_DECODED=`cat PANDORA_BASE.temp2` rm PANDORA_BASE.temp PANDORA_BASE.temp2 if [ "$OS_NAME" = "FreeBSD" ] then sed -e "s/^PATH\=[.]*/PATH\=$PANDORA_BASE_DECODED\/usr\/local\/bin\:/g" $DAEMON_SCRIPT > $DAEMON_TEMP mv $DAEMON_TEMP $DAEMON_SCRIPT sed -e "s/^command\=[.]*/command\=$PANDORA_BASE_DECODED/g" $DAEMON_SCRIPT > $DAEMON_TEMP mv $DAEMON_TEMP $DAEMON_SCRIPT sed -e 's/^command_args\=\"[.]*/command_args\=\"$PANDORA_BASE_DECODED/g' $DAEMON_SCRIPT > $DAEMON_TEMP mv $DAEMON_TEMP $DAEMON_SCRIPT sed -e 's/^required_files\=\"[.]*/required_files\=\"$PANDORA_BASE_DECODED/g' $DAEMON_SCRIPT > $DAEMON_TEMP mv $DAEMON_TEMP $DAEMON_SCRIPT else sed -e "s/^PATH\=[.]*/PATH\=$PANDORA_BASE_DECODED\/usr\/bin\:/g" $DAEMON_SCRIPT > $DAEMON_TEMP mv $DAEMON_TEMP $DAEMON_SCRIPT sed -e "s/^PANDORA_PATH\=[.]*/PANDORA_PATH\=$PANDORA_BASE_DECODED/g" $DAEMON_SCRIPT > $DAEMON_TEMP mv $DAEMON_TEMP $DAEMON_SCRIPT sed -e "s/^LOGFILE\=[.]*/LOGFILE\=$PANDORA_BASE_DECODED/g" $DAEMON_SCRIPT > $DAEMON_TEMP mv $DAEMON_TEMP $DAEMON_SCRIPT sed -e "s/^DAEMON\=[.]*/DAEMON\=$PANDORA_BASE_DECODED/g" $DAEMON_SCRIPT > $DAEMON_TEMP mv $DAEMON_TEMP $DAEMON_SCRIPT sed -e "s/^PANDORA_USER\=.*/PANDORA_USER\=$PANDORA_USER/g" $DAEMON_SCRIPT > $DAEMON_TEMP mv $DAEMON_TEMP $DAEMON_SCRIPT fi sed -e "s/^temporal [.]*/temporal $PANDORA_BASE_DECODED/g" $AGENT_CFG > $AGENT_CFG_TEMP mv $AGENT_CFG_TEMP $AGENT_CFG sed -e "s/^logfile [.]*/logfile $PANDORA_BASE_DECODED/g" $AGENT_CFG > $AGENT_CFG_TEMP mv $AGENT_CFG_TEMP $AGENT_CFG fi echo "Creating Pandora FMS Agent home directory at $PANDORA_BASE$PANDORA_HOME" if [ ! -z "$PANDORA_BASE" ] then mkdir -p $PANDORA_BASE 2> /dev/null mkdir -p $PANDORA_BASE/var/log 2> /dev/null mkdir -p $PANDORA_BASE/$PANDORA_MAN/man1 2> /dev/null if [ "$OS_NAME" = "FreeBSD" ] then mkdir -p $PANDORA_BASE/usr/local/bin 2> /dev/null else mkdir -p $PANDORA_BASE/usr/bin 2> /dev/null fi fi mkdir -p $PANDORA_BASE$PANDORA_HOME 2> /dev/null # Create directories based on PANDORA_BASE mkdir -p $PANDORA_BASE/tmp 2> /dev/null mkdir -p $PANDORA_BASE$PANDORA_TEMP/data_out 2> /dev/null mkdir -p $PANDORA_BASE$PANDORA_CFG 2> /dev/null mkdir -p $PANDORA_BASE$PANDORA_LOG_DIR 2> /dev/null # Set the user the agent will run as if [ "$PANDORA_USER" != "root" ] then sed -e "s/.*pandora_user .*/pandora_user $PANDORA_USER/" $AGENT_CFG > $AGENT_CFG_TEMP 2> /dev/null && \ mv $AGENT_CFG_TEMP $AGENT_CFG chmod 755 pandora_agent_daemon chown -R $PANDORA_USER $PANDORA_BASE fi # Create logfile if [ ! -z "`touch $PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG`" ] then echo "Seems to be a problem generating logfile ($PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG) please check it"; else echo "Created logfile at $PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG..." fi echo "$LOG_TIMESTAMP Pandora FMS installer has created this file at startup" > $PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG # Copying agent and securing it echo "Copying Pandora FMS Agent to $PANDORA_BASE$PANDORA_BIN..." cp pandora_agent $PANDORA_BASE$PANDORA_BIN chmod 755 $PANDORA_BASE$PANDORA_BIN cp pandora_agent_exec $PANDORA_BASE$PANDORA_EXEC_BIN chmod 755 $PANDORA_BASE$PANDORA_EXEC_BIN chown $PANDORA_USER:0 $PANDORA_BASE$PANDORA_BIN chown $PANDORA_USER:0 $PANDORA_BASE$PANDORA_EXEC_BIN echo "Copying Pandora FMS Agent configuration file to $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf..." if [ -f $PANDORA_BASE/$PANDORA_CFG/pandora_agent.conf ] then cp $PANDORA_BASE/$PANDORA_CFG/pandora_agent.conf $PANDORA_BASE/$PANDORA_CFG/pandora_agent.conf.$OLDFILENAMETMP echo "Backing up old configuration file to $PANDORA_BASE/$PANDORA_CFG/pandora_agent.conf.$OLDFILENAMETMP" fi echo "Copying Pandora FMS Agent plugins to $PANDORA_BASE$PANDORA_HOME/plugins..." cp -r plugins $PANDORA_BASE$PANDORA_HOME chmod -R 700 $PANDORA_BASE$PANDORA_HOME/plugins ln -sf $PANDORA_BASE$PANDORA_HOME/plugins $PANDORA_BASE$PANDORA_CFG echo "Copying Pandora FMS Agent collections to $PANDORA_BASE$PANDORA_HOME/collections..." cp -r collections $PANDORA_BASE$PANDORA_HOME chmod -R 700 $PANDORA_BASE$PANDORA_HOME/collections ln -sf $PANDORA_BASE$PANDORA_HOME/collections $PANDORA_BASE$PANDORA_CFG echo "Copying tentacle server to $PANDORA_BASE$TENTACLE_SERVER" cp tentacle_server $PANDORA_BASE$TENTACLE_SERVER chmod 755 $PANDORA_BASE$TENTACLE_SERVER chown $PANDORA_USER:0 $PANDORA_BASE$TENTACLE_SERVER echo "Copying tentacle client to $PANDORA_BASE$TENTACLE" cp tentacle_client $PANDORA_BASE$TENTACLE chmod 755 $PANDORA_BASE$TENTACLE chown $PANDORA_USER:0 $PANDORA_BASE$TENTACLE echo "Installing the Pandora Agent and Tentacle Client manuals" cp man/man1/tentacle_client.1.gz $PANDORA_BASE/$PANDORA_MAN/man1 chmod 644 $PANDORA_BASE/$PANDORA_MAN/man1/tentacle_client.1.gz cp man/man1/pandora_agent.1.gz $PANDORA_BASE/$PANDORA_MAN/man1 chmod 644 $PANDORA_BASE/$PANDORA_MAN/man1/pandora_agent.1.gz echo "Setting secure permissions and ownership for all Pandora FMS Agent files..." chown -R $PANDORA_USER $PANDORA_BASE$PANDORA_HOME chmod -R 700 $PANDORA_BASE$PANDORA_TEMP/data_out chmod 711 $PANDORA_BASE$PANDORA_LOG_DIR chmod 640 $PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG chown $PANDORA_USER:0 $PANDORA_BASE$PANDORA_LOG_DIR/$PANDORA_LOG if [ "$OS_NAME" = "FreeBSD" ] then chown $PANDORA_USER:daemon $PANDORA_BASE$PANDORA_TEMP chmod -R 770 $PANDORA_BASE$PANDORA_TEMP chmod 775 $PANDORA_BASE$PANDORA_TEMP fi echo "Copying default agent configuration to $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf" # Check existence. if [ ! -r "$OS_NAME/pandora_agent.conf" ]; then echo "There is no default agent for the platform $OS_NAME. Please create one as $OS_NAME/pandora_agent.conf and send it to Pandora." 1>&2 exit 1 fi cp $OS_NAME/pandora_agent.conf $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf chmod 600 $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf chown $PANDORA_USER $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf if [ "$OS_NAME" = "FreeBSD" ] then echo "Linking start-up daemon script 'pandora_agent' on $OS_NAME"; else echo "Linking start-up daemon script 'pandora_agent_daemon' on $OS_NAME"; fi if [ "$OS_NAME" = "AIX" ] then cp pandora_agent_daemon /etc/rc.pandora_agent_daemon ln -sf /etc/rc.pandora_agent_daemon /etc/rc.d/rc2.d/S90pandora_agent_daemon chmod 755 $PANDORA_STARTUP chown root:0 $PANDORA_STARTUP echo "Pandora FMS agent has been included in /etc/rc.d/rc2.d/S90pandora_agent_daemon" fi if [ $OS_NAME = "HP-UX" ] then PANDORA_STARTUP=/sbin/init.d/pandora_agent_daemon cp pandora_agent_daemon $PANDORA_STARTUP ln -sf /sbin/init.d/pandora_agent_daemon /sbin/rc3.d/S90pandora_agent_daemon 2> /dev/null ln -sf /sbin/init.d/pandora_agent_daemon /sbin/rc2.d/S90pandora_agent_daemon 2> /dev/null chmod 755 $PANDORA_STARTUP chown root:0 $PANDORA_STARTUP echo "Pandora FMS agent has been included in /sbin/rcX.d/S90pandora_agent_daemon" fi if [ $OS_NAME = "Darwin" ] then cp $OS_NAME/com.pandorafms.pandorafms.plist /Library/LaunchDaemons echo "Pandora FMS agent has been included in /Library/LaunchDaemons" PANDORA_STARTUP=/Library/LaunchDaemons echo "To start now: launchctl load -w /Library/LaunchDaemons/com.pandorafms.pandorafms.plist" fi if [ $OS_NAME = "SunOS" ] then PANDORA_STARTUP=/etc/init.d/pandora_agent_daemon cp pandora_agent_daemon $PANDORA_STARTUP ln -sf /etc/init.d/pandora_agent_daemon /etc/rc2.d/S90pandora_agent_daemon 2> /dev/null chmod 755 $PANDORA_STARTUP chown root:0 $PANDORA_STARTUP echo "Pandora FMS agent has been included in /etc/rc2.d/S90pandora_agent_daemon" fi if [ $OS_NAME = "Linux" ] then PANDORA_STARTUP=/etc/init.d/pandora_agent_daemon cp pandora_agent_daemon $PANDORA_STARTUP if [ -d /etc/rc.d/ ] then ln -sf /etc/init.d/pandora_agent_daemon /etc/rc.d/rc2.d/S90pandora_agent 2> /dev/null ln -sf /etc/init.d/pandora_agent_daemon /etc/rc.d/rc3.d/S90pandora_agent 2> /dev/null else ln -sf /etc/init.d/pandora_agent_daemon /etc/rc2.d/S90pandora_agent 2> /dev/null ln -sf /etc/init.d/pandora_agent_daemon /etc/rc2.d/S90pandora_agent 2> /dev/null fi chmod 755 $PANDORA_STARTUP chown root:0 $PANDORA_STARTUP fi if [ "$OS_NAME" = "FreeBSD" ] then PANDORA_STARTUP=/usr/local/etc/rc.d/pandora_agent cp FreeBSD/pandora_agent $PANDORA_STARTUP chmod 555 $PANDORA_STARTUP chown root:wheel $PANDORA_STARTUP fi echo "Done." echo " " echo "You have your startup script ready at $PANDORA_STARTUP" echo " " echo "Tentacle is the default transfer mode since 2.0 version." echo " " echo "If you want to use SSH, firstly you need to copy your public SSH keys " echo " ($HOME/.ssh/id_dsa) under /home/pandora/.ssh/authorized_keys " echo "on your Pandora FMS Server host" echo " " echo "You also need to setup your $PANDORA_BASE$PANDORA_CFG/pandora_agent.conf config file" echo " " if [ "$OS_NAME" = "FreeBSD" ] then echo "Define 'pandora_agent_enable=\"YES\"' in /etc/rc.conf to enable the daemon." else echo "Check your startup configuration to be sure Pandora FMS Agent is ready " echo "to start automatically when system restarts": fi # Restore the daemon script if [ ! -z "${DAEMON_SCRIPT:-}" ]; then cp -f "$DAEMON_SCRIPT.bak" "$DAEMON_SCRIPT" >/dev/null 2>&1 rm -f "$DAEMON_SCRIPT.bak" >/dev/null 2>&1 fi # Restore the configuration file if [ ! -z "${AGENT_CFG:-}" ]; then cp -f "$AGENT_CFG.bak" "$AGENT_CFG" >/dev/null 2>&1 rm -f "$AGENT_CFG.bak" >/dev/null 2>&1 fi } if [ ! -f "pandora_agent" ] then echo " " 1>&2 echo "Execute installer from the directory where you have your files. " 1>&2 help 1>&2 exit 1 fi # Script banner at start echo " " echo "Pandora FMS Agent UNIX Installer $PI_VERSION $PI_BUILD (c) 2008-2013 ArticaST" echo "This program is licensed under GPL2 Terms. http://pandorafms.com" echo " " case "$MODE" in '--force-install') FORCE=1 install exit 0 ;; '--install') install exit 0 ;; '--uninstall') uninstall exit 0 ;; *) help ;; esac unix/ChangeLog0000644000000000000000000005531312165132002012310 0ustar rootroot2013-07-03 Ramon Novoa * pandora_agent.redhat.spec: Merged from trunk. Make absolute calls to chkconfig. Add the service before enabling it. 2013-06-26 Miguel de Dios * Linux/pandora_agent.conf: restored the remote_config as disabled for to avoid problems. 2013-06-25 Sancho Lerena * Linux/pandora_agent.conf: new defaul values (inventory enabled, remote config enabled). 2013-06-13 Ramon Novoa * pandora_agent: Quote the XML data file name before trying to send it. 2013-05-22 Sancho Lerena * pandora_agent.spec, pandora_agent.redhat.spec: Improved management of existant .conf files (for package auto upgrade). 2013-03-11 Koichiro Kikuchi * pandora_agent: Fixed bug that the send_buffered_xml_files doesn't remove xml files successfully sent. 2013-02-22 Sancho Lerena * Darwin/pandora_agent.conf: Added disk monitor. * Darwin/com.pandorafms.pandorafms.plist: Better values for launchdaemon on Mac. 2013-02-19 Koichiro Kikuchi * pandora_agent_installer: Removed duplicated chown line. Merged from trunk. 2013-02-12 Hirofumi Kosaka * pandora_agent: Fixed bug that data transfer would fail when secondary_transfer_mode is different from transfer_mode. Merged from trunk. 2013-01-21 Koichiro KIKUCHI * pandora_agent.redhat.spec: Updated version strings. 2013-01-11 Junichi Satoh * SunOS/make_solaris_package/make_solaris_package.sh: Updated AGENT_VERSION string. 2013-01-09 Sancho Lerena * pandora_agent_installer: Updated version strings. * Darwin, Darwin/pandora_agent.conf, Darwin/com.pandorafms.pandorafms.plist, pandora_agent: Updated agent for run on MacOS. Thanks to Guido Leenders. 2012-08-28 Junichi Satoh * pandora_agent: Merged from trunk. Improved to be able to use CRLF in pandora_agent.conf. 2012-08-15 Junichi Satoh * pandora_agent: Merged from trunk. Changed not to use thread library when agent_threads is set to 1 or undefined. This change is to avoid RHEL/CentOS 5 perl thread library bug. 2012-06-25 Sancho Lerena * pandora_agent: Updated version. 2012-06-21 Koichiro Kikuchi * pandora_agent.redhat.spec: Don't create pandora user if already exists. 2012-05-30 Ramon Novoa * pandora_agent: Check for valid regular expressions before adding module conditions. 2012-05-29 Sancho Lerena * pandora_agent_installer, DEBIAN/control, pandora_agent.spec, pandora_agent.redhat.spec: Updated version string. 2012-04-25 Miguel de Dios * DEBIAN/make_deb_package.sh: removed the lost "return" in the source code. I am sorry. 2012-04-25 Miguel de Dios * DEBIAN/postinst, DEBIAN/make_deb_package.sh: disabled the checking the plugins files with same name. 2012-04-24 Ramon Novoa * pandora_agent: Leave the secondary server password empty by default. Fixes bug #3519520. 2012-04-20 Ramon Novoa * pandora_agent_installer: Merged from trunk. Backup and restore conf file and daemon launcher. Moved the code that sets PANDORA_USER back to its original place and set the variable properly instead. 2012-04-19 Koichiro Kikuchi * pandora_agent: Merged from trunk. Also added the temporal directory to the file path for symlink check. 2012-04-18 Ramon Novoa * pandora_agent: Merged from trunk. Add the temporal directory to the file path before trying to send a buffered XML file. 2012-03-02 Koichiro Kikuchi * pandora_agent: Merged from trunk. Added symlink checks for temporary files before writing them to avoid symlink attacks. 2012-02-29 Ramon Novoa * Linux/pandora_agent.conf: Merged from from trunk. Added a warning text. 2012-02-28 Ramon Novoa * Linux/pandora_agent.conf, pandora_agent: Merged from trunk. Added support for xml_buffer. 2012-02-10 Hirofumi Kosaka * pandora_agent: Merged from trunk. Allow filename wildcards to specify additional configuration files. 2012-01-17 Kikuchi Koichiro * pandora_agent.redhat.spec: Update version string (to 4.0.1). 2011-12-19 Ramon Novoa * pandora_agent: Merged from trunk. Wait for broker childs instead of ignoring SIGCHLD. 2011-12-19 Ramon Novoa * pandora_agent: Merged from trunk. Ignore SIGCHLD. 2011-12-14 Ramon Novoa * pandora_agent: Do not display a warning if the output of a pre-condition is not numeric. 2011-12-07 KIKUCHI Koichiro * pandora_agent_installer: Removed duplicated lines and spaces to tabs. Also removed lines that set group to wheel (gid of wheel is 0). * plugins/files_indir: Added support for FreeBSD. * plugins/pandora_update: Fixed $conf_path for FreeBSD and spaces to tabs. 2011-11-15 Ramon Novoa * pandora_agent: Re-wrote broker agent code (was not working properly). 2011-09-29 Koichiro Kikuchi * pandora_agent.redhat.spec: Fixed wrong command paths in %prereq. 2011-09-13 Koichiro Kikuchi * pandora_agent: Clear the old process information before parsing current process information. Also added missing load_procs() call to module_cpuproc(). 2011-09-05 Koichiro Kikuchi * pandora_agent_daemon: Added support for OpenVZ/Virtuozzo. 2011-09-02 Koichiro Kikuchi * pandora_agent: Now module_condition and module_precondition accept numeric parameter without fractional part. 2011-08-22 Sancho Lerena * pandora_agent.spec, pandora_agent.redhat.spec (added) Updated specs to be used with OpenSUSE build service. New version for CentOS/RHEL 2011-08-19 Sancho Lerena * DEBIAN/control DEBIAN/make_deb_package.sh: Updated version to 4.0RC1. 2011-08-19 Sancho Lerena * pandora_agents/unix/pandora_agent.spec: Updated spec. 2011-07-14 Ramon Novoa * pandora_agent: Set additional module configuration parameters from the XML. 2011-04-13 Dario Rodriguez * HP-UX/pandora_agent.conf: Fixed a wrong path for command swapinfo. 2011-04-28 Junichi Satoh * SunOS/make_solaris_package/prototype, SunOS/make_solaris_package/make_solaris_package.sh: Added tentacle_server. 2011-04-28 Junichi Satoh * FreeBSD/pandora_agent.conf: Added missing templates. 2011-04-13 Dario Rodriguez * AIX/pandora_agent.conf, Linux/pandora_agent.conf, HP-UX/pandora_agent.conf SunOS/pandora_agent.conf: Deleted proxy_user parameter because is not needed. Also fixed some comments. * pandora_agent: Resctricted Proxy Mode to non root users. The agent must be launched by a non root user to use Proxy Mode. 2011-04-12 Dario Rodriguez * pandora_agent_daemon: Deleted code that kill tentacle server and replaced kill -9 to kill of agent stop command. * Linux/pandora_agent.conf, AIX/pandora_agent.conf, HP-UX/pandora_agent.conf,SunOS/pandora_agent.conf : Added parameters proxy_max_connection and proxy_timeout 1. * pandora_agent: Fixed problems launching tentacle_server and also added code to handle kill signal. 2011-04-11 Dario Rodriguez * pandora_agent: Fixed an error with command that launch tentacle server when proxy mode is enable. 2011-04-11 Dario Rodriguez * pandora_agent_installer: Added code to install tentacle_server with pandora agent. * AIX/pandora_agent.conf: Added two new parameters proxy_mode and proxy_user. * tentacle_server: Added tentacle server with proxy support. * pandora_agent_daemon: Add feature to stop tentacle_server when pandora agent stops. * Linux/pandora_agent.conf: Added two new parameters proxy_mode and proxy_user. * HP-UX/pandora_agent.conf: Added two new parameters proxy_mode and proxy_user. * pandora_agent: Added support to tentacle_server and proxy_mode. * SunOS/pandora_agent.conf: Added two new parameters proxy_mode and proxy_user. 2011-04-04 Dario Rodriguez * pandora_agent_installer: Fixed an error with chown in AIX OS. 2011-04-04 Dario Rodriguez * plugins/pandora_update: Fixed a problem getting pandora_agent pid in SunOS. 2011-04-04 Dario Rodriguez * pandora_agent_installer: Added correct user to tentacle_client binary. 2011-04-04 Dario Rodriguez * pandora_agent_installer: Modified agent isntaller to deal with specified user installation. 2011-04-04 Dario Rodriguez * plugins/pandora_update: Modified plugin for agent autoupdate. 2011-03-09 Ramon Novoa * pandora_agent: Fixed a typo. 2011-03-09 Ramon Novoa * pandora_agent: Added a module to get the ocupied space % in a partition. 2011-02-23 Ramon Novoa * DEBIAN/postinst: Updated. 2011-02-14 Sancho Lerena * OpenWRT: Special files for OpenWRT/Perl version. 2011-02-10 Ramon Novoa * pandora_agent: Detach threads to avoid excessive resource usage, since threads were not joined until all modules were executed. 2011-02-01 Junichi Satoh * FreeBSD/pandora_agent.conf: Fixed invalid cpu usage data is returned when system has only one disk device. 2011-01-27 Junichi Satoh * pandora_agent_daemon: Changed order of 'su' argument. Username should be as the 1st argument on Solaris. 2010-12-28 Ramon Novoa * pandora_agent.spec: Added a release variable as in the rest of the spec files. 2010-12-27 Ramon Novoa * pandora_agent_installer, DEBIAN/postinst, DEBIAN/prerm, DEBIAN/make_deb_package.sh, pandora_agent.spec, pandora_agent, SunOS/make_solaris_package/prototype, SunOS/make_solaris_package/make_solaris_package.sh, pandora_agent_exec: Renamed pandora_exec to pandora_agent_exec to avoid conflicts with the pandora_exec script installed by the server. 2010-12-16 Ramon Novoa * pandora_agent_installer, pandora_agent_daemon: Additional changes to run the agent as a different user. Starting and stopping the daemon did not work except as root. 2010-12-16 Miguel de Dios * DEBIAN/control, DEBIAN/make_deb_package.sh, pandora_console.spec, pandora_console.redhat.spec: update the version number. 2010-12-04 Junichi Satoh * plugins/pandora_update: Added support for FreeBSD. 2010-12-02 Junichi Satoh * SunOS/make_solaris_package/prototype: Added pandora_update. 2010-12-01 Ramon Novoa * plugins/pandora_update: Fixed md5 calculation. 2010-11-29 Ramon Novoa * pandora_agent_installer: Remove all init symbolic links. * plugins/pandora_update: Give the agent daemon some time to stop. Necessary on Windows. 2010-11-25 Miguel de Dios * pandora_agent.spec: change version number. 2010-11-22 Ramon Novoa * pandora_agent_daemon: Solaris specific fixes. 2010-11-22 Ramon Novoa * Linux/pandora_agent.conf: Set root as the default pandora_user. * pandora_agent: Share the semaphore after creating it. Removed an unnecessary require. 2010-11-19 Ramon Novoa * pandora_agent, AIX/pandora_agent.conf, pandora_agent_daemon, Linux/pandora_agent.conf, HP-UX/pandora_agent.conf, NT4/pandora_agent.conf, SunOS/pandora_agent.conf, FreeBSD/pandora_agent.conf: Added a new configuration option that lets the agent run as a different user by changing the process' EUID. * pandora_agent_installer: Several fixes. 2010-11-15 Raúl Mateos * pandora_agent*, pandora_exec, plugins/pandora_update: Small changes: Year, version, spaces to tabs. 2010-11-14 Sancho Lerena * plugins/pandora_update: Small tool (in perl), used also in windows (compiled as .exe), to auto-upgrade the software agents by stopping replacing the binary, and starting again the service/process, and also notifying the system about the upgrade. This will be possible using the new filecollection mechanism in 3.2 version. 2010-11-10 Miguel de Dios * DEBIAN/postinst, DEBIAN/prerm, DEBIAN/make_deb_package.sh: fixed the use pandora_exec for Pandora Server and Pandora Agent, now make a pandora_exec.agent and try to link to pandora_exec. Fixes: #3106578 2010-11-10 Miguel de Dios * DEBIAN/make_deb_package.sh: fixed the include the bigger NT4 files in the DEB package. 2010-11-04 Sancho Lerena * NT4: New binary version of Unix perl agent for NT4, with some tools. .exe compiled with ActiveState SDK 9.0 * pandora_agent: Some small modifications to make it work nicely in windows boxes. 2010-11-02 Raul Mateos * tentacle_client: Fixed year from last commit. Converted some spaces to tab. 2010-11-02 Miguel de Dios * ChangeLog: uploaded lost lines of my commit of yesterday. 2010-11-01 Miguel de Dios * DEBIAN/postinst, DEBIAN/conffiles, DEBIAN/make_deb_package.sh: fixed the warning of check md5sum on dir "plugins". Now the dir "plugins" is filled postinstall with the package plugins in temp directory, the copy is interactive for don't overwrite the user modified plugins of previous installation. Fixes: #3081496 2010-10-19 Junichi Satoh * SunOS/make_solaris_package/prototype: Added nagios_plugin_wrapper. 2010-10-15 Sancho Lerena * plugins/nagios_plugin_wrapper: Added new plugin. * pandora_agent: Version update. 2010-10-08 Ramon Novoa * pandora_agent: Pass server_pwd and server_ssl configuration tokens to tentacle. Fixes bug #3080299. 2010-10-07 Ramon Novoa * Linux/pandora_agent.conf: Added an example usage of the agent_threads configuration token. 2010-10-06 Junichi Satoh * pandora_agent: Added FreeBSD specific commands. 2010-10-04 Ramon Novoa * plugins/inventory: Fixed inventory process information. * pandora_agent: Fixed an error that showed when no logfile was specified in the agent configuration file. 2010-09-27 Junichi Satoh * FreeBSD/pandora_agent: Fixed a typo. 2010-09-27 Junichi Satoh * FreeBSD/pandora_agent: Changed PID detection method to support "jail", FreeBSD virtualization. 2010-09-27 Junichi Satoh * pandora_agent_installer: Set PANDORA_USER="root" when it is not defined. 2010-09-22 Sancho Lerena * pandora_agent.spec: Updated RPM spec for SUSE 2010-09-17 Ramon Novoa * pandora_agent: Added multi-thread support. 2010-09-17 Junichi Satoh * SunOS/make_solaris_package/README, SunOS/make_solaris_package/copyright, SunOS/make_solaris_package/make_solaris_package.sh, SunOS/make_solaris_package/prototype: Added agent package builder for Solaris. 2010-08-17 Junichi Satoh * pandora_agent_daemon, tentacle_client: Added support for Solaris virtualization, "zone". 2010-08-11 Ramon Novoa * pandora_agent: Fixed collection issues related to the agent. See bug #3042577. 2010-08-04 Sancho Lerena * DEBIAN/control, pandora_agent.spec: Added unzip to dependencies (for fille collection management). 2010-08-04 Miguel de Dios * pandora_agent_daemon: fixed user of daemon, it is root, not dario. 2010-07-28 Junichi Satoh * SunOS/pandora_agent.conf: Fixed a typo. 2010-07-21 Ramon Novoa * pandora_agent: Delete unused collections. 2010-07-20 Ramon Novoa * pandora_agent_installer: Fixed some directories and permissions. 2010-07-20 Ramon Novoa * pandora_agent_installer, DEBIAN/make_deb_package.sh, pandora_agent.spec: Updated to take the collections directory into account. * collections: Added to repository. Collections directory. 2010-07-19 Ramon Novoa * pandora_agent: Added support for file collections. 2010-07-12 Ramon Novoa * pandora_agent: changed the module cron configuration token to module_crontab. 2010-07-08 Ramon Novoa * pandora_exec: Do not verify the command to allow pipes and complex commands. * pandora_agent: Quote the command passed to pandora_exec. Fixed the module cron. Modules without a module cron would not run. 2010-07-05 Junichi Satoh * pandora_agent_installer: Fixed typo and directory permission for FreeBSD. * FreeBSD/pandora_agent: Simplified. 2010-07-02 Ramon Novoa * pandora_agent: Fixed a typo. 2010-06-30 Ramon Novoa * pandora_agent: Improved the module cron to allow intervals and multiple runs within an interval. 2010-06-30 Ramon Novoa * pandora_agent: Call df with -P from the Linux abstraction layer to avoid split lines. 2010-06-25 Ramon Novoa * pandora_agent: Added the module_cron feature to schedule modules using a cron-like syntax. 2010-06-23 Ramon Novoa * pandora_agent: Added the module_save and module_condition features. See http://www.openideas.info/wiki/ for more information. 2010-06-14 Junichi Satoh * pandora_agent_installer: Set execute bit to startup script for FreeBSD. 2010-06-09 Ramon Novoa * pandora_agent: Improved OS version detection. Disabled error output for plugins. 2010-06-09 Ramon Novoa * pandora_agent.spec: Create the man dir. 2010-06-09 Ramon Novoa * pandora_agent_installer, pandora_agent.spec: Copy the man pages. 2010-06-08 Ramon Novoa * pandora_agent: Removed the need for indexes in the abstraction layer. 2010-06-07 Ramon Novoa * pandora_agent: Added build information to the agent version. 2010-06-07 Junichi Satoh * pandora_agent_installer: Added support for FreeBSD. * FreeBSD/pandora_agent: Added startup script for FreeBSD. * FreeBSD/pandora_agent.conf: Added configuration file for FreeBSD. 2010-06-04 Ramon Novoa * pandora_agent.spec: Fixed. Upgrading an RPM broke the installation. 2010-05-20 Miguel de Dios * DEBIAN/postinst, DEBIAN/make_deb_package.sh: fixed the script to generate deb package. 2010-05-20 Miguel de Dios * DEBIAN/make_deb_package.sh: fixed the permissions to DEBIAN temp package. 2010-05-19 Miguel de Dios * DEBIAN, DEBIAN/control, DEBIAN/conffiles, DEBIAN/make_deb_package.sh, DEBIAN/md5sums: added the scripts and conf files for create package. 2010-05-18 Ramon Novoa * pandora_agent: Added a data collection layer and native modules similar to those of the Windows agent. 2010-05-13 Ramon Novoa * pandora_agent: Disabled the plugin command check. Was not working. 2010-04-29 Sancho Lerena * pandora_agent_installer: Added darwin (snow leopard), and BSD to installer OS detection. * AIX/pandora_agent.conf: Fixed version & date. * HP-UX/pandora_agent.conf: Replaced some default modules by better ones. 2010-02-22 Pablo de la Concepción * Linux/pandora_agent.conf: Added parameters position_description and parent_agent_name, and updated loadaverage with a more efficient version. * pandora_agent: Added POD documentation, modified to only add to the XML the minimum parameters (positional parameters, parent_agent_name,...) are not sent with default values if not deffined in the config file. Updated verion and build. 2010-02-16 Pablo de la Concepción * Linux/pandora_agent.conf: Fixed Load Average module example 2010-02-16 Pablo de la Concepción Updated tentacle from the tentacle repository and generated manpage. TODO:Make the installer install the manpages * unix/tentacle_client: Added pod documentation to generate manpages. * man/man1/tentacle_client.1: First version of the manpages for tentacle_client 2010-02-10 Miguel de Dios * pandora_agent_installer: fix bug when uninstall the agent in the same machine that it have a Pandora Server, that the uninstaller deleted the dirs share with Pandora Server (/var/spool/pandora/*) 2010-01-27 Sancho Lerena * plugins/files_indir: New agent to detect if files in a specficied directory are less than in previous run. Return two modules. 2009-12-15 Ramon Novoa * pandora_agent: Removed debugging code. 2009-12-15 Ramon Novoa * pandora_agent: Make modules with a module_interval run the first time. 2009-12-07 Sancho Lerena * plugins/inventory: Fixed some problems with the plugin (for linux). Added inventory for RPM systems. 2009-12-03 Ramon Novoa * pandora_agent: Empty modules and plugins before loading a remote configuration. Made the md5 function 64bit proof :-) 2009-11-19 Ramon Novoa * pandora_agent: Fixed bug #2888991. Skip remote_config if debug is enabled. 2009-11-18 Sancho Lerena * pandora_agent: Fixed a problem sending the module type in the XML. This causes that all modules were "generic_data". 2009-11-16 Sancho Lerena * pandora_agent: Updated default encoding to iso-8859-1 instead iso-8859-15, because in some systems this encoding is not installed and don't work :-(. Thanks for summa_sp for report this. 2009-11-06 Raul Mateos * *.conf: Updated URL and some small fixes. * README: Updated name :-D 2009-11-05 Sancho Lerena * pandora_agent_installer: Added a common installer for all systems. * Deleted daemon script for all systems, creaded a general one. * Modified HPUX to HP-UX directory. * Updated some .conf